add
zongzhibin
2024-11-28 e01f8369e106e235a4454f56c428156bf12d9d99
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
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
 
    }
}