已添加1个文件
已修改16个文件
189 ■■■■ 文件已修改
doc/20260113-product_model.sql 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/controller/ProductController.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/mapper/ProductModelMapper.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/ProductModel.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDtoCopy.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/mapper/ProcurementRecordMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordServiceImpl.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProcessRouteController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProcessRoute.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProcessRouteService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProcessRouteServiceImpl.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/InvoiceRegistrationServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/basic/ProductModelMapper.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/procurementrecord/ProcurementRecordMapper.xml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/20260113-product_model.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,6 @@
alter table product_model
    add product_code varchar(255)  null comment '产品编码';
alter table process_route
    add process_route_code varchar(255)  null comment '工艺路线编码';
src/main/java/com/ruoyi/basic/controller/ProductController.java
@@ -1,5 +1,6 @@
package com.ruoyi.basic.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.basic.dto.ProductDto;
@@ -12,9 +13,13 @@
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.sales.service.ISalesLedgerProductService;
import com.ruoyi.sales.service.ISalesLedgerService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@@ -28,8 +33,8 @@
    private IProductService productService;
    private IProductModelService productModelService;
    @Autowired
    private ISalesLedgerProductService salesLedgerProductService;
    /**
     * æŸ¥è¯¢äº§å“
     */
@@ -73,6 +78,13 @@
        if (ids == null || ids.length == 0) {
            return AjaxResult.error("请传入要删除的ID");
        }
        // æ£€æŸ¥æ˜¯å¦æœ‰é”€å”®å•†å“è®°å½•关联该产品
        LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(SalesLedgerProduct::getProductId, ids);
        List<SalesLedgerProduct> salesLedgerProductList = salesLedgerProductService.list(queryWrapper);
        if (salesLedgerProductList.size() > 0) {
            return AjaxResult.error("该产品存在销售/采购记录,不能删除");
        }
        return toAjax(productService.delProductByIds(ids));
    }
@@ -85,6 +97,13 @@
        if (ids == null || ids.length == 0) {
            return AjaxResult.error("请传入要删除的ID");
        }
        // æ£€æŸ¥æ˜¯å¦æœ‰é”€å”®å•†å“è®°å½•关联该产品规格型号
        LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(SalesLedgerProduct::getProductModelId, ids);
        List<SalesLedgerProduct> salesLedgerProductList = salesLedgerProductService.list(queryWrapper);
        if (salesLedgerProductList.size() > 0) {
            return AjaxResult.error("该产品规格型号存在销售/采购记录,不能删除");
        }
        return toAjax(productModelService.delProductModel(ids));
    }
src/main/java/com/ruoyi/basic/mapper/ProductModelMapper.java
@@ -16,4 +16,7 @@
public interface ProductModelMapper extends BaseMapper<ProductModel> {
    IPage<ProductModel> listPageProductModel(Page<ProductModel> page, @Param("c") ProductModel productModel);
    ProductModel selectLatestRecord();
}
src/main/java/com/ruoyi/basic/pojo/ProductModel.java
@@ -27,6 +27,9 @@
    @Excel(name = "产品名称")
    private String productName;
    @Excel(name = "产品编码")
    private String productCode;
    /**
     * è§„格型号
     */
src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
@@ -14,12 +14,15 @@
import com.ruoyi.basic.service.IProductModelService;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -45,12 +48,21 @@
        if (productModelDto.getId() == null) {
            ProductModel productModel = new ProductModel();
            BeanUtils.copyProperties(productModelDto,productModel);
            return productModelMapper.insert(productModel);
            productModelMapper.insert(productModel);
            String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            String idStr = String.format("%06d", productModel.getId()); // å…­ä½è¡¥0
            String newProductCode = "BM" + dateStr + idStr;
            // æ›´æ–°æ•°æ®åº“中的productCode
            productModel.setProductCode(newProductCode);
            return productModelMapper.updateById(productModel);
        } else {
            return productModelMapper.updateById(productModelDto);
        }
    }
    @Override
    public int delProductModel(Long[] ids) {
        List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(new QueryWrapper<SalesLedgerProduct>()
src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDtoCopy.java
@@ -49,7 +49,7 @@
     */
    private String customerName;
    private String salesLedgerProductId;
    private Long salesLedgerProductId;
    /**
     * å‡ºå…¥åº“数量
src/main/java/com/ruoyi/procurementrecord/mapper/ProcurementRecordMapper.java
@@ -39,4 +39,6 @@
    IPage<ProcurementPageDto> listPageByProduction(Page page, @Param("req") ProcurementPageDto procurementDto);
    IPage<ProcurementPageDtoCopy> listPageCopyByProduction(Page page, @Param("req") ProcurementPageDto procurementDto);
    IPage<ProcurementPageDtoCopy> listPagePRS(Page page, @Param("req") ProcurementPageDto procurementDto);
}
src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordServiceImpl.java
@@ -593,7 +593,7 @@
    @Override
    public IPage<ProcurementPageDtoCopy> listPageCopyByProduction(Page page, ProcurementPageDto procurementDto) {
        IPage<ProcurementPageDtoCopy> procurementPageDtoCopyIPage = procurementRecordMapper.listPageCopyByProduction(page, procurementDto);
        IPage<ProcurementPageDtoCopy> procurementPageDtoCopyIPage = procurementRecordMapper.listPagePRS(page, procurementDto);
        List<ProcurementPageDtoCopy> procurementPageDtoCopyList = procurementPageDtoCopyIPage.getRecords();
        // è®¡ç®—待入库数量
        // æŸ¥è¯¢é‡‡è´­è®°å½•已入库数量
@@ -601,38 +601,48 @@
        if(CollectionUtils.isEmpty( collect)){
            return procurementPageDtoCopyIPage;
        }
        LambdaQueryWrapper<ProcurementRecordOut> procurementRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        procurementRecordLambdaQueryWrapper.in(ProcurementRecordOut::getProcurementRecordStorageId, collect);
        procurementRecordLambdaQueryWrapper.eq(ProcurementRecordOut::getType, 2);
        List<ProcurementRecordOut> procurementRecords = procurementRecordOutMapper.selectList(procurementRecordLambdaQueryWrapper);
        if(CollectionUtils.isEmpty( procurementRecords)){
            return procurementPageDtoCopyIPage;
        }
        // 1. æŸ¥è¯¢é‡‡è´­è®°å½•已入库的出库记录(按storageId分组)
        LambdaQueryWrapper<ProcurementRecordOut> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(ProcurementRecordOut::getProcurementRecordStorageId, collect);
        List<ProcurementRecordOut> recordOutList = procurementRecordOutMapper.selectList(queryWrapper);
        // 2. æŒ‰SalesLedgerProductId分组,统计每个id对应的已出库数量总和-已出库数量
        Map<Integer, BigDecimal> storageIdToTotalOutNumMap = recordOutList.stream()
                .collect(Collectors.groupingBy(
                        ProcurementRecordOut::getSalesLedgerProductId,
                        Collectors.reducing(
                                BigDecimal.ZERO,
                                ProcurementRecordOut::getInboundNum,
                                (a, b) -> a.add(b == null ? BigDecimal.ZERO : b)
                        )
                ));
        // 2. procurementPageDtoCopyList按SalesLedgerProductId分组,统计每个id对应的已出库数量总和-入库库数量
        Map<Long, BigDecimal> storageIdToTotalintNumMap = procurementPageDtoCopyList.stream()
                .collect(Collectors.groupingBy(
                        ProcurementPageDtoCopy::getSalesLedgerProductId,
                        Collectors.reducing(
                                BigDecimal.ZERO,
                                ProcurementPageDtoCopy::getInboundNum,
                                (a, b) -> a.add(b == null ? BigDecimal.ZERO : b)
                        )
                ));
        // 3. å¾ªçŽ¯ç»™dto赋值
        for (ProcurementPageDtoCopy dto : procurementPageDtoCopyList) {
            // æ ¹æ®é‡‡è´­å°è´¦ID筛选对应的出库记录
            List<ProcurementRecordOut> collect1 = procurementRecords.stream()
                    .filter(ProcurementRecordOut -> ProcurementRecordOut.getProcurementRecordStorageId().equals(dto.getId()))
                    .collect(Collectors.toList());
            // å¦‚果没有相关的出库记录,跳过该条数据
            if(CollectionUtils.isEmpty(collect1)){
                dto.setInboundNum0(dto.getInboundNum());
                dto.setTotalInboundNum(BigDecimal.ZERO);
                continue;
            }
            // è®¡ç®—已出库数量总和,并设置待出库数量
            BigDecimal totalInboundNum = collect1.stream()
                    .map(ProcurementRecordOut::getInboundNum)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            // å‡ºåº“数量 = æ€»æ•°é‡ - å¾…出库数量
            Integer storageId = dto.getId();
            Integer salesLedgerProductId = Integer.valueOf(Math.toIntExact(dto.getSalesLedgerProductId()));
            // èŽ·å–å½“å‰salesLedgerProductId对应的已出库总数(默认0)
            BigDecimal totalInboundNum = storageIdToTotalOutNumMap.getOrDefault(salesLedgerProductId, BigDecimal.ZERO);
            // å·²å‡ºåº“数量
            dto.setTotalInboundNum(totalInboundNum);
            // å¾…出库数量 = æ€»æ•°é‡ - å·²å‡ºåº“数量
            dto.setInboundNum0(dto.getInboundNum().subtract(totalInboundNum));
            // åº“存价值
            if(dto.getUnitPrice() != null){
                dto.setTotalPrice(dto.getTotalInboundNum().multiply(dto.getUnitPrice()));
            }
            // å¾…出库数量 = æ€»æ•°é‡ - å·²å‡ºåº“数量(总数量空值则默认0)
//            BigDecimal totalNum = dto.getInboundNum() == null ? BigDecimal.ZERO : dto.getInboundNum();
            BigDecimal totalNum = storageIdToTotalintNumMap.getOrDefault(salesLedgerProductId, BigDecimal.ZERO);
            dto.setInboundNum(totalNum);
            dto.setInboundNum0(totalNum.subtract(totalInboundNum));
            // åº“存价值 = å·²å‡ºåº“数量 * å•价(单价空值则默认0)
            BigDecimal unitPrice = dto.getUnitPrice() == null ? BigDecimal.ZERO : dto.getUnitPrice();
            dto.setTotalPrice(totalInboundNum.multiply(unitPrice));
        }
        return procurementPageDtoCopyIPage;
    }
src/main/java/com/ruoyi/production/controller/ProcessRouteController.java
@@ -29,7 +29,7 @@
    @ApiOperation("新增工艺路线")
    @PostMapping ()
    public R add(@RequestBody  ProcessRoute processRoute) {
        return R.ok(processRouteService.save(processRoute));
        return R.ok(processRouteService.saveProcessRoute(processRoute));
    }
    @ApiOperation("修改工艺路线")
    @PutMapping ()
src/main/java/com/ruoyi/production/pojo/ProcessRoute.java
@@ -32,4 +32,7 @@
    @ApiModelProperty(value = "更新时间")
    @TableField(fill = FieldFill.UPDATE)
    private LocalDateTime updateTime;
    @ApiModelProperty(value = "工艺路线编码")
    private String processRouteCode;
}
src/main/java/com/ruoyi/production/service/ProcessRouteService.java
@@ -5,8 +5,11 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.production.dto.ProcessRouteDto;
import com.ruoyi.production.pojo.ProcessRoute;
import io.swagger.models.auth.In;
public interface ProcessRouteService extends IService<ProcessRoute> {
    IPage<ProcessRouteDto> pageProcessRouteDto(Page<ProcessRouteDto> page, ProcessRouteDto processRouteDto);
    Integer saveProcessRoute(ProcessRoute processRoute);
}
src/main/java/com/ruoyi/production/service/impl/ProcessRouteServiceImpl.java
@@ -13,6 +13,9 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
@Service
@AllArgsConstructor
@Slf4j
@@ -26,4 +29,15 @@
        return processRouteMapper.pageProcessRouteDto(page, processRouteDto);
    }
    @Override
    public Integer saveProcessRoute(ProcessRoute processRoute) {
        this.save(processRoute);
        String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String idStr = String.format("%06d", processRoute.getId());
        String newProductCode = "GY" + dateStr + idStr;
        // æ›´æ–°æ•°æ®åº“中的productCode
        processRoute.setProcessRouteCode(newProductCode);
        return processRouteMapper.updateById(processRoute);
    }
}
src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java
@@ -52,10 +52,12 @@
            procurementDto.setSalesLedgerProductId(item.getId());
            procurementDto.setProductCategory(item.getProductCategory());
            IPage<ProcurementPageDtoCopy> result = procurementRecordService.listPageCopyByProduction(new Page<>(1,-1), procurementDto);
            ProcurementPageDtoCopy procurementDtoCopy = result.getRecords().get(0);
            if(item.getQuantity().compareTo(procurementDtoCopy.getInboundNum0())>=0){
                item.setApproveStatus(1);
                salesLedgerProductService.addOrUpdateSalesLedgerProduct(item);
            if(result.getRecords().size()>0) {
                ProcurementPageDtoCopy procurementDtoCopy = result.getRecords().get(0);
                if (item.getQuantity().compareTo(procurementDtoCopy.getInboundNum0()) >= 0) {
                    item.setApproveStatus(1);
                    salesLedgerProductService.addOrUpdateSalesLedgerProduct(item);
                }
            }
        });
        return AjaxResult.success(list);
src/main/java/com/ruoyi/sales/service/impl/InvoiceRegistrationServiceImpl.java
@@ -78,6 +78,8 @@
                invoiceRegistrationProduct.setSalesLedgerProductId(productDatum.getId().intValue());
                invoiceRegistrationProductMapper.insert(invoiceRegistrationProduct);
                productDatum.setInvoiceNum(currentInvoiceNum);
                productDatum.setInvoiceAmount(productDatum.getCurrentInvoiceAmount());
                salesLedgerProductMapper.updateById(productDatum);
                // æ–°å¢žä¸€æ¡å¼€ç¥¨å°è´¦æ•°æ®
                InvoiceLedger invoiceLedger = new InvoiceLedger();
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -70,6 +70,7 @@
//                .eq(SalesLedgerProduct::getType, salesLedgerProduct.getType());
        List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectSalesLedgerProductList(salesLedgerProduct);
        if(!CollectionUtils.isEmpty(salesLedgerProducts)){
            // å¼€ç¥¨
            InvoiceRegistrationProductDto invoiceRegistrationProductDto = new InvoiceRegistrationProductDto();
            invoiceRegistrationProductDto.setSalesLedgerId(salesLedgerProduct.getSalesLedgerId().intValue());
            List<InvoiceRegistrationProductDto> invoiceRegistrationProductDtoList = invoiceRegistrationProductMapper.invoiceRegistrationProductList(invoiceRegistrationProductDto);
@@ -78,14 +79,20 @@
                for (SalesLedgerProduct ledgerProduct : salesLedgerProducts) {
                    BigDecimal invoiceNum = BigDecimal.ZERO;
                    BigDecimal invoiceAmount = BigDecimal.ZERO;
                    BigDecimal noInvoiceNum = BigDecimal.ZERO;
                    BigDecimal noInvoiceAmount = BigDecimal.ZERO;
                    for (InvoiceRegistrationProductDto registrationProductDto : invoiceRegistrationProductDtoList) {
                        if(ledgerProduct.getId().intValue() == registrationProductDto.getSalesLedgerProductId()){
                            invoiceNum =  invoiceNum.add(registrationProductDto.getInvoiceNum());
                            invoiceAmount = invoiceAmount.add(registrationProductDto.getInvoiceAmount());
                            noInvoiceNum = ledgerProduct.getQuantity().subtract(invoiceNum);
                            noInvoiceAmount = ledgerProduct.getTaxInclusiveTotalPrice().subtract(invoiceAmount);
                        }
                    }
                    ledgerProduct.setInvoiceNum(invoiceNum);
                    ledgerProduct.setInvoiceAmount(invoiceAmount);
                    ledgerProduct.setNoInvoiceNum(noInvoiceNum);
                    ledgerProduct.setNoInvoiceAmount(noInvoiceAmount);
                }
            }
src/main/resources/mapper/basic/ProductModelMapper.xml
@@ -13,6 +13,7 @@
        <result column="tenant_id" property="tenantId" />
        <result column="product_name" property="productName" />
        <result column="product_id" property="productId" />
        <result column="product_code" property="productCode" />
    </resultMap>
    <select id="listPageProductModel" resultType="com.ruoyi.basic.pojo.ProductModel">
        select pm.*,p.product_name
@@ -28,6 +29,11 @@
        </where>
        order by  pm.id
    </select>
    <select id="selectLatestRecord" resultType="com.ruoyi.basic.pojo.ProductModel">
            SELECT * FROM product_model
            ORDER BY create_time DESC, id DESC
            LIMIT 1
    </select>
</mapper>
src/main/resources/mapper/procurementrecord/ProcurementRecordMapper.xml
@@ -336,4 +336,21 @@
        group by t2.product_category,t2.specification_model,t1.unit_price
        order by t1.create_time desc
    </select>
    <select id="listPagePRS" resultType="com.ruoyi.procurementrecord.dto.ProcurementPageDtoCopy">
        select *
        from  procurement_record_storage t1
        left join sales_ledger_product t2 on t2.id = t1.sales_ledger_product_id
          <where>
              1=1
              <if test="req.productCategory != null and req.productCategory != ''">
                  and t2.product_category like  concat('%',#{req.productCategory},'%')
              </if>
              <if test="req.timeStr != null and req.timeStr != ''">
                  and t1.create_time like  concat('%',#{req.timeStr},'%')
              </if>
              <if test="req.salesLedgerProductId != null and req.salesLedgerProductId != ''">
                  and t1.sales_ledger_product_id = #{req.salesLedgerProductId}
              </if>
          </where>
    </select>
</mapper>