zss
8 天以前 e620584c3286579a7f89ff73d227f58d721d6798
Merge branch 'jtwy' into dev_New
已添加1个文件
已修改14个文件
295 ■■■■ 文件已修改
src/main/java/com/ruoyi/basic/mapper/ProductModelMapper.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/ProductModel.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/controller/HomeController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/dto/ProductionProgressDto.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/dto/ProductionTurnoverDto.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/service/HomeService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordServiceImpl.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/ProductWorkOrderMapper.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/basic/ProductModelMapper.xml 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductOrderMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductWorkOrderMapper.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/mapper/ProductModelMapper.java
@@ -4,6 +4,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.procurementrecord.dto.ProcurementPageDto;
import org.apache.ibatis.annotations.Param;
@@ -17,6 +18,8 @@
    IPage<ProductModel> listPageProductModel(Page<ProductModel> page, @Param("c") ProductModel productModel);
    IPage<ProductModel> listPageProductionStock(Page<ProductModel> page, @Param("req") ProcurementPageDto req);
    ProductModel selectLatestRecord();
}
src/main/java/com/ruoyi/basic/pojo/ProductModel.java
@@ -6,6 +6,7 @@
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@TableName("product_model")
@@ -59,4 +60,7 @@
    @TableField(exist = false)
    @Excel(name = "剩余库存")
    private BigDecimal stockQuantity;
    @TableField(exist = false)
    private LocalDateTime createTime;
}
src/main/java/com/ruoyi/home/controller/HomeController.java
@@ -99,7 +99,7 @@
    @GetMapping("/workInProcessTurnover")
    @ApiOperation("在制品周转情况")
    public AjaxResult workInProcessTurnover(){
        Map<Integer, List<ProductWorkOrderDto>> productWorkOrderDtoMap = homeService.workInProcessTurnover();
        return AjaxResult.success(productWorkOrderDtoMap);
        ProductionTurnoverDto productionTurnoverDto = homeService.workInProcessTurnover();
        return AjaxResult.success(productionTurnoverDto);
    }
}
src/main/java/com/ruoyi/home/dto/ProductionProgressDto.java
@@ -12,14 +12,14 @@
@ApiModel
public class ProductionProgressDto {
    @ApiModelProperty("总订单数")
    private Integer totalOrderCount;
    private Long totalOrderCount;
    @ApiModelProperty("已完成订单数")
    private Integer completedOrderCount;
    private Long completedOrderCount;
    @ApiModelProperty("未完成订单数")
    private Integer uncompletedOrderCount;
    @ApiModelProperty("总体完成进度")
    private BigDecimal completedProgressCount;
    private Long uncompletedOrderCount;
    @ApiModelProperty("部分完成订单数")
    private Long partialCompletedOrderCount;
    @ApiModelProperty("订单详情")
    private List<ProductOrderDto> completedOrderDetails;
}
src/main/java/com/ruoyi/home/dto/ProductionTurnoverDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
package com.ruoyi.home.dto;
import com.ruoyi.production.dto.ProductOrderDto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
@ApiModel
public class ProductionTurnoverDto {
    @ApiModelProperty("总在制数量")
    private Long totalOrderCount;
    @ApiModelProperty("平均周转天数")
    private BigDecimal averageTurnoverDays;
    @ApiModelProperty("周转效率")
    private BigDecimal turnoverEfficiency;
    @ApiModelProperty("工序详情")
    private List<String> processDetails;
    @ApiModelProperty("工序对应的数量详情")
    private List<Long> processQuantityDetails;
}
src/main/java/com/ruoyi/home/service/HomeService.java
@@ -31,6 +31,6 @@
    Long noticesCount();
     ProductionProgressDto productionProgress();
     Map<Integer, List<ProductWorkOrderDto>> workInProcessTurnover();
    ProductionProgressDto productionProgress();
    ProductionTurnoverDto workInProcessTurnover();
}
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -2,9 +2,12 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.approve.mapper.ApproveProcessMapper;
import com.ruoyi.approve.pojo.ApproveProcess;
import com.ruoyi.basic.mapper.ProductModelMapper;
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.collaborativeApproval.mapper.NoticeMapper;
import com.ruoyi.collaborativeApproval.pojo.Notice;
import com.ruoyi.common.utils.SecurityUtils;
@@ -24,13 +27,16 @@
import com.ruoyi.procurementrecord.pojo.CustomStorage;
import com.ruoyi.procurementrecord.pojo.ProcurementRecordOut;
import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.production.dto.ProductOrderDto;
import com.ruoyi.production.dto.ProductWorkOrderDto;
import com.ruoyi.production.dto.ProductionProductMainDto;
import com.ruoyi.production.mapper.ProductOrderMapper;
import com.ruoyi.production.mapper.ProductProcessMapper;
import com.ruoyi.production.mapper.ProductWorkOrderMapper;
import com.ruoyi.production.mapper.ProductionProductMainMapper;
import com.ruoyi.production.pojo.ProductOrder;
import com.ruoyi.production.pojo.ProductProcess;
import com.ruoyi.production.pojo.ProductWorkOrder;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.mapper.SysDeptMapper;
@@ -57,6 +63,7 @@
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
@@ -111,10 +118,13 @@
    @Autowired
    private ProductOrderMapper productOrderMapper;
    @Autowired
    private ProductionProductMainMapper productionProductMainMapper;
    private ProductProcessMapper productProcessMapper;
    @Autowired
    private ProductWorkOrderMapper productWorkOrderMapper;
    @Autowired
    private ProductModelMapper productModelMapper;
    @Autowired
    private StockUtils stockUtils;
    @Override
    public HomeBusinessDto business() {
        // æž„建结果
@@ -167,23 +177,35 @@
            homeBusinessDto.setMonthPurchaseHaveMoney(unReceiptPaymentAmount.setScale(2, RoundingMode.HALF_UP).toString());
        }
        // ç»Ÿè®¡åº“å­˜
        List<ProcurementRecordStorage> procurementRecordStorages = procurementRecordStorageMapper.selectList(null);
        BigDecimal stockAmount = procurementRecordStorages.stream()
                .map(ProcurementRecordStorage::getInboundNum)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        // è‡ªå®šä¹‰åº“å­˜
        List<CustomStorage> customStorages = customStorageMapper.selectList(null);
        BigDecimal customStockAmount = customStorages.stream()
                .map(CustomStorage::getInboundNum)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        List<ProcurementRecordOut> procurementRecordOuts = procurementRecordOutMapper.selectList(null);
        BigDecimal outboundAmount = procurementRecordOuts.stream()
                .map(ProcurementRecordOut::getInboundNum)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal stock = stockAmount.add(customStockAmount).subtract(outboundAmount);
//        List<ProcurementRecordStorage> procurementRecordStorages = procurementRecordStorageMapper.selectList(null);
//        BigDecimal stockAmount = procurementRecordStorages.stream()
//                .map(ProcurementRecordStorage::getInboundNum)
//                .filter(Objects::nonNull)
//                .reduce(BigDecimal.ZERO, BigDecimal::add);
//        // è‡ªå®šä¹‰åº“å­˜
//        List<CustomStorage> customStorages = customStorageMapper.selectList(null);
//        BigDecimal customStockAmount = customStorages.stream()
//                .map(CustomStorage::getInboundNum)
//                .filter(Objects::nonNull)
//                .reduce(BigDecimal.ZERO, BigDecimal::add);
//        List<ProcurementRecordOut> procurementRecordOuts = procurementRecordOutMapper.selectList(null);
//        BigDecimal outboundAmount = procurementRecordOuts.stream()
//                .map(ProcurementRecordOut::getInboundNum)
//                .filter(Objects::nonNull)
//                .reduce(BigDecimal.ZERO, BigDecimal::add);
//        BigDecimal stock = stockAmount.add(customStockAmount).subtract(outboundAmount);
        IPage<ProductModel> productModelIPage = productModelMapper.listPageProductModel(new Page<>(1, -1), new ProductModel());
        if(!CollectionUtils.isEmpty(productModelIPage.getRecords())){
            //获取规格id
            List<Long> modelIds = productModelIPage.getRecords().stream().map(ProductModel::getId).collect(Collectors.toList());
            BigDecimal stockQuantityTotal = modelIds.stream()
                    .map(stockUtils::getStockQuantity)
                    .map(map -> map.get("stockQuantity"))
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            homeBusinessDto.setInventoryNum(stockQuantityTotal.setScale(2, RoundingMode.HALF_UP).toString());
        }
        // èŽ·å–å½“å¤©å…¥åº“æ•°é‡
        LambdaQueryWrapper<ProcurementRecordStorage> procurementRecordStorageLambdaQueryWrapper = new LambdaQueryWrapper<>();
        procurementRecordStorageLambdaQueryWrapper.ge(ProcurementRecordStorage::getCreateTime, now)  // å¤§äºŽç­‰äºŽå½“天
@@ -193,7 +215,7 @@
                .map(ProcurementRecordStorage::getInboundNum)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        homeBusinessDto.setInventoryNum(stock.setScale(2, RoundingMode.HALF_UP).toString());
//        homeBusinessDto.setInventoryNum(stock.setScale(2, RoundingMode.HALF_UP).toString());
        homeBusinessDto.setTodayInventoryNum(stockAmount1.setScale(2, RoundingMode.HALF_UP).toString());
        return homeBusinessDto;
    }
@@ -510,37 +532,55 @@
    @Override
    public ProductionProgressDto productionProgress() {
        ProductionProgressDto productionProgressDto = new ProductionProgressDto();
        List<ProductOrder> productOrderList = productOrderMapper.selectList(new LambdaQueryWrapper<ProductOrder>());
        List<ProductOrderDto> productOrderDtoList = new ArrayList<>();
        productOrderList.forEach(productOrder -> {
            ProductOrderDto productOrderDto = productOrderMapper.productMainByOrderId(productOrder);
//            if (productOrderDto != null && productOrderDto.getPlanQuantity() != null && productOrderDto.getQuantity() != null) {
//                productOrderDto.setCompletionStatus((productOrderDto.getPlanQuantity().subtract(productOrderDto.getQuantity())).divide(productOrderDto.getPlanQuantity(), 2, RoundingMode.HALF_UP));
//            }
            productOrderDtoList.add(productOrderDto);
        });
        productionProgressDto.setCompletedOrderDetails(productOrderDtoList);
        // 1. æŸ¥è¯¢æ‰€æœ‰ç”Ÿäº§è®¢å•(可根据需求添加过滤条件,如排除已删除、已取消的订单)
        IPage<ProductOrderDto> productOrderDtoIPage = productOrderMapper.pageProductOrder(new Page<>(1, -1), new ProductOrderDto());
        // 2. åˆå§‹åŒ–汇总数据
        int totalCount = productOrderDtoIPage.getRecords().size();
        int completedCount = (int) productOrderDtoIPage.getRecords().stream().map(productOrderDto -> productOrderMapper.productMainByOrderId(productOrderDto)).filter(productOrderDto1 -> productOrderDto1.getQuantity() != null && productOrderDto1.getQuantity().compareTo(BigDecimal.ZERO) == 0).count();
        // 6. èµ‹å€¼æ±‡æ€»æ•°æ®
        ProductOrderDto orderDto = new ProductOrderDto();
        orderDto.setStartTime(LocalDateTime.now().minusMonths(1));
        orderDto.setEndTime(LocalDateTime.now());
        List<ProductOrderDto> productOrderDtos = productOrderMapper.pageProductOrder(new Page<>(1, -1), orderDto).getRecords();
        productionProgressDto.setCompletedOrderDetails(productOrderDtos);
        long totalCount = productOrderDtos.size();
        long count = productOrderDtos.stream().filter(productOrderDto -> productOrderDto.getCompleteQuantity().compareTo(productOrderDto.getQuantity()) >= 0).count();
        long count2 = productOrderDtos.stream().filter(productOrderDto -> productOrderDto.getCompleteQuantity().compareTo(BigDecimal.ZERO) == 0).count();
        productionProgressDto.setTotalOrderCount(totalCount);
        productionProgressDto.setCompletedOrderCount(completedCount);
        productionProgressDto.setUncompletedOrderCount(totalCount - completedCount);
        productionProgressDto.setCompletedProgressCount(BigDecimal.valueOf(completedCount).divide(BigDecimal.valueOf(totalCount), 2, RoundingMode.HALF_UP));
        productionProgressDto.setCompletedOrderCount(count);
        productionProgressDto.setUncompletedOrderCount(count2);
        productionProgressDto.setPartialCompletedOrderCount(totalCount-count-count2);
        return productionProgressDto;
    }
    @Override
    public Map<Integer, List<ProductWorkOrderDto>> workInProcessTurnover() {
        List<ProductWorkOrderDto> productWorkOrderDtoList = productWorkOrderMapper.selectProductWorkOrderDtoList();
       //根据状态区分工单的各个状态
        Map<Integer, List<ProductWorkOrderDto>> productWorkOrderDtoMap = productWorkOrderDtoList.stream().collect(Collectors.groupingBy(ProductWorkOrderDto::getStatus));
        return productWorkOrderDtoMap;
    public ProductionTurnoverDto workInProcessTurnover() {
        ProductionTurnoverDto productionTurnoverDto = new ProductionTurnoverDto();
        ProductWorkOrderDto workOrder = new ProductWorkOrderDto();
        workOrder.setPlanStartTime(LocalDate.now().minusMonths(1));
        workOrder.setPlanEndTime(LocalDate.now());
        List<ProductWorkOrderDto> productWorkOrders = productWorkOrderMapper.pageProductWorkOrder(new Page<>(1, -1), workOrder).getRecords();
        long sum = productWorkOrders.stream()
                .filter(productWorkOrder -> productWorkOrder.getPlanQuantity().compareTo(productWorkOrder.getCompleteQuantity()) > 0)
                .map(ProductWorkOrder::getPlanQuantity)
                .mapToLong(BigDecimal::longValue)
                .sum();
        if (sum == 0)return null;
        productionTurnoverDto.setTotalOrderCount(sum);//总在制品数量
        productionTurnoverDto.setAverageTurnoverDays(BigDecimal.valueOf(sum).divide(BigDecimal.valueOf(ChronoUnit.DAYS.between(LocalDateTime.now().minusMonths(1), LocalDateTime.now())),2,RoundingMode.HALF_UP));
        long completeQuantity = productWorkOrders.stream()
                .filter(productWorkOrder -> productWorkOrder.getCompleteQuantity().compareTo(productWorkOrder.getPlanQuantity()) >= 0)
                .map(ProductWorkOrder::getCompleteQuantity)
                .mapToLong(BigDecimal::longValue)
                .sum();
        productionTurnoverDto.setTurnoverEfficiency(BigDecimal.valueOf(completeQuantity).divide(BigDecimal.valueOf(sum),2,RoundingMode.HALF_UP));
        Map<String, List<ProductWorkOrderDto>> map = productWorkOrders.stream()
                .filter(productWorkOrder -> productWorkOrder.getPlanQuantity().compareTo(productWorkOrder.getCompleteQuantity()) > 0)
                .collect(Collectors.groupingBy(ProductWorkOrderDto::getProcessName));
        List<String> strings = new ArrayList<>();
        List<Long> processQuantityDetails = new ArrayList<>();
        map.entrySet().stream().forEach(entry -> {
            String key = entry.getKey();
            long completeSum = entry.getValue().stream().map(ProductWorkOrderDto::getCompleteQuantity).mapToLong(BigDecimal::longValue).sum();
            strings.add(key);
            processQuantityDetails.add(completeSum);
        });
        productionTurnoverDto.setProcessDetails(strings);
        productionTurnoverDto.setProcessQuantityDetails(processQuantityDetails);
        return productionTurnoverDto;
    }
}
src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordController.java
@@ -237,8 +237,8 @@
    @GetMapping("/listPageProductionStock")
    @Log(title = "库存管理-成品库存", businessType = BusinessType.OTHER)
    public AjaxResult listPageProductionStock(Page page) {
        IPage<ProductModel> result = procurementRecordService.listPageProductionStock(page);
    public AjaxResult listPageProductionStock(Page page, ProcurementPageDto procurementDto) {
        IPage<ProductModel> result = procurementRecordService.listPageProductionStock(page,procurementDto);
        return AjaxResult.success(result);
    }
}
src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordService.java
@@ -60,7 +60,7 @@
    BigDecimal getProcurementAmount(Long salesProductId);
    InventoryInformationDto getReportList();
    IPage<ProductModel> listPageProductionStock(Page page);
    IPage<ProductModel> listPageProductionStock(Page page, ProcurementPageDto procurementDto);
    IPage<ProcurementPageDto> listPageByProductProduction(Page page, ProcurementPageDto procurementDto);
}
src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordServiceImpl.java
@@ -882,16 +882,10 @@
        }
        return procurementPageDtoCopyIPage;
    }
    @Override
    public IPage<ProductModel> listPageProductionStock(Page page) {
        ProductModel productModel = new ProductModel();
        IPage<ProductModel> iPage = productModelMapper.listPageProductModel(page, productModel);
        iPage.getRecords().forEach(item -> {
            item.setInboundNum(stockUtils.getStockQuantity(item.getId()).get("inboundNum"));
            item.setOutboundNum(stockUtils.getStockQuantity(item.getId()).get("outboundNum"));
            item.setStockQuantity(stockUtils.getStockQuantity(item.getId()).get("stockQuantity"));
        });
        return iPage;
    public IPage<ProductModel> listPageProductionStock(Page page, ProcurementPageDto dto) {
        return productModelMapper.listPageProductionStock(page, dto);
    }
    @Override
src/main/java/com/ruoyi/production/mapper/ProductWorkOrderMapper.java
@@ -17,5 +17,4 @@
    IPage<ProductWorkOrderDto> pageProductWorkOrder(Page<ProductWorkOrderDto> page, @Param("c") ProductWorkOrderDto productWorkOrder);
    List<ProductWorkOrderDto> selectProductWorkOrderDtoList();
}
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -24,6 +24,8 @@
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.other.mapper.TempFileMapper;
import com.ruoyi.other.pojo.TempFile;
import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper;
import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.purchase.dto.PurchaseLedgerDto;
@@ -108,6 +110,7 @@
    private final QualityTestStandardParamMapper qualityTestStandardParamMapper;
    private final QualityInspectParamMapper qualityInspectParamMapper;
    private final ProcurementRecordMapper procurementRecordStorageMapper;
    @Value("${file.upload-dir}")
    private String uploadDir;
@@ -409,6 +412,19 @@
        if (ids == null || ids.length == 0) {
           throw new BaseException("请选中至少一条数据");
        }
        // æ‰¹é‡åˆ é™¤å…³è”的采购入库记录
        LambdaQueryWrapper<SalesLedgerProduct> salesLedgerProductQueryWrapper = new LambdaQueryWrapper<>();
        salesLedgerProductQueryWrapper.in(SalesLedgerProduct::getSalesLedgerId, ids)
                .eq(SalesLedgerProduct::getType, 2);
        List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(salesLedgerProductQueryWrapper);
        if (CollectionUtils.isNotEmpty(salesLedgerProducts)) {
            salesLedgerProducts.stream().forEach(salesLedgerProduct -> {
                // æ‰¹é‡åˆ é™¤å…³è”的采购台账产品
                LambdaQueryWrapper<ProcurementRecordStorage> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(ProcurementRecordStorage::getSalesLedgerProductId, salesLedgerProduct.getId());
                procurementRecordStorageMapper.delete(queryWrapper);
            });
        }
        // æ‰¹é‡åˆ é™¤å…³è”的采购台账产品
        LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(SalesLedgerProduct::getSalesLedgerId, ids)
src/main/resources/mapper/basic/ProductModelMapper.xml
@@ -34,5 +34,68 @@
            LIMIT 1
    </select>
    <select id="listPageProductionStock" resultType="com.ruoyi.basic.pojo.ProductModel">
        SELECT
        pm.id,
        pm.product_id,
        pm.model,
        pm.unit,
        p.product_name,
        GREATEST(s.last_in_time, o.last_out_time) AS create_time,
        COALESCE(s.inboundNum, 0) AS inboundNum,
        COALESCE(o.outboundNum, 0) AS outboundNum,
        COALESCE(s.inboundNum, 0) - COALESCE(o.outboundNum, 0) AS stockQuantity
        FROM product_model pm
        LEFT JOIN product p ON pm.product_id = p.id
        -- å…¥åº“汇总
        LEFT JOIN (
        SELECT
        product_model_id,
        SUM(inbound_num) AS inboundNum,
        MAX(create_time) AS last_in_time
        FROM procurement_record_storage
        <where>
            <if test="req.timeStr != null and req.timeStr != ''">
                AND create_time &gt;= #{req.timeStr}
                AND create_time &lt; DATE_ADD(#{req.timeStr}, INTERVAL 1 DAY)
            </if>
        </where>
        GROUP BY product_model_id
        ) s ON s.product_model_id = pm.id
        -- å‡ºåº“汇总
        LEFT JOIN (
        SELECT
        product_model_id,
        SUM(inbound_num) AS outboundNum,
        MAX(create_time) AS last_out_time
        FROM procurement_record_out
        <where>
            <if test="req.timeStr != null and req.timeStr != ''">
                AND create_time &gt;= #{req.timeStr}
                AND create_time &lt; DATE_ADD(#{req.timeStr}, INTERVAL 1 DAY)
            </if>
        </where>
        GROUP BY product_model_id
        ) o ON o.product_model_id = pm.id
        <where>
            <if test="req.timeStr != null and req.timeStr != ''">
                AND (s.product_model_id IS NOT NULL OR o.product_model_id IS NOT NULL)
            </if>
            <if test="req.productCategory != null and req.productCategory != ''">
                AND EXISTS (
                SELECT 1
                FROM sales_ledger_product slp
                WHERE slp.product_id = p.id
                AND slp.product_category LIKE CONCAT('%', #{req.productCategory}, '%')
                )
            </if>
        </where>
        ORDER BY pm.id DESC
    </select>
</mapper>
src/main/resources/mapper/production/ProductOrderMapper.xml
@@ -43,6 +43,9 @@
            <if test="c.specificationModel != null and c.specificationModel != ''">
                and slp.specification_model like concat('%',#{c.specificationModel},'%')
            </if>
            <if test="c.startTime != null and c.endTime != null">
                and po.create_time between #{c.startTime} and #{c.endTime}
            </if>
        </where>
    </select>
    <select id="productMainByOrderId" resultType="com.ruoyi.production.dto.ProductOrderDto">
src/main/resources/mapper/production/ProductWorkOrderMapper.xml
@@ -38,11 +38,9 @@
            <if test="c.workOrderNo != null and c.workOrderNo != ''">
                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>
        </where>
    </select>
    <select id="selectProductWorkOrderDtoList" resultType="com.ruoyi.production.dto.ProductWorkOrderDto">
        select *
        from product_work_order pwo
        left join product_order po on po.id = pwo.product_order_id
    </select>
</mapper>