18 小时以前 4bcd26a4975d6722bff65690e7a8331cd0afd520
yys
1.销售,采购台账产品反着来
2.产品图纸带到生产订单来
已修改15个文件
208 ■■■■■ 文件已修改
src/main/java/com/ruoyi/basic/pojo/ProductModel.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/IProductService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductionProductInputController.java 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductOrderDto.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/ProductWorkOrderMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductWorkOrder.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProductionProductInputService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductionProductInputServiceImpl.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductWorkOrderMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/ProductModel.java
@@ -2,11 +2,13 @@
import com.baomidou.mybatisplus.annotation.*;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.sales.pojo.CommonFile;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Data
@TableName("product_model")
@@ -14,6 +16,9 @@
    private static final long serialVersionUID = 1L;
    @TableField(exist = false)
    private List<CommonFile> SalesLedgerFiles;
    /**
     * 序号
     */
src/main/java/com/ruoyi/basic/service/IProductService.java
@@ -23,4 +23,5 @@
    IPage<ProductModel> listPageProductModel(Page<ProductModel> page, ProductModel productModel);
    AjaxResult listPage(Page page, ProductAndModelDto productDto);
}
src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
@@ -12,6 +12,7 @@
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.basic.service.IProductModelService;
import com.ruoyi.common.enums.FileNameType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
@@ -199,7 +200,7 @@
        // 查询所有工艺路线
        List<ProductProcess> productRoutes = productProcessMapper.selectList(new QueryWrapper<ProductProcess>());
        if(CollectionUtils.isEmpty(productRoutes)){
            throw new RuntimeException("请先创建产品工艺路线");
            throw new ServiceException("请先创建产品工艺路线");
        }
        for (ProductModelExcelCopyDto dto : dtoList) {
            // 查询条件:型号+图纸编号(更精准,符合分组逻辑)
src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java
@@ -64,7 +64,11 @@
    @Override
    public IPage<ProductModel> listPageProductModel(Page<ProductModel> page, ProductModel productModel) {
        return productModelMapper.listPageProductModel(page, productModel);
        IPage<ProductModel> productModelIPage = productModelMapper.listPageProductModel(page, productModel);
        productModelIPage.getRecords().forEach(item -> {
            item.setSalesLedgerFiles(commonFileService.getFileListByBusinessId(item.getId(), FileNameType.PRODUCT_MODEL.getValue()));
        });
        return productModelIPage;
    }
    @Override
src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java
@@ -12,7 +12,8 @@
    PURCHASE_STOCK_IN("7", "采购-入库"),
    QUALITYINSPECT_STOCK_IN("6", "质检-合格入库"),
    DEFECTIVE_PASS("11", "不合格-让步放行"),
    RETURN_HE_IN("14", "销售退货-合格入库");
    RETURN_HE_IN("14", "销售退货-合格入库"),
    RETURN_MATERIAL_IN("15", "退料-入库");
    private final String code;
src/main/java/com/ruoyi/production/controller/ProductionProductInputController.java
@@ -3,14 +3,17 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.production.dto.ProductionProductInputDto;
import com.ruoyi.production.pojo.ProductionProductInput;
import com.ruoyi.production.service.ProductionProductInputService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
@RequestMapping("productionProductInput")
import java.util.List;
@RequestMapping("/productionProductInput")
@RestController
@Api(value = "生产投入")
public class ProductionProductInputController {
@@ -18,8 +21,16 @@
    @Autowired
    private ProductionProductInputService productionProductInputService;
    @GetMapping("listPage")
    @GetMapping("/listPage")
    public R page(Page<ProductionProductInputDto> page, ProductionProductInputDto productionProductInputDto) {
        return R.ok(productionProductInputService.listPageProductionProductInputDto(page, productionProductInputDto));
    }
    @ApiOperation(value = "退料")
    @PostMapping("/returnMaterial")
    @Transactional(rollbackFor = Exception.class)
    public R returnMaterial(@RequestBody List<ProductionProductInput> productionProductInput) {
        return R.ok(productionProductInputService.returnMaterial(productionProductInput));
    }
}
src/main/java/com/ruoyi/production/dto/ProductOrderDto.java
@@ -5,12 +5,14 @@
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.production.pojo.ProductOrder;
import com.ruoyi.production.pojo.ProductWorkOrder;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
@Data
@ExcelIgnoreUnannotated
@@ -68,4 +70,7 @@
    @ApiModelProperty(value = "操作 1-开始 2-暂停")
    private Integer operation;
    @ApiModelProperty(value = "生产任务")
    private List<ProductWorkOrderDto> productWorkOrders;
}
src/main/java/com/ruoyi/production/mapper/ProductWorkOrderMapper.java
@@ -17,6 +17,8 @@
    IPage<ProductWorkOrderDto> pageProductWorkOrder(Page<ProductWorkOrderDto> page, @Param("c") ProductWorkOrderDto productWorkOrder);
    List<ProductWorkOrderDto> getProductWorkOrderList(@Param("c") ProductWorkOrderDto productWorkOrder);
    ProductWorkOrderDto getProductWorkOrderFlowCard(@Param("id") Long id);
    List<ProductWorkOrderDto> selectWorkOrderStartStats(@Param("startDate") String startDate, @Param("endDate") String endDate);
src/main/java/com/ruoyi/production/pojo/ProductWorkOrder.java
@@ -11,6 +11,7 @@
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
/**
 * 产品工单实体类
@@ -20,8 +21,16 @@
@TableName("product_work_order")
public class ProductWorkOrder implements Serializable {
    private static final long serialVersionUID = 1L;
    @TableField(exist = false)
    @ApiModelProperty(value = "颜色 1-灰色 2-黄色 3-绿色 4-红色")
    private Integer color;
    /**
     * 主键id
     */
src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java
@@ -26,6 +26,9 @@
    @ApiModelProperty(value = "数量")
    private BigDecimal quantity;
    @ApiModelProperty(value = "退料数量")
    private BigDecimal returnQuantity;
    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
src/main/java/com/ruoyi/production/service/ProductionProductInputService.java
@@ -6,6 +6,10 @@
import com.ruoyi.production.dto.ProductionProductInputDto;
import com.ruoyi.production.pojo.ProductionProductInput;
import java.util.List;
public interface ProductionProductInputService extends IService<ProductionProductInput> {
    IPage<ProductionProductInputDto> listPageProductionProductInputDto(Page page, ProductionProductInputDto productionProductInputDto);
    Object returnMaterial(List<ProductionProductInput> productionProductInput);
}
src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java
@@ -269,14 +269,14 @@
    }
    private ProductModel findModel(String name, String spec) {
        Product product = productService.getOne(new LambdaQueryWrapper<Product>()
                .eq(Product::getProductName, name).last("limit 1"));
        if (product == null) throw new ServiceException("产品未维护:" + name);
//        Product product = productService.getOne(new LambdaQueryWrapper<Product>()
//                .eq(Product::getProductName, name).last("limit 1"));
//        if (product == null) throw new ServiceException("产品未维护:" + name);
        ProductModel model = productModelService.getOne(new LambdaQueryWrapper<ProductModel>()
                .eq(ProductModel::getProductId, product.getId())
//                .eq(ProductModel::getProductId, product.getId())
                .eq(ProductModel::getModel, spec).last("limit 1"));
        if (model == null) throw new ServiceException("规格未维护:" + name + "[" + spec + "]");
        if (model == null) throw new ServiceException("图纸编号未维护:" + name + "[" + spec + "]");
        return model;
    }
src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java
@@ -15,6 +15,7 @@
import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.production.dto.ProductOrderDto;
import com.ruoyi.production.dto.ProductStructureDto;
import com.ruoyi.production.dto.ProductWorkOrderDto;
import com.ruoyi.production.mapper.*;
import com.ruoyi.production.pojo.*;
import com.ruoyi.production.service.ProductOrderService;
@@ -102,10 +103,73 @@
            // 附件
            productOrderDto.setSalesLedgerFiles(commonFileService.getFileListByBusinessId(productOrderDto.getId()
            , FileNameType.PRODUCT_ORDER.getValue()));
            // 获取对应工单记录
            ProductWorkOrderDto productWorkOrder = new ProductWorkOrderDto();
            productWorkOrder.setProductOrderId(productOrderDto.getId());
            List<ProductWorkOrderDto> productWorkOrders = productWorkOrderMapper.getProductWorkOrderList(productWorkOrder);
            if(CollectionUtils.isNotEmpty(productWorkOrders)){
                productOrderDto.setProductWorkOrders(calculateColor(productWorkOrders));
            }
        });
        return productOrderDtoIPage;
    }
    /**
     * 自动计算颜色(核心方法)
     * @param productWorkOrders
     */
    public List<ProductWorkOrderDto> calculateColor(List<ProductWorkOrderDto> productWorkOrders) {
        List<ProductWorkOrderDto> result = new java.util.ArrayList<>();
        for (int i = 0; i < productWorkOrders.size(); i++) {
            ProductWorkOrderDto current = productWorkOrders.get(i);
            // 判断是否存在下一道工单 + 下一道工单是否有完成数量
            boolean nextOrderHasComplete = false;  // 黄色
            boolean nextOrderHasScrap = false; // 红色
            // 如果不是最后一条,就取下一条判断
            for (int j = i + 1; j < productWorkOrders.size(); j++) {
                if (i < productWorkOrders.size() - 1) {
                    ProductWorkOrderDto next = productWorkOrders.get(j);
                    BigDecimal nextComplete = next.getCompleteQuantity() == null ? BigDecimal.ZERO : next.getCompleteQuantity();
                    BigDecimal nextScrap = next.getPlanQuantity() == null ? BigDecimal.ZERO : next.getPlanQuantity();
                    // 下一道工单完成数量 > 0
                    nextOrderHasComplete = nextComplete.compareTo(BigDecimal.ZERO) > 0;
                    nextOrderHasScrap = nextComplete.compareTo(nextScrap) == 0;
                    break;
                }
            }
            // =============== 核心:计算颜色并赋值 ===============
            BigDecimal planQty = current.getPlanQuantity() == null ? BigDecimal.ZERO : current.getPlanQuantity();
            BigDecimal completeQty = current.getCompleteQuantity() == null ? BigDecimal.ZERO : current.getCompleteQuantity();
            // 1. 当前工序完成数量等于0 且 下一道工序已完成 → 红色(4)
            if (completeQty.compareTo(BigDecimal.ZERO) == 0
                    && nextOrderHasScrap) {
                current.setColor(4);
            }
            // 2. 需求数量 > 完成数量(未完成) 且 下一道工序完成数量 > 0 → 黄色(2)
            else if (planQty.compareTo(completeQty) > 0
                    && nextOrderHasComplete) {
                current.setColor(2);
            }
            // 3. 完成数量=0 → 灰色(1)
            else if (completeQty.compareTo(BigDecimal.ZERO) == 0) {
                current.setColor(1);
            }
            // 4. 完成数量=需求数量 → 绿色(3)
            else if (completeQty.compareTo(planQty) == 0) {
                current.setColor(3);
            }
            // 其他情况默认灰色(可选)
            else {
                current.setColor(1);
            }
            result.add(current);
        }
        return result;
    }
    @Override
    public int bindingRoute(ProductOrder productOrder) {
        //新增生产订单下的工艺路线主表
src/main/java/com/ruoyi/production/service/impl/ProductionProductInputServiceImpl.java
@@ -1,15 +1,24 @@
package com.ruoyi.production.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.production.dto.ProductionProductInputDto;
import com.ruoyi.production.mapper.ProductStructureRecordMapper;
import com.ruoyi.production.mapper.ProductionProductInputMapper;
import com.ruoyi.production.pojo.ProductStructureRecord;
import com.ruoyi.production.pojo.ProductionProductInput;
import com.ruoyi.production.service.ProductionProductInputService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;
@Service
@AllArgsConstructor
@@ -17,8 +26,37 @@
    @Autowired
    private ProductionProductInputMapper productionProductInputMapper;
    @Autowired
    private StockUtils stockUtils;
    @Autowired
    private ProductStructureRecordMapper productStructureRecordMapper;
    @Override
    public IPage<ProductionProductInputDto> listPageProductionProductInputDto(Page page, ProductionProductInputDto productionProductInputDto) {
        return productionProductInputMapper.listPageProductionProductInputDto(page, productionProductInputDto);
    }
    @Override
    public Object returnMaterial(List<ProductionProductInput> productionProductInput) {
        if(CollectionUtils.isEmpty(productionProductInput)){
            return "请选择要退料的数据";
        }
        for (ProductionProductInput input : productionProductInput) {
            ProductionProductInput productionProductInput1 = productionProductInputMapper.selectById(input.getId());
            BigDecimal qty = input.getReturnQuantity() == null ? BigDecimal.ZERO : input.getReturnQuantity();
            BigDecimal qty1 = productionProductInput1.getReturnQuantity() == null ? BigDecimal.ZERO : productionProductInput1.getReturnQuantity();
            productionProductInput1.setReturnQuantity(qty.add(qty1));
            productionProductInputMapper.updateById(productionProductInput1);
            // 退料入库
            stockUtils.addStock(input.getProductModelId(), input.getReturnQuantity(), StockInQualifiedRecordTypeEnum.RETURN_MATERIAL_IN.getCode(), input.getId());
            // 增加物料清单
            ProductStructureRecord productStructureRecord = productStructureRecordMapper.selectById(input.getProductStructureRecordId());
            if(productStructureRecord != null){
                productStructureRecord.setCompletedQuantity(productStructureRecord.getCompletedQuantity().subtract(qty));
                productStructureRecordMapper.updateById(productStructureRecord);
            }
        }
        return "退料成功";
    }
}
src/main/resources/mapper/production/ProductWorkOrderMapper.xml
@@ -97,4 +97,38 @@
        limit 1
        ;
    </select>
    <select id="getProductWorkOrderList" resultType="com.ruoyi.production.dto.ProductWorkOrderDto"
            parameterType="com.ruoyi.production.dto.ProductWorkOrderDto">
        SELECT
        pwo.*,
        pp.NAME as processName,
        pm.model,
        pm.unit,
        p.product_name AS productName,
        pm.drawing_number,
        po.nps_no AS productOrderNpsNo,
        ROUND(pwo.complete_quantity / pwo.plan_quantity * 100, 2) AS completionStatus,
        CASE
        WHEN pwo.work_order_no LIKE 'FG%' THEN '返工返修'
        ELSE '正常'
        END AS work_order_type
        FROM
        product_work_order pwo
        LEFT JOIN product_process_route_item ppri ON ppri.id = pwo.product_process_route_item_id
        LEFT JOIN product_order po ON po.id = pwo.product_order_id
        LEFT JOIN product_process pp ON pp.id = ppri.process_id
        LEFT JOIN product_model pm ON pm.id = ppri.product_model_id
        LEFT JOIN product p ON p.id = pm.product_id
        <where>
            <if test="c.workOrderNo != null and c.workOrderNo != ''">
                and pwo.work_order_no like concat('%',#{c.workOrderNo},'%')
            </if>
            <if test="c.planStartTime != null and c.planEndTime != null">
                and DATE(pwo.create_time) between #{c.planStartTime} and #{c.planEndTime}
            </if>
            <if test="c.productOrderId != null and c.productOrderId != ''">
                and pwo.product_order_id = #{c.productOrderId}
            </if>
        </where>
    </select>
</mapper>