using HH.WMS.Entitys;
using HH.WMS.Entitys.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using HH.WMS.Entitys.Basic;
using System.Threading;
using HH.WMS.Common;
using HH.WMS.BLL;
using HH.WMS.BLL.CoreServer;
using HH.WMS.Entitys.Sys;
using HH.WMS.BLL.OutStock;
using HH.WMS.BLL.Algorithm;
using HH.WMS.Common.Algorithm;
using HH.WMS.Common.Algorithm.Out;
using HH.WMS.BLL.Common;
namespace HH.WMS.CoreServer.Service
{
public class WaveService
{
#region 线程
//内销线程
public Thread thNxCreateWave = null;
//外销线程
public Thread thWxCreateWave = null;
//执行分拣单线程
public Thread thExecuteSorting = null;
//执行分拣出,盘点出的任务
public Thread thExecuteTask = null;
#endregion
#region 开始
///
/// 开始
///
public void Start()
{
#region 执行分拣单
//执行分拣单
thExecuteSorting = thExecuteSorting ?? new Thread(() =>
{
DoRepeatAction(ExecuteSorting);
});
thExecuteSorting.IsBackground = true;
thExecuteSorting.Start();
#endregion
#region 执行任务
//执行任务
thExecuteTask = thExecuteTask ?? new Thread(() =>
{
DoRepeatAction(ExecuteTask);
});
thExecuteTask.IsBackground = true;
thExecuteTask.Start();
#endregion
}
#endregion
#region 重复执行一个action
///
/// 重复执行一个action
///
///
private void DoRepeatAction(Func func)
{
while (true)
{
try
{
var result = func();
if (!result.Success)
{
Log.Info("error", result.Msg);
}
}
catch (Exception ex)
{
Log.Info("error", ex.Message);
}
finally
{
//每次执行完休眠2秒钟
Thread.Sleep(2000);
}
}
}
#endregion
#region 执行分拣单,生成分拣明细
///
/// 执行分拣单,生成分拣明细
///
///
public OperateResult ExecuteSorting()
{
//获取待分拣分拣单
var staySortings = BLLCreator.CreateDapper().GetTopList(5, new
{
CN_S_STATE = Constants.Sorting_Stay
});
//分拣单子表
var staySortingDtl = new List();
if (staySortings.Any())
{
//获取分拣单子表
staySortingDtl = BLLCreator.CreateDapper().GetList(new
{
CN_S_SORTING_NO = staySortings.Select(s => s.CN_S_SORTING_NO).ToList()
});
}
//逐个执行,单个失败不会return
foreach (var staySorting in staySortings)
{
staySorting.SortingDtlList = staySortingDtl.FindAll(f => f.CN_S_SORTING_NO == staySorting.CN_S_SORTING_NO);
//调用算法获取分拣明细
var sortingLocationResult = GetSortingLocation(staySorting);
if (!sortingLocationResult.Success)
{
//消息
Log.Info("分拣单获取分拣明细失败:", JsonConvert.SerializeObject(sortingLocationResult));
continue;
}
//分拣明细
var sortingLocations = sortingLocationResult.GetData>();
staySorting.SortingLocationList.AddRange(sortingLocations);
var currentArea = BLLCreator.Create().GetArea(staySorting.CN_S_STOCK_AREA);
//自动库时生成任务
if (currentArea.CN_C_IS_AUTO == Constants.Y)
{
//生成任务
List endAreas = new List();
var outTaskResult = GetOutTask(staySorting, ref endAreas);
if (!outTaskResult.Success)
{
Log.Info("分拣单生成出库任务失败:", JsonConvert.SerializeObject(outTaskResult));
continue;
}
var tasks = outTaskResult.GetData>();
staySorting.Tasks = tasks;
staySorting.EndBits = endAreas;
}
var executeResult = BLLCreator.Create().ExecuteSorting(staySorting);
if (!executeResult.Success)
{
//消息
Log.Info("执行分拣executeResult失败:", JsonConvert.SerializeObject(executeResult));
continue;
}
}
return OperateResult.Succeed();
}
#endregion
#region 执行任务
///
/// 执行任务
///
///
public OperateResult ExecuteTask()
{
var noExecuteTask = BLLCreator.CreateDapper().GetList(new
{
CN_B_SENDAMS = false,
CN_S_TASK_TYPE = new List() { Constants.TaskType_SortingOut, Constants.TaskType_CheckOut },
}).OrderBy(o=>o.CN_T_CREATE);
foreach (var task in noExecuteTask)
{
//需要调作业区入库算法,算出货位给出库任务
var inAssignEntity = new InAssignEntity
{
objectType = InAssignEntity.ObjectType.托盘,
objectCode = task.CN_S_TRAY_CODE,
lockLocation = false,
lstAreaPrior = new List()
{
{
new areaPriorClass{
areaCode = task.CN_S_END_AREA,
Prior = 1
}
}
}
};
Log.Info("ExecuteTask调用算法InAssign参数", JsonConvert.SerializeObject(inAssignEntity));
InAssignResultEntity inAssignResultEntity = BLLCreator.Create().InAssign(inAssignEntity);
Log.Info("ExecuteTask调用算法InAssign结果", JsonConvert.SerializeObject(inAssignResultEntity));
if (!inAssignResultEntity.Success) continue;
//当前分拣单库区
task.EndAreaEntity = BLLCreator.Create().GetArea(task.CN_S_END_AREA);
task.CN_S_END_BIT = inAssignResultEntity.locationCode;
var executeTaskResult = BLLCreator.Create().ExecuteTask(task);
if (!executeTaskResult.Success)
Log.Info("executeTaskResult Msg", executeTaskResult.Msg);
}
return OperateResult.Succeed();
}
#endregion
#region 获取任务
///
/// 获取任务
///
///
///
///
public OperateResult GetOutTask(TN_WM_SORTING_LISTEntity sortingEntity, ref List endAreas)
{
try
{
//当前分拣单库区
var currentArea = BLLCreator.Create().GetArea(sortingEntity.CN_S_STOCK_AREA);
if (currentArea == null)
return OperateResult.Error("未找到库区:" + sortingEntity.CN_S_STOCK_AREA);
//托盘货位分组
var trayGroup = sortingEntity.SortingLocationList.GroupBy(g => new
{
g.CN_S_SORTING_NO,
g.CN_S_TRAY_CODE,
g.CN_S_LOCATION_CODE
}).Select(s => new
{
s.Key.CN_S_SORTING_NO,
s.Key.CN_S_TRAY_CODE,
s.Key.CN_S_LOCATION_CODE,
CN_F_QUANTITY = s.Sum(m => m.CN_F_QUANTITY)
});
//整托托盘
List fullTrayCode = new List();
//托盘区的需要考虑整托
if (currentArea.CN_S_AREA_NAME == Constants.TrayArea)
{
//托盘数量汇总
var trayQtyGroup = trayGroup.GroupBy(g => g.CN_S_TRAY_CODE).Select(s => new
{
CN_S_TRAY_CODE = s.Key,
CN_F_QUANTITY = s.Sum(m => m.CN_F_QUANTITY)
});
//所有托盘物料关联明细
var trayItems = BLLCreator.CreateDapper().GetList(new
{
CN_S_TRAY_CODE = trayQtyGroup.Select(s => s.CN_S_TRAY_CODE).ToList()
});
//比较算法返回的托盘物料数量与明细数量是否相等(整托)
foreach (var tray in trayQtyGroup)
{
//整托
if (tray.CN_F_QUANTITY ==
trayItems.Where(s => s.CN_S_TRAY_CODE == tray.CN_S_TRAY_CODE)
.Sum(m => m.CN_F_QUANTITY))
{
fullTrayCode.Add(tray.CN_S_TRAY_CODE);
}
}
}
List taskList = new List();
//存在非整托货位托盘
var pickTrays = trayGroup.Where(s => !fullTrayCode.Contains(s.CN_S_TRAY_CODE))
.Select(e => new TN_WM_SORTING_LOCATIONEntity()
{
CN_S_SORTING_NO = e.CN_S_SORTING_NO,
CN_S_TRAY_CODE = e.CN_S_TRAY_CODE,
CN_S_LOCATION_CODE = e.CN_S_LOCATION_CODE,
}).ToList();
if (pickTrays.Any())
{
//非整托任务
WorkflowEntity workflowEntity = new WorkflowEntity(Constants.Workflow_Out)
{
CirObj = Constants.Tray,
StartArea = currentArea.CN_S_AREA_CODE,
ReturnList = true
};
//找站点 GetWorkPosition
var trayWorkflow = BLLCreator.Create().GetWorkPosition(workflowEntity);
if (!trayWorkflow.Success) return trayWorkflow;
var workAreaPro = trayWorkflow.GetData>();
//分拣出库任务
var pickTasks = GetTaskEntity(workAreaPro[0], pickTrays);
endAreas.AddRange(workAreaPro.Select(s => s.CN_S_END_AREA_CODE).ToList());
taskList.AddRange(pickTasks);
}
//存在非整托货位托盘
var fullTrays = trayGroup.Where(s => fullTrayCode.Contains(s.CN_S_TRAY_CODE))
.Select(e => new TN_WM_SORTING_LOCATIONEntity()
{
CN_S_SORTING_NO = e.CN_S_SORTING_NO,
CN_S_TRAY_CODE = e.CN_S_TRAY_CODE,
CN_S_LOCATION_CODE = e.CN_S_LOCATION_CODE,
}).ToList();
if (fullTrays.Any())
{
//整托任务
WorkflowEntity workflowEntity = new WorkflowEntity(Constants.Workflow_Out)
{
CirObj = Constants.Tray,
StartArea = currentArea.CN_S_AREA_CODE,
IsFullTray = Constants.Y,
};
//找站点 GetWorkPosition
var trayWorkflow = BLLCreator.Create().GetWorkPosition(workflowEntity);
if (!trayWorkflow.Success) return trayWorkflow;
var workAreaPro = trayWorkflow.GetData();
//需要调作业区入库算法,算出货位给出库任务
var inAssignEntity = new InAssignEntity
{
objectType = InAssignEntity.ObjectType.托盘,
objectCode = fullTrays[0].CN_S_TRAY_CODE,
lockLocation = false,
lstAreaPrior = new List()
{
{
new areaPriorClass{
areaCode = workAreaPro.CN_S_END_AREA_CODE,
Prior = 1
}
}
}
};
Log.Info("调用算法InAssign参数", JsonConvert.SerializeObject(inAssignEntity));
InAssignResultEntity inAssignResultEntity = BLLCreator.Create().InAssign(inAssignEntity);
Log.Info("调用算法InAssign结果", JsonConvert.SerializeObject(inAssignResultEntity));
if (!inAssignResultEntity.Success) return OperateResult.Error(inAssignResultEntity.Msg);
//整托出库任务
var fullTasks = GetTaskEntity(workAreaPro, pickTrays, inAssignResultEntity.locationCode);
taskList.AddRange(fullTasks);
}
return OperateResult.Succeed(null, taskList);
}
catch (Exception ex)
{
return OperateResult.Error(ex.Message);
}
}
#endregion
#region 获取任务实体
///
/// 获取任务实体
///
///
///
///
private List GetTaskEntity(TN_WM_WORK_AREA_PROEntity workArea, List sortingLocations, string endBit = "")
{
var trayLocationGroup = sortingLocations.GroupBy(g => new
{
g.CN_S_TRAY_CODE,
g.CN_S_LOCATION_CODE,
g.CN_S_SORTING_NO
}).Select(s => new
{
s.Key.CN_S_TRAY_CODE,
s.Key.CN_S_LOCATION_CODE,
s.Key.CN_S_SORTING_NO
});
List taskList = new List();
foreach (var task in trayLocationGroup)
{
string postData = "{\"appCode\":\"" + Constants.appCode + "\",\"ruleName\":\"" + Constants.Rule_TaskNo + "\",\"orgId\":\"\",\"orgFlag\":\"\"}";
string taskNo = WebApiManager.HttpAutoBom_Post("api/BillRule/GenBillNo", postData);
TN_WM_TASKEntity taskEntity = new TN_WM_TASKEntity()
{
CN_S_TASK_NO = taskNo,
CN_S_TASK_TYPE = Constants.TaskType_SortingOut,
CN_S_FROM_OP = Constants.Out,
CN_S_FROM_NO = task.CN_S_SORTING_NO,
CN_S_TRAY_CODE = task.CN_S_TRAY_CODE,
CN_S_STOCK_CODE = "",
CN_S_START_AREA = workArea.CN_S_START_AREA_CODE,
CN_S_START_BIT = task.CN_S_LOCATION_CODE,
CN_S_END_AREA = workArea.CN_S_END_AREA_CODE,
CN_S_END_BIT = endBit,
CN_S_STATE = Constants.TaskState_NoExecuted,
CN_T_CREATE = DateTime.Now,
CN_T_MODIFY = DateTime.Now,
EndAreaEntity = BLLCreator.Create().GetArea(workArea.CN_S_END_AREA_CODE)
};
taskList.Add(taskEntity);
}
return taskList;
}
#endregion
#region 是否在上班时间
///
/// 是否在上班时间
///
///
private WaveConfig WaveConfig()
{
//没加仓库条件
var waveStrategyValues = BLLCreator.CreateDapper().GetList(new
{
CN_S_CODE = new List
{
Constants.Strategy_StartTime,
Constants.Strategy_EndTime,
Constants.Strategy_SeveralMaxCreateWave,
Constants.Strategy_LessMinute
}
});
WaveConfig waveConfig = new WaveConfig();
//上班时间
var startTime = waveStrategyValues.Find(f => f.CN_S_CODE == Constants.Strategy_StartTime);
string _startTime = startTime != null ? startTime.CN_S_VALUE : Constants.WaveDefault_StartTime;
_startTime = string.IsNullOrEmpty(_startTime) ? Constants.WaveDefault_StartTime : _startTime;
waveConfig.StartTime = DateTime.Parse(_startTime);
//下班时间
var endTime = waveStrategyValues.Find(f => f.CN_S_CODE == Constants.Strategy_EndTime);
string _endTime = endTime != null ? endTime.CN_S_VALUE : Constants.WaveDefault_EndTime;
_endTime = string.IsNullOrEmpty(_endTime) ? Constants.WaveDefault_EndTime : _endTime;
waveConfig.EndTime = DateTime.Parse(_endTime);
//内销几单一波
var severalMaxCreateWave = waveStrategyValues.Find(f => f.CN_S_CODE == Constants.Strategy_SeveralMaxCreateWave);
string _severalMaxCreateWave = severalMaxCreateWave != null ? severalMaxCreateWave.CN_S_VALUE : Constants.WaveDefault_SeveralMaxCreateWave;
_severalMaxCreateWave = string.IsNullOrEmpty(_severalMaxCreateWave) ? Constants.WaveDefault_SeveralMaxCreateWave : _severalMaxCreateWave;
waveConfig.SeveralMaxCreateWave = int.Parse(_severalMaxCreateWave);
//内销几分钟后生成
var lessMinute = waveStrategyValues.Find(f => f.CN_S_CODE == Constants.Strategy_LessMinute);
string _lessMinute = lessMinute != null ? lessMinute.CN_S_VALUE : Constants.WaveDefault_LessMinute;
_lessMinute = string.IsNullOrEmpty(_lessMinute) ? Constants.WaveDefault_LessMinute : _lessMinute;
waveConfig.LessMinute = int.Parse(_lessMinute);
//result
return waveConfig;
}
#endregion
#region 是否在上班时间
///
/// 是否在上班时间
///
///
///
private bool IsWorkTime(WaveConfig waveConfig)
{
try
{
TimeSpan dspWorkingDayAM = waveConfig.StartTime.TimeOfDay;
TimeSpan dspWorkingDayPM = waveConfig.EndTime.TimeOfDay;
TimeSpan dspNow = DateTime.Now.TimeOfDay;
if (dspNow >= dspWorkingDayAM && dspNow <= dspWorkingDayPM)
{
return true;
}
return false;
}
catch
{
return false;
}
}
#endregion
#region 创建波次分拣单
///
/// 创建波次分拣单
///
///
/// 是否内销
///
public OperateResult WaveCreate(List outList)
{
//登陆信息&生成单号
UserRuleEntity user = new UserRuleEntity()
{
RuleCode = Constants.Rule_WaveNo
};
//生成波次号
string waveNo = user.GenerateNo();
return ChangeOutOperate(outList, (outMstList, batchesList, stockList, lstStrate) =>
{
//批分分配量
var bResult = stockList.BatchesStockAllocQty(batchesList, lstStrate);
if (!bResult.Success)
return bResult;
//批分结果数据
var batchesResult = bResult.GetData();
if (batchesResult == null)
return OperateResult.Error("生成打单数据异常");
//算库区
OperateResult outAreaResult = OutArea(batchesResult.OutMstList);
if (!outAreaResult.Success) return outAreaResult;
//算法库区返回结果
var algorResultEntity = outAreaResult.GetData();
Log.Info("WaveCreate 调用OutArea返回值algorResultEntity", JsonConvert.SerializeObject(algorResultEntity));
//算法库区返回结果
if (!algorResultEntity.Success)
return OperateResult.Error("算法异常:" + algorResultEntity.Msg);
//算法结果
var algorResult = algorResultEntity.itemOutAreaResult;
//算法结果
if (algorResult == null)
return OperateResult.Error("库存不足,请先完成来料区的上架");
//获取分拣单数据
var sortingDataResult = GetSortingData(algorResult, user, waveNo);
if (!sortingDataResult.Success)
return sortingDataResult;
//生成的分拣单数据
var sortingList = sortingDataResult.GetData>();
List itemCodes = new List();
sortingList.ForEach(x =>
{
if (x.SortingDtlList != null)
x.SortingDtlList.ForEach(y =>
{
itemCodes.Add(y.CN_S_ITEM_CODE);
});
});
//分拣单的所有库区量表数据
var stockAreaList = BLLCreator.Create>().GetList(new
{
CN_S_STOCK_AREA = sortingList.Select(x => x.CN_S_STOCK_AREA).ToList(),
CN_S_ITEM_CODE = itemCodes
});
Log.Info("批分库区参数 sortingList:", JsonConvert.SerializeObject(sortingList));
Log.Info("批分库区参数 lstStrate:", JsonConvert.SerializeObject(lstStrate));
//批分库区量表
var batchesAreaResult = stockAreaList.BatchesAreaQty(sortingList, lstStrate);
if (!batchesAreaResult.Success)
return batchesAreaResult;
Log.Info("批分库区结果 batchesAreaResult:", JsonConvert.SerializeObject(batchesAreaResult));
//波次实体
batchesResult.WaveMst = GetWaveEntity(batchesResult, waveNo);
if (batchesResult.ShortageOutList.Any())
{
//新的发货单赋值波次号
batchesResult.ShortageOutList.ForEach(f =>
{
if (f.CN_S_STATE != Constants.State_Shortage)
f.CN_S_WAVE_CODE = batchesResult.WaveMst.CN_S_WAVE_NO;
});
}
//分拣单实体
batchesResult.SortingList = sortingList;
//库区量表实体
batchesResult.StockAreaList = stockAreaList;
//创建波次分拣单
return BLLCreator.Create().WaveCreate(batchesResult);
});
}
#endregion
#region 获取分拣单数据
///
/// 获取分拣单数据
///
///
///
///
///
public OperateResult GetSortingData(List outAreaResultList, UserRuleEntity user, string waveNo)
{
try
{
//分拣单
List sortingList = new List();
//分拣单组别
user.RuleCode = Constants.SortingGroup;
string sortingGroup = user.GenerateNo();
//分拣单号
user.RuleCode = Constants.SortingNo;
int sortingIndex = 1;
IEnumerable> igOutAreaResult = outAreaResultList.GroupBy(x => new { x.stockCode, x.areaCode });
foreach (var _igOutAreaResult in igOutAreaResult)
{
//分拣单
TN_WM_SORTING_LISTEntity sortingEntity = new TN_WM_SORTING_LISTEntity()
{
CN_GUID = Guid.NewGuid().ToString(),
CN_S_SORTING_NO = waveNo + "-" + sortingIndex++,
CN_S_OP_FROM = Constants.Rule_WaveNo,
CN_S_FROM_NO = waveNo,
CN_T_OPERATE = DateTime.Now.ToString(),// "", //丢里咯木
CN_S_STOCK_CODE = _igOutAreaResult.Key.stockCode,
CN_S_STOCK_AREA = _igOutAreaResult.Key.areaCode,
CN_S_STATE = Constants.Sorting_Stay,
CN_S_SEEDING_MODE = "",
CN_S_GROUP = sortingGroup,
CN_S_CREATOR = user.LoginCode,
CN_S_CREATOR_BY = user.LoginName,
CN_T_CREATE = DateTime.Now,
CN_S_MODIFY = user.LoginCode,
CN_S_MODIFY_BY = user.LoginName,
CN_T_MODIFY = DateTime.Now
};
//分拣单子表行索引
int sortingDtlindex = 1;
//分拣单子表
sortingEntity.SortingDtlList = new List();
//分拣明细
sortingEntity.SortingLocationList = new List();
foreach (var outArea in _igOutAreaResult.AsEnumerable())
{
foreach (var d in outArea.lstItem)
{
//物料详细
AutoBomItemEntity item = BLLCreator.Create().GetItemEntity(d.itemCode) ?? new AutoBomItemEntity();
//分拣单子行
TN_WM_SORTING_DTLEntity sortingDtlEntity = new TN_WM_SORTING_DTLEntity()
{
CN_GUID = Guid.NewGuid().ToString(),
CN_S_SORTING_NO = sortingEntity.CN_S_SORTING_NO,
CN_N_ROW_NO = sortingDtlindex++,
CN_F_QUANTITY = d.itemQty,
CN_S_ITEM_CODE = d.itemCode,
CN_S_ITEM_NAME = item.CN_S_ITEM_NAME,
CN_S_STATE = Constants.Sorting_Stay,
CN_S_LOT_NO = outArea.batchCode,
CN_S_PRODUCTION_BATCH = outArea.prodBatchCode,
CN_S_ITEM_STATE = outArea.itemState,
CN_S_OWNER = outArea.ownerName,
CN_S_MODEL = item.CN_S_MODEL,
CN_S_FIGURE_NO = item.CN_S_FIGURE_NO,
CN_S_MEASURE_UNIT = item.CN_S_MEASURE_UNIT
};
sortingEntity.SortingDtlList.Add(sortingDtlEntity);
}
}
sortingList.Add(sortingEntity);
}
return OperateResult.Succeed(null, sortingList);
}
catch (Exception ex)
{
return OperateResult.Error(ex.Message);
}
}
#endregion
#region 获取波次实体
///
/// 获取波次实体
///
///
///
private TN_WM_WAVE_MSTEntity GetWaveEntity(BatchesResult bResult, string waveNo)
{
TN_WM_WAVE_MSTEntity waveMstEntity = new TN_WM_WAVE_MSTEntity()
{
CN_S_CREATE_TYPE = Constants.CreateType_Manual,
CN_S_WAVE_NO = waveNo,
CN_S_FROM = "WMS",
CN_GUID = Guid.NewGuid().ToString(),
CN_S_STATE = Constants.Sorting_Stay,
CN_T_CREATE = DateTime.Now,
CN_T_MODIFY = DateTime.Now,
CN_T_OPERATE = DateTime.Now,
CN_S_CREATOR = "自动",
CN_S_CREATOR_BY = "auto",
CN_S_MODIFY = "自动",
CN_S_MODIFY_BY = "auto",
CN_C_NEED_SEEDING = Constants.Y,
CN_S_STATUS = Constants.State_New,
CN_S_SEEDING_MODE = "",
CN_S_STOCK_CODE = bResult.OutMstList[0].CN_S_STOCK_CODE
};
waveMstEntity.WaveDtlList = new List();
int index = 1;
foreach (var outDtl in bResult.OutMstList)
{
TN_WM_WAVE_DTLEntity waveDtlEntity = new TN_WM_WAVE_DTLEntity()
{
CN_GUID = Guid.NewGuid().ToString(),
CN_S_WAVE_NO = waveNo,
CN_S_ORDER_NO = outDtl.CN_S_OP_NO,
CN_S_STATE = Constants.State_New,
CN_T_CREATE = DateTime.Now,
CN_T_MODIFY = DateTime.Now,
CN_S_CREATOR = "自动",
CN_S_CREATOR_BY = "auto",
CN_S_MODIFY = "自动",
CN_S_MODIFY_BY = "auto",
CN_S_MSTGUID = waveMstEntity.CN_GUID,
CN_N_ORDER = index++
};
waveMstEntity.WaveDtlList.Add(waveDtlEntity);
}
return waveMstEntity;
}
#endregion
#region 获取分拣明细
///
///获取分拣明细
///
///
///
///
private OperateResult GetSortingLocation(TN_WM_SORTING_LISTEntity sortingEntity)
{
try
{
//所有库区
var allAreas = BLLCreator.Create().GetArea();
//所有自动库区
var autoAreas = allAreas.FindAll(f => f.CN_C_IS_AUTO == Constants.Y);
//当前库区
var currentArea = allAreas.Find(f => f.CN_S_AREA_CODE == sortingEntity.CN_S_STOCK_AREA);
if (currentArea == null)
{
//未找到库区
string notFoundArea = "分拣单:{0}的库区:{1}在Mongo中未找到";
notFoundArea = string.Format(notFoundArea,
sortingEntity.CN_S_SORTING_NO,
sortingEntity.CN_S_STOCK_AREA);
return OperateResult.Error(notFoundArea);
}
//自动库分拣处理
if (currentArea.CN_C_IS_AUTO == Constants.Y)
{
if (currentArea.CN_S_CURRENT_MODE != Constants.CurrentMode_Out)
{
//当前库区不为出库模式,不允许生成明细
string notOutMode = "库区:{0}的模式为:{1},不允许执行分拣,请切换到:{2}";
notOutMode = string.Format(notOutMode,
currentArea.CN_S_AREA_CODE,
currentArea.CN_S_CURRENT_MODE,
Constants.CurrentMode_Out);
return OperateResult.Error(notOutMode);
}
// if (currentArea.CN_N_PICK_MAX > 0)
if(true)
{
//当前库区分拣中的分拣单
var beingSorting = BLLCreator.CreateDapper().GetList(new
{
CN_S_STOCK_AREA = sortingEntity.CN_S_STOCK_AREA,
CN_S_STATE = Constants.Sorting_Being
});
//当前库区分拣中的分拣单数达到最大数
//if (beingSorting.Count >= currentArea.CN_N_PICK_MAX)
if (beingSorting.Count >=0)
{
//错误消息
string pickMaxError = "库区:{0}中正在分拣的分拣单数已达到可同时分拣的最大数:{1},请先分拣:{2}";
//pickMaxError = string.Format(pickMaxError, sortingEntity.CN_S_STOCK_AREA,
// currentArea.CN_N_PICK_MAX,
// string.Join(",", beingSorting.Select(s => s.CN_S_SORTING_NO))
// );
return OperateResult.Error(pickMaxError);
}
}
//调算法获取明细
return AlgorithmLocation(sortingEntity);
}
else
{
//收货区和暂存区
if (currentArea.CN_S_AREA_CLASS == Constants.ReceivingArea || currentArea.CN_S_AREA_CLASS == Constants.TempStorageArea)
{
return OperateResult.Error("收货区和暂存区的分拣明细待开发");
}
else//大件和平库的处理
{
return OperateResult.Error("大件和平库的分拣明细待开发");
}
}
}
catch (Exception ex)
{
return OperateResult.Error(ex.Message);
}
}
#endregion
#region 算法获取明细
///
/// 算法获取明细
///
///
///
private OperateResult AlgorithmLocation(TN_WM_SORTING_LISTEntity sortingEntity)
{
try
{
//分拣明细
List sortingLocationList = new List();
//调算法算货位
OperateResult outNewResult = OutNew(sortingEntity);
if (!outNewResult.Success) return outNewResult;
//算法结果
var outResult = outNewResult.GetData();
//算法结果
if (outResult.lstItemNotEnough.Any())
{
outResult.lstItemNotEnough.ForEach(x =>
{
var currentNotEnough = sortingEntity.SortingDtlList.Find(s => s.CN_S_ITEM_CODE.Equals(x.itemCode));
if (currentNotEnough != null)
x.itemName = currentNotEnough.CN_S_ITEM_NAME;
});
return OperateResult.Warning("物料:" + string.Join(";", outResult.lstItemNotEnough.Select(x => x.itemCode)) + "库存不足,请先完成来料区的上架", outResult.lstItemNotEnough);
}
if (!outResult.Success)
return OperateResult.Error("算法异常:" + outResult.Msg);
if (sortingEntity.SortingDtlList.Sum(x => x.CN_F_QUANTITY) != Convert.ToDecimal(outResult.itemLocations.Sum(x => x.itemQty)))
{
return OperateResult.Error("算法异常:返回的物料信息不完整!");
}
var locations = outResult.itemLocations.Select(m =>
{
AutoBomItemEntity mm = BLLCreator.Create().GetItemEntity(m.itemCode) ?? new AutoBomItemEntity();
return new TN_WM_SORTING_LOCATIONEntity()
{
CN_GUID = Guid.NewGuid().ToString(),
CN_S_LOT_NO = m.batchCode,
CN_S_ITEM_STATE = m.itemState,
CN_S_OWNER = m.ownerName,
CN_F_QUANTITY = m.itemQty,
CN_F_PICKED_QTY = 0,
CN_S_ITEM_CODE = m.itemCode,
CN_S_LOCATION_CODE = m.locationCode,
CN_S_TRAY_CODE = m.trayCode,
CN_S_TRAY_GRID = m.trayGrid,
CN_S_SORTING_NO = sortingEntity.CN_S_SORTING_NO,
CN_S_STATE = sortingEntity.CN_S_STATE,
CN_S_ORDER_NO = "",
CN_S_CREATOR = "自动",
CN_S_CREATOR_BY = "auto",
CN_S_ITEM_NAME = mm.CN_S_ITEM_NAME,
CN_S_MODEL = mm.CN_S_MODEL,
CN_S_FIGURE_NO = mm.CN_S_FIGURE_NO,
CN_S_MEASURE_UNIT = mm.CN_S_MEASURE_UNIT,
CN_S_PACKING_UNIT = m.packUnit,
CN_F_PACKING_QTY = m.packQty,
CN_S_PRODUCTION_BATCH = m.prodBatchCode,
CN_T_CREATE = DateTime.Now,
CN_T_MODIFY = DateTime.Now
};
}).ToList();
sortingLocationList.AddRange(locations);
return OperateResult.Succeed(null, sortingLocationList);
}
catch (Exception ex)
{
return OperateResult.Error(ex.Message);
}
}
#endregion
#region 带出出库订单,批分,仓库实体
///
/// 带出出库订单实体
///
///
///
///
public OperateResult ChangeOutOperate(List outMst, Func, List, List, List, OperateResult> funcOut)
{
try
{
List batchesList = new List();
foreach (var _out in outMst)
{
_out.OutDtlList = BLLCreator.Create>().GetList(new
{
CN_S_OP_NO = _out.CN_S_OP_NO,
CN_C_AUTO_INOUT = false
});
//.FindAll(a =>
//{
// if (_out.CN_S_OUT_TYPE == Constants.OutType_BigOut) return true;
// //物料详细
// AutoBomItemEntity item = BLLCreator.Create().GetItemEntity(a.CN_S_ITEM_CODE);
// if (item == null)
// throw new Exception("autobom中未找到物料:" + a.CN_S_ITEM_CODE);
// if (item.CN_S_STORE_TYPE == Constants.BigArea)
// a.CN_C_BIG = true;
// return true;
//});
batchesList.AddRange(_out.OutDtlList.Select(p =>
{
return new BatchesEntity()
{
ItemCode = p.CN_S_ITEM_CODE,
ItemState = p.CN_S_ITEM_STATE,
ItemArrivalLot = p.CN_S_LOT_CODE,
ItemProductionLot = p.CN_S_PRODUCTION_BATCH,
Owner = _out.CN_S_OWNER,
Qty = p.CN_F_QUANTITY,
OpNo = _out.CN_S_OP_NO,
OutMst = _out,
IsFilter = p.CN_C_AUTO_INOUT
};
}).ToList());
}
//当前子表物料库存
var stockList = BLLCreator.Create>().GetList(new
{
CN_S_ITEM_CODE = batchesList.Select(p => p.ItemCode).ToList()
});
//算法策略
List lstStrate = BLLCreator.Create().GetStrateListByAreaOrStock("", "", Constants.Out)
.OrderByDescending(a => a.CN_N_PRIORITY).Select(o => o.CN_S_CODE).ToList();
return funcOut(outMst, batchesList, stockList, lstStrate);
}
catch (Exception ex)
{
return OperateResult.Error(ex.Message);
}
}
#endregion
#region 算库区
///
/// 算库区
///
///
///
private OperateResult OutArea(List outMstList)
{
try
{
//所有出库物料
var outItemList = new List();
outMstList.ForEach(p =>
{
//子表货主赋值
p.OutDtlList.ForEach(q => q.CN_S_OWNER = p.CN_S_OWNER);
outItemList.AddRange(p.OutDtlList);
});
//初始化调用算法数据
List itemQuerys =
outItemList.GroupBy(p => new
{
p.CN_S_ITEM_CODE,
p.CN_S_ITEM_STATE,
p.CN_S_OWNER,
p.CN_S_LOT_CODE,
p.CN_S_PRODUCTION_BATCH
}).Select(x => new itemQueryClass()
{
itemCode = x.Key.CN_S_ITEM_CODE,
batchCode = x.Key.CN_S_LOT_CODE,
prodBatchCode = x.Key.CN_S_PRODUCTION_BATCH,
itemState = x.Key.CN_S_ITEM_STATE,
ownerName = x.Key.CN_S_OWNER,
stockCode = outMstList[0].CN_S_STOCK_CODE,
itemQty = x.Sum(y => y.CN_F_QUANTITY)
}).ToList();
//初始化调用算法库区
var allArea = BLLCreator.Create().GetArea();
List lstAreaPrior = allArea.Select(p => new areaPriorClass()
{
areaCode = p.CN_S_AREA_CODE,
Prior = p.CN_N_PRIORITY
}).ToList();
Log.Info("调用OutArea参数 itemQuerys", JsonConvert.SerializeObject(itemQuerys));
Log.Info("调用OutArea参数 lstAreaPrior", JsonConvert.SerializeObject(lstAreaPrior));
//调用出库算法
string outAreaParams = JsonConvert.SerializeObject(new
{
itemQuerys = itemQuerys,
lstAreaPrior = lstAreaPrior
});
OutAreaResultAllEntity algorResultEntity = BLLCreator.Create().OutArea(itemQuerys, lstAreaPrior);
Log.Info("algorResultEntity", JsonConvert.SerializeObject(algorResultEntity));
return OperateResult.Succeed(null, algorResultEntity);
}
catch (Exception ex)
{
return OperateResult.Error("WaveService-OutArea:" + ex.Message);
}
}
#endregion
#region 算货位
///
/// 算货位
///
///
///
private OperateResult OutNew(TN_WM_SORTING_LISTEntity sortingEntity)
{
try
{
//初始化调用算法数据
List algorItems = sortingEntity.SortingDtlList.GroupBy(x => new
{
x.CN_S_ITEM_CODE,
x.CN_S_ITEM_STATE,
x.CN_S_OWNER,
x.CN_S_LOT_NO,
x.CN_S_PRODUCTION_BATCH
}).Select(y => new itemQueryClass()
{
stockCode = sortingEntity.CN_S_STOCK_CODE,
areaCode = sortingEntity.CN_S_STOCK_AREA,
itemCode = y.Key.CN_S_ITEM_CODE,
batchCode = y.Key.CN_S_LOT_NO,
prodBatchCode = y.Key.CN_S_PRODUCTION_BATCH,
itemState = y.Key.CN_S_ITEM_STATE,
ownerName = y.Key.CN_S_OWNER,
itemQty = y.Sum(z => z.CN_F_QUANTITY)
}).ToList();
var lstAreaPrior = algorItems.Select(x => new areaPriorClass()
{
areaCode = x.areaCode,
Prior = 1
}).ToList();
OutAlgorEnitty outNewParams = new OutAlgorEnitty
{
lstDevice = new List(),
lstAreaPrior = lstAreaPrior,
lstQueryItem = algorItems,
lockLocation = false
};
Log.Info("调用OutNew参数 outNewParams", JsonConvert.SerializeObject(outNewParams));
OutResultEntityNew outResult = BLLCreator.Create().OutNew(outNewParams);
Log.Info("调用OutNew返回值 outResult", JsonConvert.SerializeObject(outResult));
return OperateResult.Succeed(null, outResult);
}
catch (Exception ex)
{
return OperateResult.Error("WaveService-OutNew:" + ex.Message);
}
}
#endregion
}
#region 波次配置
///
/// 波次配置
///
public class WaveConfig
{
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public int SeveralMaxCreateWave { get; set; }
public int LessMinute { get; set; }
}
#endregion
}