using Rhea.Common;
using Tiger.IBusiness;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
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))
{
action = NodeSubmit(action, input);
return action;
}
//当前岗位在当前工单不是首站,则查找条码已绑定的工单当作当前工单
else
{
var wosns = Biz.Db.Queryable((q, s) => new JoinQueryInfos(JoinType.Inner, q.ORDER_NO == s.WORK_ORDER))
.ByAuth(input.AuthOption).Where((q, s) => s.SN == input.SN || s.TRAY_SN == input.SN).Select((q, s) => new { Batch = q, SN = s }).ToList();
//查找到条码已绑定的工单
if (!wosns.IsNullOrEmpty())
{
if (wosns.First().Batch.ACT_LINE != CurLine.LINE_CODE)
{
action.IsSuccessed = false;
//action.LocaleMsg = new($"条码[{0}]已在产线[{1}]投入生产,请在正确岗位扫描");
action.LocaleMsg = new("MES.Transaction.PackingNode.Submit.NotCorrectLine", input.SN, wosns.First().Batch.ACT_LINE);
return action;
}
else
{
if (CurBatch?.Batch?.ORDER_NO != wosns.First().Batch.ORDER_NO)
{
//条码已绑定的工单不等于当前工单则重新选择工单
var result = await SelectOrder(new() { AuthOption = input.AuthOption, OrderNo = wosns.First().Batch.ORDER_NO });
if (!result.IsSuccessed)
{
action.IsSuccessed = result.IsSuccessed;
action.LocaleMsg = result.LocaleMsg;
return action;
}
}
//条码过站
action = NodeSubmit(action, input);
return action;
}
}
//查找不到条码已绑定的工单
else
{
//没有当前工单,则先选择工单后再扫描条码
if (CurBatch.IsNullOrEmpty())
{
action.IsSuccessed = false;
//action.LocaleMsg = new($"未选择工单,请先选择要生产的工单");
action.LocaleMsg = new("MES.Transaction.TestNode.Submit.NotSelectOrderException");
return action;
}
//有当前工单且不是投入,则提示条码未投入生产,请先去首站扫描
else
{
action.IsSuccessed = false;
//action.LocaleMsg = new($"条码[{input.SN}]尚未投入生产,请先去首站扫描", input.SN);
action.LocaleMsg = new("MES.Transaction.TestNode.Submit.NotInputException", input.SN);
return action;
}
}
}
}
//完成第一步,后开始执行当前工序的行为列表
//完成工序节点工步后,后开始执行当前工序的行为工步
else if (IsFinishNodeSteps && !IsFinishAllSteps)
{
var submitStep = Steps.Where(q => q.ID == input.CurStepID && !q.IsFinished).FirstOrDefault();
if (submitStep.IsNullOrEmpty())
{
action = BeginNextActionStep(input);
return action;
}
else
{
var result = submitStep.Submit(input);
//如果当前工步已完成,开始执行下一工步
if (result.IsSuccessed && submitStep.IsFinished)
{
result = BeginNextActionStep(input);
}
//如果当前工步未完成
else
{
//行为执行出错,工步被重置
if (Steps.IsNullOrEmpty())
{
result.LocaleMsg = new(Biz.T(result.LocaleMsg, input.Locale) + Biz.T(Biz.L("MES.Transaction.Position.RescanSN"), input.Locale));
}
else
{
result.Data.SetValue(CurBatch, CurStep, CurStep?.ID, IsFinishAllSteps);
}
}
//如果所有工步都完成
if (IsFinishAllSteps)
{
return DoIfFinishAllSteps(result);
}
return result;
}
}
//没有可执行的工步
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.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
{
//判断工单实时状态判断是否可以生产
var woStatus = CurBatch.CheckCanProduce(curNode);
if (!woStatus.IsSuccessed)
{
return woStatus;
}
//非法过站防呆:进入工序时要增加判断条码是否按流程过站
var wipSNs = Biz.Db.Queryable().IncludesAllFirstLayer().Where(q => (q.SN == input.SN || q.TRAY_SN == input.SN) && q.WORK_ORDER == CurBatch.WO.ORDER_NO).ToList();
if (wipSNs.IsNullOrEmpty())
{
var wipSN = new MES_WIP_DATA()
{
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,
HOLD_FLAG = "N",
REWORK_FLAG = CurBatch.WO.ORDER_TYPE == BIZ_MES_WO.ORDER_TYPEs.Rework.GetValue() ? "Y" : "N",
FINISHED_FLAG = "N",
INV_FLAG = "N",
DFT_FLAG = "N",
DFT_COUNT = 0,
};
wipSNs.Add(wipSN);
}
var canGotoNext = CurBatch.CanGotoNext(input, wipSNs.First(), curNode);
if (!canGotoNext.IsSuccessed)
{
return canGotoNext;
}
//当工步列表为空,则执行当前工序的必要逻辑当作第一个工序节点,完成后按需求创建后续的工步列表
if (Steps.IsNullOrEmpty())
{
//绑定条码到工单
foreach (var wipSN in wipSNs)
{
if (!CurBatch.WoSNs.Any(q => q.SN == wipSN.SN))
{
CurBatch.WoSNs.Add(new()
{
WORK_ORDER = CurBatch.Batch.ORDER_NO,
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.SN == w.SN)).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 (curNode.IS_INPUT == "Y")
{
var woSN = woSNs.First(q => q.SN == wipSN.SN);
woSN.STATUS = BIZ_MES_WO_SN.STATUSs.Inputed.GetValue();
wipSN.STATUS = MES_WIP_DATA.STATUSs.Input.GetValue();
wipSN.INLINE_DATE = DateTime.Now;
}
//如果是产出站
if (curNode.IS_OUTPUT == "Y")
{
var woSN = woSNs.First(q => q.SN == wipSN.SN);
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;
}
}
//工单开工
CurBatch.StartWorking(UserCode);
//把当前条码增加到当前条码列表
CurWipSNs = wipSNs;
CurWipSNHiss.Clear();
foreach (var wipSN in wipSNs)
{
CurWipSNHiss.Add(new MES_WIP_HIS(wipSN, $"工单[{wipSN.WORK_ORDER}]条码[{wipSN.SN}]在岗位[{wipSN.POST_CODE}]过站工序[{wipSN.NODE_NAME}]成功"));
}
//初始化工步列表
Steps.Clear();
var curStep = new Biz.WorkStep(IWorkStep.Types.Node, this)
{
Sequence = Steps.Count + 1,
Node = curNode,
DBSubmitAction = () =>
{
var db = GetCommitDB();
db.Storageable(woSNs, UserCode).ExecuteCommand();
db.Storageable(wipSNs, UserCode).ExecuteCommand();
db.Storageable(CurWipSNHiss, UserCode).ExecuteCommand();
//如果是投入站
if (curNode.IS_INPUT == "Y")
{
db.Updateable().SetColumns(q => q.INPUT_QTY == q.INPUT_QTY + wipSNs.Count).Where(q => q.ORDER_NO == CurBatch.WO.ORDER_NO).ExecuteCommand();
db.Updateable().SetColumns(q => q.INPUT_QTY == q.INPUT_QTY + wipSNs.Count).Where(q => q.BATCH_NO == CurBatch.Batch.BATCH_NO).ExecuteCommand();
}
//如果是产出站
if (curNode.IS_OUTPUT == "Y")
{
db.Updateable().SetColumns(q => q.OUTPUT_QTY == q.OUTPUT_QTY + wipSNs.Count).Where(q => q.ORDER_NO == CurBatch.WO.ORDER_NO).ExecuteCommand();
db.Updateable().SetColumns(q => q.OUTPUT_QTY == q.OUTPUT_QTY + wipSNs.Count).Where(q => q.BATCH_NO == CurBatch.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 = curStep;
}
else if (!IsFinishNodeSteps)
{
var curStep = Steps.Where(q => q.Type == IWorkStep.Types.Node && !q.IsFinished).OrderBy(q => q.Sequence).First();
//完成当前工序节点工步
curStep.IsFinished = true;
CurStep = curStep;
}
//未完成所有工步
if (!IsFinishAllSteps)
{
var result = new ApiAction(new SubmitOutput());
//未完成所有工序节点工步
if (!IsFinishNodeSteps)
{
var next = Steps.Where(q => q.Type == IWorkStep.Types.Node && !q.IsFinished).OrderBy(q => q.Sequence).First();
//设置后续可执行的工步列表
NextSteps.Clear();
NextSteps.Add(next);
//根据后续工步返回ApiAction
result.Data.SetValue(CurBatch, CurStep, next.ID, IsFinishAllSteps);
//根据工序节点工步的序号返回相应的操作提示
switch (next.Sequence)
{
case 2:
//action.LocaleMsg = new($"请执行第二步");
result.LocaleMsg = new("MES.Transaction.TestNode.第二步操作提示");
break;
default:
break;
}
}
//已完成所有工序节点工步,开始执行行为工步
else
{
result = BeginNextActionStep(input);
}
return result;
}
//已完成所有工步
else
{
action.Data.SetValue(CurBatch, CurStep, "", IsFinishAllSteps);
action = DoIfFinishAllSteps(action);
}
}
catch (Exception ex)
{
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)
{
//保存数据库
SaveStepsCommitActionToDB();
//保存成功,返回过站消息
//action.LocaleMsg = new($"工单[{CurWipSN.WORK_ORDER}]的条码[{CurWipSN.SN}]在岗位[{CurWipSN.POST_CODE}]工序[{CurWipSN.NODE_NAME}]过站成功,状态[{CurWipSN.STATUS.GetEnumDesc()}]");
action.LocaleMsg = new("MES.Transaction.CollectNode.ScanSn.PassSuccess", CurWipSNs.First().WORK_ORDER, CurSN, CurWipSNs.First().POST_CODE, CurWipSNs.First().NODE_NAME, CurWipSNs.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);
return action;
}
#endregion Functions
public override bool Close(bool needSaveHistoryLog = false)
{
//needSaveHistoryLog = true;
//保存操作日志
this.IsFinished = true;
return IsFinished ? base.Close(needSaveHistoryLog) : IsFinished;
}
}//endClass
}