package logic import ( "context" "errors" "bj_power_mes/ent/materialrequest" ) // ============ 配送进度(跨系统只读聚合,不新增账本) ============ // // 口径(2026-09-19 定稿):一个字段只有一个写者;跨系统只读聚合、绝不双写。 // // WMS 台账(唯一真源):totalQty 需求 / outQty 已发出 / returnedQty 已退回 / consumedQty 已消耗 // MES 备料单(唯一真源):receivedQty 已接料(工位扫码接料累加) // // 派生(本接口现算,不落库): // // 净领用 netOut = outQty − returnedQty // 待发缺口 gap = totalQty − netOut // 在途 inTransit = outQty − receivedQty // 线边 lineSide = receivedQty − consumedQty // // 恒等式:入库总量 = 在库 + 在途 + 线边 + 已消耗 + 退库回仓 + 盘点差异 type DeliveryProgressRow struct { OrderNo string `json:"orderNo"` MaterialCode string `json:"materialCode"` MaterialName string `json:"materialName"` TargetStation string `json:"targetStation"` TotalQty int `json:"totalQty"` OutQty int `json:"outQty"` ReturnedQty int `json:"returnedQty"` ConsumedQty int `json:"consumedQty"` NetOut int `json:"netOut"` Gap int `json:"gap"` ReceivedQty int `json:"receivedQty"` InTransit int `json:"inTransit"` LineSide int `json:"lineSide"` Status string `json:"status"` CompletedAt int64 `json:"completedAt"` } // DeliveryProgress 配送进度:WMS 台账四段量 + MES 已接料 → 派生在途/线边。 // 仅读不写;WMS 不可达时返回错误由前端提示(不伪造数据)。 func (s *Service) DeliveryProgress(ctx context.Context, orderNo, materialCode string, page, pageSize int) (map[string]any, error) { if s.ctx.Wms == nil { return nil, errors.New("WMS 未配置,无法获取配送进度") } if page < 1 { page = 1 } if pageSize < 1 || pageSize > 200 { pageSize = 50 } rows, total, err := s.ctx.Wms.LedgerProgress(ctx, orderNo, materialCode, page, pageSize) if err != nil { return nil, err } // MES 侧已接料量:按「工单+图号」汇总。一次查询 + 内存聚合,避免逐行查询。 type lk struct{ orderNo, materialCode string } recv := map[lk]int{} orders := make([]string, 0, len(rows)) seen := map[string]bool{} for _, r := range rows { if r.OrderNo != "" && !seen[r.OrderNo] { seen[r.OrderNo] = true orders = append(orders, r.OrderNo) } } if len(orders) > 0 { list, e := s.ctx.EntClient.MaterialRequest.Query(). Where(materialrequest.OrderNoIn(orders...)).All(ctx) if e == nil { for _, mr := range list { recv[lk{mr.OrderNo, mr.MaterialCode}] += int(mr.ReceivedQty + 0.5) } } } out := make([]DeliveryProgressRow, 0, len(rows)) for _, r := range rows { got := recv[lk{r.OrderNo, r.MaterialCode}] out = append(out, DeliveryProgressRow{ OrderNo: r.OrderNo, MaterialCode: r.MaterialCode, MaterialName: r.MaterialName, TargetStation: r.TargetStation, TotalQty: r.TotalQty, OutQty: r.OutQty, ReturnedQty: r.ReturnedQty, ConsumedQty: r.ConsumedQty, NetOut: r.NetOut, Gap: r.Gap, ReceivedQty: got, InTransit: r.OutQty - got, LineSide: got - r.ConsumedQty, Status: r.Status, CompletedAt: r.CompletedAt, }) } return map[string]any{"total": total, "list": out, "page": page, "pageSize": pageSize}, nil }