Files
bj_power/bj_power_mes/internal/logic/product.go
T
SunYF 6d8bb75696 refactor(wms/mes): 统一多场景查询逻辑,移除关键字混搜
1. 移除所有多字段关键字混搜,改为各筛选字段独立查询
2. 调整excel导出相关逻辑,优化文件名处理与导入模板
3. 修复物料导入的类型解析与token获取逻辑
4. 更新依赖与前端页面文案、筛选参数
2026-09-08 13:43:08 +08:00

153 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 logic
import (
"context"
"errors"
"fmt"
"strings"
"bj_power_mes/ent"
"bj_power_mes/ent/bomitem"
"bj_power_mes/ent/producttype"
"bj_power_mes/ent/workorder"
"bj_power_mes/internal/wmsclient"
)
// 产品型号(成品档案):编码主数据单一来源 = WMSmaterials item_type=3)。
// MES 本页改为实时代理 WMS;WMS 不可达时降级读本地 product_types 只读缓存(仅查询,
// 写操作必须 WMS 可用),前端以 wmsOnline 标识提示。
type ProductTypeReq struct {
Id int `json:"id"`
Name string `json:"name"`
Code string `json:"code"`
Category string `json:"category"`
Remark string `json:"remark"`
IsActive bool `json:"isActive"`
}
func (s *Service) CreateProductType(ctx context.Context, req ProductTypeReq) error {
active := req.IsActive
if !req.IsActive {
active = true
}
if err := s.ctx.Wms.CreateProductType(ctx, req.Code, req.Name, req.Category, req.Remark, active); err != nil {
return errors.New("WMS 不可达或拒绝写入(编码主数据以 WMS 为单一来源):" + err.Error())
}
return nil
}
func (s *Service) UpdateProductType(ctx context.Context, req ProductTypeReq) error {
if req.Id == 0 {
return errors.New("缺少 id")
}
if err := s.ctx.Wms.UpdateProductType(ctx, req.Id, req.Name, req.Category, req.Remark, req.IsActive); err != nil {
return errors.New("WMS 不可达或拒绝写入:" + err.Error())
}
return nil
}
// DeleteProductType 删除保护:被工单/BOM 引用过的型号禁删(MES 侧引用校验,
// WMS 侧库存引用由 WMS 内部接口再校验一层)
func (s *Service) DeleteProductType(ctx context.Context, id int) error {
row, err := s.productTypeByID(ctx, id)
if err != nil {
return err
}
woCnt, _ := s.ctx.EntClient.WorkOrder.Query().Where(workorder.ProductCode(row.Code)).Count(ctx)
if woCnt > 0 {
return fmt.Errorf("该产品型号已被 %d 张工单引用,不可删除;建议停用(下架)", woCnt)
}
bomCnt, _ := s.ctx.EntClient.BomItem.Query().Where(bomitem.ProductCode(row.Code)).Count(ctx)
if bomCnt > 0 {
return fmt.Errorf("该产品型号在物料清单中有 %d 条配置,不可删除;建议停用(下架)", bomCnt)
}
if err := s.ctx.Wms.DeleteProductType(ctx, id); err != nil {
return errors.New("WMS 不可达或拒绝删除:" + err.Error())
}
return nil
}
// ListProductTypes 全量列表(下拉/兼容形态,id asc 新建在底部)。
// degraded=false 表示 WMS 不可达、数据来自本地只读缓存。
func (s *Service) ListProductTypes(ctx context.Context) ([]wmsclient.ProductTypeRow, bool, error) {
list, err := s.ctx.Wms.ProductTypes(ctx, "")
if err == nil {
return list, true, nil
}
fallback, ferr := s.localProductTypes(ctx, "", "", "")
if ferr != nil {
return nil, false, errors.New("WMS 不可达且本地缓存读取失败")
}
return fallback, false, nil
}
// ListProductTypesPage 分页+搜索(管理页真分页)。
// 2026-09-08 禁止关键字混搜:编码/名称/类别各自独立模糊。
func (s *Service) ListProductTypesPage(ctx context.Context, code, name, category, isActive string, page, pageSize int) (int64, []wmsclient.ProductTypeRow, bool, error) {
total, list, err := s.ctx.Wms.ProductTypePage(ctx, code, name, category, isActive, page, pageSize)
if err == nil {
return total, list, true, nil
}
fallback, ferr := s.localProductTypes(ctx, code, name, category)
if ferr != nil {
return 0, nil, false, errors.New("WMS 不可达且本地缓存读取失败")
}
start := (page - 1) * pageSize
if start > len(fallback) {
start = len(fallback)
}
end := start + pageSize
if end > len(fallback) {
end = len(fallback)
}
return int64(len(fallback)), fallback[start:end], false, nil
}
func (s *Service) productTypeByID(ctx context.Context, id int) (*wmsclient.ProductTypeRow, error) {
list, err := s.ctx.Wms.ProductTypes(ctx, "")
if err == nil {
for i := range list {
if list[i].ID == id {
return &list[i], nil
}
}
return nil, errors.New("产品型号不存在")
}
// 降级:本地缓存
pt, err := s.ctx.EntClient.ProductType.Get(ctx, id)
if err != nil {
return nil, errors.New("产品型号不存在(WMS 不可达,无法校验引用)")
}
return &wmsclient.ProductTypeRow{ID: pt.ID, Code: pt.Code, Name: pt.Name}, nil
}
// localProductTypes 本地只读缓存过滤(降级用):编码/名称/类别各自独立模糊匹配
func (s *Service) localProductTypes(ctx context.Context, code, name, category string) ([]wmsclient.ProductTypeRow, error) {
list, err := s.ctx.EntClient.ProductType.Query().Order(ent.Asc(producttype.FieldID)).All(ctx)
if err != nil {
return nil, err
}
codeKw := strings.ToLower(strings.TrimSpace(code))
nameKw := strings.ToLower(strings.TrimSpace(name))
catKw := strings.ToLower(strings.TrimSpace(category))
rows := make([]wmsclient.ProductTypeRow, 0, len(list))
for _, p := range list {
if codeKw != "" && !strings.Contains(strings.ToLower(p.Code), codeKw) {
continue
}
if nameKw != "" && !strings.Contains(strings.ToLower(p.Name), nameKw) {
continue
}
if catKw != "" && !strings.Contains(strings.ToLower(p.Category), catKw) {
continue
}
rows = append(rows, wmsclient.ProductTypeRow{
ID: p.ID, Code: p.Code, Name: p.Name, Category: p.Category,
Remark: p.Remark, IsActive: p.IsActive,
CreatedAt: p.CreatedAt.Unix(),
})
}
return rows, nil
}