package com.aps.core.service.impl; import java.util.*; import java.util.stream.Collectors; import com.alibaba.fastjson.JSONObject; import com.aps.common.core.utils.DateUtils; import com.aps.common.core.utils.bean.BeanUtils; import com.aps.common.core.web.domain.AjaxResult; import com.aps.common.security.utils.SecurityUtils; import com.aps.core.domain.*; import com.aps.core.mapper.*; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.aps.core.service.IApsPlateProcessShopStatService; import org.springframework.transaction.annotation.Transactional; /** * 钣金车间统计Service业务层处理 * * @author zhl * @date 2025-04-23 */ @Slf4j @Service public class ApsPlateProcessShopStatServiceImpl implements IApsPlateProcessShopStatService { @Autowired private ApsPlateProcessShopStatMapper apsPlateProcessShopStatMapper; @Resource private ApsPlateProcessStatMapper apsPlateProcessStatMapper; @Resource private ApsShopMapper shopMapper; @Resource private ApsStandardProcessMapper standardProcessMapper; @Resource private ApsPlatePlanMapper apsPlatePlanMapper; /** * 查询钣金车间统计 * * @param id 钣金车间统计主键 * @return 钣金车间统计 */ @Override public ApsPlateProcessShopStat selectApsPlateProcessShopStatById(Long id) { return apsPlateProcessShopStatMapper.selectApsPlateProcessShopStatById(id); } /** * 查询钣金车间统计列表 * * @param apsPlateProcessShopStat 钣金车间统计 * @return 钣金车间统计 */ @Override public List selectApsPlateProcessShopStatList(ApsPlateProcessShopStat apsPlateProcessShopStat) { return apsPlateProcessShopStatMapper.selectApsPlateProcessShopStatList(apsPlateProcessShopStat); } /** * 新增钣金车间统计 * * @param apsPlateProcessShopStat 钣金车间统计 * @return 结果 */ @Override public int insertApsPlateProcessShopStat(ApsPlateProcessShopStat apsPlateProcessShopStat) { apsPlateProcessShopStat.setCreateTime(DateUtils.getNowDate()); return apsPlateProcessShopStatMapper.insertApsPlateProcessShopStat(apsPlateProcessShopStat); } /** * 修改钣金车间统计 * * @param apsPlateProcessShopStat 钣金车间统计 * @return 结果 */ @Override public int updateApsPlateProcessShopStat(ApsPlateProcessShopStat apsPlateProcessShopStat) { apsPlateProcessShopStat.setUpdateTime(DateUtils.getNowDate()); return apsPlateProcessShopStatMapper.updateApsPlateProcessShopStat(apsPlateProcessShopStat); } /** * 批量删除钣金车间统计 * * @param ids 需要删除的钣金车间统计主键 * @return 结果 */ @Override public int deleteApsPlateProcessShopStatByIds(Long[] ids) { return apsPlateProcessShopStatMapper.deleteApsPlateProcessShopStatByIds(ids); } /** * 删除钣金车间统计信息 * * @param id 钣金车间统计主键 * @return 结果 */ @Override public int deleteApsPlateProcessShopStatById(Long id) { return apsPlateProcessShopStatMapper.deleteApsPlateProcessShopStatById(id); } /** * 保存钣金车间统计 */ @Transactional @Override public void saveShopStat() { try { // 开始之前先删除所有历史数据 apsPlateProcessShopStatMapper.deleteAll(); // 定义该功能使用数据源为南通的工厂 final String plant = "FORTUNA"; // 查询相关数据 ApsPlatePlan platePlan = new ApsPlatePlan(); platePlan.setPlant(plant); List planList = apsPlatePlanMapper.selectApsPlatePlanList(platePlan); List statList = apsPlateProcessStatMapper.selectApsPlateProcessStatList(new ApsPlateProcessStat()); ApsShop apsShop = new ApsShop(); apsShop.setPlantCode(plant); List shopList = shopMapper.selectApsShopList(apsShop); ApsStandardProcess process = new ApsStandardProcess(); process.setPlant(plant); List shopProcesses = standardProcessMapper.selectApsStandardProcessList(process); if (planList.isEmpty() || shopList.isEmpty() || shopProcesses.isEmpty()) { log.warn("计划列表、车间列表或工序列表为空,无法生成统计信息"); return; } // 构建车间名称到工序名称的映射 Map> shopToProcessNames = shopProcesses.stream() .collect(Collectors.groupingBy(ApsStandardProcess::getWorkShop, Collectors.mapping(ApsStandardProcess::getProcessName, Collectors.toList()) )); // 批量插入统计数据 List statsToInsert = new ArrayList<>(); for (ApsPlatePlan plan : planList) { for (ApsShop shop : shopList) { ApsPlateProcessShopStat stat = createShopStat(plan, shop, shopToProcessNames, statList); statsToInsert.add(stat); } } // 批量插入以提高性能 if (!statsToInsert.isEmpty()) { int batchSize = 1000; for (int i = 0; i < statsToInsert.size(); i += batchSize) { int end = Math.min(i + batchSize, statsToInsert.size()); List batch = statsToInsert.subList(i, end); apsPlateProcessShopStatMapper.batchInsert(batch); } } } catch (Exception e) { log.error("保存钣金车间统计时发生异常", e); throw new RuntimeException("保存钣金车间统计失败", e); } } /** * 创建单个车间统计对象 */ private ApsPlateProcessShopStat createShopStat(ApsPlatePlan plan, ApsShop shop, Map> shopToProcessNames, List statList) { String shopName = shop.getShopName(); ApsPlateProcessShopStat stat = new ApsPlateProcessShopStat(); stat.setDocNo(plan.getDocumentNumber()); stat.setShopCode(shop.getShopCode()); stat.setShopName(shopName); stat.setDelFlag("0"); stat.setCreateBy(SecurityUtils.getUsername()); stat.setCreateTime(DateUtils.getNowDate()); try { List processNames = shopToProcessNames.getOrDefault(shopName, Collections.emptyList()); if (!processNames.isEmpty()) { // 根据工序名称,查询该工单下所有的工序信息 List processStats = statList.stream() .filter(x -> processNames.contains(x.getProcessName()) && x.getWorkOrderNo().equals(plan.getDocumentNumber())) .toList(); if (!processStats.isEmpty()) { // 取出工单下工序的最小开始时间和最大结束时间 List startDayList = processStats.stream().map(ApsPlateProcessStat::getProcessPlanStartDay).filter(Objects::nonNull).toList(); if (!startDayList.isEmpty()) { if (startDayList.size() == 1) { stat.setPlanStartDate(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", startDayList.get(0))); } else { Optional minStartDay = processStats.stream() .map(ApsPlateProcessStat::getProcessPlanStartDay) .min(Comparator.naturalOrder()); Date date = minStartDay.get(); stat.setPlanStartDate(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", date)); } } List endDayList = processStats.stream().map(ApsPlateProcessStat::getProcessPlanEndDay).filter(Objects::nonNull).toList(); if (!endDayList.isEmpty()) { if (endDayList.size() == 1) { stat.setPlanEndDate(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", endDayList.get(0))); } else { Optional maxEndDay = processStats.stream() .map(ApsPlateProcessStat::getProcessPlanEndDay) .max(Comparator.naturalOrder()); Date date = maxEndDay.get(); stat.setPlanEndDate(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", date)); } } } } } catch (Exception e) { log.error("computer error:"+ JSONObject.toJSONString(stat)); } return stat; } @Override public AjaxResult getShopPlanStat() { // 提取硬编码值为常量 final String PLANT_CODE = "FORTUNA"; // 初始化对象 ApsPlatePlan platePlan = new ApsPlatePlan(); platePlan.setPlant(PLANT_CODE); ApsShop apsShop = new ApsShop(); apsShop.setPlantCode(PLANT_CODE); // 获取车间列表并处理空值 List shopList = Optional.ofNullable(shopMapper.selectApsShopList(apsShop)) .orElse(Collections.emptyList()) .stream() .map(ApsShop::getShopName) .toList(); // 获取计划列表和状态列表 List planList = Optional.ofNullable(apsPlatePlanMapper.selectApsPlatePlanList(platePlan)) .orElse(Collections.emptyList()); List shopStates = Optional.ofNullable(apsPlateProcessShopStatMapper.selectApsPlateProcessShopStatList(new ApsPlateProcessShopStat())) .orElse(Collections.emptyList()); // 提前对 shopStates 按 docNo 分组,减少重复流操作 Map> shopStatesByDocNo = shopStates.stream() .collect(Collectors.groupingBy(ApsPlateProcessShopStat::getDocNo)); // 构建结果列表 List shopPlanStats = planList.stream() .map(plan -> { ApsPlateProcessShopPlanStat shopPlanStat = new ApsPlateProcessShopPlanStat(); BeanUtils.copyProperties(plan, shopPlanStat); // 确保目标对象是合法的单个对象实例 // 根据 docNo 获取对应的 shopStatList List shopStatList = shopStatesByDocNo.getOrDefault(plan.getDocumentNumber(), Collections.emptyList()); shopPlanStat.setDeptPlans(shopStatList); return shopPlanStat; }) .toList(); // 构建返回结果 AjaxResult success = AjaxResult.success(shopPlanStats); success.put("shopNames", shopList); return success; } }