新火炬后端单体项目初始化代码
cuilei
4 天以前 eec479e2f3139286449005dcb05c014e4a60d255
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
package org.jeecg.modules.mes.service.impl;
 
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.modules.base.entity.Factory;
import org.jeecg.modules.base.entity.LineSideWarehouse;
import org.jeecg.modules.base.entity.Shift;
import org.jeecg.modules.base.entity.ShiftGroup;
import org.jeecg.modules.base.service.IFactoryService;
import org.jeecg.modules.base.service.ILineSideWarehouseService;
import org.jeecg.modules.base.service.IShiftGroupService;
import org.jeecg.modules.base.service.IShiftService;
import org.jeecg.modules.lsw.entity.LswMaterial;
import org.jeecg.modules.lsw.entity.LswMaterialInbound;
import org.jeecg.modules.lsw.enums.MaterialCategoryEnum;
import org.jeecg.modules.lsw.service.ILswMaterialInboundService;
import org.jeecg.modules.lsw.service.ILswMaterialService;
import org.jeecg.modules.mes.entity.MesMaterialLoading;
import org.jeecg.modules.mes.entity.MesProductionOrder;
import org.jeecg.modules.mes.entity.MesProductionWorkOrder;
import org.jeecg.modules.mes.entity.MesWorkReporting;
import org.jeecg.modules.mes.mapper.MesWorkReportingMapper;
import org.jeecg.modules.mes.service.IMesMaterialLoadingService;
import org.jeecg.modules.mes.service.IMesProductionOrderService;
import org.jeecg.modules.mes.service.IMesProductionWorkOrderService;
import org.jeecg.modules.mes.service.IMesWorkReportingService;
import org.jeecg.modules.mes.utils.CommonUtils;
import org.jeecg.modules.pms.entity.PmsMaterialProcess;
import org.jeecg.modules.pms.service.IPmsMaterialProcessService;
import org.jeecg.modules.pms.service.IPmsProcessBillMaterialsService;
import org.jeecg.modules.pms.vo.ProcessBillMaterialsDetailVo;
import org.jeecg.modules.sap.request.OrderLoadRequest;
import org.jeecg.modules.sap.request.OrderReportRequest;
import org.jeecg.modules.sap.service.OrderLoadService;
import org.jeecg.modules.sap.service.OrderReportService;
import org.jeecg.modules.system.service.ISysBusinessCodeRuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.util.*;
import java.util.stream.Collectors;
 
/**
 * @Description: 工单报工
 * @Author: jeecg-boot
 * @Date:   2025-07-04
 * @Version: V1.0
 */
@Slf4j
@Service
public class MesWorkReportingServiceImpl extends ServiceImpl<MesWorkReportingMapper, MesWorkReporting> implements IMesWorkReportingService {
 
    @Autowired
    private IMesProductionWorkOrderService mesProductionWorkOrderService;
    @Autowired
    private IMesProductionOrderService mesProductionOrderService;
    @Autowired
    private ILswMaterialService lswMaterialService;
    @Autowired
    private IFactoryService factoryService;
    @Autowired
    private IShiftService shiftService;
    @Autowired
    private IShiftGroupService shiftGroupService;
    @Autowired
    private ILineSideWarehouseService lineSideWarehouseService;
    @Autowired
    private ILswMaterialInboundService lswMaterialInboundService;
    @Autowired
    private IMesMaterialLoadingService mesMaterialLoadingService;
    @Autowired
    private IPmsProcessBillMaterialsService pmsProcessBillMaterialsService;
    @Autowired
    private IPmsMaterialProcessService pmsMaterialProcessService;
    @Autowired
    private ISysBusinessCodeRuleService sysBusinessCodeRuleService;
    @Autowired
    private OrderReportService orderReportService;
    @Autowired
    private OrderLoadService orderLoadService;
 
    @Override
    public List<MesWorkReporting> queryWorkReportingByWorkOrderId(String workOrderId) {
        return baseMapper.queryWorkReportingByWorkOrderId(workOrderId);
    }
 
    @Override
    public List<MesWorkReporting> queryWorkReportingByOrderId(String orderId) {
        return baseMapper.queryWorkReportingByOrderId(orderId);
    }
 
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addReporting(MesWorkReporting mesWorkReporting) {
        MesProductionWorkOrder workOrder = mesProductionWorkOrderService.getById(mesWorkReporting.getWorkOrderId());
        if (workOrder == null) {
            throw new JeecgBootException("工单不存在!");
        }
        LswMaterial material = lswMaterialService.list(new LambdaQueryWrapper<LswMaterial>()
                        .eq(LswMaterial::getMaterialNumber, workOrder.getMaterialNumber())
                        .eq(LswMaterial::getDelFlag, CommonConstant.DEL_FLAG_0)).stream()
                .findAny().orElse(null);
        if (material == null) {
            throw new JeecgBootException("物料不存在!");
        }
        MaterialCategoryEnum materialCategory = MaterialCategoryEnum.fromName(material.getMaterialCategory());
        if (materialCategory == null) {
            throw new JeecgBootException("未知的物料类型!");
        }
 
        LineSideWarehouse lineSideWarehouse = lineSideWarehouseService.list(new LambdaQueryWrapper<LineSideWarehouse>()
                        .eq(LineSideWarehouse::getFactoryId, mesWorkReporting.getFactoryId())
                        .eq(LineSideWarehouse::getDelFlag, CommonConstant.DEL_FLAG_0))
                .stream().findAny().orElse(null);
        if (lineSideWarehouse == null) {
            throw new JeecgBootException("线边仓库不存在!");
        }
 
        //生产批次号
        LocalDate today = LocalDate.now();
        String yearLastTwo = today.format(DateTimeFormatter.ofPattern("yy"));
        String dayOfYearStr = today.format(DateTimeFormatter.ofPattern("DDD"));
        ShiftGroup shiftGroup = shiftGroupService.getById(workOrder.getGroupId());
        int currentPallets = workOrder.getFinishedPallets() + 1;
        String batchNumber = yearLastTwo + dayOfYearStr + shiftGroup.getGroupCode() + currentPallets;
        mesWorkReporting.setBatchNumber(batchNumber)
                .setWarehouseId(lineSideWarehouse.getId())
                .setReporter(Objects.requireNonNull(CommonUtils.getCurrentUser()).getUsername())
                .setReportTime(new Date());
        String date = today.format(DateTimeFormatter.ofPattern("yyMMdd"));
        Factory factory = factoryService.getById(mesWorkReporting.getFactoryId());
        workOrder.setFactoryCode(factory.getFactoryCode());
        switch (materialCategory) {
            case FINISHED_PRODUCT:
                //成品报工
                productReport(mesWorkReporting, workOrder, lineSideWarehouse);
                //拼接成品报工托号
                String palletNumber4 = sysBusinessCodeRuleService.generateBusinessCodeSeq("WorkReportingPalletNumber4");
                String finishedPalletNumber = material.getMaterialNumber() + date + palletNumber4;
                mesWorkReporting.setPalletNumber(finishedPalletNumber);
                //todo 打印成品托标签、检验标识卡、移库单、完工检验工单
                break;
            case INNER_FLANGE:
            case OUTER_FLANGE:
                //半成品(内法兰、外法兰)报工
                productReport(mesWorkReporting, workOrder, lineSideWarehouse);
                //拼接半成品报工托号
                Shift shift = shiftService.getById(workOrder.getShiftId());
                String palletNumber6 = sysBusinessCodeRuleService.generateBusinessCodeSeq("WorkReportingPalletNumber6");
                String halfPalletNumber = factory.getFactoryCode() + material.getMaterialNumber() + date + shift.getShiftCode() + palletNumber6;
                mesWorkReporting.setPalletNumber(halfPalletNumber);
                break;
        }
        //新增报工记录
        save(mesWorkReporting);
        //更新排产工单
        MesProductionWorkOrder productionWorkUpdateOrder = new MesProductionWorkOrder()
                .setId(workOrder.getId())
                .setActualQuantity(workOrder.getActualQuantity().add(mesWorkReporting.getQuantity()))
                .setFinishedPallets(workOrder.getFinishedPallets() + 1);
        mesProductionWorkOrderService.updateById(productionWorkUpdateOrder);
    }
 
    //半成品(内法兰、外法兰)、成品报工
    private void productReport(MesWorkReporting mesWorkReporting, MesProductionWorkOrder workOrder, LineSideWarehouse lineSideWarehouse) {
        //1、入库 半成品/成品 到对应线边库
        LswMaterialInbound materialInbound = new LswMaterialInbound()
                .setFactoryId(workOrder.getFactoryId())
                .setWarehouseId(lineSideWarehouse.getId())
                .setMaterialNumber(workOrder.getMaterialNumber())
                .setMaterialName(workOrder.getMaterialName())
                .setBatchNumber(mesWorkReporting.getBatchNumber())
                .setQuantity(mesWorkReporting.getQuantity());
        lswMaterialInboundService.save(materialInbound);
        //2、扣减使用毛坯库存(更新上料记录)或半成品物料库存(内法兰、外法兰、小内圈、配件等),按照 排产工单id、物料编码 查询上料记录,按照时间从早到晚排序,优先扣减早的上料记录(先进先出)
        //先查询物料 BOM
        Map<String, ProcessBillMaterialsDetailVo> processBillMaterialsDetailMap = pmsProcessBillMaterialsService
                .queryMaterialsDetailByOrderIdAndMaterialNumber(mesWorkReporting.getOrderId(), workOrder.getMaterialNumber()).stream()
                .collect(Collectors.toMap(ProcessBillMaterialsDetailVo::getMaterialNumber, v1 -> v1, (v1, v2) -> v1));
        //查询上料记录
        Map<String, List<MesMaterialLoading>> materialLoadingRecordMap = mesMaterialLoadingService.list(new LambdaQueryWrapper<MesMaterialLoading>()
                        .eq(MesMaterialLoading::getWorkOrderId, workOrder.getId())
                        .in(MesMaterialLoading::getMaterialNumber, processBillMaterialsDetailMap.keySet())
                        .gt(MesMaterialLoading::getRemainingQuantity, BigDecimal.ZERO)).stream()
                .sorted(Comparator.comparing(MesMaterialLoading::getCreateTime))
                .collect(Collectors.groupingBy(MesMaterialLoading::getMaterialNumber));
        List<MesMaterialLoading> materialLoadingRecordUpdateList = CollectionUtil.newArrayList();
        for (String materialNumber : processBillMaterialsDetailMap.keySet()) {
            List<MesMaterialLoading> materialLoadingRecordList = materialLoadingRecordMap.get(materialNumber);
            if (materialLoadingRecordList.isEmpty()) {
                throw new JeecgBootException("未查询到相应物料的上料记录!");
            }
            //计算物料扣减数量
            ProcessBillMaterialsDetailVo processBillMaterialsDetailVo = processBillMaterialsDetailMap.get(materialNumber);
            BigDecimal quantity = processBillMaterialsDetailVo.getPerQuantity().multiply(mesWorkReporting.getQuantity());
            List<MesMaterialLoading> updateList = deductQuantity(materialLoadingRecordList, quantity);
            materialLoadingRecordUpdateList.addAll(updateList);
        }
        //更新上料记录
        mesMaterialLoadingService.updateBatchById(materialLoadingRecordUpdateList);
        MesProductionOrder productionOrder = mesProductionOrderService.getById(mesWorkReporting.getOrderId());
        //3、调用SAP投料接口(消耗的物料) OrderLoadService
        for (String materialNumber : processBillMaterialsDetailMap.keySet()) {
            ProcessBillMaterialsDetailVo processBillMaterialsDetailVo = processBillMaterialsDetailMap.get(materialNumber);
            OrderLoadRequest loadRequest = new OrderLoadRequest()
                    .setOrderCode(productionOrder.getOrderCode())
                    .setFactoryCode(workOrder.getFactoryCode())
                    .setMaterialNumber(materialNumber)
                    .setWarehouseCode(lineSideWarehouse.getWarehouseCode())
                    .setQuantity(processBillMaterialsDetailVo.getPerQuantity().multiply(mesWorkReporting.getQuantity()))
                    .setBatchNumber(mesWorkReporting.getBatchNumber())
                    .setProductionUnit(processBillMaterialsDetailVo.getProductionUnit());
            try {
                orderLoadService.productionOrderLoad(loadRequest);
            } catch (Exception e) {
                log.error("SAP生产订单投料异常!", e);
            }
        }
        //4、调用SAP工序报工(根据生产订单id查询对应的物料工序(半成品是多个工序,成品只有一个工序),按照工序号从小到大依次挨个报工;目前考虑异步执行) OrderReportService
        List<PmsMaterialProcess> processList = pmsMaterialProcessService.list(new LambdaQueryWrapper<PmsMaterialProcess>()
                .eq(PmsMaterialProcess::getOrderId, mesWorkReporting.getOrderId())
                .orderByAsc(PmsMaterialProcess::getProcessCode));
        for (PmsMaterialProcess process : processList) {
            OrderReportRequest reportRequest = new OrderReportRequest()
                    .setOrderCode(productionOrder.getOrderCode())
                    .setFactoryCode(workOrder.getFactoryCode())
                    .setProcessCode(process.getProcessCode())
                    .setQualifiedQuantity(mesWorkReporting.getQuantity())
                    .setWarehouseCode(lineSideWarehouse.getWarehouseCode())
                    .setBatchNumber(mesWorkReporting.getBatchNumber());
            try {
                orderReportService.productionOrderReport(reportRequest);
            } catch (Exception e) {
                log.error("SAP工序报工异常!", e);
            }
        }
    }
 
    private List<MesMaterialLoading> deductQuantity(List<MesMaterialLoading> materialLoadingRecordList, BigDecimal quantity) {
        for (MesMaterialLoading mesMaterialLoading : materialLoadingRecordList) {
            if (mesMaterialLoading.getRemainingQuantity().compareTo(quantity) >= 0) {
                mesMaterialLoading.setRemainingQuantity(mesMaterialLoading.getRemainingQuantity().subtract(quantity));
                break;
            } else {
                quantity = quantity.subtract(mesMaterialLoading.getRemainingQuantity());
                mesMaterialLoading.setRemainingQuantity(BigDecimal.ZERO);
            }
        }
        return materialLoadingRecordList;
    }
}