wangxinhui
2025-03-05 33861e7fbf9cc4af3088f715ce7607a681f9c181
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
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Common.CommonEnum;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Helper;
using WIDESEA_IBasicRepository;
using WIDESEA_IBasicService;
using WIDESEA_Model.Models;
 
namespace WIDESEA_BasicService
{
    public partial class LocationInfoService
    {
 
        double weightValue_BC = 0.5;
 
        private readonly static object _locker_BC = new object();
        static List<LocationCache> locationCaches_BC = new List<LocationCache>();
 
        /// <summary>
        /// 板材仓货位分配
        /// </summary>
        /// <param name="roadwayNo">巷道号</param>
        /// <param name="palletType">
        /// 托盘类型
        /// </param>
        /// <returns></returns>
        public Dt_LocationInfo? AssignLocation_BC(string roadwayNo, int palletType, Dt_PalletTypeInfo palletTypeInfo, string beRelocationCode = "", int heightType = 0)
        {
            lock (_locker_BC)
            {
                List<LocationCache> removeItems = locationCaches_BC.Where(x => (DateTime.Now - x.DateTime).TotalMinutes > 5).ToList();
                int count = removeItems.Count;
                for (int i = 0; i < count; i++)
                {
                    locationCaches_BC.Remove(removeItems[i]);
                }
 
                List<string> lockLocationCodes = locationCaches_BC.Select(x => x.LocationCode).ToList();
 
                List<Dt_LocationInfo> locationInfos = Repository.QueryData(x => x.RoadwayNo == roadwayNo);
                if (locationInfos == null || locationInfos.Count == 0)
                {
                    throw new Exception($"未找到该巷道的货位信息,巷道号:{roadwayNo}");
                }
 
                if (!string.IsNullOrEmpty(beRelocationCode))
                {
                    Dt_LocationInfo? beRelocation = locationInfos.FirstOrDefault(x => x.LocationCode == beRelocationCode);
                    if (beRelocation == null)
                    {
                        throw new Exception($"未找到货位信息");
                    }
                    int maxDepth = locationInfos.Max(x => x.Depth);
                    int mathCurrentRow = beRelocation.Row - Convert.ToInt32(Math.Ceiling(beRelocation.Row / maxDepth / 2.0)) * maxDepth * 2;
                    if (mathCurrentRow <= maxDepth)
                    {
                        locationInfos = locationInfos.Where(x => x.Row - Convert.ToInt32(Math.Ceiling(x.Row / maxDepth / 2.0)) * maxDepth * 2 <= maxDepth).ToList();
                    }
                    else
                    {
                        locationInfos = locationInfos.Where(x => x.Row - Convert.ToInt32(Math.Ceiling(x.Row / maxDepth / 2.0)) * maxDepth * 2 > maxDepth).ToList();
                    }
                }
 
 
                //未定义类型的空货位
                List<Dt_LocationInfo> undefinedTypeEmptyLocations = locationInfos.Where(x => (x.EnableStatus == EnableStatusEnum.Normal.ObjToInt() || x.EnableStatus == EnableStatusEnum.OnlyIn.ObjToInt()) && x.LocationStatus == LocationStatusEnum.Free.ObjToInt() && x.LocationType == LocationTypeEnum.Undefined.ObjToInt() && !lockLocationCodes.Contains(x.LocationCode)).OrderByDescending(x => x.Depth).ThenBy(x => x.Layer).ThenBy(x => x.Column).ThenBy(x => x.Row).ToList();
 
                List<Dt_LocationInfo> definedTypeEmptyLocations = locationInfos.Where(x => (x.EnableStatus == EnableStatusEnum.Normal.ObjToInt() || x.EnableStatus == EnableStatusEnum.OnlyIn.ObjToInt()) && x.LocationStatus == LocationStatusEnum.Free.ObjToInt() && x.LocationType == palletType.ObjToInt() && !lockLocationCodes.Contains(x.LocationCode)).OrderByDescending(x => x.Depth).ThenBy(x => x.Layer).ThenBy(x => x.Column).ThenBy(x => x.Row).ToList();
 
                if(heightType == 1)
                {
                    undefinedTypeEmptyLocations = undefinedTypeEmptyLocations.Where(x=>x.Layer <= 3).ToList();
                    definedTypeEmptyLocations = definedTypeEmptyLocations.Where(x => x.Layer <= 3).ToList();
                }
                else if(heightType == 2)
                {
                    undefinedTypeEmptyLocations = undefinedTypeEmptyLocations.Where(x => x.Layer == 4).ToList();
                    definedTypeEmptyLocations = definedTypeEmptyLocations.Where(x => x.Layer == 4).ToList();
                }
                else if (heightType == 3)
                {
                    undefinedTypeEmptyLocations = undefinedTypeEmptyLocations.Where(x => x.Layer == 5).ToList();
                    definedTypeEmptyLocations = definedTypeEmptyLocations.Where(x => x.Layer == 5).ToList();
                }
                else
                {
                    undefinedTypeEmptyLocations = undefinedTypeEmptyLocations.Where(x => false).ToList();
                    definedTypeEmptyLocations = definedTypeEmptyLocations.Where(x => false).ToList();
                }
 
                if (palletTypeInfo.LocaitonCount == 2)
                {
                    if (roadwayNo != "SC01_BC")
                        definedTypeEmptyLocations = definedTypeEmptyLocations.Where(x => x.Column % 2 == 1).ToList();
                    else
                        definedTypeEmptyLocations = definedTypeEmptyLocations.Where(x => x.Column % 2 == 0).ToList();
                }
 
                if (definedTypeEmptyLocations.Any())
                {
                    for (int i = 0; i < definedTypeEmptyLocations.Count; i++)
                    {
                        Dt_LocationInfo definedTypeEmptyLocation = definedTypeEmptyLocations[i];
                        Dt_LocationInfo? locationInfo = GetUsableLocation_BC(locationInfos, definedTypeEmptyLocation, palletType, palletTypeInfo);
                        //判断货位两深及以上是否存在出库锁定货位
                        if (locationInfo?.Depth == 1)
                        {
                            Dt_LocationInfo? IsBebusyLocation = locationInfos.Where(x => x.Row == (locationInfo?.Row == 2 ? locationInfo?.Row - 1 : locationInfo?.Row + 1) && x.Column==locationInfo?.Column && x.Layer== locationInfo?.Layer).FirstOrDefault();
                            if (IsBebusyLocation!=null && (IsBebusyLocation.LocationStatus<LocationStatusEnum.InStock.ObjToInt()))
                            {
                                continue;
                            }
                        }
                        if (locationInfo != null)
                        {
                            locationCaches_BC.Add(new LocationCache { LocationCode = locationInfo.LocationCode, DateTime = DateTime.Now });
                            return locationInfo;
                        }
                    }
                }
                if ((/*locationInfos.Count * weightValue_BC >= definedTypeLocations.Count &&*/ undefinedTypeEmptyLocations.Any()))//如果已定义类型货位未超过比例,且有未定义类型的货位
                {
                    if (palletTypeInfo.LocaitonCount == 2)
                    {
                        if (roadwayNo != "SC01_BC")
                            undefinedTypeEmptyLocations = undefinedTypeEmptyLocations.Where(x => x.Column % 2 == 1).ToList();
                        else
                            undefinedTypeEmptyLocations = undefinedTypeEmptyLocations.Where(x => x.Column % 2 == 0).ToList();
 
                        for (int i = 0; i < undefinedTypeEmptyLocations.Count; i++)
                        {
                            Dt_LocationInfo undefinedTypeEmptyLocation = undefinedTypeEmptyLocations[i];
                            Dt_LocationInfo? locationInfo = GetUsableLocation_BC(locationInfos, undefinedTypeEmptyLocation, palletType, palletTypeInfo);
                            //判断货位两深及以上是否存在出库锁定货位
                            if (locationInfo?.Depth == 1)
                            {
                                Dt_LocationInfo? IsBebusyLocation = locationInfos.Where(x => x.Row == (locationInfo?.Row == 2 ? locationInfo?.Row - 1 : locationInfo?.Row + 1) && x.Column == locationInfo?.Column && x.Layer == locationInfo?.Layer).FirstOrDefault();
                                if (IsBebusyLocation != null && (IsBebusyLocation.LocationStatus < LocationStatusEnum.InStock.ObjToInt()))
                                {
                                    continue;
                                }
                            }
                            if (locationInfo != null)
                            {
                                //UpdateLocationStatus(locationInfo, palletType, LocationStatusEnum.Lock, locationInfo.WarehouseId);
                                locationCaches_BC.Add(new LocationCache { LocationCode = locationInfo.LocationCode, DateTime = DateTime.Now });
                                return locationInfo;
                            }
                        }
                    }
                    
                }
                return null;
            }
        }
 
        /// <summary>
        /// 获取可用货位(测试架仓)
        /// </summary>
        /// <param name="locationInfos"></param>
        /// <param name="emptyLocation"></param>
        /// <param name="palletType"></param>
        /// <returns></returns>
        private Dt_LocationInfo? GetUsableLocation_BC(List<Dt_LocationInfo> locationInfos, Dt_LocationInfo emptyLocation, int palletType, Dt_PalletTypeInfo palletTypeInfo)
        {
 
            if (palletTypeInfo.LocaitonCount == 2)
            {
                Dt_LocationInfo? nearLocation = null;
                if (emptyLocation.RoadwayNo != "SC01_BC" && emptyLocation.Column % 2 == 1)
                    nearLocation = locationInfos.FirstOrDefault(x => x.Row == emptyLocation.Row && x.Layer == emptyLocation.Layer && x.Depth == emptyLocation.Depth && x.Column == emptyLocation.Column - 1);
                else if (emptyLocation.RoadwayNo == "SC01_BC" && emptyLocation.Column % 2 == 0)
                    nearLocation = locationInfos.FirstOrDefault(x => x.Row == emptyLocation.Row && x.Layer == emptyLocation.Layer && x.Depth == emptyLocation.Depth && x.Column == emptyLocation.Column + 1);
                if (nearLocation != null && DepthLocationIsEmpty_BC(locationInfos, nearLocation) != null)
                {
                    Dt_LocationInfo? locationInfo = DepthLocationIsEmpty_BC(locationInfos, emptyLocation);
                    if (locationInfo != null)
                    {
                        return locationInfo;
                    }
                }
            }
            else
            {
                Dt_LocationInfo? locationInfo = DepthLocationIsEmpty_BC(locationInfos, emptyLocation);
                if (locationInfo != null)
                {
                    return locationInfo;
                }
            }
            return null;
        }
 
        /// <summary>
        /// 判断不同深度的同组货位状态是否为空闲空位(测试架仓)
        /// </summary>
        /// <param name="locationInfos"></param>
        /// <param name="emptyLocation"></param>
        /// <returns></returns>
        private Dt_LocationInfo? DepthLocationIsEmpty_BC(List<Dt_LocationInfo> locationInfos, Dt_LocationInfo emptyLocation)
        {
            List<Dt_LocationInfo> locations = GetGroupLocations(locationInfos, emptyLocation);
 
            bool moreDepthFlag = false;
            bool littleDepthFlag = false;
 
            if (emptyLocation.LocationType == 0)
            {
                List<Dt_LocationInfo> moreDepth = locations.Where(x => x.Depth > emptyLocation.Depth).ToList();
                moreDepthFlag = moreDepth.FirstOrDefault(x => x.LocationStatus != LocationStatusEnum.InStock.ObjToInt() && (x.EnableStatus == EnableStatusEnum.OnlyIn.ObjToInt() || x.EnableStatus == EnableStatusEnum.Normal.ObjToInt()) && x.LocationType != 0) == null;//查询大于当前货位深度的集合里是否有状态不为有货的货位,如果是true,则表示深货位有未被使用的情况
 
                List<Dt_LocationInfo> littleDepth = locations.Where(x => x.Depth <= emptyLocation.Depth).ToList();
                littleDepthFlag = littleDepth.FirstOrDefault(x => x.LocationStatus != LocationStatusEnum.Free.ObjToInt() && (x.EnableStatus == EnableStatusEnum.OnlyIn.ObjToInt() || x.EnableStatus == EnableStatusEnum.Normal.ObjToInt()) && x.LocationType != 0) == null; //查询小于当前货位深度的集合里是否有状态不为空,且禁用状态不为禁用以及只入的货位,如果是true,则表示浅货位被使用或者被禁用的情况
            }
            else
            {
                List<Dt_LocationInfo> moreDepth = locations.Where(x => x.Depth > emptyLocation.Depth).ToList();
                moreDepthFlag = moreDepth.FirstOrDefault(x => x.LocationStatus != LocationStatusEnum.InStock.ObjToInt() && (x.EnableStatus == EnableStatusEnum.OnlyIn.ObjToInt() || x.EnableStatus == EnableStatusEnum.Normal.ObjToInt()) && x.LocationType != emptyLocation.LocationType) == null;//查询大于当前货位深度的集合里是否有状态不为有货的货位,如果是true,则表示深货位有未被使用的情况
 
                List<Dt_LocationInfo> littleDepth = locations.Where(x => x.Depth <= emptyLocation.Depth).ToList();
                littleDepthFlag = littleDepth.FirstOrDefault(x => x.LocationStatus != LocationStatusEnum.Free.ObjToInt() && (x.EnableStatus == EnableStatusEnum.OnlyIn.ObjToInt() || x.EnableStatus == EnableStatusEnum.Normal.ObjToInt()) && x.LocationType != emptyLocation.LocationType) == null; //查询小于当前货位深度的集合里是否有状态不为空,且禁用状态不为禁用以及只入的货位,如果是true,则表示浅货位被使用或者被禁用的情况
            }
            if (moreDepthFlag && littleDepthFlag)
            {
                return emptyLocation;
            }
 
            return null;
        }
    }
}