schangxiang@126.com
2025-09-17 ff43ddf18764629ff875478e4e47a7281cbd230a
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
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
using Admin.NET.Application;
using Admin.NET.Core.TaskModule.Enum;
using iWareCC.Common.Helper;
using iWareCommon;
using iWareCommon.Common.Globle;
using iWareCommon.Utils;
using iWareModel.Entity.WCS;
using iWareSql.DataAccess;
using iWareSql.MyDbContext;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Entity;
using System.Linq;
using System.Threading;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
 
namespace iWareCC
{
    /// <summary>
    /// WCS任务完成线程(平库)
    /// </summary>
    public static class TaskFinishHandler
    {
        public static void Handler()
        {
            while (true)
            {
 
                Thread.Sleep(2000);//休眠2秒
                try
                {
                    if (SystemValue.isAllowRuning_PingKuTaskFinish && SystemValue.isStartedModel)
                    {
                        using (MyDbContext dbContext = new MyDbContext())
                        {
                            //只查询平库
 
                            var models = dbContext.wms_task
                                .Where(x => x.TaskStatus == (int)TaskStatusEnum.已下发)
                                .Where(x => (x.IsDelete == false)
                                //   && (x.AreaType == (int)AreaTypeEnum.平库)
                                ).ToList();
 
                            if (models != null && models.Count > 0)
                            {
                                FinishTask(dbContext,models);
                            }
                            SystemWarningMsg._lbl_Alert_PingKuTaskFinish = "";
                        }
                    }
                }
                catch (Exception ex)
                {
                    SystemWarningMsg._lbl_Alert_PingKuTaskFinish = "WCS任务完成线程(平库) 出现异常:" + ex.Message;
                    Log4NetHelper.WriteErrorLog(LogType.PingKuTaskFinish, "WCS任务完成线程(平库) 出现异常:" + ex.Message, ex);
                }
            }
        }
 
        /// <summary>
        /// 模拟完成任务调度
        /// </summary>
        /// <param name="mycontext"></param>
        /// <returns></returns>
        public static void FinishTask(MyDbContext dbContext, List<wms_task> taskList)
        {
            string errMsg = string.Empty;
            try
            {
 
 
 
 
                 //处理调度任务
                foreach (var singleTask in taskList)
                {
 
                    OrderMovementFinishTask(dbContext, singleTask, ref errMsg);
 
                    if (!string.IsNullOrEmpty(errMsg))
                    {
                        SystemWarningMsg._lbl_Alert_OutPlanTaskHandler += "任务号" + singleTask.TaskNo + "模拟完成任务失败," + errMsg;
                    }
 
                }
 
 
 
            }
            catch (Exception ex)
            {
                SystemWarningMsg._lbl_Alert_OutPlanTaskHandler = "错误信息:" + ex;
            }
        }
 
 
        /// <summary>
        /// 模拟完成 上、下架
        /// </summary>
        /// <param name="mycontext"></param>
        /// <param name="singleTask"></param>
        /// <param name="errMsg"></param>
        /// <returns></returns>
        private static int OrderMovementFinishTask(MyDbContext mycontext, wms_task singleTask, ref string errMsg)
        {
 
            try
            {
 
                //获取移动单
                var moveOrder = BaseInfoHelper.GetOrderMovement(mycontext, singleTask, ref errMsg);
                var moveOrderDetails = BaseInfoHelper.GetMoveOrderDetails(mycontext, singleTask, moveOrder, ref errMsg);
 
                //获取业务类型
                var wmsBusinessType = BusinessTypeHelper.GetBusinessTypeInfoFromDB(moveOrder.BusinessType, mycontext);
 
 
               
                //查询库位
                //目标库位校验
                var toPlace =BaseInfoHelper.GetPlace(mycontext, singleTask.ToPlaceCode, "目标库位", ref errMsg);
                //目标库区
 
                var toArea = BaseInfoHelper.GetArea(mycontext, singleTask.ToAreaCode, "目标库区", ref errMsg);
                
                ////源库位校验
                var sourcePlace = BaseInfoHelper.GetPlace(mycontext, singleTask.SourcePlaceCode, "源库位", ref errMsg);
 
 
                //解锁起始、目标库位
                sourcePlace.PlaceStatus = (int)PlaceStatusEnum.正常;
                toPlace.PlaceStatus = (int)PlaceStatusEnum.正常;
 
                //查询容器
                var container = BaseInfoHelper.GetContainer(mycontext, singleTask.ContainerCode, ref errMsg);
 
                //更新库位容器绑定关系
                UpdaeContainerPlace(mycontext, singleTask, container, toPlace, ref errMsg);
 
 
                //更新库存
                //上架更新库存状态=》已上架
                //下架更新冻结状态=》未冻结
                //创建事务记录
                //非下架、上架仅创建事务记录(因为变更了库位)
                UpdateStockQuan(mycontext, wmsBusinessType, singleTask, moveOrder, container, toPlace, toArea, ref errMsg);
 
                #region 处理移动单
                //处理移动单(上架单、下架单)
 
                //上架单或下架单业务类型设置了 自动完成 就 自动完成单据
                bool isFinish = false;
                if (wmsBusinessType.UpDownShelvesType == (int)UpDownShelvesTypeEnum.上架 || wmsBusinessType.BusinessTypeValue==(int)BusinessTypeEnum.盘点下架||
                    wmsBusinessType.DownShelvesIsAutoFinish == true)
                {
                    isFinish = true;
                }
 
                if (isFinish)
                {
                    if (moveOrderDetails.Any(a => string.IsNullOrWhiteSpace(a.ContainerCode)))
                    {
                        errMsg = $"{moveOrder.OrderTypeName}类型移动单{moveOrder.OrderNo}存在容器为空的移动单明细";
                        return 3;
                    }
                    //上架调度任务自动完成上架单
                    var updateMoveOrderDetails = moveOrderDetails.Where(w => w.ContainerCode.Equals(container.ContainerCode)).ToList();
 
                    if (updateMoveOrderDetails?.Count <= 0)
                    {
                        errMsg = $"{moveOrder.OrderTypeName}类型移动单{moveOrder.OrderNo}不存在容器为{container.ContainerCode}的移动单明细";
                        return 3;
                    }
                    foreach (var item in updateMoveOrderDetails)
                    {
                        item.OrderStatus = (int)OrderStatusEnum.已完成;
                        item.OrderStatusName = OrderStatusEnum.已完成.ToString();
                        item.UpdateTime = DateTime.Now;
                        item.UpdateUserId = 0;
                        item.UpdateUserName =FormCC.WcsSysUserName;
                    }
 
                    //更新移动单时间信息
                    UpdatOrderMovementStatus(moveOrderDetails, moveOrder, ref errMsg);
                }
 
                //盘点下架以外的下架不处理下架单,PDA分拣或自动完成分拣后完成下架单
 
                #endregion
 
                singleTask.TaskStatus = (int)TaskStatusEnum.已完成;//更新任务状态为 已完成
                singleTask.TaskStatusName = TaskStatusEnum.已完成.ToString();
                singleTask.UpdateTime = DateTime.Now;
                singleTask.TaskMsg = "任务完成";
                singleTask.FinishedTime = DateTime.Now;
 
                mycontext.SaveChanges();
                return 3;
            }
            catch (Exception ex)
            {
                SystemWarningMsg._lbl_Alert_OutPlanTaskHandler = "错误信息:" + ex;
                return 2;
            }
 
        }
 
        // <summary>
        /// 公共更新 移动单的 状态
        /// </summary>
        /// <param name="wmsOrderAsnDetails"></param>
        /// <param name="wmsOrderAsn"></param>
        public static void UpdatOrderMovementStatus(List<wms_order_movement_details> wmsOrderMovementDetails, wms_order_movement wmsOrderMovement, ref string errMsg)
        {
 
            var wmsOrderMovementDetailsAll = wmsOrderMovementDetails.Where(x => x.MovementId == wmsOrderMovement.Id && x.IsDelete == false).ToList();
            if (wmsOrderMovementDetailsAll?.Count <= 0)
            {
                errMsg = $"{wmsOrderMovement.OrderTypeName}类型移动单{wmsOrderMovement.OrderNo}更新状态,未获取到明细!";
            }
            else
            {
                int sttaus = (int)OrderStatusEnum.已完成;
                //汇总已完成的明细
                var totalOffShelvesCount = wmsOrderMovementDetailsAll.Count(o => o.OrderStatus == sttaus);
                //单据有所明细数量
                var totalTount = wmsOrderMovementDetailsAll.Count();
 
 
                if (totalOffShelvesCount == totalTount) //单据完结
                {
 
                    wmsOrderMovement.OrderStatus = (int)OrderStatusEnum.已完成;
                    wmsOrderMovement.OrderStatusName = OrderStatusEnum.已完成.ToString();
 
                    //更新时间信息
                    wmsOrderMovement.UpdateTime = DateTime.Now;
                    wmsOrderMovement.UpdateUserId = 0;
                    wmsOrderMovement.UpdateUserName =FormCC.WcsSysUserName;
                }
 
            
 
            }
        }
 
 
 
        /// <summary>
        /// 更新库存
        /// </summary>
        /// <param name="mycontext"></param>
        /// <param name="wmsBusinessType"></param>
        /// <param name="singleTask"></param>
        /// <param name="moveOrder"></param>
        /// <param name="updateStockList"></param>
        /// <param name="updateStockViewList"></param>
        /// <param name="toPlace"></param>
        /// <param name="toArea"></param>
        /// <param name="errMsg"></param>
        /// <exception cref="Exception"></exception>
        private static void UpdateStockQuan(MyDbContext mycontext, wms_base_business_type wmsBusinessType, wms_task singleTask, wms_order_movement moveOrder, wms_base_container container, wms_base_place toPlace, wms_base_area toArea, ref string errMsg)
        {
 
            //不是 上架,不是下架 不处理库存,仅操作库位转移
 
            string remark =  singleTask.BusinessTypeName + "-完成调度任务";
 
            var updateStockList = GetWmsStockQuanList(mycontext, container, ref errMsg);
            var updateStockViewList = GetWmsStockQuanViewList(mycontext, updateStockList, ref errMsg);
 
 
 
 
            foreach (var currentStock in updateStockList)
            {
                //再次之前库存的库位已经发生了变更 
 
                //上架
                if (wmsBusinessType.UpDownShelvesType== (int)UpDownShelvesTypeEnum.上架)
                {
                    // 待上架的库存,上架操作完成后变成 已上架
                    if (currentStock.StockStatus == (int)StockStatusEnum.待上架)
                    {
                        currentStock.StockStatus = (int)StockStatusEnum.已上架;
                        currentStock.StockStatusName = StockStatusEnum.已上架.ToString();
 
                    }
 
                }
                //下架
                else if (wmsBusinessType.UpDownShelvesType == (int)UpDownShelvesTypeEnum.下架)
                {
 
                    //盘点上架或 盘点下架 不解冻库存 调差解冻 
                    //下架任务完成不解冻库存,分拣完成后操作解冻
                    //没有分拣环节的 业务类型需要配置 自动完成单据,这里就解冻
                    if (wmsBusinessType.DownShelvesIsAutoFinish == true && moveOrder.BusinessType != (int)BusinessTypeEnum.盘点下架)
                    {
                        LockInfo freezeInfo = new LockInfo()
                        {
                            LockReason = "调度任务完成",
                            LockTime = DateTime.Now,
                            LockUser =FormCC.WcsSysUserName,
                            LockStatus = LockStatusEnum.未锁定,//
                        };
                        StockQuanHelper.UpdateStockLockStatus(currentStock, freezeInfo);
                    }
 
                }
                
 
                //在此之前库存的库位已经发生了变更 
                //更新时间信息
                currentStock.UpdateTime = DateTime.Now;
                currentStock.UpdateUserId = 0;
                currentStock.UpdateUserName =FormCC.WcsSysUserName;
 
                #region 添加调度任务
 
                var currentStockQuanView = updateStockViewList.FirstOrDefault(f => f.SNCode.Equals(currentStock.SNCode));
                if (currentStockQuanView == null)
                {
                    errMsg = $"跟踪码{currentStock.SNCode}没有获取到库存信息";
                    throw new Exception(errMsg);
                }
                wms_record_trans addWmsRecordTrans = CreateRecordTransInfo(moveOrder, currentStockQuanView, singleTask, currentStock, toPlace, toArea, remark);
                mycontext.wms_record_trans.Add(addWmsRecordTrans);
                #endregion
 
            }
 
 
        }
 
 
 
        /// <summary>
        /// 
        /// </summary>
        /// <param name="order"></param>
        /// <param name="currentStockQuanView"></param>
        /// <param name="task"></param>
        /// <param name="StockModel"></param>
        /// <param name="recordTransRemarks"></param>
        /// <returns></returns>
        private static wms_record_trans CreateRecordTransInfo(wms_order_movement order, v_wms_stock_quan currentStockQuanView, wms_task task , wms_stock_quan StockModel, wms_base_place toPlace, wms_base_area toArea, string recordTransRemarks)
        {
 
            try
            {
 
 
                TransferOtherDetail transferOtherDetail = new TransferOtherDetail()
                {
                    RelationNo = order.OrderNo,//上架单号
                    RelationNoLineNumber = string.Empty,//上架 关联单行号 无法精准获取 
                    Remarks = recordTransRemarks,
 
                };
 
 
 
                //源信息
                //新增的库存源信息都
                TransferDetail sourceDetail = new TransferDetail()
                {
                    SNCode = currentStockQuanView.SNCode,//源跟踪码
                    Quantity = currentStockQuanView.Quantity,//源库存数
                    StockStatus = currentStockQuanView.StockStatus,//源库存状态
                    StockStatusName = currentStockQuanView.StockStatusName,//源库存状态名称
                    StockQcStatus = currentStockQuanView.QCStatus,//源质量状态
                    StockQcStatusName = currentStockQuanView.QCStatusName,//源质量状态名称
                    ContainerCode = currentStockQuanView.ContainerCode,//源容器编号
                    ContainerName = currentStockQuanView.ContainerCode,//源容器名称
                    AreaCode = currentStockQuanView.AreaCode,//源库区编号
                    AreaName = currentStockQuanView.AreaName,//源库区名称
                    PlaceCode = currentStockQuanView.PlaceCode,//源库位编号
                    PlaceName = currentStockQuanView.PlaceName//源库位名称
 
                };
                //目标信息 确认质检产生的心得库存 库区、库位 容器跟源库存一样
                TransferDetail targetDetail = new TransferDetail()
                {
                    SNCode = StockModel.SNCode,//目标跟踪码
                    Quantity = StockModel.Quantity,//目标库存数
                    StockStatus = StockModel.StockStatus,//目标库存状态
                    StockStatusName = StockModel.StockStatusName,//目标库存状态名称
                    StockQcStatus = StockModel.QCStatus,//目标质量状态
                    StockQcStatusName = StockModel.QCStatusName,//目标质量状态名称
                    ContainerCode = StockModel.ContainerCode,//目标容器编号
                    ContainerName = StockModel.ContainerCode,//目标容器名称
                    AreaCode = toArea.AreaCode,//目标库区编号
                    AreaName = toArea.AreaName,//目标库区名称
                    PlaceCode = toPlace.PlaceCode,//目标库位编号
                    PlaceName = toPlace.PlaceName//目标库位名称
                };
 
                wms_record_trans addWmsRecordTrans = LogRecordHelper.CreateWmsRecordTrans(task, currentStockQuanView, sourceDetail, targetDetail, transferOtherDetail);
 
 
                return addWmsRecordTrans;
            }
            catch (Exception ex)
            {
 
                throw ex;
 
             
            }
        }
 
 
        /// <summary>
        /// 更新容器库位关系
        /// </summary>
        /// <param name="mycontext"></param>
        /// <param name="singleTask"></param>
        /// <param name="container"></param>
        /// <param name="toPlace"></param>
        /// <param name="errMsg"></param>
        private static void UpdaeContainerPlace(MyDbContext mycontext, wms_task singleTask, wms_base_container container, wms_base_place toPlace, ref string errMsg)
        {
            var containerPlaceList = mycontext.wms_container_place.Where(f => f.ContainerCode == singleTask.ContainerCode).ToList();
            if (containerPlaceList?.Count <= 0)
            {
                //新增库位关系绑定到目标容器
                wms_container_place addContainerPlace = new wms_container_place()
                {
                    Id = Yitter.IdGenerator.YitIdHelper.NextId(),
                    PlaceCode = toPlace.PlaceCode,
                    PlaceName = toPlace.PlaceName,
                    PlaceId = toPlace.Id,
                    ContainerName = container.ContainerName,
                    ContainerId = container.Id,
                    ContainerCode = singleTask.ContainerCode
                };
                addContainerPlace.PlaceCode = singleTask.ToPlaceCode;
                addContainerPlace.PlaceName = toPlace.PlaceName;
                addContainerPlace.PlaceId = toPlace.Id;
 
 
                addContainerPlace.CreateTime = DateTime.Now;
                addContainerPlace.CreateUserId = 0;
                addContainerPlace.CreateUserName =FormCC.WcsSysUserName;
                //addContainerPlace.UpdateTime = DateTime.Now;
                //addContainerPlace.UpdateUserId = 0;
                //addContainerPlace.UpdateUserName =FormCC.WcsSysUserName;
 
                mycontext.wms_container_place.Add(addContainerPlace);
            }
            else
            {
                if (containerPlaceList.Count > 1)
                {
                    errMsg = $"库位号{singleTask.ToPlaceCode},容器{singleTask.ContainerCode}有{containerPlaceList.Count}条绑定关系";
                    throw new Exception(errMsg);
                }
                else
                {
                    containerPlaceList.First().PlaceId = toPlace.Id;
                    containerPlaceList.First().PlaceCode = toPlace.PlaceCode;
                    containerPlaceList.First().PlaceName = toPlace.PlaceName;
 
                    containerPlaceList.First().UpdateTime = DateTime.Now;
                    containerPlaceList.First().UpdateUserId = 0;
                    containerPlaceList.First().UpdateUserName =FormCC.WcsSysUserName;
                }
            }
 
 
        }
 
        /// <summary>
        ///  获取库存详情信息-查询wms_stock_quan(表)
        /// </summary>
        /// <param name="mycontext"></param>
        /// <param name="container"></param>
        /// <param name="errMsg"></param>
        /// <returns></returns>
        private static List<wms_stock_quan> GetWmsStockQuanList(MyDbContext mycontext,wms_base_container container, ref string errMsg)
        {
 
            var updateStockList = mycontext.wms_stock_quan.Where(f => container.ContainerCode.Equals(f.ContainerCode)).ToList();
            if (updateStockList?.Count <= 0)
            {
                errMsg = $"容器{container.ContainerCode}库存不存在";
                throw new Exception(errMsg);
 
            }
 
            return updateStockList;
        }
 
        /// <summary>
        /// 获取库存详情信息-查询v_wms_stock_quan(视图)
        /// </summary>
        /// <param name="mycontext"></param>
        /// <param name="updateStockList"></param>
        /// <param name="errMsg"></param>
        /// <returns></returns>
        private static List<v_wms_stock_quan> GetWmsStockQuanViewList(MyDbContext mycontext,  List<wms_stock_quan> updateStockList, ref string errMsg)
        {
 
            var snCodeList = updateStockList.Select(s => s.SNCode).ToList();
 
            var updateStockViewList = mycontext.v_wms_stock_quan.Where(f => snCodeList.Contains(f.SNCode)).ToList();
            if (updateStockViewList?.Count <= 0)
            {
                errMsg = $"根据库存跟踪码没有获取到库存详情";
                throw new Exception(errMsg);
 
            }
 
            return updateStockViewList;
        }
 
 
 
    }
}