using DOAN.Model.MES.product; using MDM.Attribute; using MDM.Model.Process; using MDM.Models.Flow; using MDM.Models.Process; using MDM.Models.Session; using RIZO.Model.MES.recipe; using RIZO.Model.MES.recipe.Dto; using System.Text.Json; namespace MDM.Services.Flows { /// /// 普通流程功能函数 /// // [AppService(ServiceType = typeof(CommonFlowService), ServiceLifetime = LifeTime.Singleton)] public class CommonFlowService : BaseService { /// /// 普通入站流程 /// /// 工序代码 /// 产品序列号 /// 入站结果 [RIZOFlow(FlowType = "common_inbound_flow")] public InStationApplyResult CommonInboundStationFlow(string operationCode, string processCode) { // 参数验证 if (string.IsNullOrWhiteSpace(operationCode)) { return InStationApplyResult.InvalidParameters; } if (string.IsNullOrWhiteSpace(processCode)) { return InStationApplyResult.InvalidParameters; } //1.获取产品是正常件,完成件,返工件 ProductLifecycle productInfo = Context.Queryable() .Where(p => p.ProductSN == processCode) .First(); if (productInfo == null) { // 产品未开工,不得入站 RecordTrace(productInfo, operationCode, 0, ApplyStatusEnum.REJECTED, InStationApplyResult.ProductNotStartWork.ToString(), "产品未开工,不得入站"); return InStationApplyResult.ProductNotStartWork; } if (productInfo.ProductStatus == 2) { // 产品已经生产完成,不得入站 RecordTrace(productInfo, operationCode, 2, ApplyStatusEnum.REJECTED, InStationApplyResult.ProductCompleted.ToString(), "产品已经生产完成,不得入站"); return InStationApplyResult.ProductCompleted; } if (productInfo.ProductStatus == 3) { // 返工件允许入站 RecordTrace(productInfo, operationCode, 3, ApplyStatusEnum.SUCCESS, string.Empty, string.Empty); return InStationApplyResult.Success; } if (productInfo.ProductStatus == 1) { //正常件处理 // 1.检查是否重复进站 bool IsRepeatInStation = Context.Queryable() .Where(it => it.ProductSN == processCode && it.OperationCode == operationCode) .Any(); if (IsRepeatInStation) { // 重复进站禁止入站 RecordTrace(productInfo, operationCode, 3, ApplyStatusEnum.REJECTED, InStationApplyResult.RepeatInStation.ToString(), "重复进站禁止入站"); return InStationApplyResult.RepeatInStation; } // 获取工序信息 ProcessOperation processOperation = Context.Queryable() .Where(it => it.FkRoutingCode == productInfo.RoutingCode && it.OperationCode == operationCode).First(); if (processOperation == null) { return InStationApplyResult.OperationNotFound; } // 可跳过的工序直接允许入站 if (processOperation.IsSkippable == 1) { RecordTrace(productInfo, operationCode, 1, ApplyStatusEnum.SUCCESS, null, null); return InStationApplyResult.Success; } // 检查上一工序状态 if (processOperation.OperationSeq <= 10) { // 当前是第一个工序,无需检查上一工序 RecordTrace(productInfo, operationCode, 1, ApplyStatusEnum.SUCCESS, null, null); return InStationApplyResult.Success; } // 获取上一个工序 var lastOperation = Context.Queryable() .Where(it => it.FkRoutingCode == productInfo.RoutingCode) .Where(it => it.OperationSeq < processOperation.OperationSeq) .OrderByDescending(it => it.OperationSeq) .First(); if (lastOperation == null) { return InStationApplyResult.PreviousOperationNotFound; } // 获取上一工序的通过记录状态 判断上一站是否已经出站 bool lastOperationStatus = Context.Queryable() .Where(it => it.ProductSN == processCode && it.OperationCode == lastOperation.OperationCode) .Where(it => it.ApplyType == ApplyTypeEnum.OUT) .Where(it => it.ApplyStatus == ApplyStatusEnum.SUCCESS) .Any(); if (lastOperationStatus) { // 上一工序已完成,允许入站 RecordTrace(productInfo, operationCode, 1, ApplyStatusEnum.SUCCESS, InStationApplyResult.Success.ToString(), "上一工序已完成,允许入站"); return InStationApplyResult.Success; } else { // 上一工序未完成,禁止入站 RecordTrace(productInfo, operationCode, 1, ApplyStatusEnum.REJECTED, InStationApplyResult.PreviousOperationNotStarted.ToString(), "上一工序未完成,禁止入站"); return InStationApplyResult.PreviousOperationNotStarted; } } return InStationApplyResult.UnknownStatus; } /// /// 记录入站操作轨迹 /// /// 产品信息 /// 工序代码 /// 入站结果 /// 拒绝原因代码 /// 拒绝原因描述 private void RecordTrace(ProductLifecycle product, string operationCode, int ProductionLifeStage, ApplyStatusEnum isPass, string rejectReasonCode, string rejectReasonDesc) { // 更新产品状态 if (product != null) { Context.Updateable() .SetColumns(it => new ProductLifecycle { ProductStatus = 1, // 设置为生产中状态 UpdatedTime = DateTime.Now }) .Where(it => it.ProductSN == product.ProductSN) .ExecuteCommand(); } // 构建入站记录 var passstationRecord = new ProductPassstationRecord { Workorder = product?.Workorder, Routingcode = product?.RoutingCode, ProductSN = product?.ProductSN ?? string.Empty, OperationCode = operationCode, ProductionLifeStage = ProductionLifeStage, // 生产中 ApplyType = ApplyTypeEnum.IN, ApplyStatus = isPass, RejectReasonCode = rejectReasonCode, RejectReasonDesc = rejectReasonDesc, InStationTime = DateTime.Now, CreatedTime = DateTime.Now }; Context.Insertable(passstationRecord).ExecuteCommand(); } //TODO: 下发中间操作流程规则 //TODO: 扫码流程 类型 [RIZOFlow(FlowType = "Scanningcode_flow")] public string ScanningcodeFlow(string RoutingCode, string operationCode, string FlowCode) { //获取这个工序d的扫码规则 List flowRuleList = Context.Queryable().LeftJoin((f, m) => f.FkRoutingCode == m.FkRoutingCode && f.FkOperationCode == m.FkOperationCode && f.FlowCode == m.FkFlowCode) .Where((f, m) => f.FkRoutingCode == RoutingCode && f.FkOperationCode == operationCode && f.FlowTypeCode == "Scanningcode_flow" && f.FlowCode == FlowCode) .Select((f, m) => new ProcessOperationFlowMaterialParamter() { id = f.id, FkRoutingCode = f.FkRoutingCode, FkOperationCode = f.FkOperationCode, FkFlowCode = m.FkFlowCode, MaterialCode = m.MaterialCode, MaterialName = m.MaterialName, UseErrorProofRuleCode = m.UseErrorProofRuleCode, }) .ToList(); var data = new { flowbase = new { routingCode = RoutingCode, operationCode = operationCode, flowCode = FlowCode }, flowRuleList }; return System.Text.Json.JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true }); } //TODO: 数采流程 类型 (工位流程) [RIZOFlow(FlowType = "data_collect_flow")] public string DataCollectFlow(string RoutingCode, string operationCode, string FlowCode, string ProductlinebodyCode, string WorkstationCode) { //获取这个工序d的扫码规则 List flowRuleList = Context.Queryable().LeftJoin ((f, m) => f.FkRoutingCode == m.FkRoutingCode && f.FkOperationCode == m.FkOperationCode && f.FlowCode == m.FkFlowCode) .Where((f, m) => f.FkRoutingCode == RoutingCode && f.FkOperationCode == operationCode && f.FlowTypeCode == "Scanningcode_flow") .Where((f, m) => m.FkProductlinebodyCode == ProductlinebodyCode && m.FkWorkstationCode == WorkstationCode && m.FkFlowCode == FlowCode) .Select((f, m) => new ProcessOperationWorkstationFlowCollectParameter() { FkRoutingCode = f.FkRoutingCode, FkOperationCode = f.FkOperationCode, FkProductlinebodyCode = m.FkProductlinebodyCode, FkWorkstationCode = m.FkWorkstationCode, FkFlowCode = m.FkFlowCode, ParameterCode = m.ParameterCode, PlcPoint = m.PlcPoint, ParameterName = m.ParameterName, Description = m.Description, DataType = m.DataType, Unit = m.Unit, StandardValue = m.StandardValue, MinValue = m.MinValue, MaxValue = m.MaxValue, IsControlled = m.IsControlled, IsMonitored = m.IsMonitored, ControlType = m.ControlType, DefaultValue = m.DefaultValue, IsRequired = m.IsRequired, Sequence = m.Sequence, }) .ToList(); var data = new { flowbase = new { routingCode = RoutingCode, operationCode = operationCode, productlinebodyCode = ProductlinebodyCode, workstationCode = WorkstationCode, flowCode = FlowCode }, flowRuleList }; return System.Text.Json.JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true }); } //TODO: 配方流程 类型 [RIZOFlow(FlowType = "recipe_distribute_flow")] public string RecipeDistributeFlow(string RoutingCode, string operationCode, string FlowCode) { var flowRuleList = Context.Queryable() .LeftJoin((refpr, ver) => refpr.RecipeCode == ver.RecipeCode) .LeftJoin((refpr, ver, param) => ver.RecipeCode == param.RecipeCode && ver.Version == param.Version) .Where((refpr, ver, param) => refpr.FkFlowCode == FlowCode && refpr.FkRoutingCode == RoutingCode && refpr.FkOperationCode == operationCode) .Select((refpr, ver, param) => new PfRecipeParametersDto { Id = param.Id, RecipeCode = param.RecipeCode, Version = param.Version, ParamName = param.ParamName, Unit = param.Unit, UpperLimit = param.UpperLimit, LowerLimit = param.LowerLimit, StandardValue = param.StandardValue, Remark = param.Remark }).ToList(); var data = new { flowbase = new { routingCode = RoutingCode, operationCode = operationCode, flowCode = FlowCode }, flowRuleList }; return System.Text.Json.JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true }); } /// /// 普通出站流程 /// /// /// /// [RIZOFlow(FlowType = "common_outbound_flow")] public OutStationApplyResult CommonOutboundStationFlow(string operationCode, string processCode) { // 参数验证 if (string.IsNullOrWhiteSpace(operationCode) || string.IsNullOrWhiteSpace(processCode)) { return OutStationApplyResult.InvalidParameters; } // 1.获取产品是正常件,完成件,返工件 ProductLifecycle productInfo = Context.Queryable() .Where(p => p.ProductSN == processCode) .First(); if (productInfo == null) { // 产品未开工,不得出站 RecordOutTrace(productInfo, operationCode, 1, ApplyStatusEnum.REJECTED, OutStationApplyResult.ProductNotStartWork.ToString(), "产品未开工,不得入站"); return OutStationApplyResult.ProductNotStartWork; } if (productInfo.ProductStatus == 2) { // 产品已经生产完成,不得出站 RecordOutTrace(productInfo, operationCode, 1, ApplyStatusEnum.REJECTED, OutStationApplyResult.ProductCompleted.ToString(), "产品已经生产完成,不得入站"); return OutStationApplyResult.ProductCompleted; } if (productInfo.ProductStatus == 3) { // 返工件允许出站 RecordOutTrace(productInfo, operationCode, 1, ApplyStatusEnum.SUCCESS, OutStationApplyResult.Success.ToString(), string.Empty); return OutStationApplyResult.Success; } //检查扫码流程是否已经完成 var ScanResults = Context.Queryable() .LeftJoin((f, r) => f.FkFlowCode == r.FlowCode && f.FkRoutingCode == r.Routingcode && f.FkOperationCode == r.OperationCode) .Where((f, r) => f.FkRoutingCode == productInfo.RoutingCode) .Where((f, r) => f.FkOperationCode == operationCode) .Select((f, r) => new { f.FkFlowCode, r.ScanResult }) .ToList(); bool isFinish= ScanResults.Where(it => it.ScanResult == ScanResultEnum.NG||it.ScanResult==null).Any(); if (isFinish) { RecordOutTrace(productInfo, operationCode, 1, ApplyStatusEnum.REJECTED, OutStationApplyResult.ScanFlowNotCompleted.ToString(), "产品未开工,不得入站"); return OutStationApplyResult.ScanFlowNotCompleted; } //检查数采流程是否已经完成 // 获取产线 string LineCode = Context.Queryable().Where(it => it.Workorder == productInfo.Workorder).Select(it=>it.LineCode).First(); var DataCollectList = Context.Queryable() .LeftJoin((f, p) => f.FkFlowCode == p.FlowCode && f.FkRoutingCode == p.RoutingCode && f.FkOperationCode == p.OperationCode && f.ParameterCode == p.ParameterCode) .Where((f, p) => f.FkRoutingCode == productInfo.RoutingCode&&f.FkOperationCode== operationCode&&f.FkProductlinebodyCode==LineCode) .Select((f, r) => new { f.FkFlowCode, r.Result }) .ToList(); bool isFinish_ = DataCollectList.Where(it => it.Result == 0 || it.Result == null).Any(); if (isFinish_) { RecordOutTrace(productInfo, operationCode, 1, ApplyStatusEnum.REJECTED, OutStationApplyResult.ParmetersCollectNotCompleted.ToString(), "产品未开工,不得入站"); return OutStationApplyResult.ParmetersCollectNotCompleted; } //准许出站 return OutStationApplyResult.Success; } private void RecordOutTrace(ProductLifecycle product, string operationCode, int ProductionLifeStage, ApplyStatusEnum isPass, string rejectReasonCode, string rejectReasonDesc) { // 更新产品状态 if (product != null) { Context.Updateable() .SetColumns(it => new ProductLifecycle { ProductStatus = 1, // 设置为生产中状态 UpdatedTime = DateTime.Now }) .Where(it => it.ProductSN == product.ProductSN) .ExecuteCommand(); } // 构建入站记录 var passstationRecord = new ProductPassstationRecord { Workorder = product?.Workorder, Routingcode = product?.RoutingCode, ProductSN = product?.ProductSN ?? string.Empty, OperationCode = operationCode, ProductionLifeStage = ProductionLifeStage, // 生产中 ApplyType = ApplyTypeEnum.OUT, ApplyStatus = isPass, RejectReasonCode = rejectReasonCode, RejectReasonDesc = rejectReasonDesc, InStationTime = DateTime.Now, CreatedTime = DateTime.Now }; Context.Insertable(passstationRecord).ExecuteCommand(); } } }