gongchunyi
2 小时以前 eaf6548902e9472fc9b876d531db8508e16c4f2f
feat: 生产订单的撤回、删除;BOM的子集新增/修改统一使用临时ID处理
已修改13个文件
215 ■■■■■ 文件已修改
src/main/java/com/ruoyi/production/controller/ProductOrderController.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductStructureController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductionOrderStructureController.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductionOrderStructureDto.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/enums/ProductOrderStatusEnum.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/ProductionOrderStructureMapper.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/IProductionOrderStructureService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProductOrderService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProductStructureService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductStructureServiceImpl.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductionOrderStructureServiceImpl.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductionOrderStructureMapper.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductOrderController.java
@@ -48,8 +48,14 @@
    @PostMapping("/revoke")
    @ApiOperation("撤回生产计划")
    public R revoke(@RequestBody ProductOrder productOrder) {
        return R.ok(productOrderService.revoke(productOrder));
    public R revoke(@RequestBody List<Long> ids) {
        return R.ok(productOrderService.revoke(ids));
    }
    @ApiOperation("删除生产订单")
    @DeleteMapping("/{id}")
    public R delete(@PathVariable("id") Long ids) {
        return R.ok(productOrderService.delete(ids));
    }
    /**
@@ -76,9 +82,5 @@
        return R.ok(productOrderService.addProductOrder(productOrder));
    }
    @ApiOperation("删除生产订单")
    @DeleteMapping("/{ids}")
    public R delete(@PathVariable("ids") Long[] ids) {
        return R.ok(productOrderService.delete(ids));
    }
}
src/main/java/com/ruoyi/production/controller/ProductStructureController.java
@@ -17,6 +17,7 @@
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
@RequestMapping("productStructure")
@RestController
@@ -27,9 +28,9 @@
    @ApiOperation("新增BOM子集")
    @PostMapping()
    public R addOrUpdate(@RequestBody ProductStructureDto productStructureDto){
        return R.ok(productStructureService.addProductStructureDto(productStructureDto));
    @PostMapping("/{bomId}")
    public R addOrUpdate(@PathVariable Integer bomId, @RequestBody List<ProductStructureDto> list){
        return R.ok(productStructureService.addProductStructureDto(bomId, list));
    }
    @ApiOperation("BOM查看子集详情")
src/main/java/com/ruoyi/production/controller/ProductionOrderStructureController.java
@@ -33,10 +33,10 @@
        return AjaxResult.success(list);
    }
    @PutMapping("/addOrUpdateBomStructs")
    @PutMapping("/addOrUpdateBomStructs/{orderId}")
    @ApiOperation("新增/更新BOM子集结构")
    public AjaxResult addOrUpdateBomStructs(@RequestBody ProductionOrderStructureDto instanceDto) {
        productionOrderStructureService.addOrUpdateBomStructs(instanceDto);
    public AjaxResult addOrUpdateBomStructs(@PathVariable Long orderId, @RequestBody List<ProductionOrderStructureDto> list) {
        productionOrderStructureService.addOrUpdateBomStructs(orderId, list);
        return AjaxResult.success();
    }
src/main/java/com/ruoyi/production/dto/ProductionOrderStructureDto.java
@@ -31,4 +31,12 @@
    @ApiModelProperty("父节点临时ID")
    private String parentTempId;
    @ApiModelProperty("工序名称")
    private String processName;
    @ApiModelProperty("产品名称")
    private String productName;
    @ApiModelProperty("产品规格")
    private String model;
}
src/main/java/com/ruoyi/production/enums/ProductOrderStatusEnum.java
@@ -43,13 +43,20 @@
    }
    /**
     * 判断是否允许删除(1、4)
     * 判断是否允许删除(4)
     */
    public static boolean canDelete(Integer code) {
        return WAIT.getCode().equals(code) || CANCEL.getCode().equals(code);
    }
    /**
     * 判断是否允许撤回(1)
     */
    public static boolean canRevoke(Integer code) {
        return WAIT.getCode().equals(code);
    }
    /**
     * 判断是否已开始生产(2、3)
     */
    public static boolean isStarted(Integer code) {
src/main/java/com/ruoyi/production/mapper/ProductionOrderStructureMapper.java
@@ -1,7 +1,10 @@
package com.ruoyi.production.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.production.dto.ProductionOrderStructureDto;
import com.ruoyi.production.pojo.ProductionOrderStructure;
import java.util.List;
/**
 * <p>
@@ -13,4 +16,6 @@
 */
public interface ProductionOrderStructureMapper extends BaseMapper<ProductionOrderStructure> {
    List<ProductionOrderStructureDto> listByOrderId(Long orderId);
}
src/main/java/com/ruoyi/production/service/IProductionOrderStructureService.java
@@ -18,5 +18,5 @@
    List<ProductionOrderStructureDto> listByOrderId(Long orderId);
    void addOrUpdateBomStructs(ProductionOrderStructureDto instanceDto);
    void addOrUpdateBomStructs(Long orderId, List<ProductionOrderStructureDto> list);
}
src/main/java/com/ruoyi/production/service/ProductOrderService.java
@@ -21,7 +21,7 @@
    /**
     * 撤回生产计划
     */
    Boolean revoke(ProductOrder productOrder);
    Boolean revoke(List<Long> ids);
    List<ProcessRoute> listProcessRoute(Long productModelId);
@@ -31,5 +31,5 @@
    Long insertProductOrder(ProductOrder productOrder);
    Boolean delete(Long[] id);
    Boolean delete(Long id);
}
src/main/java/com/ruoyi/production/service/ProductStructureService.java
@@ -10,7 +10,7 @@
public interface ProductStructureService extends IService<ProductStructure> {
    Boolean addProductStructureDto(ProductStructureDto productStructureDto);
    Boolean addProductStructureDto(Integer bomId, List<ProductStructureDto> list);
    List<ProductStructureDto> listByBomId(Integer bomId);
src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java
@@ -1,6 +1,5 @@
package com.ruoyi.production.service.impl;
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.core.toolkit.ObjectUtils;
@@ -137,25 +136,48 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean revoke(ProductOrder productOrder) {
        // todo 判断是否产生报工信息
        // 查询合并的生产计划
        List<ProductOrderPlan> productOrderPlans = productOrderPlanMapper.selectList(Wrappers.<ProductOrderPlan>lambdaQuery().in(ProductOrderPlan::getProductOrderId, productOrder.getId()));
        if (productOrderPlans.isEmpty()) {
            throw new RuntimeException("合并的生产计划不存在");
    public Boolean revoke(List<Long> ids) {
        List<ProductOrder> orders = productOrderMapper.selectBatchIds(ids);
        if (orders.isEmpty()) {
            throw new RuntimeException("生产订单不存在");
        }
        for (ProductOrder order : orders) {
            if (!ProductOrderStatusEnum.canRevoke(order.getStatus())) {
                throw new RuntimeException("只有【待开始】状态的订单才可以撤回");
            }
        }
        // 回退生产计划
        List<ProductOrderPlan> productOrderPlans = productOrderPlanMapper.selectList(Wrappers.<ProductOrderPlan>lambdaQuery().in(ProductOrderPlan::getProductOrderId, ids));
        for (ProductOrderPlan productOrderPlan : productOrderPlans) {
            ProductionPlan productionPlan = productionPlanMapper.selectById(productOrderPlan.getProductionPlanId());
            productionPlan.setAssignedQuantity(productionPlan.getAssignedQuantity().subtract(productOrderPlan.getAssignedQuantity()));
            productionPlanMapper.updateById(productionPlan);
            if (productionPlan != null) {
                BigDecimal newAssigned = productionPlan.getAssignedQuantity().subtract(productOrderPlan.getAssignedQuantity());
                if (newAssigned.compareTo(BigDecimal.ZERO) < 0) {
                    newAssigned = BigDecimal.ZERO;
                }
                productionPlan.setAssignedQuantity(newAssigned);
                BigDecimal volume = productionPlan.getVolume() == null ? BigDecimal.ZERO : productionPlan.getVolume();
                int status;
                if (newAssigned.compareTo(BigDecimal.ZERO) == 0) {
                    status = 0; // 未下发
                } else if (newAssigned.compareTo(volume) < 0) {
                    status = 1; // 部分下发
                } else {
                    status = 2; // 已下发
                }
                productionPlan.setStatus(status);
                productionPlanMapper.updateById(productionPlan);
            }
        }
        // 删除关联关系
        productOrderPlanMapper.delete(Wrappers.<ProductOrderPlan>lambdaQuery().in(ProductOrderPlan::getProductOrderId, productOrder.getId()));
        // 删除订单
        productOrderMapper.deleteById(productOrder.getId());
        // todo 删除订单下的工艺路线子表
        return null;
        // 将订单状态改为已取消
        for (ProductOrder order : orders) {
            order.setStatus(ProductOrderStatusEnum.CANCEL.getCode());
        }
        updateBatchById(orders);
        return true;
    }
    @Override
@@ -192,20 +214,18 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(Long[] ids) {
        List<ProductOrder> orders = productOrderMapper.selectList(Wrappers.<ProductOrder>lambdaQuery().in(ProductOrder::getId, ids));
    public Boolean delete(Long id) {
        ProductOrder order = productOrderMapper.selectById(id);
        if (orders.isEmpty()) {
        if (order == null) {
            throw new RuntimeException("生产订单不存在");
        }
        for (ProductOrder order : orders) {
            if (!ProductOrderStatusEnum.canDelete(order.getStatus())) {
                throw new RuntimeException("只有【待开始、已取消】状态的订单才可以删除");
            }
        if (!ProductOrderStatusEnum.canDelete(order.getStatus())) {
            throw new RuntimeException("只有【待开始、已取消】状态的订单才可以删除");
        }
        //  是否已生产
        List<ProductWorkOrder> productWorkOrders = productWorkOrderMapper.selectList(Wrappers.<ProductWorkOrder>lambdaQuery().in(ProductWorkOrder::getProductOrderId, ids));
        List<ProductWorkOrder> productWorkOrders = productWorkOrderMapper.selectList(Wrappers.<ProductWorkOrder>lambdaQuery().eq(ProductWorkOrder::getProductOrderId, id));
        if (!productWorkOrders.isEmpty()) {
            List<Long> workOrderIds = productWorkOrders.stream()
@@ -218,11 +238,11 @@
            }
            //  删除工单
            productWorkOrderMapper.delete(Wrappers.<ProductWorkOrder>lambdaQuery().in(ProductWorkOrder::getProductOrderId, ids));
            productWorkOrderMapper.delete(Wrappers.<ProductWorkOrder>lambdaQuery().eq(ProductWorkOrder::getProductOrderId, id));
        }
        //  回退生产计划
        List<ProductOrderPlan> productOrderPlans = productOrderPlanMapper.selectList(Wrappers.<ProductOrderPlan>lambdaQuery().in(ProductOrderPlan::getProductOrderId, ids));
        List<ProductOrderPlan> productOrderPlans = productOrderPlanMapper.selectList(Wrappers.<ProductOrderPlan>lambdaQuery().eq(ProductOrderPlan::getProductOrderId, id));
        for (ProductOrderPlan productOrderPlan : productOrderPlans) {
            ProductionPlan productionPlan = productionPlanMapper.selectById(productOrderPlan.getProductionPlanId());
@@ -253,19 +273,13 @@
        }
        // 删除中间表
        productOrderPlanMapper.delete(Wrappers.<ProductOrderPlan>lambdaQuery().in(ProductOrderPlan::getProductOrderId, ids));
        productOrderPlanMapper.delete(Wrappers.<ProductOrderPlan>lambdaQuery().eq(ProductOrderPlan::getProductOrderId, id));
        //  删除附表的工艺路线与BOM
        for (Long id : ids) {
            ProductOrder productOrder = baseMapper.selectById(id);
            productionOrderAppendixService.deleteData(productOrder.getId(), productOrder.getRouteId());
        }
//        productProcessRouteItemMapper.delete(new LambdaQueryWrapper<ProductProcessRouteItem>().in(ProductProcessRouteItem::getProductOrderId, ids));
//        productProcessRouteMapper.delete(new LambdaQueryWrapper<ProductProcessRoute>().in(ProductProcessRoute::getProductOrderId, ids));
        productionOrderAppendixService.deleteData(order.getId(), order.getRouteId());
        //  删除订单
        productOrderMapper.delete(new LambdaQueryWrapper<ProductOrder>().in(ProductOrder::getId, ids));
        productOrderMapper.deleteById(id);
        return true;
    }
src/main/java/com/ruoyi/production/service/impl/ProductStructureServiceImpl.java
@@ -25,13 +25,14 @@
    @Override
    @Transactional
    public Boolean addProductStructureDto(ProductStructureDto dto) {
    public Boolean addProductStructureDto(Integer bomId, List<ProductStructureDto> list) {
        Integer bomId = dto.getBomId();
        //  将树扁平化
        // 扁平化传入的树
        List<ProductStructureDto> flatDtoList = new ArrayList<>();
        flattenTree(dto.getChildren(), flatDtoList);
        for (ProductStructureDto root : list) {
            flatDtoList.add(root);
            flattenTree(root.getChildren(), flatDtoList);
        }
        //  查询数据库中已有的 BOM 数据
        List<ProductStructure> dbList = this.list(new LambdaQueryWrapper<ProductStructure>().eq(ProductStructure::getBomId, bomId));
@@ -65,13 +66,13 @@
            entity.setBomId(bomId);
            if (psDto.getId() == null) {
                // 新增
                entity.setId(null);
                entity.setParentId(null);
                insertList.add(entity);
                tempEntityMap.put(psDto.getTempId(), entity);
                if (psDto.getTempId() != null) {
                    tempEntityMap.put(psDto.getTempId(), entity);
                }
            } else {
                // 更新
                updateList.add(entity);
            }
        }
@@ -83,32 +84,27 @@
        //  回写新增节点 parentId
        List<ProductStructure> parentFixList = new ArrayList<>();
        //  真实的父节点 ID
        Long realParentId;
        for (ProductStructureDto psDto : flatDtoList) {
            if (psDto.getId() != null) continue;
            ProductStructure child = tempEntityMap.get(psDto.getTempId());
            if (child == null) continue;
            String parentTempId = psDto.getParentTempId();
            if (psDto.getId() == null && parentTempId != null && !parentTempId.isEmpty()) {
                ProductStructure child = tempEntityMap.get(psDto.getTempId());
            if (parentTempId != null && !parentTempId.isEmpty()) {
                if (tempEntityMap.containsKey(parentTempId)) {
                    // 父节点是新节点
                    realParentId = tempEntityMap.get(parentTempId).getId();
                } else {
                    // 父节点是老节点
                    try {
                        realParentId = Long.valueOf(parentTempId);
                    } catch (NumberFormatException e) {
                        realParentId = 0L;
                    }
                }
                child.setParentId(realParentId);
                parentFixList.add(child);
            } else if (psDto.getId() == null) {
                // 如果 parentTempId 为空,则是顶级节点
                ProductStructure child = tempEntityMap.get(psDto.getTempId());
            } else {
                child.setParentId(0L);
                parentFixList.add(child);
            }
            parentFixList.add(child);
        }
        if (!parentFixList.isEmpty()) {
src/main/java/com/ruoyi/production/service/impl/ProductionOrderStructureServiceImpl.java
@@ -2,7 +2,6 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.production.dto.ProductionOrderStructureDto;
import com.ruoyi.production.mapper.ProductionOrderStructureMapper;
import com.ruoyi.production.pojo.ProductionOrderStructure;
@@ -32,13 +31,7 @@
    @Override
    public List<ProductionOrderStructureDto> listByOrderId(Long orderId) {
        List<ProductionOrderStructure> list = list(new LambdaQueryWrapper<ProductionOrderStructure>().eq(ProductionOrderStructure::getOrderId, orderId));
        List<ProductionOrderStructureDto> dtoList = list.stream().map(item -> {
            ProductionOrderStructureDto dto = new ProductionOrderStructureDto();
            BeanUtils.copyProperties(item, dto);
            return dto;
        }).collect(Collectors.toList());
        List<ProductionOrderStructureDto> dtoList = baseMapper.listByOrderId(orderId);
        Map<Long, ProductionOrderStructureDto> map = new HashMap<>();
        for (ProductionOrderStructureDto node : dtoList) {
@@ -58,12 +51,13 @@
    }
    @Override
    public void addOrUpdateBomStructs(ProductionOrderStructureDto instanceDto) {
        Long orderId = instanceDto.getOrderId();
    public void addOrUpdateBomStructs(Long orderId, List<ProductionOrderStructureDto> list) {
        // 扁平化前端传入的树
        List<ProductionOrderStructureDto> flatList = new ArrayList<>();
        flattenTree(instanceDto.getChildren(), flatList);
        for (ProductionOrderStructureDto root : list) {
            flatList.add(root);
            flattenTree(root.getChildren(), flatList);
        }
        // 查询数据库已有数据
        List<ProductionOrderStructure> dbList = list(new LambdaQueryWrapper<ProductionOrderStructure>()
@@ -90,7 +84,7 @@
        for (ProductionOrderStructureDto dto : flatList) {
            ProductionOrderStructure entity = new ProductionOrderStructure();
            BeanUtils.copyProperties(dto, entity);
            org.springframework.beans.BeanUtils.copyProperties(dto, entity);
            entity.setOrderId(orderId);
            if (dto.getId() == null) {
                entity.setId(null);
@@ -110,13 +104,13 @@
        // 回写新增节点的 parentId
        List<ProductionOrderStructure> parentFixList = new ArrayList<>();
        Long realParentId;
        for (ProductionOrderStructureDto dto : flatList) {
            if (dto.getId() != null) continue;
            ProductionOrderStructure child = tempEntityMap.get(dto.getTempId());
            if (child == null) continue;
            String parentTempId = dto.getParentTempId();
            if (parentTempId != null && !parentTempId.isEmpty()) {
                Long realParentId;
                if (tempEntityMap.containsKey(parentTempId)) {
                    realParentId = tempEntityMap.get(parentTempId).getId();
                } else {
src/main/resources/mapper/production/ProductionOrderStructureMapper.xml
@@ -16,4 +16,20 @@
        <result column="bom_id" property="bomId"/>
    </resultMap>
    <select id="listByOrderId" resultType="com.ruoyi.production.dto.ProductionOrderStructureDto"
            parameterType="java.lang.Long">
        SELECT s.*,
               pp.name        AS process_name,
               pm.product_name AS product_name,
               sku.model       AS model
        FROM production_order_structure s
                 LEFT JOIN product_process pp ON pp.id = s.process_id
                 LEFT JOIN product_material_sku sku ON sku.id = s.product_model_id
                 LEFT JOIN product_material pm ON pm.id = sku.product_id
        WHERE s.order_id = #{orderId}
    </select>
</mapper>