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 发货通知单主表-分页
///
/// 发货通知单主表-分页
///
///
///
///
public DataTable GetOutList(OutSearchDto param, out long total)
{
return CreateDAL().GetOutList(param, out total);
}
#endregion
#region 获取出库主子表
///
/// 获取出库主子表
///
///
///
public TN_WM_OUT_MSTEntity GetOutMstAndDtl(string CN_S_OP_NO)
{
TN_WM_OUT_MSTEntity outMst = CreateDapperDAL().GetSingleEntity(new { CN_S_OP_NO = CN_S_OP_NO });
List outDtlList = CreateDapperDAL().GetList(new { CN_S_OP_NO = CN_S_OP_NO });
outMst.OutDtlList = outDtlList;
return outMst;
}
#endregion
#region 根据出库单上升仓库量表分配量
///
/// 根据出库单上升仓库量表分配量
///
///
///
public List AddOrDropStockAllocQtyByOut(TN_WM_OUT_MSTEntity outMst, BatchType batchType)
{
if (outMst.OutDtlList == null || !outMst.OutDtlList.Any())
throw new Exception("批分物料行不可为空");
var stockQty = CreateDapperDAL().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 根据分拣单明细上升仓库量表分配量
///
/// 根据出库单上升仓库量表分配量
///
///
///
public List AddOrDropStockAllocQtyBySorting(List sortingLocations, BatchType batchType)
{
if (sortingLocations == null || !sortingLocations.Any())
throw new Exception("AddOrDropStockAllocQtyBySorting 批分物料不可为空");
//仓库物料,批次空的放前面
var stockQty = CreateDapperDAL().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 根据分拣单明细上升库区量表分配量
///
/// 根据出库单上升仓库量表分配量
///
///
///
public List AddOrDropAreaAllocQtyBySorting(List sortingLocations, BatchType batchType)
{
if (sortingLocations == null || !sortingLocations.Any())
throw new Exception("AddOrDropAreaAllocQtyBySorting 批分物料不可为空");
//仓库物料,批次空的放前面
var areaQty = CreateDapperDAL().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 下架记录
///
/// 下架记录
///
///
///
///
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 根据分拣单明细上升托盘物料关联表分配量
///
/// 根据分拣单明细上升托盘物料关联表分配量
///
///
///
///
public List AddOrDropTrayAllocQtyBySorting(List sortingLocations, BatchType batchType)
{
if (sortingLocations == null || !sortingLocations.Any())
throw new Exception("AddOrDropTrayAllocQtyBySorting 批分物料不可为空");
//仓库物料,批次空的放前面
var trayQty = CreateDapperDAL().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 出库订单新增
///
/// 出库订单新增
///
///
///
public OperateResult AddOut(TN_WM_OUT_MSTEntity outMst)
{
return UseTransaction(trans =>
{
//新增主表
CreateDapperDAL().Add(outMst, trans);
//新增子表
CreateDapperDAL().AddRange(outMst.OutDtlList, trans);
//升仓库分配量
});
}
#endregion
#region 出库订单修改
///
/// 出库订单修改
///
///
///
public OperateResult UpdateOut(TN_WM_OUT_MSTEntity outMst)
{
return UseTransaction(trans =>
{
//修改主表
CreateDapperDAL().Update(outMst, new { CN_S_OP_NO = outMst.CN_S_OP_NO }, trans);
//删除子表
CreateDapperDAL().Delete(new { CN_S_OP_NO = outMst.CN_S_OP_NO }, trans);
//新增子表
CreateDapperDAL().AddRange(outMst.OutDtlList, trans);
});
}
#endregion
#region 删除出库订单
///
/// 删除出库订单
///
///
///
public OperateResult DeleteOut(string opNo)
{
return UseTransaction(trans =>
{
//删除出库订单主表
CreateDapperDAL().Delete(new { CN_S_OP_NO = opNo }, trans);
//删除出库订单子表
CreateDapperDAL().Delete(new { CN_S_OP_NO = opNo }, trans);
});
}
#endregion
#region 提交出库订单
///
/// 提交出库订单
///
///
///
///
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().Add(sortingEntity, trans);
//分拣单子表
CreateDapperDAL().AddRange(sortingEntity.SortingDtlList, trans);
//分拣明细表
CreateDapperDAL().AddRange(sortingEntity.SortingLocationList, trans);
//锁货位 预出库锁定
sortingEntity.SortingLocationList.ForEach(m =>
{
CreateDapperDAL().Update(new
{
CN_S_LOCATION_STATE = Constants.Location_State_OutLock
}, new
{
CN_S_LOCATION_CODE = m.CN_S_LOCATION_CODE
}, trans);
});
//修改出库单表属性
CreateDapperDAL().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().UpdateStockAllocQty(e, trans).AffectedRows == 0)
throw new Exception("时间戳被更新,修改仓库分配量失败");
});
//升库区分配量
addAreaAlloc.ForEach(e =>
{
if (CreateDAL().UpdateAreaAlloc(e, trans).AffectedRows == 0)
throw new Exception("时间戳被更新,修改库区分配量失败");
});
//升托盘物料关联表分配量
addTrayAlloc.ForEach(e =>
{
if (CreateDAL().UpdateTrayItemAllocQty(e, trans).AffectedRows == 0)
throw new Exception("时间戳被更新,修改托盘物料关联表分配量失败");
});
});
}
#endregion
#region 获取波次实体
///
/// 获取波次实体
///
///
///
///
///
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();
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 取货位分拣中的物料
///
/// 取货位分拣中的物料
///
///
///
public List GetSortingLocation(string locationCode)
{
return CreateDAL().GetSortingLocation(locationCode);
}
#endregion
#region 分拣货位生成任务
///
/// 分拣货位生成任务
///
///
///
public OperateResult ExecuteSortingTask(List sortingLocations)
{
//所有库区
var allArea = BLLCreator.Create().GetArea(4, sortingLocations[0].CN_S_STOCK_CODE);
//生成出库任务号
UserRuleEntity user = new UserRuleEntity()
{
RuleCode = Constants.TaskNo_Out
};
//生成出库任务
var tasks = new List();
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().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 保存分拣
///
/// 保存分拣
///
///
///
public OperateResult SaveSortingLocation(string startLocationCode, List sortingLocations)
{
#region 装载分拣数据
//分拣单
string sortingNo = sortingLocations[0].CN_S_SORTING_NO;
//分拣单实体
var sortingEntity = BLLCreator.CreateDapper().GetSingleEntity(new
{
CN_S_SORTING_NO = sortingNo
});
if (sortingEntity == null) return OperateResult.Error("未找到分拣单:" + sortingNo);
//该分拣单的所有分拣明细
var all = BLLCreator.CreateDapper().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(iAe);
if (!irEresult.Success)
{
return OperateResult.Error(irEresult.Msg);//货位获取失败!
}
else
{
endLocationCode = irEresult.lstLocation[0].locationCode.ToString();
}
var startLocation = BLLCreator.CreateDapper().GetSingleEntity(new
{
CN_S_LOCATION_CODE = startLocationCode
});
if (startLocation == null) return OperateResult.Error("未找到货位:" + startLocationCode);
//所有库区
var allArea = BLLCreator.Create().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();
var dropAreaAlloc = new List();
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().Update(new
{
CN_F_PICKED_QTY = e.CN_F_QUANTITY
}, new
{
CN_GUID = e.CN_GUID
}, trans);
});
//降托盘物料关联表分配量
dropTrayAlloc.ForEach(e =>
{
if (CreateDAL().UpdateTrayItemAllocQty(e, trans).AffectedRows == 0)
throw new Exception("时间戳被更新,修改托盘物料关联表分配量失败");
});
//下架记录
CreateDapperDAL().AddRange(downHistory, trans);
//已分拣完
if (!other.Exists(e => e.CN_F_PICKED_QTY == 0))
{
//出库单置为已完成
CreateDapperDAL().Update(new
{
CN_S_STATE = Constants.State_Completed
}, new
{
CN_S_OP_NO = sortingEntity.CN_S_FROM_NO
}, trans);
//分拣单置为已分拣
CreateDapperDAL().Update(new
{
CN_S_STATE = Constants.Sorting_Sorted
}, new
{
CN_S_SORTING_NO = sortingNo
}, trans);
//降仓库分配量
dropStockAlloc.ForEach(e =>
{
if (CreateDAL().UpdateStockAllocQty(e, trans).AffectedRows == 0)
throw new Exception("时间戳被更新,修改仓库分配量失败");
});
//降库区分配量
dropAreaAlloc.ForEach(e =>
{
if (CreateDAL().UpdateAreaAlloc(e, trans).AffectedRows == 0)
throw new Exception("时间戳被更新,修改库区分配量失败");
});
}
if (sortingLocations[0].CN_S_NEED_SORT == Constants.Y)
{
//锁货位,发任务
LockLocationAndSendAms(taskEntity, trans, true);
}
else
{
CreateDapperDAL().Delete(new
{
CN_S_LOCATION_CODE = startLocationCode
}, trans);
CreateDapperDAL().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 锁货位,发任务
///
/// 锁货位,发任务
///
///
///
private void LockLocationAndSendAms(TN_WM_TASKEntity taskEntity, IDbTransaction trans, bool lockStart = false)
{
string taskNo = taskEntity.CN_S_TASK_NO;
OperateResult re = CreateDAL>().Add(taskEntity, trans);
//锁定目的位置货位-预入库锁定
if ("Y".Equals(taskEntity.CN_C_END_IS_CONTROL_QTY))
{
var operateResult = CreateDAL().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().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().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().AddStateChange(taskEntity.CN_S_START_BIT, "正常", "预出库锁定", "分拣出生成任务锁定起点货位", "服务", "sys", taskNo, taskEntity.CN_S_STOCK_CODE, taskEntity.CN_S_START_AREA, trans);
}
var amsRes = BLLCreator.Create().SendAmsCreateTaskHK(taskEntity);
if (!amsRes.Success)
throw new Exception("SendAmsCreateTaskHK 异常:" + amsRes.Msg);
}
#endregion
}
}