549c7197ce406a8167b67d21ddbd2c1f09c533fc..854d063b5bfcadffe819456e0d4790a0579fa079
2026-03-25 gongchunyi
feat: 销售订单添加产品新增字段、产品加工参数选择
854d06 对比 | 目录
2026-03-25 gongchunyi
feat: 河南鹤壁天沐玻璃厂配置文件
7853ff 对比 | 目录
已添加14个文件
已修改3个文件
765 ■■■■■ 文件已修改
doc/河南鹤壁天沐钢化玻璃厂.sql 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/SalesLedgerProductProcessBindController.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/SalesLedgerProductProcessController.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/SalesLedgerProductDto.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductProcessBindMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductProcessMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/SalesLedgerProductProcess.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/SalesLedgerProductProcessBind.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/ISalesLedgerProductProcessBindService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/ISalesLedgerProductProcessService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductProcessBindServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductProcessServiceImpl.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-hbtmblc.yml 256 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/SalesLedgerProductProcessBindMapper.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/SalesLedgerProductProcessMapper.xml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/ºÓÄϺױÚÌìãå¸Ö»¯²£Á§³§.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
CREATE TABLE sales_ledger_product_process
(
    id               INT PRIMARY KEY AUTO_INCREMENT,
    sales_product_id INT          NOT NULL COMMENT '销售产品ID(关联sales_ledger_product.id)',
    process_name     VARCHAR(100) NOT NULL COMMENT '工艺名称',
    quantity         DECIMAL(12, 3) DEFAULT NULL COMMENT '数量',
    unit_price       DECIMAL(10, 2) DEFAULT NULL COMMENT '单价',
    remark           VARCHAR(255)   DEFAULT NULL,
    create_time      DATETIME       DEFAULT CURRENT_TIMESTAMP
) COMMENT ='销售产品加工明细';
DROP TABLE IF EXISTS `sales_ledger_product_process_bind`;
CREATE TABLE `sales_ledger_product_process_bind`
(
    `id`                              int NOT NULL AUTO_INCREMENT COMMENT '主键',
    `sales_ledger_product_id`         int NULL DEFAULT NULL COMMENT '销售台账产品信息ID',
    `sales_ledger_product_process_id` int NULL DEFAULT NULL COMMENT '销售产品加工明细ID',
    `quantity`                        int NULL DEFAULT NULL COMMENT '加工数量',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
  AUTO_INCREMENT = 2
  CHARACTER SET = utf8mb3
  COLLATE = utf8mb3_general_ci COMMENT = '销售产品额外加工数量'
  ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
ALTER TABLE sales_ledger_product
    ADD COLUMN actual_piece_area DECIMAL(18, 6) DEFAULT NULL COMMENT '实际单片面积(㎡)',
    ADD COLUMN actual_total_area DECIMAL(18, 6) DEFAULT NULL COMMENT '实际总面积(㎡)',
    ADD COLUMN settle_piece_area DECIMAL(18, 6) DEFAULT NULL COMMENT '结算单片面积(㎡)',
    ADD COLUMN settle_total_area DECIMAL(18, 6) DEFAULT NULL COMMENT '结算总面积(㎡)';
ALTER TABLE sales_ledger_product
    ADD COLUMN process_requirement VARCHAR(500) DEFAULT NULL COMMENT '加工要求';
ALTER TABLE sales_ledger_product
    ADD COLUMN remark VARCHAR(500) DEFAULT NULL COMMENT '备注';
ALTER TABLE sales_ledger_product_process
    CHANGE COLUMN remark code VARCHAR(255) COMMENT '编码';
src/main/java/com/ruoyi/sales/controller/SalesLedgerProductProcessBindController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.ruoyi.sales.controller;
import com.ruoyi.sales.service.ISalesLedgerProductProcessBindService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * é”€å”®äº§å“é¢å¤–加工数量 å‰ç«¯æŽ§åˆ¶å™¨
 * </p>
 *
 * @author deslrey
 * @since 2026-03-25
 */
@RestController
@RequestMapping("/salesLedgerProductProcessBind")
public class SalesLedgerProductProcessBindController {
    @Autowired
    private ISalesLedgerProductProcessBindService salesLedgerProductProcessBindService;
}
src/main/java/com/ruoyi/sales/controller/SalesLedgerProductProcessController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package com.ruoyi.sales.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.sales.pojo.SalesLedgerProductProcess;
import com.ruoyi.sales.service.ISalesLedgerProductProcessService;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
 * <p>
 * é”€å”®äº§å“åŠ å·¥æ˜Žç»† å‰ç«¯æŽ§åˆ¶å™¨
 * </p>
 *
 * @author deslrey
 * @since 2026-03-25
 */
@RestController
@RequestMapping("/salesLedgerProductProcess")
@ApiModel(value = "SalesLedgerProductProcessController", description = "销售产品加工明细")
public class SalesLedgerProductProcessController {
    @Autowired
    private ISalesLedgerProductProcessService salesLedgerProductProcessService;
    @ApiOperation("分页查询加工明细")
    @GetMapping("/list")
    public AjaxResult list(Page<SalesLedgerProductProcess> page, String name) {
        return AjaxResult.success(salesLedgerProductProcessService.salesLedgerProductProcessList(page, name));
    }
    @ApiOperation("新增加工明细")
    @PostMapping("/add")
    public AjaxResult add(@RequestBody SalesLedgerProductProcess process) {
        salesLedgerProductProcessService.addProcess(process);
        return AjaxResult.success();
    }
    @ApiOperation("修改加工明细")
    @PutMapping("/update")
    public AjaxResult update(@RequestBody SalesLedgerProductProcess process) {
        salesLedgerProductProcessService.updateProcess(process);
        return AjaxResult.success();
    }
    @ApiOperation("删除加工明细")
    @DeleteMapping("/delete/{id}")
    public AjaxResult delete(@PathVariable Integer id) {
        salesLedgerProductProcessService.deleteProcess(id);
        return AjaxResult.success();
    }
}
src/main/java/com/ruoyi/sales/dto/SalesLedgerProductDto.java
@@ -3,6 +3,7 @@
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.sales.pojo.SalesLedgerProductProcess;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -11,6 +12,7 @@
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
@Data
public class SalesLedgerProductDto extends SalesLedgerProduct {
@@ -65,4 +67,7 @@
    @ApiModelProperty(value = "退货总数")
    private BigDecimal totalReturnNum;
    @ApiModelProperty("销售产品额外加工")
    private List<SalesLedgerProductProcess> salesProductProcessList;
}
src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductProcessBindMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.ruoyi.sales.mapper;
import com.ruoyi.sales.pojo.SalesLedgerProductProcessBind;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
 * <p>
 * é”€å”®äº§å“é¢å¤–加工数量 Mapper æŽ¥å£
 * </p>
 *
 * @author deslrey
 * @since 2026-03-25
 */
public interface SalesLedgerProductProcessBindMapper extends BaseMapper<SalesLedgerProductProcessBind> {
}
src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductProcessMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.ruoyi.sales.mapper;
import com.ruoyi.sales.pojo.SalesLedgerProductProcess;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
 * <p>
 * é”€å”®äº§å“åŠ å·¥æ˜Žç»† Mapper æŽ¥å£
 * </p>
 *
 * @author deslrey
 * @since 2026-03-25
 */
public interface SalesLedgerProductProcessMapper extends BaseMapper<SalesLedgerProductProcess> {
}
src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
@@ -13,6 +13,7 @@
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
/**
 * äº§å“ä¿¡æ¯å¯¹è±¡ sales_ledger_product
@@ -111,22 +112,22 @@
    /**
     * æœ¬æ¬¡æ¥ç¥¨æ•°
     */
    private BigDecimal ticketsNum=BigDecimal.ZERO;
    private BigDecimal ticketsNum = BigDecimal.ZERO;
    /**
     * æœ¬æ¬¡æ¥ç¥¨é‡‘额(元)
     */
    private BigDecimal ticketsAmount=BigDecimal.ZERO;
    private BigDecimal ticketsAmount = BigDecimal.ZERO;
    /**
     * æœªæ¥ç¥¨æ•°
     */
    private BigDecimal futureTickets=BigDecimal.ZERO;
    private BigDecimal futureTickets = BigDecimal.ZERO;
    /**
     * æœªæ¥ç¥¨é‡‘额(元)
     */
    private BigDecimal futureTicketsAmount=BigDecimal.ZERO;
    private BigDecimal futureTicketsAmount = BigDecimal.ZERO;
    @ApiModelProperty(value = "开票数")
    private BigDecimal invoiceNum = BigDecimal.ZERO;
@@ -149,7 +150,7 @@
    private BigDecimal currentInvoiceAmount;
    /**
     *  äº§å“id
     * äº§å“id
     */
    private Long productId;
@@ -233,6 +234,46 @@
    @ApiModelProperty(value = "是否质检")
    private Boolean isChecked;
    @ApiModelProperty("宽")
    private BigDecimal width;
    @ApiModelProperty("高")
    private BigDecimal height;
    @ApiModelProperty("加工要求")
    private String processRequirement;
    @ApiModelProperty("备注")
    private String remark;
    /**
     * å®žé™…单片面积(㎡)
     */
    @ApiModelProperty("实际单片面积(㎡)")
    private BigDecimal actualPieceArea;
    /**
     * å®žé™…总面积(㎡)
     */
    @ApiModelProperty("实际总面积(㎡)")
    private BigDecimal actualTotalArea;
    /**
     * ç»“算单片面积(㎡)
     */
    @ApiModelProperty("结算单片面积(㎡)")
    private BigDecimal settlePieceArea;
    /**
     * ç»“算总面积(㎡)
     */
    @ApiModelProperty("结算总面积(㎡)")
    private BigDecimal settleTotalArea;
    @TableField(exist = false)
    @ApiModelProperty("销售产品额外加工")
    private List<SalesLedgerProductProcess> salesProductProcessList;
    @TableField(exist = false)
    private Integer hasSufficientStock;
src/main/java/com/ruoyi/sales/pojo/SalesLedgerProductProcess.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,53 @@
package com.ruoyi.sales.pojo;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
 * <p>
 * é”€å”®äº§å“åŠ å·¥æ˜Žç»†
 * </p>
 *
 * @author deslrey
 * @since 2026-03-25
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sales_ledger_product_process")
@ApiModel(value = "SalesLedgerProductProcess对象", description = "销售产品加工明细")
public class SalesLedgerProductProcess implements Serializable {
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @ApiModelProperty(value = "工艺名称")
    private String processName;
    @ApiModelProperty(value = "数量")
    private Integer quantity;
    @ApiModelProperty(value = "单价")
    private BigDecimal unitPrice;
    @ApiModelProperty(value = "编码")
    private String code;
    private LocalDateTime createTime;
}
src/main/java/com/ruoyi/sales/pojo/SalesLedgerProductProcessBind.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
package com.ruoyi.sales.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
 * <p>
 * é”€å”®äº§å“é¢å¤–加工数量
 * </p>
 *
 * @author deslrey
 * @since 2026-03-25
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sales_ledger_product_process_bind")
@ApiModel(value="SalesLedgerProductProcessBind对象", description="销售产品额外加工数量")
public class SalesLedgerProductProcessBind implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "主键")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @ApiModelProperty(value = "销售台账产品信息ID")
    private Integer salesLedgerProductId;
    @ApiModelProperty(value = "销售产品加工明细ID")
    private Integer salesLedgerProductProcessId;
    @ApiModelProperty(value = "加工数量")
    private Integer quantity;
}
src/main/java/com/ruoyi/sales/service/ISalesLedgerProductProcessBindService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.ruoyi.sales.service;
import com.ruoyi.sales.pojo.SalesLedgerProductProcessBind;
import com.baomidou.mybatisplus.extension.service.IService;
/**
 * <p>
 * é”€å”®äº§å“é¢å¤–加工数量 æœåŠ¡ç±»
 * </p>
 *
 * @author deslrey
 * @since 2026-03-25
 */
public interface ISalesLedgerProductProcessBindService extends IService<SalesLedgerProductProcessBind> {
}
src/main/java/com/ruoyi/sales/service/ISalesLedgerProductProcessService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.ruoyi.sales.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.sales.pojo.SalesLedgerProductProcess;
import com.baomidou.mybatisplus.extension.service.IService;
/**
 * <p>
 * é”€å”®äº§å“åŠ å·¥æ˜Žç»† æœåŠ¡ç±»
 * </p>
 *
 * @author deslrey
 * @since 2026-03-25
 */
public interface ISalesLedgerProductProcessService extends IService<SalesLedgerProductProcess> {
    Page<SalesLedgerProductProcess> salesLedgerProductProcessList(Page<SalesLedgerProductProcess> page, String name);
    void addProcess(SalesLedgerProductProcess process);
    void updateProcess(SalesLedgerProductProcess process);
    void deleteProcess(Integer id);
}
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductProcessBindServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package com.ruoyi.sales.service.impl;
import com.ruoyi.sales.pojo.SalesLedgerProductProcessBind;
import com.ruoyi.sales.mapper.SalesLedgerProductProcessBindMapper;
import com.ruoyi.sales.service.ISalesLedgerProductProcessBindService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
 * <p>
 * é”€å”®äº§å“é¢å¤–加工数量 æœåŠ¡å®žçŽ°ç±»
 * </p>
 *
 * @author deslrey
 * @since 2026-03-25
 */
@Service
public class SalesLedgerProductProcessBindServiceImpl extends ServiceImpl<SalesLedgerProductProcessBindMapper, SalesLedgerProductProcessBind> implements ISalesLedgerProductProcessBindService {
}
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductProcessServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,65 @@
package com.ruoyi.sales.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.sales.pojo.SalesLedgerProductProcess;
import com.ruoyi.sales.mapper.SalesLedgerProductProcessMapper;
import com.ruoyi.sales.service.ISalesLedgerProductProcessService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
/**
 * <p>
 * é”€å”®äº§å“åŠ å·¥æ˜Žç»† æœåŠ¡å®žçŽ°ç±»
 * </p>
 *
 * @author deslrey
 * @since 2026-03-25
 */
@Service
public class SalesLedgerProductProcessServiceImpl extends ServiceImpl<SalesLedgerProductProcessMapper, SalesLedgerProductProcess> implements ISalesLedgerProductProcessService {
    @Override
    public Page<SalesLedgerProductProcess> salesLedgerProductProcessList(Page<SalesLedgerProductProcess> page, String name) {
        LambdaQueryWrapper<SalesLedgerProductProcess> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(name)) {
            wrapper.like(SalesLedgerProductProcess::getProcessName, name);
        }
        return this.page(page, wrapper);
    }
    @Override
    public void addProcess(SalesLedgerProductProcess process) {
        checkDuplicate(process.getProcessName(), null, process.getProcessName());
        this.save(process);
    }
    @Override
    public void updateProcess(SalesLedgerProductProcess process) {
        checkDuplicate(process.getProcessName(), process.getId(), process.getProcessName());
        this.updateById(process);
    }
    @Override
    public void deleteProcess(Integer id) {
        this.removeById(id);
    }
    private void checkDuplicate(String processName, Integer excludeId, String code) {
        LambdaQueryWrapper<SalesLedgerProductProcess> wrapper = new LambdaQueryWrapper<>();
        wrapper.and(w -> w
                .eq(SalesLedgerProductProcess::getProcessName, processName)
                .or()
                .eq(SalesLedgerProductProcess::getCode, code));
        if (excludeId != null) {
            wrapper.ne(SalesLedgerProductProcess::getId, excludeId);
        }
        if (this.count(wrapper) > 0) {
            throw new RuntimeException("工序名称或编码已存在");
        }
    }
}
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -37,6 +37,8 @@
import com.ruoyi.sales.dto.*;
import com.ruoyi.sales.mapper.*;
import com.ruoyi.sales.pojo.*;
import com.ruoyi.sales.service.ISalesLedgerProductProcessBindService;
import com.ruoyi.sales.service.ISalesLedgerProductProcessService;
import com.ruoyi.sales.service.ISalesLedgerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -110,6 +112,11 @@
    private final ProductionProductInputMapper productionProductInputMapper;
    private final QualityInspectMapper qualityInspectMapper;
    private final RedisTemplate<String, String> redisTemplate;
    private final ISalesLedgerProductProcessService salesLedgerProductProcessService;
    private final ISalesLedgerProductProcessBindService salesLedgerProductProcessBindService;
    @Autowired
    private SysDeptMapper sysDeptMapper;
    @Value("${file.upload-dir}")
@@ -154,7 +161,7 @@
            // æŸ¥è¯¢é€€è´§ä¿¡æ¯
            List<Long> productIds = salesLedgerProducts.stream().map(SalesLedgerProduct::getId).collect(Collectors.toList());
            List<SimpleReturnOrderGroupDto> groupListByProductIds = new ArrayList<>();
            if(CollectionUtils.isNotEmpty(productIds)){
            if (CollectionUtils.isNotEmpty(productIds)) {
                groupListByProductIds = purchaseReturnOrderProductsMapper.getReturnOrderGroupListByProductIds(productIds);
            }
            Map<Long, BigDecimal> returnOrderGroupDtoMap = groupListByProductIds.stream().collect(Collectors.toMap(SimpleReturnOrderGroupDto::getSalesLedgerProductId, SimpleReturnOrderGroupDto::getSumReturnQuantity));
@@ -194,6 +201,23 @@
                    .last("limit 1"));
            if (shippingInfo != null) {
                product.setShippingStatus(shippingInfo.getStatus());
            }
            // åŠ å·¥æ˜Žç»†ï¼Œå…ˆæŸ¥bind表获取该产品关联的工序及数量
            List<SalesLedgerProductProcessBind> bindList = salesLedgerProductProcessBindService.list(
                    new LambdaQueryWrapper<SalesLedgerProductProcessBind>()
                            .eq(SalesLedgerProductProcessBind::getSalesLedgerProductId, product.getId()));
            if (!bindList.isEmpty()) {
                List<Integer> processIds = bindList.stream()
                        .map(SalesLedgerProductProcessBind::getSalesLedgerProductProcessId)
                        .collect(Collectors.toList());
                Map<Integer, Integer> processQuantityMap = bindList.stream()
                        .collect(Collectors.toMap(
                                SalesLedgerProductProcessBind::getSalesLedgerProductProcessId,
                                SalesLedgerProductProcessBind::getQuantity,
                                (a, b) -> a));
                List<SalesLedgerProductProcess> processList = salesLedgerProductProcessService.listByIds(processIds);
                processList.forEach(p -> p.setQuantity(processQuantityMap.get(p.getId())));
                product.setSalesProductProcessList(processList);
            }
        }
@@ -545,6 +569,9 @@
            salesLedgerProductMapper.deleteBatchIds(productIds);
        }
        //  æ¸…除产品的加工
        salesLedgerProductProcessBindService.remove(new LambdaQueryWrapper<SalesLedgerProductProcessBind>().in(SalesLedgerProductProcessBind::getSalesLedgerProductId, productIds));
        LambdaQueryWrapper<InvoiceRegistrationProduct> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(InvoiceRegistrationProduct::getSalesLedgerId, idList);
        List<InvoiceRegistrationProduct> invoiceRegistrationProducts = invoiceRegistrationProductMapper.selectList(wrapper);
@@ -727,6 +754,17 @@
            for (SalesLedgerProduct product : updateList) {
                product.setType(type.getCode());
                salesLedgerProductMapper.updateById(product);
                //  å®žçŽ°åˆ é™¤ç»‘å®šçš„å…¨éƒ¨åŠ å·¥
                salesLedgerProductProcessBindService.remove(new LambdaQueryWrapper<SalesLedgerProductProcessBind>().eq(SalesLedgerProductProcessBind::getSalesLedgerProductId, product.getId()));
                //  ç»‘定产品额外加工
                List<SalesLedgerProductProcess> salesProductProcessList = product.getSalesProductProcessList();
                salesProductProcessList.forEach(s -> {
                    SalesLedgerProductProcessBind processBind = new SalesLedgerProductProcessBind();
                    processBind.setSalesLedgerProductId(Math.toIntExact(product.getId()));
                    processBind.setSalesLedgerProductProcessId(s.getId());
                    processBind.setQuantity(s.getQuantity());
                    salesLedgerProductProcessBindService.save(processBind);
                });
            }
        }
        // æ‰§è¡Œæ’入操作
@@ -737,6 +775,15 @@
                salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
                salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
                salesLedgerProductMapper.insert(salesLedgerProduct);
                //  ç»‘定产品额外加工
                List<SalesLedgerProductProcess> salesProductProcessList = salesLedgerProduct.getSalesProductProcessList();
                salesProductProcessList.forEach(s -> {
                    SalesLedgerProductProcessBind processBind = new SalesLedgerProductProcessBind();
                    processBind.setSalesLedgerProductId(Math.toIntExact(salesLedgerProduct.getId()));
                    processBind.setSalesLedgerProductProcessId(s.getId());
                    processBind.setQuantity(s.getQuantity());
                    salesLedgerProductProcessBindService.save(processBind);
                });
                // æ·»åŠ ç”Ÿäº§æ•°æ®
                salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
            }
src/main/resources/application-hbtmblc.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,256 @@
# é¡¹ç›®ç›¸å…³é…ç½®
ruoyi:
  # åç§°
  name: RuoYi
  # ç‰ˆæœ¬
  version: 3.8.9
  # ç‰ˆæƒå¹´ä»½
  copyrightYear: 2025
  # æ–‡ä»¶è·¯å¾„ ç¤ºä¾‹ï¼ˆ Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
  profile: D:/ruoyi/uploadPath
  # èŽ·å–ip地址开关
  addressEnabled: false
  # éªŒè¯ç ç±»åž‹ math æ•°å­—计算 char å­—符验证
  captchaType: math
  # ååŒå®¡æ‰¹ç¼–号前缀(配置文件后缀命名)
  approvalNumberPrefix: DEV
  # ä¸ªæŽ¨ Unipush é…ç½®
  getui:
    appId: PfjyAAE0FK64FaO1w2CMb1
    appKey: zTMb831OEL6J4GK1uE3Ob4
    masterSecret: K1GFtsv42v61tXGnF7SGE5
    domain: https://restapi.getui.cn/v2/
    # ç¦»çº¿æŽ¨é€ä½¿ç”¨çš„包名/组件名
    intentComponent: uni.app.UNI099A590/io.dcloud.PandoraEntry
# å¼€å‘环境配置
server:
  # æœåŠ¡å™¨çš„HTTP端口,默认为8080
  port: 7003
  servlet:
    # åº”用的访问路径
    context-path: /
  tomcat:
    # tomcat的URI编码
    uri-encoding: UTF-8
    # è¿žæŽ¥æ•°æ»¡åŽçš„æŽ’队数,默认为100
    accept-count: 1000
    threads:
      # tomcat最大线程数,默认为200
      max: 800
      # Tomcat启动初始化的线程数,默认值10
      min-spare: 100
# æ—¥å¿—配置
logging:
  level:
    org.quartz: DEBUG
    com.ruoyi: warn
    org.springframework: warn
minio:
  endpoint: http://114.132.189.42/
  port: 7019
  secure: false
  accessKey: admin
  secretKey: 12345678
  preview-expiry: 24 # é¢„览地址默认24小时
  default-bucket: uploadPath
# ç”¨æˆ·é…ç½®
user:
  password:
    # å¯†ç æœ€å¤§é”™è¯¯æ¬¡æ•°
    maxRetryCount: 5
    # å¯†ç é”å®šæ—¶é—´ï¼ˆé»˜è®¤10分钟)
    lockTime: 10
# Spring配置
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    druid:
      # ä¸»åº“数据源
      master:
        url: jdbc:mysql://1.15.17.182:9999/product-inventory-management-hbtmblc?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        username: root
        password: xd@123456..
      # ä»Žåº“数据源
      slave:
        # ä»Žæ•°æ®æºå¼€å…³/默认关闭
        enabled: false
        url:
        username:
        password:
      # åˆå§‹è¿žæŽ¥æ•°
      initialSize: 5
      # æœ€å°è¿žæŽ¥æ± æ•°é‡
      minIdle: 10
      # æœ€å¤§è¿žæŽ¥æ± æ•°é‡
      maxActive: 20
      # é…ç½®èŽ·å–è¿žæŽ¥ç­‰å¾…è¶…æ—¶çš„æ—¶é—´
      maxWait: 60000
      # é…ç½®è¿žæŽ¥è¶…æ—¶æ—¶é—´
      connectTimeout: 30000
      # é…ç½®ç½‘络超时时间
      socketTimeout: 60000
      # é…ç½®é—´éš”多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      timeBetweenEvictionRunsMillis: 60000
      # é…ç½®ä¸€ä¸ªè¿žæŽ¥åœ¨æ± ä¸­æœ€å°ç”Ÿå­˜çš„æ—¶é—´ï¼Œå•位是毫秒
      minEvictableIdleTimeMillis: 300000
      # é…ç½®ä¸€ä¸ªè¿žæŽ¥åœ¨æ± ä¸­æœ€å¤§ç”Ÿå­˜çš„æ—¶é—´ï¼Œå•位是毫秒
      maxEvictableIdleTimeMillis: 900000
      # é…ç½®æ£€æµ‹è¿žæŽ¥æ˜¯å¦æœ‰æ•ˆ
      validationQuery: SELECT 1 FROM DUAL
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      webStatFilter:
        enabled: true
      statViewServlet:
        enabled: true
        # è®¾ç½®ç™½åå•,不填则允许所有访问
        allow:
        url-pattern: /druid/*
        # æŽ§åˆ¶å°ç®¡ç†ç”¨æˆ·åå’Œå¯†ç 
        login-username: ruoyi
        login-password: 123456
      filter:
        stat:
          enabled: true
          # æ…¢SQL记录
          log-slow-sql: true
          slow-sql-millis: 1000
          merge-sql: true
        wall:
          config:
            multi-statement-allow: true
  # èµ„源信息
  messages:
    # å›½é™…化资源文件路径
    basename: i18n/messages
  # æ–‡ä»¶ä¸Šä¼ 
  servlet:
    multipart:
      # å•个文件大小
      max-file-size: 1GB
      # è®¾ç½®æ€»ä¸Šä¼ çš„æ–‡ä»¶å¤§å°
      max-request-size: 2GB
  # æœåŠ¡æ¨¡å—
  devtools:
    restart:
      # çƒ­éƒ¨ç½²å¼€å…³
      enabled: false
  # redis é…ç½®
  redis:
    # åœ°å€
    host: 127.0.0.1
    #    host: 172.17.0.1
    # ç«¯å£ï¼Œé»˜è®¤ä¸º6379
    port: 6379
    # æ•°æ®åº“索引
    database: 0
    # å¯†ç 
    #    password: root2022!
    password:
    # è¿žæŽ¥è¶…æ—¶æ—¶é—´
    timeout: 10s
    lettuce:
      pool:
        # è¿žæŽ¥æ± ä¸­çš„æœ€å°ç©ºé—²è¿žæŽ¥
        min-idle: 0
        # è¿žæŽ¥æ± ä¸­çš„æœ€å¤§ç©ºé—²è¿žæŽ¥
        max-idle: 8
        # è¿žæŽ¥æ± çš„æœ€å¤§æ•°æ®åº“连接数
        max-active: 8
        # #连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms
  # Quartz定时任务配置(新增部分)
  quartz:
    job-store-type: jdbc  # ä½¿ç”¨æ•°æ®åº“存储
    jdbc:
      initialize-schema: never  # é¦–次运行时自动创建表结构,成功后改为never
      schema: classpath:org/quartz/impl/jdbcjobstore/tables_mysql_innodb.sql  # MySQL表结构脚本
    properties:
      org:
        quartz:
          scheduler:
            instanceName: RuoYiScheduler
            instanceId: AUTO
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate  # MySQL适配
            tablePrefix: qrtz_  # è¡¨åå‰ç¼€ï¼Œä¸Žè„šæœ¬ä¸€è‡´
            isClustered: false  # å•节点模式(集群需改为true)
            clusterCheckinInterval: 10000
            txIsolationLevelSerializable: true
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            threadCount: 10  # çº¿ç¨‹æ± å¤§å°
            threadPriority: 5
            makeThreadsDaemons: true
          updateCheck: false  # å…³é—­ç‰ˆæœ¬æ£€æŸ¥
# token配置
token:
  # ä»¤ç‰Œè‡ªå®šä¹‰æ ‡è¯†
  header: Authorization
  # ä»¤ç‰Œå¯†é’¥
  secret: abcdefghijklmnopqrstuvwxyz
  # ä»¤ç‰Œæœ‰æ•ˆæœŸï¼ˆé»˜è®¤30分钟)
  expireTime: 450
# MyBatis Plus配置
mybatis-plus:
  # æœç´¢æŒ‡å®šåŒ…别名   æ ¹æ®è‡ªå·±çš„项目来
  typeAliasesPackage: com.ruoyi.**.pojo
  # é…ç½®mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath*:mapper/**/*Mapper.xml
  # åŠ è½½å…¨å±€çš„é…ç½®æ–‡ä»¶
  configLocation: classpath:mybatis/mybatis-config.xml
  global-config:
    enable-sql-runner: true
    db-config:
      id-type: auto
# PageHelper分页插件
pagehelper:
  helperDialect: mysql
  supportMethodsArguments: true
  params: count=countSql
# Swagger配置
swagger:
  # æ˜¯å¦å¼€å¯swagger
  enabled: true
  # è¯·æ±‚前缀
  pathMapping: /dev-api
# é˜²æ­¢XSS攻击
xss:
  # è¿‡æ»¤å¼€å…³
  enabled: true
  # æŽ’除链接(多个用逗号分隔)
  excludes: /system/notice
  # åŒ¹é…é“¾æŽ¥
  urlPatterns: /system/*,/monitor/*,/tool/*
# ä»£ç ç”Ÿæˆ
gen:
  # ä½œè€…
  author: ruoyi
  # é»˜è®¤ç”ŸæˆåŒ…路径 system éœ€æ”¹æˆè‡ªå·±çš„æ¨¡å—名称 å¦‚ system monitor tool
  packageName: com.ruoyi.project.system
  # è‡ªåŠ¨åŽ»é™¤è¡¨å‰ç¼€ï¼Œé»˜è®¤æ˜¯true
  autoRemovePre: false
  # è¡¨å‰ç¼€ï¼ˆç”Ÿæˆç±»åä¸ä¼šåŒ…含表前缀,多个用逗号分隔)
  tablePrefix: sys_
  # æ˜¯å¦å…è®¸ç”Ÿæˆæ–‡ä»¶è¦†ç›–到本地(自定义路径),默认不允许
  allowOverwrite: false
file:
  temp-dir: D:/ruoyi/temp/uploads   # ä¸´æ—¶ç›®å½•
  upload-dir: D:/ruoyi/prod/uploads # æ­£å¼ç›®å½•
src/main/resources/mapper/sales/SalesLedgerProductProcessBindMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.sales.mapper.SalesLedgerProductProcessBindMapper">
    <!-- é€šç”¨æŸ¥è¯¢æ˜ å°„结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.sales.pojo.SalesLedgerProductProcessBind">
        <id column="id" property="id" />
        <result column="sales_ledger_product_id" property="salesLedgerProductId" />
        <result column="sales_ledger_product_process_id" property="salesLedgerProductProcessId" />
        <result column="quantity" property="quantity" />
    </resultMap>
</mapper>
src/main/resources/mapper/sales/SalesLedgerProductProcessMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.sales.mapper.SalesLedgerProductProcessMapper">
    <!-- é€šç”¨æŸ¥è¯¢æ˜ å°„结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.sales.pojo.SalesLedgerProductProcess">
        <id column="id" property="id"/>
        <result column="process_name" property="processName"/>
        <result column="quantity" property="quantity"/>
        <result column="unit_price" property="unitPrice"/>
        <result column="code" property="code"/>
        <result column="create_time" property="createTime"/>
    </resultMap>
</mapper>