using HH.WMS.BLL.Algorithm;
|
using HH.WMS.BLL.Basic;
|
using HH.WMS.BLL.External;
|
using HH.WMS.BLL.Interface;
|
using HH.WMS.Common;
|
using HH.WMS.Common.Algorithm;
|
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.Dto;
|
using HH.WMS.Entitys.Entitys;
|
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 OutStockBLL : DapperBaseBLL
|
{
|
#region 发货通知单主表-分页
|
/// <summary>
|
/// 发货通知单主表-分页
|
/// </summary>
|
/// <param name="param"></param>
|
/// <param name="total"></param>
|
/// <returns></returns>
|
public DataTable GetOutList(OutSearchDto param, out long total)
|
{
|
return CreateDAL<OutStockDAL>().GetOutList(param, out total);
|
}
|
#endregion
|
|
#region 获取出库主子表
|
/// <summary>
|
/// 获取出库主子表
|
/// </summary>
|
/// <param name="CN_S_OP_NO"></param>
|
/// <returns></returns>
|
public TN_WM_OUT_MSTEntity GetOutMstAndDtl(string CN_S_OP_NO)
|
{
|
TN_WM_OUT_MSTEntity outMst = CreateDapperDAL<TN_WM_OUT_MSTEntity>().GetSingleEntity(new { CN_S_OP_NO = CN_S_OP_NO });
|
List<TN_WM_OUT_DTLEntity> outDtlList = CreateDapperDAL<TN_WM_OUT_DTLEntity>().GetList(new { CN_S_OP_NO = CN_S_OP_NO });
|
outMst.OutDtlList = outDtlList;
|
return outMst;
|
}
|
#endregion
|
|
#region 根据出库单上升仓库量表分配量
|
/// <summary>
|
/// 根据出库单上升仓库量表分配量
|
/// </summary>
|
/// <param name="outMst"></param>
|
/// <returns></returns>
|
public List<TN_WM_B_STOCK_QTYEntity> AddOrDropStockAllocQtyByOut(TN_WM_OUT_MSTEntity outMst, BatchType batchType)
|
{
|
if (outMst.OutDtlList == null || !outMst.OutDtlList.Any())
|
throw new Exception("批分物料行不可为空");
|
|
var stockQty = CreateDapperDAL<TN_WM_B_STOCK_QTYEntity>().GetList(new
|
{
|
CN_S_ITEM_CODE = outMst.OutDtlList.Select(s => s.CN_S_ITEM_CODE).ToList()
|
});
|
if (!stockQty.Any())
|
throw new Exception("仓库中未找到单据:" + outMst.CN_S_OP_NO + "的物料");
|
|
foreach (var dtl in outMst.OutDtlList)
|
{
|
var qty = dtl.CN_F_QUANTITY;
|
var currentItemQty = stockQty.FindAll(f => f.CN_S_ITEM_CODE == dtl.CN_S_ITEM_CODE);
|
|
switch (batchType)
|
{
|
case BatchType.Add:
|
|
#region 上升分配量
|
|
foreach (var stock in currentItemQty)
|
{
|
var sQty = stock.CN_F_QUANTITY - stock.CN_F_EDITING_QTY - stock.CN_F_ALLOC_QTY;
|
|
if (sQty == 0) continue;
|
if (qty == 0) break;
|
|
if (sQty >= qty)
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY += qty;
|
qty = 0;
|
}
|
else
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY += sQty;
|
qty -= sQty;
|
}
|
}
|
if (qty > 0)
|
{
|
throw new Exception("仓库中物料:" + dtl.CN_S_ITEM_CODE + "库存量不足");
|
}
|
|
#endregion
|
|
break;
|
|
case BatchType.Drop:
|
|
#region 下降分配量
|
|
foreach (var stock in currentItemQty)
|
{
|
var aQty = stock.CN_F_ALLOC_QTY;
|
|
if (aQty == 0) continue;
|
if (qty == 0) break;
|
|
if (aQty >= qty)
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY -= qty;
|
qty = 0;
|
}
|
else
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY -= aQty;
|
qty -= aQty;
|
}
|
}
|
if (qty > 0)
|
{
|
throw new Exception("仓库中物料:" + dtl.CN_S_ITEM_CODE + "分配量不足");
|
}
|
|
#endregion
|
|
break;
|
default:
|
throw new Exception("批分参数错误");
|
}
|
|
}
|
return stockQty.FindAll(f => f.Update);
|
}
|
#endregion
|
|
#region 根据分拣单明细上升仓库量表分配量
|
/// <summary>
|
/// 根据出库单上升仓库量表分配量
|
/// </summary>
|
/// <param name="outMst"></param>
|
/// <returns></returns>
|
public List<TN_WM_B_STOCK_QTYEntity> AddOrDropStockAllocQtyBySorting(List<TN_WM_SORTING_LOCATIONEntity> sortingLocations, BatchType batchType)
|
{
|
if (sortingLocations == null || !sortingLocations.Any())
|
throw new Exception("AddOrDropStockAllocQtyBySorting 批分物料不可为空");
|
|
//仓库物料,批次空的放前面
|
var stockQty = CreateDapperDAL<TN_WM_B_STOCK_QTYEntity>().GetList(new
|
{
|
CN_S_ITEM_CODE = sortingLocations.Select(s => s.CN_S_ITEM_CODE).ToList()
|
}).Select(x => new
|
{
|
index = string.IsNullOrEmpty(x.CN_S_PRODUCTION_BATCH) ? 0 : 1,
|
x
|
}).OrderBy(o => o.index).Select(m => m.x).ToList();
|
if (!stockQty.Any())
|
throw new Exception("仓库中未找到物料:" + string.Join(",", sortingLocations.Select(s => s.CN_S_ITEM_CODE)));
|
|
sortingLocations = sortingLocations.GroupBy(g => new
|
{
|
g.CN_S_ITEM_CODE,
|
g.CN_S_PRODUCTION_BATCH
|
}).Select(s => new TN_WM_SORTING_LOCATIONEntity()
|
{
|
CN_S_ITEM_CODE = s.Key.CN_S_ITEM_CODE,
|
CN_S_PRODUCTION_BATCH = s.Key.CN_S_PRODUCTION_BATCH,
|
CN_F_QUANTITY = s.Sum(m => m.CN_F_QUANTITY)
|
}).ToList();
|
|
foreach (var dtl in sortingLocations)
|
{
|
var qty = dtl.CN_F_QUANTITY;
|
var currentItemQty = stockQty.FindAll(f => f.CN_S_ITEM_CODE == dtl.CN_S_ITEM_CODE &&
|
(string.IsNullOrEmpty(dtl.CN_S_PRODUCTION_BATCH) || dtl.CN_S_PRODUCTION_BATCH == f.CN_S_PRODUCTION_BATCH));
|
|
switch (batchType)
|
{
|
case BatchType.Add:
|
|
#region 上升分配量
|
|
foreach (var stock in currentItemQty)
|
{
|
var sQty = stock.CN_F_QUANTITY - stock.CN_F_EDITING_QTY - stock.CN_F_ALLOC_QTY;
|
|
if (sQty == 0) continue;
|
if (qty == 0) break;
|
|
if (sQty >= qty)
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY += qty;
|
qty = 0;
|
}
|
else
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY += sQty;
|
qty -= sQty;
|
}
|
}
|
if (qty > 0)
|
{
|
throw new Exception("仓库中物料:" + dtl.CN_S_ITEM_CODE + "库存量不足");
|
}
|
|
#endregion
|
|
break;
|
|
case BatchType.Drop:
|
|
#region 下降分配量
|
|
foreach (var stock in currentItemQty)
|
{
|
var aQty = stock.CN_F_ALLOC_QTY;
|
|
if (aQty == 0) continue;
|
if (qty == 0) break;
|
|
if (aQty >= qty)
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY -= qty;
|
stock.CN_F_QUANTITY -= qty;
|
qty = 0;
|
}
|
else
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY -= aQty;
|
stock.CN_F_QUANTITY -= aQty;
|
qty -= aQty;
|
}
|
}
|
if (qty > 0)
|
{
|
throw new Exception("仓库中物料:" + dtl.CN_S_ITEM_CODE + "分配量不足");
|
}
|
|
#endregion
|
|
break;
|
default:
|
throw new Exception("批分参数错误");
|
}
|
|
}
|
return stockQty.FindAll(f => f.Update);
|
}
|
#endregion
|
|
#region 根据分拣单明细上升库区量表分配量
|
/// <summary>
|
/// 根据出库单上升仓库量表分配量
|
/// </summary>
|
/// <param name="outMst"></param>
|
/// <returns></returns>
|
public List<TN_WM_B_AREA_QTYEntity> AddOrDropAreaAllocQtyBySorting(List<TN_WM_SORTING_LOCATIONEntity> sortingLocations, BatchType batchType)
|
{
|
if (sortingLocations == null || !sortingLocations.Any())
|
throw new Exception("AddOrDropAreaAllocQtyBySorting 批分物料不可为空");
|
|
//仓库物料,批次空的放前面
|
var areaQty = CreateDapperDAL<TN_WM_B_AREA_QTYEntity>().GetList(new
|
{
|
CN_S_STOCK_AREA = sortingLocations.Select(s => s.CN_S_AREA_CODE).ToList(),
|
CN_S_ITEM_CODE = sortingLocations.Select(s => s.CN_S_ITEM_CODE).ToList()
|
}).Select(x => new
|
{
|
index = string.IsNullOrEmpty(x.CN_S_PRODUCTION_BATCH) ? 0 : 1,
|
x
|
}).OrderBy(o => o.index).Select(m => m.x).ToList();
|
if (!areaQty.Any())
|
throw new Exception("库区中未找到物料:" + string.Join(",", sortingLocations.Select(s => s.CN_S_ITEM_CODE)));
|
|
sortingLocations = sortingLocations.GroupBy(g => new
|
{
|
g.CN_S_ITEM_CODE,
|
g.CN_S_AREA_CODE,
|
g.CN_S_PRODUCTION_BATCH
|
}).Select(s => new TN_WM_SORTING_LOCATIONEntity()
|
{
|
CN_S_AREA_CODE = s.Key.CN_S_AREA_CODE,
|
CN_S_ITEM_CODE = s.Key.CN_S_ITEM_CODE,
|
CN_S_PRODUCTION_BATCH = s.Key.CN_S_PRODUCTION_BATCH,
|
CN_F_QUANTITY = s.Sum(m => m.CN_F_QUANTITY)
|
}).ToList();
|
|
foreach (var dtl in sortingLocations)
|
{
|
var qty = dtl.CN_F_QUANTITY;
|
var currentItemQty = areaQty.FindAll(f => f.CN_S_ITEM_CODE == dtl.CN_S_ITEM_CODE
|
&& dtl.CN_S_AREA_CODE == f.CN_S_STOCK_AREA &&
|
(string.IsNullOrEmpty(dtl.CN_S_PRODUCTION_BATCH) || dtl.CN_S_PRODUCTION_BATCH == f.CN_S_PRODUCTION_BATCH));
|
|
switch (batchType)
|
{
|
case BatchType.Add:
|
|
#region 上升分配量
|
|
foreach (var stock in currentItemQty)
|
{
|
var sQty = stock.CN_F_QUANTITY - stock.CN_F_ALLOC_QTY;
|
|
if (sQty == 0) continue;
|
if (qty == 0) break;
|
|
if (sQty >= qty)
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY += qty;
|
qty = 0;
|
}
|
else
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY += sQty;
|
qty -= sQty;
|
}
|
}
|
if (qty > 0)
|
{
|
throw new Exception("库区中物料:" + dtl.CN_S_ITEM_CODE + "库存量不足");
|
}
|
|
#endregion
|
|
break;
|
|
case BatchType.Drop:
|
|
#region 下降分配量
|
|
foreach (var stock in currentItemQty)
|
{
|
var aQty = stock.CN_F_ALLOC_QTY;
|
|
if (aQty == 0) continue;
|
if (qty == 0) break;
|
|
if (aQty >= qty)
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY -= qty;
|
stock.CN_F_QUANTITY -= qty;
|
qty = 0;
|
}
|
else
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY -= aQty;
|
stock.CN_F_QUANTITY -= aQty;
|
qty -= aQty;
|
}
|
}
|
if (qty > 0)
|
{
|
throw new Exception("库区中物料:" + dtl.CN_S_ITEM_CODE + "分配量不足");
|
}
|
|
#endregion
|
|
break;
|
default:
|
throw new Exception("批分参数错误");
|
}
|
|
}
|
return areaQty.FindAll(f => f.Update);
|
}
|
#endregion
|
|
#region 下架记录
|
/// <summary>
|
/// 下架记录
|
/// </summary>
|
/// <param name="sl"></param>
|
/// <param name="qty"></param>
|
/// <returns></returns>
|
private TN_WM_DOWN_HISTORYEntity GetDownHistory(TN_WM_SORTING_LOCATIONEntity sl, decimal qty)
|
{
|
return new TN_WM_DOWN_HISTORYEntity
|
{
|
CN_GUID = Guid.NewGuid().ToString(),
|
CN_S_LOCATION_CODE = sl.CN_S_LOCATION_CODE,
|
CN_S_ITEM_STATE = sl.CN_S_ITEM_STATE,
|
CN_S_TRAY_CODE = sl.CN_S_TRAY_CODE,
|
CN_S_TRAY_GRID = sl.CN_S_TRAY_GRID,
|
CN_S_ITEM_CODE = sl.CN_S_ITEM_CODE,
|
CN_S_ITEM_NAME = sl.CN_S_ITEM_NAME,
|
CN_S_PRODUCTION_BATCH = sl.CN_S_LOT_NO,
|
CN_F_QUANTITY = qty,
|
CN_S_MODEL = sl.CN_S_MODEL,
|
CN_S_STOCK_AREA = sl.CN_S_AREA_CODE,
|
CN_S_STOCK_CODE = sl.CN_S_STOCK_CODE,
|
CN_T_CREATE = DateTime.Now,
|
CN_T_MODIFY = DateTime.Now,
|
CN_S_OWNER = "",
|
CN_S_MEASURE_UNIT = "",
|
CN_S_CREATOR = userInfo.CN_S_LOGIN,
|
CN_S_CREATOR_BY = userInfo.CN_S_NAME,
|
CN_S_MODIFY = "",
|
CN_S_MODIFY_BY = "",
|
CN_S_OP_FROM = "分拣完成-" + sl.CN_S_SORTING_NO,
|
//CN_S_EXT1 = uniqueCode //executeStatePara.uniqueCodes
|
};
|
}
|
#endregion
|
|
#region 根据分拣单明细上升托盘物料关联表分配量
|
/// <summary>
|
/// 根据分拣单明细上升托盘物料关联表分配量
|
/// </summary>
|
/// <param name="sortingLocations"></param>
|
/// <param name="batchType"></param>
|
/// <returns></returns>
|
public List<TN_WM_B_TRAY_ITEM_MSTEntity> AddOrDropTrayAllocQtyBySorting(List<TN_WM_SORTING_LOCATIONEntity> sortingLocations, BatchType batchType)
|
{
|
if (sortingLocations == null || !sortingLocations.Any())
|
throw new Exception("AddOrDropTrayAllocQtyBySorting 批分物料不可为空");
|
|
//仓库物料,批次空的放前面
|
var trayQty = CreateDapperDAL<TN_WM_B_TRAY_ITEM_MSTEntity>().GetList(new
|
{
|
CN_S_ITEM_CODE = sortingLocations.Select(s => s.CN_S_ITEM_CODE).ToList()
|
}).Select(x => new
|
{
|
index = string.IsNullOrEmpty(x.CN_S_PRODUCTION_BATCH) ? 0 : 1,
|
x
|
}).OrderBy(o => o.index).Select(m => m.x).ToList();
|
if (!trayQty.Any())
|
throw new Exception("托盘中未找到物料:" + string.Join(",", sortingLocations.Select(s => s.CN_S_ITEM_CODE)));
|
|
//sortingLocations = sortingLocations.GroupBy(g => new
|
//{
|
// g.CN_S_ITEM_CODE,
|
// g.CN_S_TRAY_CODE,
|
// g.CN_S_PRODUCTION_BATCH
|
//}).Select(s => new TN_WM_SORTING_LOCATIONEntity()
|
//{
|
// CN_S_ITEM_CODE = s.Key.CN_S_ITEM_CODE,
|
// CN_S_TRAY_CODE = s.Key.CN_S_TRAY_CODE,
|
// CN_S_PRODUCTION_BATCH = s.Key.CN_S_PRODUCTION_BATCH,
|
// CN_F_QUANTITY = s.Sum(m => m.CN_F_QUANTITY)
|
//}).ToList();
|
|
foreach (var dtl in sortingLocations)
|
{
|
var qty = dtl.CN_F_QUANTITY;
|
var currentItemQty = trayQty.FindAll(f => f.CN_S_ITEM_CODE == dtl.CN_S_ITEM_CODE &&
|
f.CN_S_TRAY_CODE == dtl.CN_S_TRAY_CODE);
|
|
switch (batchType)
|
{
|
case BatchType.Add:
|
|
#region 上升分配量
|
|
foreach (var stock in currentItemQty)
|
{
|
var sQty = stock.CN_F_QUANTITY - stock.CN_F_ALLOC_QTY;
|
|
if (sQty == 0) continue;
|
if (qty == 0) break;
|
|
if (sQty >= qty)
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY += qty;
|
qty = 0;
|
}
|
else
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY += sQty;
|
qty -= sQty;
|
}
|
}
|
if (qty > 0)
|
{
|
throw new Exception("托盘中物料:" + dtl.CN_S_ITEM_CODE + "库存量不足");
|
}
|
|
#endregion
|
|
break;
|
|
case BatchType.Drop:
|
|
#region 下降分配量
|
|
foreach (var stock in currentItemQty)
|
{
|
var aQty = stock.CN_F_ALLOC_QTY;
|
|
if (aQty == 0) continue;
|
if (qty == 0) break;
|
|
if (aQty >= qty)
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY -= qty;
|
stock.CN_F_QUANTITY -= qty;
|
qty = 0;
|
}
|
else
|
{
|
stock.Update = true;
|
stock.CN_F_ALLOC_QTY -= aQty;
|
stock.CN_F_QUANTITY -= aQty;
|
qty -= aQty;
|
}
|
}
|
if (qty > 0)
|
{
|
throw new Exception("托盘中物料:" + dtl.CN_S_ITEM_CODE + "分配量不足");
|
}
|
|
#endregion
|
|
break;
|
default:
|
throw new Exception("批分参数错误");
|
}
|
|
}
|
return trayQty.FindAll(f => f.Update);
|
}
|
#endregion
|
|
#region 出库订单新增
|
/// <summary>
|
/// 出库订单新增
|
/// </summary>
|
/// <param name="outMst"></param>
|
/// <returns></returns>
|
public OperateResult AddOut(TN_WM_OUT_MSTEntity outMst)
|
{
|
return UseTransaction(trans =>
|
{
|
//新增主表
|
CreateDapperDAL<TN_WM_OUT_MSTEntity>().Add(outMst, trans);
|
//新增子表
|
CreateDapperDAL<TN_WM_OUT_DTLEntity>().AddRange(outMst.OutDtlList, trans);
|
//升仓库分配量
|
});
|
}
|
#endregion
|
|
#region 出库订单修改
|
/// <summary>
|
/// 出库订单修改
|
/// </summary>
|
/// <param name="outMst"></param>
|
/// <returns></returns>
|
public OperateResult UpdateOut(TN_WM_OUT_MSTEntity outMst)
|
{
|
return UseTransaction(trans =>
|
{
|
//修改主表
|
CreateDapperDAL<TN_WM_OUT_MSTEntity>().Update(outMst, new { CN_S_OP_NO = outMst.CN_S_OP_NO }, trans);
|
//删除子表
|
CreateDapperDAL<TN_WM_OUT_DTLEntity>().Delete(new { CN_S_OP_NO = outMst.CN_S_OP_NO }, trans);
|
//新增子表
|
CreateDapperDAL<TN_WM_OUT_DTLEntity>().AddRange(outMst.OutDtlList, trans);
|
});
|
}
|
#endregion
|
|
#region 删除出库订单
|
/// <summary>
|
/// 删除出库订单
|
/// </summary>
|
/// <param name="opNo"></param>
|
/// <returns></returns>
|
public OperateResult DeleteOut(string opNo)
|
{
|
return UseTransaction(trans =>
|
{
|
//删除出库订单主表
|
CreateDapperDAL<TN_WM_OUT_MSTEntity>().Delete(new { CN_S_OP_NO = opNo }, trans);
|
//删除出库订单子表
|
CreateDapperDAL<TN_WM_OUT_DTLEntity>().Delete(new { CN_S_OP_NO = opNo }, trans);
|
});
|
}
|
#endregion
|
|
#region 提交出库订单
|
/// <summary>
|
/// 提交出库订单
|
/// </summary>
|
/// <param name="outMst"></param>
|
/// <param name="sortingList"></param>
|
/// <returns></returns>
|
public OperateResult SubmitOut(TN_WM_OUT_MSTEntity outMst, TN_WM_SORTING_LISTEntity sortingEntity)
|
{
|
#region 上升仓库、库区、托盘 分配量
|
|
var sortingLocations = sortingEntity.SortingLocationList;
|
//上升仓库量表分配量
|
var addStockAlloc = AddOrDropStockAllocQtyBySorting(sortingLocations, BatchType.Add);
|
//上升库区量表分配量
|
var addAreaAlloc = AddOrDropAreaAllocQtyBySorting(sortingLocations, BatchType.Add);
|
//上升托盘关联表分配量
|
var addTrayAlloc = AddOrDropTrayAllocQtyBySorting(sortingLocations, BatchType.Add);
|
|
#endregion
|
|
return UseTransaction(trans =>
|
{
|
//分拣单主表
|
CreateDapperDAL<TN_WM_SORTING_LISTEntity>().Add(sortingEntity, trans);
|
|
//分拣单子表
|
CreateDapperDAL<TN_WM_SORTING_DTLEntity>().AddRange(sortingEntity.SortingDtlList, trans);
|
//分拣明细表
|
CreateDapperDAL<TN_WM_SORTING_LOCATIONEntity>().AddRange(sortingEntity.SortingLocationList, trans);
|
//锁货位 预出库锁定
|
sortingEntity.SortingLocationList.ForEach(m =>
|
{
|
CreateDapperDAL<TN_WM_LOCATION_EXTEntity>().Update(new
|
{
|
CN_S_LOCATION_STATE = Constants.Location_State_OutLock
|
}, new
|
{
|
CN_S_LOCATION_CODE = m.CN_S_LOCATION_CODE
|
}, trans);
|
});
|
|
//修改出库单表属性
|
CreateDapperDAL<TN_WM_OUT_MSTEntity>().Update(new
|
{
|
CN_S_STATE = "待分拣",
|
CN_T_MODIFY = DateTime.Now,
|
}, new
|
{
|
CN_S_OP_NO = outMst.CN_S_OP_NO
|
}, trans);
|
//升仓库分配量
|
addStockAlloc.ForEach(e =>
|
{
|
if (CreateDAL<OutStockDAL>().UpdateStockAllocQty(e, trans).AffectedRows == 0)
|
throw new Exception("时间戳被更新,修改仓库分配量失败");
|
});
|
//升库区分配量
|
addAreaAlloc.ForEach(e =>
|
{
|
if (CreateDAL<OutStockDAL>().UpdateAreaAlloc(e, trans).AffectedRows == 0)
|
throw new Exception("时间戳被更新,修改库区分配量失败");
|
});
|
//升托盘物料关联表分配量
|
addTrayAlloc.ForEach(e =>
|
{
|
if (CreateDAL<OutStockDAL>().UpdateTrayItemAllocQty(e, trans).AffectedRows == 0)
|
throw new Exception("时间戳被更新,修改托盘物料关联表分配量失败");
|
});
|
});
|
}
|
#endregion
|
|
#region 获取波次实体
|
/// <summary>
|
/// 获取波次实体
|
/// </summary>
|
/// <param name="waveNo"></param>
|
/// <param name="outMst"></param>
|
/// <param name="user"></param>
|
/// <returns></returns>
|
private TN_WM_WAVE_MSTEntity GetWaveEntity(TN_WM_OUT_MSTEntity outMst)
|
{
|
var user = userInfo;
|
TN_WM_WAVE_MSTEntity waveMstEntity = new TN_WM_WAVE_MSTEntity()
|
{
|
CN_S_CREATE_TYPE = Constants.CreateType_Manual,
|
CN_S_WAVE_NO = outMst.CN_S_WAVE_CODE,
|
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 = user.CN_S_NAME,
|
CN_S_CREATOR_BY = user.CN_S_LOGIN,
|
CN_S_MODIFY = user.CN_S_NAME,
|
CN_S_MODIFY_BY = user.CN_S_LOGIN,
|
CN_C_NEED_SEEDING = Constants.Y,
|
CN_S_STATUS = Constants.State_New,
|
CN_S_SEEDING_MODE = "",
|
CN_S_STOCK_CODE = outMst.CN_S_STOCK_CODE
|
};
|
waveMstEntity.WaveDtlList = new List<TN_WM_WAVE_DTLEntity>();
|
int index = 1;
|
|
TN_WM_WAVE_DTLEntity waveDtlEntity = new TN_WM_WAVE_DTLEntity()
|
{
|
CN_GUID = Guid.NewGuid().ToString(),
|
CN_S_WAVE_NO = outMst.CN_S_WAVE_CODE,
|
CN_S_ORDER_NO = outMst.CN_S_OP_NO,
|
CN_S_STATE = Constants.State_New,
|
CN_T_CREATE = DateTime.Now,
|
CN_T_MODIFY = DateTime.Now,
|
CN_S_CREATOR = user.CN_S_NAME,
|
CN_S_CREATOR_BY = user.CN_S_LOGIN,
|
CN_S_MODIFY = user.CN_S_NAME,
|
CN_S_MODIFY_BY = user.CN_S_LOGIN,
|
CN_S_MSTGUID = waveMstEntity.CN_GUID,
|
CN_N_ORDER = index++
|
};
|
waveMstEntity.WaveDtlList.Add(waveDtlEntity);
|
return waveMstEntity;
|
}
|
#endregion
|
|
#region 取货位分拣中的物料
|
/// <summary>
|
/// 取货位分拣中的物料
|
/// </summary>
|
/// <param name="locationCode"></param>
|
/// <returns></returns>
|
public List<TN_WM_SORTING_LOCATIONEntity> GetSortingLocation(string locationCode)
|
{
|
return CreateDAL<OutStockDAL>().GetSortingLocation(locationCode);
|
}
|
#endregion
|
|
#region 分拣货位生成任务
|
/// <summary>
|
/// 分拣货位生成任务
|
/// </summary>
|
/// <param name="sortingLocations"></param>
|
/// <returns></returns>
|
public OperateResult ExecuteSortingTask(List<TN_WM_SORTING_LOCATIONEntity> sortingLocations)
|
{
|
//所有库区
|
var allArea = BLLCreator.Create<TN_AB_B_STOCK_AREABLL>().GetArea(4, sortingLocations[0].CN_S_STOCK_CODE);
|
|
//生成出库任务号
|
UserRuleEntity user = new UserRuleEntity()
|
{
|
RuleCode = Constants.TaskNo_Out
|
};
|
|
//生成出库任务
|
var tasks = new List<TN_WM_TASKEntity>();
|
foreach (var s in sortingLocations)
|
{
|
var startArea = allArea.Find(f => f.CN_S_AREA_CODE == Util.ToString(s.CN_S_AREA_CODE).Trim());
|
if (startArea == null) return OperateResult.Error("mongo未找到库区:" + s.CN_S_AREA_CODE);
|
|
var endArea = allArea.Find(f => f.CN_S_AREA_CODE == Util.ToString(s.EndArea).Trim());
|
if (endArea == null) return OperateResult.Error("mongo未找到库区:" + s.EndArea);
|
|
string taskNo = user.GenerateNo();
|
if (string.IsNullOrEmpty(taskNo))
|
throw new Exception("生成出库任务号失败");
|
var task = new TN_WM_TASKEntity
|
{
|
CN_S_TASK_NO = taskNo,
|
CN_S_TRAY_CODE = s.CN_S_TRAY_CODE,
|
CN_S_START_BIT = s.CN_S_LOCATION_CODE,
|
CN_S_END_BIT = s.EndBit,
|
CN_S_STATE = Constants.TaskState_NoExecuted,
|
|
CN_S_STOCK_CODE = s.CN_S_STOCK_CODE,
|
CN_S_START_AREA = s.CN_S_AREA_CODE,
|
CN_S_END_AREA = s.EndArea,
|
CN_N_PRIORITY = 1,
|
CN_S_CREATOR = "sys",
|
CN_S_CREATOR_BY = "sys",
|
CN_T_CREATE = DateTime.Now,
|
CN_T_MODIFY = DateTime.Now,
|
CN_S_REMARK = "",
|
CN_S_TASK_TYPE = Constants.TaskType_SortingOut,
|
CN_C_START_IS_CONTROL_QTY = startArea.CN_C_IS_CONTROL_QTY,
|
CN_C_END_IS_CONTROL_QTY = endArea.CN_C_IS_CONTROL_QTY,
|
CN_S_START_CONTROL_INV = startArea.CN_C_IS_INVENTORY,
|
CN_S_END_CONTROL_INV = endArea.CN_C_IS_INVENTORY,
|
CN_S_START_AREA_TYPE = startArea.CN_S_AREA_CLASS,
|
CN_S_END_AREA_TYPE = endArea.CN_S_AREA_CLASS,
|
CN_S_FROM_OP = Constants.Rule_SortingNo
|
};
|
tasks.Add(task);
|
}
|
|
return UseTransaction(trans =>
|
{
|
sortingLocations.ForEach(e =>
|
{
|
CreateDapperDAL<TN_WM_SORTING_LOCATIONEntity>().Update(new
|
{
|
CN_B_SEND = true
|
}, new
|
{
|
CN_S_SORTING_NO = e.CN_S_SORTING_NO,
|
CN_S_LOCATION_CODE = e.CN_S_LOCATION_CODE
|
}, trans);
|
});
|
tasks.ForEach(taskEntity =>
|
{
|
//锁货位,发任务
|
LockLocationAndSendAms(taskEntity, trans);
|
});
|
});
|
}
|
#endregion
|
|
#region 保存分拣
|
/// <summary>
|
/// 保存分拣
|
/// </summary>
|
/// <param name="sortingLocations"></param>
|
/// <returns></returns>
|
public OperateResult SaveSortingLocation(string startLocationCode, List<TN_WM_SORTING_LOCATIONEntity> sortingLocations)
|
{
|
#region 装载分拣数据
|
//分拣单
|
string sortingNo = sortingLocations[0].CN_S_SORTING_NO;
|
//分拣单实体
|
var sortingEntity = BLLCreator.CreateDapper<TN_WM_SORTING_LISTEntity>().GetSingleEntity(new
|
{
|
CN_S_SORTING_NO = sortingNo
|
});
|
if (sortingEntity == null) return OperateResult.Error("未找到分拣单:" + sortingNo);
|
//该分拣单的所有分拣明细
|
var all = BLLCreator.CreateDapper<TN_WM_SORTING_LOCATIONEntity>().GetList(new
|
{
|
CN_S_SORTING_NO = sortingNo
|
});
|
//不包括本次的分拣明细
|
var other = all.FindAll(f => !sortingLocations.Select(ss => ss.CN_GUID).Contains(f.CN_GUID));
|
|
#endregion
|
|
var taskEntity = new TN_WM_TASKEntity();
|
if (sortingLocations[0].CN_S_NEED_SORT == Constants.Y)
|
{
|
#region 生成入库任务
|
//调用算法计算终点货位
|
string endLocationCode = string.Empty;
|
//调用入库算法,获取空货位
|
InAlgorEnitty iAe = new InAlgorEnitty()
|
{
|
stockAreaCode = sortingLocations[0].CN_S_AREA_CODE,
|
logicCode = "",
|
locationQty = 1,
|
trayCode = sortingLocations[0].CN_S_TRAY_CODE,
|
itemCode = "",
|
lockLocation = false//是否需要锁定货位
|
};
|
iAe.lstDevice = null;
|
InResultEntity irEresult = BLLCreator.Create<In_AlgorBLL>().In(iAe);
|
if (!irEresult.Success)
|
{
|
return OperateResult.Error(irEresult.Msg);//货位获取失败!
|
}
|
else
|
{
|
endLocationCode = irEresult.lstLocation[0].locationCode.ToString();
|
}
|
|
var startLocation = BLLCreator.CreateDapper<TN_WM_LOCATION_EXTEntity>().GetSingleEntity(new
|
{
|
CN_S_LOCATION_CODE = startLocationCode
|
});
|
if (startLocation == null) return OperateResult.Error("未找到货位:" + startLocationCode);
|
|
//所有库区
|
var allArea = BLLCreator.Create<TN_AB_B_STOCK_AREABLL>().GetArea(4, sortingEntity.CN_S_STOCK_CODE);
|
|
var startArea = allArea.Find(f => f.CN_S_AREA_CODE == Util.ToString(startLocation.CN_S_AREA_CODE).Trim());
|
if (startArea == null) return OperateResult.Error("mongo未找到库区:" + startLocation.CN_S_AREA_CODE);
|
var endArea = allArea.Find(f => f.CN_S_AREA_CODE == Util.ToString(sortingLocations[0].CN_S_AREA_CODE).Trim());
|
if (endArea == null) return OperateResult.Error("mongo未找到库区:" + sortingLocations[0].CN_S_AREA_CODE);
|
|
//生成入库任务号
|
UserRuleEntity user = new UserRuleEntity()
|
{
|
RuleCode = Constants.TaskNo_In
|
};
|
string taskNo = user.GenerateNo();
|
if (string.IsNullOrEmpty(taskNo))
|
throw new Exception("生产入库任务号失败");
|
var s = sortingLocations[0];
|
taskEntity = new TN_WM_TASKEntity
|
{
|
CN_S_TASK_NO = taskNo,
|
CN_S_TRAY_CODE = s.CN_S_TRAY_CODE,
|
CN_S_START_BIT = startLocation.CN_S_LOCATION_CODE,
|
CN_S_END_BIT = endLocationCode,
|
CN_S_STATE = Constants.TaskState_NoExecuted,
|
|
CN_S_STOCK_CODE = sortingEntity.CN_S_STOCK_CODE,
|
CN_S_START_AREA = startLocation.CN_S_AREA_CODE,
|
CN_S_END_AREA = sortingLocations[0].CN_S_AREA_CODE,
|
CN_N_PRIORITY = 1,
|
CN_S_CREATOR = userInfo.CN_S_LOGIN,
|
CN_S_CREATOR_BY = userInfo.CN_S_NAME,
|
CN_T_CREATE = DateTime.Now,
|
CN_T_MODIFY = DateTime.Now,
|
CN_S_REMARK = "",
|
CN_S_TASK_TYPE = Constants.TaskType_SortingIn,
|
CN_C_START_IS_CONTROL_QTY = startArea.CN_C_IS_CONTROL_QTY,
|
CN_C_END_IS_CONTROL_QTY = endArea.CN_C_IS_CONTROL_QTY,
|
CN_S_START_CONTROL_INV = startArea.CN_C_IS_INVENTORY,
|
CN_S_END_CONTROL_INV = endArea.CN_C_IS_INVENTORY,
|
CN_S_START_AREA_TYPE = startArea.CN_S_AREA_CLASS,
|
CN_S_END_AREA_TYPE = endArea.CN_S_AREA_CLASS,
|
CN_S_FROM_OP = Constants.Rule_SortingNo
|
};
|
#endregion
|
}
|
|
//下降托盘关联表分配量
|
var dropTrayAlloc = AddOrDropTrayAllocQtyBySorting(sortingLocations, BatchType.Drop);
|
|
//下架记录
|
var downHistory = sortingLocations.Select(sl => new TN_WM_DOWN_HISTORYEntity
|
{
|
CN_GUID = Guid.NewGuid().ToString(),
|
CN_S_LOCATION_CODE = sl.CN_S_LOCATION_CODE,
|
CN_S_ITEM_STATE = sl.CN_S_ITEM_STATE,
|
CN_S_TRAY_CODE = sl.CN_S_TRAY_CODE,
|
CN_S_TRAY_GRID = sl.CN_S_TRAY_GRID,
|
CN_S_ITEM_CODE = sl.CN_S_ITEM_CODE,
|
CN_S_ITEM_NAME = sl.CN_S_ITEM_NAME,
|
CN_S_PRODUCTION_BATCH = sl.CN_S_PRODUCTION_BATCH,
|
CN_F_QUANTITY = sl.CN_F_QUANTITY,
|
CN_S_MODEL = sl.CN_S_MODEL,
|
CN_S_STOCK_AREA = sl.CN_S_AREA_CODE,
|
CN_S_STOCK_CODE = sortingEntity.CN_S_STOCK_CODE,
|
CN_T_CREATE = DateTime.Now,
|
CN_T_MODIFY = DateTime.Now,
|
CN_S_OWNER = "",
|
CN_S_MEASURE_UNIT = sl.CN_S_MEASURE_UNIT,
|
CN_S_CREATOR = userInfo.CN_S_LOGIN,
|
CN_S_CREATOR_BY = userInfo.CN_S_NAME,
|
CN_S_MODIFY = "",
|
CN_S_MODIFY_BY = "",
|
CN_S_OP_FROM = "分拣完成-" + sl.CN_S_SORTING_NO,
|
//CN_S_EXT1 = uniqueCode //executeStatePara.uniqueCodes
|
}).ToList();
|
|
|
var dropStockAlloc = new List<TN_WM_B_STOCK_QTYEntity>();
|
var dropAreaAlloc = new List<TN_WM_B_AREA_QTYEntity>();
|
if (!other.Exists(e => e.CN_F_PICKED_QTY == 0))
|
{
|
//下降仓库量表分配量
|
dropStockAlloc = AddOrDropStockAllocQtyBySorting(all, BatchType.Drop);
|
//下降库区量表分配量
|
dropAreaAlloc = AddOrDropAreaAllocQtyBySorting(all, BatchType.Drop);
|
}
|
return UseTransaction(trans =>
|
{
|
sortingLocations.ForEach(e =>
|
{
|
CreateDapperDAL<TN_WM_SORTING_LOCATIONEntity>().Update(new
|
{
|
CN_F_PICKED_QTY = e.CN_F_QUANTITY
|
}, new
|
{
|
CN_GUID = e.CN_GUID
|
}, trans);
|
});
|
|
//降托盘物料关联表分配量
|
dropTrayAlloc.ForEach(e =>
|
{
|
if (CreateDAL<OutStockDAL>().UpdateTrayItemAllocQty(e, trans).AffectedRows == 0)
|
throw new Exception("时间戳被更新,修改托盘物料关联表分配量失败");
|
});
|
//下架记录
|
CreateDapperDAL<TN_WM_DOWN_HISTORYEntity>().AddRange(downHistory, trans);
|
|
//已分拣完
|
if (!other.Exists(e => e.CN_F_PICKED_QTY == 0))
|
{
|
//出库单置为已完成
|
CreateDapperDAL<TN_WM_OUT_MSTEntity>().Update(new
|
{
|
CN_S_STATE = Constants.State_Completed
|
}, new
|
{
|
CN_S_OP_NO = sortingEntity.CN_S_FROM_NO
|
}, trans);
|
|
//分拣单置为已分拣
|
CreateDapperDAL<TN_WM_SORTING_LISTEntity>().Update(new
|
{
|
CN_S_STATE = Constants.Sorting_Sorted
|
}, new
|
{
|
CN_S_SORTING_NO = sortingNo
|
}, trans);
|
|
//降仓库分配量
|
dropStockAlloc.ForEach(e =>
|
{
|
if (CreateDAL<OutStockDAL>().UpdateStockAllocQty(e, trans).AffectedRows == 0)
|
throw new Exception("时间戳被更新,修改仓库分配量失败");
|
});
|
|
//降库区分配量
|
dropAreaAlloc.ForEach(e =>
|
{
|
if (CreateDAL<OutStockDAL>().UpdateAreaAlloc(e, trans).AffectedRows == 0)
|
throw new Exception("时间戳被更新,修改库区分配量失败");
|
});
|
}
|
|
if (sortingLocations[0].CN_S_NEED_SORT == Constants.Y)
|
{
|
//锁货位,发任务
|
LockLocationAndSendAms(taskEntity, trans, true);
|
}
|
else
|
{
|
CreateDapperDAL<TN_WM_B_TRAY_LOCATIONEntity>().Delete(new
|
{
|
CN_S_LOCATION_CODE = startLocationCode
|
}, trans);
|
CreateDapperDAL<TN_WM_LOCATION_EXTEntity>().Update(new
|
{
|
CN_S_LOCATION_STATE = Constants.Location_State_Normal,
|
CN_S_USE_STATE = Constants.Use_State_Empty
|
}, new
|
{
|
CN_S_LOCATION_CODE = startLocationCode
|
});
|
}
|
});
|
}
|
#endregion
|
|
#region 锁货位,发任务
|
/// <summary>
|
/// 锁货位,发任务
|
/// </summary>
|
/// <param name="taskEntity"></param>
|
/// <param name="trans"></param>
|
private void LockLocationAndSendAms(TN_WM_TASKEntity taskEntity, IDbTransaction trans, bool lockStart = false)
|
{
|
string taskNo = taskEntity.CN_S_TASK_NO;
|
OperateResult re = CreateDAL<DapperDAL<TN_WM_TASKEntity>>().Add(taskEntity, trans);
|
//锁定目的位置货位-预入库锁定
|
if ("Y".Equals(taskEntity.CN_C_END_IS_CONTROL_QTY))
|
{
|
var operateResult = CreateDAL<TN_WM_LOCATION_EXTDAL>().UpdateLocationExtStateLock(taskEntity.CN_S_END_BIT, Constants.Location_State_InLock, Constants.Location_State_Normal, "", taskNo, trans);
|
|
if (operateResult.AffectedRows == 0)
|
{
|
throw new Exception("更新目的货位状态并发冲突,该货位状态可能已经发生变化");
|
}
|
|
BLLCreator.Create<TN_WM_B_LOCATION_CHANGEBLL>().AddStateChange(taskEntity.CN_S_START_BIT, "正常", "预入库锁定", "分拣出生成任务锁定终点货位", "服务", "sys", taskNo, taskEntity.CN_S_STOCK_CODE, taskEntity.CN_S_END_AREA, trans);
|
}
|
if ("Y".Equals(taskEntity.CN_C_START_IS_CONTROL_QTY) && lockStart)
|
{
|
//锁定起始位置货位-预出库锁定
|
var operateResult = CreateDAL<TN_WM_LOCATION_EXTDAL>().UpdateLocationExtStateLock(taskEntity.CN_S_START_BIT, Constants.Location_State_OutLock, Constants.Location_State_Normal, "", taskNo, trans);
|
|
if (operateResult.AffectedRows == 0)
|
{
|
throw new Exception("更新起点货位状态并发冲突,该货位状态可能已经发生变化");
|
}
|
|
BLLCreator.Create<TN_WM_B_LOCATION_CHANGEBLL>().AddStateChange(taskEntity.CN_S_START_BIT, "正常", "预出库锁定", "分拣出生成任务锁定起点货位", "服务", "sys", taskNo, taskEntity.CN_S_STOCK_CODE, taskEntity.CN_S_START_AREA, trans);
|
|
}
|
|
var amsRes = BLLCreator.Create<OtherSysApi>().SendAmsCreateTaskHK(taskEntity);
|
if (!amsRes.Success)
|
throw new Exception("SendAmsCreateTaskHK 异常:" + amsRes.Msg);
|
}
|
#endregion
|
}
|
}
|