新火炬后端单体项目初始化代码
zhangherong
2 天以前 182c04e399f5db26406234767f7ef34b5adc0015
src/main/java/org/jeecg/modules/mes/service/impl/MesWorkReportingServiceImpl.java
@@ -1,35 +1,59 @@
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.MaterialCategory;
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.qms.entity.InspectionPlan;
import org.jeecg.modules.qms.entity.InspectionPlanItem;
import org.jeecg.modules.qms.enums.PlanCategoryEnum;
import org.jeecg.modules.qms.service.IInspectionPlanItemService;
import org.jeecg.modules.qms.service.IInspectionPlanService;
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.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
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: 工单报工
@@ -37,11 +61,14 @@
 * @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
@@ -49,11 +76,27 @@
    @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;
    @Autowired
    private IInspectionPlanService inspectionPlanService;
    @Autowired
    private IInspectionPlanItemService inspectionPlanItemService;
    @Override
    public List<MesWorkReporting> queryWorkReportingByWorkOrderId(String workOrderId) {
@@ -66,7 +109,8 @@
    }
    @Override
    public void addReporting(MesWorkReporting mesWorkReporting) {
    @Transactional(rollbackFor = Exception.class)
    public MesWorkReporting addReporting(MesWorkReporting mesWorkReporting) {
        MesProductionWorkOrder workOrder = mesProductionWorkOrderService.getById(mesWorkReporting.getWorkOrderId());
        if (workOrder == null) {
            throw new JeecgBootException("工单不存在!");
@@ -78,13 +122,11 @@
        if (material == null) {
            throw new JeecgBootException("物料不存在!");
        }
        MaterialCategory materialCategory = MaterialCategory.fromName(material.getMaterialCategory());
        MaterialCategoryEnum materialCategory = MaterialCategoryEnum.fromName(material.getMaterialCategory());
        if (materialCategory == null) {
            throw new JeecgBootException("未知的物料类型!");
        }
        //生产批次号
        String batchNumber = sysBusinessCodeRuleService.generateBusinessCodeSeq("WorkReportingBatchNumber");
        mesWorkReporting.setBatchNumber(batchNumber);
        LineSideWarehouse lineSideWarehouse = lineSideWarehouseService.list(new LambdaQueryWrapper<LineSideWarehouse>()
                        .eq(LineSideWarehouse::getFactoryId, mesWorkReporting.getFactoryId())
                        .eq(LineSideWarehouse::getDelFlag, CommonConstant.DEL_FLAG_0))
@@ -92,44 +134,163 @@
        if (lineSideWarehouse == null) {
            throw new JeecgBootException("线边仓库不存在!");
        }
        mesWorkReporting.setWarehouseId(lineSideWarehouse.getId());
        mesWorkReporting.setReporter(Objects.requireNonNull(CommonUtils.getCurrentUser()).getUsername());
        mesWorkReporting.setReportTime(new Date());
        String date = DateUtil.format(new Date(), "yyMMdd");
        //生产批次号
        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)
                .setWorkOrderCode(workOrder.getWorkOrderCode())
                .setWarehouseId(lineSideWarehouse.getId())
                .setWarehouseCode(lineSideWarehouse.getWarehouseCode())
                .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:
                //成品报工逻辑
            case FINISHED_PRODUCT:
                //成品报工
                productReport(mesWorkReporting, workOrder, lineSideWarehouse);
                //生成检验工单
                generateInspectionOrder(mesWorkReporting, workOrder);
                //拼接成品报工托号
                String palletNumber4 = sysBusinessCodeRuleService.generateBusinessCodeSeq("WorkReportingPalletNumber4");
                String finishedPalletNumber = material.getMaterialNumber() + date + palletNumber4;
                mesWorkReporting.setPalletNumber(finishedPalletNumber);
                //todo 扣减内法兰(对应机加内法兰线边库)、外法兰(对应机加外法兰线边库)、小内圈(对应装配线边库)库存,调用SAP投料接口
                //todo 调用SAP工序报工
                //todo 打印成品托标签、检验标识卡、移库单、完工检验工单;判断生产订单是否需要关闭(合格数量 = 订单数量)
                mesWorkReporting.setPalletNumber(finishedPalletNumber).setReportType("FINISHED");
                break;
            case HALF:
            case RAW:
                //半成品报工逻辑
                Factory factory = factoryService.getById(mesWorkReporting.getFactoryId());
            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);
                //todo 扣减对应线边库(外法兰毛坯、内法兰毛坯)库存后,调用SAP投料接口
                //todo 调用SAP工序报工
                break;
            case PARTS:
                mesWorkReporting.setPalletNumber(halfPalletNumber).setReportType("HALF");
                break;
        }
        //新增报工记录
        save(mesWorkReporting);
        //线边库入库逻辑
        LswMaterialInbound lswMaterialInbound = new LswMaterialInbound()
                .setFactoryId(mesWorkReporting.getFactoryId())
                .setMaterialNumber(material.getMaterialNumber())
                .setMaterialName(material.getMaterialName())
                .setBatchNumber(batchNumber)
                .setQuantity(mesWorkReporting.getQuantity())
                .setWarehouseId(lineSideWarehouse.getId());
        lswMaterialInboundService.save(lswMaterialInbound);
        //更新排产工单
        MesProductionWorkOrder productionWorkUpdateOrder = new MesProductionWorkOrder()
                .setId(workOrder.getId())
                .setActualQuantity(workOrder.getActualQuantity().add(mesWorkReporting.getQuantity()))
                .setFinishedPallets(workOrder.getFinishedPallets() + 1);
        mesProductionWorkOrderService.updateById(productionWorkUpdateOrder);
        //返回报工记录,用于托标签打印
        return mesWorkReporting;
    }
    //半成品(内法兰、外法兰)、成品报工
    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 void generateInspectionOrder(MesWorkReporting mesWorkReporting, MesProductionWorkOrder workOrder) {
        //1.根据物料编码查询检验方案
        InspectionPlan inspectionPlan = inspectionPlanService.list(new LambdaQueryWrapper<InspectionPlan>()
                .eq(InspectionPlan::getMaterialNumber, workOrder.getMaterialNumber())
                .eq(InspectionPlan::getPlanCategory, PlanCategoryEnum.COMPLETION_INSPECTION.name())
                .eq(InspectionPlan::getPlanStatus, CommonConstant.STATUS_1)
                .eq(InspectionPlan::getDelFlag, CommonConstant.DEL_FLAG_0)).stream().findFirst().orElse(null);
        if (inspectionPlan == null) {
            throw new JeecgBootException("未找到该物料的检验方案!");
        }
        List<InspectionPlanItem> inspectionPlanItemList = inspectionPlanItemService.list(new LambdaQueryWrapper<InspectionPlanItem>()
                .eq(InspectionPlanItem::getPlanId, inspectionPlan.getId())
                .orderByAsc(InspectionPlanItem::getSorter));
        if (inspectionPlanItemList.isEmpty()) {
            throw new JeecgBootException("未找到该物料的检验方案检验项明细!");
        }
        //2.生成检验工单
        //todo 检验工单目前还没有生成代码,没有功能
    }
    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;
    }
}