refactor: 清理MES端本地product_type冗余代码,对齐WMS主数据架构
1. 移除MES端本地product_type实体、schema及相关CRUD代码,改为通过WMS内部API代理获取物料主数据 2. 更新物料管理粒度逻辑,新增"其他"类型(3)支持,同步更新入库校验规则 3. 修复前端物料选择、库存筛选等页面的类型判断逻辑,统一使用manage_mode区分管理类型 4. 清理静态资源文件冗余的样式代码,调整前端页面展示逻辑 5. 更新帮助文档,修正物料类型的说明描述
This commit is contained in:
@@ -41,12 +41,12 @@ func categoryLabel(c int) string {
|
||||
}
|
||||
}
|
||||
|
||||
// typeLabelOf 汇总行类型标签(与区域汇总「其他」口径一致):itemType=4 → 其他;否则按管理粒度。
|
||||
func typeLabelOf(manageMode, itemType int) string {
|
||||
if itemType == invItemOther {
|
||||
// typeLabelOf 汇总行类型标签(与区域汇总「其他」口径一致):物料类型 manage_mode=3 → 其他;否则按管理粒度。
|
||||
func typeLabelOf(matManageMode int) string {
|
||||
if matManageMode == invManageOther {
|
||||
return "其他"
|
||||
}
|
||||
return manageModeLabel(manageMode)
|
||||
return manageModeLabel(matManageMode)
|
||||
}
|
||||
|
||||
// stockAggRow 聚合主列表的行结构(按 物料+区域+管理粒度 聚合,只返回数量,不铺开明细)
|
||||
@@ -57,8 +57,9 @@ type stockAggRow struct {
|
||||
MaterialCode string `json:"materialCode"` // 物料编码
|
||||
MaterialName string `json:"materialName"` // 物料名称
|
||||
Spec string `json:"spec"` // 规格型号
|
||||
ManageMode int `json:"manageMode"` // 1结构件/2电气件
|
||||
ItemType int `json:"itemType"` // 物料品类(4=其他:辅料/工装/试验设备)
|
||||
ManageMode int `json:"manageMode"` // 库存行管理粒度 1结构件(批次)/2电气件(SN)
|
||||
ItemType int `json:"itemType"` // 物料品类(1原材料/2半成品/3成品/4其他)
|
||||
MatManageMode int `json:"matManageMode"` // 物料档案类型(1结构件/2电气件/3其他):类型标签判定用
|
||||
ZoneCode string `json:"zoneCode"` // 区域
|
||||
ShelfNo string `json:"shelfNo"` // 货架号
|
||||
LayerNo string `json:"layerNo"` // 第几层
|
||||
@@ -91,8 +92,6 @@ func queryStockHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
qualityStatus := r.URL.Query().Get("qualityStatus")
|
||||
manageMode := r.URL.Query().Get("manageMode") // 1/2/空=全部
|
||||
category := r.URL.Query().Get("category") // 1原材料/2半成品/3成品/空=全部(完工检 SN 拾取器按成品过滤)
|
||||
itemType := atoi(r.URL.Query().Get("itemType"), 0) // 品类(B1:4=其他入库物料)
|
||||
itemTypeNot := atoi(r.URL.Query().Get("itemTypeNot"), 0) // 排除品类(§A1 类型三分互斥:结构件 = 管理粒度1 且非「其他」类)
|
||||
inboundNo := r.URL.Query().Get("inboundNo")
|
||||
startDate := r.URL.Query().Get("startDate") // 默认近3个月(由接口保证)
|
||||
endDate := r.URL.Query().Get("endDate")
|
||||
@@ -110,8 +109,6 @@ func queryStockHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
QualityStatus: qualityStatus,
|
||||
ManageMode: manageMode,
|
||||
Category: category,
|
||||
ItemType: itemType,
|
||||
ItemTypeNot: itemTypeNot,
|
||||
InboundNo: inboundNo,
|
||||
StartDate: startDate,
|
||||
EndDate: endDate,
|
||||
@@ -143,8 +140,6 @@ type aggregateStockArgs struct {
|
||||
QualityStatus string
|
||||
ManageMode string
|
||||
Category string // 1原材料/2半成品/3成品/空=全部
|
||||
ItemType int // 品类 itemType(B1:4=其他入库物料)
|
||||
ItemTypeNot int // 排除品类(§A1:结构件筛选时排除「其他」类 itemType=4)
|
||||
InboundNo string
|
||||
StartDate string
|
||||
EndDate string
|
||||
@@ -193,28 +188,23 @@ func aggregateStock(ctx *svc.ServiceContext, a aggregateStockArgs) ([]*stockAggR
|
||||
// 质量状态仅作"筛选"维度(快捷定位未检/合格/不合格),不进分组键(方案 §A1/§A5)
|
||||
q = q.Where(inventory.QualityStatusEQ(a.QualityStatus))
|
||||
}
|
||||
if a.ItemType > 0 {
|
||||
// 按品类过滤(B1):先取编码集再 IN,避免逐行 join
|
||||
codes := materialCodesByItemType(ctx, a.ItemType)
|
||||
if a.InboundNo != "" {
|
||||
q = q.Where(inventory.InboundNoContains(a.InboundNo))
|
||||
}
|
||||
// 类型(manage_mode)下拉:结构件=1 / 电气件=2 / 其他=3,一律按物料档案类型取编码集 IN,不与品类(itemType)字段混用
|
||||
switch a.ManageMode {
|
||||
case "1", "2":
|
||||
codes := materialCodesByManageMode(ctx, atoi(a.ManageMode, 0))
|
||||
if len(codes) == 0 {
|
||||
return []*stockAggRow{}, 0, nil
|
||||
}
|
||||
q = q.Where(inventory.MaterialCodeIn(codes...))
|
||||
}
|
||||
if a.ItemTypeNot > 0 {
|
||||
// 排除品类(§A1 类型三分互斥:结构件 = 管理粒度1 且非「其他」类)
|
||||
codes := materialCodesByItemType(ctx, a.ItemTypeNot)
|
||||
if len(codes) > 0 {
|
||||
q = q.Where(inventory.MaterialCodeNotIn(codes...))
|
||||
case "3":
|
||||
codes := materialCodesByManageMode(ctx, invManageOther)
|
||||
if len(codes) == 0 {
|
||||
return []*stockAggRow{}, 0, nil
|
||||
}
|
||||
}
|
||||
if a.InboundNo != "" {
|
||||
q = q.Where(inventory.InboundNoContains(a.InboundNo))
|
||||
}
|
||||
if a.ManageMode == "1" {
|
||||
q = q.Where(inventory.ManageModeEQ(1))
|
||||
} else if a.ManageMode == "2" {
|
||||
q = q.Where(inventory.ManageModeEQ(2))
|
||||
q = q.Where(inventory.MaterialCodeIn(codes...))
|
||||
}
|
||||
if a.Category == "1" {
|
||||
q = q.Where(inventory.CategoryEQ(invCatRaw))
|
||||
@@ -255,6 +245,7 @@ func aggregateStock(ctx *svc.ServiceContext, a aggregateStockArgs) ([]*stockAggR
|
||||
matName := map[string]string{}
|
||||
matSpec := map[string]string{}
|
||||
matItemType := map[string]int{}
|
||||
matManageMode := map[string]int{}
|
||||
matCodes := []string{}
|
||||
seen := map[string]bool{}
|
||||
for _, inv := range all {
|
||||
@@ -270,6 +261,7 @@ func aggregateStock(ctx *svc.ServiceContext, a aggregateStockArgs) ([]*stockAggR
|
||||
matName[m.Code] = m.Name
|
||||
matSpec[m.Code] = m.Spec
|
||||
matItemType[m.Code] = m.ItemType
|
||||
matManageMode[m.Code] = m.ManageMode
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,6 +345,7 @@ func aggregateStock(ctx *svc.ServiceContext, a aggregateStockArgs) ([]*stockAggR
|
||||
Spec: matSpec[key.MaterialCode],
|
||||
ManageMode: key.ManageMode,
|
||||
ItemType: matItemType[key.MaterialCode],
|
||||
MatManageMode: matManageMode[key.MaterialCode],
|
||||
ZoneCode: key.ZoneCode,
|
||||
ShelfNo: key.ShelfNo,
|
||||
LayerNo: key.LayerNo,
|
||||
@@ -380,8 +373,9 @@ type materialAggRow struct {
|
||||
MaterialCode string `json:"materialCode"`
|
||||
MaterialName string `json:"materialName"`
|
||||
Spec string `json:"spec"`
|
||||
ManageMode int `json:"manageMode"` // 1结构件/2电气件
|
||||
ItemType int `json:"itemType"` // 物料品类(4=其他:辅料/工装/试验设备)
|
||||
ManageMode int `json:"manageMode"` // 库存行管理粒度 1结构件(批次)/2电气件(SN)
|
||||
ItemType int `json:"itemType"` // 物料品类(1原材料/2半成品/3成品/4其他)
|
||||
MatManageMode int `json:"matManageMode"` // 物料档案类型(1结构件/2电气件/3其他):类型标签判定用
|
||||
Category int `json:"category"` // 品类 1原材料/2半成品/3成品
|
||||
TotalQty int `json:"totalQty"` // 总数量(结构件=数量求和;电气件=SN 行数)
|
||||
LockedQty int `json:"lockedQty"` // 锁定量
|
||||
@@ -404,8 +398,6 @@ type materialSummaryArgs struct {
|
||||
MaterialName string
|
||||
ManageMode string
|
||||
Category string // 1原材料/2半成品/3成品/空=全部
|
||||
ItemType int // 品类 itemType(4=其他入库物料,§A1 类型筛选)
|
||||
ItemTypeNot int // 排除品类(§A1:结构件筛选时排除「其他」类)
|
||||
Page int
|
||||
PageSize int
|
||||
}
|
||||
@@ -421,8 +413,6 @@ func materialSummaryHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
MaterialName: r.URL.Query().Get("materialName"),
|
||||
ManageMode: r.URL.Query().Get("manageMode"),
|
||||
Category: r.URL.Query().Get("category"),
|
||||
ItemType: atoi(r.URL.Query().Get("itemType"), 0),
|
||||
ItemTypeNot: atoi(r.URL.Query().Get("itemTypeNot"), 0),
|
||||
Page: atoi(r.URL.Query().Get("page"), 1),
|
||||
PageSize: atoi(r.URL.Query().Get("pageSize"), 20),
|
||||
})
|
||||
@@ -446,25 +436,20 @@ func aggregateMaterialSummary(ctx *svc.ServiceContext, a materialSummaryArgs) ([
|
||||
if a.MaterialName != "" {
|
||||
q = q.Where(inventory.MaterialNameContains(a.MaterialName))
|
||||
}
|
||||
if a.ManageMode == "1" {
|
||||
q = q.Where(inventory.ManageModeEQ(1))
|
||||
} else if a.ManageMode == "2" {
|
||||
q = q.Where(inventory.ManageModeEQ(2))
|
||||
}
|
||||
if a.ItemType > 0 {
|
||||
// 按品类过滤(§A1):先取编码集再 IN,避免逐行 join
|
||||
codes := materialCodesByItemType(ctx, a.ItemType)
|
||||
// 类型(manage_mode)下拉:结构件=1 / 电气件=2 / 其他=3,一律按物料档案类型取编码集 IN,不与品类(itemType)字段混用
|
||||
switch a.ManageMode {
|
||||
case "1", "2":
|
||||
codes := materialCodesByManageMode(ctx, atoi(a.ManageMode, 0))
|
||||
if len(codes) == 0 {
|
||||
return []*materialAggRow{}, 0, nil
|
||||
}
|
||||
q = q.Where(inventory.MaterialCodeIn(codes...))
|
||||
}
|
||||
if a.ItemTypeNot > 0 {
|
||||
// 排除品类(§A1 类型三分互斥:结构件 = 管理粒度1 且非「其他」类)
|
||||
codes := materialCodesByItemType(ctx, a.ItemTypeNot)
|
||||
if len(codes) > 0 {
|
||||
q = q.Where(inventory.MaterialCodeNotIn(codes...))
|
||||
case "3":
|
||||
codes := materialCodesByManageMode(ctx, invManageOther)
|
||||
if len(codes) == 0 {
|
||||
return []*materialAggRow{}, 0, nil
|
||||
}
|
||||
q = q.Where(inventory.MaterialCodeIn(codes...))
|
||||
}
|
||||
if a.Category == "1" {
|
||||
q = q.Where(inventory.CategoryEQ(invCatRaw))
|
||||
@@ -487,6 +472,7 @@ func aggregateMaterialSummary(ctx *svc.ServiceContext, a materialSummaryArgs) ([
|
||||
matName := map[string]string{}
|
||||
matSpec := map[string]string{}
|
||||
matItemType := map[string]int{}
|
||||
matManageMode := map[string]int{}
|
||||
matID := map[string]int64{}
|
||||
matCreatedAt := map[string]int64{}
|
||||
matCodes := []string{}
|
||||
@@ -504,6 +490,7 @@ func aggregateMaterialSummary(ctx *svc.ServiceContext, a materialSummaryArgs) ([
|
||||
matName[m.Code] = m.Name
|
||||
matSpec[m.Code] = m.Spec
|
||||
matItemType[m.Code] = m.ItemType
|
||||
matManageMode[m.Code] = m.ManageMode
|
||||
matID[m.Code] = int64(m.ID)
|
||||
matCreatedAt[m.Code] = m.CreatedAt
|
||||
}
|
||||
@@ -594,6 +581,7 @@ func aggregateMaterialSummary(ctx *svc.ServiceContext, a materialSummaryArgs) ([
|
||||
Spec: matSpec[code],
|
||||
ManageMode: g.mMode,
|
||||
ItemType: matItemType[code],
|
||||
MatManageMode: matManageMode[code],
|
||||
Category: g.mCategory,
|
||||
TotalQty: g.totalQty,
|
||||
LockedQty: g.lockedQty,
|
||||
@@ -638,7 +626,6 @@ func stockDetailsHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
keyword := r.URL.Query().Get("keyword")
|
||||
manageMode := atoi(r.URL.Query().Get("manageMode"), 0)
|
||||
category := atoi(r.URL.Query().Get("category"), 0)
|
||||
itemType := atoi(r.URL.Query().Get("itemType"), 0)
|
||||
page := atoi(r.URL.Query().Get("page"), 1)
|
||||
pageSize := atoi(r.URL.Query().Get("pageSize"), 50)
|
||||
|
||||
@@ -676,15 +663,6 @@ func stockDetailsHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
if category != 0 {
|
||||
q = q.Where(inventory.CategoryEQ(category))
|
||||
}
|
||||
if itemType > 0 {
|
||||
// 按品类过滤(B1):先取编码集再 IN,避免逐行 join
|
||||
codes := materialCodesByItemType(ctx, itemType)
|
||||
if len(codes) == 0 {
|
||||
ok(w, map[string]any{"list": []any{}, "total": 0, "page": page, "pageSize": pageSize})
|
||||
return
|
||||
}
|
||||
q = q.Where(inventory.MaterialCodeIn(codes...))
|
||||
}
|
||||
|
||||
total, err := q.Count(ctx0())
|
||||
if err != nil {
|
||||
@@ -739,11 +717,9 @@ func exportStockHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
rows, _, err := aggregateMaterialSummary(ctx, materialSummaryArgs{
|
||||
MaterialCode: r.URL.Query().Get("materialCode"),
|
||||
MaterialName: r.URL.Query().Get("materialName"),
|
||||
ManageMode: r.URL.Query().Get("manageMode"),
|
||||
Category: r.URL.Query().Get("category"),
|
||||
ItemType: atoi(r.URL.Query().Get("itemType"), 0),
|
||||
ItemTypeNot: atoi(r.URL.Query().Get("itemTypeNot"), 0),
|
||||
Page: 1,
|
||||
ManageMode: r.URL.Query().Get("manageMode"),
|
||||
Category: r.URL.Query().Get("category"),
|
||||
Page: 1,
|
||||
PageSize: 1000000, // 全量
|
||||
})
|
||||
if err != nil {
|
||||
@@ -760,7 +736,7 @@ func exportStockHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
}
|
||||
matrix = append(matrix, []any{
|
||||
id, rw.MaterialCode, rw.MaterialName, rw.Spec,
|
||||
typeLabelOf(rw.ManageMode, rw.ItemType), rw.TotalQty, rw.LockedQty, rw.AvailQty,
|
||||
typeLabelOf(rw.MatManageMode), rw.TotalQty, rw.LockedQty, rw.AvailQty,
|
||||
rw.QtyQualified, rw.QtyPending, rw.QtyRejected,
|
||||
strings.Join(rw.Zones, "、"), rw.BatchCount, rw.SnCount,
|
||||
unixFmt(rw.MaterialCreatedAt), unixFmt(rw.CreatedAt),
|
||||
@@ -783,8 +759,6 @@ func exportStockHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
PositionNo: r.URL.Query().Get("positionNo"),
|
||||
QualityStatus: r.URL.Query().Get("qualityStatus"),
|
||||
ManageMode: r.URL.Query().Get("manageMode"),
|
||||
ItemType: atoi(r.URL.Query().Get("itemType"), 0),
|
||||
ItemTypeNot: atoi(r.URL.Query().Get("itemTypeNot"), 0),
|
||||
InboundNo: r.URL.Query().Get("inboundNo"),
|
||||
StartDate: startDate,
|
||||
EndDate: endDate,
|
||||
@@ -801,7 +775,7 @@ func exportStockHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
for _, rw := range rows {
|
||||
matrix = append(matrix, []any{
|
||||
rw.ID, rw.MaterialCode, rw.MaterialName, rw.Spec,
|
||||
typeLabelOf(rw.ManageMode, rw.ItemType), rw.ZoneCode, rw.ShelfNo, rw.LayerNo, rw.PositionNo,
|
||||
typeLabelOf(rw.MatManageMode), rw.ZoneCode, rw.ShelfNo, rw.LayerNo, rw.PositionNo,
|
||||
rw.QtyQualified, rw.QtyPending, rw.QtyRejected,
|
||||
rw.TotalQty, rw.LockedQty, rw.AvailQty, rw.BatchCount, rw.SnCount,
|
||||
unixFmt(rw.CreatedAt),
|
||||
@@ -849,11 +823,11 @@ func buildZoneSummary(ctx *svc.ServiceContext) ([]zoneSummRow, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 物料品类(itemType)映射:itemType=4 → 其他(辅料/工装/试验设备)
|
||||
// 物料类型(manageMode)映射:manage_mode=3 → 其他(辅料/工装/试验设备)
|
||||
mats, _ := ctx.EntClient.Material.Query().All(ctx0())
|
||||
itemTypeMap := make(map[string]int, len(mats))
|
||||
manageModeMap := make(map[string]int, len(mats))
|
||||
for _, m := range mats {
|
||||
itemTypeMap[m.Code] = m.ItemType
|
||||
manageModeMap[m.Code] = m.ManageMode
|
||||
}
|
||||
|
||||
// 一区域一行:质量与类型均为列(数量口径:结构件按行数量、电气件按 1)
|
||||
@@ -880,7 +854,7 @@ func buildZoneSummary(ctx *svc.ServiceContext) ([]zoneSummRow, error) {
|
||||
g.QtyPending += qty
|
||||
}
|
||||
switch {
|
||||
case itemTypeMap[inv.MaterialCode] == invItemOther:
|
||||
case manageModeMap[inv.MaterialCode] == invManageOther:
|
||||
g.QtyOther += qty
|
||||
case inv.ManageMode == 2:
|
||||
g.QtyElec += qty
|
||||
|
||||
Reference in New Issue
Block a user