WorkOrderService.cs
44.4 KB
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
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
using Hh.Mes.Common.log;
using Hh.Mes.Common.Request;
using Hh.Mes.Pojo.System;
using Hh.Mes.POJO.ApiEntity;
using Hh.Mes.POJO.Entity;
using Hh.Mes.POJO.Response;
using Hh.Mes.POJO.EnumEntitys;
using Hh.Mes.POJO.WebEntity.bus;
using Hh.Mes.Service.Configure;
using Hh.Mes.Service.Repository;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using NPOI.SS.Formula.Atp;
namespace Hh.Mes.Service.Wo
{
/// <summary>
/// 组焊工单 (组焊清单)
/// </summary>
public class WorkOrderService : RepositorySqlSugar<bus_workOrder_head>
{
private readonly StationService _stationService;
private ResponseUpstream<string> responseOrder { get; set; }
public WorkOrderService(StationService stationService)
{
_stationService = stationService;
}
/// <summary>
/// //获取列表
/// </summary>
public Response Load(PageReq pageReq, bus_workOrder_head model)
{
var result = new Response();
try
{
string orderBy = (pageReq == null || string.IsNullOrEmpty(pageReq.field)) ? " id desc" : $"{pageReq.field} {pageReq.order} ";
string sqlWhere = SqlWhere(model);
var stringBuilder = new StringBuilder();
//页码,页数
//Exel ture 不分页
if (!model.Exel && pageReq != null)
{
stringBuilder.Append("declare @pageIndex int,@pageSize int,@offset int");
stringBuilder.AppendLine($" select @pageIndex={pageReq.page}, @pageSize={pageReq.limit}, @offset=(@pageIndex - 1) * @pageSize");
}
stringBuilder.AppendLine($@" select t1.* ,t2.lineName,t3.oprSequenceName
from {nameof(bus_workOrder_head)} t1 with(nolock)
left join base_line t2 with(nolock) on t1.lineCode=t2.lineCode
left join {nameof(base_process_route_detail)} t3 on t3.oprSequenceCode=t1.nowOprSequenceCode and t1.processHeadKeys=t3.headkeys
where {sqlWhere} {SqlFilter(model)}
order by {orderBy} ");
//Exel ture 不分页
if (!model.Exel)
{
stringBuilder.AppendLine(" offset @offset row fetch next @pageSize row only ");
stringBuilder.Append($@" select rowTotal= count(t1.id) from bus_workOrder_head t1 with(nolock)
WHERE Keys IN (SELECT headKeys FROM bus_workOrder_detail {SqlPageFilter(model)}) and {sqlWhere}");
}
var ds = Context.Ado.GetDataSetAll(stringBuilder.ToString(), new List<SugarParameter>(){
new SugarParameter("@productHeaderCode",model.productHeaderCode),
new SugarParameter("@workOrderCode", model.workOrderCode),
new SugarParameter("@planCode", model.planCode),
new SugarParameter("@planStartTime", model.planStartTime),
new SugarParameter("@planEndTime", model.planEndTime),
new SugarParameter("@state", model.state),
new SugarParameter("@lineCode", model.lineCode),
});
result.Result = ds.Tables[0];
result.Count = model.Exel ? (int)result.Result.Rows.Count : (int)ds.Tables[1].Rows[0]["rowTotal"];
return result;
}
catch (Exception ex)
{
return result.ResponseError(ex.Message);
}
}
public string SqlWhere(bus_workOrder_head model)
{
var stringBuilder = new StringBuilder();
stringBuilder.Append($"t1.isDelete!={SystemVariable.DeleteFlag}");
if (!string.IsNullOrWhiteSpace(model.productHeaderCode))
{
stringBuilder.Append(" and t1.productHeaderCode like '%'+@productHeaderCode+'%' ");
}
if (!string.IsNullOrWhiteSpace(model.workOrderCode)) stringBuilder.Append(" and t1.workOrderCode like '%'+@workOrderCode+'%' ");
if (!string.IsNullOrWhiteSpace(model.planCode)) stringBuilder.Append(" and t1.planCode like '%'+@planCode+'%' ");
if (model.planStartTime != null) stringBuilder.Append(" and t1.planStartTime >= @planStartTime ");
if (model.planEndTime != null) stringBuilder.Append(" and t1.planEndTime <=@planEndTime ");
if (model.state != null) stringBuilder.Append(" and t1.state =@state ");
if (!string.IsNullOrEmpty(model.lineCode) && model.lineCode != "all") stringBuilder.Append(" and t1.linecode=@lineCode");
return stringBuilder.ToString();
}
public string SqlFilter(bus_workOrder_head model)
{
//获取未报工的数据
if (model.stateDes == "false")
{
return $" and t6.workReportStatus <{(int)EnumWorkReportStatus.完工已报工}";
}
//获取已报工的数据
else if (model.stateDes == "true")
{
return $" and t6.workReportStatus >={(int)EnumWorkReportStatus.完工已报工}";
}
else
{
return string.Empty;
}
}
public string SqlPageFilter(bus_workOrder_head model)
{
//获取未报工的数据
if (model.stateDes == "false")
{
return $"WHERE workReportStatus<{(int)EnumWorkReportStatus.完工已报工}";
}
//获取已报工的数据
else if (model.stateDes == "true")
{
return $"WHERE workReportStatus >={(int)EnumWorkReportStatus.完工已报工}";
}
else
{
return string.Empty;
}
}
/// <summary>
/// //获取列表
/// </summary>
public Response LoadDesc(PageReq pageReq, bus_workOrder_detail model)
{
var data = Context.Queryable<bus_workOrder_detail, base_material>((x, y) =>
new JoinQueryInfos(JoinType.Left, x.weldMaterCode == y.materialCode||x.cutMaterCode==y.materialCode));
if (model.headKeyList != null)
{
data = data.In(x => x.headKeys, model.headKeyList);
}
else
{
data = data.Where(x => x.headKeys == model.headKeys && x.isDelete != SystemVariable.DeleteFlag);
}
var result = new Response
{
Result = data.OrderBy(x => x.serialNumber)
.Select((x, y) => new
{
x.id,
x.bodyKeys,
x.headKeys,
x.serialNumber,
x.serialNumberName,
x.workCenterCode,
x.stationCode,
x.oprSequenceCode,
x.oprSequenceName,
x.equipmentCode,
x.state,
x.workReportStatus,
materialCode = x.cutMaterCode != null ? x.cutMaterCode : x.weldMaterCode,
materialName = y.materialName,
x.cuttingLength,
x.weldNo,
x.weldType,
x.barCode,
x.partCode,
x.batchNo,
x.designNo,
x.designUrl,
x.planStartTime,
x.planEndTime,
x.actualStartTime,
x.actualEndTime,
x.isRework,
x.createBy,
x.createTime,
x.updateBy,
x.updateTime
})
.ToList(),
Count = data.Count()
};
return result;
}
public Response LoadInspection(PageReq pageReq, bus_workOrder_head model)
{
int total = 0;
var data = Context.Queryable<bus_workOrder_detail_rework>().Where(it => it.equipmentCode == model.workOrderCode).ToPageList(pageReq.page, pageReq.limit, ref total);
var result = new Response
{
Result = data,
Count = total
};
return result;
}
/// <summary>
/// 导出方法
/// </summary>
/// <returns></returns>
public dynamic Export(bus_workOrder_head Table_Entity)
{
return ExceptionsHelp.Instance.ExecuteT(() =>
{
Response result = new Response();
var dataTable = Load(null, Table_Entity);
if (dataTable.Count == 0)
{
result.Result = null;
result.Message = "没有查询到数据!";
result.Code = -1;
return result;
}
var guids = new List<Guid>();
foreach (DataRow item in dataTable.Result.Rows)
{
guids.Add(new Guid(item["keys"].ToString()));
}
var data = LoadDesc(null, new bus_workOrder_detail { headKeyList = guids });
result.Result = new
{
head = dataTable.Result,
body = data.Result
};
return result;
}, catchRetrunValue: "actionList");
}
public dynamic UpdDesc(bus_workOrder_detail model)
{
var response = new Response();
return ExceptionsHelp.Instance.ExecuteT(() =>
{
response.Status = base.Context.Updateable(model).Where(x => x.bodyKeys == model.bodyKeys).IgnoreColumns(it => new { it.createBy, it.createTime }).ExecuteCommand() > 0;
if (!response.Status) response.Message = SystemVariable.dataActionError;
return response;
});
}
public dynamic LoadMaterDetail(PageReq pageReq, bus_workOrder_detail_material entity)
{
var result = new Response<List<bus_workOrder_detail_material>>();
var data = Context.Queryable<bus_workOrder_detail_material>().Where(GetMaterFilter(entity)).ToList();
result.Result = data;
result.Count = data.Count;
return result;
}
public Expression<Func<bus_workOrder_detail_material, bool>> GetMaterFilter(bus_workOrder_detail_material entity)
{
var filter = Expressionable.Create<bus_workOrder_detail_material>();
filter = filter.And(x => x.headKey == entity.headKey && x.bodyKey == entity.bodyKey);
return filter.ToExpression();
}
public dynamic LoadReceipt(PageReq pageReq, Guid headKey, string materialCode, string materialName)
{
var result = new Response();
int total = 0;
var where = GetReceiptExpression(headKey, materialCode, materialName);
var data = Context.Queryable<base_inventory>().Where(where).Select(inve => new
{
inve.id,
inve.materialCode,
inve.materialName,
inve.oprSequenceCode,
inve.workOrderCode,
inve.qty,
inve.consumedQuantity,
inve.quantityReceived,
inve.quantityRequired,
//inve.createTime,
//inve.createBy,
//inve.updateBy,
//inve.updateTime,
inve.whCode
}).OrderBy(inve => inve.id).ToPageList(pageReq.page, pageReq.limit, ref total);
result.Result = data;
result.Count = total;
if (!data.Any())
{
result.Message = "无数据";
}
return result;
}
public dynamic UpdReceipt(List<base_inventory> entity)
{
var result = new Response();
//需求数量 >= 收货数量 >= 消耗数量
var inveItems = entity.Where(item => item.quantityRequired < item.quantityReceived || item.quantityReceived < item.consumedQuantity).Select(x => x.id).ToList();
if (inveItems.Any())
{
result.Status = false;
result.Message = $"Id为[{string.Join(",", inveItems)}]的收货数量不符合条件:需求数量 >= 收货数量 >= 消耗数量";
return result;
}
var row = Context.Updateable(entity).UpdateColumns(x => new { x.quantityReceived, x.qty, x.updateTime }).ExecuteCommand();
if (row == 0)
{
result.Status = false;
}
result.Message = $"已更新“{row}”条数据!";
return result;
}
public static Expression<Func<base_inventory, bool>> GetReceiptExpression(Guid headKey, string materialCode, string materialName)
{
var exp = Expressionable.Create<base_inventory>();
exp.And(inve => inve.headKey == headKey);
exp.AndIF(!string.IsNullOrWhiteSpace(materialCode), (inve) => inve.materialCode == materialCode);
exp.AndIF(!string.IsNullOrWhiteSpace(materialName), (inve) => inve.materialName == materialName);
return exp.ToExpression();
}
/// <summary>
/// 记录报工数据
/// </summary>
/// <returns></returns>
private Response AddWorkReportLog(bus_workOrder_detail workOrderDetail, bus_work_report_check_head workReportHead, List<bus_work_report_check_mater_body> workReportMaterBody, List<bus_work_report_check_eq_body> workReportEqBody)
{
var result = new Response();
Context.Insertable(workReportHead).AddQueue();
Context.Insertable(workReportMaterBody).AddQueue();
Context.Insertable(workReportEqBody).AddQueue();
Context.Updateable(workOrderDetail).UpdateColumns(x => new { x.workReportStatus, x.updateTime, x.updateBy }).AddQueue();
var row = ExecuteQueues(Context);
return row > 1 ? result.ResponseSuccess() : result.ResponseError();
}
/// <summary>
/// 报工后更新库存信息和工序物料消耗状态
/// </summary>
/// <param name="headKey">工序任务headKey</param>
/// <param name="materialUseLog">物料使用记录</param>
/// <remarks>
/// 消耗数 = 消耗数 + 工序任务物料消耗的数量
/// 库存数 = 库存数 - 工序任务物料消耗的数量
/// </remarks>
/// <returns></returns>
private Response UpdataInventory(Guid headKey, List<bus_workOrder_material_use_log> materialUseLog)
{
var response = new Response();
var materialCodes = new List<string>();
foreach (var item in materialUseLog)
{
var inventory = Context.Queryable<base_inventory>().First(x => x.headKey == headKey && x.materialCode == item.materialCode && x.qty >= item.qyt && item.qyt >= 0);
if (inventory != null)
{
inventory.consumedQuantity += (int)item.qyt;
inventory.qty -= (int)item.qyt;
item.employ = (int)EnumUseLog.使用;
Context.Updateable(item).ExecuteCommand();
Context.Updateable(inventory).UpdateColumns(x => new { x.consumedQuantity, x.qty }).ExecuteCommand();
}
else
{
materialCodes.Add(item.materialCode);
}
}
if (materialCodes.Any()) return response.ResponseError($"工序任务Key“{headKey}”的物料编码“{string.Join(",", materialCodes)}”库存不足或不存在");
return response;
}
/// <summary>
/// 获取当前工序任务明细设备工艺参数
/// </summary>
public Response GetEquipmentInfo(bus_workOrder_detail entity)
{
var response = new Response();
List<bus_equipment_process_template> equipmentList = null;
//通过工序明细bodykeys查询关联表中的设备工艺参数表中的数据
//var equipmentKeys = Context.Queryable<bus_workReport_materialUselog_eqProcessTem_rel>().In(x => x.bodyKeys, entity.bodyKeys).Select(x => x.eqProKeys).ToList();
var bus_workReport_materialUselog_eqProcessTem_relList = Context.Queryable<bus_workReport_materialUselog_eqProcessTem_rel>().In(x => x.bodyKeys, entity.bodyKeys).ToList();
var equipmentKeys = bus_workReport_materialUselog_eqProcessTem_relList.Where(a => a.eqProKeys != Guid.Empty).Select(x => x.eqProKeys).ToList();
if (equipmentKeys.Count == 0)
{
//工位找到设备设备编码,如果找不到就使用工作中心
var eq = Context.Queryable<base_equipment>()
.First(x => x.workStationCode == entity.stationCode);
if (eq == null)
{
var station = Context.Queryable<base_work_station>()
.First(x => x.workStationCode == entity.stationCode);
return response.ResponseError($"设备信息没有匹配工位编码【{entity?.stationCode},{station?.workStationName}】请在设备管理=>设备绑定");
}
equipmentList = Context.Queryable<bus_equipment_process_template>().Where(x => x.device_information == eq.code).ToList();
if (equipmentList.Count == 0)
{
equipmentList = Context.Queryable<bus_equipment_process_template>().Where(x => x.device_information == entity.workCenterCode).ToList();
}
response.Result = equipmentList;
}
else
{
equipmentList = Context.Queryable<bus_equipment_process_template>().In(x => x.keys, equipmentKeys).ToList();
}
if (equipmentList.Count == 0)
{
return response.ResponseError($"【工位编码{entity.stationCode}】无设备工艺参数数据,请在“设备工艺参数”菜单录入设备工艺参数,或在工作中心【{entity.workCenterCode}】配置设备工艺参数!");
}
response.Result = equipmentList;
return response;
}
/// <summary>
/// 获取当前工序任务明细物料消耗
/// </summary>
/// <returns></returns>
public Response GetMaterialInfo(bus_workOrder_detail entity)
{
var response = new Response();
//通过工序明细bodykeys查询关联表中的物料消耗表中的数据,没有默认读取物料消耗表数据
var materialKeys = Context.Queryable<bus_workReport_materialUselog_eqProcessTem_rel>().In(x => x.bodyKeys, entity.bodyKeys).Where(x => x.materialUseLogKeys != Guid.Empty && x.bodyKeys == entity.bodyKeys).Select(x => x.materialUseLogKeys).ToList();
var materUseList = new List<bus_workOrder_material_use_log>();
if (materialKeys.Count == 0)
{
var useLogFlag = (int)EnumUseLog.未使用;
var result = Context.Queryable<bus_workOrder_material_use_log>()
.Where(x => x.workOrderCode == entity.workOrderCode
&& x.employ == useLogFlag && x.lineCode == entity.lineCode
&& x.isDelete == (int)EnumDeleteOrAdd.新增或更新)
.ToList();
//过滤物料编码重复的数据
foreach (var item in result)
{
if (!materUseList.Any(x => x.materialCode == item.materialCode))
{
materUseList.Add(item);
}
}
}
else
{
materUseList = Context.Queryable<bus_workOrder_material_use_log>().In(x => x.keys, materialKeys).ToList();
}
response.Result = materUseList;
return response;
}
/// <summary>
/// 工序开工,并录入物料数据、设备数据
/// </summary>
/// <param name="headKeys"></param>
/// <param name="bodyKeys"></param>
/// <param name="id"></param>
/// <param name="actualStartTime"></param>
/// <param name="Material"></param>
/// <param name="Equipment"></param>
/// <returns></returns>
public Response UpdateProcess(Guid headKeys, Guid bodyKeys, int id,
DateTime actualStartTime, List<bus_workOrder_material_use_log> Material, List<bus_equipment_process_template> Equipment,
string stationCode)
{
var response = new Response();
//通过headKeys查询工单编码、产品编码、产线编码、工序编码、工序名称、工序编码,通过bodyKeys查询工位编码、设备编码
var WorkOrder_detail = Context.Queryable<bus_workOrder_detail>().Where(t => t.bodyKeys == bodyKeys).First();
if (WorkOrder_detail.state >= (int)EnumOrderBodyStatus.已完成)
{
return response.ResponseError("开工失败,当前工序已执行过完工操作!");
}
var WorkOrder_Head = Context.Queryable<bus_workOrder_head>().Where(t => t.keys == headKeys).First();
if (!Material.Any() && !Equipment.Any()) return response.ResponseError("物料消耗数据和设备工艺参数数据都未录入,请重新录入!");
//判断报工状态,未报工才能修改
var detail = Context.Queryable<bus_workOrder_detail>().Where(t => t.id == id && t.workReportStatus < (int)EnumWorkReportStatus.开工已报工).Any();
if (!detail) return response.ResponseError("报工为初始化才能进行数据录入与开工!");
WorkOrder_detail.equipmentCode = Context.Queryable<base_equipment>().Where(x => x.workStationCode == stationCode).First()?.code;
//查询关系表任务明细keys的所有id,根据ID进行关系表批量删除
//工序任务物料设备关系表先删除在新增
Context.Deleteable<bus_workReport_materialUselog_eqProcessTem_rel>().Where(x => x.bodyKeys == bodyKeys).AddQueue();
string user = sysWebUser?.Account;
if (Material.Any())
{
#region 批量新增物料到关系表、更新物料消耗表的信息
var workReportMaterialList = new List<bus_workReport_materialUselog_eqProcessTem_rel>();
var WorkOrderMaterialList = new List<bus_workOrder_material_use_log>();
foreach (var MaterialItem in Material)
{
var workOrder_material_equipment = new bus_workReport_materialUselog_eqProcessTem_rel
{
bodyKeys = bodyKeys,
materialUseLogKeys = MaterialItem.keys,
createTime = DateTime.Now.ToLocalTime(),
createBy = user,
};
var workOrder_material = new bus_workOrder_material_use_log
{
id = MaterialItem.id,
stationCode = stationCode,
oprSequenceCode = WorkOrder_detail.oprSequenceCode,
oprSequenceName = WorkOrder_detail.oprSequenceName,
equipmentCode = WorkOrder_detail.equipmentCode,
workOrderCode = WorkOrder_Head.workOrderCode,
createTime = DateTime.Now.ToLocalTime(),
createBy = user,
};
workReportMaterialList.Add(workOrder_material_equipment);
WorkOrderMaterialList.Add(workOrder_material);
}
Context.Insertable(workReportMaterialList).AddQueue();
Context.Updateable(WorkOrderMaterialList).UpdateColumns(it => new
{
it.stationCode,
it.oprSequenceCode,
it.oprSequenceName,
it.equipmentCode,
it.workOrderCode,
it.createTime,
it.createBy,
}).AddQueue();
#endregion
}
if (Equipment.Any())
{
#region 批量新增设备到关系表
var workReportEquipmentList = new List<bus_workReport_materialUselog_eqProcessTem_rel>();
foreach (var EquipmentlItem in Equipment)
{
var workOrder_material_equipment = new bus_workReport_materialUselog_eqProcessTem_rel
{
bodyKeys = bodyKeys,
eqProKeys = EquipmentlItem.keys,
createTime = DateTime.Now.ToLocalTime(),
createBy = user,
};
workReportEquipmentList.Add(workOrder_material_equipment);
}
Context.Insertable(workReportEquipmentList).AddQueue();
#endregion
}
var nextWorkOrder = Context.Queryable<bus_workOrder_detail>()
.Where(x => x.headKeys == WorkOrder_Head.keys && x.serialNumber > WorkOrder_detail.serialNumber)
.OrderBy(x => x.serialNumber).First();
//更新工序头表的当前工序、工序编码、当前工位、更新时间(每次开工都更新)
WorkOrder_Head.nowOprSequenceCode = WorkOrder_detail.oprSequenceCode;
WorkOrder_Head.oprSequenceCode = WorkOrder_detail.oprSequenceCode;
WorkOrder_Head.oprSequence = WorkOrder_detail.serialNumber;
WorkOrder_Head.nextOprSequenceCode = nextWorkOrder?.oprSequenceCode;
WorkOrder_Head.nowStationCode = WorkOrder_detail.stationCode;
WorkOrder_Head.nextStationCode = nextWorkOrder?.stationCode;
WorkOrder_Head.updateTime = DateTime.Now;
Context.Updateable(WorkOrder_Head).UpdateColumns(x => new
{
x.nowOprSequenceCode,
x.oprSequenceCode,
x.oprSequence,
x.nextOprSequenceCode,
x.nowStationCode,
x.nextStationCode,
x.updateTime
}).AddQueue();
#region 修改工序任务明细
//仅第一道工序开工更新头表
Context.Updateable<bus_workOrder_head>()
.SetColumns(t => t.actualStartTime == DateTime.Now)
.SetColumns(t => t.state == (int)EnumOrderHeadStatus.生产中)
.Where(t => t.keys == headKeys && t.state < (int)EnumOrderHeadStatus.生产中).AddQueue();
Context.Updateable<bus_workOrder_detail>()
.SetColumns(it => new bus_workOrder_detail()
{
equipmentCode = WorkOrder_detail.equipmentCode,
stationCode = stationCode,
actualStartTime = actualStartTime,
updateTime = DateTime.Now.ToLocalTime(),
state = (int)EnumOrderBodyStatus.生产中,
updateBy = user
}).Where(it => it.id == id).AddQueue();
#endregion
#region 记录到工序明细操作记录中
//查询工艺路线编码
var processCode = Context.Queryable<base_process_route_head>().Where(t => t.keys == WorkOrder_Head.processHeadKeys).Select(t => t.processCode).First().ToString();
bus_workOrder_detail_rework workOrder_detail_operationList = new bus_workOrder_detail_rework
{
keys = Guid.NewGuid(),
workOrderBodyKeys = bodyKeys,
workOrderHeadKeys = headKeys,
processHeadKeys = WorkOrder_Head.processHeadKeys,
processCode = processCode,
lineCode = WorkOrder_Head.lineCode,
productHeaderCode = WorkOrder_Head.productHeaderCode,
stationCode = stationCode,
equipmentCode = WorkOrder_detail.equipmentCode,
oprSequenceCode = WorkOrder_detail.oprSequenceCode,
oprSequenceName = WorkOrder_detail.oprSequenceName,
actualStartTime = actualStartTime,
workOrderCode = WorkOrder_Head.workOrderCode,
createTime = DateTime.Now.ToLocalTime(),
createBy = user,
workOrderType = (int)EnumOrderBodyType.开工,
};
Context.Insertable(workOrder_detail_operationList).IgnoreColumns(t => new { t.actualEndTime }).AddQueue();
#endregion
int resultCount = ExecuteQueues(Context);
if (resultCount <= 0)
{
return response.ResponseError(SystemVariable.dataActionError);
}
else
{
response.Message = "数据录入、开工已完成,报工请在工序任务头中点击【报工MOM】按钮";
}
return response;
}
/// <summary>
/// 工序完成
/// </summary>
public Response WorkComplete(Guid headKeys, int id, DateTime actualEndTime)
{
var response = new Response();
//查询上一个工序有没有完成,没有则返回,有则正常执行
var state = (int)EnumOrderBodyStatus.已完成;
var detail = Context.Queryable<bus_workOrder_detail>()
.Where(t => t.headKeys == headKeys && t.state < state)
.OrderBy(t => t.serialNumber)
.First();
if (detail == null)
{
return response.ResponseError("工序已经全部完成!不需要再次完成!");
}
else if (detail.id != id)
{
return response.ResponseError($"必须先完成【{detail.oprSequenceName}】工序,才能完成当前工序!");
}
else if (detail.state == (int)EnumOrderBodyStatus.初始化)
{
return response.ResponseError($"工序未开工,请先执行开工操作!");
}
//查询第一道工序和最后一道工序
var serialNumber = Context.Queryable<bus_workOrder_detail>()
.Where(t => t.headKeys == headKeys)
.Select(t => new
{
maxSerialNumber = SqlFunc.AggregateMax(t.serialNumber),
minSerialNumber = SqlFunc.AggregateMin(t.serialNumber),
}).First();
//如果是第一道工序就更新工序任务头的实际开始时间,如果是最后一道工序就更新工序任务头的实际结束时间
if (detail.serialNumber == serialNumber.maxSerialNumber)
{
//如果 序号是最大的,就是最后一道工序
if (detail.serialNumber == serialNumber.maxSerialNumber)
{
Context.Updateable<bus_workOrder_head>()
.SetColumns(t => t.actualEndTime == actualEndTime)
.SetColumns(t => t.state == (int)EnumOrderHeadStatus.已完成)
.Where(t => t.keys == headKeys).AddQueue();
}
}
//更新工序任务明细
string user = base.sysWebUser?.Account;
Context.Updateable<bus_workOrder_detail>()
.SetColumns(it => new bus_workOrder_detail()
{
actualEndTime = actualEndTime,
state = state,
updateTime = DateTime.Now.ToLocalTime(),
updateBy = user
})
.Where(it => it.id == id).AddQueue();
#region 记录到工序明细操作记录中
var workOrder_detail_operationList = Context.Queryable<bus_workOrder_detail_rework>().OrderBy(it => it.id, OrderByType.Desc).First(it => it.workOrderBodyKeys == detail.bodyKeys);
workOrder_detail_operationList.keys = Guid.NewGuid();
workOrder_detail_operationList.actualEndTime = actualEndTime;
workOrder_detail_operationList.workOrderType = (int)EnumOrderBodyType.完工;
Context.Insertable(workOrder_detail_operationList).AddQueue();
#endregion
//更新到数据库
var result = ExecuteQueues(Context);
if (result <= 0)
{
return response.ResponseError(SystemVariable.dataActionError);
}
else
{
response.Message = "工序已完成,报工请在工序任务头中点击【报工MOM】按钮";
}
return response;
}
/// <summary>
/// 获取工单进度与人员工时录入
/// </summary>
/// <param name="pageRequest"></param>
/// <param name="entity"></param>
/// <returns></returns>
public dynamic LoadWorkOrderProgress(PageReq pageRequest, bus_workOrder_head entity)
{
return ExceptionsHelp.Instance.ExecuteT(() =>
{
var response = new Response();
var total = 0;
var result = Context.Queryable<bus_workOrder_head, bus_workOrder_detail, base_product_header>((head, detail, product) =>
new JoinQueryInfos(JoinType.Inner, head.keys == detail.headKeys, JoinType.Left, head.productHeaderCode == product.productCode))
.Where(GetWorkOrderProgressLambda(entity))
.GroupBy((head, detail, product) => new
{
head.id,
head.keys,
head.productHeaderCode,
product.productName,
head.workOrderCode,
head.lineCode,
head.planCode,
head.actualStartTime,
head.actualEndTime,
head.createTime,
})
.Select((head, detail, product) => new
{
head.id,
head.keys,
head.productHeaderCode,
product.productName,
head.workOrderCode,
head.lineCode,
head.planCode,
//工序
workOrderEnd = SqlFunc.Subqueryable<bus_workOrder_detail>().Where(x => x.headKeys == head.keys && x.state >= (int)EnumOrderBodyStatus.已完成).Count(),
//报工
sendWorkOrderEnd = SqlFunc.Subqueryable<bus_workOrder_detail>().Where(x => x.headKeys == head.keys && x.workReportStatus >= (int)EnumWorkReportStatus.完工已报工).Count(),
workOrderTotal = SqlFunc.AggregateCount(detail.bodyKeys),
head.actualStartTime,
head.actualEndTime,
//设备
equipments = SqlFunc.Subqueryable<bus_workOrder_detail>().Where(x => x.headKeys == head.keys).Select(x => x.equipmentCode),
//人员
users = SqlFunc.Subqueryable<bus_workOrder_detail>().Where(x => x.headKeys == head.keys).Select(x => x.updateBy),
head.createTime
}).OrderBy(head => head.createTime, OrderByType.Desc).ToPageList(pageRequest.page, pageRequest.limit, ref total);
response.Result = result.Select(item => new
{
item.id,
item.keys,
item.productHeaderCode,
item.productName,
item.workOrderCode,
item.lineCode,
Context.Queryable<base_line>().Where(x => x.lineCode == item.lineCode).First()?.lineName,
item.planCode,
workOrderProgress = item.workOrderEnd * 100 / item.workOrderTotal,
sendWorkOrderProgress = item.sendWorkOrderEnd * 100 / item.workOrderTotal,
item.actualStartTime,
item.actualEndTime,
item.equipments,
item.users,
item.createTime,
}).ToList();
response.Count = total;
return response;
});
}
public Expression<Func<bus_workOrder_head, bool>> GetWorkOrderProgressLambda(bus_workOrder_head entity)
{
var filter = Expressionable.Create<bus_workOrder_head>();
filter.AndIF(entity.keys != Guid.Empty, head => head.keys == entity.keys);
filter.AndIF(!string.IsNullOrWhiteSpace(entity.productHeaderCode), head => head.productHeaderCode == entity.productHeaderCode);
filter.AndIF(!string.IsNullOrWhiteSpace(entity.workOrderCode), head => head.workOrderCode == entity.workOrderCode);
filter.AndIF(!string.IsNullOrWhiteSpace(entity.planCode), head => head.planCode == entity.planCode);
filter.AndIF(!string.IsNullOrWhiteSpace(entity.actualStartTime.ToString()), head => head.actualStartTime >= entity.actualStartTime);
filter.AndIF(!string.IsNullOrWhiteSpace(entity.actualEndTime.ToString()), head => head.actualEndTime <= entity.actualEndTime);
return filter.ToExpression();
}
/// <summary>
/// 获取工单进度
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public dynamic LoadWorkOrderProgressInfo(bus_workOrder_head entity)
{
var response = new Response();
var result = Context.Queryable<bus_workOrder_detail>().Where(x => x.headKeys == entity.keys).OrderBy(x => x.serialNumber)
.Select(x => new
{
x.id,
x.lineCode,
x.oprSequenceCode,
x.oprSequenceName,
x.serialNumber,
x.stationCode,
x.equipmentCode,
equipmentName = SqlFunc.Subqueryable<base_equipment>().Where(t => t.code == x.equipmentCode).Select(t => t.name),
x.updateBy,
userName = SqlFunc.Subqueryable<sys_user>().Where(d => d.account == x.updateBy).Select(d => d.name),
x.planStartTime,
x.planEndTime,
x.actualStartTime,
x.actualEndTime,
x.state,
x.workReportStatus
}).ToList();
response.Result = result;
response.Count = result.Count();
return response;
}
/// <summary>
/// 根据条码获取工序信息、物料消耗、设备工艺参数
/// </summary>
/// <param name="barCode">条码信息</param>
/// <returns></returns>
public dynamic GetWorkOrderInfoByPlanCode(string barCode)
{
var response = new Response();
if (string.IsNullOrEmpty(barCode))
{
return response.ResponseError("条码信息不能为空!");
}
var barCodeInfo = barCode.Split('#');
if (barCodeInfo.Length != 4 || barCodeInfo[3] != "001")
{
return response.ResponseError("获取数据失败,条码格式不正确!");
}
//生产计划号
string planCode = barCodeInfo[2];
var workOrderInfo = Context.Queryable<bus_workOrder_head, bus_workOrder_detail>((head, body) => new JoinQueryInfos(
JoinType.Inner, head.keys == body.headKeys)).Where((head, body) => head.planCode == planCode).OrderBy((head, body) => body.serialNumber)
.Select((head, body) => new
{
body.id,
head.keys,
body.bodyKeys,
head.planCode,
head.productHeaderCode,
productHeaderName = SqlFunc.Subqueryable<base_product_header>().Where(x => x.productCode == head.productHeaderCode).Select(x => x.productName),
body.lineCode,
body.workCenterCode,
lineName = SqlFunc.Subqueryable<base_line>().Where(x => x.lineCode == head.lineCode).Select(x => x.lineName),
head.workOrderCode,
body.state,
body.workReportStatus,
body.serialNumber,
head.planStartTime,
head.planEndTime,
body.actualStartTime,
body.actualEndTime,
body.createTime,
}).ToList();
if (!workOrderInfo.Any())
{
return response.ResponseError($"未查询到条码为:“{barCode}”的相关工序信息!");
}
var workOrderDetail = Context.Queryable<bus_workOrder_detail>().Where(x => x.headKeys == workOrderInfo.First().keys && x.workReportStatus < (int)EnumWorkReportStatus.完工已报工).OrderBy(x => x.serialNumber).First();
if (workOrderDetail is null)
{
return response.ResponseError($"生产计划号“{planCode}”没有可报工的工序!");
}
var materInfoResult = GetMaterialInfo(workOrderDetail);
var equipmentInfoResult = GetEquipmentInfo(workOrderDetail);
if (equipmentInfoResult.Result is null)
{
Response stationInfoResult = _stationService.LoadStationCodeByworkCenterCode(workOrderDetail.workCenterCode, workOrderDetail.lineCode);
if (stationInfoResult.Result != null)
{
JObject stationResultJson = JObject.Parse(JsonConvert.SerializeObject(stationInfoResult));
var stationJson = (JArray)stationResultJson["Result"];
if (stationJson.Any())
{
workOrderDetail.stationCode = stationJson[0][nameof(base_work_station.workStationCode)].ToString();
equipmentInfoResult = GetEquipmentInfo(workOrderDetail);
}
}
}
response.Result = new
{
workOrderDetail.id,
workOrderDetail.headKeys,
workOrderDetail.bodyKeys,
workOrderInfo,
materInfo = materInfoResult?.Result ?? "[]",
equipmentInfo = equipmentInfoResult?.Result ?? "[]",
status = materInfoResult.Status && equipmentInfoResult.Status
};
return response;
}
public dynamic DelByKeys(Guid[] keysList)
{
return ExceptionsHelp.Instance.ExecuteT(() =>
{
var response = new Response();
var result = 0;
Context.Deleteable<bus_workOrder_head>(t => keysList.Contains(t.keys)).AddQueue();
Context.Deleteable<bus_workOrder_detail>(t => keysList.Contains(t.headKeys)).AddQueue();
result = ExecuteQueues(Context);
if (result <= 0)
{
return response.ResponseError(SystemVariable.dataActionError);
}
return response;
});
}
}
}