using HH.WCS.Mobox3.YNJT_BZP_GT.api;
using HH.WCS.Mobox3.YNJT_BZP_GT.models;
using HH.WCS.Mobox3.YNJT_BZP_GT.models.other;
using HH.WCS.Mobox3.YNJT_BZP_GT.util;
using Newtonsoft.Json;
using NLog.Fluent;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;
using static HH.WCS.Mobox3.YNJT_BZP_GT.api.ApiModel;
namespace HH.WCS.Mobox3.YNJT_BZP_GT.wms {
///
/// wms管到作业
///
internal class WMSHelper {
internal static string GenerateTaskNo() {
var id = SYSHelper.GetSerialNumber("作业号", "OP");
var date = DateTime.Now.ToString("yyMMdd");
return $"OP{date}{id.ToString().PadLeft(4, '0')}";
}
internal static string GenerateSortingNo() {
var id = SYSHelper.GetSerialNumber("分拣单", "SO");
var date = DateTime.Now.ToString("yyMMdd");
return $"SO{date}{id.ToString().PadLeft(4, '0')}";
}
internal static List GetOperationListByState(string state) {
var db = new SqlHelper().GetInstance();
return db.Queryable().Where(a => a.S_B_STATE == state).ToList();
}
internal static List GetOperationListByState(int state) {
var db = new SqlHelper().GetInstance();
return db.Queryable().Where(a => a.N_B_STATE == state).ToList();
}
internal static List GetWaitingOperationList() {
var db = new SqlHelper().GetInstance();
return db.Queryable().Where(a => a.N_B_STATE == 0 || a.N_B_STATE == 3).ToList();
}
internal static PutawayOrder GetPutawayOrder(string no) {
var db = new SqlHelper().GetInstance();
return db.Queryable().Where(a => a.S_NO == no).First();
}
internal static bool CreatePutawayOrder(PutawayOrder model) {
var db = new SqlHelper().GetInstance();
var result = db.Insertable(model).ExecuteCommand() > 0;
db.Insertable(model.Details).ExecuteCommand();
return result;
}
internal static PutawayDetail GetPutawayOrderDetail(string no, string item_code) {
var db = new SqlHelper().GetInstance();
return db.Queryable().Where(a => a.S_PUTAWAY_NO == no && a.S_ITEM_CODE == item_code).First();
}
internal static PutawayDetail GetPutawayOrderDetail(string item_code) {
var db = new SqlHelper().GetInstance();
return db.Queryable().Where(a => a.S_ITEM_CODE == item_code && a.F_QTY - a.F_ACC_B_QTY > 0).OrderByDescending(a => a.T_CREATE).First();
}
internal static void UpdatePutawayOrderDetailQty(PutawayDetail model) {
var db = new SqlHelper().GetInstance();
db.Updateable(model).UpdateColumns(it => new { it.F_ACC_B_QTY }).ExecuteCommand();
}
internal static ShippingOrder GetShippingOrder(string no) {
var db = new SqlHelper().GetInstance();
return db.Queryable().Includes(a => a.Details).Where(a => a.S_NO == no).First();
}
internal static bool CreateShippingOrder(ShippingOrder model) {
var db = new SqlHelper().GetInstance();
var result = db.Insertable(model).ExecuteCommand() > 0;
db.Insertable(model.Details).ExecuteCommand();
return result;
}
internal static bool CreateSortingOrder(List list) {
var res = false;
//遍历获取发货单,然后判断库存,如果全都没库存,则不生成分拣单,如果有生成分拣单
//更新波次单,即使只有一个发货单也更新波次单
var db = new SqlHelper().GetInstance();
var sortingOrderNo = "";
SortingOrder sortingOrder = null;
try {
db.BeginTran();
list.ForEach(a => {
var so = db.Queryable().Includes(s => s.Details).Where(s => s.S_NO == a).First();
//判断库存,只有已经入库的才可以计算,码盘的不算,入库后出库途中的也要计算,码盘后默认叫待入库,入库后叫正常
//生成出库任务,只有托盘位置在立库才需要创建出库任务(先写死立库)
//只有全部分拣完成才允许回库(一个托盘可能对应多个分拣明细)
//查找仓库量表和库区量表,出库单需要定位仓库和库区了,出库定位物理库区就行,入库可能物料库区还要区分逻辑库区
//暂时只查仓库量表(量表如何重置,查找所有查找C_ENABLE=N的,判断如果在仓库中,改成Y,然后统计)
//生成分拣单时候增加仓库量表分配量,生成分拣单明细时候,增加库区量表分配量
if (so != null && so.Details.Count > 0) {
var fail = true;
for (int i = 0; i < so.Details.Count; i++) {
var whi = db.Queryable().Where(w => w.S_ITEM_CODE == so.Details[i].S_ITEM_CODE).First();
if (whi != null && whi.F_QTY - whi.F_ALLOC_QTY > 0) {
//有货就出
float qty = whi.F_QTY - whi.F_ALLOC_QTY > so.Details[i].F_QTY ? so.Details[i].F_QTY : whi.F_QTY - whi.F_ALLOC_QTY;
fail = false;
//有可用库存,生成分拣单
if (sortingOrderNo == "") {
sortingOrderNo = GenerateSortingNo();
sortingOrder = new SortingOrder
{
S_NO = sortingOrderNo,
S_SHIPPING_NO = so.S_NO,
Composes = new List()
};
//创建分拣单
db.Insertable(sortingOrder).ExecuteCommand();
}
else {
//获取最新分拣单
sortingOrder = db.Queryable().Includes(s => s.Composes).Where(s => s.S_NO == sortingOrderNo).First();
//更新分拣单中的发货单单号
sortingOrder.S_SHIPPING_NO = sortingOrder.S_SHIPPING_NO + ";" + so.S_NO;
sortingOrder.T_MODIFY = DateTime.Now;
db.Updateable(sortingOrder).UpdateColumns(it => new { it.S_SHIPPING_NO, it.T_MODIFY }).ExecuteCommand();
}
//查询分拣单子表(正常情况还需要增加批次判断)
var soc = db.Queryable().Where(s => s.S_ITEM_CODE == so.Details[i].S_ITEM_CODE && s.S_SORTING_NO == sortingOrder.S_NO).First();
if (soc == null) {
soc = new SortingCompose
{
S_ITEM_CODE = so.Details[i].S_ITEM_CODE,
S_SORTING_NO = sortingOrder.S_NO,
F_QTY = qty,
N_ROW_NO = sortingOrder.Composes.Count() + 1,
S_BATCH_NO = so.Details[i].S_BATCH_NO
};
//创建分拣单子表
db.Insertable(soc).ExecuteCommand();
}
else {
soc.F_QTY += qty;
soc.T_MODIFY = DateTime.Now;
//更新分拣单子表
db.Updateable(soc).UpdateColumns(it => new { it.F_QTY, it.T_MODIFY }).ExecuteCommand();
}
//更新仓库量表分配量
whi.F_ALLOC_QTY += qty;
whi.T_MODIFY = DateTime.Now;
db.Updateable(whi).UpdateColumns(it => new { it.F_ALLOC_QTY, it.T_MODIFY }).ExecuteCommand();
//跟新发货单子表配货数量
so.Details[i].F_ACC_D_QTY += qty;
so.Details[i].T_MODIFY = DateTime.Now;
db.Updateable(so.Details[i]).UpdateColumns(it => new { it.F_ACC_D_QTY, it.T_MODIFY }).ExecuteCommand();
}
}
//更新发货单状态
so.N_B_STATE = fail ? 5 : 1;
if (fail) {
so.S_NOTE = "没有库存";
}
so.S_WAVE_CODE = sortingOrderNo;
so.T_MODIFY = DateTime.Now;
db.Updateable(so).UpdateColumns(it => new { it.N_B_STATE, it.T_MODIFY, it.S_WAVE_CODE, it.S_NOTE }).ExecuteCommand();
}
//查找库区内托盘生成托盘明细(包括分拣中)怎么判断库内?查找货位绑定?还是托盘上加标识比较好,如果是整托出的,分拣确认后去掉分拣标识。
//1、只有码盘入库后的才需要加标识,分拣回的不用,分拣回的标识还在,没有变。写死码盘入的完成后加标识,整托分拣的去掉标识,防止后面重新码盘脏数据
//2、或者关联查询库内的,只给分拣出的加标识,每次分拣回再把标识清除了(如果不清除带标识的会很多,还不如全部加标识),整托的清除。
//综合选择还是方案1,这样创建分拣明细,只需要托盘物料两表查询就能定位托盘(如果信息不准,可以重置),方案2需要货位、托盘、物料三表联查
//暂时不计库区,标识用容器表 C_ENABLE 来判断,表示能不能出库
//执行分拣创建任务,遍历分拣明细中的托盘,如果在仓库就出库,如果不在就不用出库
});
//全部分拣单生成之后将分拣单状态设置为开始配货,波次号为发货单
sortingOrder = db.Queryable().Where(s => s.S_NO == sortingOrderNo).First();
sortingOrder.N_B_STATE = 1;
sortingOrder.T_MODIFY = DateTime.Now;
db.Updateable(sortingOrder).UpdateColumns(it => new { it.N_B_STATE, it.T_MODIFY }).ExecuteCommand();
db.CommitTran();
res = true;
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
db.RollbackTran();
}
return res;
}
internal static List GetSortingDetailByCntr(string cntr) {
var db = new SqlHelper().GetInstance();
var result = db.Queryable().Where(a => a.S_CNTR_CODE == cntr && a.N_B_STATE != 2).ToList();
return result;
}
internal static bool CreateWmsTask(WMSTask wmsTask) {
try {
var db = new SqlHelper().GetInstance();
return db.Insertable(wmsTask).ExecuteCommand() > 0;
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
throw;
}
}
internal static WMSTask GetWmsTaskByCntr(string cntr, bool active = true) {
WMSTask result = null;
var db = new SqlHelper().GetInstance();
if (active) {
result = db.Queryable().Where(a => a.S_CNTR_CODE.Contains(cntr) && a.N_B_STATE < 2).First();
}
else {
result = db.Queryable().Where(a => a.S_CNTR_CODE.Contains(cntr)).First();
}
return result;
}
internal static Location GetEnd(WMSTask a) {
throw new NotImplementedException();
}
internal static Location GetStart(WMSTask a) {
throw new NotImplementedException();
}
internal static void UpdateTaskState(WMSTask task) {
var db = new SqlHelper().GetInstance();
task.T_MODIFY = DateTime.Now;
task.S_B_STATE = WMSTask.GetStateStr(task.N_B_STATE);
db.Updateable(task).UpdateColumns(a => new { a.N_B_STATE, a.S_B_STATE, a.T_MODIFY }).ExecuteCommand();
}
internal static bool UpdateTaskEnd(WMSTask a) {
var db = new SqlHelper().GetInstance();
a.T_MODIFY = DateTime.Now;
return db.Updateable(a).UpdateColumns(it => new { it.S_END_LOC, it.T_MODIFY }).ExecuteCommand() > 0;
}
internal static WMSTask GetWmsTask(string code) {
var db = new SqlHelper().GetInstance();
return db.Queryable().Where(a => a.S_CODE == code).First();
}
/*
internal static void CreateSortingOrderDetail(string so_no) {
//分拣单配货
var db = new SqlHelper().GetInstance();
var so = db.Queryable().Includes(a => a.Composes).Where(a => a.S_NO == so_no && (a.N_B_STATE == 1 || a.N_B_STATE == 20)).First();//
if (so != null && so.Composes.Count > 0) {
db.BeginTran();
try {
int rowNo = 1;
so.Composes.ForEach(a => {
//按分拣单子表去配货,查找可用托盘(先查所有符合的,后面再优化)
var cirList = db.Queryable().Includes(c => c.Cntr).Where(c => c.Cntr.C_ENABLE == "Y" && c.S_ITEM_CODE == a.S_ITEM_CODE && (c.F_QTY - c.F_ALLOC_QTY) > 0).OrderBy(c => c.T_CREATE).ToList();
for (int i = 0; i < cirList.Count; i++) {
var cir = cirList[i];
var sd = new SortingDetail
{
N_ROW_NO = rowNo,
S_BATCH_NO = a.S_BATCH_NO,
S_ITEM_CODE = a.S_ITEM_CODE,
S_CNTR_CODE = cir.S_CNTR_CODE,
S_SORTING_NO = a.S_SORTING_NO
};
bool needBreak = false;
if (cir.F_QTY - cir.F_ALLOC_QTY >= (a.F_QTY - a.F_ACC_S_QTY)) {
//容器可用数量大于分拣单子表要求的数量,生成分拣明细,然后跳出循环
sd.F_QTY = a.F_QTY - a.F_ACC_S_QTY;
needBreak = true;
}
else {
//生成分拣明细,继续创建
sd.F_QTY = cir.F_QTY - cir.F_ALLOC_QTY;
}
db.Insertable(sd).ExecuteCommand();
rowNo++;
//更新容器货品表分配量
cir.F_ALLOC_QTY += sd.F_QTY;
cir.T_MODIFY = DateTime.Now;
db.Updateable(cir).UpdateColumns(it => new { it.F_ALLOC_QTY, it.T_MODIFY }).ExecuteCommand();
//更新分拣单子表的量
a.F_ACC_S_QTY += sd.F_QTY;
a.T_MODIFY = DateTime.Now;
db.Updateable(cir).UpdateColumns(it => new { it.F_ALLOC_QTY, it.T_MODIFY }).ExecuteCommand();
if (needBreak) {
break;
}
}
});
//全部分拣单子表生成分拣明细,修改分拣单状态为配货完成(反正仓库的货能配的都配完了,除非数据有异常)
so.N_B_STATE = 2;
so.T_MODIFY = DateTime.Now;
db.Updateable(so).UpdateColumns(it => new { it.N_B_STATE, it.T_MODIFY }).ExecuteCommand();
db.CommitTran();
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
db.RollbackTran();
}
}
}
*/
///
/// 获取开始配货的分拣单,一次性生成分拣明细,避免生成一半再生成,所以创建分拣明细的时候加上事务
///
///
internal static List GetWaitingSortingOrderList() {
var db = new SqlHelper().GetInstance();
return db.Queryable().Includes(a => a.Composes).Where(a => a.N_B_STATE == 1 || a.N_B_STATE == 20).ToList();
}
///
/// 获取配货完成的分拣单,每个分拣单单独创建分拣作业
///
///
internal static List GetWaitingSortingOperationList() {
var db = new SqlHelper().GetInstance();
return db.Queryable().Includes(a => a.Details).Where(a => a.N_B_STATE == 2 || a.N_B_STATE == 3).ToList();
}
///
///单个分拣单的分拣明细创建作业
///
internal static void CreateSortingOperation(SortingOrder so) {
var list = so.Details.Where(a => a.N_B_STATE == 0).ToList();
var db = new SqlHelper().GetInstance();
if (list.Count > 0) {
try {
db.BeginTran();
list.GroupBy(g => g.S_CNTR_CODE).ToList().ForEach(g => {
var cntr = g.Key;
var sdList = g.ToList();
//查询托盘货位,查到了创建任务,查不到说明在别的分拣作业中,不创建任务,需要回库后重新创建
var lcr = db.Queryable().Where(c => c.S_CNTR_CODE == cntr).First();
if (lcr != null) {
//判断托盘是否已经创建任务了,可能多个分拣明细是同一个托盘,如果创建任务了,其它分拣的要稍后,只出一次人工会搞不清楚是哪个分拣单的
var wmsTask = db.Queryable().Where(op => op.S_CNTR_CODE.Contains(cntr) && op.N_B_STATE < 2).First();
if (wmsTask == null) {
wmsTask = new WMSTask
{
S_CNTR_CODE = cntr,
S_CODE = WMSHelper.GenerateTaskNo(),
S_START_LOC = lcr.S_LOC_CODE,
S_END_LOC = "",
N_TYPE = 2,
S_TYPE = WMSTask.GetTypeStr(2),
S_OP_DEF_CODE = "",
S_OP_DEF_NAME = "分拣出立库"
};
if (db.Insertable(wmsTask).ExecuteCommand() > 0) {
LocationHelper.LockLoc(lcr.S_LOC_CODE, 2);
}
sdList.ForEach(a => {
a.N_B_STATE = 1;
a.T_MODIFY = DateTime.Now;
db.Updateable(a).UpdateColumns(it => new { it.N_B_STATE, it.T_MODIFY }).ExecuteCommand();
});
}
}
//修改分拣单状态为开始作业(不代表作业全部创建了,因为有的托盘可能已经被占用了)
so.N_B_STATE = 3;
//如果所有的作业都已经创建了,就设置为作业已经创建
if (so.Details.Count(s => s.N_B_STATE == 0) == 0) {
so.N_B_STATE = 4;
}
so.T_MODIFY = DateTime.Now;
db.Updateable(so).UpdateColumns(it => new { it.N_B_STATE, it.T_MODIFY }).ExecuteCommand();
});
db.CommitTran();
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
db.RollbackTran();
}
}
}
///
/// 类似农夫堆叠
///
///
///
///
///
internal static Location GetInstockEnd(string item, string endArea) {
Location end = null;
end = GetLocation4InAnySrc(endArea, item);
if (end == null)
{
end = GetLocation4InEmptyRow(endArea);
}
return end;
}
public static Location GetLocation4InAnySrc(string area, string itemCode) {
Location result = null;
try {
Console.WriteLine("成品满托入库 GetLocation4InAnySrc:" + area);
//1.0 获取每一排最大的列
//1.1 判断当前数量是不是满的,如果是满的并且是最大列,需要排除
var listMaxCol = new SqlHelper().GetInstance().Queryable().Where(a => a.S_AREA_CODE == area ).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList();
//1.1 查到所有有托盘的排
Console.WriteLine("查到所有有托盘的排 ");
var db = new SqlHelper().GetInstance();
var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE == area ).Includes(a => a.LocCntrRel, a => a.CntrItemRel).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList();
if (list.Count > 0) {
//1.2 查找其它尺寸有托盘或者锁定的排
for (int i = list.Count - 1; i >= 0; i--) {
//排除已经锁定的货位 和 放满了且是最大列的货位
if (list[i].N_LOCK_STATE != 0 || (list[i].N_CURRENT_NUM == list[i].N_CAPACITY && listMaxCol.Count(a => a.S_CODE == list[i].S_CODE) > 0)) {
Console.WriteLine($"排除已经锁定的货位 和 放满了且是最大列的货位 排{list[i].N_ROW}");
list.Remove(list[i]);
}
else {
//排有锁也排除
var other = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.S_LOCK_STATE != "无" && a.N_LOCK_STATE != 0).First();
if (other != null) {
Console.WriteLine($"排除有锁的排{list[i].N_ROW}");
list.Remove(list[i]);
}
}
}
Console.WriteLine($"有托盘排数为{list.Count}");
if (list.Count > 0) {
//1.3 遍历判断物料类型是否相同
Console.WriteLine("遍历判断物料类型是否相同");
for (int i = 0; i < list.Count; i++) {
//todo 还需要判断锁
if (list[i].LocCntrRel != null && list[i].LocCntrRel.CntrItemRel != null) {
Console.WriteLine($"货位{list[i].S_CODE} 物料{list[i].LocCntrRel.CntrItemRel.S_ITEM_CODE}");
if (list[i].LocCntrRel.CntrItemRel.S_ITEM_CODE == itemCode) {
if (list[i].N_CURRENT_NUM < list[i].N_CAPACITY) {
result = list[i];
}
else {
Console.WriteLine("选择后面空位");
result = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL > list[i].N_COL && a.C_ENABLE == "Y").OrderBy(a => a.N_COL).First();
}
if (result != null)
{
break;
}
}
}
}
}
}
if (result != null && (!string.IsNullOrEmpty(result.C_ENABLE) && (result.C_ENABLE == "禁用" || result.C_ENABLE == "N"))) {
//禁用了选择后面一个货位
//Console.WriteLine("禁用了选择后面一个货位");
result = db.Queryable().OrderBy(a => a.N_COL).Where(a => a.S_AREA_CODE == area && a.N_ROW == result.N_ROW && (string.IsNullOrEmpty(a.C_ENABLE) || (a.C_ENABLE != "禁用" && a.C_ENABLE != "N")) && a.N_COL > result.N_COL).First();
}
}
catch (Exception ex) {
LogHelper.Error("GetLocation4InFinish:" + ex.Message, ex);
}
return result;
}
public static Location GetLocation4InEmptyRow(string area) {
Location result = null;
try {
var db = new SqlHelper().GetInstance();
#region 查找所有数量是空的排
//Console.WriteLine("查找所有数量是空的排");
//2.0 简化查询只查每一排第一列
var list = db.Queryable().Where(a => a.S_AREA_CODE == area).OrderBy(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList().Where(a => a.N_CURRENT_NUM == 0 ).ToList();
//2.1 选一个空排
for (int i = 0; i < list.Count; i++) {
var other = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.S_LOCK_STATE != "无").First();
if (list[i].N_LOCK_STATE == 0 && other == null) {
//二次校验当前排所有货位都是空的,防止系统数据错乱
var rowSumInfo = db.Queryable().Where(l => l.S_AREA_CODE == area && l.N_ROW == list[i].N_ROW && l.N_CURRENT_NUM != 0).Count();
if (rowSumInfo == 0) {
result = list[i];
break;
}
}
}
#endregion
if (result != null && (!string.IsNullOrEmpty(result.C_ENABLE) && (result.C_ENABLE == "禁用" || result.C_ENABLE == "N"))) {
//禁用了选择后面一个货位
Console.WriteLine("禁用了选择后面一个货位");
result = db.Queryable().OrderBy(a => a.N_COL).Where(a => a.S_AREA_CODE == area && a.N_ROW == result.N_ROW && (string.IsNullOrEmpty(a.C_ENABLE) || (a.C_ENABLE != "禁用" && a.C_ENABLE != "N")) && a.N_COL > result.N_COL).First();
}
}
catch (Exception ex) {
LogHelper.Error("GetLocation4InEmptyRow:" + ex.Message, ex);
}
return result;
}
public static Location GetLocation4InEmptyRow()
{
Location result = null;
try
{
var db = new SqlHelper().GetInstance();
#region 查找所有数量是空的排
//Console.WriteLine("查找所有数量是空的排");
//2.0 简化查询只查每一排第一列
var list = db.Queryable().OrderBy(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList().Where(a => a.N_CURRENT_NUM == 0).ToList();
//2.1 选一个空排
for (int i = 0; i < list.Count; i++)
{
var other = db.Queryable().Where(a => a.S_AREA_CODE == list[i].S_AREA_CODE && a.N_ROW == list[i].N_ROW && a.S_LOCK_STATE != "无").First();
if (list[i].N_LOCK_STATE == 0 && other == null)
{
//二次校验当前排所有货位都是空的,防止系统数据错乱
var rowSumInfo = db.Queryable().Where(l => l.S_AREA_CODE == list[i].S_AREA_CODE && l.N_ROW == list[i].N_ROW && l.N_CURRENT_NUM != 0).Count();
if (rowSumInfo == 0)
{
result = list[i];
break;
}
}
}
#endregion
if (result != null && (!string.IsNullOrEmpty(result.C_ENABLE) && (result.C_ENABLE == "禁用" || result.C_ENABLE == "N")))
{
//禁用了选择后面一个货位
Console.WriteLine("禁用了选择后面一个货位");
result = db.Queryable().OrderBy(a => a.N_COL).Where(a => a.S_AREA_CODE == result.S_AREA_CODE && a.N_ROW == result.N_ROW && (string.IsNullOrEmpty(a.C_ENABLE) || (a.C_ENABLE != "禁用" && a.C_ENABLE != "N")) && a.N_COL > result.N_COL).First();
}
}
catch (Exception ex)
{
LogHelper.Error("GetLocation4InEmptyRow:" + ex.Message, ex);
}
return result;
}
internal static Location GetInstockEnd(string item)
{
var db = new SqlHelper().GetInstance();
Location end = null;
// 查询相同物料的排是否有可放货的库位
var listMaxCol = db.Queryable()
.LeftJoin((l, lc) => l.S_CODE == lc.S_LOC_CODE)
.LeftJoin((l, lc, ci) => lc.S_CNTR_CODE == ci.S_CNTR_CODE)
.Where((l, lc, ci) => l.N_CURRENT_NUM > 0 && ci.S_ITEM_CODE == item && l.S_AREA_CODE != Settings.BufferArea)
.OrderByDescending((l, lc, ci) => l.N_COL).Take(1).PartitionBy((l, lc, ci) => l.N_ROW).ToList();
foreach (var loc in listMaxCol)
{
//排有锁也排除
var other = db.Queryable().Where(a => a.S_AREA_CODE == loc.S_AREA_CODE && a.N_ROW == loc.N_ROW && a.S_LOCK_STATE != "无" && a.N_LOCK_STATE != 0).First();
if (other != null)
{
continue;
}
end = db.Queryable().OrderBy(a => a.N_COL).Where(a => a.S_AREA_CODE == loc.S_AREA_CODE && a.N_ROW == loc.N_ROW && a.N_CURRENT_NUM < a.N_CAPACITY && (string.IsNullOrEmpty(a.C_ENABLE) || (a.C_ENABLE != "禁用" && a.C_ENABLE != "N")) && a.N_COL >= loc.N_COL).First();
if (end != null) {
return end;
}
}
// 如果没有,则随机放空的排
if (end == null) {
end = GetLocation4InEmptyRow();
}
return end;
}
public static Location GetShiftStockStart(string area ,int row)
{
Location result = null;
try
{
// 1、查询当前库区-排-物料 有托盘的货位
var db = new SqlHelper().GetInstance();
result = db.Queryable()
.Where(l => l.N_CURRENT_NUM > 0 && l.S_AREA_CODE == area && l.N_ROW == row && l.N_LOCK_STATE == 0 && (l.C_ENABLE != "禁用" && l.C_ENABLE != "N"))
.Includes(l => l.LocCntrRel, l => l.CntrItemRel)
.OrderByDescending(l => l.N_COL)
.First();
}
catch (Exception ex)
{
LogHelper.Error("GetShiftStockStart:" + ex.Message, ex);
}
return result;
}
public static Location GetShiftStockStart(string area)
{
Location result = null;
try
{
// 1、查询当前库区-排-物料 有托盘的货位
var db = new SqlHelper().GetInstance();
var listMaxCol = db.Queryable()
.Where(l => l.N_CURRENT_NUM > 0 && l.S_AREA_CODE == area)
.Includes(l => l.LocCntrRel, l => l.CntrItemRel)
.OrderByDescending(l => l.N_COL)
.Take(1)
.PartitionBy(l => l.N_ROW)
.ToList();
foreach (var loc in listMaxCol)
{
//排有锁也排除
var other = db.Queryable().Where(a => a.S_AREA_CODE == loc.S_AREA_CODE && a.N_ROW == loc.N_ROW && a.S_LOCK_STATE != "无" && a.N_LOCK_STATE != 0).First();
if (other != null)
{
continue;
}
return loc;
}
}
catch (Exception ex)
{
LogHelper.Error("GetShiftStockStart:" + ex.Message, ex);
}
return result;
}
public static bool isRowLock(Location location) {
var db = new SqlHelper().GetInstance();
return db.Queryable().Where(a => a.S_AREA_CODE == location.S_AREA_CODE && a.N_ROW == location.N_ROW && a.S_LOCK_STATE != "无" && a.N_LOCK_STATE != 0).Count() > 0;
}
public static Location GetShiftStockEnd(string area, int row)
{
Location result = null;
try
{
//1.0 获取每一排最大的列
//1.1 判断当前数量是不是满的,如果是满的并且是最大列,需要排除
var listMaxCol = new SqlHelper().GetInstance().Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == row).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList();
//1.1 查到所有有托盘的排
Console.WriteLine("查到所有有托盘的排 ");
var db = new SqlHelper().GetInstance();
var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE == area && a.N_ROW == row).Includes(a => a.LocCntrRel, a => a.CntrItemRel).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList();
if (list.Count > 0)
{
//1.2 查找其它尺寸有托盘或者锁定的排
for (int i = list.Count - 1; i >= 0; i--)
{
//排除已经锁定的货位 和 放满了且是最大列的货位
if (list[i].N_LOCK_STATE != 0 || (list[i].N_CURRENT_NUM == list[i].N_CAPACITY && listMaxCol.Count(a => a.S_CODE == list[i].S_CODE) > 0))
{
Console.WriteLine($"排除已经锁定的货位 和 放满了且是最大列的货位 排{list[i].N_ROW}");
list.Remove(list[i]);
}
else
{
//排有锁也排除
var other = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.S_LOCK_STATE != "无" && a.N_LOCK_STATE != 0).First();
if (other != null)
{
Console.WriteLine($"排除有锁的排{list[i].N_ROW}");
list.Remove(list[i]);
}
}
}
Console.WriteLine($"有托盘排数为{list.Count}");
if (list.Count > 0)
{
//1.3 遍历判断物料类型是否相同
Console.WriteLine("遍历判断物料类型是否相同");
for (int i = 0; i < list.Count; i++)
{
//todo 还需要判断锁
if (list[i].LocCntrRel != null && list[i].LocCntrRel.CntrItemRel != null)
{
if (list[i].N_CURRENT_NUM < list[i].N_CAPACITY)
{
result = list[i];
}
else
{
Console.WriteLine("选择后面空位");
result = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL > list[i].N_COL && a.C_ENABLE == "Y").OrderBy(a => a.N_COL).First();
}
if (result != null)
{
break;
}
}
}
}
}
if (result == null)
{
#region 查找所有数量是空的排
//Console.WriteLine("查找所有数量是空的排");
//2.0 简化查询只查每一排第一列
list = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == row).OrderBy(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList().Where(a => a.N_CURRENT_NUM == 0).ToList();
//2.1 选一个空排
for (int i = 0; i < list.Count; i++)
{
var other = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.S_LOCK_STATE != "无").First();
if (list[i].N_LOCK_STATE == 0 && other == null)
{
//二次校验当前排所有货位都是空的,防止系统数据错乱
var rowSumInfo = db.Queryable().Where(l => l.S_AREA_CODE == area && l.N_ROW == list[i].N_ROW && l.N_CURRENT_NUM != 0).Count();
if (rowSumInfo == 0)
{
result = list[i];
break;
}
}
}
#endregion
}
if (result != null && (!string.IsNullOrEmpty(result.C_ENABLE) && (result.C_ENABLE == "禁用" || result.C_ENABLE == "N")))
{
//禁用了选择后面一个货位
//Console.WriteLine("禁用了选择后面一个货位");
result = db.Queryable().OrderBy(a => a.N_COL).Where(a => a.S_AREA_CODE == area && a.N_ROW == result.N_ROW && (string.IsNullOrEmpty(a.C_ENABLE) || (a.C_ENABLE != "禁用" && a.C_ENABLE != "N")) && a.N_COL > result.N_COL).First();
}
}
catch (Exception ex)
{
LogHelper.Error("GetLocation4InFinish:" + ex.Message, ex);
}
return result;
}
public static List GetLocationList(string area , int row) {
List result = new List ();
try {
var db = new SqlHelper().GetInstance();
result = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == row).Includes(a => a.LocCntrRel, a => a.CntrItemRel).ToList();
}
catch (Exception ex) {
LogHelper.Error("GetLocationList:" + ex.Message, ex);
}
return result;
}
public static List getShiftOrderDetail(string orderNo = null) {
var db = new SqlHelper().GetInstance();
var queryable = db.Queryable()
.LeftJoin((a, b) => a.S_NO == b.S_NO)
.Where((a, b) => b.S_B_STATE == "执行");
if (orderNo != null) {
queryable = queryable.Where((a, b) => a.S_NO == orderNo);
}
return queryable.OrderBy((a,b) => b.T_CREATE ).OrderBy((a, b) => a.T_CREATE).ToList();
}
public static bool updateShiftOrderDetail(TN_YiKuDetail detail) {
bool result = false;
var db = new SqlHelper().GetInstance();
LogHelper.Info("移库完成数量变更参数:" + JsonConvert.SerializeObject(detail), "TSSG");
result = db.Updateable()
.SetColumns(a => new TN_YiKuDetail() { N_COMPLETE_NUM = a.N_COMPLETE_NUM + 1 })
.Where(a => a.S_NO == detail.S_NO
&& a.S_START_AREA == detail.S_START_AREA
&& a.S_START_ROW == detail.S_START_ROW
&& a.S_END_AREA == detail.S_END_AREA
&& a.S_END_ROW == detail.S_END_ROW
)
.ExecuteCommand() > 0;
var completeResult = db.Queryable().Where(a => a.S_NO == detail.S_NO && a.N_QTY > a.N_COMPLETE_NUM).Count() == 0;
if(completeResult) {
result = db.Updateable().SetColumns(a => new TN_YiKuOrder() { S_B_STATE = "完成" }).Where(a => a.S_NO == detail.S_NO).ExecuteCommand() > 0;
}
return result;
}
///
/// 查询物料条码信息列表
///
///
///
public static List getMaltInfoList(string lastTime)
{
var db = new SqlHelper().GetInstance();
return db.Queryable().Where( a => DateTime.Parse(a.last_modify_time) >= DateTime.Parse(lastTime)).OrderByDescending( a => a.last_modify_time).ToList();
}
///
/// 查询物料条码信息列表
///
///
///
public static List getMaltStatusList(string lastTime)
{
var db = new SqlHelper().GetInstance();
return db.Queryable().Where(a => DateTime.Parse(a.last_modify_time) >= DateTime.Parse(lastTime) && a.bld_date == null).OrderByDescending(a => a.last_modify_time).ToList();
}
public static List getOverageList(string lastTime)
{
var db = new SqlHelper().GetInstance();
return db.Queryable().Where(a => DateTime.Parse(a.last_modify_time) >= DateTime.Parse(lastTime) ).OrderByDescending(a => a.last_modify_time).ToList();
}
///
/// 添加wms回报gt AGV回报记录
///
///
public static bool addWmsToGtLokasi(WmsToGtLokasi wmsToGtLokasi)
{
var db = new SqlHelper().GetInstance();
return db.Insertable(wmsToGtLokasi).ExecuteCommand()>0;
}
}
}