430 lines
19 KiB
C#
430 lines
19 KiB
C#
|
|
using DOAN.Model.MES.product;
|
|
using DOAN.Model.MES.recipe;
|
|
using DOAN.Model.MES.recipe.Dto;
|
|
using Infrastructure.Attribute;
|
|
using MDM.Attribute;
|
|
using MDM.Model.Material;
|
|
using MDM.Model.Process;
|
|
using MDM.Models.Flow;
|
|
using MDM.Models.Process;
|
|
using MDM.Models.Session;
|
|
using MDM.Service;
|
|
using NPOI.SS.Formula.Functions;
|
|
using System.Text.Json;
|
|
|
|
|
|
namespace MDM.Services.Flows
|
|
{
|
|
/// <summary>
|
|
/// 普通流程功能函数
|
|
/// </summary>
|
|
// [AppService(ServiceType = typeof(CommonFlowService), ServiceLifetime = LifeTime.Singleton)]
|
|
public class CommonFlowService : BaseService<Object>
|
|
{
|
|
|
|
/// <summary>
|
|
/// 普通入站流程
|
|
/// </summary>
|
|
/// <param name="operationCode">工序代码</param>
|
|
/// <param name="processCode">产品序列号</param>
|
|
/// <returns>入站结果</returns>
|
|
[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<ProductLifecycle>()
|
|
.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<ProductPassstationRecord>()
|
|
.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<ProcessOperation>()
|
|
.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<ProcessOperation>()
|
|
.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<ProductPassstationRecord>()
|
|
.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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// 记录入站操作轨迹
|
|
/// </summary>
|
|
/// <param name="product">产品信息</param>
|
|
/// <param name="operationCode">工序代码</param>
|
|
/// <param name="result">入站结果</param>
|
|
/// <param name="rejectReasonCode">拒绝原因代码</param>
|
|
/// <param name="rejectReasonDesc">拒绝原因描述</param>
|
|
private void RecordTrace(ProductLifecycle product, string operationCode, int ProductionLifeStage, ApplyStatusEnum isPass, string rejectReasonCode, string rejectReasonDesc)
|
|
{
|
|
// 更新产品状态
|
|
if (product != null)
|
|
{
|
|
Context.Updateable<ProductLifecycle>()
|
|
.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<ProcessOperationFlowMaterialParamter> flowRuleList = Context.Queryable<ProcessOperationFlow>().LeftJoin<ProcessOperationFlowMaterialParamter>((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<ProcessOperationWorkstationFlowCollectParameter> flowRuleList = Context.Queryable<ProcessOperationFlow>().LeftJoin<ProcessOperationWorkstationFlowCollectParameter>
|
|
((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<PfRefProductRecipe>()
|
|
.LeftJoin<PfRecipeVersion>((refpr, ver) => refpr.RecipeCode == ver.RecipeCode)
|
|
.LeftJoin<PfRecipeParameters>((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 });
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 普通出站流程
|
|
/// </summary>
|
|
/// <param name="operationCode"></param>
|
|
/// <param name="processCode"></param>
|
|
/// <returns></returns>
|
|
[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<ProductLifecycle>()
|
|
.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<ProcessOperationFlowMaterialParamter>()
|
|
.LeftJoin<ProductScanRecords>((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<ProWorkorder>().Where(it => it.Workorder == productInfo.Workorder).Select(it=>it.LineCode).First();
|
|
|
|
var DataCollectList = Context.Queryable<ProcessOperationWorkstationFlowCollectParameter>()
|
|
.LeftJoin<ProductProcessParameters>((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<ProductLifecycle>()
|
|
.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();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
}
|