huangjiayang
2025-04-29 7a31cf800bcc70d598c63863f637cf0a183a940e
Merge remote-tracking branch 'origin/dev' into dev
已修改6个文件
270 ■■■■■ 文件已修改
aps-modules/aps-core/src/main/java/com/aps/core/controller/ApsGasPipingRouteStatController.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/domain/ApsGasPipingRouteStat.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsGasPipingRouteStatMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/IApsGasPipingRouteStatService.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipingRouteStatServiceImpl.java 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/resources/mapper/core/ApsGasPipingRouteStatMapper.xml 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/controller/ApsGasPipingRouteStatController.java
@@ -130,4 +130,10 @@
        apsGasPipingRouteStatService.exportExcel(response, apsGasPipingRouteStat);
    }
    @PostMapping("/saveGasPipingRoutStateList")
    public void saveGasPipingRoutStateList()
    {
        apsGasPipingRouteStatService.saveGasPipingRoutStateList();
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/domain/ApsGasPipingRouteStat.java
@@ -5,6 +5,7 @@
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.springframework.data.annotation.Transient;
@@ -18,6 +19,7 @@
 * @author hjy
 * @date 2025-04-24
 */
@EqualsAndHashCode(callSuper = true)
@Schema(description = "气体管路产能负载统计实体类")
@Data
public class ApsGasPipingRouteStat extends BaseEntity
@@ -36,7 +38,7 @@
    /** 工序号 */
    @Excel(name = "工序号")
    @Schema(description = "工序号", type = "String")
    private String roadProcessNumber;
    private BigDecimal roadProcessNumber;
    /** 当前工序号 */
    @Excel(name = "当前工序号")
@@ -130,6 +132,9 @@
    @Transient
    private String searchType;
    private Boolean warning;
    private Integer num;
    /** 计划完成日 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Excel(name = "计划完工日", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsGasPipingRouteStatMapper.java
@@ -76,4 +76,6 @@
     * @return
     */
    public int insertApsGasPipingRouteStatBatch(List<ApsGasPipingRouteStat> apsGasPipingRouteStatList);
    List<ApsGasPipingRouteStat> queryTempStat();
}
aps-modules/aps-core/src/main/java/com/aps/core/service/IApsGasPipingRouteStatService.java
@@ -3,6 +3,7 @@
import com.alibaba.fastjson2.JSONObject;
import com.aps.core.domain.ApsGasPipingRouteStat;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@@ -82,4 +83,9 @@
     * @param response
     */
    public void exportExcel(HttpServletResponse response, ApsGasPipingRouteStat apsGasPipingRouteStat);
    void saveGasPipingProcessStat();
    @Transactional
    void saveGasPipingRoutStateList();
}
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipingRouteStatServiceImpl.java
@@ -1,5 +1,6 @@
package com.aps.core.service.impl;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson2.JSONObject;
import com.aps.common.core.utils.DateUtils;
import com.aps.common.core.utils.uuid.IdUtils;
@@ -22,6 +23,7 @@
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
@@ -519,4 +521,201 @@
        return yearMonths;
    }
    @Override
    public void saveGasPipingProcessStat(){
        try {
            String batchNum = IdUtils.fastSimpleUUID();
            List<ApsGasPipingRouteStat> tempList = apsGasPipingRouteStatMapper.queryTempStat();
            Map<String, List<ApsGasPipingRouteStat>> groupByOrderNo = tempList.stream().collect(groupingBy(ApsGasPipingRouteStat::getWorkOrderNo));
            Boolean hasBefore = false;
            LocalDateTime now = LocalDateTime.now();
            for (Map.Entry<String, List<ApsGasPipingRouteStat>> entry : groupByOrderNo.entrySet()) {
                List<ApsGasPipingRouteStat> statPerOrder = entry.getValue();
                /*num 为根据完工时间排序出的序号,按此排序,可保证是按完工时间倒叙排列*/
                statPerOrder.sort((a, b)->a.getNum().compareTo(b.getNum()));
                ApsGasPipingRouteStat last=null;
                for (int i = 0; i <statPerOrder.size(); i++) {
                    ApsGasPipingRouteStat stat = statPerOrder.get(i);
                    stat.setId(IdUtils.fastSimpleUUID());
                    stat.setBatchNumber(batchNum);
                    stat.setCreateBy(SecurityUtils.getUsername());
                    stat.setWarning(false);
                    if(i==0){
                        Date orderPlanEndDay = stat.getOrderPlanEndDay();
                        LocalDateTime transLocalDateTime = transLocalDateTime(orderPlanEndDay);
                        LocalTime endOfDay = LocalTime.of(23, 59, 59);
                        LocalDateTime orderPlanEndDayLocalDateTime =  LocalDateTime.of( transLocalDateTime.toLocalDate(), endOfDay);
                        if(orderPlanEndDayLocalDateTime.isBefore(now)){
                            hasBefore = true;
                            stat.setWarning(true);
                            stat.setProcessPlanEndDay(transDate(now));
                            stat.setProcessPlanStartDay(transDate(now));
                        }else {
                            /*计划完工日=钣金计划工单完成时间*/
                            stat.setProcessPlanEndDay(transDate(orderPlanEndDayLocalDateTime));
                            /*计划开工日=钣金计划工单完成时间 -  工序总工时*/
                            long seconds = stat.getProcessTotalTime().multiply(new BigDecimal(60)).multiply(new BigDecimal(60)).longValue();
                            LocalDateTime lastPlanStartDt = orderPlanEndDayLocalDateTime.minusSeconds(seconds);
                            if(lastPlanStartDt.isBefore(now)){
                                hasBefore = true;
                                stat.setProcessPlanStartDay(transDate(now));
                            }else {
                                stat.setProcessPlanStartDay(transDate(lastPlanStartDt));
                            }
                        }
                    }
                    /*当工艺工序号 >= 工单当前工序 代表是未来工序,才进行计划开工日 和计划完工日的计算
                     * 当工艺工序号 < 工单当前工序  过去工序,不进行计算
                     * */
                    if( stat.getRouteProcessNumber().compareTo(stat.getCurrentProcessNumber())>=0){
                        /*倒排时 下一道工序存在 比当前时间小的计划时间,则当前计划开始和结束时间都是当前时间*/
                        if(hasBefore){
                            stat.setWarning(true);
                            stat.setProcessPlanEndDay(transDate(now));
                            stat.setProcessPlanStartDay(transDate(now));
                        }else{
                            /*下一道工序计划时间都正常时,*/
                            if (last != null) {
                                /*当前工序结束时间=下一道工序的开始时间*/
                                stat.setProcessPlanEndDay(last.getProcessPlanStartDay());
                                /*开始时间=结束时间-总工时*/
                                long seconds = stat.getProcessTotalTime().multiply(new BigDecimal(60)).multiply(new BigDecimal(60)).longValue();
                                LocalDateTime crtStartDt = transLocalDateTime(last.getProcessPlanStartDay()).minusSeconds(seconds);
                                /*如果开始时间小于当前时间*/
                                if(crtStartDt.isBefore(now)){
                                    hasBefore=true;
                                    stat.setWarning(true);
                                    stat.setProcessPlanStartDay(transDate(now));
                                }else {
                                    stat.setProcessPlanStartDay(transDate(crtStartDt));
                                }
                            }
                        }
                    }
                    last = stat;
                    apsGasPipingRouteStatMapper.insertApsGasPipingRouteStat(stat);
                }
                hasBefore=false;
            }
            apsGasPipingRouteStatMapper.deleteApsGasPipingRouteStatByBatchNum(batchNum);
        } catch (Exception e) {
            e.printStackTrace();
        }
    };
    private Date transDate(LocalDateTime localDateTime){
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }
    private LocalDateTime transLocalDateTime(Date date){
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }
    /**
     * 保存钣金统计数据
     */
    @Transactional
    @Override
    public void saveGasPipingRoutStateList() {
        String batchNum = IdUtils.fastSimpleUUID();
        List<ApsGasPipingRouteStat> tempList = apsGasPipingRouteStatMapper.queryTempStat();
        Map<String, List<ApsGasPipingRouteStat>> groupByOrderNo = tempList.stream().collect(groupingBy(ApsGasPipingRouteStat::getWorkOrderNo));
        LocalDateTime now = LocalDateTime.now();
        /*待保存的数据*/
        List<ApsGasPipingRouteStat> cptStateList = new ArrayList<>();
        for (Map.Entry<String, List<ApsGasPipingRouteStat>> entry : groupByOrderNo.entrySet()) {
            List<ApsGasPipingRouteStat> statPerOrder = entry.getValue();
            /*num 为根据完工时间排序出的序号,按此排序,可保证是按完工时间倒叙排列*/
            statPerOrder.sort((a, b)->a.getNum().compareTo(b.getNum()));
            ApsGasPipingRouteStat last=null;
            /*当前工序是否存在 计划开工时间 小于 当前的时间,如果存在后续设置为当前时间*/
            boolean hasBefore = false;
            for (int i = 0; i <statPerOrder.size(); i++) {
                ApsGasPipingRouteStat stat = statPerOrder.get(i);
                stat.setId(String.valueOf(IdUtil.getSnowflakeNextId()));
                stat.setBatchNumber(batchNum);
                stat.setCreateTime(DateUtils.getNowDate());
                stat.setCreateBy(SecurityUtils.getUsername());
                stat.setWarning(false);
                stat.setDelFlag("0");
                if(i==0){
                    Date orderPlanEndDay = stat.getOrderPlanEndDay();
                    LocalDateTime transLocalDateTime = transLocalDateTime(orderPlanEndDay);
                    LocalTime endOfDay = LocalTime.of(23, 59, 59);
                    LocalDateTime orderPlanEndDayLocalDateTime =  LocalDateTime.of( transLocalDateTime.toLocalDate(), endOfDay);
                    if(orderPlanEndDayLocalDateTime.isBefore(now)){
                        hasBefore = true;
                        stat.setWarning(true);
                        stat.setProcessPlanEndDay(transDate(now));
                        stat.setProcessPlanStartDay(transDate(now));
                    }else {
                        /*计划完工日=钣金计划工单完成时间*/
                        stat.setProcessPlanEndDay(transDate(orderPlanEndDayLocalDateTime));
                        /*计划开工日=钣金计划工单完成时间 -  工序总工时*/
                        long seconds = stat.getProcessTotalTime().multiply(new BigDecimal(60)).multiply(new BigDecimal(60)).longValue();
                        LocalDateTime lastPlanStartDt = orderPlanEndDayLocalDateTime.minusSeconds(seconds);
                        if(lastPlanStartDt.isBefore(now)){
                            hasBefore = true;
                            stat.setProcessPlanStartDay(transDate(now));
                        }else {
                            stat.setProcessPlanStartDay(transDate(lastPlanStartDt));
                        }
                    }
                }
                /*当工艺工序号 >= 工单当前工序 代表是未来工序,才进行计划开工日 和计划完工日的计算
                 * 当工艺工序号 < 工单当前工序  过去工序,不进行计算
                 * */
                if( stat.getRoadProcessNumber().compareTo(stat.getCurrentProcessNumber())>=0){
                    /*倒排时 下一道工序存在 比当前时间小的计划时间,则当前计划开始和结束时间都是当前时间*/
                    if(hasBefore){
                        stat.setWarning(true);
                        stat.setProcessPlanEndDay(transDate(now));
                        stat.setProcessPlanStartDay(transDate(now));
                    }else{
                        /*下一道工序计划时间都正常时,*/
                        if (last != null) {
                            /*当前工序结束时间=下一道工序的开始时间*/
                            stat.setProcessPlanEndDay(last.getProcessPlanStartDay());
                            /*开始时间=结束时间-总工时*/
                            long seconds = stat.getProcessTotalTime().multiply(new BigDecimal(60)).multiply(new BigDecimal(60)).longValue();
                            LocalDateTime crtStartDt = transLocalDateTime(last.getProcessPlanStartDay()).minusSeconds(seconds);
                            /*如果开始时间小于当前时间*/
                            if(crtStartDt.isBefore(now)){
                                hasBefore=true;
                                stat.setWarning(true);
                                stat.setProcessPlanStartDay(transDate(now));
                            }else {
                                stat.setProcessPlanStartDay(transDate(crtStartDt));
                            }
                        }
                    }
                }
               if(stat.getProcessPlanStartDay()!=null){
                   Date processPlanStartDay = stat.getProcessPlanStartDay();
                   stat.setPlanStartYear(processPlanStartDay.getYear()+"");
                   stat.setPlanStartMonth(processPlanStartDay.getMonth()+"");
                   stat.setPlanStartDay(processPlanStartDay.getDay()+"");
               }
                last = stat;
                cptStateList.add(stat);
            }
        }
        // 批量插入以提高性能
        if (!cptStateList.isEmpty()) {
            int batchSize = 500;
            int size = cptStateList.size();
            for (int i = 0; i < size; i += batchSize) {
                int end = Math.min(i + batchSize, size);
                List<ApsGasPipingRouteStat> batch = cptStateList.subList(i, end);
                apsGasPipingRouteStatMapper.insertApsGasPipingRouteStatBatch(batch);
                log.info("批量插入数据,开始位置:{},结束位置:{}", i, end);
            }
        }
        apsGasPipingRouteStatMapper.deleteApsGasPipingRouteStatByBatchNum(batchNum);
        log.info("批量插入数据完成,batchNum:"+batchNum);
    }
}
aps-modules/aps-core/src/main/resources/mapper/core/ApsGasPipingRouteStatMapper.xml
@@ -26,10 +26,20 @@
        <result property="planStartYear"    column="plan_start_year"    />
        <result property="planStartMonth"    column="plan_start_month"    />
        <result property="planStartDay"    column="plan_start_day"    />
        <result property="processPlanEndDay"    column="process_plan_end_day"    />
        <result property="orderPlanEndDay"    column="order_plan_end_day"    />
        <result property="routeProcessNumber"    column="route_process_number"    />
        <result property="warning"    column="warning"    />
    </resultMap>
    <sql id="selectApsGasPipingRouteStatVo">
        select id, work_order_no, road_process_number, current_process_number, production_quantity, standard_time, process_total_time, process_plan_start_day, design_times, del_flag, create_by, process_name, create_time, item_number, standard_dosage, process_total_dosage, design_capacity, major, plan_start_year, plan_start_month, plan_start_day from aps_gas_piping_route_stat
        select id, work_order_no, road_process_number, current_process_number,
               production_quantity, standard_time, process_total_time,
               process_plan_start_day, design_times, del_flag, create_by,
               process_name, create_time, item_number, standard_dosage,
               process_total_dosage, design_capacity, major, plan_start_year,
               plan_start_month, plan_start_day , warning
        from aps_gas_piping_route_stat
    </sql>
    <select id="selectApsGasPipingRouteStatList" parameterType="ApsGasPipingRouteStat" resultMap="ApsGasPipingRouteStatResult">
@@ -75,7 +85,7 @@
            <if test="productionQuantity != null">production_quantity,</if>
            <if test="standardTime != null">standard_time,</if>
            <if test="processTotalTime != null">process_total_time,</if>
            <if test="processPlanStartDay != null and processPlanStartDay != ''">process_plan_start_day,</if>
            <if test="processPlanStartDay != null ">process_plan_start_day,</if>
            <if test="designTimes != null">design_times,</if>
            <if test="delFlag != null">del_flag,</if>
            <if test="createBy != null">create_by,</if>
@@ -89,6 +99,10 @@
            <if test="planStartYear != null">plan_start_year,</if>
            <if test="planStartMonth != null">plan_start_month,</if>
            <if test="planStartDay != null">plan_start_day,</if>
            <if test="processPlanEndDay != null">process_plan_end_day,</if>
            <if test="orderPlanEndDay != null">order_plan_end_day,</if>
            <if test="batchNumber != null">batch_number,</if>
            <if test="warning != null">warning,</if>
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="id != null">#{id},</if>
@@ -98,7 +112,7 @@
            <if test="productionQuantity != null">#{productionQuantity},</if>
            <if test="standardTime != null">#{standardTime},</if>
            <if test="processTotalTime != null">#{processTotalTime},</if>
            <if test="processPlanStartDay != null and processPlanStartDay != ''">#{processPlanStartDay},</if>
            <if test="processPlanStartDay != null ">#{processPlanStartDay},</if>
            <if test="designTimes != null">#{designTimes},</if>
            <if test="delFlag != null">#{delFlag},</if>
            <if test="createBy != null">#{createBy},</if>
@@ -112,6 +126,10 @@
            <if test="planStartYear != null">#{planStartYear},</if>
            <if test="planStartMonth != null">#{planStartMonth},</if>
            <if test="planStartDay != null">#{planStartDay},</if>
            <if test="processPlanEndDay != null">#{processPlanEndDay},</if>
            <if test="orderPlanEndDay != null">#{orderPlanEndDay},</if>
            <if test="batchNumber != null">#{batchNumber},</if>
            <if test="warning != null">#{warning},</if>
         </trim>
    </insert>
@@ -163,7 +181,7 @@
        id,work_order_no, road_process_number, current_process_number, production_quantity, standard_time,
        process_total_time, process_plan_start_day, design_times, del_flag, create_by, process_name,
        create_time, item_number, standard_dosage, process_total_dosage, design_capacity, major,
        plan_start_year, plan_start_month, plan_start_day,batch_number,process_plan_end_day
        plan_start_year, plan_start_month, plan_start_day,batch_number,process_plan_end_day,warning
        )
        VALUES
        <foreach collection="apsGasPipingRouteStatList" item="stat" separator=",">
@@ -172,10 +190,32 @@
            #{stat.standardTime}, #{stat.processTotalTime}, #{stat.processPlanStartDay}, #{stat.designTimes}, #{stat.delFlag},
            #{stat.createBy}, #{stat.processName}, #{stat.createTime}, #{stat.itemNumber}, #{stat.standardDosage},
            #{stat.processTotalDosage}, #{stat.designCapacity}, #{stat.major}, #{stat.planStartYear},
            #{stat.planStartMonth}, #{stat.planStartDay}, #{stat.batchNumber}, #{stat.processPlanEndDay}
            #{stat.planStartMonth}, #{stat.planStartDay}, #{stat.batchNumber}, #{stat.processPlanEndDay},#{stat.warning}
            )
        </foreach>
    </insert>
    <select id="queryTempStat"  resultMap="ApsGasPipingRouteStatResult" >
        select row_number() over (partition by rt.work_order_no order by rt.process_number desc ) as num,
                rt.work_order_no,
               rt.process_name,
               cast(rt.process_number as numeric(18, 2))           as road_process_number,
               cast(rt.process_number as numeric(18, 2))           as route_process_number,
               cast(pl.process_number as numeric(18, 2))           as current_process_number,
               pl.production_quantity,
               rt.standard_time,
               (rt.standard_time * pl.production_quantity)        as process_total_time,
               rt.process_plan_start_day,
               rt.process_plan_end_day,
               pl.plan_end_day                         as order_plan_end_day,
                rt.item_no as item_number,
                pl.plan_type as major,
               false as warning
        from aps_gas_piping_plan as pl
                 left join aps_process_route as rt on pl.document_number = rt.work_order_no
        where pl.document_number is not null and rt.work_order_no is not null
        order by rt.work_order_no asc, rt.process_number desc
    </select>
</mapper>