package com.aps.core.service.impl;
|
|
import java.math.BigDecimal;
|
import java.time.LocalDate;
|
import java.time.LocalDateTime;
|
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.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.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;
|
|
/**
|
* 零件统计表Service业务层处理
|
*
|
* @author zhl
|
* @date 2025-04-11
|
*/
|
@Slf4j
|
@Service
|
public class ApsPartRouteStatServiceImpl implements IApsPartRouteStatService
|
{
|
|
@Autowired
|
private ApsPartRouteStatMapper apsPartRouteStatMapper;
|
@Autowired
|
private ApsResourceGroupMapper resourceGroupMapper;
|
@Autowired
|
private ApsResourceGroupMapper apsResourceGroupMapper;
|
|
@Resource
|
private IApsAbnormalProcessAnalysisService analysisService;
|
|
/**
|
* 查询零件统计表
|
*
|
* @param id 零件统计表主键
|
* @return 零件统计表
|
*/
|
@Override
|
public ApsPartRouteStat selectApsPartRouteStatById(String id)
|
{
|
return apsPartRouteStatMapper.selectApsPartRouteStatById(id);
|
}
|
|
/**
|
* 查询零件统计表列表
|
*
|
* @param apsPartRouteStat 零件统计表
|
* @return 零件统计表
|
*/
|
@Override
|
public List<ApsPartRouteStat> selectApsPartRouteStatList(ApsPartRouteStat apsPartRouteStat)
|
{
|
return apsPartRouteStatMapper.selectApsPartRouteStatList(apsPartRouteStat);
|
}
|
|
/**
|
* 新增零件统计表
|
*
|
* @param apsPartRouteStat 零件统计表
|
* @return 结果
|
*/
|
@Override
|
public int insertApsPartRouteStat(ApsPartRouteStat apsPartRouteStat)
|
{
|
return apsPartRouteStatMapper.insertApsPartRouteStat(apsPartRouteStat);
|
}
|
|
/**
|
* 修改零件统计表
|
*
|
* @param apsPartRouteStat 零件统计表
|
* @return 结果
|
*/
|
@Override
|
public int updateApsPartRouteStat(ApsPartRouteStat apsPartRouteStat)
|
{
|
return apsPartRouteStatMapper.updateApsPartRouteStat(apsPartRouteStat);
|
}
|
|
/**
|
* 批量删除零件统计表
|
*
|
* @param ids 需要删除的零件统计表主键
|
* @return 结果
|
*/
|
@Override
|
public int deleteApsPartRouteStatByIds(String[] ids)
|
{
|
return apsPartRouteStatMapper.deleteApsPartRouteStatByIds(ids);
|
}
|
|
/**
|
* 删除零件统计表信息
|
*
|
* @param id 零件统计表主键
|
* @return 结果
|
*/
|
@Override
|
public int deleteApsPartRouteStatById(String id)
|
{
|
return apsPartRouteStatMapper.deleteApsPartRouteStatById(id);
|
}
|
|
|
|
|
/**
|
* 查询零件工序并更新计划开工日期
|
* */
|
@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();
|
for (Map.Entry<String, List<ApsPartRouteStat>> entry : groupByWorkOrderNo.entrySet()) {
|
/*取出每个零件工单的工艺路线信息*/
|
List<ApsPartRouteStat> apsPartRouteStatList = entry.getValue();
|
/*按照工序号进行排序*/
|
apsPartRouteStatList.sort((a, b)->a.getRoadProcessNumber().compareTo(b.getRoadProcessNumber()));
|
/*临时保存 上一道工序的工序总工时*/
|
ApsPartRouteStat last=null;
|
for (int i = 0; i <apsPartRouteStatList.size(); i++) {
|
ApsPartRouteStat stat = apsPartRouteStatList.get(i);
|
/*判断当前工序 当前工序只有一条*/
|
if (stat.getCurrentProcessNumber().equals(stat.getRoadProcessNumber())) {
|
/* 对 stat.getProcessPlanStartDay() 和当前日期 进行对比,只对比到日,不用管十分秒*/
|
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 (last != null) {
|
LocalDateTime lastStartDate = LocalDateTime.ofInstant(last.getProcessPlanStartDay().toInstant(), ZoneId.systemDefault());
|
lastStartDate.plusHours(last.getProcessTotalTime());
|
stat.setProcessPlanStartDay(Date.from(lastStartDate.atZone(ZoneId.systemDefault()).toInstant()));
|
}
|
}
|
/*保存上一步计算的 开工日*/
|
last = stat;
|
stat.setId(IdUtils.fastUUID().toString());
|
stat.setBatchNumber(batchNum);
|
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.setRequireTimes(0);
|
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());
|
dataRow.createCell(j*3+2).setCellValue(apsResourceDateStat.getRequireTimes());
|
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;
|
}
|
|
|
}
|