Files
bj_power/bj_power_mes/internal/logic/semi.go
T
SunYF d3eda6b588 feat&refactor: 2026-09-22 半成品业务模型重构与功能完善
- 重构半成品流转逻辑:进度权威源改为 workpiece.currentStationNo,新增 completedText 快照字段,废除 doneProcessCodes
- 清理物料品类中半成品类型,存量数据幂等清理,调整物料管理方式文案为批次/序列号
- 新增日排产状态专用更新接口,修复工单工艺校验逻辑
- 新增物料档案代理接口、深路径文件下载接口
- 优化前端界面文案与工位选择逻辑,补充追溯页半成品流转展示
- 调整WMS端物料品类校验与入库接口契约
- 新增/更新数据库表结构与实体类代码
2026-09-22 14:42:52 +08:00

79 lines
3.0 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"
"bj_power_mes/ent"
"bj_power_mes/ent/semiflow"
"bj_power_mes/ent/workpiece"
)
type SemiReq struct {
Sn string `json:"sn"`
OrderNo string `json:"orderNo"`
Action string `json:"action"` // INBOUND / OUTBOUND
TargetDock string `json:"targetDock"`
}
// SemiFlow 半成品流转:进度唯一权威源=workpiece.currentStationNo(最后报工工位号),
// 服务端按 sn 自取进度生成 completedText"已完成至工位N";未报工传空串),
// 并调用 WMS /api/internal/semi/*payload={sn,orderNo,completedText,operator},旧 doneProcessCodes 已废除)。
func (s *Service) SemiFlow(ctx context.Context, req SemiReq, operator string) error {
if req.Sn == "" {
return errors.New("sn 不能为空")
}
action := req.Action
if action == "" {
action = "INBOUND"
}
// 服务端自取进度:工件未上线(无 workpiece 记录)一律拒绝流转
wp, err := s.ctx.EntClient.Workpiece.Query().Where(workpiece.Sn(req.Sn)).First(ctx)
if err != nil {
return errors.New("工件未上线,无法暂存退库")
}
completedText := ""
if wp.CurrentStationNo > 0 {
completedText = "已完成至工位" + itoa(wp.CurrentStationNo)
}
_, err = s.ctx.EntClient.SemiFlow.Create().
SetSn(req.Sn).SetOrderNo(req.OrderNo).SetCompletedText(completedText).
SetAction(action).SetTargetDock(req.TargetDock).SetOperator(operator).Save(ctx)
if err != nil {
return err
}
// 调用 WMS 内部接口(本地 SemiFlow 已保存,下面把 WMS 同步结果如实返回,
// 不再静默吞掉——WMS 不可达或校验失败时必须让调用方感知,才能形成闭环)。
var wmsErr error
if action == "INBOUND" {
wmsErr = s.ctx.Wms.SemiInbound(ctx, req.Sn, req.OrderNo, completedText, operator)
} else {
wmsErr = s.ctx.Wms.SemiOutbound(ctx, req.Sn, req.OrderNo, completedText, operator)
}
if wmsErr != nil {
s.ctx.EventLog.Write(ctx, "semi.flow.wms_error", req.OrderNo, operator, "semi_flow", req.Sn,
"WMS 同步失败", map[string]any{"action": action, "error": wmsErr.Error()})
return wmsErr
}
s.ctx.EventLog.Write(ctx, "semi.flow", req.OrderNo, operator, "semi_flow", req.Sn, "半成品流转",
map[string]any{"action": action, "completedText": completedText})
return nil
}
// ListSemiFlows 查询半成品流转记录
func (s *Service) ListSemiFlows(ctx context.Context, sn, orderNo string) ([]*ent.SemiFlow, error) {
q := s.ctx.EntClient.SemiFlow.Query()
if sn != "" {
q = q.Where(semiflow.Sn(sn))
}
if orderNo != "" {
q = q.Where(semiflow.OrderNo(orderNo))
}
return q.Order(ent.Desc(semiflow.FieldID)).All(ctx)
}
// ListEventLogs 操作日志查询(按工单号/操作人;operators 为候选列表,任一命中即算)
func (s *Service) ListEventLogs(ctx context.Context, orderNo string, operators []string, eventType string, fromMs, toMs int64, page, pageSize int) ([]*ent.EventLog, int, error) {
return s.ctx.EventLog.Query(ctx, eventType, orderNo, operators, fromMs, toMs, page, pageSize)
}