ke_junjie
2025-06-04 84620534eb627e95811b971a4b552b6a177829bf
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
using Furion.DatabaseAccessor;
using Furion.FriendlyException;
using iWare.Wms.Core;
using Microsoft.CodeAnalysis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Admin.NET.Application.Common
{
    /// <summary>
    /// 寻找 空库位的处理类
    /// </summary>
    public class FindEmptyLocationServiceHandle
    {
        private static readonly object lockFindBestEmpty = new object();
        protected readonly IRepository<v_empty_location, MasterDbContextLocator> _v_EmptyLocationRep;
        protected readonly IRepository<WmsPlace, MasterDbContextLocator> _wareLocationRep;
        protected readonly IRepository<WareTask, MasterDbContextLocator> _wareTaskRep;
        protected readonly IRepository<WareContainerVsMaterial, MasterDbContextLocator> _wareContainerVsMaterial;
        protected readonly IRepository<WmsContainer, MasterDbContextLocator> _wareContainer;
        protected readonly IRepository<WmsContainerType, MasterDbContextLocator> _wareContainerType;
        protected readonly IRepository<v_ware_inventory_by_container, MasterDbContextLocator> _v_ware_inventory_by_container;
        protected List<v_empty_location> findEmptyLocationList = null;
 
        protected string _containerCode = "";
        protected string _siteCode = "";
 
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="v_EmptyLocationRep"></param>
        /// <param name="wareLocationRep"></param>
        /// <param name="wareTaskRep"></param>
        /// <param name="wareContainerVsMaterial"></param>
        /// <param name="wareContainer"></param>
        /// <param name="wareContainerType"></param>
        /// <param name="v_ware_inventory_by_container"></param>
        /// <param name="containerCode"></param>
        /// <param name="siteCode"></param>
        public FindEmptyLocationServiceHandle(IRepository<v_empty_location, MasterDbContextLocator> v_EmptyLocationRep,
            IRepository<WmsPlace, MasterDbContextLocator> wareLocationRep,
             IRepository<WareTask, MasterDbContextLocator> wareTaskRep,
             IRepository<WareContainerVsMaterial, MasterDbContextLocator> wareContainerVsMaterial,
             IRepository<WmsContainer, MasterDbContextLocator> wareContainer,
             IRepository<WmsContainerType, MasterDbContextLocator> wareContainerType,
             IRepository<v_ware_inventory_by_container, MasterDbContextLocator> v_ware_inventory_by_container,
        string containerCode,string siteCode
            )
        {
            _v_EmptyLocationRep = v_EmptyLocationRep;
            _wareLocationRep = wareLocationRep;
            _wareTaskRep = wareTaskRep;
            _wareContainerVsMaterial = wareContainerVsMaterial;
            _wareContainer = wareContainer;
            _wareContainerType = wareContainerType;
            _v_ware_inventory_by_container = v_ware_inventory_by_container;
            _containerCode = containerCode;
            _siteCode = siteCode;
        }
 
 
        /// <summary>
        /// 主方法入口
        ///  
        ///* 原则:
        ///*  1、方法必须使用lock锁定,防止并发抢同一个库位
        ///*  2、该库位如果所在的堆垛机被设定为 禁用,则不允许寻找该库位
        ///*  3、入库-库存分摊原则(注意:此项按照客户约定规则,视情况而定)
        /// </summary>
        public WmsPlace MainFindEmptyLocation()
        {
            lock (lockFindBestEmpty)
            {
                QueryBaseEmptyLocationList();  //查询所有的空闲库位
 
                //EnableLaneFilter();//可用的堆垛机巷道 --筛选条件
 
                //TaskOccupyFilter();//任务占用的库位 -- 筛选条件
 
                DiyFilter();//自定义查询条件 -- 筛选条件
 
                DataOrder();//数据排序
 
                //返回结果
                if (findEmptyLocationList != null && findEmptyLocationList.Count > 0)
                {
                    long id = findEmptyLocationList.First().Id;
                    //long id = 0;
                    //foreach (var item in findEmptyLocationList)
                    //{
                    //    if (item.Row == 1 || item.Row == 4)
                    //    {
                    //        var vs = item.Code.Split('-');
                    //        if (vs.Length != 4)
                    //        {
                    //            continue;
                    //        }
                    //        if (vs[1] == "01")
                    //        {
                    //            vs[1] = "02";
                    //        }
                    //        else if (vs[1] == "04")
                    //        {
                    //            vs[1] = "03";
                    //        }
                    //        string str = $"{vs[0]}-{vs[1]}-{vs[2]}-{vs[3]}";
                    //        //查看近伸位有没有货
                    //        var isExist = _inventoryByContainer.DetachedEntities.Any(u => u.WareLocationCode == str);
                    //        if (!isExist)
                    //        {
                    //            id = item.Id;
                    //            break;
                    //        }
                    //    }
                    //    else if (item.Row == 2 || item.Row == 3)
                    //    {
                    //        var vs = item.Code.Split('-');
                    //        if (vs.Length != 4)
                    //        {
                    //            continue;
                    //        }
                    //        if (vs[1] == "02")
                    //        {
                    //            vs[1] = "01";
                    //        }
                    //        else if (vs[1] == "03")
                    //        {
                    //            vs[1] = "04";
                    //        }
                    //        string str = $"{vs[0]}-{vs[1]}-{vs[2]}-{vs[3]}";
                    //        //查看远伸位有没有任务
                    //        var task = _wareTaskRep.DetachedEntities.Any(u => u.FromLocationCode == str || u.ToLocationCode == str || u.MoveFromLocation == str || u.MoveToLocation == str);
                    //        if (!task)
                    //        {
                    //            id = item.Id;
                    //            break;
                    //        }
                    //    }
                    //}
                    return _wareLocationRep.FindOrDefault(id);
                }
                return null;
            }
        }
 
        #region 虚方法
 
        /// <summary>
        /// 查询最基础的空库位集合,即获取数据库数据源的入口
        /// </summary>
        protected virtual void QueryBaseEmptyLocationList()
        {
            findEmptyLocationList = _v_EmptyLocationRep.Where(x => 1 == 1).ToList();
        }
 
        /// <summary>
        /// 可用的堆垛机巷道 -- 筛选条件
        /// </summary>
        protected virtual void EnableLaneFilter()
        {
            
        }
 
        /// <summary>
        /// 排除未终结的任务占用库位 -- 筛选条件
        /// </summary>
        protected virtual void TaskOccupyFilter()
        {
           
        }
 
        /// <summary>
        /// 自定义查询条件 -- 筛选条件
        /// </summary>
        protected virtual void DiyFilter()
        {
 
        }
 
        /// <summary>
        /// 数据排序
        /// </summary>
        protected virtual void DataOrder()
        {
            if (findEmptyLocationList != null && findEmptyLocationList.Count > 0)
            {
                findEmptyLocationList = findEmptyLocationList
                       //先按照层,升序排列
                       .OrderBy(x => x.LayerNo + x.ColumnNo).ToList();
            }
        }
 
        #endregion
 
    }
}