maven
2025-10-14 cf6b1cf6fa8f7784c6d7c64b7326d4662bc3d4b3
yys
1.智能排产
2.物料看板
3.报表分析
已添加8个文件
已修改10个文件
1030 ■■■■■ 文件已修改
main-business/pom.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/controller/ProductHomeController.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/dto/CarDto.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/dto/DateQueryDto.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/dto/ItemListDto.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/dto/MaterialStatisticsDto.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/dto/ProductionSchedulingStatisticsDto.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/dto/ReportStatisticsDto.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/entity/OfficialInventory.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/entity/PendingInventory.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/entity/ProductionScheduling.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/entity/PurchaseRegistration.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/ProductHomeService.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/impl/PendingInventoryServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/impl/ProductHomeServiceImpl.java 590 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/impl/PurchaseRegistrationServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/pom.xml 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/MyBaseEntity.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/pom.xml
@@ -64,6 +64,12 @@
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
        </dependency>
        <dependency>
            <groupId>io.swagger.core.v3</groupId>
            <artifactId>swagger-annotations-jakarta</artifactId>
            <version>2.2.22</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
    <properties>
main-business/src/main/java/com/ruoyi/business/controller/ProductHomeController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,115 @@
package com.ruoyi.business.controller;
import com.ruoyi.business.dto.*;
import com.ruoyi.business.entity.OfficialInventory;
import com.ruoyi.business.entity.ProductionScheduling;
import com.ruoyi.business.entity.PurchaseRegistration;
import com.ruoyi.business.service.ProductHomeService;
import com.ruoyi.common.core.domain.R;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
 * @author :yys
 * @date : 2025/10/13 9:12
 */
@Tag(name = "生产管控统计报表")
@RestController
@RequestMapping("/productHome")
public class ProductHomeController {
    @Autowired
    private ProductHomeService productHomeService;
    @GetMapping("/productionSchedulingStatistics")
    @Operation(summary = "智能排产-生产排程统计")
    public R<ProductionSchedulingStatisticsDto> productionSchedulingStatistics(DateQueryDto dto) {
        return productHomeService.productionSchedulingStatistics(dto);
    }
    @GetMapping("/productionSchedulingStatisticsList")
    @Operation(summary = "智能排产-生产排程统计列表")
    public R<List<ProductionScheduling>> productionSchedulingStatisticsList(DateQueryDto dto) {
        return productHomeService.productionSchedulingStatisticsList(dto);
    }
    @Operation(summary = "智能排产-库存原料列表")
    @GetMapping("/productionSchedulingInventoryList")
    public R<List<OfficialInventory>> productionSchedulingInventoryList(DateQueryDto dto) {
        return productHomeService.productionSchedulingInventoryList(dto);
    }
    @Operation(summary = "物料看板-统计")
    @GetMapping("/materialStatistics")
    public R<MaterialStatisticsDto> materialStatistics(DateQueryDto dto) {
        return productHomeService.materialStatistics(dto);
    }
    @Operation(summary = "物料看板-煤种分布")
    @GetMapping("/coalTypeDistribution")
    public R<List<ItemListDto>> coalTypeDistribution(DateQueryDto dto) {
        return productHomeService.coalTypeDistribution(dto);
    }
    @Operation(summary = "物料看板-产地分布")
    @GetMapping("/originDistribution")
    public R<List<ItemListDto>> originDistribution(DateQueryDto dto) {
        return productHomeService.originDistribution(dto);
    }
    @Operation(summary = "物料看板-热值分布")
    @GetMapping("/heatValueDistribution")
    public R<List<ItemListDto>> heatValueDistribution(DateQueryDto dto) {
        return productHomeService.heatValueDistribution(dto);
    }
    @Operation(summary = "物料看板-车次编码统计")
    @GetMapping("/carCodeDistribution")
    public R<List<CarDto>> carCodeDistribution(DateQueryDto dto) {
        return productHomeService.carCodeDistribution(dto);
    }
    @Operation(summary = "物料看板-最近交易记录")
    @GetMapping("/recentTransaction")
    public R<List<PurchaseRegistration>> recentTransaction(DateQueryDto dto) {
        return productHomeService.recentTransaction(dto);
    }
    @Operation(summary = "报表分析-统计")
    @GetMapping("/reportStatistics")
    public R<ReportStatisticsDto> reportStatistics(DateQueryDto dto) {
        return productHomeService.reportStatistics(dto);
    }
    @Operation(summary = "报表分析-达标率趋势")
    @GetMapping("/reportTrend")
    public R<List<ItemListDto>> reportTrend(DateQueryDto dto) {
        return productHomeService.reportTrend(dto);
    }
    @Operation(summary = "报表分析-煤种发热量对比")
    @GetMapping("/coalTypeHeatValueComparison")
    public R<List<ItemListDto>> coalTypeHeatValueComparison(DateQueryDto dto) {
        return productHomeService.coalTypeHeatValueComparison(dto);
    }
    @Operation(summary = "报表分析-加工得率分析")
    @GetMapping("/processingRateAnalysis")
    public R<List<ItemListDto>> processingRateAnalysis(DateQueryDto dto) {
        return productHomeService.processingRateAnalysis(dto);
    }
    @Operation(summary = "报表分析-成本结构图谱")
    @GetMapping("/costStructure")
    public R<List<ItemListDto>> costStructure(DateQueryDto dto) {
        return productHomeService.costStructure(dto);
    }
}
main-business/src/main/java/com/ruoyi/business/dto/CarDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
package com.ruoyi.business.dto;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author :yys
 * @date : 2025/10/13 14:03
 */
@Data
@Schema
public class CarDto {
    @ApiModelProperty("车辆编号")
    @Schema(description = "车辆编号")
    private String code;
    @ApiModelProperty("次数")
    @Schema(description = "次数")
    private Integer count;
    @ApiModelProperty("总量(吨)")
    @Schema(description = "总量(吨)")
    private BigDecimal total;
}
main-business/src/main/java/com/ruoyi/business/dto/DateQueryDto.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
main-business/src/main/java/com/ruoyi/business/dto/ItemListDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
package com.ruoyi.business.dto;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author :yys
 * @date : 2025/10/13 13:34
 */
@Data
@Schema
public class ItemListDto {
    @ApiModelProperty(value = "名称")
    @Schema(title = "名称")
    private String name;
    @ApiModelProperty(value = "值")
    @Schema(title = "值")
    private BigDecimal value = BigDecimal.ZERO;
    @ApiModelProperty(value = "占比")
    @Schema(title = "占比")
    private BigDecimal percent;
}
main-business/src/main/java/com/ruoyi/business/dto/MaterialStatisticsDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.ruoyi.business.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author :yys
 * @date : 2025/10/13 10:12
 */
@Data
@Schema
public class MaterialStatisticsDto {
    // ä»Šæ—¥å…¥åº“总量
    @Schema(title = "今日入库总量")
    private BigDecimal todayInboundTotal = BigDecimal.ZERO;
    // ä»Šæ—¥å‡ºåº“总量
    @Schema(title = "今日出库总量")
    private BigDecimal todayOutboundTotal = BigDecimal.ZERO;
    // å½“前库存总量
    @Schema(title = "当前库存总量")
    private BigDecimal currentInventoryTotal = BigDecimal.ZERO;
}
main-business/src/main/java/com/ruoyi/business/dto/ProductionSchedulingStatisticsDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.ruoyi.business.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author :yys
 * @date : 2025/10/13 9:18
 */
@Schema
@Data
public class ProductionSchedulingStatisticsDto {
    @Schema(title = "总排产量")
    private BigDecimal totalOutput = BigDecimal.ZERO;
    @Schema(title = "已完成排产")
    private BigDecimal completedScheduling = BigDecimal.ZERO;
    @Schema(title = "待排产")
    private BigDecimal pendingScheduling = BigDecimal.ZERO;
    @Schema(title = "库存预警(1-9随机数)")
    private Integer inventoryWarning = (int)(Math.random()*10);
}
main-business/src/main/java/com/ruoyi/business/dto/ReportStatisticsDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
package com.ruoyi.business.dto;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.models.auth.In;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Random;
/**
 * @author :yys
 * @date : 2025/10/13 16:44
 */
@Data
@Schema
public class ReportStatisticsDto {
    @ApiModelProperty("单位热值耗煤量")
    @Schema(title = "单位热值耗煤量")
    private BigDecimal unitHeatValue = BigDecimal.ZERO;
    @ApiModelProperty("整体达标率")
    @Schema(title = "整体达标率")
    private BigDecimal wholeStandardRate = BigDecimal.ZERO;
    @ApiModelProperty("平均发热量")
    @Schema(title = "平均发热量")
    private BigDecimal averageFuel = BigDecimal.ZERO;
    @ApiModelProperty("配方使用频次(1-100随机数)")
    @Schema(title = "配方使用频次(1-100随机数)")
    private Integer frequency = new Random().nextInt(100);
    @ApiModelProperty("总批次(1-100随机数)")
    @Schema(title = "总批次(1-100随机数)")
    private Integer totalBatch = new Random().nextInt(100);
}
main-business/src/main/java/com/ruoyi/business/entity/OfficialInventory.java
@@ -6,6 +6,7 @@
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.MyBaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@@ -19,6 +20,7 @@
 */
@Data
@TableName("official_inventory")
@Schema
public class OfficialInventory extends MyBaseEntity {
    /**
@@ -26,15 +28,25 @@
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     *
     * é‡‡è´­å•号
     */
    @TableField(value = "purchase_number")
    @Schema(title = "采购单号")
    private String purchaseNumber;
    /**
     * å¾…入库id
     */
    @TableField(value = "pending_id")
    @Schema(title = "待入库id")
    private Long pendingId;
    /**
     * ä¾›è´§å•†ID
     */
    @TableField(value = "supplier_id")
    @Schema(title = "供货商ID")
    private Long supplierId;
    /**
     * ç¼–号
@@ -46,52 +58,69 @@
     * ç…¤æ–™ç±»åž‹ 1-成品 2-原料
     */
    @TableField(value = "type")
    @Schema(title = "煤料类型 1-成品 2-原料")
    private Integer type;
    /**
     * ç…¤ç§
     */
    @TableField(value = "coal_id")
    @Schema(title = "煤种")
    private Long coalId;
    /**
     * ç…¤ç§åç§°
     */
    @TableField(exist = false)
    @Schema(title = "煤种名称")
    private String coalName;
    /**
     * å•位
     */
    @TableField(value = "unit")
    @Schema(title = "单位")
    private String unit;
    /**
     * åº“存数量
     */
    @TableField(value = "inventory_quantity")
    @Schema(title = "库存数量")
    private BigDecimal inventoryQuantity;
    /**
     * å•价(含税)
     */
    @TableField(value = "price_including_tax")
    @Schema(title = "单价(含税)")
    private BigDecimal priceIncludingTax;
    /**
     * æ€»ä»·ï¼ˆå«ç¨Žï¼‰
     */
    @TableField(value = "total_price_including_tax")
    @Schema(title = "总价(含税)")
    private BigDecimal totalPriceIncludingTax;
    /**
     * ä¸å«ç¨Žå•ä»·
     */
    @TableField(value = "price_excluding_tax")
    @Schema(title = "不含税单价")
    private BigDecimal priceExcludingTax;
    /**
     * ä¸å«ç¨Žæ€»ä»·
     */
    @TableField(value = "total_price_excluding_tax")
    @Schema(title = "不含税总价")
    private BigDecimal totalPriceExcludingTax;
    /**
     * å¾…补库
     */
    @TableField(value = "pending_replenishment")
    @Schema(title = "待补库")
    private BigDecimal pendingReplenishment;
    /**
     * ç™»è®°äººid
     */
    @TableField(value = "registrant_id")
    @Schema(title = "登记人id")
    private Long registrantId;
    /**
@@ -99,17 +128,20 @@
     */
    @TableField(value = "registration_date")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @Schema(title = "登记日期")
    private LocalDate registrationDate;
    /**
     * ç…¤è´¨æ–¹æ¡ˆid
     */
    @TableField(value = "coal_plan_id")
    @Schema(title = "煤质方案id")
    private Long coalPlanId;
    /**
     * åˆå¹¶id
     */
    @TableField(value = "merge_id")
    @Schema(title = "合并id")
    private String mergeId;
}
main-business/src/main/java/com/ruoyi/business/entity/PendingInventory.java
@@ -33,6 +33,13 @@
     */
    @TableField(value = "master_id")
    private Long masterId;
    /**
     *
     * é‡‡è´­å•号
     */
    @TableField(value = "purchase_number")
    private String purchaseNumber;
    /**
     *
     * é‡‡è´­id
main-business/src/main/java/com/ruoyi/business/entity/ProductionScheduling.java
@@ -6,6 +6,7 @@
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.MyBaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
@@ -19,6 +20,7 @@
 */
@Data
@TableName("production_scheduling")
@Schema
public class ProductionScheduling extends MyBaseEntity {
    private static final long serialVersionUID = 1L;
@@ -32,12 +34,21 @@
     *  ç”Ÿäº§æ˜Žç»†id
     */
    @TableField(value = "production_id")
    @Schema(title = "生产明细id")
    private Long productionId;
    /**
     * ç…¤ç§ID
     */
    @TableField(value = "coal_id")
    @Schema(title = "煤种ID")
    private Long coalId;
    /**
     * ç…¤ç§åç§°
     */
    @Schema(title = "煤种名称")
    @TableField(exist = false)
    private String coalName;
    /**
     * æ€»æ•°é‡
@@ -51,38 +62,45 @@
     * æŽ’产数量
     */
    @TableField(value = "scheduling_num")
    @Schema(title = "排产数量")
    private BigDecimal schedulingNum;
    /**
     * å…¥åº“数量
     */
    @TableField(value = "success_num")
    @Schema(title = "入库数量")
    private BigDecimal successNum;
    /**
     * ç…¤æ–™ç±»åž‹ï¼ˆ1-成品 2-原料)
     */
    @TableField(value = "type")
    @Schema(title = "煤料类型(1-成品 2-原料)")
    private Integer type;
    /**
     *状态(1-待生产 2-生产中 3-已报工)
     */
    @TableField(value = "status")
    @Schema(title = "状态(1-待生产 2-生产中 3-已报工)")
    private Integer status;
    /**
     * å•位
     */
    @TableField(value = "unit")
    @Schema(title = "单位")
    private String unit;
    /**
     * å·¥åºï¼ˆå­—典)
     */
    @TableField(value = "process")
    @Schema(title = "工序(字典)")
    private String process;
    /**
     * å·¥æ—¶å®šé¢
     */
    @TableField(value = "work_hours")
    @Schema(title = "工时定额")
    private BigDecimal workHours;
    /**
     * æŽ’产日期
@@ -90,16 +108,19 @@
    @TableField(value = "scheduling_date")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @Schema(title = "排产日期")
    private Date schedulingDate;
    /**
     * æŽ’产人id
     */
    @TableField(value = "scheduling_user_id")
    @Schema(title = "排产人id")
    private Long schedulingUserId;
    /**
     * æŽ’产人名称
     */
    @TableField(value = "scheduling_user_name")
    @Schema(title = "排产人名称")
    private String schedulingUserName;
}
main-business/src/main/java/com/ruoyi/business/entity/PurchaseRegistration.java
@@ -5,6 +5,7 @@
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.MyBaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@@ -18,6 +19,7 @@
 */
@Data
@TableName("purchase_registration")
@Schema
public class PurchaseRegistration extends MyBaseEntity {
    private static final long serialVersionUID = 1L;
@@ -27,77 +29,105 @@
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * é‡‡è´­å•号
     */
    @TableField(value = "purchase_number")
    @Schema(title = "采购单号")
    private String purchaseNumber;
    /**
     *  ä¾›åº”商id
     */
    @TableField(value = "supplier_id")
    @Schema(title = "供应商id")
    private Long supplierId;
    /**
     * ä¾›åº”商名称
     */
    @TableField(value = "supplier_name")
    @Schema(title = "供应商名称")
    private String supplierName;
    /**
     * å•位
     */
    @TableField(value = "unit")
    @Schema(title = "单位")
    private String unit;
    /**
     *
     */
    @TableField(value = "coal_id")
    @Schema(title = "煤料id")
    private Long coalId;
    /**
     * ç…¤æ–™åç§°
     */
    @TableField(exist = false)
    @Schema(title = "煤料名称")
    private String coalName;
    /**
     * é‡‡è´­æ•°é‡
     */
    @TableField(value = "purchase_quantity")
    @Schema(title = "采购数量")
    private BigDecimal purchaseQuantity;
    /**
     * å•价(含税)
     */
    @TableField(value = "price_including_tax")
    @Schema(title = "单价(含税)")
    private BigDecimal priceIncludingTax;
    /**
     * æ€»ä»·ï¼ˆå«ç¨Žï¼‰
     */
    @TableField(value = "total_price_including_tax")
    @Schema(title = "总价(含税)")
    private BigDecimal totalPriceIncludingTax;
    /**
     * ç¨Žçއ
     */
    @TableField(value = "tax_rate")
    @Schema(title = "税率")
    private BigDecimal taxRate;
    /**
     * ä¸å«ç¨Žå•ä»·
     */
    @TableField(value = "price_excluding_tax")
    @Schema(title = "不含税单价")
    private BigDecimal priceExcludingTax;
    /**
     * ä¸å«ç¨Žæ€»ä»·
     */
    @TableField(value = "total_price_excluding_tax")
    @Schema(title = "不含税总价")
    private BigDecimal totalPriceExcludingTax;
    /**
     * ç™»è®°äººid
     */
    @TableField(value = "registrant_id")
    @Schema(title = "登记人id")
    private Long registrantId;
    /**
     * ç™»è®°æ—¥æœŸ
     */
    @TableField(value = "registration_date")
    @Schema(title = "登记日期")
    private LocalDate registrationDate;
    /**
     * è¿è´¹
     */
    @TableField(value = "freight")
    @Schema(title = "运费")
    private BigDecimal freight;
    /**
     * ç±»åž‹ï¼ˆ1-成品,2-原料)
     */
    @TableField(value = "type")
    @Schema(title = "类型(1-成品,2-原料)")
    private Integer type;
    /**
     * é‡‡è´­ç±»åž‹
@@ -109,5 +139,6 @@
     * è½¦ç‰Œå·
     */
    @TableField(value = "license_plate")
    @Schema(title = "车牌号")
    private String licensePlate;
}
main-business/src/main/java/com/ruoyi/business/service/ProductHomeService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,43 @@
package com.ruoyi.business.service;
import com.ruoyi.business.dto.*;
import com.ruoyi.business.entity.OfficialInventory;
import com.ruoyi.business.entity.ProductionScheduling;
import com.ruoyi.business.entity.PurchaseRegistration;
import com.ruoyi.common.core.domain.R;
import java.util.List;
/**
 * @author :yys
 * @date : 2025/10/13 9:11
 */
public interface ProductHomeService {
    R<ProductionSchedulingStatisticsDto> productionSchedulingStatistics(DateQueryDto dto);
    R<List<ProductionScheduling>> productionSchedulingStatisticsList(DateQueryDto dto);
    R<List<OfficialInventory>> productionSchedulingInventoryList(DateQueryDto dto);
    R<MaterialStatisticsDto> materialStatistics(DateQueryDto dto);
    R<List<ItemListDto>> coalTypeDistribution(DateQueryDto dto);
    R<List<ItemListDto>> originDistribution(DateQueryDto dto);
    R<List<CarDto>> carCodeDistribution(DateQueryDto dto);
    R<List<PurchaseRegistration>> recentTransaction(DateQueryDto dto);
    R<List<ItemListDto>> heatValueDistribution(DateQueryDto dto);
    R<ReportStatisticsDto> reportStatistics(DateQueryDto dto);
    R<List<ItemListDto>> reportTrend(DateQueryDto dto);
    R<List<ItemListDto>> coalTypeHeatValueComparison(DateQueryDto dto);
    R<List<ItemListDto>> processingRateAnalysis(DateQueryDto dto);
    R<List<ItemListDto>> costStructure(DateQueryDto dto);
}
main-business/src/main/java/com/ruoyi/business/service/impl/PendingInventoryServiceImpl.java
@@ -286,6 +286,7 @@
            if (pendingInventoryDto.getOfficialId() == null) {
                OfficialInventory officialInventory = new OfficialInventory();
                BeanUtils.copyProperties(pendingInventory, officialInventory);
                officialInventory.setPurchaseNumber(pendingInventory.getPurchaseNumber());
                officialInventory.setId(null);
                officialInventory.setCoalPlanId(pendingInventoryDto.getCoalPlanId());
                officialInventory.setPendingId(pendingInventoryDto.getPId());
main-business/src/main/java/com/ruoyi/business/service/impl/ProductHomeServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,590 @@
package com.ruoyi.business.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.basic.entity.CoalInfo;
import com.ruoyi.basic.entity.CoalPlan;
import com.ruoyi.basic.entity.CoalValue;
import com.ruoyi.basic.entity.Customer;
import com.ruoyi.basic.mapper.CoalInfoMapper;
import com.ruoyi.basic.mapper.CoalPlanMapper;
import com.ruoyi.basic.mapper.CoalValueMapper;
import com.ruoyi.basic.mapper.CustomerMapper;
import com.ruoyi.business.dto.*;
import com.ruoyi.business.entity.*;
import com.ruoyi.business.mapper.*;
import com.ruoyi.business.service.ProductHomeService;
import com.ruoyi.common.core.domain.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
 * @author :yys
 * @date : 2025/10/13 9:11
 */
@Service
@Slf4j
public class ProductHomeServiceImpl implements ProductHomeService {
    @Autowired
    private ProductionMapper productionMapper;
    @Autowired
    private ProductionSchedulingMapper productionSchedulingMapper;
    @Autowired
    private OfficialInventoryMapper officialInventoryMapper;
    @Autowired
    private SalesRecordMapper salesRecordMapper;
    @Autowired
    private CoalInfoMapper coalInfoMapper;
    @Autowired
    private CustomerMapper customerMapper;
    @Autowired
    private PurchaseRegistrationMapper purchaseRegistrationMapper;
    @Autowired
    private CoalValueMapper coalValueMapper;
    @Autowired
    private CoalPlanMapper coalPlanMapper;
    @Override
    public R<ProductionSchedulingStatisticsDto> productionSchedulingStatistics(DateQueryDto dto) {
        String start = dto.getEntryDateStart();
        String end = dto.getEntryDateEnd();
        // ä½¿ç”¨ LambdaQueryWrapper æž„建查询条件
        LambdaQueryWrapper<ProductionScheduling> wrapper = new LambdaQueryWrapper<>();
        if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) {
            wrapper.between(ProductionScheduling::getSchedulingDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE));
        }
        List<ProductionScheduling> schedulingList = productionSchedulingMapper.selectList(wrapper);
        ProductionSchedulingStatisticsDto result = new ProductionSchedulingStatisticsDto();
        BigDecimal totalScheduling = BigDecimal.ZERO;
        BigDecimal completedScheduling = BigDecimal.ZERO;
        BigDecimal pendingScheduling = BigDecimal.ZERO;
        for (ProductionScheduling scheduling : schedulingList) {
            BigDecimal num = scheduling.getSchedulingNum();
            if (num != null) {
                totalScheduling = totalScheduling.add(num);
                if (scheduling.getStatus() == 3) { // å·²æŠ¥å·¥
                    completedScheduling = completedScheduling.add(num);
                } else if (scheduling.getStatus() == 1) { // å¾…生产
                    pendingScheduling = pendingScheduling.add(num);
                }
            }
        }
        result.setTotalOutput(totalScheduling);
        result.setCompletedScheduling(completedScheduling);
        result.setPendingScheduling(pendingScheduling);
        return R.ok(result);
    }
    @Override
    public R<List<ProductionScheduling>> productionSchedulingStatisticsList(DateQueryDto dto) {
        String start = dto.getEntryDateStart();
        String end = dto.getEntryDateEnd();
        // ä½¿ç”¨ LambdaQueryWrapper æž„建查询条件
        LambdaQueryWrapper<ProductionScheduling> wrapper = new LambdaQueryWrapper<>();
        if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) {
            wrapper.between(ProductionScheduling::getSchedulingDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE));
        }
        List<ProductionScheduling> schedulingList = productionSchedulingMapper.selectList(wrapper);
        // é€šè¿‡ç…¤ç§id获取煤种名称
        schedulingList.forEach(scheduling -> {
            CoalInfo coalInfo = coalInfoMapper.selectById(scheduling.getCoalId());
            scheduling.setCoalName(coalInfo.getCoal());
        });
        return R.ok(schedulingList);
    }
    @Override
    public R<List<OfficialInventory>> productionSchedulingInventoryList(DateQueryDto dto) {
        String start = dto.getEntryDateStart();
        String end = dto.getEntryDateEnd();
        // ä½¿ç”¨ LambdaQueryWrapper æž„建查询条件
        LambdaQueryWrapper<OfficialInventory> wrapper = new LambdaQueryWrapper<>();
        if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) {
            wrapper.between(OfficialInventory::getRegistrationDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE));
        }
        List<OfficialInventory> schedulingList = officialInventoryMapper.selectList(wrapper);
        schedulingList.forEach(scheduling -> {
            CoalInfo coalInfo = coalInfoMapper.selectById(scheduling.getCoalId());
            scheduling.setCoalName(coalInfo.getCoal());
        });
        return R.ok(schedulingList);
    }
    @Override
    public R<MaterialStatisticsDto> materialStatistics(DateQueryDto dto) {
        MaterialStatisticsDto result = new MaterialStatisticsDto();
        // èŽ·å–ä»Šæ—¥å¼€å§‹æ—¶é—´ï¼Œç»“æŸæ—¶é—´
        LocalDateTime todayStart = LocalDateTime.of(
                LocalDateTime.now().toLocalDate(),
                LocalTime.MIN
        );
        LocalDateTime todayEnd = LocalDateTime.of(
                LocalDateTime.now().toLocalDate(),
                LocalTime.MAX
        );
        // ä½¿ç”¨ LambdaQueryWrapper æž„建查询条件
        LambdaQueryWrapper<OfficialInventory> wrapper = new LambdaQueryWrapper<>();
        wrapper.between(OfficialInventory::getRegistrationDate, todayStart, todayEnd);
        // èŽ·å–ä»Šæ—¥å…¥åº“æ€»é‡
        List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(wrapper);
        if (!CollectionUtils.isEmpty(officialInventories)) {
            BigDecimal todayInboundTotal = officialInventories.stream()
                    .map(OfficialInventory::getInventoryQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            result.setTodayInboundTotal(todayInboundTotal);
        }
        // èŽ·å–å½“å‰åº“å­˜æ€»é‡
        R<List<OfficialInventory>> listR = productionSchedulingInventoryList(dto);
        if (R.isSuccess(listR)) {
            List<OfficialInventory> officialInventoriesList = listR.getData();
            if (!CollectionUtils.isEmpty(officialInventoriesList)) {
                BigDecimal todayOutboundTotal = officialInventoriesList.stream()
                        .map(OfficialInventory::getInventoryQuantity)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                result.setTodayOutboundTotal(todayOutboundTotal);
            }
        }
        // èŽ·å–ä»Šæ—¥å‡ºåº“æ€»é‡
        // ä½¿ç”¨ LambdaQueryWrapper æž„建查询条件
        LambdaQueryWrapper<SalesRecord> wrapperSalesRecord = new LambdaQueryWrapper<>();
        wrapperSalesRecord.between(SalesRecord::getSaleDate, todayStart, todayEnd);
        // èŽ·å–ä»Šæ—¥å…¥åº“æ€»é‡
        List<SalesRecord> salesRecords = salesRecordMapper.selectList(wrapperSalesRecord);
        if (!CollectionUtils.isEmpty(salesRecords)) {
            BigDecimal todayInboundTotal = salesRecords.stream()
                    .map(SalesRecord::getInventoryQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            result.setTodayOutboundTotal(todayInboundTotal);
        }
        return R.ok(result);
    }
    @Override
    public R<List<ItemListDto>> coalTypeDistribution(DateQueryDto dto) {
        String start = dto.getEntryDateStart();
        String end = dto.getEntryDateEnd();
        // èŽ·å–ç…¤ç§åˆ—è¡¨
        List<CoalInfo> coalInfoList = coalInfoMapper.selectList(null);
        // ä½¿ç”¨ LambdaQueryWrapper æž„建查询条件
        LambdaQueryWrapper<SalesRecord> wrapper = new LambdaQueryWrapper<>();
        if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) {
            wrapper.between(SalesRecord::getRegistrationDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE));
        }
        List<SalesRecord> salesRecords = salesRecordMapper.selectList(wrapper);
        // æ ¹æ®ç…¤ç§è¿›è¡Œåˆ†ç»„,并计算占比
        Map<Long, List<SalesRecord>> coalTypeMap = salesRecords.stream()
                .collect(Collectors.groupingBy(SalesRecord::getCoalId));
        List<ItemListDto> itemListDtos = coalInfoList.stream().map(coalInfo -> {
            ItemListDto itemListDto = new ItemListDto();
            itemListDto.setName(coalInfo.getCoal());
            // è®¡ç®—该煤种的销售记录总数量
            List<SalesRecord> records = coalTypeMap.getOrDefault(coalInfo.getId(), Collections.emptyList());
            BigDecimal totalQuantity = records.stream()
                    .map(SalesRecord::getInventoryQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            itemListDto.setValue(totalQuantity);
            return itemListDto;
        }).collect(Collectors.toList());
        // è®¡ç®—所有煤种的销售总量
        BigDecimal totalAll = itemListDtos.stream()
                .map(ItemListDto::getValue)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        // è®¾ç½®å æ¯”
        for (ItemListDto item : itemListDtos) {
            if (totalAll.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal percentage = item.getValue().multiply(BigDecimal.valueOf(100))
                        .divide(totalAll, 2, RoundingMode.HALF_UP);
                item.setPercent(percentage);
            } else {
                item.setPercent(BigDecimal.ZERO);
            }
        }
        return R.ok(itemListDtos);
    }
    @Override
    public R<List<ItemListDto>> originDistribution(DateQueryDto dto) {
        String start = dto.getEntryDateStart();
        String end = dto.getEntryDateEnd();
        // èŽ·å–å®¢æˆ·åˆ—è¡¨
        List<Customer> coalInfoList = customerMapper.selectList(null);
        // ä½¿ç”¨ LambdaQueryWrapper æž„建查询条件
        LambdaQueryWrapper<SalesRecord> wrapper = new LambdaQueryWrapper<>();
        if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) {
            wrapper.between(SalesRecord::getRegistrationDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE));
        }
        List<SalesRecord> salesRecords = salesRecordMapper.selectList(wrapper);
        // æ ¹æ®ç…¤ç§è¿›è¡Œåˆ†ç»„,并计算占比
        Map<Long, List<SalesRecord>> coalTypeMap = salesRecords.stream()
                .collect(Collectors.groupingBy(SalesRecord::getCustomerId));
        List<ItemListDto> itemListDtos = coalInfoList.stream().map(coalInfo -> {
            ItemListDto itemListDto = new ItemListDto();
            itemListDto.setName(coalInfo.getCustomerName());
            // è®¡ç®—该煤种的销售记录总数量
            List<SalesRecord> records = coalTypeMap.getOrDefault(coalInfo.getId(), Collections.emptyList());
            BigDecimal totalQuantity = records.stream()
                    .map(SalesRecord::getInventoryQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            itemListDto.setValue(totalQuantity);
            return itemListDto;
        }).collect(Collectors.toList());
        // è®¡ç®—所有煤种的销售总量
        BigDecimal totalAll = itemListDtos.stream()
                .map(ItemListDto::getValue)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        // è®¾ç½®å æ¯”
        for (ItemListDto item : itemListDtos) {
            if (totalAll.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal percentage = item.getValue().multiply(BigDecimal.valueOf(100))
                        .divide(totalAll, 2, RoundingMode.HALF_UP);
                item.setPercent(percentage);
            } else {
                item.setPercent(BigDecimal.ZERO);
            }
        }
        return R.ok(itemListDtos);
    }
    @Override
    public R<List<CarDto>> carCodeDistribution(DateQueryDto dto) {
        String start = dto.getEntryDateStart();
        String end = dto.getEntryDateEnd();
        // ä½¿ç”¨ LambdaQueryWrapper æž„建查询条件
        LambdaQueryWrapper<PurchaseRegistration> wrapper = new LambdaQueryWrapper<>();
        if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) {
            wrapper.between(PurchaseRegistration::getRegistrationDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE));
        }
        List<PurchaseRegistration> purchaseRegistrations = purchaseRegistrationMapper.selectList(wrapper);
        // é€šè¿‡è½¦ç‰Œå·åˆ†ç»„获取次数,计算总量
        Map<String, List<PurchaseRegistration>> carMap = purchaseRegistrations.stream()
                .collect(Collectors.groupingBy(PurchaseRegistration::getLicensePlate));
        List<CarDto> carDtos = carMap.entrySet().stream().map(entry -> {
            CarDto carDto = new CarDto();
            carDto.setCode(entry.getKey());
            carDto.setCount(entry.getValue().size());
            carDto.setTotal(entry.getValue().stream()
                    .map(PurchaseRegistration::getPurchaseQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));
            return carDto;
        }).collect(Collectors.toList());
        return R.ok(carDtos);
    }
    @Override
    public R<List<PurchaseRegistration>> recentTransaction(DateQueryDto dto) {
        String start = dto.getEntryDateStart();
        String end = dto.getEntryDateEnd();
        // ä½¿ç”¨ LambdaQueryWrapper æž„建查询条件
        LambdaQueryWrapper<PurchaseRegistration> wrapper = new LambdaQueryWrapper<>();
        if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) {
            wrapper.between(PurchaseRegistration::getRegistrationDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE));
        }
        List<PurchaseRegistration> purchaseRegistrations = purchaseRegistrationMapper.selectList(wrapper);
        purchaseRegistrations.forEach(purchaseRegistration -> {
            purchaseRegistration.setCoalName(coalInfoMapper.selectById(purchaseRegistration.getCoalId()).getCoal());
        });
        return R.ok(purchaseRegistrations);
    }
    @Override
    public R<List<ItemListDto>> heatValueDistribution(DateQueryDto dto) {
        String start = dto.getEntryDateStart();
        String end = dto.getEntryDateEnd();
        LambdaQueryWrapper<OfficialInventory> officialInventoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) {
            officialInventoryLambdaQueryWrapper.between(OfficialInventory::getRegistrationDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE));
        }
        List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(officialInventoryLambdaQueryWrapper);
        Map<String, BigDecimal> heatValueMap = new HashMap<>();
        BigDecimal totalQuantity = BigDecimal.ZERO;
        for (OfficialInventory officialInventory : officialInventories) {
            List<CoalValue> coalValues = coalValueMapper.selectList(new LambdaQueryWrapper<CoalValue>()
                    .eq(CoalValue::getPlanId, officialInventory.getId())
                    .eq(CoalValue::getFieldName, "发热量"));
            if (coalValues != null && !coalValues.isEmpty()) {
                // æ ¹æ®å‘热量值进行分类统计
                heatValueMap.put("4000以下", BigDecimal.ZERO);
                heatValueMap.put("4000-4500", BigDecimal.ZERO);
                heatValueMap.put("4500-5000", BigDecimal.ZERO);
                heatValueMap.put("5000-5500", BigDecimal.ZERO);
                heatValueMap.put("5500-6000", BigDecimal.ZERO);
                heatValueMap.put("6000+", BigDecimal.ZERO);
                for (CoalValue coalValue : coalValues) {
                    BigDecimal heatValue = BigDecimal.valueOf(Long.parseLong(coalValue.getCoalValue()));
                    if (heatValue == null) continue;
                    if (heatValue.compareTo(BigDecimal.valueOf(4000)) < 0) {
                        heatValueMap.put("4000以下", heatValueMap.get("4000以下").add(officialInventory.getInventoryQuantity()));
                    } else if (heatValue.compareTo(BigDecimal.valueOf(4000)) >= 0 && heatValue.compareTo(BigDecimal.valueOf(4500)) < 0) {
                        heatValueMap.put("4000-4500", heatValueMap.get("4000-4500").add(officialInventory.getInventoryQuantity()));
                    } else if (heatValue.compareTo(BigDecimal.valueOf(4500)) >= 0 && heatValue.compareTo(BigDecimal.valueOf(5000)) < 0) {
                        heatValueMap.put("4500-5000", heatValueMap.get("4500-5000").add(officialInventory.getInventoryQuantity()));
                    } else if (heatValue.compareTo(BigDecimal.valueOf(5000)) >= 0 && heatValue.compareTo(BigDecimal.valueOf(5500)) < 0) {
                        heatValueMap.put("5000-5500", heatValueMap.get("5000-5500").add(officialInventory.getInventoryQuantity()));
                    } else if (heatValue.compareTo(BigDecimal.valueOf(5500)) >= 0 && heatValue.compareTo(BigDecimal.valueOf(6000)) < 0) {
                        heatValueMap.put("5500-6000", heatValueMap.get("5500-6000").add(officialInventory.getInventoryQuantity()));
                    } else {
                        heatValueMap.put("6000+", heatValueMap.get("6000+").add(officialInventory.getInventoryQuantity()));
                    }
                }
            }
        }
        // è®¡ç®—总量
        totalQuantity = heatValueMap.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        // å°†ç»“果转换为 ItemListDto åˆ—表
        BigDecimal finalTotalQuantity = totalQuantity;
        List<ItemListDto> itemListDtos = heatValueMap.entrySet().stream()
                .map(entry -> {
                    ItemListDto itemListDto = new ItemListDto();
                    itemListDto.setName(entry.getKey());
                    itemListDto.setValue(entry.getValue());
                    if (finalTotalQuantity.compareTo(BigDecimal.ZERO) > 0) {
                        BigDecimal percentage = entry.getValue().multiply(BigDecimal.valueOf(100))
                                .divide(finalTotalQuantity, 2, RoundingMode.HALF_UP);
                        itemListDto.setPercent(percentage);
                    }
                    return itemListDto;
                })
                .collect(Collectors.toList());
        return R.ok(itemListDtos);
    }
    @Override
    public R<ReportStatisticsDto> reportStatistics(DateQueryDto dto) {
        ReportStatisticsDto reportStatisticsDto = new ReportStatisticsDto();
        String start = dto.getEntryDateStart();
        String end = dto.getEntryDateEnd();
        LambdaQueryWrapper<OfficialInventory> officialInventoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) {
            officialInventoryLambdaQueryWrapper.between(OfficialInventory::getRegistrationDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE));
        }
        List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(officialInventoryLambdaQueryWrapper);
        if(!CollectionUtils.isEmpty(officialInventories)){
            BigDecimal reduce = officialInventories.stream()
                    .map(OfficialInventory::getInventoryQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            List<CoalValue> coalValues = coalValueMapper.selectList(new LambdaQueryWrapper<CoalValue>()
                    .in(CoalValue::getPlanId, officialInventories.stream().map(OfficialInventory::getId).collect(Collectors.toList()))
                    .eq(CoalValue::getFieldName, "发热量"));
            BigDecimal totalQuantity = coalValues.stream()
                    .map(coalValue -> BigDecimal.valueOf(Long.parseLong(coalValue.getCoalValue())))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            long count = coalValues.stream()
                    .filter(coalValue -> BigDecimal.valueOf(Long.parseLong(coalValue.getCoalValue())).compareTo(BigDecimal.valueOf(5000)) >= 0)
                    .count();
            if (!coalValues.isEmpty()){
                // å•位热值耗煤量 = reduce * 1000 / totalQuantity
                BigDecimal heatValue = reduce.multiply(BigDecimal.valueOf(1000)).divide(totalQuantity, 2, RoundingMode.HALF_UP);
                reportStatisticsDto.setUnitHeatValue(heatValue);
                // å¹³å‡å‘热量
                reportStatisticsDto.setAverageFuel(totalQuantity.divide(BigDecimal.valueOf(coalValues.size()), 2, RoundingMode.HALF_UP));
                // æ•´ä½“达标率(发热量≥5000大卡)
                BigDecimal wholeStandardRate = BigDecimal.valueOf(count).divide(BigDecimal.valueOf(coalValues.size()), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
                reportStatisticsDto.setWholeStandardRate(wholeStandardRate);
            }else{
                reportStatisticsDto.setAverageFuel(BigDecimal.ZERO);
                reportStatisticsDto.setWholeStandardRate(BigDecimal.ZERO);
                reportStatisticsDto.setUnitHeatValue(BigDecimal.ZERO);
            }
        }
        return R.ok(reportStatisticsDto);
    }
    @Override
    public R<List<ItemListDto>> reportTrend(DateQueryDto dto) {
        List<LocalDate> lastFiveDaysQuery = getLastFiveDaysQuery();
        List<ItemListDto> itemListDtos = new ArrayList<>();
        for (LocalDate s : lastFiveDaysQuery) {
            ItemListDto itemListDto = new ItemListDto();
            itemListDto.setName(s.toString());
            LambdaQueryWrapper<OfficialInventory> officialInventoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
            // åœ¨s后面拼上00:00:00
            officialInventoryLambdaQueryWrapper.eq(OfficialInventory::getRegistrationDate, s);
            List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(officialInventoryLambdaQueryWrapper);
            if(!CollectionUtils.isEmpty(officialInventories)){
                List<CoalValue> coalValues = coalValueMapper.selectList(new LambdaQueryWrapper<CoalValue>()
                        .in(CoalValue::getPlanId, officialInventories.stream().map(OfficialInventory::getId).collect(Collectors.toList()))
                        .eq(CoalValue::getFieldName, "发热量"));
                // æ•´ä½“达标率(发热量≥5000大卡)
                long count = coalValues.stream()
                        .filter(coalValue -> BigDecimal.valueOf(Long.parseLong(coalValue.getCoalValue())).compareTo(BigDecimal.valueOf(5000)) >= 0)
                        .count();
                // åˆ¤æ–­é™¤æ•°ä¸èƒ½ä¸ºé›¶çš„æƒ…况
                if (!coalValues.isEmpty()) {
                    BigDecimal wholeStandardRate = BigDecimal.valueOf(count).divide(BigDecimal.valueOf(coalValues.size()), 2, RoundingMode.HALF_UP);
                    itemListDto.setValue(wholeStandardRate);
                }else{
                    itemListDto.setValue(BigDecimal.ZERO);
                }
            }
            itemListDtos.add(itemListDto);
        }
        return R.ok(itemListDtos);
    }
    @Override
    public R<List<ItemListDto>> coalTypeHeatValueComparison(DateQueryDto dto) {
        List<LocalDate> lastFiveDaysQuery = getLastFiveDaysQuery();
        List<ItemListDto> itemListDtos = new ArrayList<>();
        for (LocalDate s : lastFiveDaysQuery) {
            ItemListDto itemListDto = new ItemListDto();
            itemListDto.setName(s.toString());
            LambdaQueryWrapper<OfficialInventory> officialInventoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
            // åœ¨s后面拼上00:00:00
            officialInventoryLambdaQueryWrapper.eq(OfficialInventory::getRegistrationDate, s);
            List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(officialInventoryLambdaQueryWrapper);
            if(!CollectionUtils.isEmpty(officialInventories)){
                List<CoalValue> coalValues = coalValueMapper.selectList(new LambdaQueryWrapper<CoalValue>()
                        .in(CoalValue::getPlanId, officialInventories.stream().map(OfficialInventory::getId).collect(Collectors.toList()))
                        .eq(CoalValue::getFieldName, "发热量"));
                // å‘热量(求和)
                long count = coalValues.stream()
                        .mapToLong(coalValue -> Long.parseLong(coalValue.getCoalValue()))
                        .sum();
                itemListDto.setValue(BigDecimal.valueOf(count));
            }
            itemListDtos.add(itemListDto);
        }
        return R.ok(itemListDtos);
    }
    @Override
    public R<List<ItemListDto>> processingRateAnalysis(DateQueryDto dto) {
        List<LocalDate> lastFiveDaysQuery = getLastFiveDaysQuery();
        List<ItemListDto> itemListDtos = new ArrayList<>();
        for (LocalDate s : lastFiveDaysQuery) {
            ItemListDto itemListDto = new ItemListDto();
            itemListDto.setName(s.toString());
            // èŽ·å–é‡‡è´­æ•°é‡
            LambdaQueryWrapper<PurchaseRegistration> purchaseRegistrationLambdaQueryWrapper = new LambdaQueryWrapper<>();
            // åœ¨s后面拼上00:00:00
            purchaseRegistrationLambdaQueryWrapper.eq(PurchaseRegistration::getRegistrationDate, s);
            List<PurchaseRegistration> purchaseRegistrations = purchaseRegistrationMapper.selectList(purchaseRegistrationLambdaQueryWrapper);
            if(!CollectionUtils.isEmpty(purchaseRegistrations)){
                BigDecimal totalQuantity = purchaseRegistrations.stream()
                        .map(PurchaseRegistration::getPurchaseQuantity)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                // èŽ·å–æ­£å¼åº“å­˜æ•°é‡
                LambdaQueryWrapper<OfficialInventory> officialInventoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
                // åœ¨s后面拼上00:00:00
                officialInventoryLambdaQueryWrapper.eq(OfficialInventory::getRegistrationDate, s);
                List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(officialInventoryLambdaQueryWrapper);
                if(!CollectionUtils.isEmpty(officialInventories)){
                    BigDecimal officialInventoryQuantity = officialInventories.stream()
                            .map(OfficialInventory::getInventoryQuantity)
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                    // åŠ å·¥å¾—çŽ‡ = æ­£å¼åº“存数量/采购数量
                    if(!totalQuantity.equals(BigDecimal.ZERO)){
                        itemListDto.setValue(officialInventoryQuantity.divide(totalQuantity, 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
                    }else{
                        itemListDto.setValue(BigDecimal.ZERO);
                    }
                }
            }
            itemListDtos.add(itemListDto);
        }
        return R.ok(itemListDtos);
    }
    @Override
    public R<List<ItemListDto>> costStructure(DateQueryDto dto) {
        List<ItemListDto> itemListDtos = new ArrayList<>();
        LocalDate now = LocalDate.now();
        LocalDate startDate = now.minusDays(4);
        LambdaQueryWrapper<Production> productionLambdaQueryWrapper = new LambdaQueryWrapper<>();
        productionLambdaQueryWrapper.between(Production::getCreateTime, startDate, now);
        List<Production> productions = productionMapper.selectList(productionLambdaQueryWrapper);
        ItemListDto itemListDto = new ItemListDto();
        itemListDto.setName("人工成本");
        itemListDto.setValue(productions.stream()
                .map(Production::getLaborCost)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        itemListDtos.add(itemListDto);
        ItemListDto itemListDtoOne = new ItemListDto();
        itemListDtoOne.setName("能耗成本");
        itemListDtoOne.setValue(productions.stream()
                .map(Production::getEnergyConsumptionCost)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        itemListDtos.add(itemListDtoOne);
        return R.ok(itemListDtos);
    }
    /**
     * èŽ·å–æœ€è¿‘äº”å¤©çš„æ—¶é—´é›†åˆ
     */
    private List<LocalDate> getLastFiveDaysQuery() {
        LocalDate now = LocalDate.now();
        LocalDate startDate = now.minusDays(4);
        List<LocalDate> dates = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            LocalDate date = startDate.plusDays(i);
            dates.add(date);
        }
        return dates;
    }
}
main-business/src/main/java/com/ruoyi/business/service/impl/PurchaseRegistrationServiceImpl.java
@@ -14,6 +14,7 @@
import com.ruoyi.business.mapper.PendingInventoryMapper;
import com.ruoyi.business.mapper.PurchaseRegistrationMapper;
import com.ruoyi.business.service.PurchaseRegistrationService;
import com.ruoyi.business.utils.OrderUtils;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
@@ -95,6 +96,9 @@
        }
        purchaseRegistration.setSupplierName(supply.getSupplierName());
        if (Objects.isNull(purchaseRegistrationDto.getId())) {
            // ç”Ÿæˆé‡‡è´­å•号
            String pr = OrderUtils.countTodayByCreateTime(purchaseRegistrationMapper, "PR");
            purchaseRegistration.setPurchaseNumber(pr);
            // æ–°å¢žé‡‡è´­ç™»è®°
            purchaseRegistration.setRegistrationDate(LocalDate.now());
            int insertCount = purchaseRegistrationMapper.insert(purchaseRegistration);
@@ -102,6 +106,7 @@
                // é‡‡è´­ç™»è®°æˆåŠŸï¼ŒåŒæ­¥åˆ›å»ºå¾…å…¥åº“è®°å½•
                PendingInventory pendingInventory = createPendingInventory(purchaseRegistration);
                pendingInventory.setSupplierName(supply.getSupplierName());
                pendingInventory.setPurchaseNumber(pr);
                return pendingInventoryMapper.insert(pendingInventory);
            }
            return insertCount;
ruoyi-common/pom.xml
@@ -144,6 +144,24 @@
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.23</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>mchange-commons-java</artifactId>
            <version>0.2.15</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>io.swagger.core.v3</groupId>
            <artifactId>swagger-annotations-jakarta</artifactId>
            <version>2.2.22</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/MyBaseEntity.java
@@ -6,11 +6,12 @@
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@Schema
public class MyBaseEntity implements Serializable {
    private static final long serialVersionUID = 1L;
@@ -20,19 +21,23 @@
    /** åˆ›å»ºè€… */
    @TableField(fill = FieldFill.INSERT)
    @Schema(title = "创建者")
    private String createBy;
    /** åˆ›å»ºæ—¶é—´ */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @TableField(fill = FieldFill.INSERT, updateStrategy = FieldStrategy.NEVER)
    @Schema(title = "创建时间")
    private LocalDateTime createTime;
    /** æ›´æ–°è€… */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @Schema(title = "更新者")
    private String updateBy;
    /** æ›´æ–°æ—¶é—´ */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @Schema(title = "更新时间")
    private LocalDateTime  updateTime;
}