fix: rebuild MES as compilable go-zero+ent backend (renamed bj_power_mes), restore 3 workstation projects from pristine original, align naming; all Go projects go build clean
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
package manual_action
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"bj_power_mes/internal/svc"
|
||||
"bj_power_mes/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type CompleteRecoveryLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewCompleteRecoveryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CompleteRecoveryLogic {
|
||||
return &CompleteRecoveryLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CompleteRecoveryLogic) CompleteRecovery() (resp *types.CompleteRecoveryReply, err error) {
|
||||
if err := l.svcCtx.EventLoop.CompleteRecovery(l.ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &types.CompleteRecoveryReply{Success: true}, nil
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package manual_action
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"bj_power_mes/common/errorx"
|
||||
"bj_power_mes/constants"
|
||||
"bj_power_mes/ent"
|
||||
"bj_power_mes/internal/eventbus"
|
||||
"bj_power_mes/internal/processor/eventloop"
|
||||
"bj_power_mes/internal/svc"
|
||||
"bj_power_mes/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type ConfirmRecoveryLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// 确认 L3 恢复
|
||||
func NewConfirmRecoveryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ConfirmRecoveryLogic {
|
||||
return &ConfirmRecoveryLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ConfirmRecoveryLogic) ConfirmRecovery(req *types.ConfirmRecoveryReq) (resp *types.ConfirmRecoveryReply, err error) {
|
||||
a, err := l.svcCtx.EntClient.ManualAction.Get(l.ctx, req.Id)
|
||||
if ent.IsNotFound(err) {
|
||||
return nil, errorx.NewDirectError("人工待办不存在")
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if a.ActionType != constants.ManualActionType_RecoveryRequired {
|
||||
return nil, errorx.NewDirectError("该待办不是恢复确认")
|
||||
}
|
||||
if a.Status != constants.ManualActionStatus_PENDING {
|
||||
return nil, errorx.NewDirectError("该待办已处理或已过期")
|
||||
}
|
||||
|
||||
orderID := 0
|
||||
if a.OrderId != nil {
|
||||
orderID = *a.OrderId
|
||||
}
|
||||
if orderID <= 0 {
|
||||
return nil, errorx.NewDirectError("恢复待办缺少工单")
|
||||
}
|
||||
|
||||
_, err = l.svcCtx.EntClient.WorkOrder.Get(l.ctx, orderID)
|
||||
if ent.IsNotFound(err) {
|
||||
return nil, l.expireMissingOrderAction(req.Id, a.ActionType)
|
||||
} else if err != nil {
|
||||
return nil, fmt.Errorf("check work order %d: %w", orderID, err)
|
||||
}
|
||||
|
||||
// 根据决策执行操作
|
||||
switch req.Decision {
|
||||
case string(constants.RecoveryDecision_RESUME):
|
||||
result, err := l.svcCtx.EventLoop.SendSync(eventloop.EventLoopMessage{
|
||||
Type: eventloop.CmdRestoreOrder,
|
||||
Payload: map[string]any{"orderId": orderID},
|
||||
}, 10*time.Second)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !result.Success {
|
||||
return nil, fmt.Errorf("restore order %d failed: %s", orderID, result.Error)
|
||||
}
|
||||
case string(constants.RecoveryDecision_SUSPEND):
|
||||
// 保持当前状态,仅更新 manual_action
|
||||
case string(constants.RecoveryDecision_SCRAP):
|
||||
// 标记工件报废由后续任务处理
|
||||
case string(constants.RecoveryDecision_WAIT_UNLOAD):
|
||||
// 等待卸载后恢复
|
||||
default:
|
||||
return nil, errorx.NewDirectError("不支持的恢复决策")
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
_, err = l.svcCtx.EntClient.ManualAction.UpdateOneID(req.Id).
|
||||
SetStatus(constants.ManualActionStatus_RESOLVED).
|
||||
SetResolvedAction(req.Decision).
|
||||
SetResolvedAt(now).
|
||||
Save(l.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l.svcCtx.EventBus.Publish(l.ctx, eventbus.NewManualActionResolvedEvent(
|
||||
req.Id, string(a.ActionType), req.Decision,
|
||||
))
|
||||
|
||||
return &types.ConfirmRecoveryReply{
|
||||
OrderId: orderID,
|
||||
Decision: req.Decision,
|
||||
NewStatus: string(constants.WorkOrderStatus_InProgress),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *ConfirmRecoveryLogic) expireMissingOrderAction(actionID int, actionType constants.ManualActionType) error {
|
||||
now := time.Now()
|
||||
_, err := l.svcCtx.EntClient.ManualAction.UpdateOneID(actionID).
|
||||
SetStatus(constants.ManualActionStatus_EXPIRED).
|
||||
SetResolvedAction("ORDER_NOT_FOUND").
|
||||
SetResolvedAt(now).
|
||||
Save(l.ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("expire missing-order manual action %d: %w", actionID, err)
|
||||
}
|
||||
|
||||
l.svcCtx.EventBus.Publish(l.ctx, eventbus.NewManualActionResolvedEvent(
|
||||
actionID, string(actionType), "ORDER_NOT_FOUND",
|
||||
))
|
||||
|
||||
return errorx.NewDirectError("关联工单不存在,待办已过期")
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package manual_action
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"bj_power_mes/constants"
|
||||
entjob "bj_power_mes/ent/job"
|
||||
"bj_power_mes/internal/processor/eventloop"
|
||||
"bj_power_mes/internal/svc"
|
||||
"bj_power_mes/internal/types"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
type FixPositionLogic struct {
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewFixPositionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FixPositionLogic {
|
||||
return &FixPositionLogic{ctx: ctx, svcCtx: svcCtx}
|
||||
}
|
||||
|
||||
func (l *FixPositionLogic) FixPosition(req *types.FixPositionReq) (*types.FixPositionReply, error) {
|
||||
// SCRAP:现场找不到工件,直接报废(清位置 + 工单 failNum +1),不走暂存台校验
|
||||
if req.PositionType == "SCRAP" {
|
||||
return l.scrapJob(req.JobId)
|
||||
}
|
||||
|
||||
// 读取 job 自身的位置/工步作为默认值
|
||||
job, err := l.svcCtx.EntClient.Job.Get(l.ctx, req.JobId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get job: %w", err)
|
||||
}
|
||||
tempSlotNo := req.TempSlotNo
|
||||
if tempSlotNo == 0 {
|
||||
if job.TempSlotNo == nil || *job.TempSlotNo == 0 {
|
||||
return nil, fmt.Errorf("job %d has no temp slot, must specify tempSlotNo", req.JobId)
|
||||
}
|
||||
tempSlotNo = *job.TempSlotNo
|
||||
}
|
||||
stepId := req.StepId
|
||||
if stepId == "" {
|
||||
stepId = job.CurrentStepId
|
||||
}
|
||||
|
||||
// 校验:暂存台槽位范围
|
||||
dbState := eventloop.NewDBState(l.svcCtx.EntClient)
|
||||
capacity := dbState.TempSlotCapacity(l.ctx)
|
||||
if tempSlotNo < 1 || tempSlotNo > capacity {
|
||||
return nil, fmt.Errorf("temp slot %d out of range [1,%d]", tempSlotNo, capacity)
|
||||
}
|
||||
|
||||
// 校验:暂存台槽位未被占用
|
||||
occupied, err := l.svcCtx.EntClient.Job.Query().
|
||||
Where(
|
||||
entjob.TempSlotNoEQ(tempSlotNo),
|
||||
entjob.StatusNEQ(constants.JobStatus_Completed),
|
||||
entjob.StatusNEQ(constants.JobStatus_Scrapped),
|
||||
entjob.IDNEQ(req.JobId),
|
||||
).
|
||||
Count(l.ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("check temp slot: %w", err)
|
||||
}
|
||||
if occupied > 0 {
|
||||
return nil, fmt.Errorf("temp slot %d is occupied", tempSlotNo)
|
||||
}
|
||||
|
||||
// 执行修复:释放 equipment_slot + 更新 job 位置/步骤
|
||||
if err := dbState.FixJobPosition(l.ctx, req.JobId, tempSlotNo, stepId, req.PositionType); err != nil {
|
||||
return nil, fmt.Errorf("fix position: %w", err)
|
||||
}
|
||||
|
||||
// release MachineActor in-memory slot (only when moving OFF equipment)
|
||||
if req.PositionType != "ON_EQUIPMENT_DONE" && req.PositionType != "ON_EQUIPMENT_PROCESSING" {
|
||||
|
||||
l.svcCtx.EventLoop.SyncMachineSlotStatus(req.JobId, req.PositionType)
|
||||
}
|
||||
slog.Info("fix position: job recovered", "jobId", req.JobId, "tempSlotNo", tempSlotNo, "stepId", stepId, "positionType", req.PositionType)
|
||||
return &types.FixPositionReply{JobId: req.JobId}, nil
|
||||
}
|
||||
|
||||
// scrapJob 报废现场找不到的工件:释放设备槽位 + 终态 Scrapped + 工单 failNum +1 + 同步 Actor 内存。
|
||||
func (l *FixPositionLogic) scrapJob(jobID int) (*types.FixPositionReply, error) {
|
||||
dbState := eventloop.NewDBState(l.svcCtx.EntClient)
|
||||
if err := dbState.ScrapRecoveryJob(l.ctx, jobID); err != nil {
|
||||
return nil, fmt.Errorf("scrap job %d: %w", jobID, err)
|
||||
}
|
||||
// 同步 MachineActor 内存槽位(SCRAP 走 default 分支 ReleaseSlot)
|
||||
l.svcCtx.EventLoop.SyncMachineSlotStatus(jobID, "SCRAP")
|
||||
slog.Info("fix position: job scrapped (not found on site)", "jobId", jobID)
|
||||
return &types.FixPositionReply{JobId: jobID}, nil
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package manual_action
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"bj_power_mes/constants"
|
||||
"bj_power_mes/ent"
|
||||
"bj_power_mes/ent/job"
|
||||
"bj_power_mes/ent/manualaction"
|
||||
"bj_power_mes/internal/svc"
|
||||
"bj_power_mes/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type QueryManualActionsLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// 查询人工交互列表
|
||||
func NewQueryManualActionsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryManualActionsLogic {
|
||||
return &QueryManualActionsLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryManualActionsLogic) QueryManualActions(req *types.QueryManualActionsReq) (resp *types.QueryManualActionsReply, err error) {
|
||||
q := l.svcCtx.EntClient.ManualAction.Query()
|
||||
|
||||
if req.ActionType != "" {
|
||||
q.Where(manualaction.ActionTypeEQ(constants.ManualActionType(req.ActionType)))
|
||||
}
|
||||
if req.Resolved != nil {
|
||||
// Resolved=true 表示已完成(status=RESOLVED)
|
||||
if *req.Resolved {
|
||||
q.Where(manualaction.StatusEQ("RESOLVED"))
|
||||
} else {
|
||||
q.Where(manualaction.StatusEQ("PENDING"))
|
||||
}
|
||||
}
|
||||
if req.StartTime != nil {
|
||||
q.Where(manualaction.CreatedAtGTE(time.UnixMilli(*req.StartTime)))
|
||||
}
|
||||
if req.EndTime != nil {
|
||||
q.Where(manualaction.CreatedAtLTE(time.UnixMilli(*req.EndTime)))
|
||||
}
|
||||
|
||||
total, err := q.Count(l.ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("count manual actions: %w", err)
|
||||
}
|
||||
|
||||
q.Order(ent.Desc(manualaction.FieldCreatedAt))
|
||||
|
||||
offset := (req.Page - 1) * req.Limit
|
||||
records, err := q.Offset(offset).Limit(req.Limit).All(l.ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("query manual actions: %w", err)
|
||||
}
|
||||
|
||||
// 批量查 workpieceNo(jobId → workpieceNo)
|
||||
jobIDs := make([]int, 0)
|
||||
for _, a := range records {
|
||||
if a.JobId != nil && *a.JobId > 0 {
|
||||
jobIDs = append(jobIDs, *a.JobId)
|
||||
}
|
||||
}
|
||||
wpNoMap := make(map[int]string)
|
||||
if len(jobIDs) > 0 {
|
||||
jobs, jerr := l.svcCtx.EntClient.Job.Query().
|
||||
Where(job.IDIn(jobIDs...)).
|
||||
All(l.ctx)
|
||||
if jerr == nil {
|
||||
for _, j := range jobs {
|
||||
wpNoMap[j.ID] = j.WorkpieceNo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
items := make([]types.ManualAction, len(records))
|
||||
for i, a := range records {
|
||||
item := types.ManualAction{
|
||||
Id: a.ID,
|
||||
ActionType: string(a.ActionType),
|
||||
Status: string(a.Status),
|
||||
ResolvedAction: a.ResolvedAction,
|
||||
ResolvedBy: a.ResolvedBy,
|
||||
CreatedAt: a.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
|
||||
}
|
||||
if a.OrderId != nil {
|
||||
item.OrderId = *a.OrderId
|
||||
}
|
||||
if a.JobId != nil {
|
||||
item.JobId = *a.JobId
|
||||
item.WorkpieceNo = wpNoMap[*a.JobId]
|
||||
}
|
||||
if a.EquipmentId != nil {
|
||||
item.EquipmentId = *a.EquipmentId
|
||||
}
|
||||
if a.Context != nil {
|
||||
item.Context = a.Context
|
||||
}
|
||||
if a.ResolvedAt != nil {
|
||||
item.ResolvedAt = a.ResolvedAt.Format("2006-01-02T15:04:05Z07:00")
|
||||
}
|
||||
items[i] = item
|
||||
}
|
||||
|
||||
return &types.QueryManualActionsReply{
|
||||
PageReply: types.PageReply{
|
||||
Page: req.Page,
|
||||
Limit: req.Limit,
|
||||
Total: total,
|
||||
},
|
||||
Data: items,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package manual_action
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"bj_power_mes/constants"
|
||||
"bj_power_mes/ent"
|
||||
"bj_power_mes/ent/job"
|
||||
"bj_power_mes/ent/workorder"
|
||||
"bj_power_mes/internal/svc"
|
||||
"bj_power_mes/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type QueryRecoveryJobsLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewQueryRecoveryJobsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryRecoveryJobsLogic {
|
||||
return &QueryRecoveryJobsLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryRecoveryJobsLogic) QueryRecoveryJobs() (resp *types.QueryRecoveryJobsReply, err error) {
|
||||
// 查询 IN_PROGRESS 工单下,仍在设备中(ON_EQUIPMENT)的活跃工件,等待人工确认位置
|
||||
jobs, err := l.svcCtx.EntClient.Job.Query().
|
||||
WithWorkOrder().
|
||||
Where(
|
||||
job.StatusNotIn(constants.JobStatus_Completed, constants.JobStatus_Scrapped),
|
||||
job.PositionTypeIn(constants.PositionType_OnEquipment),
|
||||
job.HasWorkOrderWith(workorder.StatusEQ(constants.WorkOrderStatus_InProgress)),
|
||||
).
|
||||
All(l.ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("query recovery jobs: %w", err)
|
||||
}
|
||||
|
||||
data := make([]types.RecoveryJobInfo, 0, len(jobs))
|
||||
for _, j := range jobs {
|
||||
data = append(data, buildRecoveryJobInfo(j, "on_equipment")) // 在设备上需要确认有没有完成
|
||||
}
|
||||
|
||||
// 比对 PLC TempStates 与 DB tempSlotNo,标记暂存台不一致项
|
||||
data = l.appendTempMismatches(data)
|
||||
|
||||
return &types.QueryRecoveryJobsReply{Data: data}, nil
|
||||
}
|
||||
|
||||
// appendTempMismatches 读取 PLC 暂存台槽位状态,与 DB 中活跃工件的 tempSlotNo 比对,
|
||||
// 标记 db_only(DB 有记录但现场无占用)/ plc_only(现场有占用但 DB 无记录)。
|
||||
// robot 不可用或读取失败时降级为原列表,不阻塞恢复流程。
|
||||
func (l *QueryRecoveryJobsLogic) appendTempMismatches(data []types.RecoveryJobInfo) []types.RecoveryJobInfo {
|
||||
robotCtrl, ok := l.svcCtx.RobotManager.GetRobot()
|
||||
if !ok {
|
||||
slog.Info("recovery: robot unavailable, skip TempStates mismatch check")
|
||||
return data
|
||||
}
|
||||
plcStates, err := robotCtrl.TempStates()
|
||||
if err != nil || len(plcStates) == 0 {
|
||||
slog.Warn("recovery: read TempStates failed, skip mismatch check", "error", err, "len", len(plcStates))
|
||||
return data
|
||||
}
|
||||
|
||||
// 查 DB 记录在暂存台(ON_BUFFER)且有 tempSlotNo 的活跃工件(工单 IN_PROGRESS)
|
||||
tempJobs, err := l.svcCtx.EntClient.Job.Query().
|
||||
WithWorkOrder().
|
||||
Where(
|
||||
job.StatusNotIn(constants.JobStatus_Completed, constants.JobStatus_Scrapped),
|
||||
job.PositionTypeEQ(constants.PositionType_OnBuffer),
|
||||
job.TempSlotNoNotNil(),
|
||||
job.HasWorkOrderWith(workorder.StatusEQ(constants.WorkOrderStatus_InProgress)),
|
||||
).
|
||||
All(l.ctx)
|
||||
if err != nil {
|
||||
slog.Warn("recovery: query temp jobs failed, skip mismatch check", "error", err)
|
||||
return data
|
||||
}
|
||||
|
||||
// 已存在于列表中的 jobID → 索引,用于就地打标
|
||||
existing := make(map[int]int, len(data))
|
||||
for i, d := range data {
|
||||
existing[d.JobID] = i
|
||||
}
|
||||
|
||||
// slotNo → job(越界槽位跳过,RecoverOnStartup 已为越界创建 manual_action)
|
||||
slotToJob := make(map[int]*ent.Job, len(tempJobs))
|
||||
for _, tj := range tempJobs {
|
||||
if tj.TempSlotNo == nil {
|
||||
continue
|
||||
}
|
||||
slot := *tj.TempSlotNo
|
||||
if slot < 1 || slot > len(plcStates) {
|
||||
continue
|
||||
}
|
||||
slotToJob[slot] = tj
|
||||
}
|
||||
|
||||
// db_only:DB 有 tempSlotNo 但 PLC 该槽位无占用
|
||||
for slot, tj := range slotToJob {
|
||||
if !plcStates[slot-1] {
|
||||
if idx, ok := existing[tj.ID]; ok {
|
||||
data[idx].Mismatch = "db_only"
|
||||
} else {
|
||||
item := buildRecoveryJobInfo(tj, "db_only")
|
||||
data = append(data, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// plc_only:PLC 有占用但 DB 无对应 tempSlotNo 记录(现场"幽灵"工件)
|
||||
for i, occupied := range plcStates {
|
||||
slot := i + 1
|
||||
if !occupied {
|
||||
continue
|
||||
}
|
||||
if _, ok := slotToJob[slot]; ok {
|
||||
continue
|
||||
}
|
||||
data = append(data, types.RecoveryJobInfo{
|
||||
JobID: 0,
|
||||
TempSlotNo: slot,
|
||||
Status: string(constants.JobStatus_OnBuffer),
|
||||
Mismatch: "plc_only",
|
||||
})
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
func buildRecoveryJobInfo(j *ent.Job, mismatch string) types.RecoveryJobInfo {
|
||||
workOrderNo := ""
|
||||
if j.Edges.WorkOrder != nil {
|
||||
workOrderNo = j.Edges.WorkOrder.WorkOrderNo
|
||||
}
|
||||
return types.RecoveryJobInfo{
|
||||
JobID: j.ID,
|
||||
WorkpieceNo: j.WorkpieceNo,
|
||||
WorkOrderID: j.WorkOrderId,
|
||||
WorkOrderNo: workOrderNo,
|
||||
Status: string(j.Status),
|
||||
PositionType: string(j.PositionType),
|
||||
PositionRefID: j.PositionRefId,
|
||||
TempSlotNo: derefInt(j.TempSlotNo),
|
||||
CurrentStepID: j.CurrentStepId,
|
||||
CurrentStepName: "",
|
||||
DockNo: derefInt(j.DockNo),
|
||||
DockSlotNo: derefInt(j.DockSlotNo),
|
||||
ProductTypeID: j.ProductTypeId,
|
||||
Mismatch: mismatch,
|
||||
}
|
||||
}
|
||||
|
||||
func derefInt(v *int) int {
|
||||
if v == nil {
|
||||
return 0
|
||||
}
|
||||
return *v
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package manual_action
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"bj_power_mes/constants"
|
||||
"bj_power_mes/ent"
|
||||
"bj_power_mes/internal/eventbus"
|
||||
"bj_power_mes/internal/svc"
|
||||
"bj_power_mes/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type ResolveScanFailedLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// 处理扫码失败
|
||||
func NewResolveScanFailedLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ResolveScanFailedLogic {
|
||||
return &ResolveScanFailedLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ResolveScanFailedLogic) ResolveScanFailed(req *types.ResolveScanFailedReq) (resp *types.ResolveScanFailedReply, err error) {
|
||||
a, err := l.svcCtx.EntClient.ManualAction.Get(l.ctx, req.Id)
|
||||
if ent.IsNotFound(err) {
|
||||
return nil, err
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if a.ActionType != constants.ManualActionType_ScanFailed {
|
||||
return nil, err
|
||||
}
|
||||
if a.Status != constants.ManualActionStatus_PENDING {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
_, err = l.svcCtx.EntClient.ManualAction.UpdateOneID(req.Id).
|
||||
SetStatus(constants.ManualActionStatus_RESOLVED).
|
||||
SetResolvedAction(req.Action).
|
||||
SetResolvedAt(now).
|
||||
Save(l.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l.svcCtx.EventBus.Publish(l.ctx, eventbus.NewManualActionResolvedEvent(
|
||||
req.Id, string(a.ActionType), req.Action,
|
||||
))
|
||||
|
||||
return &types.ResolveScanFailedReply{
|
||||
Id: req.Id,
|
||||
Status: string(constants.ManualActionStatus_RESOLVED),
|
||||
ResolvedAction: req.Action,
|
||||
ResolvedAt: now.UnixMilli(),
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user