using HH.WMS.BLL.Algorithm;
using HH.WMS.BLL.Basic;
using HH.WMS.BLL.Common;
using HH.WMS.BLL.CoreServer;
using HH.WMS.BLL.Interface;
using HH.WMS.BLL.SysMgr;
using HH.WMS.Common;
using HH.WMS.Common.Algorithm;
using HH.WMS.Common.Algorithm.Out;
using HH.WMS.DAL;
using HH.WMS.DAL.Basic;
using HH.WMS.DAL.InStock;
using HH.WMS.DAL.OutStock;
using HH.WMS.Entitys;
using HH.WMS.Entitys.Basic;
using HH.WMS.Entitys.Common;
using HH.WMS.Entitys.Entitys;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WMS.BLL.OutStock
{
public class TN_WM_SORTING_LISTBLL : DapperBaseBLL
{
#region 分拣单列表
///
/// 分拣单列表
///
///
///
public List GetSortings(string key)
{
return CreateDAL().GetSortings(key);
}
#endregion
#region 确认分拣
///
/// 确认分拣
///
///
///
///
public OperateResult ConfirmSorting(bool sortingPicked, bool wavePicked, string waveNo, List sortingResult, string boxNo = "")
{
//分拣单捡完了,根据分拣单获取库区锁定明细
//List outLockDtl = new List();
List areaQtyList = new List();
//算法策略
List lstStrate = BLLCreator.Create().GetStrateListByAreaOrStock("", "", Constants.Out)
.OrderByDescending(a => a.CN_N_PRIORITY).Select(o => o.CN_S_CODE).ToList();
Log.Info("确认分拣", "lstStrate");
Log.Info("确认分拣", JsonConvert.SerializeObject(lstStrate));
if (sortingPicked)
{
Log.Info("确认分拣sortingResult", JsonConvert.SerializeObject(sortingResult));
var currentSorting = CreateDAL>()
.GetSingleEntity(new
{
CN_S_SORTING_NO = sortingResult[0].CN_S_SORTING_NO
});
if (currentSorting != null)
{
var currentSortingDtl = CreateDAL>()
.GetList(new
{
CN_S_SORTING_NO = currentSorting.CN_S_SORTING_NO
});
currentSorting.SortingDtlList = currentSortingDtl;
areaQtyList = CreateDAL>().GetList(new
{
CN_S_ITEM_CODE = currentSortingDtl.Select(x => x.CN_S_ITEM_CODE).ToList()
});
//反批分库区分配量
Log.Info("确认分拣", "BatchesAreaQty");
var result = areaQtyList.BatchesAreaQty(new List() { currentSorting }, lstStrate, true);
Log.Info("确认分拣", JsonConvert.SerializeObject(result));
if (!result.Success)
return result;
}
}
//分拣结果的托盘物料关联数据
var trayItemMstList = CreateDAL>().GetList(new
{
CN_S_TRAY_CODE = sortingResult.Select(x => x.CN_S_TRAY_CODE).ToList(),
CN_S_ITEM_CODE = sortingResult.Select(x => x.CN_S_ITEM_CODE).ToList()
});
foreach (var trayItemMst in trayItemMstList)
{
trayItemMst.TrayItemDtlList = new List();
trayItemMst.UnpackingDtl = new List();
//属于当前托盘,当前物料的分拣明细
var currentSortingResult = sortingResult.Where(x => x.CN_S_ITEM_CODE == trayItemMst.CN_S_ITEM_CODE && x.CN_S_TRAY_CODE == trayItemMst.CN_S_TRAY_CODE);
decimal qty = currentSortingResult.Sum(y => y.CN_F_QUANTITY);
if (trayItemMst.CN_F_QUANTITY >= qty &&
trayItemMst.CN_F_ALLOC_QTY >= qty)
{
trayItemMst.CN_F_QUANTITY -= qty;
trayItemMst.CN_F_ALLOC_QTY -= qty;
Log.Info("确认分拣", "0001");
trayItemMst.TrayItemDtlList = CreateDAL>().GetList(new
{
CN_PARENT_GUID = trayItemMst.CN_GUID
}).OrderBy(x => x.CN_S_LOT_NO).ToList();
Log.Info("确认分拣", "0002");
//空的生产批次放后面
currentSortingResult = currentSortingResult.Select(x => new
{
index = string.IsNullOrEmpty(x.CN_S_PRODUCTION_BATCH) ? 0 : 1,
x
}).OrderByDescending(y => y.index).ThenBy(z => z.x.CN_S_PRODUCTION_BATCH).Select(m => m.x);
Log.Info("确认分拣", "0003");
foreach (string stegy in lstStrate)
{
//逐个策略进行计算
switch (stegy)
{
case "FirstInFirstOut":
trayItemMst.TrayItemDtlList = trayItemMst.TrayItemDtlList.OrderBy(o => o.CN_S_LOT_NO).ToList();
break;
case "FirstWarrantFirstOut":
trayItemMst.TrayItemDtlList = trayItemMst.TrayItemDtlList.Select(x => new
{
index = string.IsNullOrEmpty(x.CN_S_PRODUCTION_BATCH) ? 0 : 1,
x
}).OrderByDescending(y => y.index).ThenBy(z => z.x.CN_S_PRODUCTION_BATCH).Select(m => m.x).ToList();
break;
}
}
Log.Info("确认分拣", "0004");
foreach (var cs in currentSortingResult)
{
var csQty = cs.CN_F_QUANTITY;
if (csQty == 0) continue;
//箱码(箱码只扣除箱码)
if (!string.IsNullOrEmpty(cs.CN_S_PACKING_UNIT))
{
var existsPackingUnit = trayItemMst.TrayItemDtlList.FindAll(f => f.CN_S_PACKING_UNIT == cs.CN_S_PACKING_UNIT && (string.IsNullOrEmpty(cs.CN_S_PRODUCTION_BATCH) || cs.CN_S_PRODUCTION_BATCH == f.CN_S_PRODUCTION_BATCH));
if (!existsPackingUnit.Any())
return OperateResult.Error("托盘:" + trayItemMst.CN_S_TRAY_CODE + "中未找到包装单位为:" + cs.CN_S_PACKING_UNIT + ",物料编码:" + cs.CN_S_ITEM_CODE + ",生产批次:" + cs.CN_S_PRODUCTION_BATCH + " 的物料");
foreach (var ep in existsPackingUnit)
{
if (csQty == 0) break;
if (ep.CN_F_QUANTITY >= csQty)
{
ep.CN_F_QUANTITY -= csQty;
csQty = 0;
}
else
{
csQty -= ep.CN_F_QUANTITY;
ep.CN_F_QUANTITY = 0;
}
}
}
else
{
//当前分拣的是单独包装
//可能不存在单个包装(拆包),可能存在单独包装但不够(拆包),可能单独包装都够
//先找所有为单独包装的,把没有包装单位的放前面,然后把最小个包装的放前面
trayItemMst.TrayItemDtlList = trayItemMst.TrayItemDtlList.Select(x => new
{
emptyPackingUnitIndex = string.IsNullOrEmpty(x.CN_S_PACKING_UNIT) ? 0 : 1,
x
}).OrderBy(o => o.emptyPackingUnitIndex).ThenBy(o => o.x.CN_F_PACKING_QTY).Select(s => s.x).ToList();
foreach (var tdtl in trayItemMst.TrayItemDtlList)
{
//需要拆包的
if (!string.IsNullOrEmpty(tdtl.CN_S_PACKING_UNIT))
{
//一包装内的个数
var packingQty = !tdtl.CN_F_PACKING_QTY.HasValue || tdtl.CN_F_PACKING_QTY == 0 ? 1 : tdtl.CN_F_PACKING_QTY.Value;
//有几个包装呢
decimal multiple = tdtl.CN_F_QUANTITY / packingQty;
if (tdtl.CN_F_QUANTITY > csQty)
{
tdtl.CN_F_QUANTITY -= csQty;
csQty = 0;
//不止一个包装时
if (multiple > 1)//取余拆单
{
int restQty = (int)tdtl.CN_F_QUANTITY / (int)packingQty;
if (restQty > 0)
{
var restAloneQty = tdtl.CN_F_QUANTITY % packingQty;
if (restAloneQty > 0)
{
tdtl.CN_F_QUANTITY = restQty * packingQty;
//多余出来的部分创建一条新记录
var aloneDtl = tdtl.Clone() as TN_WM_B_TRAY_ITEM_DTLEntity;
aloneDtl.CN_GUID = Guid.NewGuid().ToString();
aloneDtl.CN_F_QUANTITY = restAloneQty;
aloneDtl.CN_F_PACKING_QTY = 0;
aloneDtl.CN_S_PACKING_UNIT = "";
trayItemMst.UnpackingDtl.Add(aloneDtl);
}
}
else//拆的只剩单个
{
tdtl.CN_F_PACKING_QTY = 0;
tdtl.CN_S_PACKING_UNIT = "";
}
}
else//直接可以拆
{
tdtl.CN_F_PACKING_QTY = 0;
tdtl.CN_S_PACKING_UNIT = "";
}
}
else//数量大于等于包装数时全部扣完
{
csQty -= tdtl.CN_F_QUANTITY;
tdtl.CN_F_QUANTITY = 0;
}
}
else//不需要拆包,直接扣
{
if (tdtl.CN_F_QUANTITY >= csQty)
{
tdtl.CN_F_QUANTITY -= csQty;
csQty = 0;
}
else
{
csQty -= tdtl.CN_F_QUANTITY;
tdtl.CN_F_QUANTITY = 0;
}
}
}
}
if (csQty > 0)
return OperateResult.Error("物料:" + cs.CN_S_ITEM_CODE + ",包装单位:" + cs.CN_S_PACKING_UNIT + "在托盘:" + cs.CN_S_TRAY_CODE + "中不足");
//Log.Info("确认分拣cs", "000401");
//foreach (var trayItemDtl in trayItemMst.TrayItemDtlList)
//{
// if (csQty == 0) break;
// if (trayItemDtl.CN_F_QUANTITY == 0) continue;
// if (((cs.CN_F_PACKING_QTY <= 1 && trayItemDtl.CN_F_PACKING_QTY <= 1) || cs.CN_S_PACKING_UNIT == trayItemDtl.CN_S_PACKING_UNIT) &&
// (string.IsNullOrEmpty(cs.CN_S_PRODUCTION_BATCH) || cs.CN_S_PRODUCTION_BATCH == trayItemDtl.CN_S_PRODUCTION_BATCH)
// //&&
// //(string.IsNullOrEmpty(cs.CN_S_LOT_NO) || cs.CN_S_LOT_NO
// //.Equals(trayItemDtl.CN_S_LOT_NO))
// )
// {
// if (trayItemDtl.CN_F_QUANTITY >= csQty)
// {
// trayItemDtl.CN_F_QUANTITY -= csQty;
// //如果扣的当前是包,并且拣货不是按包来拣,拆包!
// if (trayItemDtl.CN_F_PACKING_QTY > 1 &&
// cs.CN_F_PACKING_QTY > 1 &&
// (cs.CN_F_PACKING_QTY != trayItemDtl.CN_F_PACKING_QTY))
// {
// trayItemDtl.CN_F_PACKING_QTY = 1;
// trayItemDtl.CN_S_PACKING_UNIT = cs.CN_S_MEASURE_UNIT;
// }
// csQty = 0;
// }
// else
// {
// csQty -= trayItemDtl.CN_F_QUANTITY;
// trayItemDtl.CN_F_QUANTITY = 0;
// }
// }
//}
}
}
}
var currentTrayLocation = CreateDAL>().GetSingleEntity(new
{
CN_S_TRAY_CODE = sortingResult[0].CN_S_TRAY_CODE
});
Log.Info("ConfirmSorting 分拣结果的托盘物料关联数据", JsonConvert.SerializeObject(trayItemMstList));
Log.Info("确认分拣", "UseTransaction start");
var operateResult = UseTransaction(trans =>
{
Log.Info("ConfirmSorting ", "确认分拣开始-------------------------------------------------------");
//保存分拣结果
CreateDAL>().AddRange(sortingResult, trans);
Log.Info("ConfirmSorting ", "保存分拣结果完成");
//下降托盘物料数据量
Log.Info("ConfirmSorting 下降托盘物料数据量数据:trayItemMstList", JsonConvert.SerializeObject(trayItemMstList));
Log.Info("ConfirmSorting 下降托盘物料数据量数据:currentTrayLocation", JsonConvert.SerializeObject(currentTrayLocation));
CreateDAL().DropTrayItemQty(trayItemMstList, currentTrayLocation, trans);
//是否有拆包新增的数据
foreach (var m in trayItemMstList)
{
if (m.UnpackingDtl.Any())
CreateDapperDAL().AddRange(m.UnpackingDtl, trans);
}
Log.Info("ConfirmSorting ", "下降托盘物料数据量");
//分拣单全部捡完置为已分拣
if (sortingPicked)
{
CreateDAL>().Update(new
{
CN_S_STATE = Constants.Sorting_Sorted
}, new
{
CN_S_SORTING_NO = sortingResult[0].CN_S_SORTING_NO
}, trans);
Log.Info("ConfirmSorting ", "分拣单全部捡完置为已分拣");
if (areaQtyList.Any())
{
Log.Info("ConfirmSorting ", "降库存");
Log.Info("ConfirmSorting 降库存数据", JsonConvert.SerializeObject(areaQtyList));
CreateDAL().UpdateAreaQtyAndAlloc(areaQtyList, trans);
Log.Info("ConfirmSorting ", "降库存完成");
}
//降库存
//if (outLockDtl.Any())
//{
// //CreateDAL().UpdateAllocQtyByLock(Constants.Rule_SortingNo, outLockDtl, trans);
// Log.Info("ConfirmSorting ", "降库存");
// CreateDAL().DeleteOutLock(outLockDtl, trans);
// Log.Info("ConfirmSorting ", "删除锁定明细");
//}
}
//波次捡完置为已分拣
if (wavePicked)
{
CreateDAL>().Update(new
{
CN_S_STATE = Constants.Sorting_Sorted
}, new
{
CN_S_WAVE_NO = waveNo
}, trans);
Log.Info("ConfirmSorting ", "波次捡完置为已分拣");
//出库单状态,已分拣
CreateDAL>().Update(new
{
CN_S_STATE = Constants.Sorting_Sorted
}, new
{
CN_S_WAVE_CODE = waveNo
}, trans);
}
if (!string.IsNullOrEmpty(boxNo))
{
//容器绑定
CreateDAL>().Update(new
{
CN_S_SORTING_CODE = sortingResult[0].CN_S_SORTING_NO,
CN_S_STATE = Constants.TrayState_InUse
}, new
{
CN_S_TRAY_CODE = boxNo
}, trans);
Log.Info("ConfirmSorting ", "容器绑定");
}
Log.Info("ConfirmSorting ", "确认分拣完成-------------------------------------------------------");
});
if (operateResult.Success && currentTrayLocation != null)
{
var currentTrayItemMst = CreateDAL>().GetList(new
{
CN_S_TRAY_CODE = currentTrayLocation.CN_S_TRAY_CODE
});
if (!currentTrayItemMst.Any())
{
operateResult = UseTransaction(trans =>
{
CreateDAL().ClearLocationByTrayCode(currentTrayLocation, trans);
});
}
}
return operateResult;
}
#endregion
public void SavePickData(SavePickEntity entity, IDbTransaction trans)
{
//保存分拣结果
CreateDAL>().AddRange(entity.SortingResult, trans);
Log.Info("SavePickData ", "保存分拣结果完成");
//更新分拣明细已拣数量
if (entity.SortingLocation != null)
{
entity.SortingLocation.ForEach(e =>
{
CreateDapperDAL().Update(new
{
CN_F_PICKED_QTY = e.CN_F_QUANTITY
}, new
{
CN_GUID = e.CN_GUID
}, trans);
});
}
//下降托盘物料数据量
Log.Info("SavePickData 下降托盘物料数据量数据:trayItemMstList", JsonConvert.SerializeObject(entity.TrayItemList));
Log.Info("SavePickData 下降托盘物料数据量数据:currentTrayLocation", JsonConvert.SerializeObject(entity.TrayLocation));
CreateDAL().DropTrayItemQty(entity.TrayItemList, entity.TrayLocation, trans);
Log.Info("SavePickData ", "下降托盘物料数据量");
//分拣单全部捡完置为已分拣
if (entity.SortingPicked)
{
CreateDAL>().Update(new
{
CN_S_STATE = Constants.Sorting_Sorted
}, new
{
CN_S_SORTING_NO = entity.SortingNo
}, trans);
Log.Info("SavePickData ", "分拣单全部捡完置为已分拣");
//分拣单全部拣完,降库区库存
if (entity.AreaQtyList.Any())
{
Log.Info("SavePickData ", "降库存");
Log.Info("SavePickData 降库存数据", JsonConvert.SerializeObject(entity.AreaQtyList));
CreateDAL().UpdateAreaQtyAndAlloc(entity.AreaQtyList, trans);
Log.Info("SavePickData ", "降库存完成");
}
}
//波次捡完置为已分拣
if (entity.WavePicked)
{
CreateDAL>().Update(new
{
CN_S_STATE = Constants.Sorting_Sorted
}, new
{
CN_S_WAVE_NO = entity.WaveNo
}, trans);
Log.Info("SavePickData ", "波次捡完置为已分拣");
//出库单状态,已分拣
CreateDAL>().Update(new
{
CN_S_STATE = Constants.Sorting_Sorted
}, new
{
CN_S_WAVE_CODE = entity.WaveNo
}, trans);
}
if (!string.IsNullOrEmpty(entity.BoxNo))
{
//容器绑定
CreateDAL>().Update(new
{
CN_S_SORTING_CODE = entity.SortingNo,
CN_S_STATE = Constants.TrayState_InUse
}, new
{
CN_S_TRAY_CODE = entity.BoxNo
}, trans);
Log.Info("SavePickData ", "容器绑定");
}
}
#region (PDA汇聚)保存边拣边播
///
/// (PDA汇聚)保存边拣边播
///
///
public OperateResult SaveBJBB(SavePickEntity entity)
{
Log.Info("保存边拣边播", "UseTransaction start");
var operateResult = UseTransaction(trans =>
{
Log.Info("保存边拣边播", "保存边拣边播开始--------------------------------------------------------");
//保存订单拣货明细
CreateDAL>().AddRange(entity.OrderSortingRel, trans);
Log.Info("SaveBJBB ", "保存订单拣货完成");
//保存拣货信息
SavePickData(entity, trans);
Log.Info("保存边拣边播", "保存边拣边播结束--------------------------------------------------------");
});
#region 非自动库才会全部捡完才会解绑托盘和货位关系
var currentArea = CreateDAL().GetStockAreaEntity(entity.CurrentSorting.CN_S_STOCK_AREA);
//非自动库才会全部捡完才会解绑托盘和货位关系
if (currentArea != null && currentArea.CN_C_IS_AUTO != Constants.Y && operateResult.Success && entity.TrayLocation != null)
{
var currentTrayItemMst = CreateDAL>().GetList(new
{
CN_S_TRAY_CODE = entity.TrayLocation.CN_S_TRAY_CODE
});
if (!currentTrayItemMst.Any())
{
operateResult = UseTransaction(trans =>
{
CreateDAL().ClearLocationByTrayCode(entity.TrayLocation, trans);
});
}
}
#endregion
return operateResult;
}
#endregion
public OperateResult SaveXJHB(SavePickEntity entity)
{
Log.Info("保存先拣后播", "UseTransaction start");
var operateResult = UseTransaction(trans =>
{
Log.Info("保存先拣后播", "保存先拣后播开始--------------------------------------------------------");
//保存拣货信息
SavePickData(entity, trans);
Log.Info("保存边拣边播", "保存先拣后播结束--------------------------------------------------------");
});
#region 非自动库才会全部捡完才会解绑托盘和货位关系
var currentArea = CreateDAL().GetStockAreaEntity(entity.CurrentSorting.CN_S_STOCK_AREA);
//非自动库才会全部捡完才会解绑托盘和货位关系
if (currentArea != null && currentArea.CN_C_IS_AUTO != Constants.Y && operateResult.Success && entity.TrayLocation != null)
{
var currentTrayItemMst = CreateDAL>().GetList(new
{
CN_S_TRAY_CODE = entity.TrayLocation.CN_S_TRAY_CODE
});
if (!currentTrayItemMst.Any())
{
operateResult = UseTransaction(trans =>
{
CreateDAL().ClearLocationByTrayCode(entity.TrayLocation, trans);
});
}
}
#endregion
return operateResult;
}
#region (PDA汇聚)分拣入
///
/// (PDA汇聚)分拣回和搬运
///
///
///
public OperateResult Transport(TN_WM_TASKEntity taskEntity)
{
return UseTransaction(trans =>
{
CreateDAL>().Add(taskEntity, trans);
CreateDAL>().Update(new
{
CN_S_LOCATION_STATE = Constants.Location_State_InLock
}, new
{
taskEntity.CN_S_END_BIT
}, trans);
var sendAms = BLLCreator.Create().SendAmsTask(taskEntity);
if (!sendAms.Success)
throw new Exception(sendAms.Msg);
});
}
#endregion
#region 执行分拣单
///
/// 执行分拣单
///
///
///
public OperateResult ExecuteSorting(TN_WM_SORTING_LISTEntity sortingEntity, List trayItem = null)
{
return UseTransaction(trans =>
{
//分拣单设为分拣中
CreateDAL>().Update(new
{
CN_S_STATE = Constants.Sorting_Being
}, new
{
CN_S_SORTING_NO = sortingEntity.CN_S_SORTING_NO
}, trans);
//分拣单子表设为分拣中
CreateDAL>().Update(new
{
CN_S_STATE = Constants.Sorting_Being
}, new
{
CN_S_SORTING_NO = sortingEntity.CN_S_SORTING_NO
}, trans);
//波次设为分拣中
CreateDAL>().Update(new
{
CN_S_STATE = Constants.Sorting_Being
}, new
{
CN_S_WAVE_NO = sortingEntity.CN_S_FROM_NO
}, trans);
//出库单分拣中
CreateDAL>().Update(new
{
CN_S_STATE = Constants.Sorting_Being
}, new
{
CN_S_WAVE_CODE = sortingEntity.CN_S_FROM_NO
}, trans);
//生成分拣单明细
//if (sortingEntity.SortingLocationList != null)
// CreateDAL>().AddRange(sortingEntity.SortingLocationList, trans);
//托盘物料分配量上升
//if (trayItem != null)
// CreateDAL().UpdateTrayItemAllocQty(trayItem, trans);
//生成任务
if (sortingEntity.Tasks.Any())
{
//增加出库任务
CreateDAL>().AddRange(sortingEntity.Tasks, trans);
//起点置为预出库锁定,终点预入库锁定
foreach (var task in sortingEntity.Tasks)
{
CreateDAL>().Update(new
{
CN_S_LOCATION_STATE = Constants.Location_State_OutLock
}, new
{
CN_S_LOCATION_CODE = task.CN_S_START_BIT
}, trans);
//存在终点
if (!string.IsNullOrEmpty(task.CN_S_END_BIT))
{
CreateDAL>().Update(new
{
CN_S_LOCATION_STATE = Constants.Location_State_InLock
}, new
{
CN_S_LOCATION_CODE = task.CN_S_END_BIT
}, trans);
//发送ams任务
var sendAms = BLLCreator.Create().SendAmsTask(task);
if (!sendAms.Success)
throw new Exception(sendAms.Msg);
}
}
}
});
}
#endregion
#region 合箱
///
/// 合箱
///
///
///
///
public OperateResult MergeBox(List sortingResult, bool sortingPicked, bool wavePicked, string waveNo)
{
return UseTransaction(trans =>
{
//分拣结果绑定周转箱
CreateDAL().MergeBox(sortingResult, trans);
if (sortingPicked)
//分拣单设为已分拣
CreateDAL>().Update(new
{
CN_S_STATE = Constants.Sorting_Sorted
}, new
{
CN_S_SORTING_NO = sortingResult[0].CN_S_SORTING_NO
}, trans);
//波次捡完置为已分拣
if (wavePicked)
CreateDAL>().Update(new
{
CN_S_STATE = Constants.Sorting_Sorted
}, new
{
CN_S_WAVE_NO = waveNo
}, trans);
});
}
#endregion
#region 根据托盘获取分拣中的分拣单数据
///
/// 根据托盘获取分拣中的分拣单数据
///
///
///
public List GetPickDataByTray(string trayCode)
{
//分拣单
var sortings = CreateDAL().GetPickSortingByTray(trayCode);
if (!sortings.Any()) return null;
//分拣单子表
var sortingDtls = CreateDAL>().GetList(new
{
CN_S_SORTING_NO = sortings.Select(s => s.CN_S_SORTING_NO).ToList()
});
//分拣明细
var sortingLocations = CreateDAL>().GetList(new
{
CN_S_SORTING_NO = sortings.Select(s => s.CN_S_SORTING_NO).ToList()
});
//分拣结果
var sortingResults = CreateDAL>().GetList(new
{
CN_S_SORTING_NO = sortings.Select(s => s.CN_S_SORTING_NO).ToList()
});
//赋值
sortings.ForEach(e =>
{
e.SortingDtlList = sortingDtls.Where(w => w.CN_S_SORTING_NO == e.CN_S_SORTING_NO).ToList();
e.SortingLocationList = sortingLocations.Where(w => w.CN_S_SORTING_NO == e.CN_S_SORTING_NO).ToList();
e.SortingResultList = sortingResults.Where(w => w.CN_S_SORTING_NO == e.CN_S_SORTING_NO).ToList();
});
return sortings;
}
#endregion
#region (cs端)先拣后播扫物料
///
/// (cs端)先拣后播扫物料
///
///
///
public OperateResult ScanItem(SavePickEntity entity)
{
var operateResult = UseTransaction(trans =>
{
//保存分拣结果
CreateDAL>().AddRange(entity.SortingResult, trans);
//下降托盘物料数据量
Log.Info("ScanItem 下降托盘物料数据量数据:trayItemMstList", JsonConvert.SerializeObject(entity.TrayItemList));
Log.Info("ScanItem 下降托盘物料数据量数据:currentTrayLocation", JsonConvert.SerializeObject(entity.TrayLocation));
CreateDAL().DropTrayItemQty(entity.TrayItemList, entity.TrayLocation, trans);
Log.Info("ScanItem ", "下降托盘物料数据量");
});
#region 非自动库才会全部捡完才会解绑托盘和货位关系
var currentArea = CreateDAL().GetStockAreaEntity(entity.CurrentSorting.CN_S_STOCK_AREA);
//非自动库才会全部捡完才会解绑托盘和货位关系
if (currentArea != null && currentArea.CN_C_IS_AUTO != Constants.Y && operateResult.Success && entity.TrayLocation != null)
{
var currentTrayItemMst = CreateDAL>().GetList(new
{
CN_S_TRAY_CODE = entity.TrayLocation.CN_S_TRAY_CODE
});
if (!currentTrayItemMst.Any())
{
operateResult = UseTransaction(trans =>
{
CreateDAL().ClearLocationByTrayCode(entity.TrayLocation, trans);
});
}
}
#endregion
return operateResult;
}
#endregion
#region (cs端)先拣后播扫周转箱
///
/// (cs端)先拣后播扫周转箱
///
///
///
public OperateResult ScanTurnoverBox(SavePickEntity entity)
{
return UseTransaction(trans =>
{
//分拣单全部捡完
if (entity.SortingPicked)
{
//修改分拣单状态为已分拣
CreateDapperDAL().Update(new
{
CN_S_STATE = Constants.Sorting_Sorted
}, new
{
CN_S_SORTING_NO = entity.SortingNo
}, trans);
//波次值为已分拣
if (entity.WavePicked)
{
CreateDapperDAL().Update(new
{
CN_S_STATE = Constants.Sorting_Sorted
}, new
{
CN_S_WAVE_NO = entity.CurrentSorting.CN_S_FROM_NO
}, trans);
}
//外销时
if (entity.IsWx)
{
//出库订单,减少库存业务表状态置为 “预出库”状态
CreateDapperDAL().Update(new
{
CN_S_STATE = Constants.State_PreOut
}, new
{
CN_S_OP_NO = entity.OutMst.CN_S_OP_NO
}, trans);
CreateDapperDAL().Update(new
{
CN_S_STATE = Constants.State_PreOut
}, new
{
CN_S_OP_NO = entity.OutMst.CN_S_OP_NO
}, trans);
CreateDapperDAL().Update(new
{
CN_S_STATE = Constants.State_PreOut
}, new
{
CN_S_FROM_NO = entity.OutMst.CN_S_OP_NO
}, trans);
}
}
//合箱
foreach (var s in entity.SortingResult)
{
CreateDapperDAL().Update(new
{
CN_S_TURNOVERBOX_CODE = entity.BoxNo
}, new
{
CN_GUID = s.CN_GUID
}, trans);
}
//设置容器状态绑定
CreateDapperDAL().Update(new
{
CN_S_STATE = Constants.TrayState_InUse,
CN_S_SORTING_CODE = entity.SortingNo
}, new
{
CN_S_TRAY_CODE = entity.BoxNo
}, trans);
//设置分拣单周转箱位置
CreateDapperDAL().Update(new
{
CN_S_COLLECT_LOCATION = entity.EndBit
}, new
{
CN_S_SORTING_CODE = entity.SortingNo
}, trans);
//当前位置预出库锁定
CreateDapperDAL().Update(new
{
CN_S_LOCATION_STATE = Constants.Location_State_OutLock
}, new
{
CN_S_LOCATION_CODE = entity.StartBit
}, trans);
//终点位置与入库锁定
CreateDapperDAL().Update(new
{
CN_S_LOCATION_STATE = Constants.Location_State_InLock
}, new
{
CN_S_LOCATION_CODE = entity.EndBit
}, trans);
});
}
#endregion
#region 获取任务
///
/// 获取任务
///
///
///
///
public OperateResult GetOutTask(ref TN_WM_SORTING_LISTEntity sortingEntity, ref List endAreas, string endArea = "", string endBit = "")
{
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 taskList = new List();
//存在非整托货位托盘
var pickTrays = trayGroup
.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())
{
#region 根据终点货位生成任务
if (string.IsNullOrEmpty(endArea))
{
//有终点货位,直接找库区
if (!string.IsNullOrEmpty(endBit))
{
var locationEntity = CreateDAL().GetLocationModel(endBit);
if (locationEntity == null)
return OperateResult.Error("未找到货位:" + endBit);
endArea = locationEntity.CN_S_AREA_CODE;
}
else
{
//非整托任务
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>();
endAreas.AddRange(workAreaPro.Select(s => s.CN_S_END_AREA_CODE).ToList());
endArea = workAreaPro[0].CN_S_END_AREA_CODE;
}
}
else
{
endAreas.Add(endArea);
}
#endregion
#region 根据终点库区生成任务
if (string.IsNullOrEmpty(endBit))
{
//存在任务调度策略时,不生成货位,通过服务去生成
var taskDispatch = GetStrategy(sortingEntity.CN_S_STOCK_CODE,
StrategyKey.TaskDispatch);
if (taskDispatch != Constants.Y)
{
//需要调作业区入库算法,算出货位给出库任务
var inAssignEntity = new InAssignEntity
{
objectType = InAssignEntity.ObjectType.托盘,
objectCode = pickTrays[0].CN_S_TRAY_CODE,
lockLocation = false,
lstAreaPrior = new List()
{
{
new areaPriorClass{
areaCode = endArea,
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);
endBit = inAssignResultEntity.locationCode;
}
}
#endregion
//分拣出库任务
var pickTasks = GetTaskEntity(sortingEntity.CN_S_STOCK_AREA, endArea, pickTrays, endBit);
taskList.AddRange(pickTasks);
}
sortingEntity.Tasks = taskList;
sortingEntity.EndBits = endAreas;
return OperateResult.Succeed(null, taskList);
}
catch (Exception ex)
{
return OperateResult.Error(ex.Message);
}
}
#endregion
#region 获取任务实体
///
/// 获取任务实体
///
///
///
///
private List GetTaskEntity(string startArea, string endArea, 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_OutTaskNo + "\",\"orgId\":\"\",\"orgFlag\":\"\"}";
string taskNo = WebApiManager.HttpAutoBom_Post("api/BillRule/GenBillNo", postData);
AutoBomStockAreaEntity startAreaE = CreateDAL().GetStockAreaEntity(startArea);
AutoBomStockAreaEntity endAreaE = CreateDAL().GetStockAreaEntity(endArea);
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 = BLLCreator.Create().GetArea(endArea).CN_S_STOCK_CODE,
CN_S_START_AREA = startArea,
CN_S_START_BIT = task.CN_S_LOCATION_CODE,
CN_S_END_AREA = endArea,
CN_S_END_BIT = endBit,
CN_S_STATE = Constants.TaskState_NoExecuted,
CN_T_CREATE = DateTime.Now,
CN_T_MODIFY = DateTime.Now,
CN_S_START_AREA_TYPE = startAreaE.CN_S_STRUCTURE,
CN_S_END_AREA_TYPE = endAreaE.CN_S_STRUCTURE,
CN_C_START_IS_CONTROL_QTY = startAreaE.CN_C_IS_CONTROL_QTY,
CN_C_END_IS_CONTROL_QTY = endAreaE.CN_C_IS_CONTROL_QTY,
CN_S_START_CONTROL_INV = startAreaE.CN_C_IS_INVENTORY,
CN_S_END_CONTROL_INV = endAreaE.CN_C_IS_INVENTORY,
EndAreaEntity = endAreaE
};
taskList.Add(taskEntity);
}
return taskList;
}
#endregion
#region 出库单获取分拣明细
///
/// 出库单获取分拣明细
///
///
///
public List GetTrayLocationByOut(string outNo)
{
return CreateDAL().GetTrayLocationByOut(outNo);
}
#endregion
#region 批分托盘物料关联(不含三生拆包部分)
///
/// 批分托盘物料关联(不含三生拆包部分)
///
///
///
public List BatchesTrayItemByResult(List sortingResult)
{
//算法策略
List lstStrate = BLLCreator.Create().GetStrateListByAreaOrStock("", "", Constants.Out)
.OrderByDescending(a => a.CN_N_PRIORITY).Select(o => o.CN_S_CODE).ToList();
//分拣结果的托盘物料关联数据
var trayItemMstList = BLLCreator.CreateDapper().GetList(new
{
CN_S_TRAY_CODE = sortingResult.Select(x => x.CN_S_TRAY_CODE).ToList(),
CN_S_ITEM_CODE = sortingResult.Select(x => x.CN_S_ITEM_CODE).ToList()
});
foreach (var trayItemMst in trayItemMstList)
{
trayItemMst.TrayItemDtlList = new List();
//属于当前托盘,当前物料的分拣明细
var currentSortingResult = sortingResult.Where(x => x.CN_S_ITEM_CODE == trayItemMst.CN_S_ITEM_CODE && x.CN_S_TRAY_CODE == trayItemMst.CN_S_TRAY_CODE);
decimal qty = currentSortingResult.Sum(y => y.CN_F_QUANTITY);
if (trayItemMst.CN_F_QUANTITY >= qty &&
trayItemMst.CN_F_ALLOC_QTY >= qty)
{
trayItemMst.CN_F_QUANTITY -= qty;
trayItemMst.CN_F_ALLOC_QTY -= qty;
Log.Info("确认分拣", "0001");
trayItemMst.TrayItemDtlList = BLLCreator.CreateDapper().GetList(new
{
CN_PARENT_GUID = trayItemMst.CN_GUID
}).OrderBy(x => x.CN_S_LOT_NO).ToList();
Log.Info("确认分拣", "0002");
//空的生产批次放后面
currentSortingResult = currentSortingResult.Select(x => new
{
index = string.IsNullOrEmpty(x.CN_S_PRODUCTION_BATCH) ? 0 : 1,
x
}).OrderByDescending(y => y.index).ThenBy(z => z.x.CN_S_PRODUCTION_BATCH).Select(m => m.x);
Log.Info("确认分拣", "0003");
foreach (string stegy in lstStrate)
{
//逐个策略进行计算
switch (stegy)
{
case "FirstInFirstOut":
trayItemMst.TrayItemDtlList = trayItemMst.TrayItemDtlList.OrderBy(o => o.CN_S_LOT_NO).ToList();
break;
case "FirstWarrantFirstOut":
trayItemMst.TrayItemDtlList = trayItemMst.TrayItemDtlList.Select(x => new
{
index = string.IsNullOrEmpty(x.CN_S_PRODUCTION_BATCH) ? 0 : 1,
x
}).OrderByDescending(y => y.index).ThenBy(z => z.x.CN_S_PRODUCTION_BATCH).Select(m => m.x).ToList();
break;
}
}
Log.Info("确认分拣", "0004");
foreach (var cs in currentSortingResult)
{
var csQty = cs.CN_F_QUANTITY;
foreach (var trayItemDtl in trayItemMst.TrayItemDtlList)
{
if (csQty == 0) break;
if (trayItemDtl.CN_F_QUANTITY == 0) continue;
if (trayItemDtl.CN_F_QUANTITY >= csQty)
{
trayItemDtl.CN_F_QUANTITY -= csQty;
csQty = 0;
}
else
{
csQty -= trayItemDtl.CN_F_QUANTITY;
trayItemDtl.CN_F_QUANTITY = 0;
}
}
}
}
}
return trayItemMstList;
}
#endregion
#region 根据库区算法结果生成分拣单数据
///
/// 根据库区算法结果生成分拣单数据
///
///
///
///
///
public OperateResult GetSortingData(List outAreaResultList, UserRuleEntity user, string waveNo, string taskEndBit = "")
{
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().GetItem(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);
}
}
#region 生成分拣明细
//调用算法获取分拣明细,分拣明细改到执行分拣单的时候生成
var sortingLocationResult = BLLCreator.Create().GetSortingLocation(sortingEntity, user);
if (!sortingLocationResult.Success)
return sortingLocationResult;
var sortingLocations = sortingLocationResult.GetData>();
sortingEntity.SortingLocationList.AddRange(sortingLocations);
#endregion
#region 自动库需要生成出库任务
//生成任务
//List endAreas = new List();
//var outTaskResult = GetOutTask(ref sortingEntity, ref endAreas, taskEndBit);
//if (!outTaskResult.Success)
//{
// return outTaskResult;
//}
#endregion
sortingList.Add(sortingEntity);
}
return OperateResult.Succeed(null, sortingList);
}
catch (Exception ex)
{
return OperateResult.Error(ex.Message);
}
}
#endregion
#region 调算法获取分拣明细
///
///调算法获取分拣明细
///
///
///
///
public OperateResult GetSortingLocation(TN_WM_SORTING_LISTEntity sortingEntity, UserRuleEntity user)
{
try
{
List sortingLocationList = new List();
if (!sortingEntity.SortingDtlList.Any())
sortingEntity.SortingDtlList = BLLCreator.CreateDapper().GetList(new
{
CN_S_SORTING_NO = sortingEntity.CN_S_SORTING_NO
});
//初始化调用算法数据
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();
Log.Info("调用OutNew参数 algorItems", JsonConvert.SerializeObject(algorItems));
var outResult = BLLCreator.Create().OutNew(new OutAlgorEnitty()
{
lstDevice = new List(),
lstAreaPrior = lstAreaPrior,
lstQueryItem = algorItems,
lockLocation = false
});
Log.Info("调用OutNew返回值 outResult", JsonConvert.SerializeObject(outResult));
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 = CreateDAL().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 = user.LoginCode,
CN_S_CREATOR_BY = user.LoginName,
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
}
}