feat: 完成多模块迭代更新
- 新增过程巡检按步骤上报、数量不符上报、工位退料功能 - 增加工单工程编号三级归属字段 - 新增物料安全库存与缺货预警 - 新增附件管理、退库单管理模块 - 优化生产看板展示逻辑与前端页面文案 - 清理冗余的工艺路线相关代码与备份文件
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"bj_power_wms/ent"
|
||||
"bj_power_wms/ent/inbounddetail"
|
||||
"bj_power_wms/ent/inboundorder"
|
||||
"bj_power_wms/ent/inspectionrecord"
|
||||
"bj_power_wms/ent/inventory"
|
||||
"bj_power_wms/ent/material"
|
||||
"bj_power_wms/internal/svc"
|
||||
@@ -16,6 +19,37 @@ import (
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
// 物料品类:4=其他(辅料/工装/试验设备),与 schema/material.go 的 item_type 保持一致
|
||||
const invItemOther = 4
|
||||
|
||||
// validateInboundQuality 入库质量门禁:该物料/批次/SN 若已被判定"不合格",拒绝入库。
|
||||
// 依据客户诉求《问题记录》L135:「不合格不入库、不上产线,仅合格品入库存数量」。
|
||||
func validateInboundQuality(ctx *svc.ServiceContext, materialCode, batchNo string, snList []string) error {
|
||||
if batchNo != "" {
|
||||
n, err := ctx.EntClient.InspectionRecord.Query().
|
||||
Where(
|
||||
inspectionrecord.MaterialCodeEQ(materialCode),
|
||||
inspectionrecord.TargetIDEQ(batchNo),
|
||||
inspectionrecord.StatusEQ("不合格"),
|
||||
).Count(ctx0())
|
||||
if err == nil && n > 0 {
|
||||
return fmt.Errorf("批次 %s 已被判定不合格,禁止入库(请走退货/报废处置)", batchNo)
|
||||
}
|
||||
}
|
||||
if len(snList) > 0 {
|
||||
recs, err := ctx.EntClient.InspectionRecord.Query().
|
||||
Where(
|
||||
inspectionrecord.MaterialCodeEQ(materialCode),
|
||||
inspectionrecord.TargetIDIn(snList...),
|
||||
inspectionrecord.StatusEQ("不合格"),
|
||||
).Limit(1).All(ctx0())
|
||||
if err == nil && len(recs) > 0 {
|
||||
return fmt.Errorf("SN %s 已被判定不合格,禁止入库", recs[0].TargetID)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// createInboundHandler 入库
|
||||
// 结构件: { inboundType, materialCode, batchNo, quantity, zoneCode, operator }
|
||||
// 电气件: { inboundType, materialCode, snList: [sn...], zoneCode, operator }
|
||||
@@ -24,7 +58,7 @@ import (
|
||||
func createInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
InboundType string `json:"inboundType"` // purchase/semi/finished/return
|
||||
InboundType string `json:"inboundType"` // purchase/semi/finished/return/other
|
||||
MaterialCode string `json:"materialCode"`
|
||||
BatchNo string `json:"batchNo"`
|
||||
Quantity int `json:"quantity"`
|
||||
@@ -34,7 +68,9 @@ func createInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
ProductionDate string `json:"productionDate"`
|
||||
Supplier string `json:"supplier"`
|
||||
Remark string `json:"remark"`
|
||||
InspectionNo string `json:"inspectionNo"`
|
||||
InspectionNo string `json:"inspectionNo"`
|
||||
OwnershipType string `json:"ownershipType"` // workorder/project/none
|
||||
OwnershipNo string `json:"ownershipNo"`
|
||||
}
|
||||
if err := parseJSON(r, &req); err != nil {
|
||||
fail(w, http.StatusBadRequest, "参数错误: "+err.Error())
|
||||
@@ -62,6 +98,22 @@ func createInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
// 其他类物料(item_type=4:辅料/工装/试验设备):规格强制必填(客户诉求 问题记录 L50)
|
||||
if m.ItemType == invItemOther {
|
||||
if strings.TrimSpace(m.Spec) == "" {
|
||||
fail(w, http.StatusBadRequest, "其他类物料必须填写规格型号,请先在物料档案补全")
|
||||
return
|
||||
}
|
||||
req.InboundType = "other"
|
||||
}
|
||||
|
||||
// 质量门禁(P0-2):已被判定不合格的批次/SN 禁止再入库——
|
||||
// 客户诉求 L135「不合格不入库、不上产线,仅合格品计入库存数量」。
|
||||
if qerr := validateInboundQuality(ctx, req.MaterialCode, req.BatchNo, req.SnList); qerr != nil {
|
||||
fail(w, http.StatusConflict, qerr.Error())
|
||||
return
|
||||
}
|
||||
|
||||
inboundNo := "IB" + uuid.NewString()[:12]
|
||||
|
||||
// 开启事务:入库单 + 库存行 + 明细 原子提交
|
||||
@@ -87,7 +139,9 @@ func createInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
SetQuantity(0).
|
||||
SetNillableOperator(strPtr(req.Operator)).
|
||||
SetNillableRemark(strPtr(req.Remark)).
|
||||
SetInspectionNo(req.InspectionNo).
|
||||
SetInspectionNo(req.InspectionNo).
|
||||
SetOwnershipType(ownershipTypeOrNone(req.OwnershipType)).
|
||||
SetNillableOwnershipNo(strPtr(req.OwnershipNo)).
|
||||
Save(ctx0())
|
||||
if err != nil {
|
||||
fail(w, http.StatusInternalServerError, "创建入库单失败: "+err.Error())
|
||||
@@ -393,6 +447,16 @@ func exportInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// ownershipTypeOrNone 归属类型归一化(工单号/科技项目号/无)
|
||||
func ownershipTypeOrNone(v string) string {
|
||||
switch v {
|
||||
case "workorder", "project":
|
||||
return v
|
||||
default:
|
||||
return "none"
|
||||
}
|
||||
}
|
||||
|
||||
// genBatchNo 生成批次号:日期 + 自增
|
||||
func genBatchNo(materialCode string) string {
|
||||
// TODO: 使用数据库序列或 Redis INCR 保证自增唯一
|
||||
|
||||
Reference in New Issue
Block a user