feat(mes): 添加定时同步可生产数量到WMS及BOM项相关标准字段

- 在main.go中添加定时任务每10分钟同步可生产数量到WMS系统
- 为BomItem实体添加relatedStandard字段及相关CRUD方法
- 为InspectionRecord实体添加reportNo、materialCode、materialName等字段
- 更新ent schema确保新字段的验证和默认值设置
- 添加必要的数据库迁移和字段映射逻辑
This commit is contained in:
SunYF
2026-09-17 12:49:07 +08:00
parent b4b274301d
commit 1cc93795ce
191 changed files with 24504 additions and 1250 deletions
+101 -6
View File
@@ -8,6 +8,7 @@ import (
"time"
"bj_power_mes/ent"
"bj_power_mes/ent/bomitem"
"bj_power_mes/ent/inspectionrecord"
)
@@ -42,6 +43,15 @@ type InspectionReq struct {
StepId int `json:"stepId"` // 工艺步骤ID
StepName string `json:"stepName"` // 工艺步骤名称
MeasuredValue string `json:"measuredValue"` // 实测值
// 质量检验(过程检/完工检/来料检)扩展字段
ReportNo string `json:"reportNo"` // 报检单号
MaterialCode string `json:"materialCode"` // 物料编码(图号)
MaterialName string `json:"materialName"` // 物料名称
Manufacturer string `json:"manufacturer"` // 生产厂家
InspectionNo string `json:"inspectionNo"` // 检验单号
AttachmentIds string `json:"attachmentIds"` // 附件ID,逗号分隔
DisposalType string `json:"disposalType"` // 处置类型 退货/返修/退换
DisposalRemark string `json:"disposalRemark"` // 处置说明
}
// CreateInspection 提交巡检记录;ALARM 类型同时触发看板报警(SSE + 清缓存)
@@ -50,7 +60,9 @@ func (s *Service) CreateInspection(ctx context.Context, req InspectionReq, opera
return errors.New("记录类型必填")
}
category := req.Category
if !oneOf(category, "CHECKIN", "POINT", "PROCESS", "DONE", "ALARM") {
// PROCESS 为 PAD 巡检终端「过程巡检」专用;MES 车间质检「过程检」用 QC_PROCESS 隔离,
// 避免同枚举导致两个列表互混、统计口径乱(P1-8)。
if !oneOf(category, "CHECKIN", "POINT", "PROCESS", "DONE", "ALARM", "INCOMING", "FINAL", "QC_PROCESS") {
return errors.New("记录类型不合法")
}
result := req.Result
@@ -60,7 +72,7 @@ func (s *Service) CreateInspection(ctx context.Context, req InspectionReq, opera
if req.Operator == "" {
req.Operator = operator
}
_, err := s.ctx.EntClient.InspectionRecord.Create().
create := s.ctx.EntClient.InspectionRecord.Create().
SetCategory(category).
SetStationNo(string(req.StationNo)).
SetShift(req.Shift).
@@ -74,8 +86,32 @@ func (s *Service) CreateInspection(ctx context.Context, req InspectionReq, opera
SetProcessCode(req.ProcessCode).
SetStepId(req.StepId).
SetStepName(req.StepName).
SetMeasuredValue(req.MeasuredValue).
Save(ctx)
SetMeasuredValue(req.MeasuredValue)
if req.ReportNo != "" {
create.SetReportNo(req.ReportNo)
}
if req.MaterialCode != "" {
create.SetMaterialCode(req.MaterialCode)
}
if req.MaterialName != "" {
create.SetMaterialName(req.MaterialName)
}
if req.Manufacturer != "" {
create.SetManufacturer(req.Manufacturer)
}
if req.InspectionNo != "" {
create.SetInspectionNo(req.InspectionNo)
}
if req.AttachmentIds != "" {
create.SetAttachmentIds(req.AttachmentIds)
}
if req.DisposalType != "" {
create.SetDisposalType(req.DisposalType)
}
if req.DisposalRemark != "" {
create.SetDisposalRemark(req.DisposalRemark)
}
_, err := create.Save(ctx)
if err != nil {
return err
}
@@ -104,13 +140,14 @@ func (s *Service) CreateInspection(ctx context.Context, req InspectionReq, opera
// ListInspections 查询巡检记录(不分页,供内部/导出用,封顶 1000)
func (s *Service) ListInspections(ctx context.Context, category, operator, from, to string) ([]*ent.InspectionRecord, error) {
rows, _, err := s.ListInspectionsPaged(ctx, category, operator, from, to, "", "", 1, 1000)
rows, _, err := s.ListInspectionsPaged(ctx, category, operator, from, to, "", "", "", "", "", 1, 1000)
return rows, err
}
// ListInspectionsPaged 分页查询巡检记录,返回 {rows, total};排序 id desc 最新置顶
// orderNo/stationNo2026-09-08 补充筛选(大小写不敏感)
func (s *Service) ListInspectionsPaged(ctx context.Context, category, operator, from, to, orderNo, stationNo string, page, pageSize int) ([]*ent.InspectionRecord, int, error) {
// materialCode/materialName/reportNo:质量检验模糊查询(Item H,每框内模糊、多框取交集)
func (s *Service) ListInspectionsPaged(ctx context.Context, category, operator, from, to, orderNo, stationNo, materialCode, materialName, reportNo string, page, pageSize int) ([]*ent.InspectionRecord, int, error) {
q := s.ctx.EntClient.InspectionRecord.Query()
if category != "" {
q = q.Where(inspectionrecord.Category(category))
@@ -121,6 +158,15 @@ func (s *Service) ListInspectionsPaged(ctx context.Context, category, operator,
if stationNo != "" {
q = q.Where(inspectionrecord.StationNoEqualFold(stationNo))
}
if materialCode != "" {
q = q.Where(inspectionrecord.MaterialCodeContainsFold(materialCode))
}
if materialName != "" {
q = q.Where(inspectionrecord.MaterialNameContainsFold(materialName))
}
if reportNo != "" {
q = q.Where(inspectionrecord.ReportNoContainsFold(reportNo))
}
if operator != "" {
q = q.Where(inspectionrecord.Operator(operator))
}
@@ -151,3 +197,52 @@ func oneOf(v string, items ...string) bool {
}
return false
}
// GetInspectionRecord 按 id 查询一条检验记录(质量检验处置/不合格单用)
func (s *Service) GetInspectionRecord(ctx context.Context, id int) (*ent.InspectionRecord, error) {
if id <= 0 {
return nil, errors.New("缺少 id")
}
rec, err := s.ctx.EntClient.InspectionRecord.Get(ctx, id)
if err != nil {
return nil, errors.New("检验记录不存在")
}
return rec, nil
}
// SetInspectionDisposal 质量检验处置:区分 退货/返修/退换,写处置说明
func (s *Service) SetInspectionDisposal(ctx context.Context, id int, disposalType, disposalRemark, operator string) error {
if id <= 0 {
return errors.New("缺少 id")
}
if !oneOf(disposalType, "退货", "返修", "退换") {
return errors.New("处置类型仅支持 退货/返修/退换")
}
rec, err := s.ctx.EntClient.InspectionRecord.Get(ctx, id)
if err != nil {
return errors.New("检验记录不存在")
}
_, err = s.ctx.EntClient.InspectionRecord.UpdateOneID(id).
SetDisposalType(disposalType).SetDisposalRemark(disposalRemark).Save(ctx)
if err != nil {
return err
}
s.ctx.EventLog.Write(ctx, "inspection.disposal", rec.OrderNo, operator, "inspection_record", rec.Sn,
"质量检验处置 "+disposalType, map[string]any{"id": id, "remark": disposalRemark})
return nil
}
// QueryBomMaterial 按物料编码或名称/图号模糊检索 BOM 料信息(质量检验"选物料自动带出 BOM"用)
func (s *Service) QueryBomMaterial(ctx context.Context, keyword string) ([]*ent.BomItem, error) {
if keyword == "" {
return []*ent.BomItem{}, nil
}
q := s.ctx.EntClient.BomItem.Query()
q = q.Where(
bomitem.Or(
bomitem.MaterialCodeContainsFold(keyword),
bomitem.MaterialNameContainsFold(keyword),
),
)
return q.Order(ent.Asc(bomitem.FieldProductCode), ent.Asc(bomitem.FieldBomName), ent.Asc(bomitem.FieldID)).Limit(200).All(ctx)
}