Files
bj_power/bj_power_wms/internal/handler/misc.go
T
SunYF 572fa975bc feat: 完成WMS系统权限体系与业务功能迭代
本提交完成了WMS系统的多维度优化升级:
1. 新增RBAC权限系统,支持角色/菜单/按钮三级权限管控
2. 重构库存盘点、物料管理、区域维护等模块的查询筛选与展示逻辑
3. 优化入库/出库/质检等业务流程,完善数据冗余与业务闭环
4. 移除旧装箱表,将装箱逻辑合并到出库主表
5. 新增前端权限判断工具、导出工具与端到端测试用例
6. 补充完善各类注释与数据库字段说明
2026-09-03 14:20:37 +08:00

190 lines
5.3 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 (
"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,
})
}
}