WCS
dengjunjie
2024-10-14 966d1fe6077c885db064fcea98bb48cbccb464d6
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
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
namespace WIDESEA_StorageBasicServices;
 
public class Dt_BillGroupStockService : ServiceBase<Dt_BillGroupStock, IDt_BillGroupStockRepository>, IDt_BillGroupStockService
{
    private readonly IUnitOfWorkManage _unitOfWorkManage;
    private readonly IDt_OutOrderService _outOrderService;
    private readonly IDt_OutOrderAndStockRepository _OutOrderAndStockRepository;
    private readonly IDt_OutOrderAndStock_HtyService _OutOrderAndStock_HtyService;
    private readonly IMapper _mapper;
    private readonly IDt_BillGroupStockDetailRepository _dt_BillGroupStockDetailRepository;
    private readonly IDt_InboundOrderDetailRepository _dt_InboundOrderDetailRepository;
    private readonly IDt_MaterielInfoRepository _dt_MaterielInfoRepository;
    private readonly IDt_InboundOrderRepository _dt_InboundOrderRepository;
    private readonly IDt_BillGroupStock_HtyRepository _dt_BillGroupStock_HtyRepository;
    private readonly IDt_BillGroupStockDetail_HtyRepository _dt_BillGroupStockDetail_HtyRepository;
 
    public Dt_BillGroupStockService(IDt_BillGroupStockRepository baseDal,
                                    IUnitOfWorkManage unitOfWorkManage,
                                    IDt_OutOrderService outOrderService,
                                    IDt_OutOrderAndStockRepository outOrderAndStockRepository,
                                    IMapper mapper,
                                    IDt_OutOrderAndStock_HtyService outOrderAndStock_HtyService,
                                    IDt_BillGroupStockDetailRepository dt_BillGroupStockDetailRepository,
                                    IDt_InboundOrderDetailRepository dt_InboundOrderDetailRepository,
                                    IDt_MaterielInfoRepository dt_MaterielInfoRepository,
                                    IDt_InboundOrderRepository dt_InboundOrderRepository,
                                    IDt_BillGroupStock_HtyRepository dt_BillGroupStock_HtyRepository,
                                    IDt_BillGroupStockDetail_HtyRepository dt_BillGroupStockDetail_HtyRepository) : base(baseDal)
    {
        _unitOfWorkManage = unitOfWorkManage;
        _outOrderService = outOrderService;
        _OutOrderAndStockRepository = outOrderAndStockRepository;
        _mapper = mapper;
        _OutOrderAndStock_HtyService = outOrderAndStock_HtyService;
        _dt_BillGroupStockDetailRepository = dt_BillGroupStockDetailRepository;
        _dt_InboundOrderDetailRepository = dt_InboundOrderDetailRepository;
        _dt_MaterielInfoRepository = dt_MaterielInfoRepository;
        _dt_InboundOrderRepository = dt_InboundOrderRepository;
        _dt_BillGroupStock_HtyRepository = dt_BillGroupStock_HtyRepository;
        _dt_BillGroupStockDetail_HtyRepository = dt_BillGroupStockDetail_HtyRepository;
    }
 
    #region 外部接口
 
    /// <summary>
    /// 根据特定条件获取库存
    /// </summary>
    /// <param name="palletCode">托盘号</param>
    /// <param name="locationID">货位ID</param>
    /// <param name="materialNo">物料编号</param>
    /// <returns>特定库存</returns>
    public async Task<Dt_BillGroupStock> GetStocks(string palletCode = null, string locationID = null, string materialNo = null)
    {
        return await Db.Queryable<Dt_BillGroupStock>()
            .WhereIF(palletCode != null, x => x.PalletCode == palletCode)
            .WhereIF(locationID != null, x => x.LocationCode == locationID)
            .WhereIF(materialNo != null, x => x.MaterialNo == materialNo)
            .Includes(x => x.LocationInfo)
            .Includes(x => x.Dt_BillGroupStockDetailList)
            .FirstAsync();
    }
 
    #endregion 外部接口
 
    #region 内部调用方法
 
    /// <summary>
    /// 更新库存集合
    /// </summary>
    /// <param name="stocks">库存集合</param>
    /// <returns>成功/失败</returns>
    public bool UpdateNavStock(List<Dt_BillGroupStock> stocks)
    {
        return BaseDal.UpdateNavStock(stocks);
    }
 
    /// <summary>
    /// 更新单个库存
    /// </summary>
    /// <param name="stocks">库存</param>
    /// <returns>成功/失败</returns>
    public bool UpdateNavStock(Dt_BillGroupStock stocks)
    {
        return BaseDal.UpdateNavStock(stocks);
    }
 
    public List<Dt_BillGroupStock> GetOutboundStockList(string materialCode)
    {
        return BaseDal.GetOutboundStockList(materialCode);
    }
 
    #endregion 内部调用方法
 
    #region private内部方法
 
    /// <summary>
    /// 根据订单号获取订单
    /// </summary>
    /// <param name="orderNumber">订单号</param>
    /// <returns>订单对象</returns>
    private Dt_OutOrder GetOrder(string orderNumber)
    {
        // 获取订单信息
        var content = _outOrderService.GetOutOrderByNumber(orderNumber);
 
        // 检查订单是否获取成功
        if (!content.Status)
        {
            return null;
        }
 
        // 反序列化订单对象
        return (Dt_OutOrder)content.Data;
    }
 
    /// <summary>
    /// 更新库存状态
    /// </summary>
    /// <param name="filteredStocks">筛选后的库存列表</param>
    /// <returns>更新后的库存列表</returns>
    private List<Dt_BillGroupStock> UpdateStocks(List<Dt_BillGroupStock> filteredStocks)
    {
        var updatedStocks = new List<Dt_BillGroupStock>();
 
        foreach (var stock in filteredStocks)
        {
            // 更新库存状态
            stock.LocationInfo.IsLocked = true;
            stock.LocationInfo.Status = 0;
            stock.State = 5;
            updatedStocks.Add(stock);
        }
 
        return updatedStocks;
    }
 
    /// <summary>
    /// 创建订单库存列表
    /// </summary>
    /// <param name="stock">筛选后的库存列表</param>
    /// <param name="order">订单对象</param>
    /// <returns>订单库存列表</returns>
    private List<Dt_OutOrderAndStock> CreateOrderStock(List<Dt_BillGroupStock> stock, Dt_OutOrder order)
    {
        var orderStocks = new List<Dt_OutOrderAndStock>();
        foreach (var item in stock)
        {
            orderStocks.Add(new Dt_OutOrderAndStock()
            {
                AllocatedQuantity = order.OrderDetailList.AllocatedQuantity,
                MaterialNo = item.MaterialNo,
                MaterialName = order.OrderDetailList.MaterialName,
                OrderNumber = order.OrderNumber,
                OutboundQuantity = order.OrderDetailList.OutboundQuantity,
                PalletCode = item.PalletCode,
                PalletQuantity = item.Dt_BillGroupStockDetailList.Sum(x => x.PalletQuantity),
                State = item.State,
                BatchNumber = order.OrderDetailList.BatchNumber,
                CompletedQuantity = order.OrderDetailList.CompletedQuantity,
                Creater = "System",
                CreateDate = DateTime.Now,
                GroupId = item.GroupId,
                LocationCode = item.LocationInfo.LocationCode,
                OutOrderId = order.Id,
            });
        }
 
        return orderStocks;
    }
 
    #endregion private内部方法
 
    #region PDA组盘
 
    /// <summary>
    /// PDA组盘前校验
    /// PDA组盘确认保存组盘信息
    /// </summary>
    /// <param name="dt_BillGroupStock">组盘信息</param>
    /// <returns></returns>
    public WebResponseContent PDAGroupPlateConfirm(Dt_BillGroupStock dt_BillGroupStock)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            string requeststr = JsonConvert.SerializeObject(dt_BillGroupStock);
            new LogLibrary.Log.LogFactory().GetLog("接口").InfoFormat(true, "PDA组盘-PDAGroupPlate", "请求", requeststr);
            //是否新增
            bool isAdd = true;
 
            #region 组盘前校验
 
            //查询入库确认和入库完成状态的库存是否存在,不允计组盘
            List<Dt_BillGroupStock> billGrouplist = BaseDal.QueryData(x => x.PalletCode == dt_BillGroupStock.PalletCode && (x.State == (int)StockStateEmun.入库确认 || x.State == (int)StockStateEmun.入库完成));
            if (billGrouplist != null && billGrouplist.Count > 0)
            {
                return content.Error("当前托盘已存在组盘信息,库存状态为已确认入库或者入库完成!");
            }
 
            //1,判断托盘号是否重复(一次组盘重复时不允计组盘,多次组盘重复时可以组盘)
            List<Dt_BillGroupStock> billGroups = BaseDal.QueryData(x => x.PalletCode == dt_BillGroupStock.PalletCode && (x.State == (int)StockStateEmun.组盘暂存));
            if (billGroups != null && billGroups.Count == 1)
            {
                if (dt_BillGroupStock.Dt_BillGroupStockDetailList.Count == 0)
                {
                    return content.Error("组盘明细列表不能为空!");
                }
 
                isAdd = false;
                Dt_BillGroupStock billGroupStock = billGroups[0];
                //如果是多次组盘,托盘号重复可以继续组盘
                if (dt_BillGroupStock.GroupType == (int)GroupTypeEmun.多次组盘)
                {
                    if (Convert.ToBoolean(billGroupStock.IsFull))//如果已满盘,不能多次组盘
                    {
                        new LogLibrary.Log.LogFactory().GetLog("接口").InfoFormat(true, "PDA组盘-PDAGroupPlate", "响应", "已满盘不能进行多次组盘!");
                        return content.Error("已满盘不能进行多次组盘!");
                    }
                }
                else
                {
                    new LogLibrary.Log.LogFactory().GetLog("接口").InfoFormat(true, "PDA组盘-PDAGroupPlate", "响应", "当前托盘已组盘,不允计重复组盘!");
                    return content.Error("当前托盘号重复,不允计组盘!");
                }
            }
            else if (billGroups != null && billGroups.Count > 1)
            {
                new LogLibrary.Log.LogFactory().GetLog("接口").InfoFormat(true, "PDA组盘-PDAGroupPlate", "响应", "当前托盘已存在组盘信息!");
                return content.Error("当前托盘已存在组盘信息!");
            }
            else
            {
                isAdd = true;
            }
            List<Dt_BillGroupStockDetail> billGroupStockDetails = new List<Dt_BillGroupStockDetail>();
            billGroupStockDetails = dt_BillGroupStock.Dt_BillGroupStockDetailList;
 
            foreach (var item in billGroupStockDetails)
            {
                int count = _dt_MaterielInfoRepository.QueryData(x => x.MaterielCode == item.MaterialNo).Count();//在物料信息表中查询物料是否存在
                if (count == 0)//物料不存在
                {
                    new LogLibrary.Log.LogFactory().GetLog("接口").InfoFormat(true, "PDA组盘-PDAGroupPlate", "响应", $"该物料信息不存在:{item.MaterialName}+{item.MaterialNo}");
                    return content.Error($"该物料信息不存在:{item.MaterialName}+{item.MaterialNo},请维护物料基本信息!");
                }
            }
            var groupDetailsByOrderDetailId = billGroupStockDetails.GroupBy(x => x.OrderDetailId).ToList();
 
            foreach (var item in groupDetailsByOrderDetailId)
            {
                //查询入库单明细预计入库数量
                decimal PreInboundQuantity = _dt_InboundOrderDetailRepository.QueryData(x => x.OrderDetailId == item.Key).Sum(x => Convert.ToDecimal(x.PreInboundQuantity));
                //根据入库单明细ID,获取已组盘数量
                decimal PalletQuantity = Convert.ToDecimal(Db.Queryable<Dt_BillGroupStock>().InnerJoin<Dt_BillGroupStockDetail>((s, sd) => s.GroupId == sd.GroupId && sd.GroupDetailId == item.Key && s.State != (int)StockStateEmun.组盘撤销).Select((s, sd) => sd).ToList().Sum(x => x.PalletQuantity));
 
                decimal currentPalletQuantity = Convert.ToDecimal(billGroupStockDetails.Sum(x => x.PalletQuantity));
                if (currentPalletQuantity > PreInboundQuantity - PalletQuantity)//如果当前组盘数量比未组盘数量多,需重新调整物料数量
                {
                    new LogLibrary.Log.LogFactory().GetLog("接口").InfoFormat(true, "PDA组盘-PDAGroupPlate", "响应", $"当前组盘物料数量大于单据明细物料数量,需重新调整物料数量!明细ID{item.Key}");
                    return content.Error($"当前组盘物料数量大于单据明细物料数量,需重新调整物料数量!明细ID{item.Key}");
                }
            }
 
            #endregion 组盘前校验
 
            #region 保存组盘信息
 
            try
            {
                dt_BillGroupStock.State = (int)StockStateEmun.组盘暂存;
                //开启事物
                _unitOfWorkManage.BeginTran();
                //todo:加个判断是新增还是修改(已处理)
                if (isAdd)//一次组盘-需新增表头
                {
                    BaseDal.AddData(dt_BillGroupStock);
                }
                else //多次组盘-只需修改表头
                {
                    BaseDal.UpdateData(dt_BillGroupStock);
                }
                //查询组盘主表获取主表主键ID,用于更新明细
                Dt_BillGroupStock billGroupStock = BaseDal.QueryFirst(x => x.PalletCode == dt_BillGroupStock.PalletCode);
                dt_BillGroupStock.Dt_BillGroupStockDetailList?.ForEach(x => x.GroupId = billGroupStock.GroupId);
                //添加组盘明细
 
                _dt_BillGroupStockDetailRepository.AddData(dt_BillGroupStock.Dt_BillGroupStockDetailList);
 
                //提交事务
                _unitOfWorkManage.CommitTran();
                content.OK("组盘成功!", dt_BillGroupStock);
            }
            catch
            {
                _unitOfWorkManage.RollbackTran();
                throw;
            }
 
            #endregion 保存组盘信息
        }
        catch (Exception ex)
        {
            new LogLibrary.Log.LogFactory().GetLog("接口").ErrorFormat(true, "PDA组盘-PDAGroupPlate", "响应", $"托盘号:{dt_BillGroupStock.PalletCode}组盘异常:{ex.Message}");
            content.Error($"托盘号:{dt_BillGroupStock.PalletCode} 组盘异常:{ex.Message}");
        }
        return content;
    }
 
    /// <summary>
    /// PDA组盘撤销确认,解绑托盘码和物料码
    /// 1,根据托盘码查询状态为“组盘暂存”组盘信息  2,修改库存状态为"组盘撤销",
    /// </summary>
    /// <param name="plateCode">托盘号</param>
    /// <returns></returns>
    public WebResponseContent PDAGroupPlateRevoke(string plateCode)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            new LogLibrary.Log.LogFactory().GetLog("接口").InfoFormat(true, "PDA撤销组盘-PDAGroupPlateRevoke", "请求", plateCode);
            Dt_BillGroupStock_Hty billGroupStockHty = new Dt_BillGroupStock_Hty();
            List<Dt_BillGroupStockDetail_Hty> billGroupStockDetailHtys = new List<Dt_BillGroupStockDetail_Hty>();
            List<Dt_BillGroupStockDetail> details = new List<Dt_BillGroupStockDetail>();
            //1,根据托盘码查询状态为“组盘暂存”组盘信息
            List<Dt_BillGroupStock> billGroupStockList = BaseDal.QueryData(x => x.PalletCode == plateCode && x.State == (int)StockStateEmun.组盘暂存);
            if (billGroupStockList != null && billGroupStockList.Count > 0)
            {
                Dt_BillGroupStock billGroupStock = billGroupStockList[0];
 
                #region 组盘历史表
 
                billGroupStockHty.PalletCode = plateCode;
                billGroupStockHty.OrderNo = billGroupStock.OrderNo;
                billGroupStockHty.OrderType = billGroupStock.OrderType;
                billGroupStockHty.MaterialNo = billGroupStock.MaterialNo;
                billGroupStockHty.BatchNo = billGroupStock.BatchNo;
                billGroupStockHty.GroupType = billGroupStock.OrderType;
                billGroupStockHty.GroupWay = billGroupStock.GroupWay;
                billGroupStockHty.IsFull = billGroupStock.IsFull;
                billGroupStockHty.LocationCode = billGroupStock.LocationCode;
                billGroupStockHty.State = (int)StockStateEmun.组盘撤销; //2,修改库存状态为"组盘撤销,并移到组盘历史记录表中
                billGroupStockHty.Remark = billGroupStock.Remark;
                billGroupStockHty.Creater = billGroupStock.Creater;
                billGroupStockHty.CreateDate = billGroupStock.CreateDate;
                billGroupStockHty.StockDetailList = new List<Dt_BillGroupStockDetail_Hty>();
                details = _dt_BillGroupStockDetailRepository.QueryData(x => x.GroupId == billGroupStock.GroupId);
                foreach (var item in details)
                {
                    Dt_BillGroupStockDetail_Hty billGroupStockDetailHty = new Dt_BillGroupStockDetail_Hty();
                    billGroupStockDetailHty.GroupId = item.GroupId;
                    billGroupStockDetailHty.PalletCode = item.PalletCode;
                    billGroupStockDetailHty.OrderNo = item.OrderNo;
                    billGroupStockDetailHty.OrderDate = item.OrderDate;
                    billGroupStockDetailHty.OrderDetailId = item.OrderDetailId;
                    billGroupStockDetailHty.BatchNo = item.BatchNo;
                    billGroupStockDetailHty.MaterialNo = item.MaterialNo;
                    billGroupStockDetailHty.MaterialName = item.MaterialName;
                    billGroupStockDetailHty.OutBoxCode = item.OutBoxCode;
                    billGroupStockDetailHty.InBoxCode = item.InBoxCode;
                    billGroupStockDetailHty.EmptyPalletCode = item.EmptyPalletCode;
                    billGroupStockDetailHty.PalletUnit = item.PalletUnit;
                    billGroupStockDetailHty.PalletQuantity = item.PalletQuantity;
                    billGroupStockDetailHty.BasicUnit = item.BasicUnit;
                    billGroupStockDetailHty.BasicQuantity = item.BasicQuantity;
                    billGroupStockDetailHty.Creater = item.Creater;
                    billGroupStockDetailHty.CreateDate = item.CreateDate;
                    billGroupStockDetailHtys.Add(billGroupStockDetailHty);
                }
 
                #endregion 组盘历史表
 
                try
                {
                    //开启事物
                    _unitOfWorkManage.BeginTran();
                    _dt_BillGroupStock_HtyRepository.AddData(billGroupStockHty);
                    _dt_BillGroupStockDetail_HtyRepository.AddData(billGroupStockDetailHtys);
                    BaseDal.DeleteData(billGroupStockList[0]);
                    _dt_BillGroupStockDetailRepository.DeleteData(details);
                    //提交事务
                    _unitOfWorkManage.CommitTran();
 
                    new LogLibrary.Log.LogFactory().GetLog("接口").InfoFormat(true, "PDA撤销组盘-PDAGroupPlateRevoke", "响应", $"撤销组盘成功");
                    content.OK("撤销组盘成功");
                }
                catch (Exception)
                {
                    _unitOfWorkManage.RollbackTran();
                    throw;
                }
            }
            else
            {
                new LogLibrary.Log.LogFactory().GetLog("接口").InfoFormat(true, "PDA撤销组盘-PDAGroupPlate", "响应", $"撤销组盘失败,未查询到可以撤销的组盘");
                content.OK("撤销组盘失败,未查询到可以撤销的组盘");
            }
        }
        catch (Exception ex)
        {
            new LogLibrary.Log.LogFactory().GetLog("接口").ErrorFormat(true, "PDA撤销组盘-PDAGroupPlate", "响应", $"托盘号:{plateCode}组盘异常:{ex.Message}");
            content.Error($"托盘号:{plateCode} 撤销组盘异常:{ex.Message}");
        }
 
        return content;
    }
 
    #endregion PDA组盘
}