using Admin.NET.Application.Entity;
|
using Microsoft.CodeAnalysis;
|
|
namespace Admin.NET.Application
|
{
|
/// <summary>
|
/// 寻找 空库位的处理类
|
/// </summary>
|
public class FindEmptyPlaceServiceHandle
|
{
|
/// <summary>
|
/// 是否正在执行方法
|
/// </summary>
|
private static bool isRuning_Fun = false;
|
private static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1);
|
|
protected readonly SqlSugarRepository<v_empty_place> _v_empty_placeRep;
|
protected readonly SqlSugarRepository<WmsBasePlace> _wmsPlaceRep;
|
private readonly SqlSugarRepository<WmsTask> _wareTaskRep;
|
|
protected List<v_empty_place> findEmptyPlaceList = null;
|
|
/// <summary>
|
/// 构造函数
|
/// </summary>
|
/// <param name="v_empty_placeRep"></param>
|
/// <param name="wmsPlaceRep"></param>
|
/// <param name="wareTaskRep"></param>
|
public FindEmptyPlaceServiceHandle(
|
SqlSugarRepository<v_empty_place> v_empty_placeRep,
|
SqlSugarRepository<WmsBasePlace> wmsPlaceRep,
|
SqlSugarRepository<WmsTask> wareTaskRep
|
)
|
{
|
_v_empty_placeRep = v_empty_placeRep;
|
_wmsPlaceRep = wmsPlaceRep;
|
_wareTaskRep = wareTaskRep;
|
}
|
|
|
/// <summary>
|
/// 主方法入口1:查询单个库位
|
///
|
///* 原则:
|
///* 1、方法必须使用lock锁定,防止并发抢同一个库位
|
///* 2、该库位如果所在的堆垛机被设定为 禁用,则不允许寻找该库位
|
///* 3、入库-库存分摊原则(注意:此项按照客户约定规则,视情况而定)
|
/// </summary>
|
public async Task<WmsBasePlace> MainFindSingleEmptyLocation(FindEmptyPlaceInput input)
|
{
|
var findList = await MainFindMultiEmptyLocation(input);
|
if (findList != null && findList.Count > 0)
|
{
|
return findList.First();
|
}
|
return null;
|
}
|
|
/// <summary>
|
/// 主方法入口2:查询多个库位
|
///
|
///* 原则:
|
///* 1、方法必须使用lock锁定,防止并发抢同一个库位
|
///* 2、该库位如果所在的堆垛机被设定为 禁用,则不允许寻找该库位
|
///* 3、入库-库存分摊原则(注意:此项按照客户约定规则,视情况而定)
|
/// </summary>
|
public async Task<List<WmsBasePlace>> MainFindMultiEmptyLocation(FindEmptyPlaceInput input)
|
{
|
try
|
{
|
if (isRuning_Fun)
|
{
|
throw Oops.Oh("程序正忙,请稍后再试");
|
}
|
await semaphoreSlim.WaitAsync();
|
isRuning_Fun = true;
|
|
await QueryBaseEmptyLocationList(input); //查询所有的空闲库位
|
|
await EnableLaneFilter();//可用的堆垛机巷道 --筛选条件
|
|
await TaskOccupyFilter();//任务占用的库位 -- 筛选条件
|
|
DiyFilter();//自定义查询条件 -- 筛选条件
|
|
DataOrder();//数据排序
|
|
//返回结果
|
if (findEmptyPlaceList != null && findEmptyPlaceList.Count > 0)
|
{
|
var queryIds = findEmptyPlaceList.Select(x => x.Id).ToList();
|
return _wmsPlaceRep.GetList(x => queryIds.Contains(x.Id));
|
}
|
return new List<WmsBasePlace>();
|
|
}
|
catch (Exception)
|
{
|
|
throw;
|
}
|
finally
|
{
|
semaphoreSlim.Release();
|
isRuning_Fun = false;
|
}
|
}
|
|
#region 虚方法
|
|
/// <summary>
|
/// 查询最基础的空库位集合,即获取数据库数据源的入口
|
/// </summary>
|
protected virtual async Task QueryBaseEmptyLocationList(FindEmptyPlaceInput input)
|
{
|
findEmptyPlaceList = await _v_empty_placeRep.GetListAsync(x => 1 == 1);
|
if (input != null)
|
{
|
if (input.AreaList?.Count > 0)
|
{
|
findEmptyPlaceList = findEmptyPlaceList.Where(x => input.AreaList.Contains(x.AreaCode)).ToList();
|
}
|
if (!string.IsNullOrEmpty(input.PalceNo))
|
{
|
findEmptyPlaceList = findEmptyPlaceList.Where(x => x.PlaceCode == input.PalceNo).ToList();
|
}
|
}
|
}
|
|
/// <summary>
|
/// 可用的堆垛机巷道 -- 筛选条件
|
/// </summary>
|
protected virtual async Task EnableLaneFilter()
|
{
|
if (findEmptyPlaceList != null && findEmptyPlaceList.Count > 0)
|
{
|
//该库位如果所在的堆垛机被设定为 禁用,则不允许寻找该库位
|
List<int?> enable_laneList = await GetEnableLaneList();
|
if (enable_laneList != null && enable_laneList.Count > 0)
|
{
|
findEmptyPlaceList = await _v_empty_placeRep.AsQueryable().Where(x => enable_laneList.Contains(x.LaneNo)).ToListAsync();
|
}
|
}
|
}
|
|
/// <summary>
|
/// 排除未终结的任务占用库位 -- 筛选条件
|
/// </summary>
|
protected virtual async Task TaskOccupyFilter()
|
{
|
if (findEmptyPlaceList != null && findEmptyPlaceList.Count > 0)
|
{
|
List<long> removeIdList = new List<long>();
|
var noFinishTask = await _wareTaskRep.AsQueryable().Where(x => x.TaskStatus != TaskStatusEnum.已完成 && x.TaskStatus != TaskStatusEnum.已取消).ToListAsync();
|
var noFinishTask_Form = noFinishTask.Select(x => x.SourcePlaceCode).ToList();
|
var noFinishTask_To = noFinishTask.Select(x => x.ToPlaceCode).ToList();
|
//排除未结束任务占用的
|
findEmptyPlaceList = findEmptyPlaceList.Where(x => !noFinishTask_Form.Contains(x.PlaceCode) && !noFinishTask_To.Contains(x.PlaceCode)).ToList();
|
}
|
}
|
|
/// <summary>
|
/// 自定义查询条件 -- 筛选条件
|
/// </summary>
|
protected virtual void DiyFilter()
|
{
|
|
}
|
|
/// <summary>
|
/// 数据排序
|
/// </summary>
|
protected virtual void DataOrder()
|
{
|
if (findEmptyPlaceList != null && findEmptyPlaceList.Count > 0)
|
{
|
findEmptyPlaceList = findEmptyPlaceList
|
//先按照层,升序排列
|
.OrderBy(x => x.LayerNo)
|
//再按照列,升序排列
|
.ThenBy(x => x.ColumnNo).ToList();
|
}
|
}
|
|
#endregion
|
|
#region 公共方法
|
|
/// <summary>
|
/// 获取可用的堆垛机所在的巷道集合
|
/// </summary>
|
/// <returns></returns>
|
protected async Task<List<int?>> GetEnableLaneList()
|
{
|
//根据自己的项目自行判断
|
////该库位如果所在的堆垛机被设定为 禁用,则不允许寻找该库位
|
//var eqType = _wareEquipmentTypeRep.FirstOrDefault(x => x.Code == EquipmentTypeEnum.Srm.ToString());
|
//if (eqType == null)
|
//{
|
// throw Oops.Bah("没有找到类型是堆垛机的数据");
|
//}
|
//var noramlEquipmentList = _wareEquipmentRep.Where(x => x.Status == 0 && x.EquipmentTypeId == eqType.Id).ToList();//查询所有可用的堆垛机列表
|
//if (noramlEquipmentList != null && noramlEquipmentList.Count > 0)
|
//{
|
// return noramlEquipmentList.Where(x => x.Lane != null).Select(x => x.Lane).ToList();
|
//}
|
return null;
|
}
|
|
#endregion
|
|
}
|
}
|