feat: 重构BOM架构,新增基础设置与虚拟工位管理功能
本次重构删除原有BOM物料清单表,改用工单工艺组合×工艺物料清单作为唯一用料来源;新增系统基础设置表支持WMS地址、日志保留天数等配置,新增虚拟工位作业管理后台接口与前端页签控制功能,同时优化工位号校验逻辑、事件日志自动清理与工单用料查询能力。
This commit is contained in:
@@ -446,9 +446,9 @@ func (s *Service) DoneWorkpiece(ctx context.Context, req DoneReq, operator strin
|
||||
return nil
|
||||
}
|
||||
|
||||
// backflushWorkpiece 反冲扣账:按工单产品整份 BOM 算「单件消耗(含损耗)」,
|
||||
// backflushWorkpiece 反冲扣账:按工单工艺组合的单台用料(工艺物料清单汇总,含损耗)算「单件消耗」,
|
||||
// 调 WMS 内部反冲接口 FIFO 扣库存 + 生成 backflush 出库单。
|
||||
// 整份 BOM 一次性下发(完工即全部物料已消耗),WMS 不可达/校验失败仅记日志。
|
||||
// 用料唯一来源=工单组合×flow_material(BOM 已删除);WMS 不可达/校验失败仅记日志。
|
||||
func (s *Service) backflushWorkpiece(ctx context.Context, wp *ent.Workpiece, operator string) {
|
||||
wo, err := s.ctx.EntClient.WorkOrder.Get(ctx, wp.WorkOrderId)
|
||||
if err != nil || wo == nil {
|
||||
@@ -456,19 +456,16 @@ func (s *Service) backflushWorkpiece(ctx context.Context, wp *ent.Workpiece, ope
|
||||
"反冲失败:工单不存在", map[string]any{"workOrderId": wp.WorkOrderId})
|
||||
return
|
||||
}
|
||||
bom, err := s.ListBom(ctx, wo.ProductCode, bomNameOrDefault(""))
|
||||
if err != nil || len(bom) == 0 {
|
||||
usage := s.WorkOrderUnitUsage(ctx, wo)
|
||||
if len(usage) == 0 {
|
||||
s.ctx.EventLog.Write(ctx, "wms.backflush.skip", wp.OrderNo, operator, "workpiece", wp.Sn,
|
||||
"无BOM物料,跳过反冲", map[string]any{"productCode": wo.ProductCode})
|
||||
"工单工艺组合无物料清单,跳过反冲", map[string]any{"orderNo": wp.OrderNo})
|
||||
return
|
||||
}
|
||||
items := make([]wmsclient.BackflushItem, 0, len(bom))
|
||||
for _, it := range bom {
|
||||
if it.MaterialCode == "" {
|
||||
continue
|
||||
}
|
||||
// 单件消耗 = 单台用量 ×(1+损耗率),四舍五入;≤0 跳过
|
||||
qty := int(math.Round(it.UnitQty * (1 + it.LossRate/100)))
|
||||
items := make([]wmsclient.BackflushItem, 0, len(usage))
|
||||
for _, it := range usage {
|
||||
// 单件消耗 = 单台含损耗用量,四舍五入;≤0 跳过
|
||||
qty := int(math.Round(it.EffQty))
|
||||
if qty <= 0 {
|
||||
continue
|
||||
}
|
||||
@@ -479,11 +476,11 @@ func (s *Service) backflushWorkpiece(ctx context.Context, wp *ent.Workpiece, ope
|
||||
}
|
||||
if wmsErr := s.ctx.Wms.Backflush(ctx, wp.OrderNo, 0, 0, operator, items); wmsErr != nil {
|
||||
s.ctx.EventLog.Write(ctx, "wms.backflush.failed", wp.OrderNo, operator, "workpiece", wp.Sn,
|
||||
"反冲扣账WMS失败(库存未扣,请人工核查)", map[string]any{"error": wmsErr.Error(), "productCode": wo.ProductCode})
|
||||
"反冲扣账WMS失败(库存未扣,请人工核查)", map[string]any{"error": wmsErr.Error(), "orderNo": wp.OrderNo})
|
||||
return
|
||||
}
|
||||
s.ctx.EventLog.Write(ctx, "wms.backflush", wp.OrderNo, operator, "workpiece", wp.Sn,
|
||||
"反冲扣账已下发WMS", map[string]any{"productCode": wo.ProductCode, "items": len(items)})
|
||||
"反冲扣账已下发WMS", map[string]any{"orderNo": wp.OrderNo, "items": len(items)})
|
||||
}
|
||||
|
||||
// retainFinishedToWms 完工品回流 WMS 库存。失败仅记日志(wms.finished.retain_failed),
|
||||
|
||||
Reference in New Issue
Block a user