huminmin
3 天以前 931beabfe37a733b6d2fb92119dab3aabe869c98
Merge branch 'dev_宁夏_中盛建材' of http://114.132.189.42:9002/r/product-inventory-management-after into dev_宁夏_中盛建材

# Conflicts:
# src/main/java/com/ruoyi/productionPlan/controller/ProductionPlanController.java
# src/main/java/com/ruoyi/productionPlan/service/ProductionPlanService.java
已添加1个文件
已修改5个文件
183 ■■■■■ 文件已修改
src/main/java/com/ruoyi/productionPlan/controller/ProductionPlanController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/productionPlan/dto/ProductionPlanSummaryDto.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/productionPlan/mapper/ProductionPlanMapper.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/productionPlan/service/ProductionPlanService.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/productionPlan/service/impl/ProductionPlanServiceImpl.java 61 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/productionPlan/ProductionPlanMapper.xml 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/productionPlan/controller/ProductionPlanController.java
@@ -5,6 +5,7 @@
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.productionPlan.dto.ProductionPlanDto;
import com.ruoyi.productionPlan.dto.ProductionPlanSummaryDto;
import com.ruoyi.productionPlan.service.ProductionPlanService;
import com.ruoyi.staff.dto.StaffLeaveDto;
import io.swagger.annotations.Api;
@@ -38,6 +39,7 @@
    }
    @GetMapping("/loadProdData")
    @ApiOperation("拉取销售生产计划")
    @Log(title = "拉取销售生产计划", businessType = BusinessType.INSERT)
    public AjaxResult loadProdData() {
        productionPlanService.loadProdData();
@@ -49,4 +51,12 @@
    public AjaxResult combine(@RequestBody ProductionPlanDto productionPlanDto) {
        return AjaxResult.success(productionPlanService.combine(productionPlanDto));
    }
    @GetMapping("/summaryByProductType")
    @ApiOperation("按照产品类别汇总统计需求量")
    @Log(title = "按照产品类别汇总统计需求量", businessType = BusinessType.OTHER)
    public AjaxResult summaryByProductType(ProductionPlanSummaryDto query) {
        List<ProductionPlanSummaryDto> list = productionPlanService.summaryByProductType(query);
        return AjaxResult.success(list);
    }
}
src/main/java/com/ruoyi/productionPlan/dto/ProductionPlanSummaryDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,70 @@
package com.ruoyi.productionPlan.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
 * <br>
 * é”€å”®ç”Ÿäº§éœ€æ±‚ - äº§å“ç±»åž‹æ±‡æ€»DTO
 * </br>
 *
 * @author deslrey
 * @version 1.0
 * @since 2026/03/11 10:24
 */
@Data
@ApiModel("生产需求产品汇总")
public class ProductionPlanSummaryDto {
    /**
     * ç‰©æ–™ç¼–码
     */
    @ApiModelProperty("物料编码")
    private String materialCode;
    /**
     * äº§å“åç§°
     */
    @ApiModelProperty("产品名称")
    private String productName;
    /**
     * äº§å“è§„æ ¼
     */
    @ApiModelProperty("产品规格")
    private String productSpec;
    /**
     * äº§å“é•¿åº¦
     */
    @ApiModelProperty("产品长度")
    private Integer length;
    /**
     * äº§å“å®½åº¦
     */
    @ApiModelProperty("产品宽度")
    private Integer width;
    /**
     * äº§å“é«˜åº¦
     */
    @ApiModelProperty("产品高度")
    private Integer height;
    /**
     * æ±‡æ€»å—æ•°
     */
    @ApiModelProperty("汇总块数")
    private Integer quantity;
    /**
     * æ±‡æ€»æ–¹æ•°
     */
    @ApiModelProperty("汇总方数")
    private BigDecimal volume;
}
src/main/java/com/ruoyi/productionPlan/mapper/ProductionPlanMapper.java
@@ -4,9 +4,11 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.productionPlan.dto.ProductionPlanDto;
import com.ruoyi.productionPlan.dto.ProductionPlanSummaryDto;
import com.ruoyi.productionPlan.pojo.ProductionPlan;
import com.ruoyi.staff.dto.StaffLeaveDto;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * <br>
@@ -19,4 +21,7 @@
 */
public interface ProductionPlanMapper extends BaseMapper<ProductionPlan> {
    IPage<ProductionPlanDto> listPage(Page page, @Param("c") ProductionPlanDto productionPlanDto);
    List<ProductionPlanSummaryDto> selectSummaryByProductType(ProductionPlanSummaryDto query);
}
src/main/java/com/ruoyi/productionPlan/service/ProductionPlanService.java
@@ -4,6 +4,7 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.productionPlan.dto.ProductionPlanDto;
import com.ruoyi.productionPlan.dto.ProductionPlanSummaryDto;
import com.ruoyi.productionPlan.pojo.ProductionPlan;
import java.util.List;
@@ -34,4 +35,9 @@
     * åˆå¹¶ç”Ÿäº§è®¡åˆ’
     */
    boolean combine(ProductionPlanDto productionPlanDto);
    /**
     * æŒ‰ç…§äº§å“ç±»åˆ«æ±‡æ€»ç»Ÿè®¡éœ€æ±‚量
     */
    List<ProductionPlanSummaryDto> summaryByProductType(ProductionPlanSummaryDto query);
}
src/main/java/com/ruoyi/productionPlan/service/impl/ProductionPlanServiceImpl.java
@@ -14,6 +14,7 @@
import com.ruoyi.production.pojo.ProductOrder;
import com.ruoyi.production.service.ProductOrderService;
import com.ruoyi.productionPlan.dto.ProductionPlanDto;
import com.ruoyi.productionPlan.dto.ProductionPlanSummaryDto;
import com.ruoyi.productionPlan.mapper.ProductionPlanMapper;
import com.ruoyi.productionPlan.pojo.ProductionPlan;
import com.ruoyi.productionPlan.service.ProductionPlanService;
@@ -30,9 +31,9 @@
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
/**
 * <br>
@@ -186,8 +187,8 @@
                List<ProductionPlan> list = parseProductionPlans(dataArr, dataSyncType, totalCount);
                if (!list.isEmpty()) {
                    //  å¤„理更新或新增
                    processSaveOrUpdate(list);
                    totalSynced += list.size();
                    int affected = processSaveOrUpdate(list);
                    totalSynced += affected;
                }
                //  åˆ¤æ–­æ˜¯å¦è¿˜æœ‰ä¸‹ä¸€é¡µ
@@ -330,19 +331,48 @@
        return list;
    }
    private void processSaveOrUpdate(List<ProductionPlan> list) {
    private int processSaveOrUpdate(List<ProductionPlan> list) {
        if (list == null || list.isEmpty()) {
            return 0;
        }
        int affected = 0;
        //  åŽ»é‡ formInstanceId
        Set<String> formIds = list.stream()
                .map(ProductionPlan::getFormInstanceId)
                .collect(Collectors.toSet());
        //  æŸ¥è¯¢æ•°æ®åº“已有数据
        List<ProductionPlan> existList = this.list(new LambdaQueryWrapper<ProductionPlan>().in(ProductionPlan::getFormInstanceId, formIds));
        //  Map (formInstanceId + materialCode)
        Map<String, ProductionPlan> existMap = new HashMap<>();
        for (ProductionPlan p : existList) {
            String key = p.getFormInstanceId() + "_" + p.getMaterialCode();
            existMap.put(key, p);
        }
        //  éåŽ†åŒæ­¥æ•°æ®
        for (ProductionPlan plan : list) {
            LambdaQueryWrapper<ProductionPlan> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ProductionPlan::getFormInstanceId, plan.getFormInstanceId())
                    .eq(ProductionPlan::getMaterialCode, plan.getMaterialCode());
            ProductionPlan existing = this.getOne(queryWrapper);
            if (existing != null) {
                plan.setId(existing.getId());
                this.updateById(plan);
            } else {
            String key = plan.getFormInstanceId() + "_" + plan.getMaterialCode();
            ProductionPlan exist = existMap.get(key);
            if (exist == null) {
                // æ–°å¢ž
                this.save(plan);
                affected++;
                log.info("新增数据 formInstanceId={}, materialCode={}", plan.getFormInstanceId(), plan.getMaterialCode());
            } else {
                // åˆ¤æ–­æ˜¯å¦éœ€è¦æ›´æ–°
                if (exist.getFormModifiedTime() == null || !exist.getFormModifiedTime().equals(plan.getFormModifiedTime())) {
                    plan.setId(exist.getId());
                    plan.setCreateTime(exist.getCreateTime());
                    this.updateById(plan);
                    affected++;
                    log.info("更新数据 formInstanceId={}, materialCode={}", plan.getFormInstanceId(), plan.getMaterialCode());
            }
        }
        }
        return affected;
    }
    private LocalDateTime parseUtcTime(String utcString) {
@@ -357,4 +387,9 @@
            return null;
        }
    }
    @Override
    public List<ProductionPlanSummaryDto> summaryByProductType(ProductionPlanSummaryDto query) {
        return baseMapper.selectSummaryByProductType(query);
    }
}
src/main/resources/mapper/productionPlan/ProductionPlanMapper.xml
@@ -44,4 +44,33 @@
        WHERE 1 = 1
    </select>
    <select id="selectSummaryByProductType" resultType="com.ruoyi.productionPlan.dto.ProductionPlanSummaryDto">
        SELECT
        material_code,
        product_name,
        product_spec,
        length,
        width,
        height,
        COALESCE(SUM(quantity),0) AS quantity,
        COALESCE(SUM(volume),0) AS volume
        FROM production_plan
        <where>
            <if test="materialCode != null and materialCode != ''">
                AND material_code LIKE CONCAT('%', #{materialCode}, '%')
            </if>
            <if test="productName != null and productName != ''">
                AND product_name LIKE CONCAT('%', #{productName}, '%')
            </if>
        </where>
        GROUP BY
        material_code,
        product_name,
        product_spec,
        length,
        width,
        height
    </select>
</mapper>