新火炬后端单体项目初始化代码
cuilei
4 天以前 eec479e2f3139286449005dcb05c014e4a60d255
报工接口、产线线边库物料查询接口
已添加1个文件
已修改15个文件
390 ■■■■ 文件已修改
db/双林新火炬MES数据库设计.pdma.json 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/org/jeecg/modules/base/enums/ProductionTypeEnum.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/org/jeecg/modules/lsw/controller/LswMaterialController.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/org/jeecg/modules/lsw/entity/LswMaterialInbound.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/org/jeecg/modules/lsw/enums/MaterialCategoryEnum.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/org/jeecg/modules/mes/controller/MesProductionWorkOrderController.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/org/jeecg/modules/mes/entity/MesMaterialLoading.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/org/jeecg/modules/mes/entity/MesProductionWorkOrder.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/org/jeecg/modules/mes/entity/MesWorkReporting.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/org/jeecg/modules/mes/service/impl/MesProductionWorkOrderServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/org/jeecg/modules/mes/service/impl/MesWorkReportingServiceImpl.java 198 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/org/jeecg/modules/pms/service/IPmsProcessBillMaterialsService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/org/jeecg/modules/pms/service/impl/PmsProcessBillMaterialsServiceImpl.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/org/jeecg/modules/pms/vo/ProcessBillMaterialsDetailVo.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/org/jeecg/modules/sap/request/OrderLoadRequest.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/org/jeecg/modules/sap/request/OrderReportRequest.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
db/Ë«ÁÖлð¾æMESÊý¾Ý¿âÉè¼Æ.pdma.json
@@ -2,9 +2,9 @@
  "name": "双林新火炬MES数据库设计",
  "describe": "描述双薪新火炬MES数据库设计详情",
  "avatar": "",
  "version": "4.9.2",
  "version": "4.9.4",
  "createdTime": "2025-3-10 16:38:19",
  "updatedTime": "2025-8-15 14:58:22",
  "updatedTime": "2025-8-18 15:02:20",
  "dbConns": [],
  "profile": {
    "default": {
@@ -632,7 +632,7 @@
      "#DDE5FF"
    ],
    "DDLToggleCase": "L",
    "menuWidth": "364px"
    "menuWidth": "296px"
  },
  "entities": [
    {
@@ -11555,6 +11555,24 @@
          "id": "125E1F1A-A084-4244-8D44-57D5838EE133"
        },
        {
          "defKey": "finished_pallets",
          "defName": "已生产托数",
          "comment": "当前班次已生产的托数量,每次报工更新",
          "type": "",
          "len": "",
          "scale": "",
          "primaryKey": false,
          "notNull": false,
          "autoIncrement": false,
          "defaultValue": "",
          "hideInGraph": false,
          "refDict": "",
          "baseType": "1D764C4A-6F9F-421E-B11A-6F3E23B51811",
          "extProps": {},
          "domain": "6BC8F04B-6CFA-4995-98D3-318F5CDD774E",
          "id": "A2AFA492-7799-4E1C-B2AB-A6004630C951"
        },
        {
          "defKey": "publisher",
          "defName": "发布人",
          "comment": "",
src/main/java/org/jeecg/modules/base/enums/ProductionTypeEnum.java
@@ -17,5 +17,18 @@
    /**
     * çƒ­å¤„理
     */
    HEATTREATMENT
    HEATTREATMENT;
    /**
     * @param name æžšä¸¾çš„名称
     * @return å¯¹åº”çš„ ProductionTypeEnum æžšä¸¾ç±»åž‹ï¼Œå¦‚果未找到则返回 null
     */
    public static ProductionTypeEnum fromName(String name) {
        for (ProductionTypeEnum typeEnum : ProductionTypeEnum.values()) {
            if (typeEnum.name().equals(name)) {
                return typeEnum;
            }
        }
        return null;
    }
}
src/main/java/org/jeecg/modules/lsw/controller/LswMaterialController.java
@@ -1,5 +1,7 @@
package org.jeecg.modules.lsw.controller;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -15,10 +17,14 @@
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.base.entity.Factory;
import org.jeecg.modules.base.entity.LineSideWarehouse;
import org.jeecg.modules.base.enums.ProductionTypeEnum;
import org.jeecg.modules.base.service.IFactoryService;
import org.jeecg.modules.base.service.ILineSideWarehouseService;
import org.jeecg.modules.lsw.entity.LswMaterial;
import org.jeecg.modules.lsw.entity.LswMaterialInventory;
import org.jeecg.modules.lsw.enums.MaterialCategoryEnum;
import org.jeecg.modules.lsw.service.ILswMaterialInventoryService;
import org.jeecg.modules.lsw.service.ILswMaterialService;
import org.jeecg.modules.lsw.vo.LswMaterialPage;
@@ -53,6 +59,8 @@
    private ILswMaterialInventoryService lswMaterialInventoryService;
    @Autowired
    private ILineSideWarehouseService lineSideWarehouseService;
    @Autowired
    private IFactoryService factoryService;
    /**
     * åˆ†é¡µåˆ—表查询
@@ -160,6 +168,45 @@
        return Result.OK(lswMaterialInventoryList);
    }
    @AutoLog(value = "线边库物料信息-通过产线类型查询线边库物料")
    @ApiOperation(value = "线边库物料信息-通过产线类型查询线边库物料", notes = "线边库物料信息-通过产线类型查询线边库物料")
    @GetMapping(value = "/queryLswMaterialByProductionType")
    public Result<List<LswMaterial>> queryLswMaterialByProductionType(@RequestParam("factoryId") String factoryId) {
        Factory factory = factoryService.getById(factoryId);
        ProductionTypeEnum productionType = ProductionTypeEnum.fromName(factory.getProductionType());
        List<LswMaterial> lswMaterialList = CollectionUtil.newArrayList();
        if (productionType == null) {
            throw new JeecgBootException("产线类型未设置,无法查询相应物料信息!");
        }
        switch (productionType) {
            case ASSEMBLE:
                //装配线,查询成品物料
                lswMaterialList = lswMaterialService.list(new LambdaQueryWrapper<LswMaterial>()
                        .eq(LswMaterial::getMaterialCategory, MaterialCategoryEnum.FINISHED_PRODUCT.name())
                        .eq(LswMaterial::getDelFlag, CommonConstant.DEL_FLAG_0)
                        .eq(LswMaterial::getMaterialStatus, CommonConstant.STATUS_1)
                        .orderByAsc(LswMaterial::getMaterialNumber));
                break;
            case INNERFLANGE:
                //内法兰机加线,查询内法兰物料
                lswMaterialList = lswMaterialService.list(new LambdaQueryWrapper<LswMaterial>()
                        .eq(LswMaterial::getMaterialCategory, MaterialCategoryEnum.INNER_FLANGE.name())
                        .eq(LswMaterial::getDelFlag, CommonConstant.DEL_FLAG_0)
                        .eq(LswMaterial::getMaterialStatus, CommonConstant.STATUS_1)
                        .orderByAsc(LswMaterial::getMaterialNumber));
                break;
            case OUTERFLANGE:
                //外法兰机加线,查询外法兰物料
                lswMaterialList = lswMaterialService.list(new LambdaQueryWrapper<LswMaterial>()
                        .eq(LswMaterial::getMaterialCategory, MaterialCategoryEnum.OUTER_FLANGE.name())
                        .eq(LswMaterial::getDelFlag, CommonConstant.DEL_FLAG_0)
                        .eq(LswMaterial::getMaterialStatus, CommonConstant.STATUS_1)
                        .orderByAsc(LswMaterial::getMaterialNumber));
                break;
        }
        return Result.OK(lswMaterialList);
    }
    /**
     * å¯¼å‡ºexcel
     *
src/main/java/org/jeecg/modules/lsw/entity/LswMaterialInbound.java
@@ -15,6 +15,7 @@
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
@@ -81,7 +82,7 @@
    /**入库数量*/
    @Excel(name = "入库数量", width = 15)
    @ApiModelProperty(value = "入库数量")
    private Double quantity;
    private BigDecimal quantity;
    /**接收人*/
    @Excel(name = "接收人", width = 15)
    @ApiModelProperty(value = "接收人")
src/main/java/org/jeecg/modules/lsw/enums/MaterialCategoryEnum.java
@@ -5,6 +5,14 @@
    OUTER_FLANGE, //外法兰
    INNER_FLANGE, //内法兰
    COMPONENTS, //配件
    BLANK, //毛坯
    ;
    BLANK; //毛坯
    public static MaterialCategoryEnum fromName(String name) {
        for (MaterialCategoryEnum category : MaterialCategoryEnum.values()) {
            if (category.name().equals(name)) {
                return category;
            }
        }
        return null;
    }
}
src/main/java/org/jeecg/modules/mes/controller/MesProductionWorkOrderController.java
@@ -204,10 +204,12 @@
    @GetMapping(value = "/execute")
    public Result<?> execute(@RequestParam("id") String id) {
        MesProductionWorkOrder workOrder = mesProductionWorkOrderService.getById(id);
        if (!ProductionWorkOrderStatus.PUBLISHED.name().equals(workOrder.getWorkOrderStatus())) {
        if (!ProductionWorkOrderStatus.PUBLISHED.name().equals(workOrder.getWorkOrderStatus())
                && !CommonConstant.DEFAULT_1.equals(workOrder.getCompletenessCheckFlag())
                && !CommonConstant.DEFAULT_1.equals(workOrder.getEquipmentInspectionFlag())
                && !CommonConstant.DEFAULT_1.equals(workOrder.getProcessInspectionFlag())) {
            return Result.error("当前工单状态不能执行!");
        }
        //todo é½å¥—性检查、工艺点检、设备点检 çš„æ ¡éªŒé€»è¾‘
        MesProductionWorkOrder executeOrder = new MesProductionWorkOrder()
                .setId(id)
                .setWorkOrderStatus(ProductionWorkOrderStatus.EXECUTING.name());
src/main/java/org/jeecg/modules/mes/entity/MesMaterialLoading.java
@@ -12,6 +12,7 @@
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
@@ -85,11 +86,11 @@
    /**数量*/
    @Excel(name = "数量", width = 15)
    @ApiModelProperty(value = "数量")
    private Double quantity;
    private BigDecimal quantity;
    /**剩余数量*/
    @Excel(name = "剩余数量", width = 15)
    @ApiModelProperty(value = "剩余数量")
    private Double remainingQuantity;
    private BigDecimal remainingQuantity;
    @TableField(exist = false)
    @ApiModelProperty(value = "工单号")
    private String workOrderCode;
src/main/java/org/jeecg/modules/mes/entity/MesProductionWorkOrder.java
@@ -116,6 +116,10 @@
    @Excel(name = "实际报工数量", width = 15)
    @ApiModelProperty(value = "实际报工数量")
    private BigDecimal actualQuantity;
    /**已生产托数(当前班次已生产的托数量,每次报工时更新)*/
    @Excel(name = "已生产托数", width = 15)
    @ApiModelProperty(value = "已生产托数")
    private Integer finishedPallets = 0;
    /**发布人*/
    @Excel(name = "发布人", width = 15)
    @ApiModelProperty(value = "发布人")
src/main/java/org/jeecg/modules/mes/entity/MesWorkReporting.java
@@ -12,6 +12,7 @@
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
@@ -79,7 +80,7 @@
    /**数量*/
    @Excel(name = "数量", width = 15)
    @ApiModelProperty(value = "数量")
    private Double quantity;
    private BigDecimal quantity;
    /**报工人*/
    @Excel(name = "报工人", width = 15)
    @ApiModelProperty(value = "报工人")
src/main/java/org/jeecg/modules/mes/service/impl/MesProductionWorkOrderServiceImpl.java
@@ -77,6 +77,9 @@
                        .eq(ShiftGroup::getFactoryId, request.getFactoryId())
                        .eq(ShiftGroup::getDelFlag, CommonConstant.DEL_FLAG_0))
                .stream().collect(Collectors.toMap(ShiftGroup::getShiftId, v1 -> v1, (v1, v2) -> v1));
        if (shiftGroupMap.isEmpty()) {
            throw new JeecgBootException("该产线下未设置班组,无法排产!");
        }
        Factory factory = factoryService.getById(request.getFactoryId());
        Map<String, Shift> shiftNameMap = new HashMap<>();
        List<Shift> shifts = shiftService.list(new LambdaQueryWrapper<Shift>()
src/main/java/org/jeecg/modules/mes/service/impl/MesWorkReportingServiceImpl.java
@@ -1,35 +1,54 @@
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.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 +56,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 +71,23 @@
    @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) {
@@ -66,6 +100,7 @@
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addReporting(MesWorkReporting mesWorkReporting) {
        MesProductionWorkOrder workOrder = mesProductionWorkOrderService.getById(mesWorkReporting.getWorkOrderId());
        if (workOrder == null) {
@@ -78,13 +113,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 +125,137 @@
        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)
                .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:
                //成品报工逻辑
            case FINISHED_PRODUCT:
                //成品报工
                productReport(mesWorkReporting, workOrder, lineSideWarehouse);
                //拼接成品报工托号
                String palletNumber4 = sysBusinessCodeRuleService.generateBusinessCodeSeq("WorkReportingPalletNumber4");
                String finishedPalletNumber = material.getMaterialNumber() + date + palletNumber4;
                mesWorkReporting.setPalletNumber(finishedPalletNumber);
                //todo æ‰£å‡å†…法兰(对应机加内法兰线边库)、外法兰(对应机加外法兰线边库)、小内圈(对应装配线边库)库存,调用SAP投料接口
                //todo è°ƒç”¨SAP工序报工
                //todo æ‰“印成品托标签、检验标识卡、移库单、完工检验工单;判断生产订单是否需要关闭(合格数量 = è®¢å•数量)
                //todo æ‰“印成品托标签、检验标识卡、移库单、完工检验工单
                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:
                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);
    }
    //半成品(内法兰、外法兰)、成品报工
    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;
    }
}
src/main/java/org/jeecg/modules/pms/service/IPmsProcessBillMaterialsService.java
@@ -5,6 +5,7 @@
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.mes.entity.MesProductionOrder;
import org.jeecg.modules.pms.entity.PmsProcessBillMaterials;
import org.jeecg.modules.pms.vo.ProcessBillMaterialsDetailVo;
import org.jeecg.modules.sap.dto.OrderBomDTO;
import java.util.List;
@@ -39,4 +40,6 @@
     * @return
     */
    IPage<PmsProcessBillMaterials> queryPageList(Page<PmsProcessBillMaterials> page, PmsProcessBillMaterials query);
    List<ProcessBillMaterialsDetailVo> queryMaterialsDetailByOrderIdAndMaterialNumber(String orderId, String materialNumber);
}
src/main/java/org/jeecg/modules/pms/service/impl/PmsProcessBillMaterialsServiceImpl.java
@@ -7,16 +7,21 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.modules.mes.entity.MesProductionOrder;
import org.jeecg.modules.pms.entity.PmsProcessBillMaterials;
import org.jeecg.modules.pms.entity.PmsProcessBillMaterialsDetail;
import org.jeecg.modules.pms.mapper.PmsProcessBillMaterialsMapper;
import org.jeecg.modules.pms.service.IPmsProcessBillMaterialsDetailService;
import org.jeecg.modules.pms.service.IPmsProcessBillMaterialsService;
import org.jeecg.modules.pms.vo.ProcessBillMaterialsDetailVo;
import org.jeecg.modules.sap.dto.OrderBomDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -98,4 +103,29 @@
        }
        return this.getBaseMapper().queryPageList(page, queryWrapper);
    }
    @Override
    public List<ProcessBillMaterialsDetailVo> queryMaterialsDetailByOrderIdAndMaterialNumber(String orderId, String materialNumber) {
        //根据生产订单id和物料编码查询订单BOM
        PmsProcessBillMaterials processBillMaterials = list(new LambdaQueryWrapper<PmsProcessBillMaterials>()
                        .eq(PmsProcessBillMaterials::getOrderId, orderId)
                        .eq(PmsProcessBillMaterials::getMaterialNumber, materialNumber))
                .stream().findFirst().orElse(null);
        if (processBillMaterials == null) {
            throw new JeecgBootException("未找到与该物料关联的订单BOM!");
        }
        //查询订单BOM明细
        List<PmsProcessBillMaterialsDetail> processBillMaterialsDetails = processBillMaterialsDetailService.queryByMaterialId(processBillMaterials.getId());
        List<ProcessBillMaterialsDetailVo> billMaterialsDetailList = CollectionUtil.newArrayList();
        for (PmsProcessBillMaterialsDetail processBillMaterialsDetail : processBillMaterialsDetails) {
            ProcessBillMaterialsDetailVo processBillMaterialsDetailVo = new ProcessBillMaterialsDetailVo()
                    .setMaterialNumber(processBillMaterialsDetail.getMaterialNumber())
                    .setMaterialName(processBillMaterialsDetail.getMaterialName())
                    .setProductionUnit(processBillMaterialsDetail.getProductionUnit())
                    .setPerQuantity(processBillMaterialsDetail.getUsageQuantity()
                            .divide(processBillMaterials.getProductionQuantity(), 2, RoundingMode.HALF_UP));
            billMaterialsDetailList.add(processBillMaterialsDetailVo);
        }
        return billMaterialsDetailList;
    }
}
src/main/java/org/jeecg/modules/pms/vo/ProcessBillMaterialsDetailVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
package org.jeecg.modules.pms.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.math.BigDecimal;
/**
 * @Description: ç‰©æ–™æ¸…单
 * @Author: jeecg-boot
 * @Date:   2025-07-01
 * @Version: V1.0
 */
@Data
@Accessors(chain = true)
public class ProcessBillMaterialsDetailVo implements Serializable {
    private static final long serialVersionUID = 1L;
    /**物料编码*/
    @ApiModelProperty(value = "物料编码")
    private String materialNumber;
    /**物料名称*/
    @ApiModelProperty(value = "物料名称")
    private String materialName;
    /**基本单位*/
    @ApiModelProperty(value = "基本单位")
    private String productionUnit;
    /**需求用量*/
    @ApiModelProperty(value = "单位用量(加工1件的用量)")
    private BigDecimal perQuantity;
}
src/main/java/org/jeecg/modules/sap/request/OrderLoadRequest.java
@@ -1,6 +1,7 @@
package org.jeecg.modules.sap.request;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
@@ -8,6 +9,7 @@
 * æŠ•料请求参数
 */
@Data
@Accessors(chain = true)
public class OrderLoadRequest {
    /** MATNR ç‰©æ–™å· */
    private String materialNumber;
src/main/java/org/jeecg/modules/sap/request/OrderReportRequest.java
@@ -1,6 +1,7 @@
package org.jeecg.modules.sap.request;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
@@ -9,6 +10,7 @@
 * è¯·æ±‚ç±»
 */
@Data
@Accessors(chain = true)
public class OrderReportRequest {
    /** I_WERKS å·¥åŽ‚ */
    private String factoryCode;