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 分拣单列表
|
/// <summary>
|
/// 分拣单列表
|
/// </summary>
|
/// <param name="key"></param>
|
/// <returns></returns>
|
public List<TN_WM_SORTING_LISTEntity> GetSortings(string key)
|
{
|
return CreateDAL<TN_WM_SORTING_LISTDAL>().GetSortings(key);
|
}
|
#endregion
|
|
#region 确认分拣
|
/// <summary>
|
/// 确认分拣
|
/// </summary>
|
/// <param name="sortingPicked"></param>
|
/// <param name="sortingResult"></param>
|
/// <returns></returns>
|
public OperateResult ConfirmSorting(bool sortingPicked, bool wavePicked, string waveNo, List<TN_WM_SORTING_RESULTEntity> sortingResult, string boxNo = "")
|
{
|
//分拣单捡完了,根据分拣单获取库区锁定明细
|
//List<TN_WM_B_OUTLOCKING_DTLEntity> outLockDtl = new List<TN_WM_B_OUTLOCKING_DTLEntity>();
|
List<TN_WM_B_AREA_QTYEntity> areaQtyList = new List<TN_WM_B_AREA_QTYEntity>();
|
//算法策略
|
List<string> lstStrate = BLLCreator.Create<SysMgr.TN_WM_B_STRATEGYBLL>().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<DapperDAL<TN_WM_SORTING_LISTEntity>>()
|
.GetSingleEntity(new
|
{
|
CN_S_SORTING_NO = sortingResult[0].CN_S_SORTING_NO
|
});
|
if (currentSorting != null)
|
{
|
var currentSortingDtl = CreateDAL<DapperDAL<TN_WM_SORTING_DTLEntity>>()
|
.GetList(new
|
{
|
CN_S_SORTING_NO = currentSorting.CN_S_SORTING_NO
|
});
|
currentSorting.SortingDtlList = currentSortingDtl;
|
|
areaQtyList = CreateDAL<DapperDAL<TN_WM_B_AREA_QTYEntity>>().GetList(new
|
{
|
CN_S_ITEM_CODE = currentSortingDtl.Select(x => x.CN_S_ITEM_CODE).ToList()
|
});
|
//反批分库区分配量
|
Log.Info("确认分拣", "BatchesAreaQty");
|
var result = areaQtyList.BatchesAreaQty(new List<TN_WM_SORTING_LISTEntity>() { currentSorting }, lstStrate, true);
|
Log.Info("确认分拣", JsonConvert.SerializeObject(result));
|
if (!result.Success)
|
return result;
|
}
|
}
|
|
//分拣结果的托盘物料关联数据
|
var trayItemMstList = CreateDAL<DapperDAL<TN_WM_B_TRAY_ITEM_MSTEntity>>().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<TN_WM_B_TRAY_ITEM_DTLEntity>();
|
trayItemMst.UnpackingDtl = new List<TN_WM_B_TRAY_ITEM_DTLEntity>();
|
//属于当前托盘,当前物料的分拣明细
|
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<DapperDAL<TN_WM_B_TRAY_ITEM_DTLEntity>>().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<DapperDAL<TN_WM_B_TRAY_LOCATIONEntity>>().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<DapperDAL<TN_WM_SORTING_RESULTEntity>>().AddRange(sortingResult, trans);
|
Log.Info("ConfirmSorting ", "保存分拣结果完成");
|
//下降托盘物料数据量
|
|
Log.Info("ConfirmSorting 下降托盘物料数据量数据:trayItemMstList", JsonConvert.SerializeObject(trayItemMstList));
|
Log.Info("ConfirmSorting 下降托盘物料数据量数据:currentTrayLocation", JsonConvert.SerializeObject(currentTrayLocation));
|
CreateDAL<TN_WM_SORTING_LISTDAL>().DropTrayItemQty(trayItemMstList, currentTrayLocation, trans);
|
//是否有拆包新增的数据
|
foreach (var m in trayItemMstList)
|
{
|
if (m.UnpackingDtl.Any())
|
CreateDapperDAL<TN_WM_B_TRAY_ITEM_DTLEntity>().AddRange(m.UnpackingDtl, trans);
|
}
|
Log.Info("ConfirmSorting ", "下降托盘物料数据量");
|
//分拣单全部捡完置为已分拣
|
if (sortingPicked)
|
{
|
CreateDAL<DapperDAL<TN_WM_SORTING_LISTEntity>>().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<TN_WM_B_AREA_QTYDAL>().UpdateAreaQtyAndAlloc(areaQtyList, trans);
|
Log.Info("ConfirmSorting ", "降库存完成");
|
}
|
//降库存
|
//if (outLockDtl.Any())
|
//{
|
// //CreateDAL<TN_WM_B_STOCK_QTYDAL>().UpdateAllocQtyByLock(Constants.Rule_SortingNo, outLockDtl, trans);
|
// Log.Info("ConfirmSorting ", "降库存");
|
// CreateDAL<TN_WM_B_STOCK_QTYDAL>().DeleteOutLock(outLockDtl, trans);
|
// Log.Info("ConfirmSorting ", "删除锁定明细");
|
//}
|
}
|
//波次捡完置为已分拣
|
if (wavePicked)
|
{
|
CreateDAL<DapperDAL<TN_WM_WAVE_MSTEntity>>().Update(new
|
{
|
CN_S_STATE = Constants.Sorting_Sorted
|
}, new
|
{
|
CN_S_WAVE_NO = waveNo
|
}, trans);
|
Log.Info("ConfirmSorting ", "波次捡完置为已分拣");
|
//出库单状态,已分拣
|
CreateDAL<DapperDAL<TN_WM_OUT_MSTEntity>>().Update(new
|
{
|
CN_S_STATE = Constants.Sorting_Sorted
|
}, new
|
{
|
CN_S_WAVE_CODE = waveNo
|
}, trans);
|
}
|
if (!string.IsNullOrEmpty(boxNo))
|
{
|
//容器绑定
|
CreateDAL<DapperDAL<TN_WM_B_TRAY_INFOEntity>>().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<DapperDAL<TN_WM_B_TRAY_ITEM_MSTEntity>>().GetList(new
|
{
|
CN_S_TRAY_CODE = currentTrayLocation.CN_S_TRAY_CODE
|
});
|
if (!currentTrayItemMst.Any())
|
{
|
operateResult = UseTransaction(trans =>
|
{
|
CreateDAL<TN_WM_SORTING_LISTDAL>().ClearLocationByTrayCode(currentTrayLocation, trans);
|
});
|
}
|
}
|
return operateResult;
|
}
|
#endregion
|
|
public void SavePickData(SavePickEntity entity, IDbTransaction trans)
|
{
|
//保存分拣结果
|
CreateDAL<DapperDAL<TN_WM_SORTING_RESULTEntity>>().AddRange(entity.SortingResult, trans);
|
Log.Info("SavePickData ", "保存分拣结果完成");
|
//更新分拣明细已拣数量
|
if (entity.SortingLocation != null)
|
{
|
entity.SortingLocation.ForEach(e =>
|
{
|
CreateDapperDAL<TN_WM_SORTING_LOCATIONEntity>().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<TN_WM_SORTING_LISTDAL>().DropTrayItemQty(entity.TrayItemList, entity.TrayLocation, trans);
|
Log.Info("SavePickData ", "下降托盘物料数据量");
|
//分拣单全部捡完置为已分拣
|
if (entity.SortingPicked)
|
{
|
CreateDAL<DapperDAL<TN_WM_SORTING_LISTEntity>>().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<TN_WM_B_AREA_QTYDAL>().UpdateAreaQtyAndAlloc(entity.AreaQtyList, trans);
|
Log.Info("SavePickData ", "降库存完成");
|
}
|
}
|
//波次捡完置为已分拣
|
if (entity.WavePicked)
|
{
|
CreateDAL<DapperDAL<TN_WM_WAVE_MSTEntity>>().Update(new
|
{
|
CN_S_STATE = Constants.Sorting_Sorted
|
}, new
|
{
|
CN_S_WAVE_NO = entity.WaveNo
|
}, trans);
|
Log.Info("SavePickData ", "波次捡完置为已分拣");
|
//出库单状态,已分拣
|
CreateDAL<DapperDAL<TN_WM_OUT_MSTEntity>>().Update(new
|
{
|
CN_S_STATE = Constants.Sorting_Sorted
|
}, new
|
{
|
CN_S_WAVE_CODE = entity.WaveNo
|
}, trans);
|
}
|
if (!string.IsNullOrEmpty(entity.BoxNo))
|
{
|
//容器绑定
|
CreateDAL<DapperDAL<TN_WM_B_TRAY_INFOEntity>>().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汇聚)保存边拣边播
|
/// <summary>
|
/// (PDA汇聚)保存边拣边播
|
/// </summary>
|
/// <returns></returns>
|
public OperateResult SaveBJBB(SavePickEntity entity)
|
{
|
Log.Info("保存边拣边播", "UseTransaction start");
|
var operateResult = UseTransaction(trans =>
|
{
|
Log.Info("保存边拣边播", "保存边拣边播开始--------------------------------------------------------");
|
//保存订单拣货明细
|
CreateDAL<DapperDAL<TN_WM_ORDER_SORTING_RELEntity>>().AddRange(entity.OrderSortingRel, trans);
|
Log.Info("SaveBJBB ", "保存订单拣货完成");
|
//保存拣货信息
|
SavePickData(entity, trans);
|
|
Log.Info("保存边拣边播", "保存边拣边播结束--------------------------------------------------------");
|
});
|
|
#region 非自动库才会全部捡完才会解绑托盘和货位关系
|
var currentArea = CreateDAL<TN_AB_B_STOCK_AREADAL>().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<DapperDAL<TN_WM_B_TRAY_ITEM_MSTEntity>>().GetList(new
|
{
|
CN_S_TRAY_CODE = entity.TrayLocation.CN_S_TRAY_CODE
|
});
|
if (!currentTrayItemMst.Any())
|
{
|
operateResult = UseTransaction(trans =>
|
{
|
CreateDAL<TN_WM_SORTING_LISTDAL>().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<TN_AB_B_STOCK_AREADAL>().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<DapperDAL<TN_WM_B_TRAY_ITEM_MSTEntity>>().GetList(new
|
{
|
CN_S_TRAY_CODE = entity.TrayLocation.CN_S_TRAY_CODE
|
});
|
if (!currentTrayItemMst.Any())
|
{
|
operateResult = UseTransaction(trans =>
|
{
|
CreateDAL<TN_WM_SORTING_LISTDAL>().ClearLocationByTrayCode(entity.TrayLocation, trans);
|
});
|
}
|
}
|
#endregion
|
|
return operateResult;
|
}
|
|
#region (PDA汇聚)分拣入
|
/// <summary>
|
/// (PDA汇聚)分拣回和搬运
|
/// </summary>
|
/// <param name="taskEntity"></param>
|
/// <returns></returns>
|
public OperateResult Transport(TN_WM_TASKEntity taskEntity)
|
{
|
return UseTransaction(trans =>
|
{
|
CreateDAL<DapperDAL<TN_WM_TASKEntity>>().Add(taskEntity, trans);
|
CreateDAL<DapperDAL<TN_WM_LOCATION_EXTEntity>>().Update(new
|
{
|
CN_S_LOCATION_STATE = Constants.Location_State_InLock
|
}, new
|
{
|
taskEntity.CN_S_END_BIT
|
}, trans);
|
var sendAms = BLLCreator.Create<OtherSysApi>().SendAmsTask(taskEntity);
|
if (!sendAms.Success)
|
throw new Exception(sendAms.Msg);
|
});
|
}
|
#endregion
|
|
#region 执行分拣单
|
/// <summary>
|
/// 执行分拣单
|
/// </summary>
|
/// <param name="sortingEntity"></param>
|
/// <returns></returns>
|
public OperateResult ExecuteSorting(TN_WM_SORTING_LISTEntity sortingEntity, List<TN_WM_B_TRAY_ITEM_MSTEntity> trayItem = null)
|
{
|
return UseTransaction(trans =>
|
{
|
//分拣单设为分拣中
|
CreateDAL<DapperDAL<TN_WM_SORTING_LISTEntity>>().Update(new
|
{
|
CN_S_STATE = Constants.Sorting_Being
|
}, new
|
{
|
CN_S_SORTING_NO = sortingEntity.CN_S_SORTING_NO
|
}, trans);
|
//分拣单子表设为分拣中
|
CreateDAL<DapperDAL<TN_WM_SORTING_DTLEntity>>().Update(new
|
{
|
CN_S_STATE = Constants.Sorting_Being
|
}, new
|
{
|
CN_S_SORTING_NO = sortingEntity.CN_S_SORTING_NO
|
}, trans);
|
//波次设为分拣中
|
CreateDAL<DapperDAL<TN_WM_WAVE_MSTEntity>>().Update(new
|
{
|
CN_S_STATE = Constants.Sorting_Being
|
}, new
|
{
|
CN_S_WAVE_NO = sortingEntity.CN_S_FROM_NO
|
}, trans);
|
//出库单分拣中
|
CreateDAL<DapperDAL<TN_WM_OUT_MSTEntity>>().Update(new
|
{
|
CN_S_STATE = Constants.Sorting_Being
|
}, new
|
{
|
CN_S_WAVE_CODE = sortingEntity.CN_S_FROM_NO
|
}, trans);
|
|
//生成分拣单明细
|
//if (sortingEntity.SortingLocationList != null)
|
// CreateDAL<DapperDAL<TN_WM_SORTING_LOCATIONEntity>>().AddRange(sortingEntity.SortingLocationList, trans);
|
//托盘物料分配量上升
|
//if (trayItem != null)
|
// CreateDAL<TN_WM_B_TRAY_ITEM_RELDAL>().UpdateTrayItemAllocQty(trayItem, trans);
|
|
//生成任务
|
if (sortingEntity.Tasks.Any())
|
{
|
//增加出库任务
|
CreateDAL<DapperDAL<TN_WM_TASKEntity>>().AddRange(sortingEntity.Tasks, trans);
|
//起点置为预出库锁定,终点预入库锁定
|
foreach (var task in sortingEntity.Tasks)
|
{
|
CreateDAL<DapperDAL<TN_WM_LOCATION_EXTEntity>>().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<DapperDAL<TN_WM_LOCATION_EXTEntity>>().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<OtherSysApi>().SendAmsTask(task);
|
if (!sendAms.Success)
|
throw new Exception(sendAms.Msg);
|
}
|
}
|
|
}
|
});
|
}
|
#endregion
|
|
#region 合箱
|
/// <summary>
|
/// 合箱
|
/// </summary>
|
/// <param name="sortingResult"></param>
|
/// <param name="sortingPicked"></param>
|
/// <returns></returns>
|
public OperateResult MergeBox(List<TN_WM_SORTING_RESULTEntity> sortingResult, bool sortingPicked, bool wavePicked, string waveNo)
|
{
|
return UseTransaction(trans =>
|
{
|
//分拣结果绑定周转箱
|
CreateDAL<TN_WM_SORTING_LISTDAL>().MergeBox(sortingResult, trans);
|
if (sortingPicked)
|
//分拣单设为已分拣
|
CreateDAL<DapperDAL<TN_WM_SORTING_LISTEntity>>().Update(new
|
{
|
CN_S_STATE = Constants.Sorting_Sorted
|
}, new
|
{
|
CN_S_SORTING_NO = sortingResult[0].CN_S_SORTING_NO
|
}, trans);
|
//波次捡完置为已分拣
|
if (wavePicked)
|
CreateDAL<DapperDAL<TN_WM_WAVE_MSTEntity>>().Update(new
|
{
|
CN_S_STATE = Constants.Sorting_Sorted
|
}, new
|
{
|
CN_S_WAVE_NO = waveNo
|
}, trans);
|
});
|
}
|
#endregion
|
|
#region 根据托盘获取分拣中的分拣单数据
|
/// <summary>
|
/// 根据托盘获取分拣中的分拣单数据
|
/// </summary>
|
/// <param name="trayCode"></param>
|
/// <returns></returns>
|
public List<TN_WM_SORTING_LISTEntity> GetPickDataByTray(string trayCode)
|
{
|
//分拣单
|
var sortings = CreateDAL<TN_WM_SORTING_LISTDAL>().GetPickSortingByTray(trayCode);
|
if (!sortings.Any()) return null;
|
//分拣单子表
|
var sortingDtls = CreateDAL<DapperDAL<TN_WM_SORTING_DTLEntity>>().GetList(new
|
{
|
CN_S_SORTING_NO = sortings.Select(s => s.CN_S_SORTING_NO).ToList()
|
});
|
//分拣明细
|
var sortingLocations = CreateDAL<DapperDAL<TN_WM_SORTING_LOCATIONEntity>>().GetList(new
|
{
|
CN_S_SORTING_NO = sortings.Select(s => s.CN_S_SORTING_NO).ToList()
|
});
|
//分拣结果
|
var sortingResults = CreateDAL<DapperDAL<TN_WM_SORTING_RESULTEntity>>().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端)先拣后播扫物料
|
/// <summary>
|
/// (cs端)先拣后播扫物料
|
/// </summary>
|
/// <param name="entity"></param>
|
/// <returns></returns>
|
public OperateResult ScanItem(SavePickEntity entity)
|
{
|
var operateResult = UseTransaction(trans =>
|
{
|
//保存分拣结果
|
CreateDAL<DapperDAL<TN_WM_SORTING_RESULTEntity>>().AddRange(entity.SortingResult, trans);
|
//下降托盘物料数据量
|
Log.Info("ScanItem 下降托盘物料数据量数据:trayItemMstList", JsonConvert.SerializeObject(entity.TrayItemList));
|
Log.Info("ScanItem 下降托盘物料数据量数据:currentTrayLocation", JsonConvert.SerializeObject(entity.TrayLocation));
|
CreateDAL<TN_WM_SORTING_LISTDAL>().DropTrayItemQty(entity.TrayItemList, entity.TrayLocation, trans);
|
Log.Info("ScanItem ", "下降托盘物料数据量");
|
});
|
|
#region 非自动库才会全部捡完才会解绑托盘和货位关系
|
var currentArea = CreateDAL<TN_AB_B_STOCK_AREADAL>().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<DapperDAL<TN_WM_B_TRAY_ITEM_MSTEntity>>().GetList(new
|
{
|
CN_S_TRAY_CODE = entity.TrayLocation.CN_S_TRAY_CODE
|
});
|
if (!currentTrayItemMst.Any())
|
{
|
operateResult = UseTransaction(trans =>
|
{
|
CreateDAL<TN_WM_SORTING_LISTDAL>().ClearLocationByTrayCode(entity.TrayLocation, trans);
|
});
|
}
|
}
|
#endregion
|
|
return operateResult;
|
}
|
#endregion
|
|
#region (cs端)先拣后播扫周转箱
|
/// <summary>
|
/// (cs端)先拣后播扫周转箱
|
/// </summary>
|
/// <param name="entity"></param>
|
/// <returns></returns>
|
public OperateResult ScanTurnoverBox(SavePickEntity entity)
|
{
|
return UseTransaction(trans =>
|
{
|
//分拣单全部捡完
|
if (entity.SortingPicked)
|
{
|
//修改分拣单状态为已分拣
|
CreateDapperDAL<TN_WM_SORTING_LISTEntity>().Update(new
|
{
|
CN_S_STATE = Constants.Sorting_Sorted
|
}, new
|
{
|
CN_S_SORTING_NO = entity.SortingNo
|
}, trans);
|
//波次值为已分拣
|
if (entity.WavePicked)
|
{
|
CreateDapperDAL<TN_WM_WAVE_MSTEntity>().Update(new
|
{
|
CN_S_STATE = Constants.Sorting_Sorted
|
}, new
|
{
|
CN_S_WAVE_NO = entity.CurrentSorting.CN_S_FROM_NO
|
}, trans);
|
}
|
//外销时
|
if (entity.IsWx)
|
{
|
//出库订单,减少库存业务表状态置为 “预出库”状态
|
CreateDapperDAL<TN_WM_OUT_MSTEntity>().Update(new
|
{
|
CN_S_STATE = Constants.State_PreOut
|
}, new
|
{
|
CN_S_OP_NO = entity.OutMst.CN_S_OP_NO
|
}, trans);
|
CreateDapperDAL<TN_WM_OUT_DTLEntity>().Update(new
|
{
|
CN_S_STATE = Constants.State_PreOut
|
}, new
|
{
|
CN_S_OP_NO = entity.OutMst.CN_S_OP_NO
|
}, trans);
|
CreateDapperDAL<TN_WM_REDUCE_INVENTORY_MSTEntity>().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<TN_WM_SORTING_RESULTEntity>().Update(new
|
{
|
CN_S_TURNOVERBOX_CODE = entity.BoxNo
|
}, new
|
{
|
CN_GUID = s.CN_GUID
|
}, trans);
|
}
|
//设置容器状态绑定
|
CreateDapperDAL<TN_WM_B_TRAY_INFOEntity>().Update(new
|
{
|
CN_S_STATE = Constants.TrayState_InUse,
|
CN_S_SORTING_CODE = entity.SortingNo
|
}, new
|
{
|
CN_S_TRAY_CODE = entity.BoxNo
|
}, trans);
|
//设置分拣单周转箱位置
|
CreateDapperDAL<TN_WM_SORTING_LISTEntity>().Update(new
|
{
|
CN_S_COLLECT_LOCATION = entity.EndBit
|
}, new
|
{
|
CN_S_SORTING_CODE = entity.SortingNo
|
}, trans);
|
//当前位置预出库锁定
|
CreateDapperDAL<TN_WM_LOCATION_EXTEntity>().Update(new
|
{
|
CN_S_LOCATION_STATE = Constants.Location_State_OutLock
|
}, new
|
{
|
CN_S_LOCATION_CODE = entity.StartBit
|
}, trans);
|
//终点位置与入库锁定
|
CreateDapperDAL<TN_WM_LOCATION_EXTEntity>().Update(new
|
{
|
CN_S_LOCATION_STATE = Constants.Location_State_InLock
|
}, new
|
{
|
CN_S_LOCATION_CODE = entity.EndBit
|
}, trans);
|
});
|
}
|
#endregion
|
|
#region 获取任务
|
/// <summary>
|
/// 获取任务
|
/// </summary>
|
/// <param name="sortingEntity"></param>
|
/// <param name="endAreas"></param>
|
/// <returns></returns>
|
public OperateResult GetOutTask(ref TN_WM_SORTING_LISTEntity sortingEntity, ref List<string> endAreas, string endArea = "", string endBit = "")
|
{
|
try
|
{
|
//当前分拣单库区
|
var currentArea = BLLCreator.Create<MongoBLL>().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<TN_WM_TASKEntity> taskList = new List<TN_WM_TASKEntity>();
|
//存在非整托货位托盘
|
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<TN_AB_STOCK_LOCATIONDAL>().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<WorkflowBLL>().GetWorkPosition(workflowEntity);
|
if (!trayWorkflow.Success) return trayWorkflow;
|
var workAreaPro = trayWorkflow.GetData<List<TN_WM_WORK_AREA_PROEntity>>();
|
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<areaPriorClass>()
|
{
|
{
|
new areaPriorClass{
|
areaCode = endArea,
|
Prior = 1
|
}
|
}
|
}
|
};
|
Log.Info("调用算法InAssign参数", JsonConvert.SerializeObject(inAssignEntity));
|
InAssignResultEntity inAssignResultEntity = BLLCreator.Create<In_AlgorBLL>().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 获取任务实体
|
/// <summary>
|
/// 获取任务实体
|
/// </summary>
|
/// <param name="workArea"></param>
|
/// <param name="sortingEntity"></param>
|
/// <returns></returns>
|
private List<TN_WM_TASKEntity> GetTaskEntity(string startArea, string endArea, List<TN_WM_SORTING_LOCATIONEntity> 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<TN_WM_TASKEntity> taskList = new List<TN_WM_TASKEntity>();
|
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<TN_AB_B_STOCK_AREADAL>().GetStockAreaEntity(startArea);
|
AutoBomStockAreaEntity endAreaE = CreateDAL<TN_AB_B_STOCK_AREADAL>().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<MongoBLL>().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 出库单获取分拣明细
|
/// <summary>
|
/// 出库单获取分拣明细
|
/// </summary>
|
/// <param name="outNo"></param>
|
/// <returns></returns>
|
public List<TN_WM_SORTING_LOCATIONEntity> GetTrayLocationByOut(string outNo)
|
{
|
return CreateDAL<TN_WM_SORTING_LISTDAL>().GetTrayLocationByOut(outNo);
|
}
|
#endregion
|
|
#region 批分托盘物料关联(不含三生拆包部分)
|
/// <summary>
|
/// 批分托盘物料关联(不含三生拆包部分)
|
/// </summary>
|
/// <param name="sortingResult"></param>
|
/// <returns></returns>
|
public List<TN_WM_B_TRAY_ITEM_MSTEntity> BatchesTrayItemByResult(List<TN_WM_SORTING_RESULTEntity> sortingResult)
|
{
|
//算法策略
|
List<string> lstStrate = BLLCreator.Create<SysMgr.TN_WM_B_STRATEGYBLL>().GetStrateListByAreaOrStock("", "", Constants.Out)
|
.OrderByDescending(a => a.CN_N_PRIORITY).Select(o => o.CN_S_CODE).ToList();
|
|
//分拣结果的托盘物料关联数据
|
var trayItemMstList = BLLCreator.CreateDapper<TN_WM_B_TRAY_ITEM_MSTEntity>().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<TN_WM_B_TRAY_ITEM_DTLEntity>();
|
//属于当前托盘,当前物料的分拣明细
|
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<TN_WM_B_TRAY_ITEM_DTLEntity>().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 根据库区算法结果生成分拣单数据
|
/// <summary>
|
/// 根据库区算法结果生成分拣单数据
|
/// </summary>
|
/// <param name="outAreaResultList"></param>
|
/// <param name="user"></param>
|
/// <param name="waveNo"></param>
|
/// <returns></returns>
|
public OperateResult GetSortingData(List<OutAreaResultEntity> outAreaResultList, UserRuleEntity user, string waveNo, string taskEndBit = "")
|
{
|
try
|
{
|
List<TN_WM_SORTING_LISTEntity> sortingList = new List<TN_WM_SORTING_LISTEntity>();
|
user.RuleCode = Constants.SortingGroup;
|
//分拣单组别
|
string sortingGroup = user.GenerateNo();
|
user.RuleCode = Constants.SortingNo;
|
int sortingIndex = 1;
|
IEnumerable<IGrouping<dynamic, OutAreaResultEntity>> 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<TN_WM_SORTING_DTLEntity>();
|
//分拣明细
|
sortingEntity.SortingLocationList = new List<TN_WM_SORTING_LOCATIONEntity>();
|
foreach (var outArea in _igOutAreaResult.AsEnumerable())
|
{
|
foreach (var d in outArea.lstItem)
|
{
|
//物料详细
|
AutoBomItemEntity item = BLLCreator.Create<TN_WMS_ITEMBLL>().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<TN_WM_SORTING_LISTBLL>().GetSortingLocation(sortingEntity, user);
|
if (!sortingLocationResult.Success)
|
return sortingLocationResult;
|
var sortingLocations = sortingLocationResult.GetData<List<TN_WM_SORTING_LOCATIONEntity>>();
|
sortingEntity.SortingLocationList.AddRange(sortingLocations);
|
#endregion
|
|
#region 自动库需要生成出库任务
|
//生成任务
|
//List<string> endAreas = new List<string>();
|
//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 调算法获取分拣明细
|
/// <summary>
|
///调算法获取分拣明细
|
/// </summary>
|
/// <param name="sortingEntity"></param>
|
/// <param name="user"></param>
|
/// <returns></returns>
|
public OperateResult GetSortingLocation(TN_WM_SORTING_LISTEntity sortingEntity, UserRuleEntity user)
|
{
|
try
|
{
|
List<TN_WM_SORTING_LOCATIONEntity> sortingLocationList = new List<TN_WM_SORTING_LOCATIONEntity>();
|
if (!sortingEntity.SortingDtlList.Any())
|
sortingEntity.SortingDtlList = BLLCreator.CreateDapper<TN_WM_SORTING_DTLEntity>().GetList(new
|
{
|
CN_S_SORTING_NO = sortingEntity.CN_S_SORTING_NO
|
});
|
//初始化调用算法数据
|
List<itemQueryClass> 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<Out_AlgorBLL>().OutNew(new OutAlgorEnitty()
|
{
|
lstDevice = new List<Device>(),
|
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<TN_WMS_ITEMDAL>().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
|
|
|
|
}
|
}
|