package handler import ( "net/http" "strconv" "strings" "bj_power_wms/ent" "bj_power_wms/ent/ordermaterialledger" "bj_power_wms/ent/semifinished" "bj_power_wms/internal/svc" ) // 半成品 / 台账 相关(盘点见 stocktake.go) // semiInboundHandler 半成品入库(携带已完成工序) // 与 MES 闭环:MES 工位报工暂存退库时调用本接口,把半成品 SN 入 WMS 库。 // 为保持两系统解耦,materialCode 不强制要求——优先用请求传入, // 其次按 SN 反查 WMS 序列号台账,都没有则留空(SN 本身即追溯锚点)。 func semiInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req struct { Sn string `json:"sn"` MaterialCode string `json:"materialCode"` DoneProcessCodes []int `json:"doneProcessCodes"` CompletedProcess string `json:"completedProcess"` ZoneCode string `json:"zoneCode"` OrderNo string `json:"orderNo"` Operator string `json:"operator"` } if err := parseJSON(r, &req); err != nil { fail(w, http.StatusBadRequest, "参数错误") return } if req.Sn == "" { fail(w, http.StatusBadRequest, "sn 必填") return } exists, err := ctx.EntClient.SemiFinished.Query(). Where(semifinished.SnEQ(req.Sn)). Exist(ctx0()) if err != nil { fail(w, http.StatusInternalServerError, err.Error()) return } if exists { fail(w, http.StatusConflict, "半成品已存在: "+req.Sn) return } // 已完成工序:MES 传 doneProcessCodes([]int) 优先,否则用 completedProcess 字符串 completed := req.CompletedProcess if len(req.DoneProcessCodes) > 0 { parts := make([]string, 0, len(req.DoneProcessCodes)) for _, c := range req.DoneProcessCodes { parts = append(parts, strconv.Itoa(c)) } completed = strings.Join(parts, ",") } // 物料编码:以请求传入为准(半成品是独立固定业务类型,不依赖统一库存表) materialCode := req.MaterialCode rec, err := ctx.EntClient.SemiFinished.Create(). SetSn(req.Sn). SetNillableMaterialCode(strPtr(materialCode)). SetNillableCompletedProcess(strPtr(completed)). SetNillableZoneCode(strPtr(req.ZoneCode)). SetStatus("在库"). SetNillableOrderNo(strPtr(req.OrderNo)). Save(ctx0()) if err != nil { fail(w, http.StatusInternalServerError, err.Error()) return } ok(w, rec) } } // semiOutboundHandler 半成品出库(重上线) func semiOutboundHandler(ctx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req struct { Sn string `json:"sn"` ZoneCode string `json:"zoneCode"` Operator string `json:"operator"` } if err := parseJSON(r, &req); err != nil { fail(w, http.StatusBadRequest, "参数错误") return } if req.Sn == "" { fail(w, http.StatusBadRequest, "sn 必填") return } rec, err := ctx.EntClient.SemiFinished.Query(). Where(semifinished.SnEQ(req.Sn)). Only(ctx0()) if err != nil { fail(w, http.StatusNotFound, "半成品不存在: "+req.Sn) return } if rec.Status != "在库" { fail(w, http.StatusConflict, "半成品不在库: "+rec.Status) return } ctx.EntClient.SemiFinished.UpdateOneID(rec.ID). SetStatus("出库"). ExecX(ctx0()) ok(w, map[string]any{"sn": req.Sn, "status": "出库"}) } } // querySemiHandler 半成品查询 func querySemiHandler(ctx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { page := atoi(r.URL.Query().Get("page"), 1) pageSize := atoi(r.URL.Query().Get("pageSize"), 20) materialCode := r.URL.Query().Get("materialCode") status := r.URL.Query().Get("status") q := ctx.EntClient.SemiFinished.Query() if materialCode != "" { q = q.Where(semifinished.MaterialCodeEQ(materialCode)) } if status != "" { q = q.Where(semifinished.StatusEQ(status)) } total, err := q.Count(ctx0()) if err != nil { fail(w, http.StatusInternalServerError, err.Error()) return } list, err := q.Order(ent.Desc("created_at")). Offset((page - 1) * pageSize).Limit(pageSize).All(ctx0()) if err != nil { fail(w, http.StatusInternalServerError, err.Error()) return } ok(w, map[string]any{ "total": total, "list": list, "page": page, "pageSize": pageSize, }) } } // ledger 相关:queryLedgerHandler 工单物料台账查询 func queryLedgerHandler(ctx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { orderNo := r.URL.Query().Get("orderNo") materialCode := r.URL.Query().Get("materialCode") page := atoi(r.URL.Query().Get("page"), 1) pageSize := atoi(r.URL.Query().Get("pageSize"), 20) q := ctx.EntClient.OrderMaterialLedger.Query() if orderNo != "" { q = q.Where(ordermaterialledger.OrderNoEQ(orderNo)) } if materialCode != "" { q = q.Where(ordermaterialledger.MaterialCodeEQ(materialCode)) } total, err := q.Count(ctx0()) if err != nil { fail(w, http.StatusInternalServerError, err.Error()) return } list, err := q.Order(ent.Desc("created_at")). Offset((page - 1) * pageSize).Limit(pageSize).All(ctx0()) if err != nil { fail(w, http.StatusInternalServerError, err.Error()) return } ok(w, map[string]any{ "total": total, "list": list, "page": page, "pageSize": pageSize, }) } }