已添加3个文件
已修改33个文件
446 ■■■■ 文件已修改
src/main/java/com/ruoyi/basic/pojo/ProductModel.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/annotation/DefaultType.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/aspectj/DefaultTypeAspect.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/controller/HomeController.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/dto/processDataProductionStatisticsDto.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/service/HomeService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java 172 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProcessRouteDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProcessRouteItemDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductBomDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductOrderDto.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductProcessRouteItemDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductStructureDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductWorkOrderDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductionDispatchAddDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductionProductInputDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductionProductOutputDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/SalesLedgerProductDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/ProductProcessMapper.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProcessRouteItemMapper.xml 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProcessRouteMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductBomMapper.xml 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductOrderMapper.xml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductProcessMapper.xml 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductProcessRouteItemMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductProcessRouteMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductStructureMapper.xml 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductWorkOrderMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductionProductInputMapper.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductionProductMainMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductionProductOutputMapper.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/SalesLedgerProductionAccountingMapper.xml 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/SalesLedgerProductMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/ProductModel.java
@@ -61,6 +61,10 @@
    @Excel(name = "剩余库存")
    private BigDecimal stockQuantity;
    @ApiModelProperty(value = "图纸编号")
    @Excel(name = "图纸编号")
    private String drawingNumber;
    @TableField(exist = false)
    private LocalDateTime createTime;
}
src/main/java/com/ruoyi/home/annotation/DefaultType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
package com.ruoyi.home.annotation;
import java.lang.annotation.*;
/**
 * <br>
 * ç»Ÿè®¡ç±»åž‹é»˜è®¤å€¼æ³¨è§£
 * é»˜è®¤ type = 1
 * </br>
 *
 * @author deslrey
 * @version 1.0
 * @since 2026/2/5
 */
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DefaultType {
    String value() default "1";
}
src/main/java/com/ruoyi/home/aspectj/DefaultTypeAspect.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
package com.ruoyi.home.aspectj;
import com.ruoyi.home.annotation.DefaultType;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Parameter;
/**
 * <br>
 * ç»Ÿè®¡ç±»åž‹é»˜è®¤å€¼æ³¨è§£åˆ‡é¢
 * </br>
 *
 * @author deslrey
 * @version 1.0
 * @since 2026/2/5
 */
@Aspect
@Component
public class DefaultTypeAspect {
    @Around("execution(* com.ruoyi.home.controller.*.*(.., @com.ruoyi.home.annotation.DefaultType (*), ..))")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Parameter[] parameters = signature.getMethod().getParameters();
        for (int i = 0; i < parameters.length; i++) {
            DefaultType annotation = parameters[i].getAnnotation(DefaultType.class);
            if (annotation != null && args[i] == null) {
                args[i] = Integer.parseInt(annotation.value());
            }
        }
        return joinPoint.proceed(args);
    }
}
src/main/java/com/ruoyi/home/controller/HomeController.java
@@ -5,6 +5,7 @@
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.home.annotation.DefaultType;
import com.ruoyi.home.dto.*;
import com.ruoyi.home.service.HomeService;
import com.ruoyi.dto.MapDto;
@@ -72,21 +73,21 @@
    /********************************************************营销采购类**************************************************/
    @GetMapping("/supplierPurchaseRanking")
    @ApiOperation("供应商采购排名")
    public AjaxResult supplierPurchaseRanking(@RequestParam(value = "type", defaultValue = "1") Integer type) {
    public AjaxResult supplierPurchaseRanking(@DefaultType Integer type) {
        List<SupplierPurchaseRankingDto> list = homeService.supplierPurchaseRanking(type);
        return AjaxResult.success(list);
    }
    @GetMapping("/customerRevenueAnalysis")
    @ApiOperation("客户营收贡献数值分析")
    public AjaxResult customerRevenueAnalysis(@RequestParam("customerId") Long customerId, @RequestParam(value = "type", defaultValue = "1") Integer type) {
    public AjaxResult customerRevenueAnalysis(Long customerId, @DefaultType Integer type) {
        CustomerRevenueAnalysisDto dto = homeService.customerRevenueAnalysis(customerId, type);
        return AjaxResult.success(dto);
    }
    @GetMapping("/customerContributionRanking")
    @ApiOperation("客户金额贡献排名")
    public AjaxResult customerContributionRanking(@RequestParam(value = "type", defaultValue = "1") Integer type) {
    public AjaxResult customerContributionRanking(@DefaultType Integer type) {
        List<CustomerContributionRankingDto> list = homeService.customerContributionRanking(type);
        return AjaxResult.success(list);
    }
@@ -124,28 +125,28 @@
    /********************************************************生产类*****************************************************/
    @GetMapping("/inputOutputAnalysis")
    @ApiOperation("投入产出分析")
    public AjaxResult inputOutputAnalysis(@RequestParam(value = "type", defaultValue = "1") Integer type){
    public AjaxResult inputOutputAnalysis(@DefaultType Integer type){
      List<InputOutputAnalysisDto> list = homeService.inputOutputAnalysis(type);
        return AjaxResult.success(list);
    }
    @GetMapping("/processOutputAnalysis")
    @ApiOperation("工序产出分析")
    public AjaxResult processOutputAnalysis(@RequestParam(value = "type", defaultValue = "1") Integer type){
    public AjaxResult processOutputAnalysis(@DefaultType Integer type){
        List<MapDto> list = homeService.processOutputAnalysis(type);
        return AjaxResult.success(list);
    }
    @GetMapping("/workOrderEfficiencyAnalysis")
    @ApiOperation("工单执行效率分析")
    public AjaxResult workOrderEfficiencyAnalysis(@RequestParam(value = "type", defaultValue = "1") Integer type){
    public AjaxResult workOrderEfficiencyAnalysis(@DefaultType Integer type){
        List<WorkOrderEfficiencyDto> list = homeService.workOrderEfficiencyAnalysis(type);
        return AjaxResult.success(list);
    }
    @GetMapping("/productionAccountingAnalysis")
    @ApiOperation("生产核算分析")
    public AjaxResult productionAccountingAnalysis(@RequestParam(value = "type", defaultValue = "1") Integer type){
    public AjaxResult productionAccountingAnalysis(@DefaultType Integer type){
        List<ProductionAccountingDto> list   = homeService.productionAccountingAnalysis(type);
        return AjaxResult.success(list);
    }
@@ -170,22 +171,29 @@
        return AjaxResult.success(productionTurnoverDto);
    }
    @GetMapping("/processDataProductionStatistics")
    @ApiOperation("工序数据生产统计数据")
    public AjaxResult processDataProductionStatistics(@DefaultType Integer type,@RequestParam(required = false) List<Long> processIds) {
        List<processDataProductionStatisticsDto> list = homeService.processDataProductionStatistics(type, processIds);
        return AjaxResult.success(list);
    }
    /********************************************************质量类*****************************************************/
    @GetMapping("/rawMaterialDetection")
    @ApiOperation("原材料检测")
    public AjaxResult rawMaterialDetection(@RequestParam(value = "type", defaultValue = "1") Integer type){
    public AjaxResult rawMaterialDetection(@DefaultType Integer type){
        return AjaxResult.success(homeService.rawMaterialDetection(type));
    }
    @GetMapping("/processDetection")
    @ApiOperation("过程检测")
    public AjaxResult processDetection(@RequestParam(value = "type", defaultValue = "1") Integer type){
    public AjaxResult processDetection(@DefaultType Integer type){
        return AjaxResult.success(homeService.processDetection(type));
    }
    @GetMapping("/factoryDetection")
    @ApiOperation("成品出厂检测")
    public AjaxResult factoryDetection(@RequestParam(value = "type", defaultValue = "1") Integer type){
    public AjaxResult factoryDetection(@DefaultType Integer type){
        return AjaxResult.success(homeService.factoryDetection(type));
    }
@@ -232,10 +240,17 @@
        return AjaxResult.success(qualityStatisticsDto);
    }
    @GetMapping("/qualityInspectionStatistics")
    @ApiOperation("质量统计")
    public AjaxResult qualityInspectionStatistics(@DefaultType Integer type) {
       QualityStatisticsDto  dto = homeService.qualityInspectionStatistics(type);
        return AjaxResult.success(dto);
    }
    /********************************************************财务类*****************************************************/
    @GetMapping("/incomeExpenseAnalysis")
    @ApiOperation("支收对比分析")
    public AjaxResult incomeExpenseAnalysis(@RequestParam(value = "type", defaultValue = "1") Integer type) {
    public AjaxResult incomeExpenseAnalysis(@DefaultType Integer type) {
        List<Map<String, Object>> result = homeService.incomeExpenseAnalysis(type);
        return AjaxResult.success(result);
    }
@@ -249,7 +264,7 @@
    @GetMapping("/expenseCompositionAnalysis")
    @ApiOperation("构成分析")
    public AjaxResult expenseCompositionAnalysis(@RequestParam(value = "type", defaultValue = "1") Integer type) {
    public AjaxResult expenseCompositionAnalysis(@DefaultType Integer type) {
        List<MapDto> list = homeService.expenseCompositionAnalysis(type);
        return AjaxResult.success(list);
    }
@@ -271,7 +286,7 @@
    @GetMapping("/statisticsReceivablePayable")
    @Log(title = "应收应付统计", businessType = BusinessType.OTHER)
    @ApiOperation("应收应付统计")
    public AjaxResult statisticsReceivablePayable(StatisticsReceivablePayableDto req, @RequestParam(value = "type", defaultValue = "1") Integer type ) {
    public AjaxResult statisticsReceivablePayable(StatisticsReceivablePayableDto req, @DefaultType Integer type ) {
        StatisticsReceivablePayableDto statisticsReceivablePayable = homeService.statisticsReceivablePayable(type);
        return AjaxResult.success(statisticsReceivablePayable);
    }
@@ -294,7 +309,7 @@
    @GetMapping("/productInOutAnalysis")
    @ApiOperation("产品出入库分析")
    public AjaxResult productInOutAnalysis(@RequestParam(value = "type", defaultValue = "1") Integer type){
    public AjaxResult productInOutAnalysis(@DefaultType Integer type){
        List<Map<String, Object>> result = homeService.productInOutAnalysis(type);
        return AjaxResult.success(result);
    }
src/main/java/com/ruoyi/home/dto/processDataProductionStatisticsDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
package com.ruoyi.home.dto;
import lombok.Data;
import java.math.BigDecimal;
/**
 * <br>
 * å·¥åºæ•°æ®ç”Ÿäº§ç»Ÿè®¡æ˜Žç»†Dto
 * </br>
 *
 * @author deslrey
 * @version 1.0
 * @since 2026/2/5
 */
@Data
public class processDataProductionStatisticsDto {
    /**
     * å·¥åºåç§°
     */
    private String processName;
    /**
     * ç´¯è®¡æ€»æŠ•å…¥
     */
    private BigDecimal totalInput;
    /**
     * ç´¯åŠ æ€»æŠ¥åºŸ
     */
    private BigDecimal totalScrap;
    /**
     * ç´¯åŠ æ€»äº§å‡º
     */
    private BigDecimal totalOutput;
}
src/main/java/com/ruoyi/home/service/HomeService.java
@@ -91,4 +91,8 @@
    List<UnqualifiedProductRankDto> unqualifiedProductRanking();
    List<MapDto> unqualifiedProductProcessingAnalysis();
    QualityStatisticsDto qualityInspectionStatistics(Integer type);
    List<processDataProductionStatisticsDto> processDataProductionStatistics(Integer type, List<Long> processIds);
}
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -33,17 +33,15 @@
import com.ruoyi.production.dto.ProductOrderDto;
import com.ruoyi.production.dto.ProductWorkOrderDto;
import com.ruoyi.production.mapper.ProductOrderMapper;
import com.ruoyi.production.mapper.ProductProcessMapper;
import com.ruoyi.production.mapper.ProductWorkOrderMapper;
import com.ruoyi.production.mapper.ProductionProductInputMapper;
import com.ruoyi.production.mapper.ProductionProductOutputMapper;
import com.ruoyi.production.mapper.SalesLedgerProductionAccountingMapper;
import com.ruoyi.production.pojo.ProductProcess;
import com.ruoyi.production.pojo.ProductWorkOrder;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.domain.SysUserDept;
import com.ruoyi.project.system.mapper.SysDeptMapper;
import com.ruoyi.project.system.mapper.SysUserDeptMapper;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.purchase.mapper.PaymentRegistrationMapper;
import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
import com.ruoyi.purchase.pojo.PaymentRegistration;
@@ -143,6 +141,9 @@
    @Autowired
    private QualityUnqualifiedMapper qualityUnqualifiedMapper;
    @Autowired
    private ProductProcessMapper productProcessMapper;
    @Override
    public HomeBusinessDto business() {
@@ -463,8 +464,8 @@
        }
        // åº”æ”¶
        List<SalesLedger> salesLedgers = salesLedgerMapper.selectList(new LambdaQueryWrapper<SalesLedger>()
                // .ge(SalesLedger::getEntryDate, startDate)
                // .lt(SalesLedger::getEntryDate, endDate)
        // .ge(SalesLedger::getEntryDate, startDate)
        // .lt(SalesLedger::getEntryDate, endDate)
        );
        // BigDecimal receivableMoney =
        // salesLedgers.stream().map(SalesLedger::getContractAmount).reduce(BigDecimal.ZERO,
@@ -473,8 +474,8 @@
        // åº”付
        List<PurchaseLedger> procurementRecords = purchaseLedgerMapper
                .selectList(new LambdaQueryWrapper<PurchaseLedger>()
                        // .ge(PurchaseLedger::getEntryDate, startDate)
                        // .lt(PurchaseLedger::getEntryDate, endDate)
                // .ge(PurchaseLedger::getEntryDate, startDate)
                // .lt(PurchaseLedger::getEntryDate, endDate)
                );
        // BigDecimal payableMoney =
        // procurementRecords.stream().map(PurchaseLedger::getContractAmount).reduce(BigDecimal.ZERO,
@@ -482,8 +483,8 @@
        BigDecimal payableMoney = sumAmount(procurementRecords, PurchaseLedger::getContractAmount);
        // é¢„æ”¶
        List<ReceiptPayment> receiptPayments = receiptPaymentMapper.selectList(new LambdaQueryWrapper<ReceiptPayment>()
                // .ge(ReceiptPayment::getReceiptPaymentDate, startDate)
                // .lt(ReceiptPayment::getReceiptPaymentDate, endDate)
        // .ge(ReceiptPayment::getReceiptPaymentDate, startDate)
        // .lt(ReceiptPayment::getReceiptPaymentDate, endDate)
        );
        // BigDecimal advanceMoney =
        // receiptPayments.stream().map(ReceiptPayment::getReceiptPaymentAmount).reduce(BigDecimal.ZERO,
@@ -492,8 +493,8 @@
        // é¢„付
        List<PaymentRegistration> paymentRegistrations = paymentRegistrationMapper
                .selectList(new LambdaQueryWrapper<PaymentRegistration>()
                        // .ge(PaymentRegistration::getPaymentDate, startDate)
                        // .lt(PaymentRegistration::getPaymentDate, endDate)
                // .ge(PaymentRegistration::getPaymentDate, startDate)
                // .lt(PaymentRegistration::getPaymentDate, endDate)
                );
        // BigDecimal prepayMoney =
        // paymentRegistrations.stream().map(PaymentRegistration::getCurrentPaymentAmount).reduce(BigDecimal.ZERO,
@@ -557,7 +558,7 @@
        productionProgressDto.setCompletedOrderDetails(productOrderDtos);
        long totalCount = productOrderDtos.size();
        long count = productOrderDtos.stream().filter(
                        productOrderDto -> productOrderDto.getCompleteQuantity().compareTo(productOrderDto.getQuantity()) >= 0)
                productOrderDto -> productOrderDto.getCompleteQuantity().compareTo(productOrderDto.getQuantity()) >= 0)
                .count();
        long count2 = productOrderDtos.stream()
                .filter(productOrderDto -> productOrderDto.getCompleteQuantity().compareTo(BigDecimal.ZERO) == 0)
@@ -1729,7 +1730,8 @@
                    BigDecimal finishQty = item.getQuantity() != null ? item.getQuantity() : BigDecimal.ZERO;
                    BigDecimal scrapQty = item.getScrapQty() != null ? item.getScrapQty() : BigDecimal.ZERO;
                    dto.setFinishQuantity(dto.getFinishQuantity() != null ? dto.getFinishQuantity().add(finishQty) : finishQty);
                    dto.setFinishQuantity(
                            dto.getFinishQuantity() != null ? dto.getFinishQuantity().add(finishQty) : finishQty);
                }
            }
@@ -1893,7 +1895,6 @@
        return dto;
    }
    @Override
    public QualityQualifiedAnalysisDto rawMaterialDetection(Integer type) {
        return commonDetection(type, 0);
@@ -1956,7 +1957,7 @@
                endDate = today.with(DayOfWeek.SUNDAY);
        }
        return new LocalDate[]{startDate, endDate};
        return new LocalDate[] { startDate, endDate };
    }
    private QualityQualifiedAnalysisDto buildQualifiedAnalysis(List<QualityInspect> list) {
@@ -2218,7 +2219,7 @@
        LocalDateTime startTime = today.minusDays(6).atStartOfDay();
        LocalDateTime endTime = today.atTime(23, 59, 59);
        return new LocalDateTime[]{startTime, endTime};
        return new LocalDateTime[] { startTime, endTime };
    }
    @Override
@@ -2353,7 +2354,7 @@
            return new ArrayList<>();
        }
        //  ç»Ÿè®¡æ¯ç§å¤„理结果的数量
        // ç»Ÿè®¡æ¯ç§å¤„理结果的数量
        Map<String, BigDecimal> countMap = new HashMap<>();
        for (QualityUnqualified item : list) {
            if (StringUtils.isEmpty(item.getDealResult()) || item.getQuantity() == null) {
@@ -2366,7 +2367,7 @@
            return new ArrayList<>();
        }
        //  è®¡ç®—总数
        // è®¡ç®—总数
        BigDecimal totalCount = countMap.values()
                .stream()
                .reduce(BigDecimal.ZERO, BigDecimal::add);
@@ -2375,7 +2376,7 @@
            return new ArrayList<>();
        }
        //  æŒ‰æ•°é‡å€’序排序
        // æŒ‰æ•°é‡å€’序排序
        List<Map.Entry<String, BigDecimal>> sortedList = countMap.entrySet()
                .stream()
                .sorted((a, b) -> b.getValue().compareTo(a.getValue()))
@@ -2411,4 +2412,135 @@
        return result;
    }
    @Override
    public QualityStatisticsDto qualityInspectionStatistics(Integer type) {
        LocalDate today = LocalDate.now();
        LocalDate startDate;
        LocalDate endDate;
        switch (type) {
            case 1: // æœ¬å‘¨
                startDate = today.with(DayOfWeek.MONDAY);
                endDate = today.with(DayOfWeek.SUNDAY);
                break;
            case 2: // æœ¬æœˆ
                startDate = today.with(TemporalAdjusters.firstDayOfMonth());
                endDate = today.with(TemporalAdjusters.lastDayOfMonth());
                break;
            case 3: // æœ¬å­£åº¦
                int currentMonth = today.getMonthValue();
                int startMonth = ((currentMonth - 1) / 3) * 3 + 1;
                startDate = LocalDate.of(today.getYear(), startMonth, 1);
                endDate = startDate.plusMonths(2).with(TemporalAdjusters.lastDayOfMonth());
                break;
            default:
                startDate = today.with(DayOfWeek.MONDAY);
                endDate = today.with(DayOfWeek.SUNDAY);
        }
        List<QualityInspect> qualityInspectList = qualityInspectMapper
                .selectList(new LambdaQueryWrapper<QualityInspect>()
                        .ge(QualityInspect::getCheckTime, startDate)
                        .le(QualityInspect::getCheckTime, endDate)
                        .eq(QualityInspect::getInspectState, 1));
        QualityStatisticsDto dto = new QualityStatisticsDto();
        dto.setSupplierNum(sumQuantity(qualityInspectList, 0)); // åŽŸææ–™
        dto.setProcessNum(sumQuantity(qualityInspectList, 1)); // è¿‡ç¨‹
        dto.setFactoryNum(sumQuantity(qualityInspectList, 2)); // å‡ºåŽ‚
        // 4. å¤„理图表项 (Item)
        List<QualityStatisticsItem> itemList = new ArrayList<>();
        Map<QualityInspect, LocalDate> dateMap = qualityInspectList.stream()
                .collect(Collectors.toMap(
                        i -> i,
                        i -> i.getCheckTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()));
        if (type == 3) {
            // å­£åº¦æ¨¡å¼ï¼šæŒ‰æœˆåˆ†ç»„
            Map<String, List<QualityInspect>> groupByMonth = qualityInspectList.stream()
                    .collect(Collectors.groupingBy(i -> {
                        LocalDate ld = dateMap.get(i);
                        return ld.format(DateTimeFormatter.ofPattern("yyyy-MM"));
                    }));
            for (int i = 0; i < 3; i++) {
                LocalDate monthDate = startDate.plusMonths(i);
                String monthStr = monthDate.format(DateTimeFormatter.ofPattern("yyyy-MM"));
                itemList.add(buildItem(monthStr, groupByMonth.getOrDefault(monthStr, new ArrayList<>())));
            }
        } else {
            // å‘¨æˆ–月模式:按天分组
            Map<String, List<QualityInspect>> groupByDay = qualityInspectList.stream()
                    .collect(Collectors.groupingBy(i -> {
                        LocalDate ld = dateMap.get(i);
                        return ld.format(DateTimeFormatter.ofPattern("MM/dd"));
                    }));
            long days = ChronoUnit.DAYS.between(startDate, endDate);
            for (int i = 0; i <= days; i++) {
                LocalDate tempDay = startDate.plusDays(i);
                String dayStr = tempDay.format(DateTimeFormatter.ofPattern("MM/dd"));
                itemList.add(buildItem(dayStr, groupByDay.getOrDefault(dayStr, new ArrayList<>())));
            }
        }
        dto.setItem(itemList);
        return dto;
    }
    private BigDecimal sumQuantity(List<QualityInspect> list, Integer type) {
        return list.stream()
                .filter(i -> i.getInspectType().equals(type))
                .map(QualityInspect::getQuantity)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
    private QualityStatisticsItem buildItem(String dateLabel, List<QualityInspect> list) {
        QualityStatisticsItem item = new QualityStatisticsItem();
        item.setDate(dateLabel);
        item.setSupplierNum(list.stream().filter(i -> i.getInspectType() == 0).map(QualityInspect::getQuantity)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        item.setProcessNum(list.stream().filter(i -> i.getInspectType() == 1).map(QualityInspect::getQuantity)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        item.setFactoryNum(list.stream().filter(i -> i.getInspectType() == 2).map(QualityInspect::getQuantity)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        return item;
    }
    @Override
    public List<processDataProductionStatisticsDto> processDataProductionStatistics(Integer type,
            List<Long> processIds) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        Long userId = SecurityUtils.isAdmin(loginUser.getUserId()) ? null : loginUser.getUserId();
        LocalDate today = LocalDate.now();
        LocalDate startDate;
        LocalDate endDate;
        switch (type) {
            case 1:
                startDate = today;
                endDate = today;
                break;
            case 2:
                startDate = today.with(DayOfWeek.MONDAY);
                endDate = today.with(DayOfWeek.SUNDAY);
                break;
            case 3:
                startDate = today.with(TemporalAdjusters.firstDayOfMonth());
                endDate = today.with(TemporalAdjusters.lastDayOfMonth());
                break;
            default:
                startDate = today;
                endDate = today;
        }
        LocalDateTime startDateTime = startDate.atStartOfDay();
        LocalDateTime endDateTime = endDate.atTime(LocalTime.MAX);
        return productProcessMapper.calculateProductionStatistics(startDateTime, endDateTime, userId, processIds);
    }
}
src/main/java/com/ruoyi/production/dto/ProcessRouteDto.java
@@ -14,5 +14,7 @@
    @ApiModelProperty("规格")
    private String model;
    private String drawingNumber;
    private String bomNo;
}
src/main/java/com/ruoyi/production/dto/ProcessRouteItemDto.java
@@ -21,6 +21,8 @@
    @ApiModelProperty(value = "产品名称")
    private String productName;
    private String drawingNumber;
    @ApiModelProperty(value = "单位")
    private String unit;
src/main/java/com/ruoyi/production/dto/ProductBomDto.java
@@ -15,4 +15,6 @@
    //产品规格型号
    private String productModelName;
    private String drawingNumber;
}
src/main/java/com/ruoyi/production/dto/ProductOrderDto.java
@@ -31,6 +31,9 @@
    @Excel(name = "产品名称")
    private String productCategory;
    private String drawingNumber;
    @ApiModelProperty(value = "规格")
    @Excel(name = "规格")
    private String specificationModel;
src/main/java/com/ruoyi/production/dto/ProductProcessRouteItemDto.java
@@ -21,6 +21,8 @@
    private Long productId;
    private String drawingNumber;
    private String productName;
    private String model;
src/main/java/com/ruoyi/production/dto/ProductStructureDto.java
@@ -21,6 +21,8 @@
    @ApiModelProperty(value = "产品id")
    private Long productId;
    private String drawingNumber;
    private String model;
    @TableField(exist = false)
src/main/java/com/ruoyi/production/dto/ProductWorkOrderDto.java
@@ -43,4 +43,6 @@
    @ApiModelProperty(value = "工单类型 æ­£å¸¸ /返工返修")
    private String workOrderType;
    private String drawingNumber;
}
src/main/java/com/ruoyi/production/dto/ProductionDispatchAddDto.java
@@ -54,4 +54,6 @@
     */
    private String specificationModel;
    private String drawingNumber;
}
src/main/java/com/ruoyi/production/dto/ProductionProductInputDto.java
@@ -15,6 +15,8 @@
    @ApiModelProperty(value = "产品名称")
    private String productName;
    private String drawingNumber;
    @ApiModelProperty(value = "单位")
    private String unit;
}
src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java
@@ -38,6 +38,8 @@
    @Excel(name = "产品名称")
    private String productName;
    private String drawingNumber;
    //产品规格型号
    @Excel(name = "产品规格型号")
    private String productModelName;
src/main/java/com/ruoyi/production/dto/ProductionProductOutputDto.java
@@ -12,4 +12,6 @@
    @ApiModelProperty(value = "产品型号")
    private String model;
    private String drawingNumber;
}
src/main/java/com/ruoyi/production/dto/SalesLedgerProductDto.java
@@ -54,6 +54,8 @@
    @ApiModelProperty(value = "产品大类")
    private String productCategory;
    private String drawingNumber;
    /**
     * è§„格型号
     */
src/main/java/com/ruoyi/production/mapper/ProductProcessMapper.java
@@ -3,12 +3,18 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.home.dto.processDataProductionStatisticsDto;
import com.ruoyi.production.dto.ProductProcessDto;
import com.ruoyi.production.pojo.ProductProcess;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.time.LocalDateTime;
import java.util.List;
@Mapper
public interface ProductProcessMapper extends BaseMapper<ProductProcess> {
    IPage<ProductProcessDto> listPage(Page page,@Param("productProcessDto") ProductProcessDto productProcessDto);
    List<processDataProductionStatisticsDto> calculateProductionStatistics(LocalDateTime startDateTime, LocalDateTime endDateTime, Long userId, List<Long> processIds);
}
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -207,7 +207,7 @@
                }
            }else {
                //直接入库
                stockUtils.addStock(productProcessRouteItem.getProductModelId(), productionProductOutput.getQuantity(), StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId());
                stockUtils.addStock(productProcessRouteItem.getProductModelId(), productQty, StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId());
            }
            /*更新工单和生产订单*/
            ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
@@ -288,11 +288,17 @@
            ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
            if (productOrder != null) {
                BigDecimal orderCompleteQty = productOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : productOrder.getCompleteQuantity();
                BigDecimal outputQty = productionProductOutput.getQuantity() != null
                        ? productionProductOutput.getQuantity() : BigDecimal.ZERO;
                BigDecimal totalQty = productionProductOutput.getQuantity() != null ? productionProductOutput.getQuantity() : BigDecimal.ZERO;
                BigDecimal scrapQty = productionProductOutput.getScrapQty() != null ? productionProductOutput.getScrapQty() : BigDecimal.ZERO;
                productOrder.setCompleteQuantity(orderCompleteQty.subtract(outputQty));
                BigDecimal actualQualifiedQty = totalQty.subtract(scrapQty);
                BigDecimal newCompleteQty = orderCompleteQty.subtract(actualQualifiedQty);
                productOrder.setCompleteQuantity(newCompleteQty.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : newCompleteQty);
                productOrder.setEndTime(null);
                productOrderMapper.updateById(productOrder);
            } else {
                throw new ServiceException("关联的生产订单不存在");
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -445,7 +445,7 @@
        IPage<SalesLedgerProductDto> salesLedgerProductDtoIPage = salesLedgerProductMapper.listPagePurchaseLedger(page, salesLedgerProduct);
        salesLedgerProductDtoIPage.getRecords().forEach(item -> {
            // åˆ¤æ–­çŠ¶æ€
            if(item.getTaxInclusiveTotalPrice().compareTo(item.getInvoiceTotal()) == 0){
            if(item.getTaxInclusiveTotalPrice().compareTo(item.getTicketsTotal()) == 0){
                item.setStatusName("已完成付款");
            }else{
                item.setStatusName("未完成付款");
src/main/resources/mapper/production/ProcessRouteItemMapper.xml
@@ -21,7 +21,8 @@
               pm.product_id,
               pm.model,
               p.product_name,
               pm.unit
               pm.unit,
               pm.drawing_number
        from
            process_route_item pri
                left join product_model pm on pri.product_model_id = pm.id
src/main/resources/mapper/production/ProcessRouteMapper.xml
@@ -13,7 +13,7 @@
    </resultMap>
    <select id="pageProcessRouteDto" resultType="com.ruoyi.production.dto.ProcessRouteDto">
        select ps.*, p.product_name,pm.product_id,pm.model,pb.bom_no
        select ps.*, p.product_name,pm.product_id,pm.model,pb.bom_no,pm.drawing_number
        from process_route ps
        left join product_bom pb on ps.bom_id = pb.id
        left join product_model pm on ps.product_model_id = pm.id
src/main/resources/mapper/production/ProductBomMapper.xml
@@ -18,6 +18,7 @@
    <select id="listPage" resultType="com.ruoyi.production.dto.ProductBomDto">
        select * from (select pb.*,
        pm.model productModelName,
        pm.drawing_number,
        p.product_name productName
        from product_bom pb
        left join product_model pm on pb.product_model_id = pm.id
@@ -39,7 +40,8 @@
    <select id="getById" resultType="com.ruoyi.production.dto.ProductBomDto">
        select pb.*,
               pm.model productModelName,
               p.product_name productName
               p.product_name productName,
               pm.drawing_number
        from product_bom pb
                 left join product_model pm on pb.product_model_id = pm.id
                 left join product p on pm.product_id = p.id
src/main/resources/mapper/production/ProductOrderMapper.xml
@@ -20,6 +20,7 @@
        p.product_name as product_category,
        pm.model as specification_model,
        pm.unit,
        pm.drawing_number,
        ppr.process_route_code,
        pb.bom_no,
        ROUND(po.complete_quantity / po.quantity * 100, 2) AS completionStatus,
@@ -79,14 +80,17 @@
               ps.unit_quantity * po.quantity as demandedQuantity,
               ps.unit,
               p.product_name,
               pm.drawing_number,
               pp.name as  process_name,
               pm.product_id,
               pm.model
               pm.model,
               pb.bom_no
        from
            product_structure ps
                left join product_model pm on ps.product_model_id = pm.id
                left join product p on pm.product_id = p.id
                left join product_process pp on ps.process_id = pp.id
                left join product_bom pb on ps.bom_id = pb.id
                left join product_process_route ppr on ps.bom_id = ppr.bom_id
                left join product_order po on po.id = ppr.product_order_id
        where ppr.product_order_id = #{orderId}
src/main/resources/mapper/production/ProductProcessMapper.xml
@@ -17,4 +17,37 @@
        </where>
        order by p.id asc
    </select>
    <select id="calculateProductionStatistics" resultType="com.ruoyi.home.dto.processDataProductionStatisticsDto">
        SELECT
        pp.name AS processName,
        SUM((ppo.quantity + ppo.scrap_qty) * pp.salary_quota) AS totalInput,
        SUM(ppo.scrap_qty * pp.salary_quota) AS totalScrap,
        SUM(ppo.quantity * pp.salary_quota) AS totalOutput
        FROM
        production_product_output ppo
        INNER JOIN production_product_main ppm ON ppo.product_main_id = ppm.id
        INNER JOIN product_process_route_item ppri ON ppm.product_process_route_item_id = ppri.id
        INNER JOIN product_process pp ON ppri.process_id = pp.id
        <where>
            <if test="startDateTime != null">
                AND ppo.create_time &gt;= #{startDateTime}
            </if>
            <if test="endDateTime != null">
                AND ppo.create_time &lt;= #{endDateTime}
            </if>
            <if test="userId != null">
                AND ppm.user_id = #{userId}
            </if>
            <if test="processIds != null and processIds.size() > 0">
                AND pp.id IN
                <foreach collection="processIds" item="id" open="(" separator="," close=")">
                    #{id}
                </foreach>
            </if>
        </where>
        GROUP BY
        pp.id,
        pp.name
    </select>
</mapper>
src/main/resources/mapper/production/ProductProcessRouteItemMapper.xml
@@ -15,11 +15,16 @@
               pp.name as process_name,
               pm.model,
               pm.unit,
               pm.drawing_number,
               p.product_name,
               ppr.process_route_Code,
               pb.bom_no,
               case when pwo.complete_quantity>0 then true else false end as is_complete
        from product_process_route_item ppri
                 left join product_model pm on ppri.product_model_id = pm.id
                 left join product p on pm.product_id = p.id
                  left join product_process_route ppr on ppr.id = ppri.product_route_id
            left join product_bom pb on pb.id = ppr.bom_id
                 left join product_process pp on pp.id = ppri.process_id
                 left join product_work_order pwo on pwo.product_process_route_item_id = ppri.id
        where ppri.product_order_id = #{orderId}
src/main/resources/mapper/production/ProductProcessRouteMapper.xml
@@ -15,7 +15,7 @@
        <result column="product_order_id" property="productOrderId"/>
    </resultMap>
    <select id="listMain" resultType="com.ruoyi.production.dto.ProcessRouteDto">
        select ppr.*, p.product_name, pm.product_id, pm.model, pb.bom_no
        select ppr.*, p.product_name, pm.product_id, pm.model, pb.bom_no,pm.drawing_number
        from product_process_route ppr
                 left join product_bom pb on ppr.bom_id = pb.id
                 left join product_model pm on ppr.product_model_id = pm.id
src/main/resources/mapper/production/ProductStructureMapper.xml
@@ -16,11 +16,14 @@
               p.product_name,
               pp.name as  process_name,
               pm.product_id,
               pm.model
               pm.model,
               pm.drawing_number,
               pb.bom_no
        from
            product_structure ps
                left join product_model pm on ps.product_model_id = pm.id
                left join product p on pm.product_id = p.id
                left join product_bom pb on ps.bom_id = pb.id
                left join product_process pp on ps.process_id = pp.id
        where ps.bom_id = #{bomId}
        order by ps.id
@@ -30,7 +33,8 @@
               p.product_name,
               pp.name as  process_name,
               pm.product_id,
               pm.model
               pm.model,
               pm.drawing_number
        from
            product_structure ps
                left join product_model pm on ps.product_model_id = pm.id
src/main/resources/mapper/production/ProductWorkOrderMapper.xml
@@ -25,6 +25,7 @@
        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
@@ -55,6 +56,7 @@
        pp.NAME as processName,
        pm.model,
        pm.unit,
        pm.drawing_number,
        p.product_name AS productName,
        po.nps_no AS productOrderNpsNo,
        ROUND(pwo.complete_quantity / pwo.plan_quantity * 100, 2) AS completionStatus,
src/main/resources/mapper/production/ProductionProductInputMapper.xml
@@ -15,6 +15,7 @@
        pm.model as model,
        ppm.product_no as productNo,
        p.product_name,
        pm.drawing_number,
        pm.unit
        from
        production_product_input ppi
src/main/resources/mapper/production/ProductionProductMainMapper.xml
@@ -19,6 +19,7 @@
        u.nick_name as nickName,
        p.product_name as productName,
        pm.model as productModelName,
        pm.drawing_number,
        ppo.quantity,
        ppo.scrap_qty,
        pm.unit,
@@ -64,6 +65,7 @@
        sl.customer_name,
        p.product_name,
        pm.model as product_model_name,
        pm.drawing_number,
        pm.unit,
        slpa.process,
        ppo.quantity,
src/main/resources/mapper/production/ProductionProductOutputMapper.xml
@@ -14,6 +14,7 @@
    <select id="listPageProductionProductOutputDto" resultType="com.ruoyi.production.dto.ProductionProductOutputDto">
        select ppo.*,
        pm.model as model,
        pm.drawing_number,
        ppm.product_no as productNo
        from
        production_product_output ppo
src/main/resources/mapper/production/SalesLedgerProductionAccountingMapper.xml
@@ -84,8 +84,7 @@
            </if>
        </where>
        GROUP BY slpa.scheduling_user_name
        GROUP BY slpa.scheduling_user_name,slpa.scheduling_user_id
    </select>
    <select id="selectDailyWagesStats" resultType="java.util.Map">
src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -97,7 +97,7 @@
                AND slp.product_category like concat('%',#{req.productCategory},'%')
            </if>
            <if test="req.status != null and req.status ">
                AND slp.pending_invoice_total &gt; 0
                AND slp.pending_tickets_total &gt; 0
            </if>
        </where>
        order by slp.register_date desc