Files
bj_power/bj_power_wms/internal/handler/misc.go
T
SunYF c1fc6d32b2 feat: 完成多模块功能迭代与优化
本次提交包含多模块功能更新:
1. 权限系统重构:移除硬编码admin放行逻辑,新增精细化权限控制,完善权限树形结构与用户/角色保护
2. 新增物料导入导出接口,补充台账查询条件
3. 优化列表查询排序逻辑,新增区域编码大小写不敏感搜索
4. 修复帮助抽屉重复弹出问题,补充页面权限控制
5. 新增弱密码提示逻辑,优化MES/WMS用户/角色管理权限
6. 调整路由结构,新增权限校验脚本与前端权限树重构
7. 补充数据库字段与依赖包更新
2026-09-03 18:13:59 +08:00

198 lines
5.6 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"), 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")
materialName := r.URL.Query().Get("materialName")
status := r.URL.Query().Get("status")
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))
}
if materialName != "" {
q = q.Where(ordermaterialledger.MaterialNameContains(materialName))
}
if status != "" {
q = q.Where(ordermaterialledger.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"), 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,
})
}
}