240 lines
9.4 KiB
C#
240 lines
9.4 KiB
C#
using JSMachine.WMS.App.Dto;
|
|
using JSMachine.WMS.App.Dto.Enum;
|
|
using JSMachine.WMS.App.IService;
|
|
using JSMachine.WMS.Business.StockIn.IService;
|
|
using JSMachine.WMS.Business.StockIn.ServiceImpl.Strategy;
|
|
using JSMachine.WMS.Infrastructure.Helper;
|
|
using JSMachine.WMS.PLC.ModbusImpl.Elevator.Util;
|
|
using JSMachine.WMS.RPC.ErpRPC.Dto.In.XRBusinessResult;
|
|
using JSMachine.WMS.RPC.ErpRPC.Dto.Out.XRBusinessResult;
|
|
using JSMachine.WMS.RPC.ErpRPC.IService;
|
|
using NPOI.OpenXmlFormats.Dml.Chart;
|
|
|
|
namespace JSMachine.WMS.Business.StockIn.ServiceImpl
|
|
{
|
|
/// <summary>
|
|
/// PDA入库业务类
|
|
/// </summary>
|
|
public class StockInService : IStockInService
|
|
{
|
|
private IPaperStorageService _paperStorageService;
|
|
private IStorageRackService _storageRackService;
|
|
private IERPTaskService _erpTaskService;
|
|
private IAGVTaskService _agvTaskService;
|
|
private IElevatorPlcQueueService _elevatorPlcQueueService;
|
|
public StockInService(
|
|
IPaperStorageService paperStorageService,
|
|
IStorageRackService storageRackService,
|
|
IERPTaskService erpTaskService,
|
|
IAGVTaskService agvTaskService,
|
|
IElevatorPlcQueueService elevatorPlcQueueService
|
|
)
|
|
{
|
|
_paperStorageService = paperStorageService;
|
|
_storageRackService = storageRackService;
|
|
_erpTaskService = erpTaskService;
|
|
_agvTaskService = agvTaskService;
|
|
_elevatorPlcQueueService = elevatorPlcQueueService;
|
|
}
|
|
|
|
/// <summary>
|
|
/// PDA入库
|
|
/// </summary>
|
|
/// <param name="stockInParam"></param>
|
|
/// <returns></returns>
|
|
public async Task<string> StockIn(PDAInParam stockInParam)
|
|
{
|
|
// 入库流程依次校验重复任务、物料和起点库位,再计算目标库位并创建任务。
|
|
//1.查询物料信息是否存在
|
|
//2.查询库位是否存在
|
|
//3.计算目标库位并锁定
|
|
//4.写入ErpTask表
|
|
|
|
bool existUnCompleteTask = await _erpTaskService.Exist(p =>
|
|
p.CreationTime > DateTime.Now.Date &&
|
|
(p.TaskType == TaskTypeEnum.PdaIn || p.TaskType==TaskTypeEnum.TailIn)&&
|
|
(p.TaskStatus == TaskStatusEnum.Initial || p.TaskStatus == TaskStatusEnum.InExecution) &&
|
|
p.BarCode == stockInParam.BarCode);
|
|
|
|
if (existUnCompleteTask)
|
|
{
|
|
LogHelper.Warn($"合格证号 {stockInParam.BarCode} 已有待入库的任务,请检查是否扫错");
|
|
return $"合格证号 {stockInParam.BarCode} 已有待入库的任务,请检查是否扫错";
|
|
}
|
|
|
|
MateriaInfoDto materiaInfo = await CheckMaterialInfo(stockInParam.BarCode);
|
|
if (materiaInfo == null)
|
|
{
|
|
string msg = $"未在ERP中查询到合格证号为 {stockInParam.BarCode} 的物料信息";
|
|
|
|
LogHelper.Warn(msg);
|
|
return msg;
|
|
}
|
|
|
|
StorageRackDto startStoragRack = await _storageRackService.GetSingalByExpression(p =>
|
|
p.StorageRackNo == stockInParam.StorageRackNo &&
|
|
!p.IsDisabled);
|
|
|
|
if (startStoragRack == null)
|
|
{
|
|
string msg = $"入库起点库位 {stockInParam.StorageRackNo} 不可用";
|
|
|
|
LogHelper.Warn(msg);
|
|
return msg;
|
|
}
|
|
|
|
//如果是尾托回库,需要自动计算任务楼层
|
|
if (stockInParam.TaskType == TaskTypeEnum.TailIn)
|
|
{
|
|
AGVTaskDto outTask = await _agvTaskService.GetSingalByExpression(p =>
|
|
p.BarCode == stockInParam.BarCode &&
|
|
(p.TaskType == TaskTypeEnum.SaleOut || p.TaskType == TaskTypeEnum.TransferStockOut) &&
|
|
!p.StartPositionCode.Contains("TSJ"),
|
|
p => p.CreationTime,
|
|
SqlSugar.OrderByType.Desc);
|
|
|
|
if (outTask == null)
|
|
{
|
|
string msg = $"合格证号 {stockInParam.BarCode} 批次 {materiaInfo.MateriaBatch} 没有对应的出库任务," +
|
|
$"因此不知道该物料原来所属楼层,请人工将该货物放置到合适的库位上,然后使用pda更新物料信息";
|
|
LogHelper.Error(msg);
|
|
|
|
return msg;
|
|
}
|
|
|
|
stockInParam.Floor = outTask.Floor;
|
|
}
|
|
|
|
//预先计算可用的库位(所有未禁用,空白库位-未完成的入库任务)
|
|
int usableWarehouseCout = await _storageRackService.Count(p =>
|
|
p.Floor == stockInParam.Floor &&
|
|
p.Transport == TransportEnum.NormalArea &&
|
|
!p.IsDisabled);
|
|
int unCompleteErpTaskCount = await _erpTaskService.Count(p =>
|
|
p.CreationTime > DateTime.Now.Date &&
|
|
(p.TaskType == TaskTypeEnum.PdaIn || p.TaskType == TaskTypeEnum.TailIn) &&
|
|
!(p.TaskStatus == TaskStatusEnum.Completed || p.TaskStatus == TaskStatusEnum.Cancelled)
|
|
);
|
|
|
|
if (usableWarehouseCout- unCompleteErpTaskCount <=0)
|
|
{
|
|
string msg = $"没有空余库位,无法入库";
|
|
|
|
LogHelper.Warn(msg);
|
|
|
|
return msg;
|
|
}
|
|
|
|
ERPTaskDto erpTask = CreateErpTask(stockInParam, materiaInfo);
|
|
bool bRet = await _erpTaskService.Add(erpTask);
|
|
if (!bRet)
|
|
{
|
|
string msg = $"数据库操作失败";
|
|
|
|
LogHelper.Warn(msg);
|
|
return msg;
|
|
}
|
|
|
|
return string.Empty;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 从ERPTask生成AgvTask(pda入库)
|
|
/// </summary>
|
|
/// <param name="erpTask"></param>
|
|
/// <returns></returns>
|
|
public async Task<bool> CreateAgvTaskFirstFloor(ERPTaskDto erpTask)
|
|
{
|
|
//1.入库到一楼寻找一楼库位
|
|
//2.入库到二楼寻找一楼提升机库位
|
|
|
|
StorageRackDto destWareHouse = await CalculateDestWarehouse(erpTask, erpTask.MateriaBatch, erpTask.Floor);
|
|
if (destWareHouse == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
AGVTaskDto agvTask = new()
|
|
{
|
|
ErpTaskId = erpTask.Id,
|
|
BarCode = erpTask.BarCode,
|
|
OrderNo = erpTask.OrderNo,
|
|
CustomName = erpTask.CustomName,
|
|
MateriaName = erpTask.MateriaName,
|
|
MateriaType = erpTask.MateriaType,
|
|
MateriaNum = erpTask.ErpOrderNum,
|
|
MateriaBatch = erpTask.MateriaBatch,
|
|
MateriaCode = erpTask.MateriaCode,
|
|
|
|
TaskType = erpTask.TaskType,
|
|
TaskStatus = TaskStatusEnum.Initial,
|
|
Priority = PriorityEnum.High,
|
|
Floor = FloorEnum.FirstFloor,
|
|
|
|
StartPositionCode = erpTask.StorageRackNo,
|
|
EndPositionCode = destWareHouse.StorageRackNo,
|
|
|
|
ErpUploadStatus = destWareHouse.Transport == TransportEnum.Elevator ? ErpUploadStatusEnum.Unnecessary : ErpUploadStatusEnum.WaittingToUpload,
|
|
|
|
Transport = TransportEnum.NormalArea
|
|
};
|
|
|
|
destWareHouse.IsLock = true;
|
|
|
|
await _storageRackService.Lock(destWareHouse);
|
|
return await _agvTaskService.Add(agvTask);
|
|
}
|
|
|
|
private async Task<MateriaInfoDto> CheckMaterialInfo(string barcode)
|
|
{
|
|
XRResultDto xRResult = await _paperStorageService.GetMateriaInfo(barcode);
|
|
if (xRResult?.status == 200)
|
|
return xRResult.data;
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 计算目标库位
|
|
/// </summary>
|
|
/// <param name="materiaInfo"></param>
|
|
/// <returns></returns>
|
|
private async Task<StorageRackDto> CalculateDestWarehouse(ERPTaskDto erpTask, string materiaBatch, FloorEnum floor)
|
|
{
|
|
//1.入库到一楼寻找一楼库位
|
|
//2.入库到二楼寻找一楼提升机库位
|
|
|
|
if (floor == FloorEnum.FirstFloor)
|
|
{
|
|
IStockInStrategy stockInStrategy = StrategyFactory.CreateStockInStrategy(TransportEnum.ManualArea, floor, materiaBatch);
|
|
|
|
StorageRackDto destWarehouse = await stockInStrategy.CalCulateWarehouse();
|
|
return destWarehouse;
|
|
}
|
|
|
|
StorageRackDto elevatorWarehouse = await ElevatorUtil.GetUsableElevatorChannel(erpTask.Id, FloorEnum.FirstFloor);
|
|
return elevatorWarehouse;
|
|
}
|
|
|
|
private ERPTaskDto CreateErpTask(PDAInParam pdaInParam, MateriaInfoDto materiaInfoDto)
|
|
{
|
|
ERPTaskDto eRPTaskDto = new()
|
|
{
|
|
StorageRackNo = pdaInParam.StorageRackNo,
|
|
OrderNo = materiaInfoDto.OrderNo,
|
|
BarCode = materiaInfoDto.BarCode,
|
|
MateriaName = materiaInfoDto.MateriaName,
|
|
ErpOrderNum = pdaInParam.TaskType == TaskTypeEnum.PdaIn ? int.Parse(materiaInfoDto.MateriaNum) : pdaInParam.MertialNum,
|
|
MateriaBatch = materiaInfoDto.MateriaBatch,
|
|
MateriaCode = materiaInfoDto.MateriaCode,
|
|
|
|
TaskStatus = TaskStatusEnum.Initial,
|
|
TaskType = pdaInParam.TaskType,
|
|
Floor = pdaInParam.Floor
|
|
};
|
|
|
|
return eRPTaskDto;
|
|
}
|
|
}
|
|
}
|