docs(test): 更新电表箱装配业务回归测试文档

- 将文档从代码审计任务转换为端到端业务回归测试链路
- 重新组织文档结构为链路总览、示例数据基线和详细步骤
- 添加完整的业务场景清单涵盖WMS/MES/工位终端三大系统
- 定义统一的测试数据包括产品型号、物料清单、工位派工等
- 提供详细的步骤断言和数量等式验证方法
- 建立贯穿全链路的数据流向和状态变更追踪体系
This commit is contained in:
SunYF
2026-09-21 10:48:53 +08:00
parent 0d34bcd6a3
commit 132c3ed6bd
63 changed files with 3309 additions and 5784 deletions
+84 -12
View File
@@ -464,6 +464,29 @@ func parseManageMode(s string) int {
return 0
}
// parseItemType 解析导入模板"品类"列:原材料/半成品/成品/其他(兼容 1/2/3/4);无法识别返回 0。
// 注意:"半成品"含"成品"子串,必须先判半成品再判成品。
func parseItemType(s string) int {
s = strings.TrimSpace(s)
if s == "" {
return 0
}
switch {
case strings.Contains(s, "原材料"):
return 1
case strings.Contains(s, "半成品"):
return 2
case strings.Contains(s, "成品"):
return 3
case strings.Contains(s, "其他"):
return 4
}
if n := atoi(s, 0); n >= 1 && n <= 4 {
return n
}
return 0
}
// excelMaterialImportHandler 物料档案 Excel 批量导入
// 模板(首行忽略表头):图号 | 名称 | 规格 | 单位 | 类型(结构件/电气件) | 说明
// (图号=物料编码,问题记录 L18 合并裁决,不再单设图号列;「简称」列已按 2026-09-19 裁决移除)
@@ -507,29 +530,71 @@ func excelMaterialImportHandler(ctx *svc.ServiceContext) http.HandlerFunc {
spec string
unit string
manageMode int
itemType int
description string
}
plans := make([]planRow, 0, len(rows)-1)
errs := make([]importErr, 0)
// 表头→列下标映射:容忍列顺序变化与多余列(如「品类」插在单位与类型之间)。
// 先按"去括号后的表头名"精确匹配,再按关键字包含兜底(顺序稳定),都找不到回退模板固定下标。
normHeader := func(s string) string {
s = strings.TrimSpace(s)
for _, op := range []string{"", "("} {
if i := strings.Index(s, op); i >= 0 {
s = s[:i]
}
}
return strings.TrimSpace(s)
}
headerNorm := make([]string, len(rows[0]))
for j, h := range rows[0] {
headerNorm[j] = normHeader(h)
}
colOf := func(names []string, fallback int) int {
for _, n := range names {
for j, hn := range headerNorm {
if hn == n {
return j
}
}
}
for _, n := range names {
for j, hn := range headerNorm {
if hn != "" && strings.Contains(hn, n) {
return j
}
}
}
return fallback
}
codeCol := colOf([]string{"图号", "物料编码", "编码"}, 0)
nameCol := colOf([]string{"名称", "物料名称"}, 1)
specCol := colOf([]string{"规格", "规格型号"}, 2)
unitCol := colOf([]string{"单位"}, 3)
typeCol := colOf([]string{"类型", "管理类型", "管理粒度"}, 4)
catCol := colOf([]string{"品类", "类别"}, -1)
descCol := colOf([]string{"说明", "备注", "描述"}, 5)
// 阶段1:解析 + 校验(不落库)
for i, row := range rows {
if i == 0 {
continue // 表头
}
cell := func(idx int) string {
if idx < len(row) {
return strings.TrimSpace(row[idx])
if idx < 0 || idx >= len(row) {
return ""
}
return ""
return strings.TrimSpace(row[idx])
}
pr := planRow{row: i + 1}
pr.code = cell(0)
pr.name = cell(1)
pr.spec = cell(2)
pr.unit = cell(3)
pr.manageMode = parseManageMode(cell(4))
pr.description = cell(5)
pr.code = cell(codeCol)
pr.name = cell(nameCol)
pr.spec = cell(specCol)
pr.unit = cell(unitCol)
pr.manageMode = parseManageMode(cell(typeCol))
pr.itemType = parseItemType(cell(catCol))
pr.description = cell(descCol)
if pr.code == "" {
errs = append(errs, importErr{pr.row, pr.code, "图号为空"})
@@ -551,6 +616,10 @@ func excelMaterialImportHandler(ctx *svc.ServiceContext) http.HandlerFunc {
errs = append(errs, importErr{pr.row, pr.code, "类型无法识别,请填写「结构件」或「电气件」(兼容 1/2)"})
continue
}
if catCol >= 0 && cell(catCol) != "" && pr.itemType == 0 {
errs = append(errs, importErr{pr.row, pr.code, "品类无法识别,请填写「原材料/半成品/成品/其他」(兼容 1/2/3/4"})
continue
}
exists, _ := ctx.EntClient.Material.Query().
Where(material.CodeEQ(pr.code)).Exist(ctx0())
if exists {
@@ -580,7 +649,7 @@ func excelMaterialImportHandler(ctx *svc.ServiceContext) http.HandlerFunc {
}()
for _, pr := range plans {
if _, e = tx.Material.Create().
mc := tx.Material.Create().
SetCode(pr.code).
SetName(pr.name).
SetNillableSpec(strPtr(pr.spec)).
@@ -588,8 +657,11 @@ func excelMaterialImportHandler(ctx *svc.ServiceContext) http.HandlerFunc {
SetNillableDescription(strPtr(pr.description)).
SetManageMode(pr.manageMode).
SetIsBatchManaged(pr.manageMode == 1).
SetIsSerialManaged(pr.manageMode == 2).
Save(ctx0()); e != nil {
SetIsSerialManaged(pr.manageMode == 2)
if pr.itemType > 0 {
mc = mc.SetItemType(pr.itemType)
}
if _, e = mc.Save(ctx0()); e != nil {
fail(w, http.StatusInternalServerError, "创建物料失败: "+e.Error())
return
}