feat(mes): 添加定时同步可生产数量到WMS及BOM项相关标准字段

- 在main.go中添加定时任务每10分钟同步可生产数量到WMS系统
- 为BomItem实体添加relatedStandard字段及相关CRUD方法
- 为InspectionRecord实体添加reportNo、materialCode、materialName等字段
- 更新ent schema确保新字段的验证和默认值设置
- 添加必要的数据库迁移和字段映射逻辑
This commit is contained in:
SunYF
2026-09-17 12:49:07 +08:00
parent b4b274301d
commit 1cc93795ce
191 changed files with 24504 additions and 1250 deletions
+32 -10
View File
@@ -160,6 +160,28 @@ func manageModeLabel(m int) string {
return "-"
}
// locLabel 拼接完整库位串:大区/货架/层/位置,跳过空段(方案 E 库位四级贯通)。
// 例:"Z01/A架/3层/12位";仅有大区时返回大区;全空返回 "-"。
func locLabel(zoneCode, shelfNo, layerNo, positionNo string) string {
parts := make([]string, 0, 4)
if zoneCode != "" {
parts = append(parts, zoneCode)
}
if shelfNo != "" {
parts = append(parts, shelfNo+"架")
}
if layerNo != "" {
parts = append(parts, layerNo+"层")
}
if positionNo != "" {
parts = append(parts, positionNo+"位")
}
if len(parts) == 0 {
return "-"
}
return strings.Join(parts, "/")
}
// unixFmt 把 unix 秒转成 yyyy-MM-dd HH:mm:ss(时间戳<=0 返回空串)
func unixFmt(ts int64) string {
if ts <= 0 {
@@ -189,8 +211,8 @@ type importErr struct {
}
// excelInboundHandler Excel 批量导入入库
// mode=batch(结构件):列头(首行忽略) 物料编码 | 批次号(可空自动生成) | 数量 | 生产日期 | 供应商 | 区域 | 备注
// mode=sn(电气件) 列头(首行忽略) 物料编码 | SN | 区域 | 生产日期 | 供应商
// mode=batch(结构件):列头(首行忽略) 图号 | 批次号(可空自动生成) | 数量 | 生产日期 | 供应商 | 区域 | 备注
// mode=sn(电气件) 列头(首行忽略) 图号 | SN | 区域 | 生产日期 | 供应商
//
// 强约束:全成功或全失败(一次性全导入 or 全失败,禁止部分成功)。
// 流程:阶段1 逐行解析+校验(物料存在/数量>0/SN不重复/区域必填) → 任一错则整体拒绝并列出错误行(一行不写);
@@ -259,7 +281,7 @@ func excelInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
pr.code = cell(0)
if mode == "sn" {
pr.sn = cell(1)
pr.zone = cell(2) // 电气件模板: 物料编码|SN|区域|生产日期|供应商
pr.zone = cell(2) // 电气件模板: 图号|SN|区域|生产日期|供应商
pr.prodDate = cell(3)
pr.supplier = cell(4)
pr.remark = cell(4)
@@ -268,12 +290,12 @@ func excelInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
pr.qty = atoi(cell(2), 0)
pr.prodDate = cell(3)
pr.supplier = cell(4)
pr.zone = cell(5) // 结构件模板: 物料编码|批次号|数量|生产日期|供应商|区域|备注
pr.zone = cell(5) // 结构件模板: 图号|批次号|数量|生产日期|供应商|区域|备注
pr.remark = cell(6)
}
if pr.code == "" {
errs = append(errs, importErr{pr.row, pr.code, "物料编码为空"})
errs = append(errs, importErr{pr.row, pr.code, "图号为空"})
continue
}
m, e := ctx.EntClient.Material.Query().Where(material.CodeEQ(pr.code)).Only(ctx0())
@@ -364,11 +386,11 @@ func excelInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return
}
} else {
batchNo := pr.batchNo
if batchNo == "" {
// 同一导入内多行空批次需保证批次号唯一,追加行号后缀
batchNo = genBatchNo(pr.code) + fmt.Sprintf("-%d", pr.row)
}
batchNo := pr.batchNo
if batchNo == "" {
// 自动批次号(物料编码-日期-流水号);同一导入内多行空批次自动取得递增流水,天然唯一
batchNo = genBatchNo(ctx, pr.code)
}
existing, e2 := tx.Inventory.Query().
Where(inventory.ManageModeEQ(1), inventory.BatchNoEQ(batchNo)).Only(ctx0())
if e2 == nil {