Merge remote-tracking branch 'origin/dev_宁夏_中盛建材' into dev_宁夏_中盛建材

# Conflicts:
# src/main/java/com/ruoyi/home/controller/HomeController.java
# src/main/java/com/ruoyi/home/service/HomeService.java
# src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
已添加1个文件
已修改4个文件
207 ■■■■■ 文件已修改
src/main/java/com/ruoyi/home/controller/HomeController.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/dto/SolidWasteCoreIndicatorsDto.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/service/HomeService.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductionRecordServiceImpl.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/controller/HomeController.java
@@ -397,6 +397,24 @@
        return AjaxResult.success(homeService.energy(dto));
    }
    @GetMapping("/solidWaste/coreIndicators")
    @ApiOperation("固废消纳量-核心指标")
    public AjaxResult coreIndicators(productionStatisticsDto dto){
        return AjaxResult.success(homeService.coreIndicators(dto));
    }
    @GetMapping("/solidWaste/trends")
    @ApiOperation("固废消纳量-固废消纳趋势")
    public AjaxResult trends(productionStatisticsDto dto){
        return AjaxResult.success(homeService.trends(dto));
    }
    @GetMapping("/solidWaste/typeDistribution")
    @ApiOperation("固废消纳量-固废类型分布")
    public AjaxResult typeDistribution(productionStatisticsDto dto){
        return AjaxResult.success(homeService.typeDistribution(dto));
    }
    @GetMapping("/manage")
    @ApiOperation("首页--经营关注")
    public AjaxResult manage() {
src/main/java/com/ruoyi/home/dto/SolidWasteCoreIndicatorsDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.ruoyi.home.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
 * å›ºåºŸæ¶ˆçº³é‡æ ¸å¿ƒæŒ‡æ ‡Dto
 *
 * @author deslrey
 * @version 1.0
 * @since 2026/04/02
 */
@Data
@ApiModel(value = "SolidWasteCoreIndicatorsDto", description = "固废消纳量核心指标Dto")
public class SolidWasteCoreIndicatorsDto {
    @ApiModelProperty("合计量")
    private BigDecimal totalAmount = BigDecimal.ZERO;
    @ApiModelProperty("累计消纳量 (自2022å¹´èµ·)")
    private BigDecimal cumulativeAmount = BigDecimal.ZERO;
}
src/main/java/com/ruoyi/home/service/HomeService.java
@@ -120,5 +120,11 @@
    List<HomeEnergyStatisticsDto> energy(productionStatisticsDto dto);
    SolidWasteCoreIndicatorsDto coreIndicators(productionStatisticsDto dto);
    List<SolidWasteStatisticsDto> trends(productionStatisticsDto dto);
    List<MapDto> typeDistribution(productionStatisticsDto dto);
    Map<String,Long> manage();
}
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -3435,6 +3435,157 @@
    }
    @Override
    public SolidWasteCoreIndicatorsDto coreIndicators(productionStatisticsDto dto) {
        if (dto == null) {
            dto = new productionStatisticsDto();
            dto.setDateType(1);
        }
        LocalDate now = LocalDate.now();
        LocalDate startDate = null;
        if (dto.getDateType() != null && dto.getDateType() == 1) { // æœ¬æœˆè‡³ä»Š
            startDate = now.withDayOfMonth(1);
        } else { // æœ¬å¹´è‡³ä»Š
            startDate = now.withDayOfYear(1);
        }
        // ç´¯è®¡æ¶ˆçº³é‡ä»Ž2022-01-01开始
        LocalDate cumulativeStartDate = LocalDate.of(2022, 1, 1);
        // æŸ¥è¯¢ä»Ž2022-01-01至今的所有报工数据
        List<ProductionProductMain> mainList = productionProductMainService.list(Wrappers.<ProductionProductMain>lambdaQuery()
                .ge(ProductionProductMain::getReportingTime, cumulativeStartDate.atStartOfDay()));
        if (CollectionUtils.isEmpty(mainList)) return new SolidWasteCoreIndicatorsDto();
        List<Long> mainIds = mainList.stream().map(ProductionProductMain::getId).collect(Collectors.toList());
        Map<Long, ProductionProductMain> mainMap = mainList.stream().collect(Collectors.toMap(ProductionProductMain::getId, m -> m));
        // èŽ·å–æŠ•å…¥æ˜Žç»†
        List<ProductionProductInput> allInputs = productionProductInputService.list(Wrappers.<ProductionProductInput>lambdaQuery()
                .in(ProductionProductInput::getProductMainId, mainIds));
        if (CollectionUtils.isEmpty(allInputs)) return new SolidWasteCoreIndicatorsDto();
        // èŽ·å–è§„æ ¼å’Œç‰©æ–™åç§°
        Set<Long> skuIds = allInputs.stream().map(ProductionProductInput::getProductId).filter(Objects::nonNull).collect(Collectors.toSet());
        Map<Long, String> skuToMaterialNameMap = new HashMap<>();
        if (!skuIds.isEmpty()) {
            List<ProductMaterialSku> skus = productMaterialSkuService.listByIds(skuIds);
            Set<Long> productIds = skus.stream().map(ProductMaterialSku::getProductId).filter(Objects::nonNull).collect(Collectors.toSet());
            Map<Long, String> materialNameMap = productMaterialService.listByIds(productIds).stream()
                    .collect(Collectors.toMap(ProductMaterial::getId, ProductMaterial::getProductName));
            skuToMaterialNameMap = skus.stream()
                    .filter(s -> s.getProductId() != null && materialNameMap.containsKey(s.getProductId()))
                    .collect(Collectors.toMap(ProductMaterialSku::getId, s -> materialNameMap.get(s.getProductId())));
        }
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal cumulativeAmount = BigDecimal.ZERO;
        Set<String> targetMaterials = new HashSet<>(Arrays.asList("粉煤灰", "石膏", "石灰"));
        for (ProductionProductInput input : allInputs) {
            String materialName = skuToMaterialNameMap.get(input.getProductId());
            if (materialName == null || !targetMaterials.contains(materialName)) continue;
            ProductionProductMain main = mainMap.get(input.getProductMainId());
            if (main == null || main.getReportingTime() == null) continue;
            BigDecimal qty = UnitUtils.convertValueToTon(input.getQuantity(), input.getUnit());
            // ç´¯åŠ ç´¯è®¡æ¶ˆçº³é‡
            cumulativeAmount = cumulativeAmount.add(qty);
            if (!main.getReportingTime().toLocalDate().isBefore(startDate)) {
                totalAmount = totalAmount.add(qty);
            }
        }
        SolidWasteCoreIndicatorsDto result = new SolidWasteCoreIndicatorsDto();
        result.setTotalAmount(totalAmount.setScale(2, RoundingMode.HALF_UP));
        result.setCumulativeAmount(cumulativeAmount.setScale(2, RoundingMode.HALF_UP));
        return result;
    }
    @Override
    public List<SolidWasteStatisticsDto> trends(productionStatisticsDto dto) {
        return solidWaste(dto);
    }
    @Override
    public List<MapDto> typeDistribution(productionStatisticsDto dto) {
        if (dto == null) {
            dto = new productionStatisticsDto();
            dto.setDateType(1);
        }
        LocalDate now = LocalDate.now();
        LocalDate startDate = null;
        if (dto.getDateType() != null && dto.getDateType() == 1) { // æœ¬æœˆè‡³ä»Š
            startDate = now.withDayOfMonth(1);
        } else { // æœ¬å¹´è‡³ä»Š
            startDate = now.withDayOfYear(1);
        }
        // æŸ¥è¯¢æŠ¥å·¥ä¸»è¡¨
        List<ProductionProductMain> mainList = productionProductMainService.list(Wrappers.<ProductionProductMain>lambdaQuery()
                .ge(ProductionProductMain::getReportingTime, startDate.atStartOfDay()));
        if (CollectionUtils.isEmpty(mainList)) return new ArrayList<>();
        List<Long> mainIds = mainList.stream().map(ProductionProductMain::getId).collect(Collectors.toList());
        // èŽ·å–æŠ•å…¥æ˜Žç»†
        List<ProductionProductInput> allInputs = productionProductInputService.list(Wrappers.<ProductionProductInput>lambdaQuery()
                .in(ProductionProductInput::getProductMainId, mainIds));
        if (CollectionUtils.isEmpty(allInputs)) return new ArrayList<>();
        // èŽ·å–è§„æ ¼å’Œç‰©æ–™åç§°
        Set<Long> skuIds = allInputs.stream().map(ProductionProductInput::getProductId).filter(Objects::nonNull).collect(Collectors.toSet());
        Map<Long, String> skuToMaterialNameMap = new HashMap<>();
        if (!skuIds.isEmpty()) {
            List<ProductMaterialSku> skus = productMaterialSkuService.listByIds(skuIds);
            Set<Long> productIds = skus.stream().map(ProductMaterialSku::getProductId).filter(Objects::nonNull).collect(Collectors.toSet());
            Map<Long, String> materialNameMap = productMaterialService.listByIds(productIds).stream()
                    .collect(Collectors.toMap(ProductMaterial::getId, ProductMaterial::getProductName));
            skuToMaterialNameMap = skus.stream()
                    .filter(s -> s.getProductId() != null && materialNameMap.containsKey(s.getProductId()))
                    .collect(Collectors.toMap(ProductMaterialSku::getId, s -> materialNameMap.get(s.getProductId())));
        }
        Map<String, BigDecimal> countMap = new HashMap<>();
        countMap.put("粉煤灰", BigDecimal.ZERO);
        countMap.put("石膏", BigDecimal.ZERO);
        countMap.put("石灰", BigDecimal.ZERO);
        BigDecimal total = BigDecimal.ZERO;
        for (ProductionProductInput input : allInputs) {
            String materialName = skuToMaterialNameMap.get(input.getProductId());
            if (materialName == null || !countMap.containsKey(materialName)) continue;
            BigDecimal qty = UnitUtils.convertValueToTon(input.getQuantity(), input.getUnit());
            countMap.put(materialName, countMap.get(materialName).add(qty));
            total = total.add(qty);
        }
        List<MapDto> result = new ArrayList<>();
        for (Map.Entry<String, BigDecimal> entry : countMap.entrySet()) {
            MapDto mapDto = new MapDto();
            mapDto.setName(entry.getKey());
            BigDecimal value = entry.getValue().setScale(2, RoundingMode.HALF_UP);
            mapDto.setValue(value.toString());
            if (total.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal rate = entry.getValue().divide(total, 4, RoundingMode.HALF_UP)
                        .multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP);
                mapDto.setRate(rate.toString());
            } else {
                mapDto.setRate("0.00");
            }
            result.add(mapDto);
        }
        return result;
    }
    @Override
    public Map<String, Long> manage() {
        Map<String, Long> map = new HashMap<>();
        //生产订单总数
src/main/java/com/ruoyi/production/service/impl/ProductionRecordServiceImpl.java
@@ -206,10 +206,14 @@
        BigDecimal totalQty = productOrder.getQuantity() == null ? BigDecimal.ZERO : productOrder.getQuantity();
        //  å‰©ä½™å¯æŠ¥å·¥æ•°é‡
        BigDecimal remainQty = totalQty.subtract(completeQty);
        //  æœ¬æ¬¡æŠ¥å·¥åˆæ ¼æ•°é‡ä¸èƒ½è¶…过剩余数量(校验必须在累加前执行)
        //  æœ¬æ¬¡æŠ¥å·¥åˆæ ¼æ•°é‡ä¸èƒ½è¶…过剩余数量
        if (qualifiedQty.compareTo(remainQty) > 0) {
            throw new ServiceException("报工失败,本次报工数量不能大于剩余可报工数量,剩余报工数量:[" + remainQty + "]");
        }
        //  æœ¬æ¬¡æŠ¥å·¥ä¸åˆæ ¼æ•°é‡ä¸èƒ½è¶…过本次报工数量
        if (dto.getUnqualifiedQuantity() != null && dto.getUnqualifiedQuantity().compareTo(dto.getQuantity()) > 0) {
            throw new ServiceException("报工失败,本次报工不合格数量不能大于报工数量,报工数量:[" + dto.getQuantity() + "]");
        }
        //  åŽ†å²å·²å®Œæˆ + æœ¬æ¬¡åˆæ ¼æ•°é‡
        BigDecimal newCompleteQty = completeQty.add(qualifiedQty);
        productOrder.setCompleteQuantity(newCompleteQty);