chore: 批量完成项目多模块迭代优化

1. 废弃半成品库存表并统一库存主表
2. 修复列表排序与搜索大小写不敏感问题
3. 新增用户最近登录时间、工单BOM名称字段
4. 完善角色管理、工位选择器功能
5. 增加拧紧数据补录、成品自动回流WMS能力
6. 统一导出时间范围校验规则
7. 丰富物料/备料单筛选条件
8. 调整菜单与权限命名适配产品型号业务
This commit is contained in:
SunYF
2026-09-08 11:44:04 +08:00
parent 06689970e2
commit e852c7cd37
96 changed files with 4528 additions and 542 deletions
+34 -2
View File
@@ -18,6 +18,7 @@ type WorkOrderReq struct {
WorkOrderNo string `json:"workOrderNo"`
ProductTypeId int `json:"productTypeId"`
ProductCode string `json:"productCode"`
BomName string `json:"bomName"` // 建单选定的 BOM 名称(同型号多份并存;空=「默认」)
ProductName string `json:"productName"`
Quantity int `json:"quantity"`
ProcessSeq string `json:"processSeq"`
@@ -26,13 +27,34 @@ type WorkOrderReq struct {
PlanEnd string `json:"planEnd"`
}
// validateBomName 校验该产品型号下是否存在指定名称的 BOM(型号下无任何 BOM 时放行,允许先建单后补 BOM)
func (s *Service) validateBomName(ctx context.Context, productCode, bomName string) error {
if productCode == "" {
return nil
}
names, err := s.ListBomNames(ctx, productCode)
if err != nil {
return nil // 查询异常不阻塞建单(与 WMS 降级策略同思路)
}
if len(names) == 0 {
return nil
}
target := bomNameOrDefault(bomName)
for _, n := range names {
if n.BomName == target {
return nil
}
}
return fmt.Errorf("产品型号 %s 下不存在名为「%s」的BOM,请先在物料清单中创建", productCode, target)
}
// CreateWorkOrder 创建工单(状态恒 CREATED,后续用状态流转按钮推进)
func (s *Service) CreateWorkOrder(ctx context.Context, req WorkOrderReq, operator string) error {
if req.WorkOrderNo == "" {
return errors.New("工单号不能为空")
}
if req.ProductTypeId == 0 {
return errors.New("请选择产品型")
return errors.New("请选择产品型")
}
if req.Quantity <= 0 {
req.Quantity = 1
@@ -50,10 +72,14 @@ func (s *Service) CreateWorkOrder(ctx context.Context, req WorkOrderReq, operato
return err
}
req.ProcessSeq = NormalizeProcessSeq(req.ProcessSeq)
if err := s.validateBomName(ctx, req.ProductCode, req.BomName); err != nil {
return err
}
b := s.ctx.EntClient.WorkOrder.Create().
SetWorkOrderNo(req.WorkOrderNo).
SetProductTypeId(req.ProductTypeId).
SetProductCode(req.ProductCode).
SetBomName(bomNameOrDefault(req.BomName)).
SetProductName(req.ProductName).
SetQuantity(req.Quantity).
SetProcessSeq(req.ProcessSeq).
@@ -101,6 +127,12 @@ func (s *Service) UpdateWorkOrder(ctx context.Context, req WorkOrderReq, operato
if req.ProductCode != "" {
u.SetProductCode(req.ProductCode)
}
if req.BomName != "" {
if err := s.validateBomName(ctx, req.ProductCode, req.BomName); err != nil {
return err
}
u.SetBomName(bomNameOrDefault(req.BomName))
}
if req.ProductName != "" {
u.SetProductName(req.ProductName)
}
@@ -140,7 +172,7 @@ func (s *Service) ListWorkOrders(ctx context.Context, orderNo, status, productCo
if productName != "" {
q = q.Where(workorder.ProductNameContains(productName))
}
return q.Order(ent.Desc(workorder.FieldID)).All(ctx)
return q.Order(ent.Desc(workorder.FieldCreatedAt), ent.Desc(workorder.FieldID)).All(ctx)
}
func (s *Service) GetWorkOrder(ctx context.Context, id int) (*ent.WorkOrder, error) {