using iWareSql;
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
using iWareSql.DBModel;
|
using XiGang.Core.Model;
|
using iWareSql.DataAccess;
|
using iWareCommon.Common.Globle;
|
using System.Threading;
|
using iWareCommon.Utils;
|
using iWareModel;
|
using iWareCC.Common.Helper;
|
|
namespace iWareCC
|
{
|
/// <summary>
|
/// 出库计划任务分解线程
|
/// </summary>
|
public class OutPlanTaskDecompose
|
{
|
/// <summary>
|
/// 处理【下发中】的出库计划任务
|
/// </summary>
|
public static void HandlerIssuingTask()
|
{
|
var errMsg = "";
|
bool result;
|
while (true)
|
{
|
Thread.Sleep(2000);//休眠2秒
|
try
|
{
|
if (SystemValue.isAllowRuning_HandlerIssuingTask && SystemValue.isStartedModel)
|
{
|
//查询状态=下发中的出库计划
|
var queryState1 = (int)OutPlanStateEnum.下发中;
|
var queryState2 = (int)OutPlanStateEnum.部分下发;
|
List<Plan_OutTask> planList = null;
|
var isAllowDecomposePlanTask = false;
|
using (DbModel context = new DbModel())
|
{
|
planList = context.Plan_OutTask.Where(x => x.PlanState == queryState1 || x.PlanState == queryState2).ToList();
|
if (planList != null && planList.Count > 0)
|
{
|
//屏蔽,这样每次只处理3个,会导致赵通他们板链线ecu刷数据 【EditBy shaocx,2022-08-12】
|
/*
|
//首先验证下是否允许下发
|
isAllowDecomposePlanTask = IsAllowDecomposePlanTask(context, ref errMsg);
|
if (isAllowDecomposePlanTask == false)
|
{
|
SystemWarningMsg._lbl_Alert_HandlerIssuingTask = errMsg;
|
continue;//继续下一个循环
|
}
|
//*/
|
}
|
}
|
if (planList != null && planList.Count > 0)
|
{
|
foreach (var item in planList)
|
{
|
errMsg = "";//重置
|
using (DbModel mycontext = new DbModel())
|
{
|
//建议:一次只执行一个出库计划,只要有一个计划成功创建了任务,该循环就跳出,目的是解决出库计划时若下发5个任务中,若其中4号任务不齐套,在5号及以后出库时4号任务刚好齐套,则将4号任务作为最高优先级插队进行出库 【EditBy shaocx,2022-08-10】
|
result = SingleOutPlanTaskHandler(mycontext, item, ref errMsg);
|
|
Log4NetHelper.WriteInfoLog(LogType.OutPlanTask, "处理【下发中】的出库计划任务=>" + errMsg);
|
SystemWarningMsg._lbl_Alert_HandlerIssuingTask = errMsg + "[处理任务" + item.PlanNo + "]";
|
if (result == true)
|
{
|
break;//跳出循环,直接执行循环的下一个过程 【EditBy shaocx,2022-08-10】
|
}
|
}
|
}
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
SystemWarningMsg._lbl_Alert_HandlerIssuingTask = "出现异常:" + ex.Message;
|
Log4NetHelper.WriteErrorLog(LogType.CCWCFService, "HandlerIssuingTask出现异常:" + ex.Message, ex);
|
}
|
}
|
}
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="context"></param>
|
/// <param name="outTask"></param>
|
/// <param name="errMsg"></param>
|
/// <returns>true:表示已经找到库存,并创建好了任务,false:表示没有找到库存</returns>
|
private static bool SingleOutPlanTaskHandler(DbModel context, Plan_OutTask outTask, ref string errMsg)
|
{
|
bool fun_Result = false;
|
//注意:这里必须重新获取下对象,因为前面的方法中DbModel是不一样的,不是一个上下文,修改不了数据 【EditBy shaocx,2022-07-28】
|
Plan_OutTask new_outTask = context.Plan_OutTask.Where(x => x.Id == outTask.Id).First();
|
errMsg = "";
|
var queryState1 = (int)OutTaskDetailStateEnum.等待中;
|
var queryState2 = (int)OutTaskDetailStateEnum.缺料;
|
var detaiList = context.Plan_OutTaskDetail.Where(x =>
|
(x.OutTaskDetailState == queryState1 || x.OutTaskDetailState == queryState2)
|
&& x.M_PlanId == new_outTask.Id)
|
.OrderBy(x => x.CreateTime)//按照创建时间升序 【EditBy shaocx,2022-08-10】
|
.ThenBy(x => x.PlanSequence)//其次按照顺序升序,主要是给 按照按订货号出库的出库顺序来的 【EditBy shaocx,2024-01-31】
|
.ToList();
|
if (detaiList != null && detaiList.Count > 0)
|
{
|
//建议:一次只执行一次出库任务
|
foreach (var item in detaiList)
|
{
|
var result = SingleOutPlanDetailTaskHandlerForVirtual(context, new_outTask, item, ref errMsg);
|
//var result = false;//暂时先屏蔽读取虚拟库存的数据
|
if (result == false)
|
{//表示没有找到虚拟库存,就再去查 真实库存
|
result = SingleOutPlanDetailTaskHandler(context, new_outTask, item, ref errMsg);
|
if (result == false)
|
{//表示没有找到实际库存
|
|
}
|
else
|
{//表示找到了实际库存,并成功创建了任务
|
fun_Result = true;
|
break;//成功后就跳出循环
|
}
|
}
|
else
|
{//表示找到了虚拟出库,并成功创建了任务
|
fun_Result = true;
|
break;//成功后就跳出循环
|
}
|
}
|
}
|
else
|
{
|
//不予处理
|
}
|
return fun_Result;
|
}
|
|
/// <summary>
|
/// 单个处理出库计划明细-真实库存中处理
|
/// </summary>
|
/// <param name="context"></param>
|
/// <param name="outTask"></param>
|
/// <param name="outDetailTask"></param>
|
/// <param name="errMsg"></param>
|
/// <returns>true:表示已经找到库存,并创建好了任务,false:表示没有找到库存</returns>
|
private static bool SingleOutPlanDetailTaskHandler(DbModel context, Plan_OutTask outTask, Plan_OutTaskDetail outDetailTask, ref string errMsg)
|
{
|
errMsg = "";
|
var remark = "消费下发中的任务";
|
//1、搜索库存是否存在
|
var queliaoReason = "";
|
var findStore = StoreHandler.FindStoreForOutPlan(context, outDetailTask, ref errMsg, ref queliaoReason);
|
if (findStore == null)
|
{//表示查找库存失败
|
//更新Plan_OutTaskDetail表的OperationRemark值
|
var changeOutTaskDetailState = OutTaskDetailStateEnum.缺料;
|
outDetailTask.OutTaskDetailState = (int)changeOutTaskDetailState;
|
outDetailTask.OutTaskDetailStateName = changeOutTaskDetailState.ToString();//更新 状态为缺料 [EditBy shaocx,2022-08-24]
|
outDetailTask.OperationRemark = SysGloble.QUELIAO_STR;
|
|
//赋值缺料原因 【Editby shaocx,2022-10-24】
|
outDetailTask.Remark = MyExtendHelper.GetQueliaoReason(outDetailTask.Remark, queliaoReason);
|
|
outDetailTask.ModifyTime = DateTime.Now;
|
outDetailTask.ModifyBy = SysGloble.WCSSystem;
|
//重要:!提前生成顺序号 [EditBy shaocx,2022-08-24]
|
string taskSequenceGuid = "";
|
outDetailTask.MainTaskSequence = MainTaskHandler.GenerateTaskSequence(context, ref taskSequenceGuid);
|
outDetailTask.TaskSequenceGuid = taskSequenceGuid;
|
|
context.SaveChanges();
|
|
Log4NetHelper.WriteInfoLog(LogType.OutPlanTask, errMsg);
|
return false;
|
}
|
else
|
{//查找到库存
|
|
#region 事务处理
|
string taskSequenceGuid = "";
|
int myTaskSequence = GetLastOutTaskDetailTaskSequenceForQueLiao(context, outDetailTask, ref taskSequenceGuid);
|
using (var trans = context.Database.BeginTransaction())
|
{
|
try
|
{
|
var sourcePlace = StationHandler.GetPlaceByPlaceId(findStore.StationId, context);
|
//2、锁定库存
|
StationHandler.SetPlaceLockStatus(true, SysGloble.WCSSystem, ref sourcePlace, remark);
|
StationHandler.SetPlaceTaskDoingStatus(true, SysGloble.WCSSystem, ref sourcePlace, remark);
|
|
//3、创建出库任务
|
FunRetEntity addOutStoreTaskResult = MainTaskHandler.AddOutStoreTask(outDetailTask, findStore, context, MainTaskTypeEnum.自动出库, new SysUser()
|
{
|
ID = 0,
|
Name = SysGloble.WCSSystem
|
}, sourcePlace, myTaskSequence, taskSequenceGuid);
|
if (addOutStoreTaskResult.result == false)
|
{
|
errMsg = addOutStoreTaskResult.resMsg;
|
throw new Exception(errMsg);
|
}
|
|
//4、更新出库明细表
|
var mainTask = addOutStoreTaskResult.resData as Task_Main;
|
if (mainTask == null)
|
{
|
errMsg = "新建的主任务对象为NULL";
|
throw new Exception(errMsg);
|
}
|
|
outDetailTask.TaskSequenceGuid = mainTask.TaskSequenceGuid;//重要!保存TaskSequenceGuid值 【EditBy shaocx,2022-08-25】
|
|
outDetailTask.OperationRemark = "设备任务已创建";//注意:这里的OperationRemark一定要更新,因为缺料的时候我更新了,缺料的查询也用到了 【EditBy shaocx,2022-04-29】
|
outDetailTask.MainTaskId = mainTask.Id;
|
outDetailTask.MainTaskNo = mainTask.TaskNo;
|
outDetailTask.SerialNumber = findStore.SerialNumber;//保存序列号
|
outDetailTask.OrderNo = findStore.OrderNo;
|
outDetailTask.MaterialId = findStore.MaterialId;//保存物料信息
|
var changeOutTaskDetailState = OutTaskDetailStateEnum.设备任务待执行;
|
PlanOutTaskHandler.UpdateStateForOutTaskDetail(outDetailTask, changeOutTaskDetailState, remark);
|
//5、更新出库主表
|
SetPlanStateForPlan_OutTask(context, outTask, changeOutTaskDetailState, remark);
|
|
//清理之前残留的缺料的信息 【Editby shaocx,2022-10-24】
|
outDetailTask.Remark = MyExtendHelper.CleareQueliaoReason(outDetailTask.Remark);
|
|
////更改任务主表为任务已分解
|
////更新主表的任务状态
|
//var _changeTaskState = MainTaskStatusEnum.出库任务已分解;
|
//mainTask.TaskState = (int)_changeTaskState;
|
//mainTask.TaskStateName = _changeTaskState.ToString();
|
|
//保存数据库
|
context.SaveChanges();
|
|
trans.Commit();
|
return true;//找到了库存,并处理成功了
|
}
|
catch (Exception ex)
|
{
|
trans.Rollback();
|
SystemWarningMsg._lbl_Alert_HandlerIssuingTask = "SingleOutPlanDetailTaskHandler出现异常:" + ex.Message;
|
Log4NetHelper.WriteErrorLog(LogType.CCWCFService, "SingleOutPlanDetailTaskHandler 出现异常:" + ex.Message, ex);
|
throw ex;
|
}
|
}
|
#endregion
|
}
|
}
|
|
|
/// <summary>
|
/// 单个处理出库计划明细-虚拟库存中处理 [Editby shaocx,2022-07-28]
|
/// </summary>
|
/// <param name="context"></param>
|
/// <param name="outTask"></param>
|
/// <param name="outDetailTask"></param>
|
/// <param name="errMsg"></param>
|
/// <returns>true:表示找到虚拟库存,并处理成功了,false表示没有找到虚拟库存</returns>
|
private static bool SingleOutPlanDetailTaskHandlerForVirtual(DbModel context, Plan_OutTask outTask, Plan_OutTaskDetail outDetailTask, ref string errMsg)
|
{
|
errMsg = "";
|
var remark = "消费下发中的任务";
|
//1、搜索库存是否存在
|
var findVirtualStore = StoreHandler.FindStoreForOutPlanByVirtual(context, outDetailTask, ref errMsg);
|
if (findVirtualStore == null)
|
{//表示查找库存失败
|
return false;//表示在虚拟库存中没有找到库存
|
}
|
else
|
{//查找到库存
|
|
#region 事务处理
|
using (var trans = context.Database.BeginTransaction())
|
{
|
try
|
{
|
//1、库存移除
|
context.Wms_VirtualStore.Remove(findVirtualStore);
|
//findVirtualStore.IsDeleted = true;
|
//findVirtualStore.ModifyBy = "";
|
//findVirtualStore.OperationRemark = remark + "[锁定库存]";
|
//findVirtualStore.ModifyTime = DateTime.Now;
|
|
//2、创建虚拟出库任务,注意:任务状态必须是已完成,因为是虚拟出库
|
FunRetEntity addOutStoreTaskResult = MainTaskHandler.AddOutStoreTaskForVirtual(outDetailTask, findVirtualStore, context, MainTaskTypeEnum.自动出库, new SysUser()
|
{
|
ID = 0,
|
Name = SysGloble.WCSSystem
|
});
|
if (addOutStoreTaskResult.result == false)
|
{
|
errMsg = addOutStoreTaskResult.resMsg;
|
throw new Exception(errMsg);
|
}
|
|
//4、更新出库明细表
|
var mainTask = addOutStoreTaskResult.resData as Task_Main;
|
if (mainTask == null)
|
{
|
errMsg = "新建的主任务对象为NULL";
|
throw new Exception(errMsg);
|
}
|
|
outDetailTask.OperationRemark = "设备任务已创建,并完成";//注意:这里的OperationRemark一定要更新,因为缺料的时候我更新了,缺料的查询也用到了 【EditBy shaocx,2022-04-29】
|
outDetailTask.MainTaskId = mainTask.Id;
|
outDetailTask.MainTaskNo = mainTask.TaskNo;
|
outDetailTask.SerialNumber = findVirtualStore.SerialNumber;//保存序列号
|
outDetailTask.OrderNo = findVirtualStore.OrderNo;
|
outDetailTask.MaterialId = findVirtualStore.MaterialId;//保存物料信息
|
var changeOutTaskDetailState = OutTaskDetailStateEnum.完成;//注意:要变成 已完成
|
PlanOutTaskHandler.UpdateStateForOutTaskDetail(outDetailTask, changeOutTaskDetailState, remark);
|
//5、更新出库主表
|
SetPlanStateForPlan_OutTask(context, outTask, changeOutTaskDetailState, remark);
|
|
|
//保存数据库
|
context.SaveChanges();
|
|
trans.Commit();
|
|
return true;
|
}
|
catch (Exception ex)
|
{
|
trans.Rollback();
|
SystemWarningMsg._lbl_Alert_HandlerIssuingTask = "SingleOutPlanDetailTaskHandler出现异常:" + ex.Message;
|
Log4NetHelper.WriteErrorLog(LogType.CCWCFService, "SingleOutPlanDetailTaskHandler 出现异常:" + ex.Message, ex);
|
throw ex;
|
}
|
}
|
|
#endregion
|
}
|
}
|
|
private static void SetPlanStateForPlan_OutTask(DbModel context, Plan_OutTask outTask, OutTaskDetailStateEnum currnetChange, string remark)
|
{
|
//计算数量
|
var queryState1 = (int)OutTaskDetailStateEnum.完成;
|
var queryState2 = (int)OutTaskDetailStateEnum.执行中;
|
var allPlanList = context.Plan_OutTaskDetail.Where(x => x.M_PlanId == outTask.Id).ToList();
|
outTask.Qty = allPlanList.Count;//重新赋值总数量
|
|
var issued_planList = allPlanList.Where(x => x.OutTaskDetailState == queryState1 || x.OutTaskDetailState == queryState2).ToList();
|
int issued_planListCount = issued_planList.Count();
|
|
if (currnetChange == OutTaskDetailStateEnum.完成 || currnetChange == OutTaskDetailStateEnum.执行中)
|
{
|
//计入本次要修改的条数
|
//是否这里不需要+1,待测试 【重要!!!!!】
|
//issued_planListCount += 1;
|
}
|
OutPlanStateEnum changeOutTaskDetailState;
|
if (outTask.Qty <= issued_planListCount)
|
{//更新主表状态为 全部下发
|
|
changeOutTaskDetailState = OutPlanStateEnum.全部下发;
|
PlanOutTaskHandler.UpdateStateForOutTask(outTask, changeOutTaskDetailState, remark);
|
//修改齐套性为已齐套 [EditBy shaocx,2022-05-16]
|
outTask.IsPickFinished = true;
|
//更新计划进度
|
outTask.PlanRate = 100;
|
outTask.Qty_Finish = outTask.Qty;
|
outTask.Qty_NoFinish = 0;
|
}
|
else if (issued_planListCount > 0)
|
{
|
changeOutTaskDetailState = OutPlanStateEnum.部分下发;
|
PlanOutTaskHandler.UpdateStateForOutTask(outTask, changeOutTaskDetailState, remark);
|
//更新计划进度
|
//outTask.PlanRate = (issued_planListCount / allPlanList.Count()) * 100;
|
outTask.PlanRate = CSharpHelper.ExecPercentRetInt(issued_planListCount, outTask.Qty);
|
|
outTask.Qty_Finish = issued_planListCount;
|
outTask.Qty_NoFinish = outTask.Qty - issued_planListCount;
|
}
|
}
|
|
|
/// <summary>
|
/// 是否允许继续分解任务计划 [EditBy shaocx,2022-08-11]
|
/// </summary>
|
/// <param name="context"></param>
|
/// <returns></returns>
|
private static bool IsAllowDecomposePlanTask(DbModel context, ref string errMsg)
|
{
|
var queryState1 = (int)MainTaskStatusEnum.待出库;
|
var queryState2 = (int)MainTaskStatusEnum.出库任务已分解;
|
var queryState3 = (int)MainTaskStatusEnum.出库中;
|
|
var queryMaterialType = (int)MaterialTypeEnum.一般物料;
|
|
var queryInOutFlag = (int)MainInOutFlagEnum.出库;
|
|
|
var mainList = context.Task_Main.Where(x => (x.TaskState == queryState1 || x.TaskState == queryState2 || x.TaskState == queryState3) && x.MaterialType == queryMaterialType
|
&& x.InOutFlag == queryInOutFlag).ToList();
|
|
if (mainList != null && mainList.Count >= 3)
|
{//为什么是3,考虑到 1012+2个出库口都有发动机的情况
|
errMsg = "目前已有" + mainList.Count + "条出库任务未结束,不允许继续分解任务计划";
|
return false;
|
}
|
return true;
|
}
|
|
/// <summary>
|
/// 缺料的数据,插队处理
|
/// </summary>
|
/// <param name="context"></param>
|
/// <param name="planDetail"></param>
|
/// <returns></returns>
|
private static int GetLastOutTaskDetailTaskSequenceForQueLiao(DbModel context, Plan_OutTaskDetail planDetail, ref string taskSequenceGuid)
|
{
|
if (planDetail.OutTaskDetailState == (int)OutTaskDetailStateEnum.缺料)
|
{//如果是缺料的话,就需要 插队处理 【EditBy shaocx,2022-08-24】
|
//首先要判断当前同一个TaskSequenceGuid是否都做完了,如果都做完了,那么他就要排到第一位优先执行,如果还没做完,就按照原先的顺序来。
|
taskSequenceGuid = planDetail.TaskSequenceGuid;
|
bool isNeedChaDui = PlanOutTaskHandler.IsNeedChaDuiCommonTaskSequenceGuid(context, taskSequenceGuid);
|
if (isNeedChaDui)
|
{
|
return 1;//插队处理
|
}
|
return Convert.ToInt32(planDetail.MainTaskSequence);//按照原先的节奏顺序走
|
}
|
return 0;//正常排序
|
}
|
}
|
}
|