1. 全局替换"工序"为"工艺"统一术语,包括页面文案、枚举、注释
2. 重构工单与工件工艺数据模型:
- 新增工艺组合表flow_material作为备料/齐套唯一源头
- 新增工位状态表station_state支持自主停单/恢复接单
- 移除station_process派工表,改用工单工艺组合作为路线唯一源头
- 替换processCode为flowId作为工艺关联标识
- 重构工件当前进度字段为currentStationNo
3. 删除冗余的静态备份资源文件
4. 调整物料选择组件默认启用仅显示激活物料
5. 优化工单创建/编辑逻辑,新增工艺组合校验与保存
117 lines
4.1 KiB
Go
117 lines
4.1 KiB
Go
package logic
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"fmt"
|
||
"strings"
|
||
|
||
"bj_power_mes/ent"
|
||
"bj_power_mes/ent/stationstate"
|
||
"bj_power_mes/ent/workorder"
|
||
)
|
||
|
||
// ---------- 工位停单(station_state,只认当天) ----------
|
||
|
||
// SetStationPause 工人自主停单/恢复(某工位当天停止/恢复接单)。
|
||
// upsert:stationNo+date 唯一;恢复=标记可用即续走,工单/组合/排产三要素零变动。
|
||
// 停单瞬间做「工艺全停」判定:某工艺绑定的全部工位当天都停单 → 报警(flow_all_paused)+事件日志。
|
||
func (s *Service) SetStationPause(ctx context.Context, stationNo int, paused bool, reason, operator string) error {
|
||
if stationNo <= 0 {
|
||
return errors.New("stationNo 必填")
|
||
}
|
||
date := TodayStr()
|
||
exist, err := s.ctx.EntClient.StationState.Query().
|
||
Where(stationstate.StationNo(stationNo), stationstate.Date(date)).Only(ctx)
|
||
if err != nil && !ent.IsNotFound(err) {
|
||
return err
|
||
}
|
||
if exist == nil {
|
||
if err := s.ctx.EntClient.StationState.Create().
|
||
SetStationNo(stationNo).SetDate(date).SetPaused(paused).
|
||
SetReason(reason).SetOperator(operator).Exec(ctx); err != nil {
|
||
return err
|
||
}
|
||
} else {
|
||
if err := s.ctx.EntClient.StationState.UpdateOneID(exist.ID).
|
||
SetPaused(paused).SetReason(reason).SetOperator(operator).Exec(ctx); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
action := "工位恢复接单"
|
||
eventType := "station.respawn"
|
||
if paused {
|
||
action = "工位停止接单(停单)"
|
||
eventType = "station.pause"
|
||
}
|
||
s.ctx.EventLog.Write(ctx, eventType, "", operator, "station_state", itoa(stationNo),
|
||
fmt.Sprintf("%s(工位%d,%s)", action, stationNo, date),
|
||
map[string]any{"stationNo": stationNo, "date": date, "paused": paused, "reason": reason})
|
||
if paused {
|
||
s.checkAllPausedFlows(ctx, operator)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// checkAllPausedFlows 工艺全停判定:执行中工单的组合里,某工艺涉及的全部工位当天都停单 → 报警+日志。
|
||
// (上位机在该工艺全停期间不下发流转指令;恢复=任一工位恢复即续走。)
|
||
func (s *Service) checkAllPausedFlows(ctx context.Context, operator string) {
|
||
wos, err := s.ctx.EntClient.WorkOrder.Query().
|
||
Where(workorder.Status("IN_PROGRESS")).All(ctx)
|
||
if err != nil {
|
||
return
|
||
}
|
||
for _, wo := range wos {
|
||
items, _ := RouteStationsFromWO(ctx, s.ctx.EntClient, wo)
|
||
if len(items) == 0 {
|
||
continue
|
||
}
|
||
byFlow := map[int][]int{}
|
||
for _, it := range items {
|
||
byFlow[it.FlowId] = append(byFlow[it.FlowId], it.StationNo)
|
||
}
|
||
for flowId, stations := range byFlow {
|
||
allPaused := len(stations) > 0
|
||
parts := make([]string, 0, len(stations))
|
||
for _, no := range stations {
|
||
parts = append(parts, itoa(no))
|
||
if !s.GetStationPaused(ctx, no) {
|
||
allPaused = false
|
||
}
|
||
}
|
||
if !allPaused {
|
||
continue
|
||
}
|
||
content := fmt.Sprintf("工艺「%s」的全部工位(%s)已停单,上位机不下发流转指令",
|
||
s.flowNameById(ctx, flowId), strings.Join(parts, ","))
|
||
_, _ = s.ctx.EntClient.Alert.Create().
|
||
SetRuleId(0).SetType("flow_all_paused").SetTitle("工艺全停").
|
||
SetContent(content).SetRefType("process_flow").SetRefId(fmt.Sprintf("%d", flowId)).
|
||
SetOrderNo(wo.WorkOrderNo).SetReceiver("").SetStatus("UNREAD").Save(ctx)
|
||
s.ctx.EventLog.Write(ctx, "flow.all_paused", wo.WorkOrderNo, operator, "process_flow", itoa(flowId),
|
||
content, map[string]any{"flowId": flowId, "stations": stations})
|
||
}
|
||
}
|
||
}
|
||
|
||
// GetStationPaused 某工位当天是否停单(无记录=未停单)
|
||
func (s *Service) GetStationPaused(ctx context.Context, stationNo int) bool {
|
||
if stationNo <= 0 {
|
||
return false
|
||
}
|
||
rows, err := s.ctx.EntClient.StationState.Query().
|
||
Where(stationstate.StationNo(stationNo), stationstate.Date(TodayStr()), stationstate.Paused(true)).
|
||
Limit(1).All(ctx)
|
||
return err == nil && len(rows) > 0
|
||
}
|
||
|
||
// ListStationStates 查询停单状态列表(date 空取当天)
|
||
func (s *Service) ListStationStates(ctx context.Context, date string) ([]*ent.StationState, error) {
|
||
if date == "" {
|
||
date = TodayStr()
|
||
}
|
||
return s.ctx.EntClient.StationState.Query().
|
||
Where(stationstate.Date(date)).
|
||
Order(ent.Asc(stationstate.FieldStationNo)).All(ctx)
|
||
}
|