Files
bj_power/bj_power_wms/internal/handler/misc.go
T
SunYF bb22148625 feat: 完成区域管理、装箱功能优化与接口标准化
- 新增区域状态字段与增删改查接口,支持区域启用/停用
- 重构实体字段JSON标签为camelCase格式统一接口规范
- 优化入库、盘点、装箱流程的交互与提示文案
- 新增装箱管理功能,支持合同号关联与装箱编辑
- 调整前端菜单与帮助文档适配业务场景变更
2026-09-01 13:49:44 +08:00

336 lines
9.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handler
import (
"encoding/json"
"net/http"
"bj_power_wms/ent"
"bj_power_wms/ent/ordermaterialledger"
"bj_power_wms/ent/packagebox"
"bj_power_wms/ent/semifinished"
"bj_power_wms/ent/serialnumber"
"bj_power_wms/internal/svc"
)
// 半成品 / 包装 / 台账 相关(盘点见 stocktake.go
// semiInboundHandler 半成品入库(携带已完成工序)
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"`
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 == "" || req.MaterialCode == "" {
fail(w, http.StatusBadRequest, "sn 和 materialCode 必填")
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
}
rec, err := ctx.EntClient.SemiFinished.Create().
SetSn(req.Sn).
SetMaterialCode(req.MaterialCode).
SetNillableCompletedProcess(strPtr(req.CompletedProcess)).
SetNillableZoneCode(strPtr(req.ZoneCode)).
SetStatus("在库").
SetNillableOrderNo(strPtr(req.OrderNo)).
Save(ctx0())
if err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
}
// 同时记入 SN 台账(半成品也是精密件)
ctx.EntClient.SerialNumber.Create().
SetSnCode(req.Sn).
SetMaterialCode(req.MaterialCode).
SetStatus("在库").
SetNillableCurrentZone(strPtr(req.ZoneCode)).
SaveX(ctx0())
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())
ctx.EntClient.SerialNumber.Update().
Where(serialnumber.SnCodeEQ(req.Sn)).
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("id")).
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,
})
}
}
// packageBindHandler 装箱绑定(箱号 ↔ SN),支持合同号
func packageBindHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req struct {
BoxNo string `json:"boxNo"`
SnList []string `json:"snList"`
MaterialCode string `json:"materialCode"`
ContractNo string `json:"contractNo"`
Operator string `json:"operator"`
Remark string `json:"remark"`
}
if err := parseJSON(r, &req); err != nil {
fail(w, http.StatusBadRequest, "参数错误")
return
}
if req.BoxNo == "" || len(req.SnList) == 0 {
fail(w, http.StatusBadRequest, "箱号和 SN 清单必填")
return
}
exists, err := ctx.EntClient.PackageBox.Query().
Where(packagebox.BoxNoEQ(req.BoxNo)).
Exist(ctx0())
if err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
}
if exists {
fail(w, http.StatusConflict, "箱号已存在: "+req.BoxNo)
return
}
// SN 列表序列化
snJSON := toJSON(req.SnList)
pkg, err := ctx.EntClient.PackageBox.Create().
SetBoxNo(req.BoxNo).
SetSnList(snJSON).
SetNillableMaterialCode(strPtr(req.MaterialCode)).
SetQuantity(len(req.SnList)).
SetNillableContractNo(strPtr(req.ContractNo)).
SetNillableOperator(strPtr(req.Operator)).
SetNillableRemark(strPtr(req.Remark)).
Save(ctx0())
if err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
}
ok(w, pkg)
}
}
// packageUpdateHandler 编辑装箱(重新装箱 SN / 修改合同号等)
func packageUpdateHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req struct {
ID int `json:"id"`
SnList []string `json:"snList"`
MaterialCode string `json:"materialCode"`
ContractNo string `json:"contractNo"`
Operator string `json:"operator"`
Remark string `json:"remark"`
}
if err := parseJSON(r, &req); err != nil || req.ID <= 0 {
fail(w, http.StatusBadRequest, "参数错误")
return
}
upd := ctx.EntClient.PackageBox.UpdateOneID(req.ID)
if len(req.SnList) > 0 {
upd.SetSnList(toJSON(req.SnList)).SetQuantity(len(req.SnList))
}
upd.SetNillableMaterialCode(strPtr(req.MaterialCode)).
SetNillableContractNo(strPtr(req.ContractNo)).
SetNillableOperator(strPtr(req.Operator)).
SetNillableRemark(strPtr(req.Remark))
pkg, err := upd.Save(ctx0())
if err != nil {
fail(w, http.StatusInternalServerError, "更新装箱失败: "+err.Error())
return
}
ok(w, pkg)
}
}
// toJSON 序列化任意值为 JSON 字符串
func toJSON(v any) string {
b, err := json.Marshal(v)
if err != nil {
return "[]"
}
return string(b)
}
// queryPackageHandler 装箱查询(多条件:箱号/合同号/操作人/物料/时间范围)
func queryPackageHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
boxNo := r.URL.Query().Get("boxNo")
contractNo := r.URL.Query().Get("contractNo")
operator := r.URL.Query().Get("operator")
materialCode := r.URL.Query().Get("materialCode")
startAt := r.URL.Query().Get("startAt")
endAt := r.URL.Query().Get("endAt")
page := atoi(r.URL.Query().Get("page"), 1)
pageSize := atoi(r.URL.Query().Get("pageSize"), 20)
q := ctx.EntClient.PackageBox.Query()
if boxNo != "" {
q = q.Where(packagebox.BoxNoContains(boxNo))
}
if contractNo != "" {
q = q.Where(packagebox.ContractNoContains(contractNo))
}
if operator != "" {
q = q.Where(packagebox.OperatorContains(operator))
}
if materialCode != "" {
q = q.Where(packagebox.MaterialCodeEQ(materialCode))
}
if startAt != "" {
start := atoi64(startAt, 0)
if start > 0 {
q = q.Where(packagebox.CreatedAtGTE(start))
}
}
if endAt != "" {
end := atoi64(endAt, 0)
if end > 0 {
q = q.Where(packagebox.CreatedAtLTE(end))
}
}
total, err := q.Count(ctx0())
if err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
}
list, err := q.Order(ent.Desc("id")).
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("id")).
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,
})
}
}