216 lines
8.7 KiB
C#
216 lines
8.7 KiB
C#
using JSMachine.WMS.App.Dto;
|
|||
|
|
using JSMachine.WMS.App.Dto.Enum;
|
||
|
|
using JSMachine.WMS.App.IService;
|
||
|
|
using JSMachine.WMS.Domain.Entity;
|
||
|
|
using JSMachine.WMS.Domain.IRepository;
|
||
|
|
using JSMachine.WMS.Infrastructure;
|
||
|
|
using JSMachine.WMS.Infrastructure.Helper;
|
||
|
|
using SqlSugar;
|
||
|
|
using static JSMachine.WMS.App.Dto.StorageRackDto;
|
||
|
|
|
||
|
|
namespace JSMachine.WMS.App.ServiceImpl
|
||
|
|
{
|
||
|
|
public class StorageRackService : BaseService<StorageRackDto, StorageRack>, IStorageRackService
|
||
|
|
{
|
||
|
|
private IStorageRackRepository _storageRackRepository;
|
||
|
|
public StorageRackService(IStorageRackRepository repository) : base(repository)
|
||
|
|
{
|
||
|
|
_storageRackRepository = repository;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 根据库位号查询库位信息
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="storageRackNo"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public async Task<StorageRackDto> GetByStorageRackNo(string storageRackNo)
|
||
|
|
{
|
||
|
|
return await GetSingalByExpression(p => p.StorageRackNo == storageRackNo);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 根据批次号计算目标存储区库位
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="materiaBatch"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
//public async Task<StorageRackDto> CalculateDestWarehouse(string materiaBatch, FloorEnum floor)
|
||
|
|
//{
|
||
|
|
// //如果某一列有一个库位被锁定,说明该列有未完成的任务(任务完成会解锁库位),因此该列不可以再生成新的任务
|
||
|
|
|
||
|
|
// //获取楼层的所有库位
|
||
|
|
// List<StorageRackDto> wareHouses = await GetListByExpression(p =>
|
||
|
|
// p.Floor == floor && p.Transport == TransportEnum.NormalArea);
|
||
|
|
|
||
|
|
// if (wareHouses.IsNullOrEmpty())
|
||
|
|
// {
|
||
|
|
// LogHelper.Warn($"{floor} 层没有空余库位");
|
||
|
|
// return null;
|
||
|
|
// }
|
||
|
|
|
||
|
|
// wareHouses = wareHouses.OrderBy(p => p.AreaNumSort).OrderBy(p => p.ReservoirAreaColumnId).ToList();
|
||
|
|
|
||
|
|
// List<StorageRackDto> sameBatchWarehouses = wareHouses.Where(p => p.MateriaBatch == materiaBatch).ToList();
|
||
|
|
// StorageRackDto destStorageRack = null;
|
||
|
|
|
||
|
|
// //没有相同批次则任选一个空白的列
|
||
|
|
// if (sameBatchWarehouses.IsNullOrEmpty())
|
||
|
|
// {
|
||
|
|
// var groupByColumn = wareHouses.GroupBy(p => p.ReservoirAreaColumnId);
|
||
|
|
|
||
|
|
// foreach (var columnGroup in groupByColumn)
|
||
|
|
// {
|
||
|
|
// bool emptyColumn = columnGroup.All(p => !p.IsLock && !p.IsDisabled && string.IsNullOrEmpty(p.BarCode));
|
||
|
|
// if (emptyColumn)
|
||
|
|
// {
|
||
|
|
// destStorageRack = columnGroup.OrderByDescending(p => p.NumSort).First();
|
||
|
|
// break;
|
||
|
|
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
// else //存在相同批次则搜寻该批次所在的列下是否还有空库位
|
||
|
|
// {
|
||
|
|
// foreach (StorageRackDto sameBatchWarehous in sameBatchWarehouses)
|
||
|
|
// {
|
||
|
|
// var sameColumnWarehouse = wareHouses.Where(p => p.ReservoirAreaColumnId == sameBatchWarehous.ReservoirAreaColumnId);
|
||
|
|
// //同批次的列中也不能有任何库位被锁定
|
||
|
|
// if (sameColumnWarehouse.All(p => !p.IsLock && !p.IsDisabled))
|
||
|
|
// {
|
||
|
|
// destStorageRack = sameColumnWarehouse
|
||
|
|
// .OrderByDescending(p => p.NumSort)
|
||
|
|
// .FirstOrDefault(p => string.IsNullOrEmpty(p.BarCode));
|
||
|
|
|
||
|
|
// if (destStorageRack != null)
|
||
|
|
// break;
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
|
||
|
|
// //如果同批次下都没有合适的库位,则需要找空列
|
||
|
|
// if (destStorageRack == null)
|
||
|
|
// {
|
||
|
|
// List<StorageRackDto> remain = wareHouses.Except(sameBatchWarehouses, new StorageRackDtoIEqualityComparer()).ToList();
|
||
|
|
// if (remain.IsNullOrEmpty())
|
||
|
|
// {
|
||
|
|
// LogHelper.Warn("排除相同批次库位后没有剩余可用库位");
|
||
|
|
|
||
|
|
// return null;
|
||
|
|
// }
|
||
|
|
|
||
|
|
// var groupByColumn = remain.GroupBy(p => p.ReservoirAreaColumnId);
|
||
|
|
|
||
|
|
// foreach (var columnGroup in groupByColumn)
|
||
|
|
// {
|
||
|
|
// bool emptyColumn = columnGroup.All(p => !p.IsLock && !p.IsDisabled && string.IsNullOrEmpty(p.BarCode));
|
||
|
|
// if (emptyColumn)
|
||
|
|
// {
|
||
|
|
// destStorageRack = columnGroup.OrderByDescending(p => p.NumSort).First();
|
||
|
|
// break;
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
|
||
|
|
// }
|
||
|
|
// return destStorageRack;
|
||
|
|
//}
|
||
|
|
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 根据批次号判断是否存在空余库位
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="materialBatch"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
//public async Task<bool> HasEmptyWareHouse(string materiaBatch, TaskTypeEnum taskType, FloorEnum floor)
|
||
|
|
//{
|
||
|
|
// //直接调用目标库位计算方法,能够计算出目标库位则有库位,否则就是没有
|
||
|
|
// //一楼采用完全不混放模式
|
||
|
|
// //二楼视配置
|
||
|
|
|
||
|
|
|
||
|
|
//}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 获取可用的提升机库位
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="floor"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public async Task<List<StorageRackDto>> GetUsableElevatorWareHouse(FloorEnum floor)
|
||
|
|
{
|
||
|
|
List<long?> reservoirAreaIds = floor == FloorEnum.FirstFloor ? [1091, 1092] : [2091, 2092];
|
||
|
|
|
||
|
|
List<StorageRackDto> elevatorWarehouse = await
|
||
|
|
GetListByExpression(p =>
|
||
|
|
reservoirAreaIds.Contains(p.ReservoirAreaId)
|
||
|
|
&&
|
||
|
|
!p.IsLock && !p.IsDisabled
|
||
|
|
);
|
||
|
|
return elevatorWarehouse;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 根据提升机编号和通道号获取提所属库位信息
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="elevatorNo"></param>
|
||
|
|
/// <param name="channel"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public async Task<StorageRackDto> GetElevatorWareHouse(int elevatorNo, int channel)
|
||
|
|
{
|
||
|
|
string nameMatch = elevatorNo == 1 ? "1号" : "2号";
|
||
|
|
StorageRackDto storageRack = await GetSingalByExpression(p => p.ElevatorChannel == channel && p.StorageRackName.Contains(nameMatch));
|
||
|
|
|
||
|
|
return storageRack;
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<bool> Lock(StorageRackDto storageRack)
|
||
|
|
{
|
||
|
|
storageRack.IsLock = true;
|
||
|
|
|
||
|
|
LogHelper.Info($"锁定库位{storageRack.StorageRackNo}");
|
||
|
|
|
||
|
|
return await base.EditSingalWithSpecificCols(storageRack, ["IsLock"]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<bool> Unlock(StorageRackDto storageRack)
|
||
|
|
{
|
||
|
|
storageRack.IsLock = false;
|
||
|
|
LogHelper.Info($"解锁库位{storageRack.StorageRackNo}");
|
||
|
|
|
||
|
|
return await base.EditSingalWithSpecificCols(storageRack, ["IsLock"]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public Task<bool> UpdateLockStatus(Guid id, bool isLock)
|
||
|
|
{
|
||
|
|
return base.ExcuteSql($"update StorageRack set IsLock = {isLock} where Id = '{id}'");
|
||
|
|
}
|
||
|
|
|
||
|
|
public Task<bool> UpdateDisableStatus(Guid id, bool isDisable)
|
||
|
|
{
|
||
|
|
return base.ExcuteSql($"update StorageRack set IsDisabled = {isDisable} where Id = '{id}'");
|
||
|
|
}
|
||
|
|
|
||
|
|
private static readonly SemaphoreSlim SemaphoreSlim = new(1,1);
|
||
|
|
public async Task<StorageRackDto> GetUsableTransferStorageRack()
|
||
|
|
{
|
||
|
|
await SemaphoreSlim.WaitAsync();
|
||
|
|
|
||
|
|
StorageRackDto storageRackDto = await
|
||
|
|
base.GetSingalByExpression(p =>
|
||
|
|
p.Transport == TransportEnum.TransitArea &&
|
||
|
|
!p.IsLock &&
|
||
|
|
!p.IsDisabled &&
|
||
|
|
string.IsNullOrEmpty(p.BarCode));
|
||
|
|
|
||
|
|
if (storageRackDto != null)
|
||
|
|
await Lock(storageRackDto);
|
||
|
|
|
||
|
|
SemaphoreSlim.Release();
|
||
|
|
return storageRackDto;
|
||
|
|
}
|
||
|
|
|
||
|
|
//public async Task<int> PreCalUsableStorageRackCount(FloorEnum floor)
|
||
|
|
//{
|
||
|
|
// //1. 一楼不混放,需要查找同批次,或者空白列
|
||
|
|
// //2.二楼可以混放,仅需要查找到一个空库位即可
|
||
|
|
//}
|
||
|
|
}
|
||
|
|
}
|