zs
2025-05-14 0e5c33e776e68700dbe443cd453dd844b125a2fc
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
using CMS.Plugin.FormulaManagement.Abstractions;
using CMS.Plugin.OrderManagement.Abstractions;
using CMS.Plugin.OrderManagement.Abstractions.Enums;
using CMS.Plugin.OrderManagement.Abstractions.Models;
using CMS.Plugin.PipeLineLems.Application.Contracts.Dtos.WorkPlan;
using CMS.Plugin.ProductManagement.Abstractions;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Microsoft.Extensions.DependencyInjection;
using NPOI.Util;
using CMS.Plugin.PipeLineLems.Domain.CallMaterialOrder;
using CMS.Plugin.PipeLineLems.Application.Contracts.Services;
using CMS.Plugin.PipeLineLems.Application.Contracts.Dtos.CallMaterialOrder;
using Volo.Abp.Uow;
using System.Text;
using CMS.Plugin.PipeLineLems.Domain.WorkPlan;
using CMS.Plugin.PipeLineLems.Domain.CallMaterialOrderRecord;
using Volo.Abp.Users;
using CmsQueryExtensions.Entitys;
using CMS.Unit.RuntimeValue.Abstractions;
using CMS.Extensions.Variable;
using CMS.Plugin.TraceManagement.Abstractions.Models.Traces;
using CMS.Plugin.ProcessManagement.Abstractions;
using KissUtil.Extensions;
using CMS.Plugin.TraceManagement.Abstractions;
using CMS.Plugin.ProductManagement.Abstractions.Models;
using CMS.Plugin.MaterialManagement.Abstractions;
 
namespace CMS.Plugin.PipeLineLems.Application.Implements;
 
/// <summary> 
/// 作业计划表应用服务 
/// </summary> 
public class SharedService : CMSPluginAppService
{
 
 
    public async Task<MesOrderResponse> CommonPick(IServiceProvider _serviceProvider, PickInput input, MyCurrentUser myCurrentUser)
    {
        //1、记录分拣记录表
        //2、更新作业计划表的状态 =已分拣
        //3、写入 分拣变量
 
        VariableService _variableService = _serviceProvider.GetRequiredService<VariableService>();
        var _workSectionManager = _serviceProvider.GetRequiredService<IWorkSectionManager>();
        var _workStationManager = _serviceProvider.GetRequiredService<IWorkStationManager>();
        var traceProvider = _serviceProvider.GetRequiredService<ITraceProvider>();
        var materialProvider = _serviceProvider.GetRequiredService<IMaterialProvider>();
        var workPlanAppService = _serviceProvider.GetRequiredService<IWorkPlanAppService>();
 
        Dictionary<string, object?> keyValuePairs = new Dictionary<string, object?>
                    {
                        { "分拣托盘号","托盘1"},
                        { "分拣方向", "短管装配"},
                        { "分拣人", myCurrentUser.UserAccount }
                    };
        _variableService.WriteValueAsync(keyValuePairs);
 
        //根据工序名获取工序对象
        var workSection = await _workSectionManager.GetByNameAsync("分拣工序");
        var workStation = await _workStationManager.GetByNameAsync("分拣工位");
        //写入追溯报表
        var finishTime = DateTime.Now;
        TraceModel traceModel = new TraceModel()
        {
            SerialNumber = input.PipeSpecCode,
            WorkSectionId = workSection.Id,
            WorkSectionName = workSection.Name,
            WorkStationName = workStation.Name,
 
            FinishTime = finishTime,
            IsQualified = true,
            UnqualifiedReason = "",
            ProductModel = "",
            ProductName = "",
 
        };
        traceModel.Params = new List<TraceParamModel>();
        foreach (var item in workSection.ProcessParameters)
        {
            var value = "ssss";
            traceModel.Params.Add(new TraceParamModel()
            {
                Key = item.Key,
                Value = value.SafeString()
            });
        }
        //物料参数列表
        var firstWorkPlans = await workPlanAppService.GetListByFilterAsync(x => x.PipeSpecCode == input.PipeSpecCode);
 
        var firstWorkPlan = await workPlanAppService.GetSingleByFilterAsync(x => x.PipeSpecCode == input.PipeSpecCode);
        var rawPipe_DataIdentifier = await materialProvider.FindByNameAsync("分拣原料管标识");
        var rawPipe_MaterialMode = await materialProvider.FindByNameAsync("分拣原料管型号");
        List<TraceMaterialModel> _MaterialParams = new List<TraceMaterialModel>();
        foreach (var item in workSection.MaterialParameters)
        {
            if (item.Name == "分拣原料管型号")
            {
                _MaterialParams.Add(new TraceMaterialModel()
                {
                    Key = item.Key,
                    Quantity = 1,
                    MaterialId = rawPipe_MaterialMode.MaterialId,
                    MaterialDetailId = rawPipe_MaterialMode.MaterialDetails.First().Id,
                    Value = firstWorkPlan.MaterialMode
 
                });
            }
            if (item.Name == "分拣原料管标识")
            {
                _MaterialParams.Add(new TraceMaterialModel()
                {
                    Key = item.Key,
                    Quantity = 1,
                    MaterialId = rawPipe_DataIdentifier.MaterialId,
                    MaterialDetailId = rawPipe_DataIdentifier.MaterialDetails.First().Id,
                    Value = firstWorkPlan.DataIdentifier,
 
                });
            }
        };
 
        //配置过程参数(采集参数、配方参数)
        traceModel.Params = new List<TraceParamModel>();
        foreach (var item in workSection.ProcessParameters)
        {
            string _value = "";
            if (item.Name == "分拣方向")
            {
                _value = "短管装配";
            }
            //item.Key
            TraceParamModel traceParamModel = new TraceParamModel()
            {
                Key = item.Key,
                Value = _value
            };
            traceModel.Params.Add(traceParamModel);
        };
 
        traceModel.MaterialParams = _MaterialParams;
 
        await traceProvider.CreateTraceAsync(traceModel);
 
        var response = new MesOrderResponse
        {
            Code = "200",
            Data = "",
            Message = "处理成功",
            Time = DateTime.UtcNow
        };
        return response;
    }
    /// <summary>
    /// 创建作业计划
    /// </summary>
    /// <param name="input"></param>
    /// <param name="_serviceProvider"></param>
    /// <param name="workPlanAppService"></param>
    /// <returns></returns>
    /// <exception cref="UserFriendlyException"></exception>
 
    public async Task<MesOrderResponse> CommonCreatebyApsAsync(List<WorkPlanInput> input, IServiceProvider _serviceProvider,
    WorkPlanAppService workPlanAppService,
    string userId, string userAccount
    )
    {
 
        if (input == null)
        {
            throw new UserFriendlyException("输入参数不能为空");
        }
 
        if (input.Count == 0)
        {
            throw new UserFriendlyException("输入参数Data不能为空");
        }
 
        //校验数据
        //1、原料标识相同的不能存在于两个 管段编号中
        //var validationResult = ValidateUniqueDataIdentifierPerPipeSection(input);
        //if (!validationResult.isValid)
        //{
        //    处理验证失败的情况
        //    throw new UserFriendlyException($"验证失败: {validationResult.errorMessage}");
        //    返回错误信息给客户端或进行其他处理
        //}
 
 
        var callMaterialOrderAppService = _serviceProvider.GetRequiredService<ICallMaterialOrderAppService>();
 
        var orderManager = _serviceProvider.GetRequiredService<IOrderManager>();
        var productProvider = _serviceProvider.GetRequiredService<IProductProvider>();
        var formulaProvider = _serviceProvider.GetRequiredService<IFormulaProvider>();
 
        List<OrderModel> orderModels = new List<OrderModel>();
 
        #region 事务
 
        using var scope = _serviceProvider.CreateScope();
        var unitOfWorkManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
        using var uow = unitOfWorkManager.Begin(requiresNew: true);
 
        try
        {
            #region 数据处理
 
            //按照 原料标识 分组
            var groupTask = input.GroupBy(x => x.DataIdentifier);
            foreach (var gTask in groupTask)
            {
 
 
 
                //var product = await productProvider.FindByNameAsync(orderItem.PipeSectionName);
                //if (product == null)
                //{
                //    throw new UserFriendlyException($"产品名称[{orderItem.PipeSectionName}]不存在");
                //}
 
                //var formula = await formulaProvider.GetFormulaAsync(product.Id);
                //if (formula == null)
                //{
                //    throw new UserFriendlyException($"产品型号[{orderItem.MaterialCode}]无关联配方");
                //}
                //首先要创建 打码切割的工单 
                var productForCut = await productProvider.FindByNameAsync("切割原料管");
                if (productForCut == null)
                {
                    throw new UserFriendlyException($"产品名称[切割原料管]不存在");
                }
                var formulaForCut = await formulaProvider.GetFormulaAsync(productForCut.Id);
                if (formulaForCut == null)
                {
                    throw new UserFriendlyException($"产品名称[切割原料管]无关联配方");
                }
                //按照 管段编号 分组
                var group = gTask.ToList().GroupBy(x => x.PipeSpecCode);
                foreach (var item in group)
                {
                    var prodOrderNo = "Order_" + item.Key;
                    var order = await orderManager.GetByCodeAsync(prodOrderNo);
                    if (order != null)
                    {
                        //throw new UserFriendlyException($"生产工单[{prodOrderNo}]已存在");
                        continue;
                    }
 
                    OrderModel orderModelForCut = new OrderModel()
                    {
                        Id = Guid.NewGuid(),
                        Code = prodOrderNo,
                        Source = "APS推送",
                        PlanStartTime = gTask.ToList().First().PlannedStartTime,
                        PlanFinishTime = gTask.ToList().First().PlannedEndTime,
                        PlanQty = 1,
                        Status = OrderStatus.NotActive,
                        Product = new AssociationProductModel() { Id = productForCut.Id, Name = productForCut.Name, Model = productForCut.Model, ShortNumber = productForCut.ShortNumber },
                        Formula = new AssociationFormulaModel() { Id = formulaForCut.Id, Code = formulaForCut.Code, Name = formulaForCut.Name }
                    };
                    orderModelForCut.ExtraProperties["OuterDiameter"] = gTask.ToList().First().OuterDiameter;//外径
                    orderModelForCut.ExtraProperties["Material"] = gTask.ToList().First().Material;//材质
                    orderModelForCut.ExtraProperties["Length"] = gTask.ToList().First().Length;//长度
                    orderModelForCut.ExtraProperties["DataIdentifier"] = gTask.ToList().First().DataIdentifier;//原料标识
                    orderModelForCut.ExtraProperties["MaterialMode"] = gTask.ToList().First().MaterialMode;//原料类型
                    orderModelForCut.ExtraProperties["PipeFittingCode"] = gTask.ToList().First().PipeFittingCode;//管段编号
 
                    var orderForCut = await orderManager.GetByCodeAsync(orderModelForCut.Code);
                    if (orderForCut != null)
                    {
                        //throw new UserFriendlyException($"工单[{orderModelForCut.Code}]已存在");
                        //不再抛异常,直接跳过
                        break;
                    }
 
                    var orderModelResultForCut = await orderManager.CreateAsync(orderModelForCut);
                    if (orderModelResultForCut == null)
                    {
                        throw new UserFriendlyException($"工单[{orderModelForCut.Code}]创建失败");
                    }
                    orderModels.Add(orderModelResultForCut);
 
 
                    //OrderModel orderModel = new OrderModel();
                    //orderModel.Id = Guid.NewGuid();
                    //orderModel.Code = orderItem.TaskCode;
                    //orderModel.Source = "APS推送";
                    //orderModel.Product = new AssociationProductModel() { Id = product.Id, Name = product.Name, Model = product.Model, ShortNumber = product.ShortNumber };
                    ////orderModel.Formula = new AssociationFormulaModel() { Id = formula.Id, Code = formula.Code, Name = formula.Name };
                    //orderModel.PlanStartTime = orderItem.PlannedStartTime;
                    //orderModel.PlanFinishTime = orderItem.PlannedEndTime;
                    //orderModel.PlanQty = (ulong?)orderItem.OrderQty;
                    //orderModel.Status = OrderStatus.NotActive;
                    //orderModel.ExtraProperties["Source"] = "ddd";
                    //var source = orderModel.ExtraProperties["Source"];
                    //var orderModelResult = await orderManager.CreateAsync(orderModel);
                    //if (orderModelResult == null)
                    //{
                    //    throw new UserFriendlyException($"工单[{orderItem.TaskCode}]创建失败");
                    //}
                    //orderModels.Add(orderModelResult);
                }
 
 
                //保存到 scms_callmaterialorders 表中
                CallMaterialOrderCreateDto insertObjForOrder = new CallMaterialOrderCreateDto()
                {
                    CallMaterialStatus = Domain.Shared.Enums.CallMaterialStatusEnum.未执行,
                    DataIdentifier = gTask.Key,
                    MaterialMode = gTask.ToList().First().MaterialMode,
                    CreatorName = userAccount,
                    Quantity = 1
                };
 
                await callMaterialOrderAppService.CreateAsync(insertObjForOrder);
            }
 
 
 
            //throw new UserFriendlyException($"主动触发失败");
            //保存到  scms_workplans 表中
            foreach (var item in input)
            {
                var insertObj = ObjectMapper.Map<WorkPlanInput, WorkPlanCreateDto>(item);
                //insertObj.OrgMaterialCode = "1111";
                insertObj.CallMaterialStatus = Domain.Shared.Enums.CallMaterialStatusEnum.未执行;
                insertObj.WorkPlanStatus = Domain.Shared.Enums.WorkPlanStatusEnum.未生产;
                insertObj.Sort = 1;
                insertObj.CreatorName = userAccount;
                insertObj.Remark = "系统导入";
                await workPlanAppService.CreateAsync(insertObj);
            }
 
            #endregion
 
            await uow.CompleteAsync();
        }
        catch (Exception)
        {
            await uow.RollbackAsync();
            throw;
        }
        finally
        {
 
        }
 
 
 
        #endregion
 
 
 
        // 发布事件
        //await _eventBus.PublishAsync(new EntityChangedEto("MESCREATE", input, null, EntityChangeType.Add, true));
 
        var response = new MesOrderResponse
        {
            Code = "000000",
            Data = orderModels,
            Message = "处理成功",
            Time = DateTime.UtcNow
        };
        return response;
    }
 
    /// <summary>
    /// 验证原料标识相同的记录不能存在于两个不同的管段编号中
    /// </summary>
    /// <param name="inputs">作业计划输入参数列表</param>
    /// <returns>验证结果,包含是否通过验证及错误信息</returns>
    public static (bool isValid, string errorMessage) ValidateUniqueDataIdentifierPerPipeSection(List<WorkPlanInput> inputs)
    {
        if (inputs == null || !inputs.Any())
        {
            return (true, string.Empty);
        }
 
        // 使用Lookup分组,键为原料标识,值为对应的管段编号集合
        var dataIdentifierGroups = inputs.ToLookup(x => x.DataIdentifier, x => x.PipeSpecCode);
 
        foreach (var group in dataIdentifierGroups)
        {
            // 忽略空的原料标识
            if (string.IsNullOrEmpty(group.Key))
            {
                continue;
            }
 
            // 获取当前原料标识对应的唯一管段编号集合
            var uniquePipeSections = group.Distinct().ToList();
 
            // 如果存在多个不同的管段编号,则违反规则
            if (uniquePipeSections.Count > 1)
            {
                return (false, $"原料标识 '{group.Key}' 存在于多个不同的管段编号中: {string.Join(", ", uniquePipeSections)}");
            }
        }
 
        return (true, string.Empty);
    }
 
 
    /// <summary>
    /// 根据原料标识进行叫料操作
    /// </summary>
    /// <param name="dataIdentifier">原料标识</param>
    /// <param name="_serviceProvider">服务提供者</param>
    /// <returns>操作结果</returns>
    /// <exception cref="UserFriendlyException">当数据不存在或状态不允许叫料时抛出</exception>
    public async Task<MesOrderResponse> CallMaterialByDataIdentifier(Guid id, IServiceProvider _serviceProvider)
    {
        if (string.IsNullOrEmpty(id.ToString()))
        {
            throw new UserFriendlyException("原料标识不能为空");
        }
 
        var callMaterialOrderRepository = _serviceProvider.GetRequiredService<ICallMaterialOrderRepository>();
        var workPlanRepository = _serviceProvider.GetRequiredService<IWorkPlanRepository>();
        var callMaterialOrderRecordRepository = _serviceProvider.GetRequiredService<ICallMaterialOrderRecordRepository>();
        var orderManager = _serviceProvider.GetRequiredService<IOrderManager>();
 
        // 查找数据
 
        var callMaterialOrder = await callMaterialOrderRepository.GetAsync(id);
        if (callMaterialOrder == null)
        {
            throw new UserFriendlyException($"找不到叫料记录");
        }
 
        // 验证状态
        if (callMaterialOrder.CallMaterialStatus != Domain.Shared.Enums.CallMaterialStatusEnum.未执行)
        {
            throw new UserFriendlyException($"原料标识为 '{callMaterialOrder.DataIdentifier}' 的叫料记录状态为 '{callMaterialOrder.CallMaterialStatus}',不允许叫料");
        }
 
        // 更新数据
        callMaterialOrder.WmsRetResult = "成功";
        callMaterialOrder.WmsTaskNo = GenerateRandomTaskNo();
        callMaterialOrder.CallMaterialStatus = Domain.Shared.Enums.CallMaterialStatusEnum.叫料完成;
        callMaterialOrder.LastModifierName = "SuperAdmin";
 
        await callMaterialOrderRepository.UpdateAsync(callMaterialOrder);
 
        //更新作业计划表
        var workPlanList = await workPlanRepository.FindByDataIdentifierAsync(callMaterialOrder.DataIdentifier);
        foreach (var item in workPlanList)
        {
            item.CallMaterialStatus = Domain.Shared.Enums.CallMaterialStatusEnum.叫料完成;
            item.LastModifierName = "SuperAdmin";
        }
        await workPlanRepository.UpdateManyAsync(workPlanList);
 
        //新增叫料记录表
        var callMaterialOrderRecord = new CallMaterialOrderRecord()
        {
            CallMaterialStatus = Domain.Shared.Enums.CallMaterialStatusEnum.叫料完成,
            MaterialMode = callMaterialOrder.MaterialMode,
            DataIdentifier = callMaterialOrder.DataIdentifier,
            Quantity = 1,
            WmsRetResult = callMaterialOrder.WmsRetResult,
            WmsTaskNo = callMaterialOrder.WmsTaskNo,
            CreatorName = "SuperAdmin"
        };
        await callMaterialOrderRecordRepository.InsertAsync(callMaterialOrderRecord);
 
        //更新工单表的状态
        var pipeSpecCodeList = workPlanList.Select(x => x.PipeSpecCode).Distinct().ToList();
        foreach (var item in pipeSpecCodeList)
        {
            var prodOrderNo = "Order_" + item;
            var order = await orderManager.GetByCodeAsync(prodOrderNo);
            if (order != null)
            {
                order.ExtraProperties["CallMaterialStatus"] = Domain.Shared.Enums.CallMaterialStatusEnum.叫料完成.ToString();
            }
            await orderManager.UpdateAsync(order);
        }
 
 
        // 返回结果
        var response = new MesOrderResponse
        {
            Code = "200",
            Message = "叫料成功",
            Time = DateTime.UtcNow
        };
        return response;
    }
 
    /// <summary>
    /// 生成随机的WmsTaskNo
    /// </summary>
    /// <returns>随机生成的任务编号</returns>
    private string GenerateRandomTaskNo()
    {
        // 获取当前时间戳(从1970-01-01 00:00:00 UTC到现在的秒数)
        long timestamp = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
 
        // 生成前缀
        return $"WMS{timestamp}";
    }
}