using System;
|
using System.Collections.Generic;
|
using SqlSugar;
|
using System.Linq;
|
using System.Linq.Expressions;
|
using Model.InterFaceModel;
|
using Model.ModelDto;
|
using SqlSugar.Extensions;
|
using WMS.Entity.BllSoEntity;
|
using WMS.Entity.Context;
|
using WMS.Entity.DataEntity;
|
using WMS.Entity.SysEntity;
|
using WMS.IBLL.IPdaServer;
|
using Newtonsoft.Json;
|
using WMS.BLL.Logic;
|
using WMS.BLL.LogServer;
|
using WMS.DAL;
|
using WMS.Entity.LogEntity;
|
using Model.ModelDto.BllSoDto;
|
using Utility.Tools;
|
|
namespace WMS.BLL.BllPdaServer
|
{
|
public class PdaSoServer : IPdaSoServer
|
{
|
private static readonly SqlSugarScope Db = DataContext.Db;
|
|
//验证托盘是否存在并是否可出库
|
public string IsEnableOkPalletNo(string palletNo)
|
{
|
try
|
{
|
string sqlMsg = "";
|
var models = Db.Queryable<SysPallets>().Where(m => m.IsDel == "0" && m.PalletNo == palletNo).ToList();
|
|
if (models.Count > 1)
|
{
|
sqlMsg = "-1:存在重复托盘号,请检查!";
|
return sqlMsg;
|
}
|
if (models.Count > 0)
|
{
|
if (models[0].Status == "0")
|
{
|
sqlMsg = "-1:托盘号状态为未使用!";
|
}
|
}
|
else
|
{
|
sqlMsg = "-1:托盘号不存在!";
|
}
|
|
return sqlMsg;
|
}
|
catch (Exception ex)
|
{
|
throw new Exception(ex.Message);
|
}
|
}
|
|
//获取托盘中含有的执行中的单据
|
public List<string> GetRunSoNoticeList(string palletNo)
|
{
|
try
|
{
|
if (string.IsNullOrWhiteSpace(palletNo))//判断托盘是否为空
|
{
|
throw new Exception("托盘码为空,请输入托盘码");
|
}
|
//获取状态为待拣货或者部分拣货的出库单
|
var allotList = Db.Queryable<BllExportAllot>().Where(m => m.IsDel == "0" && (m.Status == "2" || m.Status == "3") && m.PalletNo == palletNo).Select(m => m.SONo).Distinct().Where(m => !string.IsNullOrWhiteSpace(m)).ToList();
|
|
return allotList;
|
}
|
catch (Exception ex)
|
{
|
throw new Exception(ex.Message);
|
}
|
}
|
|
//获取出库托盘上的物料批次(根据托盘码)
|
public List<DetailIdSkuLotNo> GetSoSkuLotNoListByPallet(string palletNo, string soNo)
|
{
|
try
|
{
|
if (string.IsNullOrWhiteSpace(palletNo))//判断托盘是否为空
|
{
|
throw new Exception("托盘码为空,请输入托盘码");
|
}
|
//获取状态为待拣货或者部分拣货的出库单
|
var allotList = Db.Queryable<BllExportAllot>().Where(m => m.IsDel == "0" && (m.Status == "2" || m.Status == "3") && m.PalletNo == palletNo);
|
if (!string.IsNullOrWhiteSpace(soNo))
|
{
|
allotList = allotList.Where(m => m.SONo == soNo);
|
}
|
|
var list = allotList.GroupBy(m => new { m.SODetailNo, m.SkuNo, m.SkuName, m.LotNo }).Select(m => new DetailIdSkuLotNo()
|
{
|
SoDetailId = m.SODetailNo,
|
SkuNo = m.SkuNo,
|
SkuName = m.SkuName,
|
LotNo = m.LotNo,
|
}).ToList();
|
|
return list;
|
}
|
catch (Exception ex)
|
{
|
throw new Exception(ex.Message);
|
}
|
}
|
|
//获取出库口、规格、待拣及已拣数量(根据出库单明细ID、托盘号)
|
public OutPdaInfo GetOutlets(string soDetailId, string palletNo)
|
{
|
try
|
{
|
|
var allotInfo = Db.Queryable<BllExportAllot>().Where(m => m.IsDel == "0" && m.SODetailNo == int.Parse(soDetailId) && m.PalletNo == palletNo && (m.Status == "2" || m.Status == "3")).ToList();
|
|
if (allotInfo.Count > 1)
|
{
|
throw new Exception($"{palletNo}托盘上存在多条相同的分配信息,请核实");
|
}
|
if (allotInfo.Count <= 0)
|
{
|
throw new Exception($"{palletNo}托盘上货物已拣货完毕或不存在拣货信息,请核查!");
|
}
|
var data = allotInfo.First();
|
var data2 = new OutPdaInfo()
|
{
|
OutModel = data.OutMode,
|
Standard = data.Standard,
|
PickQty = data.Qty,
|
PickedQty = data.CompleteQty,
|
BoxexQty = data.BoxexQty
|
};
|
return data2;
|
}
|
catch (Exception e)
|
{
|
throw new Exception(e.Message);
|
}
|
}
|
|
//获取出库单的计划数量和完成
|
public OutPdaInfo GetPlanAndFinishQty(string soDetailId)
|
{
|
try
|
{
|
var detail = Db.Queryable<BllExportNoticeDetail>().First(m => m.Id == int.Parse(soDetailId) && m.IsDel == "0");
|
if (detail == null)
|
{
|
throw new Exception("未查询到出库单的明细");
|
}
|
var data = new OutPdaInfo()
|
{
|
PlanQty = detail.Qty,
|
FinishQty = detail.CompleteQty
|
};
|
return data;
|
}
|
catch (Exception e)
|
{
|
throw new Exception(e.Message);
|
}
|
}
|
|
//获取箱码信息(根据箱码在库存箱码明细中查询)
|
public BoxInfo GetBoxInfo(string boxNo, string boxNo2, string boxNo3)
|
{
|
try
|
{
|
Expression<Func<DataBoxInfo, bool>> item = Expressionable.Create<DataBoxInfo>()
|
.AndIF(!string.IsNullOrWhiteSpace(boxNo), it => it.BoxNo == boxNo)
|
.AndIF(!string.IsNullOrWhiteSpace(boxNo2), it => it.BoxNo2 == boxNo2)
|
.AndIF(!string.IsNullOrWhiteSpace(boxNo3), it => it.BoxNo3 == boxNo3)
|
.And(m => m.IsDel == "0")
|
.ToExpression();//注意 这一句 不能少
|
var info = Db.Queryable<DataBoxInfo>().Where(item).GroupBy(m => m.BoxNo).Select(m => SqlFunc.AggregateSum(m.Qty)).ToList();
|
if (info.Count == 0)
|
{
|
throw new Exception("未在库存中查询到箱码信息");
|
}
|
var data = new BoxInfo()
|
{
|
Qty = info[0]
|
};
|
return data;
|
}
|
catch (Exception e)
|
{
|
throw new Exception(e.Message);
|
}
|
}
|
|
//获取托盘拣货明细的信息
|
public List<BoxInfo> GetComDetailByPalletNo(string palletNo, string soDetailId)
|
{
|
try
|
{
|
var allotInfo = Db.Queryable<BllExportAllot>().Where(m => m.IsDel == "0" && m.SODetailNo == int.Parse(soDetailId) && m.PalletNo == palletNo && (m.Status == "2" || m.Status == "3")).ToList();
|
|
if (allotInfo.Count > 1)
|
{
|
throw new Exception($"{palletNo}托盘上存在多条相同的分配信息,请核实");
|
}
|
if (allotInfo.Count <= 0)
|
{
|
throw new Exception($"{palletNo}托盘上货物已拣货完毕或不存在拣货信息,请核查!");
|
}
|
var data = allotInfo.First();
|
var list = new List<BoxInfo>();
|
var t = new BoxInfo()
|
{
|
SkuNo = data.SkuNo,
|
SkuName = data.SkuName,
|
LotNo = data.LotNo,
|
PickedQty = data.CompleteQty,
|
};
|
list.Add(t);
|
//var info = Db.Queryable<BllCompleteDetail>().Where(m => m.IsDel == "0" && m.ExportAllotId == data.Id).ToList();
|
//var list = new List<BoxInfo>();
|
//foreach (var item in info)
|
//{
|
// var t = new BoxInfo()
|
// {
|
// BoxNo = item.BoxNo,
|
// SkuNo = item.SkuNo,
|
// SkuName = item.SkuName,
|
// LotNo = item.LotNo,
|
// PickedQty = item.CompleteQty,
|
// };
|
// list.Add(t);
|
//}
|
|
return list;
|
}
|
catch (Exception e)
|
{
|
throw new Exception(e.Message);
|
}
|
}
|
|
//出库pda拣货
|
public void SoSetPick(string soNo, string soDetailId, string palletNo, int pickQty, int userId)
|
{
|
Db.BeginTran();
|
try
|
{
|
#region 判断
|
|
if (string.IsNullOrWhiteSpace(soNo))
|
{
|
throw new Exception("出库单据不能为空");
|
}
|
if (string.IsNullOrWhiteSpace(soDetailId))
|
{
|
throw new Exception("出库物料-批次不能为空");
|
}
|
if (string.IsNullOrWhiteSpace(palletNo))
|
{
|
throw new Exception("托盘码不能为空");
|
}
|
//if (string.IsNullOrWhiteSpace(boxNo))
|
//{
|
// throw new Exception("箱码不能为空");
|
//}
|
//出库单
|
var notice = Db.Queryable<BllExportNotice>().First(m => m.IsDel == "0" && m.SONo == soNo);
|
if (notice == null)
|
{
|
throw new Exception("未查询到该出库单的信息");
|
}
|
if (notice.Status != "3")
|
{
|
throw new Exception("出库单的状态不是正在执行,不能拣货");
|
}
|
//出库单明细
|
var noticeDetail = Db.Queryable<BllExportNoticeDetail>()
|
.First(m => m.IsDel == "0" && m.Id == int.Parse(soDetailId));
|
if (noticeDetail == null)
|
{
|
throw new Exception("未查询到该出库单明细的信息");
|
}
|
//出库分配信息
|
var allot = Db.Queryable<BllExportAllot>().First(m =>
|
m.IsDel == "0" && (m.Status == "2" || m.Status == "3") && m.SONo == soNo &&
|
m.SODetailNo == int.Parse(soDetailId) && m.PalletNo == palletNo);
|
if (allot == null)
|
{
|
throw new Exception("未查询到该托盘的分配信息");
|
}
|
//剩余拣货数量(待拣减去已拣)
|
var needQty = allot.Qty - allot.CompleteQty;
|
if (needQty <= 0)
|
{
|
throw new Exception("当前托盘拣货数量已完成,请勿重复拣货");
|
}
|
if (pickQty > needQty)
|
{
|
throw new Exception("拣货数量大于当前剩余的拣货数量,请核实!");
|
}
|
//库存
|
var stock = Db.Queryable<DataStock>().First(m =>
|
m.IsDel == "0" && m.SkuNo == noticeDetail.SkuNo && m.LotNo == noticeDetail.LotNo);
|
if (stock == null)
|
{
|
throw new Exception("未查询到该托盘分配的库存信息!");
|
}
|
//库存明细
|
var stockDetail = Db.Queryable<DataStockDetail>().First(m => m.IsDel == "0" && m.Id == allot.StockId);
|
if (stockDetail == null)
|
{
|
throw new Exception("未查询到该托盘分配的库存明细信息!");
|
}
|
//库存箱码
|
var stockBox = Db.Queryable<DataBoxInfo>().Where(m => m.IsDel == "0" && m.StockDetailId == stockDetail.Id).ToList();
|
var sku = Db.Queryable<SysMaterials>().First(m => m.IsDel == "0" && m.SkuNo == stock.SkuNo);
|
#endregion
|
|
#region 箱码判断
|
|
//List<DataBoxInfo> boxInfos;
|
//if (!string.IsNullOrWhiteSpace(boxNo3)) //是否整箱
|
//{
|
// var boxInfo = Db.Queryable<DataBoxInfo>().Where(m => m.IsDel == "0" && m.BoxNo3 == boxNo3);
|
// boxInfos = boxInfo.ToList();
|
// if (boxInfo.Count() == 0)
|
// {
|
// throw new Exception("未查询到该箱码及追溯码的信息");
|
// }
|
// if (boxInfo.Count() > 1)
|
// {
|
// throw new Exception("该箱码及追溯码的信息大于1,信息错误,请核实!");
|
// }
|
|
// if (boxInfo.Any(m => m.PalletNo != palletNo))
|
// {
|
// throw new Exception("该托盘与箱码没有绑定关系");
|
// }
|
// var boxQty = boxInfo.First().Qty;
|
// if (boxQty > needQty)
|
// {
|
// throw new Exception("拣货数量不能大于剩余待拣数量");
|
// }
|
|
//}
|
//else if(!string.IsNullOrWhiteSpace(boxNo2)) //是否整盒
|
//{
|
// var boxInfo = Db.Queryable<DataBoxInfo>().Where(m => m.IsDel == "0" && m.BoxNo2 == boxNo2);
|
// boxInfos = boxInfo.ToList();
|
// if (boxInfo.Count() == 0)
|
// {
|
// throw new Exception("未查询到该箱码及盒码的信息");
|
// }
|
// if (boxInfo.Any(m => m.PalletNo != palletNo))
|
// {
|
// throw new Exception("该托盘与箱码没有绑定关系");
|
// }
|
// var boxQty = boxInfo.GroupBy(m => m.BoxNo2).Select(m => SqlFunc.AggregateSum(m.Qty)).ToList();
|
// if (boxQty[0] > needQty)
|
// {
|
// throw new Exception("拣货数量不能大于剩余待拣数量");
|
// }
|
//}
|
//else
|
//{
|
// if (string.IsNullOrWhiteSpace(boxNo)) //判断支码是否为空
|
// {
|
// throw new Exception("追溯码不能为空");
|
// }
|
// var boxInfo = Db.Queryable<DataBoxInfo>().Where(m => m.IsDel == "0" && m.BoxNo == boxNo);
|
// boxInfos = boxInfo.ToList();
|
// if (boxInfo.Count() == 0)
|
// {
|
// throw new Exception("未查询到该箱码的信息");
|
// }
|
// if (boxInfo.Any(m => m.PalletNo != palletNo))
|
// {
|
// throw new Exception("该托盘与箱码没有绑定关系");
|
// }
|
// var boxQty = boxInfo.GroupBy(m => m.BoxNo).Select(m => SqlFunc.AggregateSum(m.Qty)).ToList();
|
// if (boxQty[0] > needQty)
|
// {
|
// throw new Exception("拣货数量不能大于箱内剩余待拣数量");
|
// }
|
|
//}
|
|
#endregion
|
|
var comDetail = Db.Queryable<BllCompleteDetail>().First(m => m.IsDel == "0" && m.PalletNo == palletNo && m.ExportAllotId == allot.Id);
|
var comList = new List<BllCompleteDetail>();
|
foreach (var item in stockBox)
|
{
|
if (comDetail != null)
|
{
|
comDetail.CompleteQty += pickQty;
|
Db.Updateable(comDetail).ExecuteCommand();
|
continue;
|
}
|
else
|
{
|
//添加拣货明细
|
var completeDetail = new BllCompleteDetail()
|
{
|
SONo = soNo,
|
SODetailNo = int.Parse(soDetailId),
|
ExportAllotId = allot.Id,
|
StockId = allot.StockId,
|
BoxNo = item.BoxNo,
|
BoxNo2 = item.BoxNo2,
|
BoxNo3 = item.BoxNo3,
|
|
LotNo = allot.LotNo,
|
LotText = allot.LotText,
|
SupplierLot = allot.SupplierLot,
|
SkuNo = allot.SkuNo,
|
SkuName = allot.SkuName,
|
Standard = allot.Standard,
|
PalletNo = palletNo,
|
CompleteQty = pickQty,
|
|
CreateUser = userId
|
};
|
comList.Add(completeDetail);
|
}
|
|
if (notice.Type == "4")//判断是否是质检取样拣货
|
{
|
continue;
|
}
|
item.Qty -= pickQty;
|
if (item.Qty == 0)
|
{
|
//删除库存箱码明细
|
Db.Deleteable(item).ExecuteCommand();
|
}
|
else
|
{
|
Db.Updateable(item).ExecuteCommand();
|
}
|
|
}
|
|
if (comList.Count > 0)
|
{
|
Db.Insertable(comList).ExecuteCommand();
|
}
|
|
//修改出库分配信息
|
allot.CompleteQty += pickQty;
|
allot.Status = allot.Qty == allot.CompleteQty ? "5" : "3";
|
Db.Updateable(allot).ExecuteCommand();
|
|
//删除或修改库存
|
if (notice.Type != "4")
|
{
|
stock.Qty -= pickQty;
|
}
|
stock.LockQty -= pickQty;
|
if (stock.Qty <= 0)
|
{
|
Db.Deleteable(stock).ExecuteCommand();
|
}
|
else
|
{
|
Db.Updateable(stock).ExecuteCommand();
|
}
|
|
//删除或修改库存明细
|
if (notice.Type != "4")
|
{
|
stockDetail.Qty -= pickQty;
|
}
|
stockDetail.LockQty -= pickQty;
|
if (stockDetail.LockQty > 0 && stockDetail.LockQty < stockDetail.Qty)
|
{
|
stockDetail.Status = "1";
|
}
|
else if (stockDetail.LockQty == 0)
|
{
|
stockDetail.Status = "0";
|
}
|
if (stockDetail.Qty <= 0)
|
{
|
Db.Deleteable(stockDetail).ExecuteCommand();
|
}
|
else
|
{
|
Db.Updateable(stockDetail).ExecuteCommand();
|
}
|
|
var num2 = Db.Queryable<DataStockDetail>().Count(m => m.IsDel == "0" && m.PalletNo == palletNo);
|
if (num2 <= 0)
|
{
|
//改变托盘状态
|
var pallet = Db.Queryable<SysPallets>().First(m => m.PalletNo == palletNo && m.IsDel == "0");
|
if (pallet == null)
|
{
|
throw new Exception("未在托盘表中查询到托盘信息");
|
}
|
pallet.Status = "0";
|
Db.Updateable(pallet).ExecuteCommand();
|
}
|
//修改出库单明细拣货数量
|
noticeDetail.CompleteQty += pickQty;
|
if (noticeDetail.Qty == noticeDetail.CompleteQty)
|
{
|
noticeDetail.Status = "3";
|
}
|
Db.Updateable(noticeDetail).ExecuteCommand();
|
|
var num = Db.Queryable<BllExportNoticeDetail>()
|
.Count(m => m.IsDel == "0" && m.SONo == soNo && m.CompleteQty < m.Qty);
|
if (num <= 0)
|
{
|
notice.Status = "4"; //更改为执行完成
|
Db.Updateable(notice).ExecuteCommand();
|
}
|
|
|
#region 库存记录
|
|
//获取对应物料当天库存信息
|
string strinfo = $"select top 1 * from DataStockInfo where IsDel = '0' and SkuNo = '{stockDetail.SkuNo}' order by CreateTime desc";
|
var datainfo = Db.Ado.SqlQuerySingle<DataStockInfo>(strinfo);
|
|
//datainfo.ArrivalQty += item.Qty;//入库数量
|
datainfo.ExportQty += pickQty;//出库数量
|
datainfo.BalanceQty -= pickQty;//结存数量
|
datainfo.YearBalanceQty -= pickQty;//结存数量(月)
|
datainfo.YearExportQty += pickQty;//出库数量(月)
|
Db.Updateable(datainfo).ExecuteCommand();
|
|
#endregion
|
|
|
Db.CommitTran();
|
|
}
|
catch (Exception e)
|
{
|
Db.RollbackTran();
|
throw new Exception(e.Message);
|
}
|
}
|
|
//下发空托出库
|
public List<OutCommandDto> IssuePlnOutHouse(int num, string outMode)
|
{
|
try
|
{
|
throw new NotImplementedException();
|
}
|
catch (Exception e)
|
{
|
throw new Exception(e.Message);
|
}
|
|
}
|
|
//平库出库完成
|
public void PlaneExportSuccess(string soNo, string palletNo)
|
{
|
try
|
{
|
|
}
|
catch (Exception e)
|
{
|
throw new Exception(e.Message);
|
}
|
}
|
|
#region 申请空托盘
|
|
/// <summary>
|
/// pda申请空托出库
|
/// </summary>
|
/// <param name="skuNo">物料号</param>
|
/// <param name="userId">操作人</param>
|
/// <param name="url">下发人</param>
|
/// <param name="origin">来源PC、否则为空</param>
|
/// <returns></returns>
|
public List<OutCommandDto> PalletLocation(string skuNo, int userId, string url, string origin)
|
{
|
|
OutCommandDto comDto;//返回wcs的入库命令
|
try
|
{
|
var outDto1 = new List<OutCommandDto>(); //先出库数据的集合(深度为1的储位)
|
var outDto2 = new List<OutCommandDto>(); //后出库数据的集合(深度为2的储位)
|
var moveDto = new List<OutCommandDto>(); //要移库数据的集合
|
var com = new Common();
|
|
Db.BeginTran();
|
|
//先进行分配 因为无出库单
|
|
//此物品直接拣货成功
|
//根据托盘号前往库位查询库存明细表信息
|
//获取以后根据最大任务号生成任务
|
|
//判断储位信息 深度为1 直接出库并下发出库任务 同时库存明细表中 增加分配数量 锁定数量 出库后直接拣货完成 更改库存表状态
|
//深度为2 先进行移库 再下发出库任务 下发移库任务和出库任务同时下发 移库时 修改库存明细表状态为 移库锁定 锁定数量 库存总表增加锁定数量 分配最近储位 下发移库任务
|
|
//新增任务
|
|
#region 空托盘出库业务
|
|
#region 判断
|
|
//获取物料信息
|
var sku = Db.Queryable<SysMaterials>().First(m => m.SkuNo == skuNo && m.IsDel == "0");
|
|
var roadway = Db.Queryable<SysStorageRoadway>().Where(a => a.IsDel == "0" && a.WareHouseNo == "W03" && a.Status == "0").Select(a => a.RoadwayNo).ToList();
|
if (roadway.Count == 0)
|
{
|
throw new Exception("当前巷道已被全部禁用!");
|
}
|
|
//先获取库存总表是否存在该空托盘在库中
|
var dataStock = Db.Queryable<DataStock>().First(m => m.SkuNo == skuNo && m.IsDel == "0" && (m.Qty - m.FrozenQty - m.LockQty - m.FrozenQty) > 0);
|
if (dataStock == null)
|
{
|
//库存中没有该空托盘剁
|
|
throw new Exception("库存中没有该空托盘剁!");
|
}
|
//根据库存总表获取库存明细信息 库存状态为待分配和部分分配
|
var dataStockDeali = Db.Queryable<DataStockDetail>().Where(m => roadway.Contains(m.RoadwayNo) && m.SkuNo == skuNo && m.IsDel == "0" && (m.Qty - m.FrozenQty - m.LockQty - m.FrozenQty) > 0 && m.Status == "0" || m.Status == "1").OrderBy(m => m.CompleteTime).ToList();
|
//判断空托盘是否有待分配和部分分配
|
if (dataStockDeali.Count == 0)
|
{
|
//库内该空托盘没有待分配和部分分配的
|
|
throw new Exception("库内该空托盘没有待分配和部分分配的!");
|
}
|
|
//判断是否已存在该任务 存在返回
|
var logTasks = Db.Queryable<LogTask>().First(m => m.IsDel == "0" && m.Type == "1" && m.PalletNo == dataStockDeali[0].PalletNo && (m.Status == "1" || m.Status == "0"));
|
if (logTasks != null)
|
{
|
|
throw new Exception("已存在正在执行或等待执行的托盘任务!");
|
}
|
|
#endregion
|
|
#region 包装信息
|
|
////包装信息
|
//var packList = Db.Queryable<SysPackag>().First(m => m.PackagNo == sku.PackagNo && m.IsDel == "0");
|
//if (packList == null)
|
//{
|
// throw new Exception("未查询到物料包装");
|
//}
|
//var pNum = 0;//托盘物品数量
|
//var bNum = 0;//箱物品数量
|
//if (packList.L5Num.HasValue)
|
//{
|
// pNum = Convert.ToInt32(packList.L5Num);
|
// bNum = Convert.ToInt32(packList.L4Num);
|
//}
|
//else if (packList.L4Num.HasValue)
|
//{
|
// pNum = Convert.ToInt32(packList.L4Num);
|
// bNum = Convert.ToInt32(packList.L3Num);
|
//}
|
//else if (packList.L3Num.HasValue)
|
//{
|
// pNum = Convert.ToInt32(packList.L3Num);
|
// bNum = Convert.ToInt32(packList.L2Num);
|
//}
|
//else if (packList.L2Num.HasValue)
|
//{
|
// pNum = Convert.ToInt32(packList.L2Num);
|
// bNum = Convert.ToInt32(packList.L1Num);
|
//}
|
//else if (packList.L1Num.HasValue)
|
//{
|
// pNum = Convert.ToInt32(packList.L1Num);
|
// bNum = Convert.ToInt32(packList.L1Num);
|
//}
|
//if (pNum == 0)
|
//{
|
// throw new Exception("未查询到物料包装托箱关系信息");
|
//}
|
#endregion
|
|
#region 分配
|
|
//进行分配空托盘
|
var assign = new AllotSku();
|
//取合适库存商品
|
//Dictionary<int, int> stockQtyDic = new Dictionary<int, int>();//托出库物品数
|
//分配货物
|
//int qty = assign.AllotPallets(dataStockDeali, (int)dataStockDeali[0].Qty, (int)dataStockDeali[0].Qty, 1, stockQtyDic);
|
|
//获取库存明细信息
|
DataStockDetail stockDeali = new DataStockDetail();
|
|
foreach (var sc in dataStockDeali)
|
{
|
stockDeali = dataStockDeali.First(it => it.Id == sc.Id);
|
//var s = dataStockDeali.FirstOrDefault(m => m.Id == sc.Id);
|
//添加分配表信息
|
var allot = new BllExportAllot
|
{
|
SONo = "",
|
WaveNo = "",
|
SODetailNo = 0,
|
StockId = sc.Id,
|
LotNo = "",
|
LotText = "",
|
SupplierLot = "",
|
SkuNo = sc.SkuNo,
|
SkuName = sc.SkuName,
|
Standard = sc.Standard,
|
PalletNo = sc.PalletNo,
|
IsBale = "0", //是否裹包
|
IsBelt = "0", //是否打带
|
|
BoxexQty = sc.Qty,
|
Qty = (int)sc.Qty,
|
CompleteQty = 0,
|
Status = "0",
|
LogisticsId = 0,
|
IsAdvance = "0",
|
OutMode = "",//出库口
|
|
CreateUser = 0,
|
CreateTime = DateTime.Now
|
};
|
Db.Insertable(allot).ExecuteCommand();
|
dataStock.LockQty += (int)sc.Qty;
|
sc.LockQty += sc.Qty;
|
|
if (sc.LockQty == sc.Qty)
|
{
|
sc.Status = "2";
|
}
|
else
|
{
|
sc.Status = "1";
|
}
|
Db.Updateable(dataStock).ExecuteCommand(); //库存总表锁定数量修改
|
var sd = Db.Updateable(sc).UpdateColumns(it => new { it.LockQty, it.Status }).ExecuteCommand(); //库存明细总表锁定数量修改
|
break;
|
}
|
|
#endregion
|
|
#region 出库
|
|
//所有要出库的出库分配信息(未下发的信息和待拣货的信息)
|
var list = Db.Queryable<BllExportAllot>().Where(a => a.IsDel == "0" && a.SkuNo == stockDeali.SkuNo && a.PalletNo == stockDeali.PalletNo && (a.Status == "0" || (a.Status == "2" && a.CompleteQty == 0))).ToList();
|
if (list.Count == 0) //判断是否有需要下发的出库流水
|
{
|
throw new Exception("当前出库单据无需要下发的托盘");
|
}
|
|
//要出库的托盘集合
|
var outLpnList = list.Select(m => m.PalletNo).ToList();
|
//要出库的明细集合
|
var outStockDetail = Db.Queryable<DataStockDetail>().Where(m => m.IsDel == "0" && outLpnList.Contains(m.PalletNo)).ToList();
|
|
|
|
//记录错误信息的集合
|
var flagList = new List<int>();//1:当前要出库的储位正在移出、2 出库的托盘储位信息错误(在储位表中未查询到)、3储位损坏不能出库、4 要出库的托盘正在入库,5 双深度出库前面储位是入库中或者移入中
|
|
//循环分配的信息生成出库任务
|
foreach (var item in list)
|
{
|
var taskNoStr = "";
|
var stockDetail = outStockDetail.First(m => m.PalletNo == item.PalletNo);
|
// 储位号
|
var locateNo = stockDetail.LocatNo;
|
//托盘上物料(用于判断物料是否是桶装类型)
|
var skuinfo = Db.Queryable<SysMaterials>().First(m => m.SkuNo == item.SkuNo);
|
#region 判断
|
|
//判断托盘是否在库内(不在库内)
|
if (string.IsNullOrWhiteSpace(locateNo))
|
{
|
//判断托盘是否在入库中
|
var imBl = com.GetImTask(item.PalletNo);
|
if (imBl != null)
|
{
|
flagList.Add(4);
|
continue;
|
}
|
//(状态为待拣货的 1)
|
if (item.Status == "0")
|
{
|
//if (sku.Type == "2" || sku.Type == "3" || sku.Type == "4")//桶装类型手持拣货
|
//{
|
//}
|
//如果不在仓库内,当前分配信息直接更新出库完成
|
item.Status = "2";//状态
|
//item.OutMode = "1号口";//出库口
|
Db.Updateable(item).ExecuteCommand();
|
|
}
|
continue;
|
}
|
|
var locate = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == locateNo && m.IsDel == "0");//当前出库的储位信息
|
if (locate == null)
|
{
|
flagList.Add(2);
|
continue;
|
}
|
//判断储位标志是否为损坏
|
if (locate.Flag == "2")
|
{
|
flagList.Add(3);
|
continue;
|
}
|
|
#endregion
|
|
if (locate.Status == "1") //有物品
|
{
|
if (locate.Depth == "01") //深度为1
|
{
|
#region 添加出库任务
|
|
var taskNo = new Common().GetMaxNo("TK");
|
var exTask = new LogTask //出库任务
|
{
|
TaskNo = taskNo,
|
Sender = "WMS",
|
Receiver = "WCS",
|
IsSuccess = 0, //是否下发成功 0失败 1成功
|
|
StartLocat = locate.LocatNo,//起始位置
|
EndLocat = "",//目标位置
|
PalletNo = item.PalletNo,//托盘码
|
IsSend = 1,//是否可再次下发
|
IsCancel = 1,//是否可取消
|
IsFinish = 1,//是否可完成
|
Type = "1",//任务类型 0 入库任务 1 出库任务 2 移库任务
|
Status = "0",//任务状态0:等待执行1正在执行2执行完成
|
OrderType = "1",//0 入库单 1 出库单 2 盘点单 3 移库单
|
Msg = locate.LocatNo + "的出库任务"
|
};
|
Db.Insertable(exTask).ExecuteCommand();
|
|
outDto1.Add(new OutCommandDto()
|
{
|
StartRoadway = locate.RoadwayNo, //起始巷道
|
PalletNo = item.PalletNo,//托盘号
|
StartLocat = locate.LocatNo, // 起始位置
|
EndLocat = "28", // 目标位置
|
TaskNo = exTask.TaskNo, // 任务号
|
Type = "1",// 任务类型 (出库)
|
OutMode = "", //目标地址
|
Order = 1,
|
SkuType = sku.Type, //物料类型
|
LotNo = item.LotNo, // 批次
|
IsBale = item.IsBale, //是否裹包
|
IsBelt = item.IsBelt, //是否打带
|
Qty = item.Qty, //拣货数量
|
//FullQty = (int)item.BoxexQty, //托盘数量
|
PalletType = stockDetail.PalletType, //托盘类型(有无子托)0||空||null:无子托盘1:有子托盘
|
});
|
taskNoStr = exTask.TaskNo;
|
#endregion
|
|
}
|
else if (locate.Depth == "02") //深度为2
|
{
|
//获取出库深度为2储位前面的储位信息
|
var slotBefore = com.GetLocateNoDepth1(locate.WareHouseNo, locate.LocatNo);
|
if (slotBefore.Status == "1") //前面的储位有货物、进行移库操作
|
{
|
//要出库深度为2的储位前面的储位中货物是否要出库
|
var isout = outStockDetail.Count(m => m.LocatNo == slotBefore.LocatNo);
|
|
if (isout <= 0) //进行移库
|
{
|
//去库存表中找到储位对应的托盘码操作
|
var stockNew = Db.Queryable<DataStockDetail>().First(m => m.LocatNo == slotBefore.LocatNo);
|
if (stockNew == null)
|
{
|
var slotChange = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == slotBefore.LocatNo);
|
slotChange.Status = "0";
|
Db.Updateable(slotChange).ExecuteCommand();
|
}
|
else
|
{
|
//获取移库的库位
|
var newSlot = MoveAddress(slotBefore.LocatNo, slotBefore.RoadwayNo, slotBefore.AreaNo);
|
//当前移库库位的储位信息
|
var locatey = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == newSlot && m.IsDel == "0");
|
if (!string.IsNullOrEmpty(newSlot))
|
{
|
#region 添加出库时发生的移库任务
|
|
var exYkTaskNo = new Common().GetMaxNo("TK");
|
var exYkTask = new LogTask //出库时产生移库任务
|
{
|
TaskNo = exYkTaskNo,
|
Sender = "WMS",
|
Receiver = "WCS",
|
IsSuccess = 0, //是否下发成功 0失败 1成功
|
|
StartLocat = stockNew.LocatNo,//起始位置
|
EndLocat = newSlot,//目标位置
|
PalletNo = stockNew.PalletNo,//托盘码
|
IsSend = 1,//是否可再次下发
|
IsCancel = 1,//是否可取消
|
IsFinish = 1,//是否可完成
|
Type = "2",//任务类型 0 入库任务 1 出库任务 2 移库任务
|
Status = "0",//任务状态0:等待执行1正在执行2执行完成
|
OrderType = "1",//0 入库单 1 出库单 2 盘点单 3 移库单
|
|
Msg = stockNew.LocatNo + " ==>> " + newSlot + "的移库任务",
|
};
|
Db.Insertable(exYkTask).ExecuteCommand();
|
|
moveDto.Add(new OutCommandDto()
|
{
|
StartRoadway = slotBefore.RoadwayNo, //起始巷道
|
PalletNo = stockNew.PalletNo,//托盘号
|
StartLocat = stockNew.LocatNo, // 起始位置
|
EndLocat = newSlot, // 目标位置
|
EndRoadway = locatey.RoadwayNo, // 目标巷道
|
TaskNo = exYkTask.TaskNo, // 任务号
|
Type = "2",// 任务类型 (移库)
|
OutMode = "", //目标地址
|
Order = 1,
|
SkuType = sku.Type, //物料类型
|
LotNo = stockNew.LotNo,
|
Qty = 0, //拣货数量
|
//FullQty = (int)stockNew.Qty, //托盘数量
|
PalletType = stockNew.PalletType, //托盘类型(有无子托)0||空||null:无子托盘1:有子托盘
|
});
|
#endregion
|
|
#region 改变储位装填
|
var slotChange = Db.Queryable<SysStorageLocat>().First(m => m.Id == slotBefore.Id);
|
var slotChange2 = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == newSlot);
|
slotChange.Status = "5"; //改变状态(正在移出)
|
slotChange2.Status = "4"; // 改变状态(正在移入)
|
Db.Updateable(slotChange).ExecuteCommand();
|
Db.Updateable(slotChange2).ExecuteCommand();
|
#endregion
|
}
|
else
|
{
|
#region 添加出库任务
|
|
var exYkTaskNo1 = new Common().GetMaxNo("TK");
|
var exYkTask1 = new LogTask //出库移库没有库位了进行出库任务
|
{
|
TaskNo = exYkTaskNo1,
|
Sender = "WMS",
|
Receiver = "WCS",
|
IsSuccess = 0, //是否下发成功 0失败 1成功
|
|
StartLocat = stockNew.LocatNo,//起始位置
|
EndLocat = "",//目标位置
|
PalletNo = stockNew.PalletNo,//托盘码
|
IsSend = 1,//是否可再次下发
|
IsCancel = 1,//是否可取消
|
IsFinish = 1,//是否可完成
|
Type = "1",//任务类型 0 入库任务 1 出库任务 2 移库任务
|
Status = "0",//任务状态0:等待执行1正在执行2执行完成
|
OrderType = "1",//0 入库单 1 出库单 2 盘点单 3 移库单
|
Msg = locate.LocatNo + "的出库任务"
|
};
|
Db.Insertable(exYkTask1).ExecuteCommand();
|
|
outDto1.Add(new OutCommandDto()
|
{
|
StartRoadway = slotBefore.RoadwayNo, //起始巷道
|
PalletNo = stockNew.PalletNo,//托盘号
|
StartLocat = stockNew.LocatNo, // 起始位置
|
EndLocat = "28", // 目标位置
|
TaskNo = exYkTask1.TaskNo, // 任务号
|
Type = "1",// 任务类型 (出库)
|
OutMode = "", //目标地址
|
Order = 1,
|
SkuType = sku.Type, //物料类型
|
LotNo = "", // 批次
|
IsBale = "0", //是否裹包
|
IsBelt = "0", //是否打带
|
Qty = 0, //拣货数量
|
//FullQty = (int)stockNew.Qty, //托盘数量
|
PalletType = stockNew.PalletType, //托盘类型(有无子托)0||空||null:无子托盘1:有子托盘
|
});
|
#endregion
|
|
#region MyRegion
|
|
var slotChange = Db.Queryable<SysStorageLocat>().First(m => m.Id == slotBefore.Id);
|
slotChange.Status = "3"; //改变状态(正在出库)
|
Db.Updateable(slotChange).ExecuteCommand();
|
|
#endregion
|
}
|
}
|
}
|
}
|
else if (slotBefore.Status == "2" || slotBefore.Status == "4") //前面储位状态是入库中或者移入中
|
{
|
flagList.Add(5);
|
continue;
|
}
|
|
#region 添加出库任务
|
|
var taskNo1 = new Common().GetMaxNo("TK");
|
var exTask1 = new LogTask //出库任务
|
{
|
TaskNo = taskNo1,
|
Sender = "WMS",
|
Receiver = "WCS",
|
IsSuccess = 0, //是否下发成功 0失败 1成功
|
|
StartLocat = locate.LocatNo,//起始位置
|
EndLocat = "",//目标位置
|
PalletNo = item.PalletNo,//托盘码
|
IsSend = 1,//是否可再次下发
|
IsCancel = 1,//是否可取消
|
IsFinish = 1,//是否可完成
|
Type = "1",//任务类型 0 入库任务 1 出库任务 2 移库任务
|
Status = "0",//任务状态0:等待执行1正在执行2执行完成
|
OrderType = "1",//0 入库单 1 出库单 2 盘点单 3 移库单
|
Msg = locate.LocatNo + "的出库任务"
|
};
|
Db.Insertable(exTask1).ExecuteCommand();
|
|
outDto2.Add(new OutCommandDto()
|
{
|
StartRoadway = locate.RoadwayNo, //起始巷道
|
PalletNo = item.PalletNo,//托盘号
|
StartLocat = locate.LocatNo, // 起始位置
|
EndLocat = "28", // 目标位置
|
TaskNo = exTask1.TaskNo, // 任务号
|
Type = "1",// 任务类型 (出库)
|
OutMode = "", //目标地址
|
Order = 1,
|
SkuType = sku.Type, //物料类型
|
IsBale = item.IsBale, //是否裹包
|
IsBelt = item.IsBelt, //是否打带
|
Qty = item.Qty, //拣货数量
|
//FullQty = (int)item.BoxexQty, //托盘数量
|
PalletType = stockDetail.PalletType, //托盘类型(有无子托)0||空||null:无子托盘1:有子托盘
|
});
|
taskNoStr = exTask1.TaskNo;
|
#endregion
|
|
}
|
|
|
#region 改变数据
|
if (item.Status == "0")//判断托盘是否下发过
|
{
|
var noticeDetail = Db.Queryable<BllExportNoticeDetail>().First(m => m.IsDel == "0" && m.Id == item.SODetailNo);
|
if (noticeDetail != null) //更新出库单据的下发数量
|
{
|
noticeDetail.FactQty += item.Qty;
|
Db.Updateable(noticeDetail).ExecuteCommand();
|
}
|
}
|
item.TaskNo = taskNoStr; // 出库分配信息中更新任务号
|
item.Status = "1"; // 出库分配信息状态改为正在执行
|
Db.Updateable(item).ExecuteCommand();
|
locate.Status = "3"; //要出库的储位改变状态 正在出库
|
Db.Updateable(locate).ExecuteCommand();
|
|
#endregion
|
|
flagList.Add(0);
|
}
|
else if (locate.Status == "3") //出库中
|
{
|
if (sku.Type == "2" || sku.Type == "3" || sku.Type == "4")
|
{
|
continue;
|
}
|
#region 改变数据
|
//判断是否是已经出过库又回库(状态为待拣货的 1)
|
if (item.Status == "0")
|
{
|
var noticeDetail = Db.Queryable<BllExportNoticeDetail>().First(m => m.IsDel == "0" && m.Id == item.SODetailNo);
|
if (noticeDetail != null) //更新出库单据的下发数量
|
{
|
noticeDetail.FactQty += item.Qty;
|
Db.Updateable(noticeDetail).ExecuteCommand();
|
}
|
}
|
var taskNo = Db.Queryable<LogTask>().First(m => m.OrderType == "1" && m.TaskNo != item.TaskNo && m.Status == "1" && m.PalletNo == item.PalletNo);
|
item.TaskNo = taskNo.TaskNo;
|
item.Status = "1"; // 出库分配信息状态改为正在执行
|
Db.Updateable(item).ExecuteCommand();
|
|
#endregion
|
}
|
else if (locate.Status == "5") //移出中
|
{
|
flagList.Add(1);
|
}
|
}
|
|
//先移库后出库
|
outDto1.AddRange(moveDto);
|
outDto1.AddRange(outDto2);
|
//var time1 = DateTime.Now;//发送时间 .ToString("yyyy-MM-dd HH:mm:ss")
|
//var time2 = DateTime.Now;//返回时间 .ToString("yyyy-MM-dd HH:mm:ss")
|
//// 正式运行程序放开
|
//var list2 = outDto1.Select(m => m.TaskNo).ToList();
|
//var jsonData = JsonConvert.SerializeObject(outDto1);
|
////更改任务的发送返回时间//
|
//new TaskServer().EditTaskIssueOk(list2, time1, time2);
|
if (outDto1.Count > 0)
|
{
|
// 正式运行程序放开
|
var list2 = outDto1.Select(m => m.TaskNo).ToList();
|
var jsonData = JsonConvert.SerializeObject(outDto1);
|
string response = "";
|
|
try
|
{
|
var time1 = DateTime.Now;//发送时间 .ToString("yyyy-MM-dd HH:mm:ss")
|
response = HttpHelper.DoPost(url, jsonData, "下发给WCS出库命令", "WCS");
|
var time2 = DateTime.Now;//返回时间 .ToString("yyyy-MM-dd HH:mm:ss")
|
|
//解析返回数据
|
var wcsModel = JsonConvert.DeserializeObject<WcsModel>(response);
|
if (wcsModel.stateCode == 1)
|
{
|
//更改任务的发送返回时间//
|
new TaskServer().EditTaskIssueOk(list2, time1, time2);
|
//str += "下发成功";
|
}
|
if (wcsModel.stateCode == -1)
|
{
|
new TaskServer().EditTaskIssueNo(list2, time1, time2, wcsModel.errMsg);
|
throw new Exception(wcsModel.errMsg);
|
}
|
}
|
catch (Exception ex)
|
{
|
throw new Exception(ex.Message);
|
}
|
|
}
|
|
#endregion
|
|
#endregion
|
|
if (origin == "PC")
|
{
|
//添加操作日志记录
|
var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", skuNo, "出库", $"选择{skuNo}托盘出库", userId);
|
}
|
|
Db.CommitTran();
|
return outDto1;
|
|
}
|
catch (Exception e)
|
{
|
Db.RollbackTran();
|
throw new Exception(e.Message);
|
}
|
|
}
|
|
|
#region 移库目标库位
|
/// <summary>
|
/// 获取移库目标库位
|
/// </summary>
|
/// <param name="oldAddress">需要移动的库位地址</param>
|
/// <param name="roadWay">巷道</param>
|
/// <param name="area">区域</param>
|
/// <returns>目标库位地址 为"" 直接下发两次出库指令</returns>
|
public string MoveAddress(string oldAddress, string roadWay, string area)//01020201 排-列-层-深度
|
{
|
string nowAddress = "";
|
// 获取移库目标储位
|
var row = int.Parse(oldAddress.Substring(0, 2));
|
var lie = int.Parse(oldAddress.Substring(2, 2));
|
var ceng = int.Parse(oldAddress.Substring(4, 2));
|
|
var sqlString = $@"select LocatNo,[Row],[Column],Layer, (ABS(Row-{row}) + ABS([Column]-{lie}) + ABS(Layer-{ceng})) as distNum
|
from SysStorageLocat
|
where Flag = '0' and Status in ('0','3','5') and Depth = '02' and RoadwayNo = '{roadWay}' and AreaNo = '{area}'
|
order by distNum;";
|
|
var addressModels = Db.Ado.SqlQuery<AddressCls>(sqlString).ToList();
|
if (addressModels.Count > 0) // 判断同巷道内排空库位
|
{
|
var listLocaete = new List<string>();
|
foreach (var item in addressModels)
|
{
|
// 目标内库位对应的外库位
|
string addressee = item.LocatNo.Substring(0, 6) + "01";
|
|
// 判断目标库位的外库位是否存在货物 (正常情况下正在移入情况不存在,因为移库先移入里面,后移入外面)
|
//SlotStatus 0: 空储位 1:有货 2:正在入库 3:正在出库 4:正在移入 5:正在移出
|
sqlString = $"select count(*) from SysStorageLocat where LocatNo = '{addressee}' and Status in ('0','3','5') and Flag in ('0','1') ; ";
|
var rowNum = Db.Ado.SqlQuery<int>(sqlString).First();
|
if (rowNum == 0)
|
{
|
continue;
|
}
|
else
|
{
|
nowAddress = item.LocatNo;
|
break;
|
}
|
}
|
}
|
if (nowAddress == "")
|
{
|
// 判断同巷道外排空库位
|
sqlString = $@"select LocatNo,[Row],[Column],Layer, (ABS(Row-{row}) + ABS([Column]-{lie}) + ABS(Layer-{ceng})) as distNum
|
from SysStorageLocat
|
where Flag = '0' and Status in ('0','3','5') and Depth = '01' and RoadwayNo = '{roadWay}' and AreaNo = '{area}'
|
order by distNum;";
|
var adderModeling = Db.Ado.SqlQuery<AddressCls>(sqlString).ToList();
|
if (adderModeling.Count > 0)
|
{
|
nowAddress = adderModeling[0].LocatNo;
|
}
|
else
|
{
|
// 库内不存在空储位
|
nowAddress = "";
|
}
|
}
|
|
|
return nowAddress;
|
}
|
#endregion
|
|
#endregion
|
}
|
}
|