using Rhea.Common;
using SqlSugar;
using Tiger.IBusiness;
using Tiger.Model;
using Tiger.Model.Entitys.MES.Position;
namespace Tiger.Business.MES.Transaction
{
///
/// 测试工序事务
///
public class TestNode : Position, ITestNode
{
public new ITestNode Init(string id, string apiHost, string userCode, string postCode)
{
base.Init(id, apiHost, userCode, postCode);
Logger.Console.Info($"User[{userCode}] start a {this.GetType().Name}[{postCode}] Transaction[ID: {TransID}]");
return this;
}
#region Propertys & Variables
#endregion Propertys & Variables
#region Functions
///
/// 测试工序:提交操作数据
///
///
///
public async Task> Submit(SubmitInput input)
{
var action = new ApiAction(new SubmitOutput());
try
{
//工步列表为空或者工序节点工步有未完成时,优先完成工序节点工步
if (Steps.IsNullOrEmpty() || !IsFinishNodeSteps)
{
//先判断当前工单不为空且当前岗位在当前工单是不是首站,如果是则不允许变更当前工单,尝试把条码绑定到当前工单
if (!CurBatch.IsNullOrEmpty() && CurBatch.IsFirstNode(PostCode))
{
//更新CurBatch
CurBatch?.Update();
//提交数据
action = NodeSubmit(action, input);
//更新工序信息
if (!action.IsSuccessed)
{
var info = WoContext.GetSnOperInfo(input.SN).Data;
info.InputQty = CurOperInfo(input.Locale).InputQty;
action.Data.OperInfo = info;
}
else if (Steps.Any() && !IsFinishAllSteps)
{
action.Data.OperInfo = SetOperNodeInfo(CurOperInfo(input.Locale));
}
}
//当前岗位在当前工单不是首站,则查找条码已绑定的工单当作当前工单
else
{
var wosns = Biz.Db.Queryable((q, s) => new JoinQueryInfos(JoinType.Inner, q.ORDER_NO == s.WORK_ORDER && q.BATCH_NO == s.BATCH_NO))
.ByAuth(input.AuthOption)//.Where((q, s) => s.STATUS < BIZ_MES_WO_SN.STATUSs.Finished.GetValue())
.Where((q, s) => s.SN == input.SN || s.FLOW_SN == input.SN || s.TRAY_SN == input.SN).Select((q, s) => new { Batch = q, SN = s }).ToList();
//查找到条码已绑定的工单
if (wosns.Any(q => q.SN.STATUS < BIZ_MES_WO_SN.STATUSs.Finished.GetValue()))
{
var curSNs = wosns.Where(q => q.SN.STATUS < BIZ_MES_WO_SN.STATUSs.Finished.GetValue());
if (curSNs.First().Batch.ACT_LINE != CurLine.LINE_CODE)
{
action.Data.ShortMsg = new("产线错误", ShortMessage.Types.Error);
action.Data.OperInfo = new();
action.IsSuccessed = false;
//action.LocaleMsg = new($"条码[{0}]已在产线[{1}]投入生产,请在正确岗位扫描");
action.LocaleMsg = new("MES.Transaction.PackingNode.Submit.NotCorrectLine", input.SN, curSNs.First().Batch.ACT_LINE);
}
else
{
if (CurBatch?.Batch?.ORDER_NO != curSNs.First().Batch.ORDER_NO)
{
//条码已绑定的工单不等于当前工单则重新选择工单
var result = await SelectOrder(new() { AuthOption = input.AuthOption, OrderNo = curSNs.First().Batch.ORDER_NO }, curSNs.First().Batch.BATCH_NO);
if (!result.IsSuccessed)
{
action.Data.ShortMsg = new("工单异常", ShortMessage.Types.Error);
action.Data.OperInfo = new();
action.IsSuccessed = result.IsSuccessed;
action.LocaleMsg = result.LocaleMsg;
return action;
}
}
//更新CurBatch
CurBatch?.Update();
//条码过站
action = NodeSubmit(action, input);
if (!action.IsSuccessed && !CurWipSNs.Any())
{
var info = WoContext.GetSnOperInfo(input.SN).Data;
info.InputQty = CurOperInfo(input.Locale).InputQty;
action.Data.OperInfo = info;
}
else if (Steps.Any() && !IsFinishAllSteps)
{
action.Data.OperInfo = SetOperNodeInfo(CurOperInfo(input.Locale));
}
}
}
//查找不到条码已绑定的工单
else
{
var lastSn = wosns.OrderByDescending(q => q.SN.UPDATE_TIME).FirstOrDefault();
if (!lastSn.IsNullOrEmpty())
{
action.Data.ShortMsg = new($"产品{lastSn.SN.STATUS.GetEnumDesc()}", ShortMessage.Types.Error);
action.Data.OperInfo = new();
action.IsSuccessed = false;
//action.LocaleMsg = new($"进站扫描错误,条码[{0}]{1}");
action.LocaleMsg = new("MES.Transaction.TestNode.Submit.SnStatusError", input.SN, lastSn.SN.STATUS.GetEnumDesc());
}
else
{
//没有当前工单,则先选择工单后再扫描条码
if (CurBatch.IsNullOrEmpty())
{
action.Data.ShortMsg = new("未选择工单", ShortMessage.Types.Error);
action.Data.OperInfo = new();
action.IsSuccessed = false;
//action.LocaleMsg = new($"未选择工单,请先选择要生产的工单");
action.LocaleMsg = new("MES.Transaction.TestNode.Submit.NotSelectOrderException");
}
//有当前工单且不是投入,则提示条码未投入生产,请先去首站扫描
else
{
action.Data.ShortMsg = new("未投入生产", ShortMessage.Types.Error);
action.Data.OperInfo = new();
action.IsSuccessed = false;
//action.LocaleMsg = new($"条码[{input.SN}]尚未投入生产,请先去首站扫描", input.SN);
action.LocaleMsg = new("MES.Transaction.TestNode.Submit.NotInputException", input.SN);
}
}
}
}
}
//完成工序节点工步后,开始执行当前工序的行为工步
else if (IsFinishNodeSteps && !IsFinishAllSteps)
{
//更新CurBatch
CurBatch?.Update();
var submitStep = Steps.Where(q => q.ID == input.CurStepID && !q.IsFinished).FirstOrDefault();
//如果客户端返回的当前工步ID找不到未完成的行为工步,则直接开始下一个行为工步
if (submitStep.IsNullOrEmpty())
{
action = BeginNextActionStep(input);
}
else
{
action = submitStep.Submit(input);
//如果当前工步已完成,开始执行下一工步
if (action.IsSuccessed && submitStep.IsFinished)
{
action = BeginNextActionStep(input);
}
//如果当前工步未完成
else
{
//行为执行出错,工步被重置
if (Steps.IsNullOrEmpty())
{
action.LocaleMsg = new(Biz.T(action.LocaleMsg, input.Locale) + Biz.T(Biz.L("MES.Transaction.Position.RescanSN"), input.Locale));
}
else
{
action.Data.SetValue(CurBatch, CurStep, CurStep?.ID, IsFinishAllSteps);
}
}
}
//如果所有工步都完成
if (IsFinishAllSteps)
{
action = DoIfFinishAllSteps(action, input.Locale);
}
else
{
action.Data.OperInfo = CurOperInfo(input.Locale);
}
}
//没有可执行的工步
else
{
action.Data.ShortMsg = new("重置扫描", ShortMessage.Types.Error);
action.Data.OperInfo = CurOperInfo(input.Locale);
ResetNode();
action.IsSuccessed = false;
//action.LocaleMsg = new($"岗位[{CurPosition.POST_CODE}]工步执行异常,请重新扫描产品条码", CurPosition.POST_CODE);
action.LocaleMsg = new("MES.Transaction.TestNode.Submit.WorkStepException", CurPosition.POST_CODE);
}
}
catch (Exception ex)
{
action.Data.ShortMsg = new("工序异常", ShortMessage.Types.Error);
action.Data.OperInfo = CurOperInfo(input.Locale);
//action.CatchExceptionWithLog(ex, $"测试工序:提交操作数据异常");
action.CatchExceptionWithLog(ex, Biz.L("MES.Transaction.TestNode.SubmitException"));
}
return action;
}
///
/// 工序节点工步提交数据
///
///
///
///
public ApiAction NodeSubmit(ApiAction action, SubmitInput input)
{
var curNode = CurBatch.GetNode(PostCode);
try
{
//工序节点逻辑增加如果根基当前岗位找不到对应工序的时候要报错
if (curNode.IsNullOrEmpty())
{
action.Data.ShortMsg = new("未知工序", ShortMessage.Types.Error);
action.IsSuccessed = false;
//action.LocaleMsg = new($"岗位[{0}]在工单[{1}]工艺路线中找不到对应的工序,请检查工单工艺路线中工序与岗位的绑定关系是否正确");
action.LocaleMsg = new("MES.Transaction.TestNode.NodeSubmit.OperateNodeError", PostCode, CurBatch.WO.ORDER_NO);
return action;
}
var curNodeSetting = CurBatch.GetNodeSetting(curNode);
//当工步列表为空,则执行当前工序的必要逻辑当作第一个工序节点,完成后按需求创建后续的工步列表
if (Steps.IsNullOrEmpty())
{
BeginAt = DateTime.Now;
//判断工单实时状态判断是否可以生产
var woStatus = CurBatch.CheckCanProduce(curNode, curNodeSetting);
if (!woStatus.IsSuccessed)
{
woStatus.Data.ShortMsg = new("工单异常", ShortMessage.Types.Error);
return woStatus;
}
var wipSNs = Biz.Db.Queryable().IncludesAllFirstLayer().Where(q => q.SN == input.SN || q.FLOW_SN == input.SN || q.TRAY_SN == input.SN).ToList();
if (wipSNs.IsNullOrEmpty())
{
var wipSN = new MES_WIP_DATA()
{
SN = input.SN,
FLOW_SN = input.SN,
STATUS = MES_WIP_DATA.STATUSs.Init.GetValue(),
ITEM_CODE = CurBatch.WO.ITEM_CODE,
WORK_ORDER = CurBatch.Batch.ORDER_NO,
BATCH_NO = CurBatch.Batch.BATCH_NO,
FTY_CODE = CurFactory.FTY_CODE,
WS_CODE = CurWorkshop.WS_CODE,
LINE_CODE = CurLine.LINE_CODE,
POST_CODE = CurPosition.POST_CODE,
HOLD_FLAG = "N",
REWORK_FLAG = CurBatch.WO.ORDER_TYPE == BIZ_MES_WO.ORDER_TYPEs.Rework.GetValue() ? "Y" : "N",
FINISHED_FLAG = "N",
UNBIND_FLAG = "N",
INV_FLAG = "N",
DFT_FLAG = "N",
DFT_COUNT = 0,
};
wipSNs.Add(wipSN);
}
//如果条码不是当前工单或者产线的则报错
if (wipSNs.Any(q => q.WORK_ORDER != CurBatch.WO.ORDER_NO || q.LINE_CODE != CurLine.LINE_CODE))
{
if (wipSNs.First().LINE_CODE == CurLine.LINE_CODE)
{
action.Data.ShortMsg = new("工单错误", ShortMessage.Types.Error);
action.IsSuccessed = false;
//action.LocaleMsg = new($"产品[{CurSN}]不属于当前工单,请切换到工单[{wipSNs.First().WORK_ORDER}]后再扫描");
action.LocaleMsg = new("MES.Transaction.TestNode.NodeSubmit.WoError", input.SN, wipSNs.First().WORK_ORDER);
return action;
}
else
{
action.Data.ShortMsg = new("产线错误", ShortMessage.Types.Error);
action.IsSuccessed = false;
//action.LocaleMsg = new($"产品[{CurSN}]已在产线[{wipSNs.First().LINE_CODE}]投产,请到产线[{wipSNs.First().LINE_CODE}]扫描");
action.LocaleMsg = new("MES.Transaction.TestNode.NodeSubmit.LineError", input.SN, wipSNs.First().LINE_CODE);
return action;
}
}
//非法过站防呆:进入工序时要增加判断条码是否按流程过站
var canGotoNext = CurBatch.CanGotoNext(input, wipSNs.First(), curNode);
if (!canGotoNext.IsSuccessed)
{
woStatus.Data.ShortMsg = new("进站错误", ShortMessage.Types.Error);
return canGotoNext;
}
//绑定条码到工单
foreach (var wipSN in wipSNs)
{
if (!CurBatch.WoSNs.Any(q => q.WIP_ID == wipSN.ID))
{
CurBatch.WoSNs.Add(new()
{
WORK_ORDER = CurBatch.Batch.ORDER_NO,
WIP_ID = wipSN.ID,
SN = wipSN.SN,
FLOW_SN = wipSN.SN,
TRAY_SN = wipSN.TRAY_SN,
STATUS = BIZ_MES_WO_SN.STATUSs.NotInput.GetValue(),
});
}
}
//更新工单条码明细信息
var woSNs = CurBatch.WoSNs.Where(q => wipSNs.Any(w => q.WIP_ID == w.ID)).ToList();
foreach (var woSN in woSNs)
{
woSN.AUTH_ORG = CurBatch.WO.AUTH_ORG;
woSN.AUTH_PROD = CurLine.LINE_CODE;
woSN.BATCH_NO = CurBatch.Batch.BATCH_NO;
}
//条码过站
foreach (var wipSN in wipSNs)
{
wipSN.AUTH_ORG = CurBatch.WO.AUTH_ORG;
wipSN.AUTH_PROD = CurLine.LINE_CODE;
wipSN.STATUS = MES_WIP_DATA.STATUSs.OK.GetValue();//wipSN.STATUS > 0 ? MES_WIP_DATA.STATUSs.OK.GetValue() : wipSN.STATUS;
wipSN.ROT_CODE = CurBatch.WO.ROUTE_CODE;
wipSN.NODE_ID = curNode.ID;
wipSN.NODE_NAME = curNode.NODE_NAME;
wipSN.FTY_CODE = CurFactory.FTY_CODE;
wipSN.WS_CODE = CurWorkshop.WS_CODE;
wipSN.LINE_CODE = CurLine.LINE_CODE;
wipSN.POST_CODE = CurPosition.POST_CODE;
wipSN.OPER_CODE = curNode.OPER_CODE;
wipSN.SEGMENT = curNode.SEGMENT;
wipSN.OPERATION_TIME = DateTime.Now;
var curShiftPeriod = GetShiftPeriodForNow();
if (!curShiftPeriod.IsNullOrEmpty())
{
wipSN.SFTS_CODE = curShiftPeriod.ShiftSys.SFTS_CODE;
wipSN.SFT_CODE = curShiftPeriod.Shift.SFT_CODE;
wipSN.PRD_CODE = curShiftPeriod.Period.PRD_CODE;
}
//如果是投入站
if (curNodeSetting.IS_INPUT == "Y")
{
var woSN = woSNs.First(q => q.WIP_ID == wipSN.ID);
woSN.STATUS = BIZ_MES_WO_SN.STATUSs.Inputed.GetValue();
wipSN.STATUS = MES_WIP_DATA.STATUSs.Input.GetValue();
wipSN.INLINE_DATE = DateTime.Now;
}
//如果是产出站
if (curNodeSetting.IS_OUTPUT == "Y")
{
var woSN = woSNs.First(q => q.WIP_ID == wipSN.ID);
woSN.STATUS = BIZ_MES_WO_SN.STATUSs.Finished.GetValue();
wipSN.STATUS = MES_WIP_DATA.STATUSs.Finished.GetValue();
wipSN.OUTLINE_DATE = DateTime.Now;
}
//如果有提交不良
if (!input.DFT_CODE.IsNullOrEmpty())
{
wipSN.STATUS = MES_WIP_DATA.STATUSs.NG.GetValue();
wipSN.DFT_FLAG = "Y";
wipSN.DFT_COUNT++;
wipSN.DFT_CODE = input.DFT_CODE;
var dft = CurBatch.Defects.FirstOrDefault(q => q.DFT_CODE == wipSN.DFT_CODE);
var defect = new MES_WIP_DFT()
{
AUTH_ORG = wipSN.AUTH_ORG,
AUTH_PROD = wipSN.LINE_CODE,
SN = wipSN.SN,
STATUS = MES_WIP_DFT.STATUSs.WaitHandle.GetValue(),
ITEM_CODE = wipSN.ITEM_CODE,
WORK_ORDER = wipSN.WORK_ORDER,
BATCH_NO = wipSN.BATCH_NO,
ROT_CODE = wipSN.ROT_CODE,
NODE_ID = wipSN.NODE_ID,
NODE_NAME = wipSN.NODE_NAME,
FTY_CODE = wipSN.FTY_CODE,
WS_CODE = wipSN.WS_CODE,
LINE_CODE = wipSN.LINE_CODE,
POST_CODE = wipSN.POST_CODE,
OPER_CODE = wipSN.OPER_CODE,
SEGMENT = wipSN.SEGMENT,
DFT_CODE = dft.DFT_CODE,
DFT_NAME = dft.DFT_NAME,
DFT_LEVEL = dft.DFT_LEVEL,
FLOW_SN = wipSN.FLOW_SN,
TRAY_SN = wipSN.TRAY_SN,
INNER_SN = wipSN.INNER_SN,
CARTON_SN = wipSN.CARTON_SN,
PALLET_SN = wipSN.PALLET_SN,
INV_FLAG = wipSN.INV_FLAG,
OPERATION_TIME = DateTime.Now,
SFTS_CODE = wipSN.SFTS_CODE,
SFT_CODE = wipSN.SFT_CODE,
PRD_CODE = wipSN.PRD_CODE,
OBA_BATCH = wipSN.OBA_BATCH,
LOCK_BATCH = wipSN.LOCK_BATCH,
WIP_ID = wipSN.ID,
};
wipSN.Defects.Add(defect);
CurDefects.Add(defect);
}
}
//产品被判断不良后下线,并从工单中移除正在生产的条码
if (CurDefects.Any() && curNodeSetting.IF_DFT_OFFLINE == "Y")
{
woStatus.Data.ShortMsg = new("产品下线", ShortMessage.Types.Error);
return OfflineIfDefect(action, wipSNs, input.Locale);
}
//工单开工
CurBatch.StartWorking(UserCode);
//把当前条码增加到当前条码列表
CurWipSNs = wipSNs;
CurWipSNHiss.Clear();
foreach (var wipSN in wipSNs)
{
var his = new MES_WIP_HIS(wipSN, $"工单[{wipSN.WORK_ORDER}]条码[{wipSN.SN}]在岗位[{wipSN.POST_CODE}]过站工序[{wipSN.NODE_NAME}]成功(TransId: {TransID} )");
wipSN.History.Add(his);
CurWipSNHiss.Add(his);
}
//创建变量克隆对象用于传入DBSubmitAction中保存当前需要暂存的数据值
var _woSns = woSNs.Clone();
var _wipSns = wipSNs.Clone();
var _wipHiss = CurWipSNHiss.Clone();
var _defect = CurDefects.Clone();
var _curNodeSetting = curNodeSetting.Clone();
var _Batch = CurBatch.Batch.Clone();
//初始化工步列表
Steps.Clear();
var curStep = new WorkStep(IWorkStep.NodeTypes.Node, this)
{
Name = "扫描产品",
Sequence = Steps.Count + 1,
Node = curNode,
OperSetting = CurBatch.NodeSets.FirstOrDefault(q => q.NODE_ID == curNode.ID),
DBSubmitAction = () =>
{
//使用统一的事务DB对象
var db = GetCommitDB();
//数据保存逻辑
db.Storageable(_woSns, UserCode).ExecuteCommand();
db.Storageable(_wipSns, UserCode).ExecuteCommand();
db.Storageable(_wipHiss, UserCode).ExecuteCommand();
//如果有不良则保存
if (_defect.Any())
{
db.Storageable(_defect, UserCode).ExecuteCommand();
}
//如果是投入站
if (_curNodeSetting.IS_INPUT == "Y")
{
db.Updateable().SetColumns(q => q.INPUT_QTY == q.INPUT_QTY + _woSns.Count).Where(q => q.ORDER_NO == _Batch.ORDER_NO).ExecuteCommand();
db.Updateable().SetColumns(q => q.INPUT_QTY == q.INPUT_QTY + _woSns.Count).Where(q => q.BATCH_NO == _Batch.BATCH_NO).ExecuteCommand();
}
//如果是产出站
if (_curNodeSetting.IS_OUTPUT == "Y")
{
db.Updateable().SetColumns(q => q.OUTPUT_QTY == q.OUTPUT_QTY + _woSns.Count).Where(q => q.ORDER_NO == _Batch.ORDER_NO).ExecuteCommand();
db.Updateable().SetColumns(q => q.OUTPUT_QTY == q.OUTPUT_QTY + _woSns.Count).Where(q => q.BATCH_NO == _Batch.BATCH_NO).ExecuteCommand();
}
}
};
Steps.Add(curStep);
//有需要用户提交信息则添加工序节点的其他工步
//最后添加当前工序的行为工步
try
{
GenerateSteps(curStep);
}
catch (System.Exception ex)
{
ResetNode();
//action.CatchExceptionWithLog(ex, $"{curNode.NODE_NAME}:工序行为工步生成异常,请检查工序行为设置");
action.CatchExceptionWithLog(ex, Biz.L("MES.Transaction.TestNode.NodeSubmit.GenerateStepsException", curNode.NODE_NAME));
}
//完成第一个工序节点工步
curStep.IsFinished = true;
curStep.Status = StepStatus.Finished;
CurStep = curStep;
}
else if (!IsFinishNodeSteps)
{
var curStep = Steps.Where(q => q.NodeType == IWorkStep.NodeTypes.Node && !q.IsFinished).OrderBy(q => q.Sequence).First();
//根据工序节点工步的序号处理相应工步的处理逻辑
switch (curStep.Sequence)
{
case 2:
{
//第二工步的处理逻辑
//完成当前工序节点工步
curStep.IsFinished = true;
curStep.Status = StepStatus.Finished;
CurStep = curStep;
}
break;
default:
break;
}
}
//未完成所有工步
if (!IsFinishAllSteps)
{
//未完成所有工序节点工步
if (!IsFinishNodeSteps)
{
var next = Steps.Where(q => q.NodeType == IWorkStep.NodeTypes.Node && !q.IsFinished).OrderBy(q => q.Sequence).First();
//设置后续可执行的工步列表
NextSteps.Clear();
NextSteps.Add(next);
//根据后续工步返回ApiAction
action.Data.SetValue(CurBatch, CurStep, next.ID, IsFinishAllSteps);
//根据工序节点工步的序号返回相应的操作提示
switch (next.Sequence)
{
case 2:
//action.LocaleMsg = new($"请执行第二步");
action.LocaleMsg = new("MES.Transaction.TestNode.第二步操作提示");
break;
default:
break;
}
}
//已完成所有工序节点工步,开始执行行为工步
else
{
action = BeginNextActionStep(input);
}
}
//已完成所有工步
if (IsFinishAllSteps)
{
action.Data.SetValue(CurBatch, CurStep, "", IsFinishAllSteps);
action = DoIfFinishAllSteps(action, input.Locale);
}
}
catch (Exception ex)
{
action.Data.ShortMsg = new("工步异常", ShortMessage.Types.Error);
ResetNode();
//action.CatchExceptionWithLog(ex, $"{curNode.NODE_NAME}:工序节点工步提交数据异常,请检查工序节点设置");
action.CatchExceptionWithLog(ex, Biz.L("MES.Transaction.TestNode.NodeSubmitException", curNode.NODE_NAME));
}
return action;
}
///
/// 完成所有工步后执行
///
///
///
public ApiAction DoIfFinishAllSteps(ApiAction action, string locale)
{
var operInfo = SetOperNodeInfo(CurOperInfo(locale));
Action endAction = null;
//如果当前条码已经走到流程终点则记录条码完工
if (operInfo.IsReachedEndNode)
{
//更新工单条码明细信息
var woSNs = CurBatch.WoSNs.Where(q => CurWipSNs.Any(w => q.WIP_ID == w.ID)).ToList();
foreach (var woSN in woSNs)
{
woSN.STATUS = BIZ_MES_WO_SN.STATUSs.Finished.GetValue();
}
var curNode = CurBatch.Nodes.First(q => q.OPER_CODE == "EndNode");
//条码完工
foreach (var wipSN in CurWipSNs)
{
wipSN.STATUS = MES_WIP_DATA.STATUSs.Finished.GetValue();
wipSN.NODE_ID = curNode.ID;
wipSN.NODE_NAME = curNode.NODE_NAME;
wipSN.OPER_CODE = curNode.OPER_CODE;
wipSN.SEGMENT = curNode.SEGMENT;
}
var wipHiss = new List();
foreach (var wipSN in CurWipSNs)
{
var his = new MES_WIP_HIS(wipSN, $"工单[{wipSN.WORK_ORDER}]条码[{wipSN.SN}]在岗位[{wipSN.POST_CODE}]过站工序[{wipSN.NODE_NAME}]成功(TransId: {TransID} )");
wipSN.History.Add(his);
wipHiss.Add(his);
}
//创建变量克隆对象用于传入DBSubmitAction中保存当前需要暂存的数据值
var _woSns = woSNs.Clone();
var _wipSns = CurWipSNs.Clone();
var _wipHiss = wipHiss.Clone();
//保存数据
endAction = () =>
{
//使用统一的事务DB对象
var db = GetCommitDB();
//数据保存逻辑
db.Storageable(_woSns, UserCode).ExecuteCommand();
db.Storageable(_wipSns, UserCode).ExecuteCommand();
db.Storageable(_wipHiss, UserCode).ExecuteCommand();
};
}
//保存数据库
SaveStepsCommitActionToDB(endAction);
//保存成功,返回过站消息
operInfo.InputQty += CurWipSNs.Count;
action.Data.OperInfo = operInfo;
action.Data.ShortMsg = new(CurWipSNs.Any(q => q.DFT_FLAG == "Y") ? "不良过站" : "良品过站", ShortMessage.Types.Success);
//action.LocaleMsg = new($"工单[{CurWipSN.WORK_ORDER}]的条码[{CurWipSN.SN}]在岗位[{CurWipSN.POST_CODE}]工序[{CurWipSN.NODE_NAME}]过站成功,状态[{CurWipSN.STATUS.GetEnumDesc()}]");
action.LocaleMsg = new("MES.Transaction.TestNode.ScanSn.PassSuccess", CurWipSNs.First().WORK_ORDER, CurSN, CurWipSNs.First().POST_CODE, CurWipSNs.First().NODE_NAME, CurWipSNs.First().STATUS.GetEnumDesc());
//如果当前条码已经完工,检查当前工单批次和工单是否完工
if (action.Data.OperInfo.IsReachedEndNode)
{
CurBatch.CheckIsComplete(UserCode);
}
//重置工序
ResetNode();
return action;
}
///
/// 产品被判断不良后下线
///
///
///
public ApiAction OfflineIfDefect(ApiAction action, List wipSNs, string locale)
{
var operInfo = SetOperNodeInfo(CurOperInfo(locale));
operInfo.CurNode = wipSNs.FirstOrDefault()?.NODE_NAME;
operInfo.NextNode = "下线退库";
//更新工单条码明细信息
var woSNs = CurBatch.WoSNs.Where(q => wipSNs.Any(w => q.WIP_ID == w.ID)).ToList();
foreach (var woSN in woSNs)
{
woSN.STATUS = BIZ_MES_WO_SN.STATUSs.Offline.GetValue();
}
//条码下线
foreach (var wipSN in wipSNs)
{
wipSN.STATUS = MES_WIP_DATA.STATUSs.Offline.GetValue();
wipSN.UNBIND_FLAG = "Y";
}
var wipHiss = new List();
foreach (var wipSN in wipSNs)
{
var his = new MES_WIP_HIS(wipSN, $"工单[{wipSN.WORK_ORDER}]条码[{wipSN.SN}]在岗位[{wipSN.POST_CODE}]工序[{wipSN.NODE_NAME}]因不良[{wipSN.Defects.FirstOrDefault()?.DFT_NAME}]下线(TransId: {TransID} )");
wipSN.History.Add(his);
wipHiss.Add(his);
}
//创建变量克隆对象用于传入DBSubmitAction中保存当前需要暂存的数据值
var _woSns = woSNs.Clone();
var _wipSns = wipSNs.Clone();
var _wipHiss = wipHiss.Clone();
var _defect = CurDefects.Clone();
//使用统一的事务DB对象
var db = GetCommitDB();
//保存数据库
var dbTran = db.UseTran(() =>
{
//数据保存逻辑
db.Storageable(_woSns, UserCode).ExecuteCommand();
db.Storageable(_wipSns, UserCode).ExecuteCommand();
db.Storageable(_wipHiss, UserCode).ExecuteCommand();
db.Storageable(_defect, UserCode).ExecuteCommand();
});
if (!dbTran.IsSuccess)
{
//抛出异常
throw dbTran.ErrorException;
}
//从工单中移除正在生产的条码
CurBatch.RemoveWipSn(wipSNs, UserCode);
//保存成功,返回过站消息
action.Data.OperInfo = operInfo;
action.Data.ShortMsg = new("下线退库", ShortMessage.Types.Warning);
//action.LocaleMsg = new($"工单[0]的条码[1]在岗位[2]工序[3]因不良[4]下线,状态[5]");
action.LocaleMsg = new("MES.Transaction.TestNode.OfflineIfDefect", wipSNs.First().WORK_ORDER, CurSN, wipSNs.First().POST_CODE, wipSNs.First().NODE_NAME, wipSNs.First().Defects.FirstOrDefault()?.DFT_NAME, wipSNs.First().STATUS.GetEnumDesc());
//重置工序
ResetNode();
return action;
}
///
/// 测试工序:获取工序不良代码
///
///
public ApiAction> GetDefects()
{
var action = new ApiAction>();
//没有当前工单,则先选择工单后再扫描条码
if (CurBatch.IsNullOrEmpty())
{
action.IsSuccessed = false;
//action.LocaleMsg = new($"请先扫描要过站的条码");
action.LocaleMsg = new("MES.Transaction.TestNode.GetDefects.NotScanException");
return action;
}
action.Data = CurBatch.GetNodeDefects(PostCode);
//action.Data = new List { new DefectOutput { DFTG_CODE = "111111"} };
//action.Data = new List { new DefectOutput { DFTG_CODE = "222222" } };
return action;
}
#endregion Functions
public override bool Close(bool needSaveHistoryLog = false)
{
//needSaveHistoryLog = true;
//保存操作日志
this.IsFinished = true;
return IsFinished ? base.Close(needSaveHistoryLog) : IsFinished;
}
}//endClass
}