sfd
2025-05-26 2a64b537e8e3bce9ce030585a3da17d48379c0ad
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsPartRouteStatServiceImpl.java
@@ -1,17 +1,40 @@
package com.aps.core.service.impl;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import com.aps.common.core.utils.poi.ExcelUtil;
import com.aps.common.core.utils.uuid.IdUtils;
import com.aps.common.core.utils.uuid.UUID;
import com.aps.common.core.web.domain.AjaxResult;
import com.aps.core.domain.ApsPartPlan;
import com.aps.core.domain.ApsResourceDateStat;
import com.aps.core.domain.ApsResourceGroup;
import com.aps.core.mapper.ApsAbnormalProcessAnalysisMapper;
import com.aps.core.mapper.ApsResourceGroupMapper;
import com.aps.core.service.IApsAbnormalProcessAnalysisService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Removal;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.commons.config.DefaultsBindHandlerAdvisor;
import org.springframework.stereotype.Service;
import com.aps.core.mapper.ApsPartRouteStatMapper;
import com.aps.core.domain.ApsPartRouteStat;
import com.aps.core.service.IApsPartRouteStatService;
import org.springframework.transaction.annotation.Transactional;
import static java.util.stream.Collectors.groupingBy;
@@ -21,12 +44,20 @@
 * @author zhl
 * @date 2025-04-11
 */
@Slf4j
@Service
public class ApsPartRouteStatServiceImpl implements IApsPartRouteStatService 
{
    @Autowired
    private ApsPartRouteStatMapper apsPartRouteStatMapper;
    private DefaultsBindHandlerAdvisor.MappingsProvider mappingsProvider;
    @Autowired
    private ApsResourceGroupMapper resourceGroupMapper;
    @Autowired
    private ApsResourceGroupMapper apsResourceGroupMapper;
    @Resource
    private IApsAbnormalProcessAnalysisService analysisService;
    /**
     * 查询零件统计表
@@ -103,13 +134,17 @@
    /**
     * 查询零件工序并更新计划开工日期
     * */
    @Transactional
    @Override
    public void updatePartRoutPlanDate() {
        List<ApsPartRouteStat> tempList = apsPartRouteStatMapper.selectPartRoutStat();
        /*对tempList 按照 workOrderNo 进行分组*/
        Map<String, List<ApsPartRouteStat>> groupByWorkOrderNo = tempList.stream().collect(groupingBy(ApsPartRouteStat::getWorkOrderNo));
        /*本次计算批次号*/
        String batchNum = IdUtils.fastSimpleUUID();
        apsPartRouteStatMapper.deleteLastBatch(batchNum);
        for (Map.Entry<String, List<ApsPartRouteStat>> entry : groupByWorkOrderNo.entrySet()) {
            /*取出每个零件工单的工艺路线信息*/
            List<ApsPartRouteStat> apsPartRouteStatList = entry.getValue();
@@ -118,28 +153,191 @@
            /*临时保存 上一道工序的工序总工时*/
            ApsPartRouteStat last=null;
            for (int i = 0; i <apsPartRouteStatList.size(); i++) {
                ApsPartRouteStat stat = apsPartRouteStatList.get(0);
                ApsPartRouteStat stat = apsPartRouteStatList.get(i);
                /*判断当前工序 当前工序只有一条*/
                if (stat.getCurrentProcessNumber().equals(stat.getRoadProcessNumber())) {
                    /* 对 stat.getProcessPlanStartDay() 和当前日期 进行对比,只对比到日,不用管十分秒*/
                    if (stat.getProcessPlanStartDay().toLocalDate().isBefore(LocalDateTime.now().toLocalDate())) {
                        stat.setProcessPlanStartDay(LocalDateTime.now());
                    LocalDate startLocalDate = LocalDate.ofInstant(stat.getProcessPlanStartDay().toInstant(), ZoneId.systemDefault());
                    LocalDate nowLocalDate = LocalDate.now();
                    if (startLocalDate.isBefore(nowLocalDate)) {
                        stat.setProcessPlanStartDay(new Date());
                    }
                }
                /*未开工工序的计划开工日=上一道工序的计划开工日+上一道工序的工序总工时。*/
                if (stat.getCurrentProcessNumber().compareTo(stat.getRoadProcessNumber()) > 0) {
                if (stat.getCurrentProcessNumber().compareTo(stat.getRoadProcessNumber()) < 0) {
                    if (last != null) {
                        stat.setProcessPlanStartDay(last.getProcessPlanStartDay().plusHours(last.getProcessTotalTime()));
                        LocalDateTime lastStartDate = LocalDateTime.ofInstant(last.getProcessPlanStartDay().toInstant(), ZoneId.systemDefault());
                        long seconds = last.getProcessTotalTime().multiply(new BigDecimal(60)).multiply(new BigDecimal(60)).longValue();
                        LocalDateTime currentStartDate = lastStartDate.plusSeconds(seconds);
                        stat.setProcessPlanStartDay(Date.from(currentStartDate.atZone(ZoneId.systemDefault()).toInstant()));
                    }
                }
                /*保存上一步计算的 开工日*/
                last = stat;
                stat.setId(IdUtils.fastUUID().toString());
                stat.setBatchNumber(batchNum);
                stat.setDelFlag("0");
                apsPartRouteStatMapper.insertApsPartRouteStat(stat);
            }
        }
        apsPartRouteStatMapper.deleteLastBatch(batchNum);
        /*计算并保存 工序异常信息*/
        analysisService.batchSaveAbnormalInfo();
    }
    /** 查询资源日历表
     */
    @Override
    public AjaxResult selectResourceDateStat() {
        /*查出所有统计的数据*/
        AjaxResult result = new AjaxResult(200, "生成成功");
        List<ApsResourceDateStat> list = apsPartRouteStatMapper.selectResourceDateStat();
        List<ApsResourceGroup> resourceGroupList = apsResourceGroupMapper.selectApsResourceGroupList(new ApsResourceGroup());
        if (!list.isEmpty()) {
            /*求出计划的最大时间,没有 设置为当前时间+15天*/
            ApsResourceDateStat apsResourceDateStat = list.stream().max(Comparator.comparing(ApsResourceDateStat::getPlanDay)).orElse(null);
            LocalDate maxPlanDay = LocalDate.now().plus(15, ChronoUnit.DAYS);
            if (apsResourceDateStat != null) {
                maxPlanDay = apsResourceDateStat.getPlanDay();
            }
            /*组织出日期表头*/
            List<String> planDays = new ArrayList<>();
            LocalDate startDay = LocalDate.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            while (!startDay.isAfter(maxPlanDay)) {
                planDays.add(startDay.format(formatter));
                startDay = startDay.plus(1, ChronoUnit.DAYS);
            }
            /*组织出列头数据*/
            /*准备资源组信息*/
            List<Map<String, List<ApsResourceDateStat>>> targetList = new ArrayList<>();
            resourceGroupList.forEach(resourceGroup -> {
                String resourceName=resourceGroup.getResourceGroupName();
                        /*根据日期表头的顺序,组织出每个日期下的统计项目*/
                Map<String, List<ApsResourceDateStat>> maps = new HashMap<>(Map.of());
                List<ApsResourceDateStat> currentDaysResouces=new ArrayList<>();
                for (String planDay : planDays) {
                    /*查找当前计划日期下的所有资源组的数据*/
                    Optional<ApsResourceDateStat> first = list.stream()
                            .filter(item ->
                                    item.getPlanDay().equals(LocalDate.parse(planDay, formatter))
                                 && item.getResourceGroupName().equals(resourceName)
                            ).collect(Collectors.toList()).stream().findFirst();
                    if(first.isPresent()){
                        currentDaysResouces.add(first.get());
                    }
                    else {
                        ApsResourceDateStat empty = new ApsResourceDateStat();
                        empty.setPlanDay(LocalDate.parse(planDay, formatter));
                      //  empty.setDesignTimes(resourceGroup.getDevicesQuantity().intValue()*resourceGroup.getTheoryHours().intValue());
                        empty.setDesignTimes(resourceGroup.getTheoryHours().multiply(BigDecimal.valueOf( resourceGroup.getDevicesQuantity())));
                        empty.setRequireTimes(BigDecimal.ZERO);
                        empty.setResourceName(resourceName);
                        empty.setResourceGroupName(resourceName);
                        empty.setCapacityLoad(BigDecimal.ZERO);
                        currentDaysResouces.add(empty);
                    }
                };
                maps.put(resourceName, currentDaysResouces);
                targetList.add(maps);
            });
            result.put("planTitle", planDays);
            result.put("planTable", targetList);
        }
        return result;
    }
    @Override
    public void exportExcel(HttpServletResponse response) {
        SXSSFWorkbook wb = new SXSSFWorkbook(500);
        wb.createSheet();
        wb.setSheetName(0, "零件统计表");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        Map<String, CellStyle> styles = createStyles(wb);
        CellStyle title = styles.get("title");
        try
        {
            AjaxResult stat = selectResourceDateStat();
            List<String> days = (List<String>) stat.get("planTitle");
            List<Map<String, List<ApsResourceDateStat>>> table= (List<Map<String, List<ApsResourceDateStat>>>) stat.get("planTable");
            SXSSFSheet sheet = wb.getSheetAt(0);
            /*填写日期列 和 工时列*/
            SXSSFRow rowDay = sheet.createRow(0);
            SXSSFRow rowTitle = sheet.createRow(1);
            SXSSFCell daytitle = rowDay.createCell(0);
            daytitle.setCellValue("日期");
            daytitle.setCellStyle(title);
            SXSSFCell titleCell = rowTitle.createCell(0);
            titleCell.setCellValue("资源组");
            titleCell.setCellStyle(title);
            for (int i = 0; i < days.size(); i++) {
                SXSSFCell dateCell = rowDay.createCell(i * 3 + 1);
                SXSSFCell designHoursCell = rowTitle.createCell(i * 3 + 1);
                SXSSFCell requireHoursCell = rowTitle.createCell(i * 3 + 2);
                SXSSFCell loadCell = rowTitle.createCell(i * 3 + 3);
                dateCell.setCellValue(days.get(i));
                designHoursCell.setCellValue("设计工时");
                requireHoursCell.setCellValue("需求工时");
                loadCell.setCellValue("产能负荷");
                /*set cell style*/
                dateCell.setCellStyle(title);
                designHoursCell.setCellStyle(title);
                requireHoursCell.setCellStyle(title);
                loadCell.setCellStyle(title);
                /*合并日期单元格*/
                sheet.addMergedRegion( new CellRangeAddress(0, 0, i*3+1, i*3+3));
            }
            for (int i = 0; i < table.size(); i++) {
                Map<String, List<ApsResourceDateStat>> resourceList = table.get(i);
                /*创建数据行*/
                SXSSFRow dataRow  = sheet.createRow(i+2);
                for( Map.Entry<String, List<ApsResourceDateStat>> entry : resourceList.entrySet()){
                    String resourceName = entry.getKey();
                    List<ApsResourceDateStat> resourceDateStats = entry.getValue();
                    dataRow.createCell(0).setCellValue(resourceName);
                    for (int j = 0; j < resourceDateStats.size(); j++) {
                        ApsResourceDateStat apsResourceDateStat = resourceDateStats.get(j);
                        dataRow.createCell(j*3+1).setCellValue(apsResourceDateStat.getDesignTimes().doubleValue());
                        dataRow.createCell(j*3+2).setCellValue(apsResourceDateStat.getRequireTimes().doubleValue());
                        dataRow.createCell(j*3+3).setCellValue(apsResourceDateStat.getCapacityLoad().doubleValue()+"%");
                    }
                }
            }
            wb.write(response.getOutputStream());
        }
        catch (Exception e)
        {
            log.error("导出Excel异常{}", e.getMessage());
        }
        finally
        {
            IOUtils.closeQuietly(wb);
        }
    }
    private Map<String,CellStyle> createStyles(SXSSFWorkbook wb)
    {
        Map<String,CellStyle> styles=new HashMap<>();
        CellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        Font titleFont = wb.createFont();
        titleFont.setFontName("Arial");
        titleFont.setFontHeightInPoints((short) 12);
        titleFont.setBold(true);
        style.setFont(titleFont);
        DataFormat dataFormat = wb.createDataFormat();
        style.setDataFormat(dataFormat.getFormat("@"));
        styles.put("title", style);
        return styles;
    }
}