7a0530a22b160ae186bfdde5d52a5eee5995b6da..2a64b537e8e3bce9ce030585a3da17d48379c0ad
2025-05-26 sfd
修改json类型转换错误
dev
2a64b5 对比 | 目录
2025-05-26 hongjli
管路&气柜产能负载按日统计查不到数据时不返回空
7a4a03 对比 | 目录
2025-05-26 sfd
Merge branch 'dev' of http://192.168.50.149:8085/r/aps-backend into dev
230e56 对比 | 目录
2025-05-26 sfd
修改sql 字段错误
74d189 对比 | 目录
2025-05-24 zhanghl
将本地log 从git 排除
c81869 对比 | 目录
2025-05-23 zhanghl
[钣金计划大表] 优化:焊缝统计导出Excel样式
dec895 对比 | 目录
2025-05-23 zhanghl
Merge remote-tracking branch 'origin/dev' into dev
c8abec 对比 | 目录
2025-05-23 zhanghl
[钣金计划大表] 增加分布式锁
1c61a2 对比 | 目录
2025-05-23 hongjli
Merge remote-tracking branch 'origin/dev' into dev
67e4ad 对比 | 目录
2025-05-23 sfd
恢复权限过滤
740191 对比 | 目录
2025-05-23 hongjli
管路&气柜产能负载设计产能增加对专业过滤
ad2fb3 对比 | 目录
2025-05-23 sfd
Merge branch 'dev' of http://192.168.50.149:8085/r/aps-backend into dev
50cf97 对比 | 目录
2025-05-23 sfd
管路产能查看车间转码
010366 对比 | 目录
2025-05-23 zhanghl
[钣金计划大表] 优化为Stream.parallel提高并发
adfb74 对比 | 目录
2025-05-23 zhanghl
Merge remote-tracking branch 'origin/dev' into dev
687c9b 对比 | 目录
2025-05-23 zhanghl
[钣金计划大表] 优化注释
54ffd5 对比 | 目录
2025-05-23 sfd
Merge branch 'dev' of http://192.168.50.149:8085/r/aps-backend into dev
cd3e49 对比 | 目录
2025-05-23 sfd
修改字段excel配置
edca6e 对比 | 目录
2025-05-23 hongjli
Merge remote-tracking branch 'origin/dev' into dev
a57390 对比 | 目录
2025-05-23 hongjli
管路&气柜产能负载对返回结果集进行排序
771fc6 对比 | 目录
2025-05-23 zhanghl
Merge remote-tracking branch 'origin/dev' into dev
6da289 对比 | 目录
2025-05-23 zhanghl
[钣金计划大表] 优化注释
8e0034 对比 | 目录
2025-05-23 sfd
Merge branch 'dev' of http://192.168.50.149:8085/r/aps-backend into dev
b8fed1 对比 | 目录
2025-05-23 sfd
Update ApsStandardProcessController.java
b60b39 对比 | 目录
2025-05-23 sfd
修改导入导出规则
8c6327 对比 | 目录
2025-05-23 zhanghl
Merge remote-tracking branch 'origin/dev' into dev
0de06a 对比 | 目录
2025-05-23 zhanghl
[钣金计划大表] 优化更新逻辑
52aa02 对比 | 目录
2025-05-23 hongjli
Merge remote-tracking branch 'origin/dev' into dev
48f522 对比 | 目录
2025-05-23 hongjli
管路&气柜产能负载取消返回空值
2ef8fc 对比 | 目录
2025-05-23 zhanghl
[焊缝统计表V2] add:导出功能
3e5a42 对比 | 目录
2025-05-23 zhanghl
Merge remote-tracking branch 'origin/dev' into dev
97ee59 对比 | 目录
2025-05-23 zhanghl
[焊缝统计表V2] add:导出功能
8bcbb0 对比 | 目录
2025-05-23 hongjli
设计产能从产能规划中取值时取消对major的过滤
563b22 对比 | 目录
2025-05-23 hongjli
管路&气柜产能负载补充对designTimes的取值
26c853 对比 | 目录
2025-05-23 hongjli
row按workshop聚合统计时添加processName的参数的补充
789bac 对比 | 目录
2025-05-23 hongjli
补充关联不到工艺路线的料号保存至气体异常料号报表
7c1e70 对比 | 目录
2025-05-22 hongjli
管路&气柜产能负载决动态row聚合时数据过滤问题
32d81c 对比 | 目录
2025-05-22 zhanghl
Merge remote-tracking branch 'origin/dev' into dev
d096e4 对比 | 目录
2025-05-22 zhanghl
钣金计划大表:增加需求追溯号逻辑
608ab8 对比 | 目录
2025-05-22 sfd
Merge branch 'dev' of http://192.168.50.149:8085/r/aps-backend into dev
e5a96b 对比 | 目录
2025-05-22 sfd
修改workshop 取值
879819 对比 | 目录
2025-05-22 Zhu Zhonghua
Merge branch 'dev' of http://192.168.50.149:8085/r/aps-backend into dev
15ad2e 对比 | 目录
2025-05-22 Zhu Zhonghua
修改循环删除问题
dfb52b 对比 | 目录
2025-05-22 hongjli
Merge remote-tracking branch 'origin/dev' into dev
460907 对比 | 目录
2025-05-22 hongjli
管路&气柜产能负载优化,实现动态row聚合统计
bc0fdd 对比 | 目录
2025-05-22 zhanghl
Merge remote-tracking branch 'origin/dev' into dev
f274ea 对比 | 目录
2025-05-22 zhanghl
优化JOB任务相关代码:增加注释
093ab7 对比 | 目录
2025-05-22 hongjli
Merge remote-tracking branch 'origin/dev' into dev
e4efff 对比 | 目录
2025-05-22 hongjli
管路&气柜产能负载代码重构
d21e1b 对比 | 目录
2025-05-22 zhanghl
更新job计时功能,显示为分秒
93e554 对比 | 目录
已修改78个文件
已添加10个文件
4367 ■■■■ 文件已修改
.gitignore 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-common/aps-common-core/src/main/java/com/aps/common/core/utils/poi/ExcelUtil.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-common/aps-common-redis/src/main/java/com/aps/common/redis/service/RedisLockUtils.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-common/aps-common-security/src/main/java/com/aps/common/security/utils/DictUtils.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/controller/ApsGasPipingRouteStatController.java 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/controller/basicData/ApsGasPipelineCapacityPlanController.java 106 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/controller/basicData/ApsStandardProcessController.java 130 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/controller/mainPlan/ApsBomHeaderController.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/controller/mainPlan/ApsGasPipelineMoController.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/controller/mainPlan/ApsGasPipelinePredictionController.java 77 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/controller/mainPlan/ApsMaterialProductGroupManagementController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/controller/mainPlan/ApsPlate/ApsPlateProcessShopStatController.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/controller/mainPlan/ApsPlate/ApsPlateProcessStatController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/controller/mainPlan/ApsWeldSeamStatisticsV2Controller.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/domain/ApsGasPipelineCapacityPlan.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/domain/ApsGasPipelineMo.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/domain/ApsGasPipelinePrediction.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/domain/ApsGasPipingRouteStat.java 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/domain/ApsMaterialProductGroupManagement.java 87 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/domain/ApsStandardProcess.java 196 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/enums/PLAN_TASK_STATUS.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/enums/PLAN_TASK_TYPE.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/enums/REDIS_LOCK_KEY.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsGasPipelineCapacityPlanMapper.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsGasPipingRouteStatMapper.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsPlateProcessStatMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsPlateStandardRequireErrorMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsShopMapper.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsStandardProcessMapper.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/ApsPlanTaskService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/ApsPlate/IApsPlateProcessStatService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/ApsPlate/IApsPlateStandardRequireBatchService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/ApsPlate/IApsPlateStandardRequireErrorService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/IApsBomHeaderService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/IApsGasPipelineCapacityPlanService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/IApsGasPipingRouteStatService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/IApsShopService.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsBomHeaderServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsBomServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipelineCapacityPlanServiceImpl.java 92 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipelineMoServiceImpl.java 65 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipelinePredictionServiceImpl.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipingRouteStatServiceImpl.java 1041 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsMaterialProductGroupManagementServiceImpl.java 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsMaterialStorageManagementServiceImpl.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsPlanTaskServiceImpl.java 78 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsPlate/ApsPlatePlanServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsPlate/ApsPlateProcessShopStatServiceImpl.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsPlate/ApsPlateProcessStatServiceImpl.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsPlate/ApsPlateStandardRequireBatchServiceImpl.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsPlate/ApsPlateStandardRequireErrorServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsPlate/ApsPlateStandardRequireServiceImpl.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsShopServiceImpl.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsStandardProcessRouteHeaderServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsStandardProcessRouteLineServiceImpl.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsStandardProcessServiceImpl.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsWorkCalendarServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/mainPlan/IApsWeldSeamStatisticsV2Service.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/mainPlan/impl/ApsWeldSeamStatisticsV2ServiceImpl.java 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/resources/mapper/core/ApsBomHeaderMapper.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/resources/mapper/core/ApsGasPipelineCapacityPlanMapper.xml 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/resources/mapper/core/ApsGasPipingRouteStatMapper.xml 326 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/resources/mapper/core/ApsPlate/ApsPlateProcessShopStatMapper.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/resources/mapper/core/ApsPlate/ApsPlateProcessStatMapper.xml 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/resources/mapper/core/ApsPlate/ApsPlateStandardRequireBomOrderDetailMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/resources/mapper/core/ApsPlate/ApsPlateStandardRequireBomStockDetailMapper.xml 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/resources/mapper/core/ApsPlate/ApsPlateStandardRequireErrorMapper.xml 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/resources/mapper/core/ApsPlate/ApsPlateStandardRequireMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/resources/mapper/core/ApsWeldSeamStatisticsV2Mapper.xml 112 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/resources/templates/标准工序数据模板v1.0.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/resources/templates/气体工单数据模板v1.0.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/resources/templates/气体预测数据模板v1.0.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/java/com/aps/job/domain/ApsWeldSeamStandardJob.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/java/com/aps/job/mapper/ApsBomHeaderJobMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/java/com/aps/job/mapper/ApsBomLineJobMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/java/com/aps/job/mapper/ApsWeldSeamStandardJobMapper.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/java/com/aps/job/mapper/ApsWeldSeamStandardMapper.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/java/com/aps/job/service/IApsWeldSeamStandardJobService.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/java/com/aps/job/service/impl/ApsBomHeaderJobServiceImpl.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/java/com/aps/job/service/impl/ApsMaterialManagementJobServiceImpl.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/java/com/aps/job/service/impl/ApsMaterialStorageManagementJobServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/java/com/aps/job/service/impl/ApsStandardProcessRouteHeaderJobServiceImpl.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/java/com/aps/job/service/impl/ApsWeldSeamStandardJobServiceImpl.java 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/java/com/aps/job/service/impl/ApsWorkOrderProcessServiceImpl.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/java/com/aps/job/task/RyTask.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/java/com/aps/job/util/AbstractQuartzJob.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/resources/mapper/job/ApsWeldSeamStandardJobMapper.xml 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-job/src/main/resources/mapper/job/ApsWeldSeamStandardMapper.xml 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -43,4 +43,6 @@
!*/build/*.java
!*/build/*.html
!*/build/*.xml
!*/build/*.xml
logs/
aps-common/aps-common-core/src/main/java/com/aps/common/core/utils/poi/ExcelUtil.java
@@ -692,33 +692,10 @@
    {
        // å†™å…¥å„条记录,每条记录对应excel表中的一行
        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
        CellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        Font titleFont = wb.createFont();
        titleFont.setFontName("Arial");
        titleFont.setFontHeightInPoints((short) 16);
        titleFont.setBold(true);
        style.setFont(titleFont);
        DataFormat dataFormat = wb.createDataFormat();
        style.setDataFormat(dataFormat.getFormat("@"));
        CellStyle style = getTitleCellStyle(wb);
        styles.put("title", style);
        style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setBorderRight(BorderStyle.THIN);
        style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderLeft(BorderStyle.THIN);
        style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderTop(BorderStyle.THIN);
        style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderBottom(BorderStyle.THIN);
        style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        Font dataFont = wb.createFont();
        dataFont.setFontName("Arial");
        dataFont.setFontHeightInPoints((short) 10);
        style.setFont(dataFont);
        style = getDataCellStyle(wb);
        styles.put("data", style);
        style = wb.createCellStyle();
@@ -737,6 +714,40 @@
        return styles;
    }
    public static CellStyle getTitleCellStyle(Workbook wb) {
        CellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        Font titleFont = wb.createFont();
        titleFont.setFontName("Arial");
        titleFont.setFontHeightInPoints((short) 16);
        titleFont.setBold(true);
        style.setFont(titleFont);
        DataFormat dataFormat = wb.createDataFormat();
        style.setDataFormat(dataFormat.getFormat("@"));
        return style;
    }
    public static CellStyle getDataCellStyle(Workbook wb) {
        CellStyle style;
        style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setBorderRight(BorderStyle.THIN);
        style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderLeft(BorderStyle.THIN);
        style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderTop(BorderStyle.THIN);
        style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderBottom(BorderStyle.THIN);
        style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        Font dataFont = wb.createFont();
        dataFont.setFontName("Arial");
        dataFont.setFontHeightInPoints((short) 10);
        style.setFont(dataFont);
        return style;
    }
    /**
     * æ ¹æ®Excel注解创建表格头样式
     * 
@@ -752,27 +763,49 @@
            String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor());
            if (!headerStyles.containsKey(key))
            {
                CellStyle style = wb.createCellStyle();
                style.cloneStyleFrom(styles.get("data"));
                style.setAlignment(HorizontalAlignment.CENTER);
                style.setVerticalAlignment(VerticalAlignment.CENTER);
                style.setFillForegroundColor(excel.headerBackgroundColor().index);
                style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                Font headerFont = wb.createFont();
                headerFont.setFontName("Arial");
                headerFont.setFontHeightInPoints((short) 10);
                headerFont.setBold(true);
                headerFont.setColor(excel.headerColor().index);
                style.setFont(headerFont);
                // è®¾ç½®è¡¨æ ¼å¤´å•元格文本形式
                DataFormat dataFormat = wb.createDataFormat();
                style.setDataFormat(dataFormat.getFormat("@"));
                CellStyle style = getHeaderStyle(wb, excel);
                headerStyles.put(key, style);
            }
        }
        return headerStyles;
    }
    private static CellStyle getHeaderStyle(Workbook wb, Excel excel) {
        CellStyle style = wb.createCellStyle();
        style.cloneStyleFrom(getDataCellStyle(wb));
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setFillForegroundColor(excel.headerBackgroundColor().index);
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        Font headerFont = wb.createFont();
        headerFont.setFontName("Arial");
        headerFont.setFontHeightInPoints((short) 10);
        headerFont.setBold(true);
        headerFont.setColor(excel.headerColor().index);
        style.setFont(headerFont);
        // è®¾ç½®è¡¨æ ¼å¤´å•元格文本形式
        DataFormat dataFormat = wb.createDataFormat();
        style.setDataFormat(dataFormat.getFormat("@"));
        return style;
    }
    public static CellStyle getCommonHeaderStyle(Workbook wb) {
        CellStyle style = wb.createCellStyle();
        style.cloneStyleFrom(getDataCellStyle(wb));
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setFillForegroundColor( IndexedColors.GREY_50_PERCENT.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        Font headerFont = wb.createFont();
        headerFont.setFontName("Arial");
        headerFont.setFontHeightInPoints((short) 10);
        headerFont.setBold(true);
        headerFont.setColor(IndexedColors.WHITE.getIndex());
        style.setFont(headerFont);
        // è®¾ç½®è¡¨æ ¼å¤´å•元格文本形式
        DataFormat dataFormat = wb.createDataFormat();
        style.setDataFormat(dataFormat.getFormat("@"));
        return style;
    }
    /**
     * æ ¹æ®Excel注解创建表格列样式
     * 
@@ -1316,7 +1349,7 @@
    /**
     * å¾—到所有定义字段
     */
    private void createExcelField()
    public void createExcelField()
    {
        this.fields = getFields();
        this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
aps-common/aps-common-redis/src/main/java/com/aps/common/redis/service/RedisLockUtils.java
@@ -29,6 +29,9 @@
     * åˆ¤æ–­æ˜¯å¦å­˜åœ¨é”
     * */
    public boolean existLock(String key,String value){
        if(null==this.redisTemplate.opsForValue().get(key)){
            return false;
        }
        return this.redisTemplate.opsForValue().get(key).equals(value);
    }
aps-common/aps-common-security/src/main/java/com/aps/common/security/utils/DictUtils.java
@@ -1,43 +1,43 @@
package com.aps.common.security.utils;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import com.alibaba.fastjson2.JSONArray;
import com.aps.common.core.constant.CacheConstants;
import com.aps.common.core.utils.SpringUtils;
import com.aps.common.core.utils.StringUtils;
import com.aps.common.redis.service.RedisService;
import com.aps.system.api.domain.SysDictData;
import org.springframework.util.CollectionUtils;
/**
 * å­—典工具类
 *
 *
 * @author ruoyi
 */
public class DictUtils
{
public class DictUtils {
    /**
     * è®¾ç½®å­—典缓存
     *
     * @param key å‚æ•°é”®
     *
     * @param key       å‚æ•°é”®
     * @param dictDatas å­—典数据列表
     */
    public static void setDictCache(String key, List<SysDictData> dictDatas)
    {
    public static void setDictCache(String key, List<SysDictData> dictDatas) {
        SpringUtils.getBean(RedisService.class).setCacheObject(getCacheKey(key), dictDatas);
    }
    /**
     * èŽ·å–å­—å…¸ç¼“å­˜
     *
     *
     * @param key å‚æ•°é”®
     * @return dictDatas å­—典数据列表
     */
    public static List<SysDictData> getDictCache(String key)
    {
    public static List<SysDictData> getDictCache(String key) {
        JSONArray arrayCache = SpringUtils.getBean(RedisService.class).getCacheObject(getCacheKey(key));
        if (StringUtils.isNotNull(arrayCache))
        {
        if (StringUtils.isNotNull(arrayCache)) {
            return arrayCache.toList(SysDictData.class);
        }
        return null;
@@ -45,31 +45,56 @@
    /**
     * åˆ é™¤æŒ‡å®šå­—典缓存
     *
     *
     * @param key å­—典键
     */
    public static void removeDictCache(String key)
    {
    public static void removeDictCache(String key) {
        SpringUtils.getBean(RedisService.class).deleteObject(getCacheKey(key));
    }
    /**
     * æ¸…空字典缓存
     */
    public static void clearDictCache()
    {
    public static void clearDictCache() {
        Collection<String> keys = SpringUtils.getBean(RedisService.class).keys(CacheConstants.SYS_DICT_KEY + "*");
        SpringUtils.getBean(RedisService.class).deleteObject(keys);
    }
    /**
     * è®¾ç½®cache key
     *
     *
     * @param configKey å‚æ•°é”®
     * @return ç¼“存键key
     */
    public static String getCacheKey(String configKey)
    {
    public static String getCacheKey(String configKey) {
        return CacheConstants.SYS_DICT_KEY + configKey;
    }
    public static interface CacheValue{
        String get(String label);
    }
    /**
     * æ ¹æ®å­—典类型和字典标签获取字典值
     *
     * @param dictType
     * @return
     */
    public static CacheValue getCacheValue(String dictType) {
        List<SysDictData> cacheData = StringUtils.isEmpty(dictType) ? Collections.emptyList() : getDictCache(dictType);
        return label -> {
            if (CollectionUtils.isEmpty(cacheData)){
                return null;
            }
            if(StringUtils.isEmpty(label)){
                return null;
            }
            return cacheData.stream().filter(item -> Objects.equals(item.getDictLabel(), label))
                    .findFirst()
                    .map(SysDictData::getDictValue)
                    .orElse(null);
        };
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/controller/ApsGasPipingRouteStatController.java
@@ -16,6 +16,7 @@
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
 * æ°”体管路产能负载统计Controller
@@ -62,7 +63,7 @@
    /**
     * èŽ·å–æ°”ä½“ç®¡è·¯äº§èƒ½è´Ÿè½½ç»Ÿè®¡è¯¦ç»†ä¿¡æ¯
     */
    @Operation(summary = "获取气体管路产能负载统计详细信息", description = "根据id获取")
    @Operation(summary = "获取气体管路产能负载统计详细信息", description = "根据ID查询")
    @RequiresPermissions("aps:apsGasPipingRouteStat:query")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") String id)
@@ -73,7 +74,7 @@
    /**
     * æ–°å¢žæ°”体管路产能负载统计
     */
    @Operation(summary = "新增气体管路产能负载统计", description = "单个新增")
    @Operation(summary = "新增气体管路产能负载统计", description = "新增")
    @RequiresPermissions("aps:apsGasPipingRouteStat:add")
    @Log(title = "气体管路产能负载统计", businessType = BusinessType.INSERT)
    @PostMapping
@@ -85,7 +86,7 @@
    /**
     * ä¿®æ”¹æ°”体管路产能负载统计
     */
    @Operation(summary = "修改气体管路产能负载统计", description = "单个修改")
    @Operation(summary = "修改气体管路产能负载统计", description = "修改")
    @RequiresPermissions("aps:apsGasPipingRouteStat:edit")
    @Log(title = "气体管路产能负载统计", businessType = BusinessType.UPDATE)
    @PutMapping
@@ -97,7 +98,7 @@
    /**
     * åˆ é™¤æ°”体管路产能负载统计
     */
    @Operation(summary = "删除气体管路产能负载统计", description = "批量删除")
    @Operation(summary = "删除气体管路产能负载统计", description = "删除")
    @RequiresPermissions("aps:apsGasPipingRouteStat:remove")
    @Log(title = "气体管路产能负载统计", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
@@ -105,6 +106,29 @@
    {
        return toAjax(apsGasPipingRouteStatService.deleteApsGasPipingRouteStatByIds(ids));
    }
    /**
     * ç”Ÿæˆæ°”体管路产能负载统计数据
     */
    @Operation(summary = "生成气体管路产能负载统计数据", description = "根据预测数据和工单数据生成统计数据")
    @RequiresPermissions("aps:apsGasPipingRouteStat:generate")
    @Log(title = "气体管路产能负载统计", businessType = BusinessType.INSERT)
    @PostMapping("/generate")
    public AjaxResult generateGasPipingRouteStatData()
    {
        return toAjax(apsGasPipingRouteStatService.generateGasPipingRouteStatData());
    }
    /**
     * èšåˆæ°”体管路产能负载统计数据
     */
    @Operation(summary = "聚合气体管路产能负载统计数据", description = "聚合统计数据,支持动态选择行维度(rowGroupBy)进行聚合,如按工序名称、车间、工厂、专业等")
    @RequiresPermissions("aps:apsGasPipingRouteStat:aggregate")
    @PostMapping("/aggregate")
    public AjaxResult aggregateGasPipingRouteStat(@RequestBody Map<String, Object> params)
    {
        return success(apsGasPipingRouteStatService.aggregateGasPipingRouteStat(params));
    }
    @Operation(summary = "计算气体管路产能负载统计", description = "计算")
    @PostMapping("/computeCapacity")
aps-modules/aps-core/src/main/java/com/aps/core/controller/basicData/ApsGasPipelineCapacityPlanController.java
@@ -10,8 +10,10 @@
import com.aps.common.security.annotation.RequiresPermissions;
import com.aps.common.security.utils.SecurityUtils;
import com.aps.core.domain.ApsGasPipelineCapacityPlan;
import com.aps.core.domain.ApsShop;
import com.aps.core.domain.ApsStandardProcess;
import com.aps.core.service.IApsGasPipelineCapacityPlanService;
import com.aps.core.service.IApsShopService;
import com.aps.core.service.IApsStandardProcessService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -20,11 +22,13 @@
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
/**
 * æ°”体管路产能规划Controller
 *
 *
 * @author hjy
 * @date 2025-04-24
 */
@@ -32,13 +36,15 @@
@Tag(name = "气体管路产能规划", description = "气体管路产能规划接口")
@RestController
@RequestMapping("/gasPipelineCapacityPlan")
public class ApsGasPipelineCapacityPlanController extends BaseController
{
public class ApsGasPipelineCapacityPlanController extends BaseController {
    @Autowired
    private IApsGasPipelineCapacityPlanService apsGasPipelineCapacityPlanService;
    @Autowired
    private IApsStandardProcessService apsStandardProcessService;
    @Autowired
    private IApsShopService apsShopService;
    /**
     * æŸ¥è¯¢æ°”体管路产能规划列表
@@ -46,43 +52,67 @@
    @Operation(summary = "查询气体管路产能规划列表", description = "分页查询")
    @RequiresPermissions("aps:gasPipelineCapacityPlan:list")
    @GetMapping("/list")
    public TableDataInfo list(ApsGasPipelineCapacityPlan apsGasPipelineCapacityPlan)
    {
    public TableDataInfo list(ApsGasPipelineCapacityPlan apsGasPipelineCapacityPlan) {
//        startPage();
        List<ApsGasPipelineCapacityPlan> list = apsGasPipelineCapacityPlanService.selectApsGasPipelineCapacityPlanList(apsGasPipelineCapacityPlan);
        ApsStandardProcess apsStandardProcess = new ApsStandardProcess();
        apsStandardProcess.setMajor(apsGasPipelineCapacityPlan.getMajor());
        apsStandardProcess.setPlant(apsGasPipelineCapacityPlan.getOrgCode());
        List<ApsStandardProcess> processList = apsStandardProcessService.selectApsStandardProcessListAll(apsStandardProcess);
        if(list.isEmpty()){
            for(ApsStandardProcess apsStandardProcessTemp : processList){
        List<ApsShop> apsShops = apsShopService.findShopByFactory(apsGasPipelineCapacityPlan.getOrgCode());
        if (list.isEmpty()) {
            for (ApsStandardProcess apsStandardProcessTemp : processList) {
                ApsGasPipelineCapacityPlan apsGasPipelineCapacityPlanTemp = new ApsGasPipelineCapacityPlan();
                apsGasPipelineCapacityPlanTemp.setProcessName(apsStandardProcessTemp.getProcessName());
                apsGasPipelineCapacityPlanTemp.setOrgCode(apsStandardProcessTemp.getPlant());
                apsGasPipelineCapacityPlanTemp.setWorkshop(apsShops.stream()
                        .filter(shop -> Objects.equals(shop.getShopCode(), apsStandardProcessTemp.getWorkShop()))
                        .map(ApsShop::getShopName)
                        .findFirst()
                        .orElse(null));
                list.add(apsGasPipelineCapacityPlanTemp);
            }
        } else {
            list.forEach(capacityPlan -> {
                processList.stream().filter(p -> Objects.equals(p.getPlant(), capacityPlan.getOrgCode()))
                        .filter(p -> Objects.equals(p.getMajor(), capacityPlan.getMajor()))
                        .filter(p -> p.getWorkShop() != null)
                        .findFirst().ifPresent(p -> {
                            capacityPlan.setWorkshop(apsShops.stream()
                                    .filter(shop -> Objects.equals(shop.getShopCode(), p.getWorkShop()))
                                    .map(ApsShop::getShopName)
                                    .findFirst()
                                    .orElse(null));
                        });
            });
        }
        if(processList.size()>list.size()){
            List<String> newProcess = new ArrayList<>();
            for(ApsStandardProcess apsStandardProcessTemp : processList){
        if (processList.size() > list.size()) {
            List<ApsStandardProcess> newProcess = new ArrayList<>();
            for (ApsStandardProcess apsStandardProcessTemp : processList) {
                boolean flag = true;
                for(ApsGasPipelineCapacityPlan temp : list){
                    if(apsStandardProcessTemp.getProcessName().equals(temp.getProcessName())){
                for (ApsGasPipelineCapacityPlan temp : list) {
                    if (apsStandardProcessTemp.getProcessName().equals(temp.getProcessName())) {
                        flag = false;
                        break;
                    }
                }
                if(flag){
                    newProcess.add(apsStandardProcessTemp.getProcessName());
                if (flag) {
                    newProcess.add(apsStandardProcessTemp);
                }
            }
            for(String processName : newProcess){
            for (ApsStandardProcess process : newProcess) {
                ApsGasPipelineCapacityPlan apsGasPipelineCapacityPlanTemp = new ApsGasPipelineCapacityPlan();
                apsGasPipelineCapacityPlanTemp.setProcessName(processName);
                apsGasPipelineCapacityPlanTemp.setProcessName(process.getProcessName());
                apsGasPipelineCapacityPlanTemp.setOrgCode(process.getPlant());
                apsGasPipelineCapacityPlanTemp.setWorkshop(apsShops.stream()
                        .filter(shop -> Objects.equals(shop.getShopCode(), process.getWorkShop()))
                        .map(ApsShop::getShopName)
                        .findFirst()
                        .orElse(null));
                list.add(apsGasPipelineCapacityPlanTemp);
            }
        }
        list.sort((a, b)->a.getProcessName().compareTo(b.getProcessName()));
        list.sort(Comparator.comparing(ApsGasPipelineCapacityPlan::getProcessName));
        return getDataTable(list);
    }
@@ -93,11 +123,31 @@
    @RequiresPermissions("aps:gasPipelineCapacityPlan:export")
    @Log(title = "气体管路产能规划", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, ApsGasPipelineCapacityPlan apsGasPipelineCapacityPlan)
    {
    public void export(HttpServletResponse response, ApsGasPipelineCapacityPlan apsGasPipelineCapacityPlan) {
        List<ApsGasPipelineCapacityPlan> list = apsGasPipelineCapacityPlanService.selectApsGasPipelineCapacityPlanList(apsGasPipelineCapacityPlan);
        ExcelUtil<ApsGasPipelineCapacityPlan> util = new ExcelUtil<ApsGasPipelineCapacityPlan>(ApsGasPipelineCapacityPlan.class);
        util.exportExcel(response, list, "气体管路产能规划数据");
    }
    /**
     * å¤åˆ¶æ°”体管路产能规划
     */
    @Operation(summary = "复制气体管路产能规划", description = "复制")
    @RequiresPermissions("aps:gasPipelineCapacityPlan:copy")
    @Log(title = "复制气体管路产能规划", businessType = BusinessType.INSERT)
    @PutMapping("/copy")
    public AjaxResult copy(
            // æ ¼å¼ï¼šyyyy-MM
            @RequestParam String date,
            @RequestParam String factory,
            @RequestParam String major,
            // æ ¼å¼ï¼šyyyy-MM
            @RequestParam String toStart,
            // æ ¼å¼ï¼šyyyy-MM
            @RequestParam String toEnd) {
        apsGasPipelineCapacityPlanService.copyPlan(date, factory, major, toStart, toEnd);
        return success();
    }
    /**
@@ -106,8 +156,7 @@
    @Operation(summary = "获取气体管路产能规划详细信息", description = "根据id获取")
    @RequiresPermissions("aps:gasPipelineCapacityPlan:query")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(apsGasPipelineCapacityPlanService.selectApsGasPipelineCapacityPlanById(id));
    }
@@ -118,14 +167,13 @@
    @RequiresPermissions("aps:gasPipelineCapacityPlan:add")
    @Log(title = "气体管路产能规划", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody List<ApsGasPipelineCapacityPlan> apsGasPipelineCapacityPlan)
    {
    public AjaxResult add(@RequestBody List<ApsGasPipelineCapacityPlan> apsGasPipelineCapacityPlan) {
        apsGasPipelineCapacityPlan.forEach(apsGasPipelineCapacityPlanTemp -> {
            if(apsGasPipelineCapacityPlanTemp.getId()==null){
            if (apsGasPipelineCapacityPlanTemp.getId() == null) {
                apsGasPipelineCapacityPlanTemp.setCreateBy(SecurityUtils.getUsername());
                apsGasPipelineCapacityPlanTemp.setCreateTime(DateUtils.getNowDate());
                apsGasPipelineCapacityPlanService.insertApsGasPipelineCapacityPlan(apsGasPipelineCapacityPlanTemp);
            }else{
            } else {
                apsGasPipelineCapacityPlanTemp.setUpdateBy(SecurityUtils.getUsername());
                apsGasPipelineCapacityPlanTemp.setUpdateTime(DateUtils.getNowDate());
                apsGasPipelineCapacityPlanService.updateApsGasPipelineCapacityPlan(apsGasPipelineCapacityPlanTemp);
@@ -141,8 +189,7 @@
    @RequiresPermissions("aps:gasPipelineCapacityPlan:edit")
    @Log(title = "气体管路产能规划", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody ApsGasPipelineCapacityPlan apsGasPipelineCapacityPlan)
    {
    public AjaxResult edit(@RequestBody ApsGasPipelineCapacityPlan apsGasPipelineCapacityPlan) {
        return toAjax(apsGasPipelineCapacityPlanService.updateApsGasPipelineCapacityPlan(apsGasPipelineCapacityPlan));
    }
@@ -152,9 +199,8 @@
    @Operation(summary = "删除气体管路产能规划", description = "批量删除")
    @RequiresPermissions("aps:gasPipelineCapacityPlan:remove")
    @Log(title = "气体管路产能规划", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(apsGasPipelineCapacityPlanService.deleteApsGasPipelineCapacityPlanByIds(ids));
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/controller/basicData/ApsStandardProcessController.java
@@ -7,20 +7,39 @@
import com.aps.common.log.annotation.Log;
import com.aps.common.log.enums.BusinessType;
import com.aps.common.security.annotation.RequiresPermissions;
import com.aps.common.security.utils.DictUtils;
import com.aps.core.domain.ApsShop;
import com.aps.core.domain.ApsStandardProcess;
import com.aps.core.service.IApsShopService;
import com.aps.core.service.IApsStandardProcessService;
import com.aps.system.api.domain.SysDictData;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
 * æ ‡å‡†å·¥åºController
 *
 *
 * @author hjy
 * @date 2025-04-23
 */
@@ -29,10 +48,12 @@
@Tag(name = "标准工序", description = "标准工序接口")
@RestController
@RequestMapping("/standardProcess")
public class ApsStandardProcessController extends BaseController
{
public class ApsStandardProcessController extends BaseController {
    @Autowired
    private IApsStandardProcessService apsStandardProcessService;
    @Autowired
    IApsShopService apsShopService;
    /**
     * æŸ¥è¯¢æ ‡å‡†å·¥åºåˆ—表
@@ -40,10 +61,19 @@
    @Operation(summary = "查询标准工序列表", description = "分页查询")
    @RequiresPermissions("aps:standardProcess:list")
    @GetMapping("/list")
    public TableDataInfo list(ApsStandardProcess apsStandardProcess)
    {
    public TableDataInfo list(ApsStandardProcess apsStandardProcess) {
        startPage();
        List<ApsStandardProcess> list = apsStandardProcessService.selectApsStandardProcessList(apsStandardProcess);
        List<ApsShop> apsShops = apsShopService.findShopByCodes(list.stream().map(ApsStandardProcess::getWorkShop)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet()));
        list.forEach(temp -> {
            temp.setWorkShop(apsShops.stream()
                    .filter(tempShop -> Objects.equals(tempShop.getShopCode(), temp.getWorkShop()))
                    .map(ApsShop::getShopName)
                    .findFirst()
                    .orElse(null));
        });
        return getDataTable(list);
    }
@@ -54,8 +84,7 @@
    @RequiresPermissions("aps:standardProcess:export")
    @Log(title = "标准工序", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, ApsStandardProcess apsStandardProcess)
    {
    public void export(HttpServletResponse response, ApsStandardProcess apsStandardProcess) {
        List<ApsStandardProcess> list = apsStandardProcessService.selectApsStandardProcessList(apsStandardProcess);
        ExcelUtil<ApsStandardProcess> util = new ExcelUtil<ApsStandardProcess>(ApsStandardProcess.class);
        util.exportExcel(response, list, "标准工序数据");
@@ -67,8 +96,7 @@
    @Operation(summary = "获取标准工序详细信息", description = "根据id获取")
    @RequiresPermissions("aps:standardProcess:query")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(apsStandardProcessService.selectApsStandardProcessById(id));
    }
@@ -79,8 +107,7 @@
    @RequiresPermissions("aps:standardProcess:add")
    @Log(title = "标准工序", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody ApsStandardProcess apsStandardProcess)
    {
    public AjaxResult add(@RequestBody ApsStandardProcess apsStandardProcess) {
        return toAjax(apsStandardProcessService.insertApsStandardProcess(apsStandardProcess));
    }
@@ -91,8 +118,7 @@
    @RequiresPermissions("aps:standardProcess:edit")
    @Log(title = "标准工序", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody ApsStandardProcess apsStandardProcess)
    {
    public AjaxResult edit(@RequestBody ApsStandardProcess apsStandardProcess) {
        return toAjax(apsStandardProcessService.updateApsStandardProcess(apsStandardProcess));
    }
@@ -102,9 +128,8 @@
    @Operation(summary = "删除标准工序", description = "批量删除")
    @RequiresPermissions("aps:standardProcess:remove")
    @Log(title = "标准工序", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(apsStandardProcessService.deleteApsStandardProcessByIds(ids));
    }
@@ -112,7 +137,7 @@
     * å¯¼å…¥æ ‡å‡†å·¥åºæ•°æ®
     */
    @Operation(summary = "导入标准工序数据", description = "增量导入")
    @RequiresPermissions("aps:standardProcess:importData")
//    @RequiresPermissions("aps:standardProcess:importData")
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file) throws Exception {
        ExcelUtil<ApsStandardProcess> util = new ExcelUtil<>(ApsStandardProcess.class);
@@ -120,9 +145,9 @@
        //判断导入数据是否为空
        if (!tempList.isEmpty()) {
            Boolean res = apsStandardProcessService.importData(tempList);
            if(res){
            if (res) {
                return AjaxResult.success("导入成功!");
            }else{
            } else {
                return AjaxResult.error("导入失败!");
            }
        } else {
@@ -136,9 +161,72 @@
    @Operation(summary = "根据车间查询标准工序列表", description = "全量查询")
    @RequiresPermissions("aps:standardProcess:listByWorkShop")
    @GetMapping("/listByWorkShop")
    public TableDataInfo listByWorkShop(ApsStandardProcess apsStandardProcess)
    {
    public TableDataInfo listByWorkShop(ApsStandardProcess apsStandardProcess) {
        List<ApsStandardProcess> list = apsStandardProcessService.selectApsStandardProcessList(apsStandardProcess);
        return getDataTable(list);
    }
    /**
     * ä¸‹è½½æ ‡å‡†å·¥åºæ•°æ®å¯¼å…¥æ¨¡æ¿
     */
    @SneakyThrows
    @Operation(summary = "下载标准工序数据导入模板", description = "下载标准工序数据导入模板")
//    @RequiresPermissions("gasPipeline:prediction:template")
//    @Log(title = "下载气体预测数据导入模板", businessType = BusinessType.EXPORT)
    @GetMapping("/template")
    public ResponseEntity<ByteArrayResource> exportTemplate() {
        byte[] file = IOUtils.resourceToByteArray("/templates/标准工序数据模板v1.0.xlsx");
        Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(file));
        Sheet sheet = workbook.getSheet("字典-工厂");
        List<SysDictData> sysDictDataList = DictUtils.getDictCache("aps_factory");
        boolean changed = false;
        if (sysDictDataList != null) {
            for (int i = 0; i < sysDictDataList.size(); i++) {
                Row row = sheet.createRow(i + 1);
                row.createCell(0).setCellValue(sysDictDataList.get(i).getDictValue());
                row.createCell(1).setCellValue(sysDictDataList.get(i).getDictLabel());
            }
            sheet = workbook.getSheet("字典-车间");
            List<ApsShop> shops = apsShopService.findAllShops();
            for (int i = 0; i < shops.size(); i++) {
                Row row = sheet.createRow(i + 1);
                ApsShop shop = shops.get(i);
                row.createCell(0).setCellValue(sysDictDataList
                        .stream()
                        .filter(d -> d.getDictValue().equals(shop.getPlantCode()))
                        .map(SysDictData::getDictLabel)
                        .findFirst()
                        .orElse(null));
                row.createCell(1).setCellValue(shops.get(i).getShopCode());
                row.createCell(2).setCellValue(shops.get(i).getShopName());
            }
            changed = true;
        }
        sheet = workbook.getSheet("字典-专业");
        sysDictDataList = DictUtils.getDictCache("aps_domain");
        if (sysDictDataList != null) {
            for (int i = 0; i < sysDictDataList.size(); i++) {
                Row row = sheet.createRow(i + 1);
                row.createCell(0).setCellValue(sysDictDataList.get(i).getDictValue());
                row.createCell(1).setCellValue(sysDictDataList.get(i).getDictLabel());
            }
            changed = true;
        }
        if (changed) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            workbook.write(baos);
            file = baos.toByteArray();
        }
        workbook.close();
        ByteArrayResource resource = new ByteArrayResource(file);
        return ResponseEntity.ok()
                .header("Access-Control-Expose-Headers", HttpHeaders.CONTENT_DISPOSITION)
                .header(HttpHeaders.CONTENT_DISPOSITION,
                        String.format("attachment;filename=%s", URLEncoder.encode("气体预测数据模板.xlsx", StandardCharsets.UTF_8)))
                .header(HttpHeaders.CONTENT_TYPE, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
                .contentLength(file.length)
                .body(resource);
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/controller/mainPlan/ApsBomHeaderController.java
@@ -129,7 +129,8 @@
    @PostMapping("/setBomDataToRedis")
    public void setBomDataToRedis()
    {
        apsBomHeaderService.setBomDataToRedis("");
        apsBomHeaderService.setBomDataToRedis("FORTUNA");
        //apsBomHeaderService.setBomDataToRedis("FORTUNE");
    }
    @PostMapping("/test")
@@ -137,4 +138,10 @@
    {
        apsBomHeaderService.setBomDataToRedis("FORTUNA");
    }
    @GetMapping("/getBomRdsCount/{orgCode}")
    public Integer getBomRdsCount(String orgCode)
    {
        return apsBomHeaderService.getBomKeys(orgCode);
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/controller/mainPlan/ApsGasPipelineMoController.java
@@ -7,15 +7,30 @@
import com.aps.common.log.annotation.Log;
import com.aps.common.log.enums.BusinessType;
import com.aps.common.security.annotation.RequiresPermissions;
import com.aps.common.security.utils.DictUtils;
import com.aps.core.domain.ApsGasPipelineMo;
import com.aps.core.service.IApsGasPipelineMoService;
import com.aps.system.api.domain.SysDictData;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
@@ -117,4 +132,38 @@
    {
        return toAjax(apsGasPipelineMoService.deleteApsGasPipelineMoByIds(ids));
    }
    /**
     * ä¸‹è½½æ°”体预测数据导入模板
     */
    @SneakyThrows
    @Operation(summary = "下载气体工单数据导入模板", description = "下载气体工单数据导入模板")
//    @RequiresPermissions("gasPipeline:mo:template")
//    @Log(title = "下载气体工单数据导入模板", businessType = BusinessType.EXPORT)
    @GetMapping("/template")
    public ResponseEntity<ByteArrayResource> exportTemplate() {
        byte[] file = IOUtils.resourceToByteArray("/templates/气体工单数据模板v1.0.xlsx");
        Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(file));
        Sheet sheet = workbook.getSheet("字典-生产基地");
        List<SysDictData> sysDictDataList = DictUtils.getDictCache("aps_factory");
        if (sysDictDataList != null) {
            for (int i = 0; i < sysDictDataList.size(); i++) {
                Row row = sheet.createRow(i + 1);
                row.createCell(0).setCellValue(sysDictDataList.get(i).getDictValue());
                row.createCell(1).setCellValue(sysDictDataList.get(i).getDictLabel());
            }
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            workbook.write(baos);
            file = baos.toByteArray();
        }
        workbook.close();
        ByteArrayResource resource = new ByteArrayResource(file);
        return ResponseEntity.ok()
                .header("Access-Control-Expose-Headers", HttpHeaders.CONTENT_DISPOSITION)
                .header(HttpHeaders.CONTENT_DISPOSITION,
                        String.format("attachment;filename=%s", URLEncoder.encode("气体工单数据模板.xlsx", StandardCharsets.UTF_8)))
                .header(HttpHeaders.CONTENT_TYPE, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
                .contentLength(file.length)
                .body(resource);
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/controller/mainPlan/ApsGasPipelinePredictionController.java
@@ -7,20 +7,35 @@
import com.aps.common.log.annotation.Log;
import com.aps.common.log.enums.BusinessType;
import com.aps.common.security.annotation.RequiresPermissions;
import com.aps.common.security.utils.DictUtils;
import com.aps.core.domain.ApsGasPipelinePrediction;
import com.aps.core.service.IApsGasPipelinePredictionService;
import com.aps.system.api.domain.SysDictData;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
 * ç®¡è·¯æ‰‹å·¥æ°”体预测数据Controller
 *
 *
 * @author ruoyi
 * @date 2025-05-19
 */
@@ -28,8 +43,7 @@
@Tag(name = "管路手工气体预测数据", description = "管路手工气体预测数据接口")
@RestController
@RequestMapping("/gasPipelinePrediction")
public class ApsGasPipelinePredictionController extends BaseController
{
public class ApsGasPipelinePredictionController extends BaseController {
    @Autowired
    private IApsGasPipelinePredictionService apsGasPipelinePredictionService;
@@ -39,8 +53,7 @@
    @Operation(summary = "查询管路手工气体预测数据列表", description = "分页查询")
    @RequiresPermissions("gasPipeline:prediction:list")
    @GetMapping("/list")
    public TableDataInfo list(ApsGasPipelinePrediction apsGasPipelineMo)
    {
    public TableDataInfo list(ApsGasPipelinePrediction apsGasPipelineMo) {
        startPage();
        List<ApsGasPipelinePrediction> list = apsGasPipelinePredictionService.selectApsGasPipelinePredictionList(apsGasPipelineMo);
        return getDataTable(list);
@@ -54,8 +67,43 @@
    public AjaxResult importData(MultipartFile file) throws Exception {
        apsGasPipelinePredictionService.batchInsertApsGasPipelinePrediction(file);
        return  toAjax(true);
        return toAjax(true);
    }
    /**
     * ä¸‹è½½æ°”体预测数据导入模板
     */
    @SneakyThrows
    @Operation(summary = "下载气体预测数据导入模板", description = "下载气体预测数据导入模板")
//    @RequiresPermissions("gasPipeline:prediction:template")
//    @Log(title = "下载气体预测数据导入模板", businessType = BusinessType.EXPORT)
    @GetMapping("/template")
    public ResponseEntity<ByteArrayResource> exportTemplate() {
        byte[] file = IOUtils.resourceToByteArray("/templates/气体预测数据模板v1.0.xlsx");
        Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(file));
        Sheet sheet = workbook.getSheet("字典-生产基地");
        List<SysDictData> sysDictDataList = DictUtils.getDictCache("aps_factory");
        if (sysDictDataList != null) {
            for (int i = 0; i < sysDictDataList.size(); i++) {
                Row row = sheet.createRow(i + 1);
                row.createCell(0).setCellValue(sysDictDataList.get(i).getDictValue());
                row.createCell(1).setCellValue(sysDictDataList.get(i).getDictLabel());
            }
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            workbook.write(baos);
            file = baos.toByteArray();
        }
        workbook.close();
        ByteArrayResource resource = new ByteArrayResource(file);
        return ResponseEntity.ok()
                .header("Access-Control-Expose-Headers", HttpHeaders.CONTENT_DISPOSITION)
                .header(HttpHeaders.CONTENT_DISPOSITION,
                        String.format("attachment;filename=%s", URLEncoder.encode("气体预测数据模板.xlsx", StandardCharsets.UTF_8)))
                .header(HttpHeaders.CONTENT_TYPE, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
                .contentLength(file.length)
                .body(resource);
    }
    /**
     * å¯¼å‡ºç®¡è·¯æ‰‹å·¥æ°”体预测数据列表
     */
@@ -63,8 +111,7 @@
    @RequiresPermissions("gasPipeline:prediction:export")
    @Log(title = "管路手工气体预测数据", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, ApsGasPipelinePrediction apsGasPipelinePrediction)
    {
    public void export(HttpServletResponse response, ApsGasPipelinePrediction apsGasPipelinePrediction) {
        List<ApsGasPipelinePrediction> list = apsGasPipelinePredictionService.selectApsGasPipelinePredictionList(apsGasPipelinePrediction);
        ExcelUtil<ApsGasPipelinePrediction> util = new ExcelUtil<ApsGasPipelinePrediction>(ApsGasPipelinePrediction.class);
        util.exportExcel(response, list, "管路手工气体预测数据数据");
@@ -76,8 +123,7 @@
    @Operation(summary = "获取管路手工气体预测数据详细信息", description = "根据id获取")
    @RequiresPermissions("gasPipeline:prediction:query")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(apsGasPipelinePredictionService.selectApsGasPipelinePredictionById(id));
    }
@@ -88,8 +134,7 @@
    @RequiresPermissions("gasPipeline:prediction:add")
    @Log(title = "管路手工气体预测数据", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody ApsGasPipelinePrediction apsGasPipelinePrediction)
    {
    public AjaxResult add(@RequestBody ApsGasPipelinePrediction apsGasPipelinePrediction) {
        return toAjax(apsGasPipelinePredictionService.insertApsGasPipelinePrediction(apsGasPipelinePrediction));
    }
@@ -100,8 +145,7 @@
    @RequiresPermissions("gasPipeline:prediction:edit")
    @Log(title = "管路手工气体预测数据", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody ApsGasPipelinePrediction apsGasPipelinePrediction)
    {
    public AjaxResult edit(@RequestBody ApsGasPipelinePrediction apsGasPipelinePrediction) {
        return toAjax(apsGasPipelinePredictionService.updateApsGasPipelinePrediction(apsGasPipelinePrediction));
    }
@@ -111,9 +155,8 @@
    @Operation(summary = "删除管路手工气体预测数据", description = "批量删除")
    @RequiresPermissions("gasPipeline:prediction:remove")
    @Log(title = "管路手工气体预测数据", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(apsGasPipelinePredictionService.deleteApsGasPipelinePredictionByIds(ids));
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/controller/mainPlan/ApsMaterialProductGroupManagementController.java
@@ -56,6 +56,8 @@
        apsMaterialProductGroupManagementService.batchInsertApsMaterialProductGroupManagement(file);
        return  toAjax(true);
    }
    /**
     * å¯¼å‡ºç‰©æ–™äº§å“ç»„数据管理列表
     */
aps-modules/aps-core/src/main/java/com/aps/core/controller/mainPlan/ApsPlate/ApsPlateProcessShopStatController.java
@@ -6,9 +6,11 @@
import com.aps.common.log.enums.BusinessType;
import com.aps.common.security.annotation.RequiresPermissions;
import com.aps.core.domain.ApsPlate.ApsPlateProcessShopStat;
import com.aps.core.service.ApsPlanTaskService;
import com.aps.core.service.ApsPlate.IApsPlateProcessShopStatService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -27,7 +29,8 @@
{
    @Autowired
    private IApsPlateProcessShopStatService apsPlateProcessShopStatService;
    @Resource
    ApsPlanTaskService apsPlanTaskService;
    /**
     * å¯¼å‡ºé’£é‡‘车间统计列表
@@ -48,12 +51,17 @@
    @Operation(summary = "钣金计划大表", description = "更新统计数据")
    @Log(title = "钣金车间统计", businessType = BusinessType.UPDATE)
    @RequiresPermissions("plateProcessShopStat:update")
    //@RequiresPermissions("plateProcessShopStat:update")
    @PostMapping("/update")
    public AjaxResult update()
    {
        apsPlateProcessShopStatService.saveShopStat();
        return toAjax(true);
        try {
           return  apsPlanTaskService.generatorPlatePlanTable();
        } catch (Exception e) {
          return AjaxResult.error("更新失败!"+e.getMessage());
        }
    }
    /**
aps-modules/aps-core/src/main/java/com/aps/core/controller/mainPlan/ApsPlate/ApsPlateProcessStatController.java
@@ -89,7 +89,7 @@
    @PostMapping("/update")
    public AjaxResult updateStat()
    {
        apsPlateProcessStatService.savePlateProcessStat();
        apsPlateProcessStatService.computePlateProcessStat();
        return toAjax(true);
    }
    /**
aps-modules/aps-core/src/main/java/com/aps/core/controller/mainPlan/ApsWeldSeamStatisticsV2Controller.java
@@ -14,6 +14,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
/**
@@ -45,14 +46,11 @@
    /**
     * å¯¼å‡ºç„Šç¼ç»Ÿè®¡è¡¨V2列表
     */
    @RequiresPermissions("weldSeamStatistics:weldSeamStatisticsV2:export")
    //@RequiresPermissions("weldSeamStatistics:weldSeamStatisticsV2:export")
    @Log(title = "焊缝统计表V2", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, ApsWeldSeamStatisticsV2 apsWeldSeamStatisticsV2)
    {
        List<ApsWeldSeamStatisticsV2> list = apsWeldSeamStatisticsV2Service.selectApsWeldSeamStatisticsV2List(apsWeldSeamStatisticsV2);
        ExcelUtil<ApsWeldSeamStatisticsV2> util = new ExcelUtil<ApsWeldSeamStatisticsV2>(ApsWeldSeamStatisticsV2.class);
        util.exportExcel(response, list, "焊缝统计表V2数据");
    public void export(HttpServletResponse response, ApsWeldSeamStatisticsV2 apsWeldSeamStatisticsV2) throws IOException {
        apsWeldSeamStatisticsV2Service.exportWeldSeamStatistics(response);
    }
    /**
aps-modules/aps-core/src/main/java/com/aps/core/domain/ApsGasPipelineCapacityPlan.java
@@ -2,9 +2,14 @@
import com.aps.common.core.annotation.Excel;
import com.aps.common.core.web.domain.BaseEntity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.springframework.data.annotation.Id;
import java.math.BigDecimal;
@@ -14,12 +19,16 @@
 * @author hjy
 * @date 2025-04-24
 */
@Data
@Schema(description = "气体管路产能规划实体类")
public class ApsGasPipelineCapacityPlan extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    @Id
    @TableId(type = IdType.AUTO)
    /** ä¸»é”®id */
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    @Schema(description = "主键id", type = "Long")
    private Long id;
@@ -58,6 +67,7 @@
    @Schema(description = "日产出单位", type = "String")
    private String dayProduceUnit;
    /** äººå‘˜æ•°é‡ */
    @Excel(name = "人员数量")
    @Schema(description = "人员数量", type = "BigDecimal")
@@ -83,6 +93,12 @@
    @Schema(description = "工厂代码", type = "String")
    private String orgCode;
    /** è½¦é—´ */
    @Excel(name = "车间")
    @Schema(description = "车间", type = "String")
    private String workshop;
    public void setOrgCode(String orgCode)
    {
        this.orgCode = orgCode;
aps-modules/aps-core/src/main/java/com/aps/core/domain/ApsGasPipelineMo.java
@@ -11,6 +11,7 @@
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Date;
/**
 * ç®¡è·¯æ‰‹å·¥æ°”体工单数据对象 aps_gas_pipeline_mo
@@ -45,70 +46,14 @@
    @Schema(description = "料号")
    private String materialCode;
    /** è®¡åˆ’完工日期 */
    /** è®¡åˆ’完工日 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Excel(name = "计划完工日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Schema(description = "计划完工日期")
    private Timestamp planEnd;
    @Excel(name = "计划完工日", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Schema(description = "计划完工日")
    private Date planEnd;
    /** æ•°é‡ */
    @Excel(name = "数量")
    @Schema(description = "数量")
    private BigDecimal quantity;
    public void setId(Long id)
    {
        this.id = id;
    }
    public Long getId()
    {
        return id;
    }
    public void setMo(String mo)
    {
        this.mo = mo;
    }
    public String getMo()
    {
        return mo;
    }
    public void setFactory(String factory)
    {
        this.factory = factory;
    }
    public String getFactory()
    {
        return factory;
    }
    public void setMaterialCode(String materialCode)
    {
        this.materialCode = materialCode;
    }
    public String getMaterialCode()
    {
        return materialCode;
    }
    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("id", getId())
            .append("mo", getMo())
            .append("factory", getFactory())
            .append("materialCode", getMaterialCode())
            .append("planEnd", getPlanEnd())
            .append("createBy", getCreateBy())
            .append("createTime", getCreateTime())
            .append("updateBy", getUpdateBy())
            .append("updateTime", getUpdateTime())
            .toString();
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/domain/ApsGasPipelinePrediction.java
@@ -12,6 +12,7 @@
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -48,7 +49,7 @@
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Excel(name = "预测日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Schema(description = "预测日期")
    private Timestamp predictDate;
    private Date predictDate;
    /** æ•°é‡ */
    @Excel(name = "数量")
aps-modules/aps-core/src/main/java/com/aps/core/domain/ApsGasPipingRouteStat.java
@@ -61,17 +61,18 @@
    private BigDecimal processTotalTime;
    /** è®¡åˆ’开工日 */
    @Excel(name = "计划开工日", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Excel(name = "计划开工日", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Schema(description = "计划开工日", type = "Date")
    private Date processPlanStartDay;
    /** è®¾è®¡å·¥æ—¶ */
    @Excel(name = "设计工时")
    @Schema(description = "设计工时", type = "Long")
    private Long designTimes;
    @Schema(description = "设计工时", type = "BigDecimal")
    private BigDecimal designTimes;
    /** åˆ é™¤æ ‡å¿—(0代表存在 2代表删除) */
    @Schema(description = "删除标志(0代表存在 2代表删除)", type = "String")
    @Schema(description = "删除标志", type = "String")
    private String delFlag;
    /** å·¥åºåç§° */
@@ -99,7 +100,7 @@
    @Schema(description = "设计产能", type = "BigDecimal")
    private BigDecimal designCapacity;
    /** è®¾è®¡äº§èƒ½ */
    /** ä¸“业 */
    @Excel(name = "专业")
    @Schema(description = "专业", type = "String")
    private String major;
@@ -119,13 +120,38 @@
    @Schema(description = "日", type = "String")
    private String planStartDay;
    /** è®¡åˆ’完成日 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Excel(name = "计划完成日", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Schema(description = "计划完成日", type = "Date")
    private Date processPlanEndDay;
    /** è®¢å•计划完成日 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Excel(name = "订单计划完成日", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Schema(description = "订单计划完成日", type = "Date")
    private Date orderPlanEndDay;
    /** è­¦å‘Š */
    @Excel(name = "警告")
    @Schema(description = "警告", type = "Boolean")
    private Boolean warning;
    /** å·¥åŽ‚ */
    @Excel(name = "工厂")
    @Schema(description = "工厂", type = "String")
    private String plant;
    /** è½¦é—´ */
    @Excel(name = "车间")
    @Schema(description = "车间", type = "String")
    private String workshop;
    /** æ‰¹æ¬¡å· */
    @Excel(name = "批次号")
    @Schema(description = "批次号", type = "String")
    private String batchNumber;
    /** å·¥åŽ‚ */
    private String plant;
    @Transient
    private String searchStartDate;
@@ -135,14 +161,8 @@
    @Transient
    private String searchType;
    private Boolean warning;
    private Integer num;
    private BigDecimal routeProcessNumber;
    private Date orderPlanEndDay;
    /** è®¡åˆ’完成日 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Excel(name = "计划完工日", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    private Date processPlanEndDay;
    @Override
    public String toString() {
aps-modules/aps-core/src/main/java/com/aps/core/domain/ApsMaterialProductGroupManagement.java
@@ -1,14 +1,12 @@
package com.aps.core.domain;
import com.aps.common.core.annotation.Excel;
import com.aps.common.core.web.domain.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.aps.common.core.annotation.Excel;
import org.springframework.data.annotation.Id;
/**
@@ -31,7 +29,7 @@
    /**
     * é€‚用工厂  å‚考 aps_factory
     */
    @Excel(name = "适用工厂  å‚考 aps_factory")
    @Excel(name = "适用工厂")
    @Schema(description = "适用工厂  å‚考 aps_factory")
    private String factory;
@@ -45,20 +43,26 @@
    /**
     * ä¸“业 å‚考    aps_domain
     */
    @Excel(name = "专业 å‚考    aps_domain")
    @Excel(name = "专业归属")
    @Schema(description = "专业 å‚考    aps_domain")
    private String domain;
    /**
     * æ˜¯å¦ä¸ºä¸»é˜¶ æ˜¯/否
     */
    @Excel(name = "是否为主阶 æ˜¯/否")
    @Excel(name = "是否主阶料号")
    @Schema(description = "是否为主阶 æ˜¯/否")
    private String isMain;
    @JsonIgnore
    @TableField(exist = false)
    private String key;
    /**
     * æ–™å·ç±»åˆ« åˆ¶é€ ä»¶/采购件
     */
    @Excel(name = "料号类别")
    @Schema(description = "料号类别 åˆ¶é€ ä»¶/采购件")
    private String materialType;
    @JsonIgnore
    public String getKey() {
@@ -66,76 +70,5 @@
            key = getFactory() + "##" + getMaterialCode();
        }
        return key;
    }
    /**
     * æ–™å·ç±»åˆ« åˆ¶é€ ä»¶/采购件
     */
    @Excel(name = "料号类别 åˆ¶é€ ä»¶/采购件")
    @Schema(description = "料号类别 åˆ¶é€ ä»¶/采购件")
    private String materialType;
    public void setId(Long id) {
        this.id = id;
    }
    public Long getId() {
        return id;
    }
    public void setFactory(String factory) {
        this.factory = factory;
    }
    public String getFactory() {
        return factory;
    }
    public void setMaterialCode(String materialCode) {
        this.materialCode = materialCode;
    }
    public String getMaterialCode() {
        return materialCode;
    }
    public void setDomain(String domain) {
        this.domain = domain;
    }
    public String getDomain() {
        return domain;
    }
    public void setIsMain(String isMain) {
        this.isMain = isMain;
    }
    public String getIsMain() {
        return isMain;
    }
    public void setMaterialType(String materialType) {
        this.materialType = materialType;
    }
    public String getMaterialType() {
        return materialType;
    }
    @Override
    public String toString() {
        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
                .append("id", getId())
                .append("factory", getFactory())
                .append("materialCode", getMaterialCode())
                .append("domain", getDomain())
                .append("createBy", getCreateBy())
                .append("createTime", getCreateTime())
                .append("updateBy", getUpdateBy())
                .append("updateTime", getUpdateTime())
                .append("isMain", getIsMain())
                .append("materialType", getMaterialType())
                .toString();
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/domain/ApsStandardProcess.java
@@ -2,97 +2,131 @@
import com.aps.common.core.annotation.Excel;
import com.aps.common.core.web.domain.BaseEntity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.springframework.data.annotation.Id;
import java.math.BigDecimal;
/**
 * æ ‡å‡†å·¥åºå¯¹è±¡ aps_standard_process
 *
 *
 * @author hjy
 * @date 2025-04-23
 */
@Schema(description = "标准工序实体")
public class ApsStandardProcess extends BaseEntity
{
public class ApsStandardProcess extends BaseEntity {
    private static final long serialVersionUID = 1L;
    @Id
    @TableId(type = IdType.AUTO)
    /** ä¸»é”®id */
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    /** ä¸»é”®id */
    @Schema(description = "主键id", type = "Long")
    private Long id;
    /** å·¥åºç¼–码 */
    /**
     * å·¥åºç¼–码
     */
    @Schema(description = "工序编码", type = "String")
    @Excel(name = "工序编码")
    private String processNumber;
    /** å·¥åºåç§° */
    /**
     * å·¥åºåç§°
     */
    @Schema(description = "工序名称", type = "String")
    @Excel(name = "工序名称")
    private String processName;
    /** èµ„源组 */
    /**
     * èµ„源组
     */
    @Schema(description = "资源组", type = "String")
    @Excel(name = "资源组")
    private String resourceGroupName;
    /** ä¸“业 */
    /**
     * ä¸“业
     */
    @Schema(description = "专业", type = "String")
    @Excel(name = "专业")
    private String major;
    /** äº§èƒ½æ¨¡åž‹: ç‹¬å /合批 */
    /**
     * äº§èƒ½æ¨¡åž‹: ç‹¬å /合批
     */
    @Schema(description = "产能模型", type = "String")
    @Excel(name = "产能模型")
    private String model;
    /** è®¾è®¡äº§èƒ½ */
    /**
     * è®¾è®¡äº§èƒ½
     */
    @Schema(description = "设计产能", type = "String")
    @Excel(name = "设计产能")
    private BigDecimal designCapacity;
    /** å·¥åŽ‚Id */
    /**
     * å·¥åŽ‚Id
     */
    @Schema(description = "工厂Id", type = "String")
//    @Excel(name = "工厂Id")
    private String plantId;
    /** å·¥åŽ‚ */
    /**
     * å·¥åŽ‚
     */
    @Schema(description = "适用工厂", type = "String")
    @Excel(name = "适用工厂")
    private String plant;
    /** è½¦é—´Id */
    /**
     * è½¦é—´Id
     */
    @Schema(description = "车间Id", type = "String")
//    @Excel(name = "车间Id")
    private String workShopId;
    /** è½¦é—´ */
    /**
     * è½¦é—´
     */
    @Schema(description = "适用车间", type = "String")
    @Excel(name = "适用车间")
    private String workShop;
    /** æ—¥åކId */
    /**
     * æ—¥åކId
     */
    @Schema(description = "日历Id", type = "Long")
//    @Excel(name = "日历Id")
    private Long workCalenderId;
    /** æ—¥åŽ†æè¿° */
    /**
     * æ—¥åŽ†æè¿°
     */
    @Schema(description = "日历描述", type = "String")
    @Excel(name = "日历描述")
    private String workCalender;
    /** äº§èƒ½æ¨¡åž‹Id */
    /**
     * äº§èƒ½æ¨¡åž‹Id
     */
    @Schema(description = "产能模型Id", type = "Long")
//    @Excel(name = "产能模型Id")
    private Long modelId;
    /** åˆ é™¤æ ‡å¿—(0代表存在 2代表删除) */
    /**
     * åˆ é™¤æ ‡å¿—(0代表存在 2代表删除)
     */
    @Schema(description = "删除标志(0代表存在 2代表删除)", type = "String")
    private String delFlag;
    public String getMajor() {
@@ -103,168 +137,140 @@
        this.major = major;
    }
    public void setId(Long id)
    {
    public void setId(Long id) {
        this.id = id;
    }
    public Long getId()
    {
    public Long getId() {
        return id;
    }
    public void setProcessNumber(String processNumber)
    {
    public void setProcessNumber(String processNumber) {
        this.processNumber = processNumber;
    }
    public String getProcessNumber()
    {
    public String getProcessNumber() {
        return processNumber;
    }
    public void setProcessName(String processName)
    {
    public void setProcessName(String processName) {
        this.processName = processName;
    }
    public String getProcessName()
    {
    public String getProcessName() {
        return processName;
    }
    public void setResourceGroupName(String resourceGroupName)
    {
    public void setResourceGroupName(String resourceGroupName) {
        this.resourceGroupName = resourceGroupName;
    }
    public String getResourceGroupName()
    {
    public String getResourceGroupName() {
        return resourceGroupName;
    }
    public void setModel(String model)
    {
    public void setModel(String model) {
        this.model = model;
    }
    public String getModel()
    {
    public String getModel() {
        return model;
    }
    public void setDesignCapacity(BigDecimal designCapacity)
    {
    public void setDesignCapacity(BigDecimal designCapacity) {
        this.designCapacity = designCapacity;
    }
    public BigDecimal getDesignCapacity()
    {
    public BigDecimal getDesignCapacity() {
        return designCapacity;
    }
    public void setPlantId(String plantId)
    {
    public void setPlantId(String plantId) {
        this.plantId = plantId;
    }
    public String getPlantId()
    {
    public String getPlantId() {
        return plantId;
    }
    public void setPlant(String plant)
    {
    public void setPlant(String plant) {
        this.plant = plant;
    }
    public String getPlant()
    {
    public String getPlant() {
        return plant;
    }
    public void setWorkShopId(String workShopId)
    {
    public void setWorkShopId(String workShopId) {
        this.workShopId = workShopId;
    }
    public String getWorkShopId()
    {
    public String getWorkShopId() {
        return workShopId;
    }
    public void setWorkShop(String workShop)
    {
    public void setWorkShop(String workShop) {
        this.workShop = workShop;
    }
    public String getWorkShop()
    {
    public String getWorkShop() {
        return workShop;
    }
    public void setWorkCalenderId(Long workCalenderId)
    {
    public void setWorkCalenderId(Long workCalenderId) {
        this.workCalenderId = workCalenderId;
    }
    public Long getWorkCalenderId()
    {
    public Long getWorkCalenderId() {
        return workCalenderId;
    }
    public void setDelFlag(String delFlag)
    {
    public void setDelFlag(String delFlag) {
        this.delFlag = delFlag;
    }
    public String getDelFlag()
    {
    public String getDelFlag() {
        return delFlag;
    }
    public void setModelId(Long modelId)
    {
    public void setModelId(Long modelId) {
        this.modelId = modelId;
    }
    public Long getModelId()
    {
    public Long getModelId() {
        return modelId;
    }
    public void setWorkCalender(String workCalender)
    {
    public void setWorkCalender(String workCalender) {
        this.workCalender = workCalender;
    }
    public String getWorkCalender()
    {
    public String getWorkCalender() {
        return workCalender;
    }
    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("id", getId())
            .append("processNumber", getProcessNumber())
            .append("processName", getProcessName())
            .append("resourceGroupName", getResourceGroupName())
            .append("model", getModel())
            .append("designCapacity", getDesignCapacity())
            .append("plantId", getPlantId())
            .append("plant", getPlant())
            .append("workShopId", getWorkShopId())
            .append("workShop", getWorkShop())
            .append("workCalenderId", getWorkCalenderId())
            .append("delFlag", getDelFlag())
            .append("createBy", getCreateBy())
            .append("createTime", getCreateTime())
            .append("updateBy", getUpdateBy())
            .append("updateTime", getUpdateTime())
            .append("modelId", getModelId())
            .append("workCalender", getWorkCalender())
            .append("major", getMajor())
            .toString();
        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
                .append("id", getId())
                .append("processNumber", getProcessNumber())
                .append("processName", getProcessName())
                .append("resourceGroupName", getResourceGroupName())
                .append("model", getModel())
                .append("designCapacity", getDesignCapacity())
                .append("plantId", getPlantId())
                .append("plant", getPlant())
                .append("workShopId", getWorkShopId())
                .append("workShop", getWorkShop())
                .append("workCalenderId", getWorkCalenderId())
                .append("delFlag", getDelFlag())
                .append("createBy", getCreateBy())
                .append("createTime", getCreateTime())
                .append("updateBy", getUpdateBy())
                .append("updateTime", getUpdateTime())
                .append("modelId", getModelId())
                .append("workCalender", getWorkCalender())
                .append("major", getMajor())
                .toString();
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/enums/PLAN_TASK_STATUS.java
@@ -2,8 +2,8 @@
public enum PLAN_TASK_STATUS {
    IN_PROCESS("InProgress","进行中"),
    FINISHED("Finished","完成");
    FINISHED("Finished","完成"),
    ERROR("Error","失败");
    private String code;
    private String desc;
aps-modules/aps-core/src/main/java/com/aps/core/enums/PLAN_TASK_TYPE.java
@@ -2,8 +2,8 @@
public enum PLAN_TASK_TYPE {
    PLATE_PLAN("PlateOrderPlan","生成钣金工单计划");
    PLATE_PLAN("PlateOrderPlan","生成钣金工单计划"),
    PLATE_SHOP_PLAN_TABLE("PlateShopPlanTable","生成钣金计划大表");
    private String code;
    private String desc;
aps-modules/aps-core/src/main/java/com/aps/core/enums/REDIS_LOCK_KEY.java
@@ -3,8 +3,9 @@
public enum REDIS_LOCK_KEY {
    /*钣金工单计划任务*/
    PLATE_ORDER_PLAN("PLAN_TASK:PLATE_ORDER_PLAN");
    PLATE_ORDER_PLAN("PLAN_TASK:PLATE_ORDER_PLAN"),
    /*钣金计划大表*/
    PLATE_SHOP_PLAN_TABLE("PLAN_TASK:PLATE_SHOP_PLAN_TABLE");
    private String key;
    public String getKey() {
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsGasPipelineCapacityPlanMapper.java
@@ -1,7 +1,9 @@
package com.aps.core.mapper;
import com.aps.core.domain.ApsGasPipelineCapacityPlan;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -12,7 +14,7 @@
 * @date 2025-04-24
 */
@Mapper
public interface ApsGasPipelineCapacityPlanMapper
public interface ApsGasPipelineCapacityPlanMapper extends BaseMapper<ApsGasPipelineCapacityPlan>
{
    /**
     * æŸ¥è¯¢æ°”体管路产能规划
@@ -29,6 +31,23 @@
     * @return æ°”体管路产能规划集合
     */
    public List<ApsGasPipelineCapacityPlan> selectApsGasPipelineCapacityPlanList(ApsGasPipelineCapacityPlan apsGasPipelineCapacityPlan);
    /**
     * æŸ¥è¯¢è®¾è®¡äº§èƒ½æ•°æ® - ä¸“用于接口二功能
     *
     * @param processName å·¥åºåç§°
     * @param year å¹´ä»½
     * @param month æœˆä»½
     * @param major ä¸“业
     * @param orgCode å·¥åŽ‚ä»£ç 
     * @return æ°”体管路产能规划集合
     */
    public List<ApsGasPipelineCapacityPlan> selectDesignCapacityForInterface2(
            @Param("processName") String processName,
            @Param("year") String year,
            @Param("month") String month,
            @Param("major") String major,
            @Param("orgCode") String orgCode);
    /**
     * æ–°å¢žæ°”体管路产能规划
@@ -61,4 +80,6 @@
     * @return ç»“æžœ
     */
    public int deleteApsGasPipelineCapacityPlanByIds(Long[] ids);
    void deleteByDateAndFactory(String year, String month, String factory, String major);
}
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsGasPipingRouteStatMapper.java
@@ -4,6 +4,7 @@
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
/**
 * æ°”体管路产能负载统计Mapper接口
@@ -69,7 +70,6 @@
     */
    public int deleteApsGasPipingRouteStatByBatchNum(String batchNumber);
    /**
     * æ‰¹é‡æ’入管路气柜产能数据
     * @param apsGasPipingRouteStatList
@@ -78,4 +78,70 @@
    public int insertApsGasPipingRouteStatBatch(List<ApsGasPipingRouteStat> apsGasPipingRouteStatList);
    List<ApsGasPipingRouteStat> queryTempStat();
    /**
     * åˆ é™¤æ‰€æœ‰æ°”体管路产能负载统计数据
     *
     * @return ç»“æžœ
     */
    public int deleteAll();
    /**
     * è”合查询手工气体预测数据相关信息
     *
     * @return æ‰‹å·¥æ°”体预测数据及关联信息
     */
    public List<Map<String, Object>> selectPredictionRouteData();
    /**
     * è”合查询手工气体工单数据相关信息
     *
     * @return æ‰‹å·¥æ°”体工单数据及关联信息
     */
    public List<Map<String, Object>> selectMoRouteData();
    /**
     * æ ¹æ®æ—¶é—´ç»´åº¦èšåˆæŸ¥è¯¢ç»Ÿè®¡æ•°æ®
     *
     * @param params æŸ¥è¯¢å‚数,包含时间范围和过滤条件
     * @return æŒ‰å·¥åºåç§°å’Œæ—¶é—´ç»´åº¦èšåˆçš„æ•°æ®
     */
    public List<Map<String, Object>> selectAggregatedStatData(Map<String, Object> params);
    /**
     * æŸ¥è¯¢åŽŸå§‹ç»Ÿè®¡æ•°æ®ï¼ˆä¸è¿›è¡Œèšåˆï¼‰
     *
     * @param params æŸ¥è¯¢å‚æ•°
     * @return åŽŸå§‹ç»Ÿè®¡æ•°æ®åˆ—è¡¨
     */
    public List<Map<String, Object>> selectRawStatData(Map<String, Object> params);
    /**
     * æŸ¥è¯¢æ‰€æœ‰æ‰‹å·¥æ°”体工单数据
     *
     * @return æ‰€æœ‰æ‰‹å·¥æ°”体工单数据
     */
    public List<Map<String, Object>> selectAllMoData();
    /**
     * æŸ¥è¯¢åŸºç¡€ç»Ÿè®¡æ•°æ®ï¼ˆä¸åŒ…含时间限制)
     *
     * @param params æŸ¥è¯¢å‚数(不包含时间范围参数)
     * @return åŸºç¡€ç»Ÿè®¡æ•°æ®åˆ—表
     */
    public List<Map<String, Object>> selectBaseStatData(Map<String, Object> params);
    /**
     * æŸ¥è¯¢æ‰€æœ‰åŽ»é‡çš„å·¥åºåç§°
     *
     * @return æ‰€æœ‰åŽ»é‡çš„å·¥åºåç§°åˆ—è¡¨
     */
    public List<String> selectDistinctProcessNames();
    /**
     * æŸ¥è¯¢æ‰€æœ‰åŽ»é‡çš„è½¦é—´
     *
     * @return æ‰€æœ‰åŽ»é‡çš„è½¦é—´åˆ—è¡¨
     */
    public List<String> selectDistinctWorkshops();
}
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsPlateProcessStatMapper.java
@@ -73,4 +73,6 @@
     * æ‰¹é‡æ’入数据
     * */
    int batchInsertPlateStat(List<ApsPlateProcessStat> list);
    int deleteAll();
}
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsPlateStandardRequireErrorMapper.java
@@ -61,5 +61,13 @@
     */
    public int deleteApsPlateStandardRequireErrorByIds(Long[] ids);
    
    /**
     * æ‰¹é‡æ’入钣金标准需求异常信息
     *
     * @param errorList éœ€è¦æ’入的异常数据集合
     * @return ç»“æžœ
     */
    public int batchInsert(List<ApsPlateStandardRequireError> errorList);
    int deleteLastPatch(String batchNumber);
}
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsShopMapper.java
@@ -1,8 +1,13 @@
package com.aps.core.mapper;
import java.util.List;
import java.util.Set;
import com.aps.core.domain.ApsShop;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.jetbrains.annotations.NotNull;
/**
 * è½¦é—´Mapper接口
@@ -11,7 +16,7 @@
 * @date 2025-04-14
 */
@Mapper
public interface ApsShopMapper
public interface ApsShopMapper extends BaseMapper<ApsShop>
{
    /**
     * æŸ¥è¯¢è½¦é—´
@@ -60,4 +65,32 @@
     * @return ç»“æžœ
     */
    public int deleteApsShopByIds(String[] ids);
    @Select("""
        <script>
            select * from aps_shop where 1 = 0
            <if test="!names.isEmpty()"> or shop_name in
                <foreach collection="names" item="item" open="(" separator="," close=")">
                    #{item}
                </foreach>
            </if>
        </script>
    """)
    List<ApsShop> selectApsByName(@NotNull Set<String> names);
    @Select("select * from aps_shop where plant_code = #{orgCode}")
    List<ApsShop> selectApsByFactory(String orgCode);
    @Select("""
        <script>
            select * from aps_shop where 1 = 0
            <if test="!codes.isEmpty()"> or shop_code in
                <foreach collection="codes" item="item" open="(" separator="," close=")">
                    #{item}
                </foreach>
            </if>
        </script>
    """)
    List<ApsShop> selectByCodes(Set<String> codes);
}
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsStandardProcessMapper.java
@@ -1,6 +1,7 @@
package com.aps.core.mapper;
import com.aps.core.domain.ApsStandardProcess;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
@@ -10,7 +11,7 @@
 * @author hjy
 * @date 2025-04-23
 */
public interface ApsStandardProcessMapper
public interface ApsStandardProcessMapper extends BaseMapper<ApsStandardProcess>
{
    /**
     * æŸ¥è¯¢æ ‡å‡†å·¥åº
aps-modules/aps-core/src/main/java/com/aps/core/service/ApsPlanTaskService.java
@@ -23,4 +23,6 @@
    void updateTaskStatus(String batchNum, PLAN_TASK_STATUS status);
    AjaxResult generatorPlan();
    AjaxResult generatorPlatePlanTable();
}
aps-modules/aps-core/src/main/java/com/aps/core/service/ApsPlate/IApsPlateProcessStatService.java
@@ -60,6 +60,6 @@
     */
    public int deleteApsPlateProcessStatById(String id);
    @Transactional
    void savePlateProcessStat();
    List<ApsPlateProcessStat> computePlateProcessStat();
}
aps-modules/aps-core/src/main/java/com/aps/core/service/ApsPlate/IApsPlateStandardRequireBatchService.java
@@ -63,5 +63,5 @@
    String getNewBatchNumber();
    @Transactional
    void initRequireBatch();
    void initRequireBatch(String batchNumber);
}
aps-modules/aps-core/src/main/java/com/aps/core/service/ApsPlate/IApsPlateStandardRequireErrorService.java
@@ -1,6 +1,8 @@
package com.aps.core.service.ApsPlate;
import java.util.List;
import com.aps.core.domain.ApsPlate.ApsPlateStandardRequire;
import com.aps.core.domain.ApsPlate.ApsPlateStandardRequireError;
/**
@@ -58,4 +60,6 @@
     * @return ç»“æžœ
     */
    public int deleteApsPlateStandardRequireErrorById(Long id);
    void saveRequireError(ApsPlateStandardRequire require, String message);
}
aps-modules/aps-core/src/main/java/com/aps/core/service/IApsBomHeaderService.java
@@ -66,4 +66,6 @@
     * @return
     */
    public boolean setBomDataToRedis(String orgCode);
    Integer getBomKeys(String orgCode);
}
aps-modules/aps-core/src/main/java/com/aps/core/service/IApsGasPipelineCapacityPlanService.java
@@ -59,4 +59,6 @@
     * @return ç»“æžœ
     */
    public int deleteApsGasPipelineCapacityPlanById(Long id);
    void copyPlan(String date, String factory, String major, String toStart, String toEnd);
}
aps-modules/aps-core/src/main/java/com/aps/core/service/IApsGasPipingRouteStatService.java
@@ -6,6 +6,7 @@
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
/**
 * æ°”体管路产能负载统计Service接口
@@ -88,4 +89,20 @@
    @Transactional
    void saveGasPipingRoutStateList();
    /**
     * æ ¹æ®æ‰‹å·¥æ°”体预测数据和手工气体工单数据生成统计数据
     *
     * @return ç»“æžœ
     */
    @Transactional
    public int generateGasPipingRouteStatData();
    /**
     * èšåˆæ°”体管路产能负载统计数据
     *
     * @param params èšåˆå‚æ•°
     * @return èšåˆç»“æžœ
     */
    public Map<String, Object> aggregateGasPipingRouteStat(Map<String, Object> params);
}
aps-modules/aps-core/src/main/java/com/aps/core/service/IApsShopService.java
@@ -1,7 +1,10 @@
package com.aps.core.service;
import java.util.List;
import java.util.Set;
import com.aps.core.domain.ApsShop;
import org.jetbrains.annotations.NotNull;
/**
 * è½¦é—´Service接口
@@ -58,4 +61,10 @@
     * @return ç»“æžœ
     */
    public int deleteApsShopById(String id);
    List<ApsShop> findAllShops();
    List<ApsShop> findShopByFactory(String orgCode);
    List<ApsShop> findShopByCodes(@NotNull Set<String> collect);
}
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsBomHeaderServiceImpl.java
@@ -131,4 +131,8 @@
        }
        return true;
    }
    @Override
    public Integer getBomKeys(String orgCode){
        return redisTemplate.keys("BOM:BOM_"+orgCode+"*").size();
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsBomServiceImpl.java
@@ -140,10 +140,6 @@
                bomLineList.add(apsBom);
            }
        }
//        else {
//            bomLineList = selectApsBomLineList(plant, itemNumber);
//        }
        return bomLineList;
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipelineCapacityPlanServiceImpl.java
@@ -5,56 +5,59 @@
import com.aps.core.domain.ApsGasPipelineCapacityPlan;
import com.aps.core.mapper.ApsGasPipelineCapacityPlanMapper;
import com.aps.core.service.IApsGasPipelineCapacityPlanService;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
 * æ°”体管路产能规划Service业务层处理
 *
 *
 * @author hjy
 * @date 2025-04-24
 */
@Service
public class ApsGasPipelineCapacityPlanServiceImpl implements IApsGasPipelineCapacityPlanService
{
public class ApsGasPipelineCapacityPlanServiceImpl implements IApsGasPipelineCapacityPlanService {
    @Autowired
    private ApsGasPipelineCapacityPlanMapper apsGasPipelineCapacityPlanMapper;
    /**
     * æŸ¥è¯¢æ°”体管路产能规划
     *
     *
     * @param id æ°”体管路产能规划主键
     * @return æ°”体管路产能规划
     */
    @Override
    public ApsGasPipelineCapacityPlan selectApsGasPipelineCapacityPlanById(Long id)
    {
    public ApsGasPipelineCapacityPlan selectApsGasPipelineCapacityPlanById(Long id) {
        return apsGasPipelineCapacityPlanMapper.selectApsGasPipelineCapacityPlanById(id);
    }
    /**
     * æŸ¥è¯¢æ°”体管路产能规划列表
     *
     *
     * @param apsGasPipelineCapacityPlan æ°”体管路产能规划
     * @return æ°”体管路产能规划
     */
    @Override
    public List<ApsGasPipelineCapacityPlan> selectApsGasPipelineCapacityPlanList(ApsGasPipelineCapacityPlan apsGasPipelineCapacityPlan)
    {
    public List<ApsGasPipelineCapacityPlan> selectApsGasPipelineCapacityPlanList(ApsGasPipelineCapacityPlan apsGasPipelineCapacityPlan) {
        return apsGasPipelineCapacityPlanMapper.selectApsGasPipelineCapacityPlanList(apsGasPipelineCapacityPlan);
    }
    /**
     * æ–°å¢žæ°”体管路产能规划
     *
     *
     * @param apsGasPipelineCapacityPlan æ°”体管路产能规划
     * @return ç»“æžœ
     */
    @Override
    public int insertApsGasPipelineCapacityPlan(ApsGasPipelineCapacityPlan apsGasPipelineCapacityPlan)
    {
    public int insertApsGasPipelineCapacityPlan(ApsGasPipelineCapacityPlan apsGasPipelineCapacityPlan) {
        apsGasPipelineCapacityPlan.setCreateTime(DateUtils.getNowDate());
        apsGasPipelineCapacityPlan.setCreateBy(SecurityUtils.getUsername());
        return apsGasPipelineCapacityPlanMapper.insertApsGasPipelineCapacityPlan(apsGasPipelineCapacityPlan);
@@ -62,13 +65,12 @@
    /**
     * ä¿®æ”¹æ°”体管路产能规划
     *
     *
     * @param apsGasPipelineCapacityPlan æ°”体管路产能规划
     * @return ç»“æžœ
     */
    @Override
    public int updateApsGasPipelineCapacityPlan(ApsGasPipelineCapacityPlan apsGasPipelineCapacityPlan)
    {
    public int updateApsGasPipelineCapacityPlan(ApsGasPipelineCapacityPlan apsGasPipelineCapacityPlan) {
        apsGasPipelineCapacityPlan.setUpdateTime(DateUtils.getNowDate());
        apsGasPipelineCapacityPlan.setUpdateBy(SecurityUtils.getUsername());
        return apsGasPipelineCapacityPlanMapper.updateApsGasPipelineCapacityPlan(apsGasPipelineCapacityPlan);
@@ -76,25 +78,73 @@
    /**
     * æ‰¹é‡åˆ é™¤æ°”体管路产能规划
     *
     *
     * @param ids éœ€è¦åˆ é™¤çš„æ°”体管路产能规划主键
     * @return ç»“æžœ
     */
    @Override
    public int deleteApsGasPipelineCapacityPlanByIds(Long[] ids)
    {
    public int deleteApsGasPipelineCapacityPlanByIds(Long[] ids) {
        return apsGasPipelineCapacityPlanMapper.deleteApsGasPipelineCapacityPlanByIds(ids);
    }
    /**
     * åˆ é™¤æ°”体管路产能规划信息
     *
     *
     * @param id æ°”体管路产能规划主键
     * @return ç»“æžœ
     */
    @Override
    public int deleteApsGasPipelineCapacityPlanById(Long id)
    {
    public int deleteApsGasPipelineCapacityPlanById(Long id) {
        return apsGasPipelineCapacityPlanMapper.deleteApsGasPipelineCapacityPlanById(id);
    }
    @SneakyThrows
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void copyPlan(String date, String factory, String major, String toStart, String toEnd) {
        String[] dtSrc = date.split("-");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Calendar dtStart = Calendar.getInstance();
        dtStart.setTime(sdf.parse(toStart));
        dtStart.set(Calendar.DAY_OF_MONTH, 1);
        Calendar dtEnd = Calendar.getInstance();
        dtEnd.setTime(sdf.parse(toEnd));
        dtEnd.set(Calendar.DAY_OF_MONTH, 2);
        ApsGasPipelineCapacityPlan plan = new ApsGasPipelineCapacityPlan();
        plan.setYear(Integer.valueOf(dtSrc[0]).toString());
        plan.setMonth(Integer.valueOf(dtSrc[1]).toString());
        plan.setOrgCode(factory);
        plan.setMajor(major);
        List<ApsGasPipelineCapacityPlan> templatePlans = apsGasPipelineCapacityPlanMapper.selectApsGasPipelineCapacityPlanList(plan);
        templatePlans.forEach(p -> {
            p.setCreateBy(SecurityUtils.getUsername());
            p.setCreateTime(new Date());
            p.setUpdateBy(null);
            p.setUpdateTime(null);
//                apsGasPipelineCapacityPlanMapper.insertApsGasPipelineCapacityPlan(p);
        });
        while (dtStart.before(dtEnd)) {
            String year = dtStart.get(Calendar.YEAR) + "";
            String month = (dtStart.get(Calendar.MONTH) + 1) + "";
            apsGasPipelineCapacityPlanMapper.deleteByDateAndFactory(
                    year,
                    month,
                    factory,
                    major
            );
            templatePlans.forEach(p -> {
                p.setId(null);
                p.setYear(year);
                p.setMonth(month);
//                apsGasPipelineCapacityPlanMapper.insertApsGasPipelineCapacityPlan(p);
            });
            apsGasPipelineCapacityPlanMapper.insert(templatePlans);
            dtStart.add(Calendar.MONTH, 1);
        }
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipelineMoServiceImpl.java
@@ -2,25 +2,18 @@
import cn.hutool.core.util.IdUtil;
import com.aps.common.core.utils.DateUtils;
import com.aps.common.core.utils.poi.ExcelUtil;
import com.aps.common.security.utils.DictUtils;
import com.aps.common.security.utils.SecurityUtils;
import com.aps.core.domain.ApsGasPipelineMo;
import com.aps.core.mapper.ApsGasPipelineMoMapper;
import com.aps.core.service.IApsGasPipelineMoService;
import io.micrometer.common.util.StringUtils;
import lombok.SneakyThrows;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
@@ -108,49 +101,21 @@
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int batchInsertGasPipelineMo(MultipartFile file) {
        Workbook workbook = WorkbookFactory.create(file.getInputStream());
        Sheet sheet = workbook.getSheetAt(0);
        int rows = sheet.getLastRowNum();
        if (rows > 0) {
            List<ApsGasPipelineMo> list = new ArrayList<>();
        ExcelUtil<ApsGasPipelineMo> util = new ExcelUtil<>(ApsGasPipelineMo.class);
        List<ApsGasPipelineMo> tempList = util.importExcel(file.getInputStream());
        DictUtils.CacheValue cacheValue = DictUtils.getCacheValue("aps_factory");
        tempList.forEach(apsGasPipelineMo -> {
            apsGasPipelineMo.setId(IdUtil.getSnowflakeNextId());
            apsGasPipelineMo.setFactory(cacheValue.get(apsGasPipelineMo.getFactory()));
            apsGasPipelineMo.setCreateBy(SecurityUtils.getUsername());
            apsGasPipelineMo.setCreateTime(DateUtils.getNowDate());
        });
            /*数据列从1开始*/
            for (int i = 1; i <= rows; i++) {
                Row row = sheet.getRow(i);
                if (row.getCell(0) == null){
                    continue;
                }
                String mo = row.getCell(0).getStringCellValue();
                if (StringUtils.isEmpty(mo)){
                    continue;
                }
                String factory = row.getCell(1).getStringCellValue();
                String materialNum = row.getCell(2).getStringCellValue();
                double quantity = row.getCell(3).getNumericCellValue();
                Date planEnd = row.getCell(4).getDateCellValue();
                if (StringUtils.isNotBlank(factory) &&
                    StringUtils.isNotBlank(materialNum) &&
                    planEnd != null) {
                    ApsGasPipelineMo apsGasPipelineMo = new ApsGasPipelineMo();
                    apsGasPipelineMo.setMo(mo);
                    apsGasPipelineMo.setMaterialCode(materialNum);
                    apsGasPipelineMo.setId(IdUtil.getSnowflakeNextId());
                    apsGasPipelineMo.setFactory(factory);
                    apsGasPipelineMo.setCreateBy(SecurityUtils.getUsername());
                    apsGasPipelineMo.setCreateTime(DateUtils.getNowDate());
                    apsGasPipelineMo.setQuantity(new BigDecimal(quantity));
                    apsGasPipelineMo.setPlanEnd(new Timestamp(planEnd.getTime()));
                    list.add(apsGasPipelineMo);
                }
            }
            if (!list.isEmpty()) {
                apsGasPipelineMoMapper.deleteAll();
                apsGasPipelineMoMapper.insert(list);
            }
            return list.size();
        if (!tempList.isEmpty()) {
            apsGasPipelineMoMapper.deleteAll();
            apsGasPipelineMoMapper.insert(tempList);
        }
        return 0;
        return tempList.size();
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipelinePredictionServiceImpl.java
@@ -2,27 +2,19 @@
import cn.hutool.core.util.IdUtil;
import com.aps.common.core.utils.DateUtils;
import com.aps.common.core.utils.poi.ExcelUtil;
import com.aps.common.security.utils.DictUtils;
import com.aps.common.security.utils.SecurityUtils;
import com.aps.core.domain.ApsGasPipelinePrediction;
import com.aps.core.domain.ApsMaterialProductGroupManagement;
import com.aps.core.mapper.ApsGasPipelinePredictionMapper;
import com.aps.core.service.IApsGasPipelinePredictionService;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import io.micrometer.common.util.StringUtils;
import lombok.SneakyThrows;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
/**
@@ -107,70 +99,54 @@
    @SneakyThrows
    @Override
    public int batchInsertApsGasPipelinePrediction(MultipartFile file) {
        Workbook workbook = WorkbookFactory.create(file.getInputStream());
        Sheet sheet = workbook.getSheetAt(0);
        int rows = sheet.getLastRowNum();
        if (rows > 0) {
            List<ApsGasPipelinePrediction> list = new ArrayList<>();
            Set<String> keys = new HashSet<>();
            /*数据列从1开始*/
            for (int i = rows; i > 0; --i) {
                Row row = sheet.getRow(i);
                if (row.getCell(0) == null) {
                    continue;
                }
        ExcelUtil<ApsGasPipelinePrediction> util = new ExcelUtil<>(ApsGasPipelinePrediction.class);
        List<ApsGasPipelinePrediction> list = util.importExcel(file.getInputStream());
        DictUtils.CacheValue cacheValue = DictUtils.getCacheValue("aps_factory");
        Set<String> keys = new HashSet<>();
        list.forEach(item -> {
            item.setId(IdUtil.getSnowflakeNextId());
            item.setFactory(cacheValue.get(item.getFactory()));
            item.setCreateBy(SecurityUtils.getUsername());
            item.setCreateTime(DateUtils.getNowDate());
        });
                String materialCode = row.getCell(0).getStringCellValue();
                if (StringUtils.isEmpty(materialCode)) {
                    continue;
                }
                String factory = row.getCell(1).getStringCellValue();
                double quantity = row.getCell(2).getNumericCellValue();
                Date date = row.getCell(3).getDateCellValue();
                if (StringUtils.isNotBlank(factory) &&
                    date != null) {
                    ApsGasPipelinePrediction item = new ApsGasPipelinePrediction();
                    item.setId(IdUtil.getSnowflakeNextId());
                    item.setFactory(factory);
                    item.setMaterialCode(materialCode);
                    item.setCreateBy(SecurityUtils.getUsername());
                    item.setCreateTime(DateUtils.getNowDate());
                    item.setPredictQuantity(new BigDecimal(quantity));
                    item.setPredictDate(new Timestamp(date.getTime()));
                    if (!keys.contains(item.getKey())) {
                        keys.add(item.getKey());
                        list.add(item);
        for (int i = list.size() - 1; i >= 0; --i) {
            list.get(i).setKey(null);
            if (!keys.contains(list.get(i).getKey())) {
                keys.add(list.get(i).getKey());
            } else {
                list.remove(i);
            }
        }
        if (!list.isEmpty()) {
            List<Map<String, Object>> facCodeKey = apsGasPipelinePredictionMapper.selectByFacOrMaterial(keys);
            if (!facCodeKey.isEmpty()) {
                Iterator<ApsGasPipelinePrediction> it = list.iterator();
                while (it.hasNext()) {
                    ApsGasPipelinePrediction item = it.next();
                    int count = 0;
                    for (Map<String, Object> map : facCodeKey) {
                        if (map.get("key").equals(item.getKey())) {
                            item.setId((Long) map.get("id"));
                            item.setCreateBy(null);
                            item.setCreateTime(null);
                            item.setUpdateBy(SecurityUtils.getUsername());
                            item.setUpdateTime(new Timestamp(System.currentTimeMillis()));
                            apsGasPipelinePredictionMapper.updateById(item);
                            count++;
                        }
                    }
                    if (count > 0) {
                        it.remove();
                    }
                }
            }
            if (!list.isEmpty()) {
                List<Map<String, Object>> facCodeKey = apsGasPipelinePredictionMapper.selectByFacOrMaterial(keys);
                if (!facCodeKey.isEmpty()) {
                    Iterator<ApsGasPipelinePrediction> it = list.iterator();
                    while (it.hasNext()) {
                        ApsGasPipelinePrediction item = it.next();
                        long count = facCodeKey.stream()
                                .filter(map -> map.get("key").equals(item.getKey()))
                                .peek(row -> {
                                    item.setId((Long) row.get("id"));
                                    item.setCreateBy(null);
                                    item.setCreateTime(null);
                                    item.setUpdateBy(SecurityUtils.getUsername());
                                    item.setUpdateTime(new Timestamp(System.currentTimeMillis()));
                                    apsGasPipelinePredictionMapper.updateById(item);
                                }).count();
                        if (count > 0){
                            it.remove();
                        }
                    }
                }
                if (!list.isEmpty()) {
                    apsGasPipelinePredictionMapper.insert(list);
                }
                apsGasPipelinePredictionMapper.insert(list);
            }
            return list.size();
        }
        return 0;
        return list.size();
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipingRouteStatServiceImpl.java
@@ -6,12 +6,12 @@
import com.aps.common.core.utils.uuid.IdUtils;
import com.aps.common.security.utils.SecurityUtils;
import com.aps.core.domain.*;
import com.aps.core.mapper.ApsGasPipelineCapacityPlanMapper;
import com.aps.core.mapper.ApsGasPipingPlanMapper;
import com.aps.core.mapper.ApsGasPipingRouteStatMapper;
import com.aps.core.domain.ApsPlate.ApsPlateStandardRequireError;
import com.aps.core.mapper.*;
import com.aps.core.service.IApsGasMaterialUsageService;
import com.aps.core.service.IApsGasPipingRouteStatService;
import com.aps.core.service.IApsStandardProcessService;
import com.aps.core.mapper.ApsPlateStandardRequireErrorMapper;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
@@ -60,6 +60,9 @@
    @Autowired
    private IApsStandardProcessService apsStandardProcessService;
    @Autowired
    private ApsPlateStandardRequireErrorMapper apsPlateStandardRequireErrorMapper;
    /**
     * æŸ¥è¯¢æ°”体管路产能负载统计
@@ -1009,4 +1012,1036 @@
        log.info("批量插入数据完成,batchNum:"+batchNum);
    }
    /**
     * æ ¹æ®æ‰‹å·¥æ°”体预测数据和手工气体工单数据生成统计数据
     *
     * @return ç»“æžœ
     */
    @Override
    @Transactional
    public int generateGasPipingRouteStatData() {
        int count = 0;
        // æ¸…空之前的数据
        apsGasPipingRouteStatMapper.deleteAll();
        // ç”Ÿæˆæ‰¹æ¬¡å·
        String batchNumber = IdUtils.fastSimpleUUID();
        List<ApsGasPipingRouteStat> statList = new ArrayList<>();
        // å¤„理手工气体预测数据 - ä½¿ç”¨è”合查询获取所有相关数据
        List<Map<String, Object>> predictionDataList = apsGasPipingRouteStatMapper.selectPredictionRouteData();
        // æŒ‰ç‰©æ–™ä»£ç åˆ†ç»„,便于处理同一物料的不同工序
        Map<String, List<Map<String, Object>>> predictionGroups = predictionDataList.stream()
                .collect(Collectors.groupingBy(data -> data.get("material_code").toString()));
        // å¤„理每个物料的工艺路线
        for (String materialCode : predictionGroups.keySet()) {
            List<Map<String, Object>> materialData = predictionGroups.get(materialCode);
            // æŒ‰å·¥åºå·æŽ’序
            materialData.sort((a, b) -> {
                String numA = a.get("process_number").toString();
                String numB = b.get("process_number").toString();
                return numA.compareTo(numB);
            });
            // èŽ·å–æ‰€æœ‰å·¥åºçš„ä¿¡æ¯å¹¶åˆ›å»ºç»Ÿè®¡è®°å½•
            List<ApsGasPipingRouteStat> processList = new ArrayList<>();
            for (Map<String, Object> data : materialData) {
                ApsGasPipingRouteStat stat = new ApsGasPipingRouteStat();
                stat.setId(IdUtils.fastSimpleUUID());
                stat.setWorkOrderNo(""); // é¢„测数据没有工单号
                stat.setItemNumber(data.get("material_code").toString());
                stat.setProcessName(data.get("process_name").toString());
                stat.setRoadProcessNumber(new BigDecimal(data.get("process_number").toString()));
                // ç”Ÿäº§æ•°é‡å’Œæ ‡å‡†å·¥æ—¶
                BigDecimal quantity = new BigDecimal(data.get("predict_quantity").toString()).setScale(4, RoundingMode.HALF_UP);
                BigDecimal standardTime = new BigDecimal(data.get("standard_time").toString()).setScale(4, RoundingMode.HALF_UP);
                stat.setProductionQuantity(quantity);
                stat.setStandardTime(standardTime);
                stat.setProcessTotalTime(standardTime.multiply(quantity).setScale(4, RoundingMode.HALF_UP));
                // å·¥åŽ‚ã€ä¸“ä¸šå’Œè½¦é—´
                stat.setPlant(data.get("factory").toString());
                stat.setMajor(data.get("domain") != null ? data.get("domain").toString() : "");
                stat.setWorkshop(data.get("workshop") != null ? data.get("workshop").toString() : "");
                // æ‰¹æ¬¡å·å’Œåˆ›å»ºä¿¡æ¯
                stat.setBatchNumber(batchNumber);
                stat.setCreateBy(SecurityUtils.getUsername());
                stat.setCreateTime(truncateToSeconds(DateUtils.getNowDate()));
                processList.add(stat);
            }
            // è®¡ç®—计划完工日和计划开工日
            if (!processList.isEmpty()) {
                int lastIndex = processList.size() - 1;
                // æœ€åŽä¸€é“工序的计划完工日期为预测日期
                ApsGasPipingRouteStat lastProcess = processList.get(lastIndex);
                Date predictDate = (Date) materialData.get(lastIndex).get("predict_date");
                lastProcess.setProcessPlanEndDay(truncateToSeconds(predictDate));
                // æ ‡è®°æ˜¯å¦å‡ºçŽ°è¿‡æ—¶é—´å†²çªçš„æƒ…å†µ
                boolean hasTimeConflict = false;
                // è®¡ç®—每个工序的计划开工日和完工日 - ä»Žæœ€åŽä¸€é“工序开始倒推
                for (int i = lastIndex; i >= 0; i--) {
                    ApsGasPipingRouteStat current = processList.get(i);
                    // å¦‚果当前是最后一道工序,计划开工日 = è®¡åˆ’完工日 - å·¥åºæ€»å·¥æ—¶
                    if (i == lastIndex) {
                        hasTimeConflict = calculateProcessPlanStartDay(current, hasTimeConflict);
                    } else {
                        // éžæœ€åŽä¸€é“工序,计划完工日为下一道工序的计划开工日
                        ApsGasPipingRouteStat next = processList.get(i + 1);
                        current.setProcessPlanEndDay(next.getProcessPlanStartDay());
                        // å¦‚果已经出现时间冲突,后续工序的计划开工日和计划完工日都设为当前时间
                        if (hasTimeConflict) {
                            current.setProcessPlanStartDay(truncateToSeconds(new Date()));
                        } else {
                            // å¦åˆ™æ­£å¸¸è®¡ç®—,并检查是否出现时间冲突
                            hasTimeConflict = calculateProcessPlanStartDay(current, hasTimeConflict);
                        }
                    }
                    // è®¾ç½®å¹´ã€æœˆã€æ—¥
                    setDateComponents(current);
                }
                statList.addAll(processList);
            }
        }
        // å¤„理手工气体工单数据 - ä½¿ç”¨è”合查询获取所有相关数据
        List<Map<String, Object>> moDataList = apsGasPipingRouteStatMapper.selectMoRouteData();
        // èŽ·å–æ‰€æœ‰çš„MO数据,用于检查哪些MO没有关联到工艺路线
        List<Map<String, Object>> allMoData = apsGasPipingRouteStatMapper.selectAllMoData();
        // è®°å½•已关联工艺路线的MO编号
        Set<String> processedMoSet = new HashSet<>();
        // æŒ‰å·¥å•号分组,便于处理同一工单的不同工序
        Map<String, List<Map<String, Object>>> moGroups = moDataList.stream()
                .collect(Collectors.groupingBy(data -> data.get("work_order_no").toString()));
        // å¤„理每个工单的工艺路线
        for (String workOrderNo : moGroups.keySet()) {
            List<Map<String, Object>> workOrderData = moGroups.get(workOrderNo);
            // æ ‡è®°è¯¥å·¥å•已处理
            processedMoSet.add(workOrderNo);
            // æŒ‰å·¥åºå·æŽ’序
            workOrderData.sort((a, b) -> {
                String numA = a.get("process_number").toString();
                String numB = b.get("process_number").toString();
                return numA.compareTo(numB);
            });
            // èŽ·å–æ‰€æœ‰å·¥åºçš„ä¿¡æ¯å¹¶åˆ›å»ºç»Ÿè®¡è®°å½•
            List<ApsGasPipingRouteStat> processList = new ArrayList<>();
            for (Map<String, Object> data : workOrderData) {
                ApsGasPipingRouteStat stat = new ApsGasPipingRouteStat();
                stat.setId(IdUtils.fastSimpleUUID());
                stat.setWorkOrderNo(data.get("work_order_no").toString());
                stat.setItemNumber(data.get("material_code").toString());
                stat.setProcessName(data.get("process_name").toString());
                stat.setRoadProcessNumber(new BigDecimal(data.get("process_number").toString()));
                // ç”Ÿäº§æ•°é‡å’Œæ ‡å‡†å·¥æ—¶
                BigDecimal quantity = new BigDecimal(data.get("quantity").toString()).setScale(4, RoundingMode.HALF_UP);
                BigDecimal standardTime = new BigDecimal(data.get("standard_time").toString()).setScale(4, RoundingMode.HALF_UP);
                stat.setProductionQuantity(quantity);
                stat.setStandardTime(standardTime);
                stat.setProcessTotalTime(standardTime.multiply(quantity).setScale(4, RoundingMode.HALF_UP));
                // å·¥åŽ‚ã€ä¸“ä¸šå’Œè½¦é—´
                stat.setPlant(data.get("factory").toString());
                stat.setMajor(data.get("domain") != null ? data.get("domain").toString() : "");
                stat.setWorkshop(data.get("workshop") != null ? data.get("workshop").toString() : "");
                // æ‰¹æ¬¡å·å’Œåˆ›å»ºä¿¡æ¯
                stat.setBatchNumber(batchNumber);
                stat.setCreateBy(SecurityUtils.getUsername());
                stat.setCreateTime(truncateToSeconds(DateUtils.getNowDate()));
                processList.add(stat);
            }
            // è®¡ç®—计划完工日和计划开工日
            if (!processList.isEmpty()) {
                int lastIndex = processList.size() - 1;
                // æœ€åŽä¸€é“工序的计划完工日期为工单计划完工日期
                ApsGasPipingRouteStat lastProcess = processList.get(lastIndex);
                Date planEnd = (Date) workOrderData.get(0).get("plan_end");
                lastProcess.setProcessPlanEndDay(truncateToSeconds(planEnd));
                // æ ‡è®°æ˜¯å¦å‡ºçŽ°è¿‡æ—¶é—´å†²çªçš„æƒ…å†µ
                boolean hasTimeConflict = false;
                // è®¡ç®—每个工序的计划开工日和完工日 - ä»Žæœ€åŽä¸€é“工序开始倒推
                for (int i = lastIndex; i >= 0; i--) {
                    ApsGasPipingRouteStat current = processList.get(i);
                    // å¦‚果当前是最后一道工序,计划开工日 = è®¡åˆ’完工日 - å·¥åºæ€»å·¥æ—¶
                    if (i == lastIndex) {
                        hasTimeConflict = calculateProcessPlanStartDay(current, hasTimeConflict);
                    } else {
                        // éžæœ€åŽä¸€é“工序,计划完工日为下一道工序的计划开工日
                        ApsGasPipingRouteStat next = processList.get(i + 1);
                        current.setProcessPlanEndDay(next.getProcessPlanStartDay());
                        // å¦‚果已经出现时间冲突,后续工序的计划开工日和计划完工日都设为当前时间
                        if (hasTimeConflict) {
                            current.setProcessPlanStartDay(truncateToSeconds(new Date()));
                        } else {
                            // å¦åˆ™æ­£å¸¸è®¡ç®—,并检查是否出现时间冲突
                            hasTimeConflict = calculateProcessPlanStartDay(current, hasTimeConflict);
                        }
                    }
                    // è®¾ç½®å¹´ã€æœˆã€æ—¥
                    setDateComponents(current);
                }
                statList.addAll(processList);
            }
        }
        // å¤„理没有关联到工艺路线的MO数据
        List<ApsPlateStandardRequireError> errorList = new ArrayList<>();
        for (Map<String, Object> moData : allMoData) {
            String workOrderNo = moData.get("mo").toString();
            // å¦‚果该工单没有被处理过,说明没有关联到工艺路线
            if (!processedMoSet.contains(workOrderNo)) {
                ApsPlateStandardRequireError error = ApsPlateStandardRequireError.builder()
                        .id(Long.valueOf(IdUtils.fastSimpleUUID().hashCode()))
                        .batchNumber(batchNumber)
                        .requireId(IdUtil.getSnowflakeNextId())
                        .docNum(workOrderNo)
                        .itemNum(moData.get("material_code").toString())
                        .orgCode(moData.get("factory").toString())
                        .message("标准工艺路线不存在")
                        .delFlag("0")
                        .build();
                // è®¾ç½®åŸºç±»å±žæ€§
                error.setCreateBy(SecurityUtils.getUsername());
                error.setCreateTime(truncateToSeconds(DateUtils.getNowDate()));
                errorList.add(error);
            }
        }
        // æ‰¹é‡æ’入异常数据
        if (!errorList.isEmpty()) {
            apsPlateStandardRequireErrorMapper.batchInsert(errorList);
        }
        // æ‰¹é‡æ’入数据
        if (!statList.isEmpty()) {
            for (int i = 0; i < statList.size(); i += 500) {
                int endIndex = Math.min(i + 500, statList.size());
                List<ApsGasPipingRouteStat> batch = statList.subList(i, endIndex);
                count += apsGasPipingRouteStatMapper.insertApsGasPipingRouteStatBatch(batch);
            }
        }
        return count;
    }
    /**
     * è®¡ç®—工序计划开工日,并判断是否发生时间冲突
     *
     * @param stat å½“前工序统计对象
     * @param hasTimeConflict ä¹‹å‰æ˜¯å¦å·²ç»å‘生时间冲突
     * @return æ˜¯å¦å‘生时间冲突
     */
    private boolean calculateProcessPlanStartDay(ApsGasPipingRouteStat stat, boolean hasTimeConflict) {
        Date planEndDay = stat.getProcessPlanEndDay();
        if (planEndDay == null) {
            return hasTimeConflict;
        }
        // è®¡ç®—工序总工时对应的秒数
        long processTotalTimeSeconds = stat.getProcessTotalTime()
                .multiply(BigDecimal.valueOf(60 * 60))
                .longValue();
        // èŽ·å–å½“å‰æ—¶é—´å¹¶ç²¾ç¡®åˆ°ç§’çº§åˆ«
        Date now = truncateToSeconds(new Date());
        // è®¡ç®—开工日期并精确到秒级别
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(planEndDay);
        // åˆ†æ‰¹å‡åŽ»ç§’æ•°ï¼Œé¿å…int溢出
        long seconds = processTotalTimeSeconds;
        while (seconds > 0) {
            int step = (seconds > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) seconds;
            calendar.add(Calendar.SECOND, -step);
            seconds -= step;
        }
        Date calculatedStartDay = truncateToSeconds(calendar.getTime());
        // å¦‚果计划完工日期小于等于当前时间,则计划开工日也设为计划完工日(当前时间)
        if (planEndDay.compareTo(now) <= 0) {
            stat.setProcessPlanStartDay(truncateToSeconds(planEndDay));
            return true; // å‘生时间冲突
        }
        // å¦‚果计算出的计划开工日小于等于当前时间,则设为当前时间
        else if (calculatedStartDay.compareTo(now) <= 0) {
            stat.setProcessPlanStartDay(now);
            return true; // é¦–次出现时间冲突
        }
        // å¦åˆ™æ­£å¸¸è®¾ç½®è®¡åˆ’开工日
        else {
            stat.setProcessPlanStartDay(calculatedStartDay);
            return hasTimeConflict; // ä¿æŒåŽŸæœ‰å†²çªçŠ¶æ€
        }
    }
    /**
     * å°†æ—¥æœŸç²¾ç¡®åˆ°ç§’级别,去除毫秒信息
     *
     * @param date åŽŸå§‹æ—¥æœŸ
     * @return ç²¾ç¡®åˆ°ç§’的日期
     */
    private Date truncateToSeconds(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }
    /**
     * è®¾ç½®æ—¥æœŸç›¸å…³ç»„件(年、月、日)
     */
    private void setDateComponents(ApsGasPipingRouteStat stat) {
        if (stat.getProcessPlanStartDay() != null) {
            SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy");
            SimpleDateFormat monthFormat = new SimpleDateFormat("MM");
            SimpleDateFormat dayFormat = new SimpleDateFormat("dd");
            stat.setPlanStartYear(yearFormat.format(stat.getProcessPlanStartDay()));
            stat.setPlanStartMonth(monthFormat.format(stat.getProcessPlanStartDay()));
            stat.setPlanStartDay(dayFormat.format(stat.getProcessPlanStartDay()));
        }
    }
    /**
     * èšåˆæ°”体管路产能负载统计数据
     * åœ¨Service层完成聚合处理,支持多维度分组
     *
     * @param params èšåˆå‚æ•°
     * @return èšåˆç»“æžœ
     */
    @Override
    public Map<String, Object> aggregateGasPipingRouteStat(Map<String, Object> params) {
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> plantTable = new ArrayList<>();
        // èŽ·å–æ—¶é—´é¢—ç²’åº¦å‚æ•°
        String timeGranularity = params.containsKey("timeGranularity") ?
                (String) params.get("timeGranularity") : "day"; // é»˜è®¤ä¸º"日"粒度
        // èŽ·å–row维度的聚合字段 - é»˜è®¤ä¸ºå·¥åºåç§°(processName)
        String rowGroupBy = params.containsKey("rowGroupBy") ?
                (String) params.get("rowGroupBy") : "processName";
        // ç¡®å®šåˆ†ç»„维度 - å·¥åŽ‚ã€ä¸“ä¸šã€è½¦é—´
        boolean groupByPlant = params.containsKey("groupByPlant") && Boolean.TRUE.equals(params.get("groupByPlant"));
        boolean groupByMajor = params.containsKey("groupByMajor") && Boolean.TRUE.equals(params.get("groupByMajor"));
        boolean groupByWorkshop = params.containsKey("groupByWorkshop") && Boolean.TRUE.equals(params.get("groupByWorkshop"));
        // å¦‚æžœrowGroupBy已经是某个维度,则该维度不需要再次分组
        if ("plant".equals(rowGroupBy)) groupByPlant = false;
        if ("major".equals(rowGroupBy)) groupByMajor = false;
        if ("workshop".equals(rowGroupBy)) groupByWorkshop = false;
        // æž„建查询条件
        Map<String, Object> queryParams = new HashMap<>();
        // è®¾ç½®æŸ¥è¯¢æ¡ä»¶ - åˆ†ç±»æ¡ä»¶
        if (params.containsKey("plant")) {
            Object plantParam = params.get("plant");
            if (plantParam instanceof List) {
                queryParams.put("plants", plantParam);
            } else if (plantParam instanceof String) {
                // å¤„理可能的逗号分隔字符串
                String plantStr = (String) plantParam;
                if (plantStr.contains(",")) {
                    List<String> plantList = Arrays.asList(plantStr.split(","));
                    queryParams.put("plants", plantList);
                } else {
                    queryParams.put("plant", plantStr);
                }
            }
        }
        if (params.containsKey("major")) {
            Object majorParam = params.get("major");
            if (majorParam instanceof List) {
                queryParams.put("majors", majorParam);
            } else if (majorParam instanceof String) {
                // å¤„理可能的逗号分隔字符串
                String majorStr = (String) majorParam;
                if (majorStr.contains(",")) {
                    List<String> majorList = Arrays.asList(majorStr.split(","));
                    queryParams.put("majors", majorList);
                } else {
                    queryParams.put("major", majorStr);
                }
            }
        }
        if (params.containsKey("workshop")) {
            Object workshopParam = params.get("workshop");
            if (workshopParam instanceof List) {
                queryParams.put("workshops", workshopParam);
            } else if (workshopParam instanceof String) {
                // å¤„理可能的逗号分隔字符串
                String workshopStr = (String) workshopParam;
                if (workshopStr.contains(",")) {
                    List<String> workshopList = Arrays.asList(workshopStr.split(","));
                    queryParams.put("workshops", workshopList);
                } else {
                    queryParams.put("workshop", workshopStr);
                }
            }
        }
        // ç¡®å®šæ—¶é—´èŒƒå›´
        List<String> timePoints = new ArrayList<>();
        if ("day".equalsIgnoreCase(timeGranularity)) {
            // "日"粒度:传入一个月份,聚合该月每一天的数据
            if (!params.containsKey("yearMonth")) {
                result.put("plantTable", plantTable);
                result.put("message", "日粒度聚合需要指定yearMonth参数");
                return result;
            }
            String yearMonth = (String) params.get("yearMonth");
            // ç”ŸæˆæŒ‡å®šæœˆä»½ä¸­çš„æ¯ä¸€å¤©
            YearMonth ym = YearMonth.parse(yearMonth);
            int daysInMonth = ym.lengthOfMonth();
            for (int day = 1; day <= daysInMonth; day++) {
                String dayStr = String.format("%02d", day);
                timePoints.add(yearMonth + "-" + dayStr);
            }
            // è®¾ç½®æŸ¥è¯¢å‚æ•°
            String[] ymParts = yearMonth.split("-");
            queryParams.put("yearStart", ymParts[0]);
            queryParams.put("monthStart", ymParts[1]);
            queryParams.put("yearEnd", ymParts[0]);
            queryParams.put("monthEnd", ymParts[1]);
        } else if ("month".equalsIgnoreCase(timeGranularity)) {
            // "月"粒度:传入一个时间区间,聚合该区间内每个月的数据
            if (!params.containsKey("startDate") || !params.containsKey("endDate")) {
                result.put("plantTable", plantTable);
                result.put("message", "月粒度聚合需要指定startDate和endDate参数");
                return result;
            }
            String startDate = (String) params.get("startDate");
            String endDate = (String) params.get("endDate");
            // è§£æžå¼€å§‹å’Œç»“束年月
            YearMonth start = YearMonth.parse(startDate);
            YearMonth end = YearMonth.parse(endDate);
            // ç”ŸæˆåŒºé—´å†…的每个月
            timePoints = getYearMonthsInRange(start, end);
            // è®¾ç½®æŸ¥è¯¢å‚æ•°
            String[] startParts = startDate.split("-");
            String[] endParts = endDate.split("-");
            queryParams.put("yearStart", startParts[0]);
            queryParams.put("monthStart", startParts[1]);
            queryParams.put("yearEnd", endParts[0]);
            queryParams.put("monthEnd", endParts[1]);
        }
        if (timePoints.isEmpty()) {
            result.put("plantTable", plantTable);
            result.put("message", "未能生成有效的时间点列表");
            return result;
        }
        // æŸ¥è¯¢åŽŸå§‹æ•°æ®ï¼ˆä¸ä¾èµ–æ•°æ®åº“èšåˆï¼‰
        List<Map<String, Object>> rawData = apsGasPipingRouteStatMapper.selectRawStatData(queryParams);
        // å¦‚果没有查询到原始数据,但需要返回所有工序/车间的数据
        if (rawData.isEmpty()) {
            // åˆ›å»ºæ²¡æœ‰æ—¶é—´é™åˆ¶çš„基础查询参数
            Map<String, Object> baseParams = new HashMap<>(queryParams);
            baseParams.remove("yearStart");
            baseParams.remove("monthStart");
            baseParams.remove("yearEnd");
            baseParams.remove("monthEnd");
            // ç›´æŽ¥ä»Žaps_gas_piping_route_stat表查询所有可能的工序和车间
            List<Map<String, Object>> baseData = apsGasPipingRouteStatMapper.selectBaseStatData(baseParams);
            // ä¸ºæ¯ä¸ªå·¥åº/车间创建基于时间的空数据
            for (Map<String, Object> data : baseData) {
                String rowGroupValue = getStringValue(data, rowGroupBy);
                if (rowGroupValue == null || rowGroupValue.trim().isEmpty()) continue;
                Map<String, Object> rowEntry = new HashMap<>();
                Map<String, Object> rowDetail = new HashMap<>();
                // æ·»åŠ åŸºæœ¬ä¿¡æ¯
                String plant = getStringValue(data, "plant");
                String major = getStringValue(data, "major");
                String workshop = getStringValue(data, "workshop");
                if (groupByPlant) rowDetail.put("plant", plant);
                if (groupByMajor) rowDetail.put("major", major);
                if (groupByWorkshop) rowDetail.put("workshop", workshop);
                // å¤„理工序名称 - å¦‚æžœrowGroupBy为workshop,需要添加processName字段
                if ("workshop".equals(rowGroupBy)) {
                    String processName = getStringValue(data, "processName");
                    rowDetail.put("processName", processName != null ? processName : "");
                }
                // ä¸ºæ¯ä¸ªæ—¶é—´ç‚¹åˆ›å»ºé›¶å€¼æ•°æ®
                List<Map<String, Object>> timeDataList = new ArrayList<>();
                for (String timePoint : timePoints) {
                    Map<String, Object> pointData = new HashMap<>();
                    pointData.put("planDay", timePoint);
                    pointData.put("requireTimes", BigDecimal.ZERO);
                    pointData.put("designTimes", BigDecimal.ZERO);
                    pointData.put("capacityLoad", BigDecimal.ZERO);
                    timeDataList.add(pointData);
                }
                rowDetail.put("timeData", timeDataList);
                rowEntry.put(rowGroupValue, rowDetail);
                plantTable.add(rowEntry);
            }
            // æ›´æ–°ç»“果但不直接返回,继续执行后续注意点4的处理
            result.put("plantTable", plantTable);
            result.put("timePoints", timePoints);
            result.put("rowGroupBy", rowGroupBy);
        } else {
            // åœ¨Service层完成聚合
            // ä½¿ç”¨ç»„合key来实现多维度分组(动态rowGroupBy字段 + å¯é€‰çš„工厂/专业/车间)
            Map<String, Map<String, Object>> groupInfoMap = new HashMap<>();
            Map<String, Map<String, BigDecimal>> groupTimeDataMap = new HashMap<>();
            // å­˜å‚¨æ¯ä¸ªgroupKey对应的processName集合
            Map<String, Set<String>> groupProcessNamesMap = new HashMap<>();
            // éåŽ†åŽŸå§‹æ•°æ®ï¼ŒæŒ‰å¤šç»´åº¦åˆ†ç»„è¿›è¡Œèšåˆ
            for (Map<String, Object> data : rawData) {
                // èŽ·å–è¡Œåˆ†ç»„å­—æ®µå€¼
                String rowGroupValue = getStringValue(data, rowGroupBy);
                if (rowGroupValue == null || rowGroupValue.trim().isEmpty()) {
                    log.warn("跳过处理:{} å­—段值为空", rowGroupBy);
                    continue;
                }
                // èŽ·å–å·¥åºåç§°ï¼ˆç”¨äºŽæ—¥å¿—å’ŒåŽç»­å¤„ç†ï¼‰
                String processName = getStringValue(data, "processName");
                // å¤„理开工日期
                Date processPlanStartDay = (Date) data.get("processPlanStartDay");
                if (processPlanStartDay == null) {
                    log.warn("跳过处理:计划开工日为null, {}={}", rowGroupBy, rowGroupValue);
                    continue;
                }
                // æž„建分组键 - åŸºäºŽrow分组字段和可选的其他维度
                String plant = getStringValue(data, "plant");
                String major = getStringValue(data, "major");
                String workshop = getStringValue(data, "workshop");
                StringBuilder groupKeyBuilder = new StringBuilder(rowGroupValue);
                // æ ¹æ®ç”¨æˆ·é€‰æ‹©çš„分组维度添加到分组键
                if (groupByPlant && plant != null) {
                    groupKeyBuilder.append("_PLANT_").append(plant);
                }
                if (groupByMajor && major != null) {
                    groupKeyBuilder.append("_MAJOR_").append(major);
                }
                if (groupByWorkshop && workshop != null) {
                    groupKeyBuilder.append("_WORKSHOP_").append(workshop);
                }
                String groupKey = groupKeyBuilder.toString();
                // è®°å½•分组的基本信息(只记录一次)
                if (!groupInfoMap.containsKey(groupKey)) {
                    Map<String, Object> groupInfo = new HashMap<>();
                    groupInfo.put(rowGroupBy, rowGroupValue);
                    groupInfo.put("plant", plant);
                    groupInfo.put("major", major);
                    groupInfo.put("workshop", workshop);
                    groupInfo.put("processName", processName);
                    groupInfoMap.put(groupKey, groupInfo);
                }
                // æ”¶é›†processName
                if (processName != null && !processName.trim().isEmpty()) {
                    if (!groupProcessNamesMap.containsKey(groupKey)) {
                        groupProcessNamesMap.put(groupKey, new HashSet<>());
                    }
                    groupProcessNamesMap.get(groupKey).add(processName);
                }
                // è®¡ç®—时间点Key
                String timeKey;
                LocalDate planStartLocalDate = processPlanStartDay.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                if ("day".equalsIgnoreCase(timeGranularity)) {
                    // æ—¥ç²’度: 2025-05-25
                    timeKey = planStartLocalDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
                } else {
                    // æœˆç²’度: 2025-05
                    timeKey = planStartLocalDate.getYear() + "-" + String.format("%02d", planStartLocalDate.getMonthValue());
                }
                // èŽ·å–è¯¥åˆ†ç»„çš„æ—¶é—´ç‚¹æ˜ å°„ï¼Œå¦‚æžœä¸å­˜åœ¨åˆ™åˆ›å»º
                if (!groupTimeDataMap.containsKey(groupKey)) {
                    groupTimeDataMap.put(groupKey, new HashMap<>());
                }
                Map<String, BigDecimal> timeMap = groupTimeDataMap.get(groupKey);
                // ç´¯åŠ è¯¥åˆ†ç»„åœ¨è¯¥æ—¶é—´ç‚¹çš„å·¥æ—¶æ•°æ®
                BigDecimal processTotalTime = getBigDecimalValue(data, "processTotalTime");
                if (processTotalTime != null) {
                    BigDecimal currentTotal = timeMap.getOrDefault(timeKey, BigDecimal.ZERO);
                    timeMap.put(timeKey, currentTotal.add(processTotalTime));
                }
            }
            // æž„建最终返回的数据结构
            for (String groupKey : groupInfoMap.keySet()) {
                Map<String, Object> rowEntry = new HashMap<>();
                Map<String, Object> rowDetail = new HashMap<>();
                // èŽ·å–è¯¥åˆ†ç»„çš„åŸºæœ¬ä¿¡æ¯
                Map<String, Object> groupInfo = groupInfoMap.get(groupKey);
                String rowGroupValue = (String) groupInfo.get(rowGroupBy);
                // æ·»åŠ åˆ†ç»„åŸºæœ¬ä¿¡æ¯
                if (groupByPlant) {
                    rowDetail.put("plant", groupInfo.get("plant"));
                }
                if (groupByMajor) {
                    rowDetail.put("major", groupInfo.get("major"));
                }
                if (groupByWorkshop) {
                    rowDetail.put("workshop", groupInfo.get("workshop"));
                }
                // å¤„理processName - å¦‚æžœrowGroupBy为workshop,则将所有processName用分号连接
                if ("workshop".equals(rowGroupBy)) {
                    Set<String> processNames = groupProcessNamesMap.getOrDefault(groupKey, new HashSet<>());
                    if (!processNames.isEmpty()) {
                        String joinedProcessNames = String.join(";", processNames);
                        rowDetail.put("processName", joinedProcessNames);
                    } else {
                        rowDetail.put("processName", groupInfo.get("processName"));
                    }
                } else if (!"processName".equals(rowGroupBy)) {
                    // ä¿ç•™å·¥åºåç§°ä¿¡æ¯ï¼Œä»¥ä¾¿å‰ç«¯å±•示
                    rowDetail.put("processName", groupInfo.get("processName"));
                }
                // æ·»åŠ æ—¶é—´æ•°æ®
                List<Map<String, Object>> timeDataList = new ArrayList<>();
                Map<String, BigDecimal> timeMap = groupTimeDataMap.getOrDefault(groupKey, new HashMap<>());
                for (String timePoint : timePoints) {
                    Map<String, Object> pointData = new HashMap<>();
                    pointData.put("planDay", timePoint);
                    // èŽ·å–è¯¥æ—¶é—´ç‚¹çš„éœ€æ±‚å·¥æ—¶ï¼Œå¦‚æžœä¸å­˜åœ¨åˆ™è®¾ä¸º0
                    BigDecimal requireTimes = timeMap.getOrDefault(timePoint, BigDecimal.ZERO);
                    pointData.put("requireTimes", requireTimes);
                    // è®¾è®¡å·¥æ—¶å’Œäº§èƒ½è´Ÿè·ç¨åŽè®¡ç®—
                    pointData.put("designTimes", 0);
                    pointData.put("capacityLoad", 0);
                    timeDataList.add(pointData);
                }
                rowDetail.put("timeData", timeDataList);
                rowEntry.put(rowGroupValue, rowDetail);
                plantTable.add(rowEntry);
            }
        }
        // åœ¨è¿”回前查询设计产能数据并计算产能负荷
        for (Map<String, Object> rowEntry : plantTable) {
            for (String rowKey : rowEntry.keySet()) {
                Map<String, Object> rowDetail = (Map<String, Object>) rowEntry.get(rowKey);
                List<Map<String, Object>> timeDataList = (List<Map<String, Object>>) rowDetail.get("timeData");
                // èŽ·å–åŸºæœ¬ä¿¡æ¯
                String plant = rowDetail.containsKey("plant") ? (String) rowDetail.get("plant") : null;
                String major = rowDetail.containsKey("major") ? (String) rowDetail.get("major") : null;
                String workshop = rowDetail.containsKey("workshop") ? (String) rowDetail.get("workshop") : null;
                // å¤„理不同的rowGroupBy情况
                if ("workshop".equals(rowGroupBy) && rowDetail.containsKey("processName")) {
                    // æƒ…况1: æŒ‰workshop聚合,需要拆分processName字段
                    String processNamesStr = (String) rowDetail.get("processName");
                    String[] processNames = processNamesStr.split(";");
                    // ä¼˜åŒ–查询 - åˆ›å»ºç¼“存,按月份缓存查询结果
                    // Key: year-month-processName, Value: æŸ¥è¯¢ç»“果列表
                    Map<String, List<ApsGasPipelineCapacityPlan>> capacityPlanCache = new HashMap<>();
                    // éåŽ†æ¯ä¸ªæ—¶é—´ç‚¹
                    for (Map<String, Object> timeData : timeDataList) {
                        String planDay = (String) timeData.get("planDay");
                        BigDecimal requireTimes = new BigDecimal(timeData.get("requireTimes").toString());
                        BigDecimal totalDesignTimes = BigDecimal.ZERO;
                        // æ‹†åˆ†å¹´æœˆæ—¥
                        String[] dateParts = planDay.split("-");
                        String year = dateParts[0];
                        String month = dateParts[1];
                        // ç»Ÿä¸€month格式为整数字符串,去掉前导零
                        month = String.valueOf(Integer.parseInt(month));
                        String yearMonth = year + "-" + month;
                        // ç´¯åŠ å¤šä¸ªå·¥åºçš„è®¾è®¡äº§èƒ½
                        for (String processName : processNames) {
                            // æž„建缓存键
                            String cacheKey = yearMonth + "-" + processName.trim();
                            // ä»Žç¼“存获取或查询数据
                            List<ApsGasPipelineCapacityPlan> capacityPlans;
                            if (capacityPlanCache.containsKey(cacheKey)) {
                                capacityPlans = capacityPlanCache.get(cacheKey);
                            } else {
                                // ä½¿ç”¨ä¸“用查询方法查询设计产能数据
                                // æŒ‰æ–‡æ¡£è¦æ±‚:根据process_name和plant去aps_gas_pipeline_capacity_plan表中查询
                                capacityPlans = apsGasPipelineCapacityPlanMapper.selectDesignCapacityForInterface2(
                                        processName.trim(), year, month, major, plant);
                                // å°†ç»“果存入缓存
                                capacityPlanCache.put(cacheKey, capacityPlans);
                            }
                            // ç´¯åŠ è®¾è®¡äº§èƒ½å€¼
                            for (ApsGasPipelineCapacityPlan plan : capacityPlans) {
                                if ("day".equalsIgnoreCase(timeGranularity)) {
                                    // æ—¥ç²’度使用日产出数量
                                    if (plan.getDayProduceAllNum() != null) {
                                        totalDesignTimes = totalDesignTimes.add(plan.getDayProduceAllNum());
                                    }
                                } else {
                                    // æœˆç²’度使用月产出总数量
                                    if (plan.getMonthProduceAllNum() != null) {
                                        totalDesignTimes = totalDesignTimes.add(plan.getMonthProduceAllNum());
                                    }
                                }
                            }
                        }
                        // æ›´æ–°è®¾è®¡å·¥æ—¶
                        timeData.put("designTimes", totalDesignTimes);
                        // è®¡ç®—产能负荷 = éœ€æ±‚产能/设计产能×100%
                        if (totalDesignTimes.compareTo(BigDecimal.ZERO) > 0) {
                            BigDecimal capacityLoad = requireTimes
                                    .divide(totalDesignTimes, 2, RoundingMode.HALF_UP)
                                    .multiply(new BigDecimal(100));
                            timeData.put("capacityLoad", capacityLoad);
                        } else {
                            timeData.put("capacityLoad", 0);
                        }
                    }
                } else {
                    // æƒ…况2: æŒ‰processName或其他字段聚合
                    String processName = rowDetail.containsKey("processName") ?
                            (String) rowDetail.get("processName") : rowKey;
                    // ä¼˜åŒ–查询 - åˆ›å»ºç¼“存,按月份缓存查询结果
                    Map<String, List<ApsGasPipelineCapacityPlan>> capacityPlanCache = new HashMap<>();
                    // éåŽ†æ¯ä¸ªæ—¶é—´ç‚¹
                    for (Map<String, Object> timeData : timeDataList) {
                        String planDay = (String) timeData.get("planDay");
                        BigDecimal requireTimes = new BigDecimal(timeData.get("requireTimes").toString());
                        // æ‹†åˆ†å¹´æœˆæ—¥
                        String[] dateParts = planDay.split("-");
                        String year = dateParts[0];
                        String month = dateParts[1];
                        // ç»Ÿä¸€month格式为整数字符串,去掉前导零
                        month = String.valueOf(Integer.parseInt(month));
                        String yearMonth = year + "-" + month;
                        // æž„建缓存键
                        String cacheKey = yearMonth + "-" + processName;
                        // ä»Žç¼“存获取或查询数据
                        List<ApsGasPipelineCapacityPlan> capacityPlans;
                        if (capacityPlanCache.containsKey(cacheKey)) {
                            capacityPlans = capacityPlanCache.get(cacheKey);
                        } else {
                            // ä½¿ç”¨ä¸“用查询方法查询设计产能数据
                            // æŒ‰æ–‡æ¡£è¦æ±‚:根据process_name和plant去aps_gas_pipeline_capacity_plan表中查询
                            capacityPlans = apsGasPipelineCapacityPlanMapper.selectDesignCapacityForInterface2(
                                    processName, year, month, major, plant);
                            // å°†ç»“果存入缓存
                            capacityPlanCache.put(cacheKey, capacityPlans);
                        }
                        // ç´¯åŠ è®¾è®¡äº§èƒ½å€¼
                        BigDecimal totalDesignTimes = BigDecimal.ZERO;
                        for (ApsGasPipelineCapacityPlan plan : capacityPlans) {
                            if ("day".equalsIgnoreCase(timeGranularity)) {
                                // æ—¥ç²’度使用日产出数量
                                if (plan.getDayProduceAllNum() != null) {
                                    totalDesignTimes = totalDesignTimes.add(plan.getDayProduceAllNum());
                                }
                            } else {
                                // æœˆç²’度使用月产出总数量
                                if (plan.getMonthProduceAllNum() != null) {
                                    totalDesignTimes = totalDesignTimes.add(plan.getMonthProduceAllNum());
                                }
                            }
                        }
                        // æ›´æ–°è®¾è®¡å·¥æ—¶
                        timeData.put("designTimes", totalDesignTimes);
                        // è®¡ç®—产能负荷 = éœ€æ±‚产能/设计产能×100%
                        if (totalDesignTimes.compareTo(BigDecimal.ZERO) > 0) {
                            BigDecimal capacityLoad = requireTimes
                                    .divide(totalDesignTimes, 2, RoundingMode.HALF_UP)
                                    .multiply(new BigDecimal(100));
                            timeData.put("capacityLoad", capacityLoad);
                        } else {
                            timeData.put("capacityLoad", 0);
                        }
                    }
                }
            }
        }
        result.put("plantTable", plantTable);
        result.put("timePoints", timePoints);
        result.put("rowGroupBy", rowGroupBy);
        // æ ¹æ®æ–‡æ¡£æ³¨æ„ç‚¹3,添加排序逻辑
        if (!plantTable.isEmpty()) {
            // å¯¹èšåˆç»“果进行排序
            Collections.sort(plantTable, (map1, map2) -> {
                String key1 = map1.keySet().iterator().next();
                String key2 = map2.keySet().iterator().next();
                // é¦–先按rowGroupBy排序(processName或workshop)
                int result1 = key1.compareTo(key2);
                if (result1 != 0) {
                    return result1;
                }
                // å¦‚æžœrowGroupBy相同,再按plant排序
                Map<String, Object> detail1 = (Map<String, Object>) map1.get(key1);
                Map<String, Object> detail2 = (Map<String, Object>) map2.get(key2);
                String plant1 = detail1.containsKey("plant") ? (String) detail1.get("plant") : "";
                String plant2 = detail2.containsKey("plant") ? (String) detail2.get("plant") : "";
                return plant1.compareTo(plant2);
            });
        }
        // å®žçŽ°æ³¨æ„ç‚¹4:当时间颗粒度为"日"时,确保没有数据的工厂也返回完整结构
        if ("day".equalsIgnoreCase(timeGranularity) && params.containsKey("plant")) {
            // èŽ·å–è¯·æ±‚ä¸­çš„å·¥åŽ‚åˆ—è¡¨
            List<String> requestedPlants = new ArrayList<>();
            Object plantParam = params.get("plant");
            if (plantParam instanceof List) {
                requestedPlants.addAll((List<String>) plantParam);
            } else if (plantParam instanceof String) {
                String plantStr = (String) plantParam;
                if (plantStr.contains(",")) {
                    requestedPlants.addAll(Arrays.asList(plantStr.split(",")));
                } else {
                    requestedPlants.add(plantStr);
                }
            }
            if (!requestedPlants.isEmpty()) {
                // æ£€æŸ¥å“ªäº›å·¥åŽ‚æ²¡æœ‰æ•°æ®
                Set<String> plantsWithData = new HashSet<>();
                for (Map<String, Object> rowEntry : plantTable) {
                    for (String rowKey : rowEntry.keySet()) {
                        Map<String, Object> rowDetail = (Map<String, Object>) rowEntry.get(rowKey);
                        if (rowDetail.containsKey("plant")) {
                            plantsWithData.add((String) rowDetail.get("plant"));
                        }
                    }
                }
                // æ‰¾å‡ºæ²¡æœ‰æ•°æ®çš„工厂
                List<String> plantsWithoutData = requestedPlants.stream()
                        .filter(plant -> !plantsWithData.contains(plant))
                        .collect(Collectors.toList());
                if (!plantsWithoutData.isEmpty()) {
                    // èŽ·å–æ‰€æœ‰åŽ»é‡çš„processName或workshop
                    List<String> allUniqueValues;
                    if ("processName".equals(rowGroupBy)) {
                        allUniqueValues = apsGasPipingRouteStatMapper.selectDistinctProcessNames();
                    } else if ("workshop".equals(rowGroupBy)) {
                        allUniqueValues = apsGasPipingRouteStatMapper.selectDistinctWorkshops();
                    } else {
                        // å¦‚æžœrowGroupBy不是processName或workshop,跳过处理
                        return result;
                    }
                    // ä¸ºæ¯ä¸ªæ²¡æœ‰æ•°æ®çš„工厂创建空数据结构
                    for (String plant : plantsWithoutData) {
                        for (String uniqueValue : allUniqueValues) {
                            if (uniqueValue == null || uniqueValue.trim().isEmpty()) {
                                continue;
                            }
                            // æ£€æŸ¥æ˜¯å¦å·²ç»å­˜åœ¨è¿™ä¸ªå€¼
                            boolean exists = false;
                            for (Map<String, Object> entry : plantTable) {
                                if (entry.containsKey(uniqueValue)) {
                                    Map<String, Object> detail = (Map<String, Object>) entry.get(uniqueValue);
                                    String existingPlant = detail.containsKey("plant") ? (String) detail.get("plant") : "";
                                    if (plant.equals(existingPlant)) {
                                        exists = true;
                                        break;
                                    }
                                }
                            }
                            // å¦‚果不存在,创建新的空数据结构
                            if (!exists) {
                                Map<String, Object> rowEntry = new HashMap<>();
                                Map<String, Object> rowDetail = new HashMap<>();
                                // è®¾ç½®åŸºæœ¬ä¿¡æ¯
                                rowDetail.put("plant", plant);
                                if (groupByMajor) {
                                    rowDetail.put("major", "");
                                }
                                if (groupByWorkshop && !"workshop".equals(rowGroupBy)) {
                                    rowDetail.put("workshop", "");
                                }
                                // å¤„理processName - å¦‚æžœrowGroupBy为workshop,需要设置空的processName
                                if ("workshop".equals(rowGroupBy)) {
                                    rowDetail.put("processName", "");
                                }
                                // ä¸ºæ¯ä¸ªæ—¶é—´ç‚¹åˆ›å»ºé›¶å€¼æ•°æ®
                                List<Map<String, Object>> timeDataList = new ArrayList<>();
                                for (String timePoint : timePoints) {
                                    Map<String, Object> pointData = new HashMap<>();
                                    pointData.put("planDay", timePoint);
                                    pointData.put("requireTimes", BigDecimal.ZERO);
                                    pointData.put("designTimes", BigDecimal.ZERO);
                                    pointData.put("capacityLoad", BigDecimal.ZERO);
                                    timeDataList.add(pointData);
                                }
                                rowDetail.put("timeData", timeDataList);
                                rowEntry.put(uniqueValue, rowDetail);
                                plantTable.add(rowEntry);
                            }
                        }
                    }
                    // é‡æ–°æŽ’序结果
                    Collections.sort(plantTable, (map1, map2) -> {
                        String key1 = map1.keySet().iterator().next();
                        String key2 = map2.keySet().iterator().next();
                        // é¦–先按rowGroupBy排序(processName或workshop)
                        int result1 = key1.compareTo(key2);
                        if (result1 != 0) {
                            return result1;
                        }
                        // å¦‚æžœrowGroupBy相同,再按plant排序
                        Map<String, Object> detail1 = (Map<String, Object>) map1.get(key1);
                        Map<String, Object> detail2 = (Map<String, Object>) map2.get(key2);
                        String plant1 = detail1.containsKey("plant") ? (String) detail1.get("plant") : "";
                        String plant2 = detail2.containsKey("plant") ? (String) detail2.get("plant") : "";
                        return plant1.compareTo(plant2);
                    });
                    // æ›´æ–°ç»“æžœ
                    result.put("plantTable", plantTable);
                }
            }
        }
        return result;
    }
    /**
     * ä»ŽMap中安全获取String值
     */
    private String getStringValue(Map<String, Object> data, String key) {
        Object value = data.get(key);
        if (value == null) {
            return null;
        }
        return value.toString();
    }
    /**
     * ä»ŽMap中安全获取BigDecimal值
     */
    private BigDecimal getBigDecimalValue(Map<String, Object> data, String key) {
        Object value = data.get(key);
        if (value == null) {
            return null;
        }
        if (value instanceof BigDecimal) {
            return (BigDecimal) value;
        } else if (value instanceof Number) {
            return new BigDecimal(((Number) value).toString());
        } else if (value instanceof String) {
            try {
                return new BigDecimal((String) value);
            } catch (NumberFormatException e) {
                log.warn("无法将值转换为BigDecimal: {}", value);
                return null;
            }
        }
        return null;
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsMaterialProductGroupManagementServiceImpl.java
@@ -1,73 +1,64 @@
package com.aps.core.service.impl;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;
import cn.hutool.core.util.IdUtil;
import com.aps.common.core.utils.DateUtils;
import com.aps.common.core.utils.poi.ExcelUtil;
import com.aps.common.security.utils.DictUtils;
import com.aps.common.security.utils.SecurityUtils;
import com.aps.core.domain.ApsGasPipelinePrediction;
import com.aps.core.domain.ApsMaterialProductGroupManagement;
import com.aps.core.mapper.ApsMaterialProductGroupManagementMapper;
import com.aps.core.service.IApsMaterialProductGroupManagementService;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import io.micrometer.common.util.StringUtils;
import lombok.SneakyThrows;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;
/**
 * ç‰©æ–™äº§å“ç»„数据管理Service业务层处理
 *
 *
 * @author ruoyi
 * @date 2025-05-19
 */
@Service
public class ApsMaterialProductGroupManagementServiceImpl implements IApsMaterialProductGroupManagementService
{
public class ApsMaterialProductGroupManagementServiceImpl implements IApsMaterialProductGroupManagementService {
    @Autowired
    private ApsMaterialProductGroupManagementMapper apsMaterialProductGroupManagementMapper;
    /**
     * æŸ¥è¯¢ç‰©æ–™äº§å“ç»„数据管理
     *
     *
     * @param id ç‰©æ–™äº§å“ç»„数据管理主键
     * @return ç‰©æ–™äº§å“ç»„数据管理
     */
    @Override
    public ApsMaterialProductGroupManagement selectApsMaterialProductGroupManagementById(Long id)
    {
    public ApsMaterialProductGroupManagement selectApsMaterialProductGroupManagementById(Long id) {
        return apsMaterialProductGroupManagementMapper.selectApsMaterialProductGroupManagementById(id);
    }
    /**
     * æŸ¥è¯¢ç‰©æ–™äº§å“ç»„数据管理列表
     *
     *
     * @param apsMaterialProductGroupManagement ç‰©æ–™äº§å“ç»„数据管理
     * @return ç‰©æ–™äº§å“ç»„数据管理
     */
    @Override
    public List<ApsMaterialProductGroupManagement> selectApsMaterialProductGroupManagementList(ApsMaterialProductGroupManagement apsMaterialProductGroupManagement)
    {
    public List<ApsMaterialProductGroupManagement> selectApsMaterialProductGroupManagementList(ApsMaterialProductGroupManagement apsMaterialProductGroupManagement) {
        return apsMaterialProductGroupManagementMapper.selectApsMaterialProductGroupManagementList(apsMaterialProductGroupManagement);
    }
    /**
     * æ–°å¢žç‰©æ–™äº§å“ç»„数据管理
     *
     *
     * @param apsMaterialProductGroupManagement ç‰©æ–™äº§å“ç»„数据管理
     * @return ç»“æžœ
     */
    @Override
    public int insertApsMaterialProductGroupManagement(ApsMaterialProductGroupManagement apsMaterialProductGroupManagement)
    {
    public int insertApsMaterialProductGroupManagement(ApsMaterialProductGroupManagement apsMaterialProductGroupManagement) {
        apsMaterialProductGroupManagement.setId(IdUtil.getSnowflakeNextId());
        apsMaterialProductGroupManagement.setCreateBy(SecurityUtils.getUsername());
        apsMaterialProductGroupManagement.setCreateTime(DateUtils.getNowDate());
@@ -76,13 +67,12 @@
    /**
     * ä¿®æ”¹ç‰©æ–™äº§å“ç»„数据管理
     *
     *
     * @param apsMaterialProductGroupManagement ç‰©æ–™äº§å“ç»„数据管理
     * @return ç»“æžœ
     */
    @Override
    public int updateApsMaterialProductGroupManagement(ApsMaterialProductGroupManagement apsMaterialProductGroupManagement)
    {
    public int updateApsMaterialProductGroupManagement(ApsMaterialProductGroupManagement apsMaterialProductGroupManagement) {
        apsMaterialProductGroupManagement.setUpdateTime(DateUtils.getNowDate());
        apsMaterialProductGroupManagement.setUpdateBy(SecurityUtils.getUsername());
        return apsMaterialProductGroupManagementMapper.updateApsMaterialProductGroupManagement(apsMaterialProductGroupManagement);
@@ -90,98 +80,76 @@
    /**
     * æ‰¹é‡åˆ é™¤ç‰©æ–™äº§å“ç»„数据管理
     *
     *
     * @param ids éœ€è¦åˆ é™¤çš„物料产品组数据管理主键
     * @return ç»“æžœ
     */
    @Override
    public int deleteApsMaterialProductGroupManagementByIds(Long[] ids)
    {
    public int deleteApsMaterialProductGroupManagementByIds(Long[] ids) {
        return apsMaterialProductGroupManagementMapper.deleteApsMaterialProductGroupManagementByIds(ids);
    }
    /**
     * åˆ é™¤ç‰©æ–™äº§å“ç»„数据管理信息
     *
     *
     * @param id ç‰©æ–™äº§å“ç»„数据管理主键
     * @return ç»“æžœ
     */
    @Override
    public int deleteApsMaterialProductGroupManagementById(Long id)
    {
    public int deleteApsMaterialProductGroupManagementById(Long id) {
        return apsMaterialProductGroupManagementMapper.deleteApsMaterialProductGroupManagementById(id);
    }
    @SneakyThrows
    @Override
    public int batchInsertApsMaterialProductGroupManagement(MultipartFile file) {
        Workbook workbook = WorkbookFactory.create(file.getInputStream());
        Sheet sheet = workbook.getSheetAt(0);
        int rows = sheet.getLastRowNum();
        if (rows > 0) {
            List<ApsMaterialProductGroupManagement> list = new ArrayList<>();
            /*数据列从1开始*/
            Set<String> keys = new HashSet<>();
            for (int i = rows; i > 0; --i) {
                Row row = sheet.getRow(i);
                if (row.getCell(0) == null) {
                    continue;
                }
                String materialCode = row.getCell(0).getStringCellValue();
                if (StringUtils.isEmpty(materialCode)){
                    continue;
                }
                String materialType = row.getCell(1).getStringCellValue();
                String domain = row.getCell(2).getStringCellValue();
                String isMain = row.getCell(3).getStringCellValue();
                String factory = row.getCell(4).getStringCellValue();
                if (StringUtils.isNotBlank(materialType) &&
                    StringUtils.isNotBlank(domain) &&
                    StringUtils.isNotBlank(isMain) &&
                    StringUtils.isNotBlank(factory)) {
                    ApsMaterialProductGroupManagement item = new ApsMaterialProductGroupManagement();
                    item.setId(IdUtil.getSnowflakeNextId());
                    item.setFactory(factory);
                    item.setDomain(domain);
                    item.setMaterialType(materialType);
                    item.setMaterialCode(materialCode);
                    item.setIsMain(isMain);
                    item.setCreateBy(SecurityUtils.getUsername());
                    item.setCreateTime(DateUtils.getNowDate());
                    if (!keys.contains(item.getKey())) {
                        keys.add(item.getKey());
                        list.add(item);
                    }
                }
        ExcelUtil<ApsMaterialProductGroupManagement> util = new ExcelUtil<>(ApsMaterialProductGroupManagement.class);
        List<ApsMaterialProductGroupManagement> list = util.importExcel(file.getInputStream());
        DictUtils.CacheValue cacheValue = DictUtils.getCacheValue("aps_factory");
        DictUtils.CacheValue cacheDomain = DictUtils.getCacheValue("aps_domain");
        Set<String> keys = new HashSet<>();
        list.forEach(item -> {
            item.setId(IdUtil.getSnowflakeNextId());
            item.setDomain(cacheDomain.get(item.getDomain()));
            item.setFactory(cacheValue.get(item.getFactory()));
            item.setCreateBy(SecurityUtils.getUsername());
            item.setCreateTime(DateUtils.getNowDate());
        });
        for (int i = list.size() - 1; i >= 0; --i) {
            list.get(i).setKey(null);
            if (!keys.contains(list.get(i).getKey())) {
                keys.add(list.get(i).getKey());
            } else {
                list.remove(i);
            }
            if (!list.isEmpty()) {
                Set<String> facCodeKey = apsMaterialProductGroupManagementMapper.selectByFacOrMaterial(keys);
                if (!facCodeKey.isEmpty()) {
                    Iterator<ApsMaterialProductGroupManagement> it = list.iterator();
                    while (it.hasNext()) {
                        ApsMaterialProductGroupManagement item = it.next();
                        if (facCodeKey.contains(item.getKey())) {
                            LambdaUpdateWrapper<ApsMaterialProductGroupManagement> wrapper = new LambdaUpdateWrapper<>();
                            wrapper.eq(ApsMaterialProductGroupManagement::getFactory, item.getFactory());
                            wrapper.eq(ApsMaterialProductGroupManagement::getMaterialCode, item.getMaterialCode());
                            item.setCreateBy(null);
                            item.setCreateTime(null);
                            item.setUpdateBy(SecurityUtils.getUsername());
                            item.setUpdateTime(new Timestamp(System.currentTimeMillis()));
                            apsMaterialProductGroupManagementMapper.update(item, wrapper);
                            it.remove();
                        }
                    }
                }
                if (!list.isEmpty()) {
                    apsMaterialProductGroupManagementMapper.insert(list);
                }
            }
            return list.size();
        }
        return 0;
        if (!list.isEmpty()) {
            Set<String> facCodeKey = apsMaterialProductGroupManagementMapper.selectByFacOrMaterial(keys);
            if (!facCodeKey.isEmpty()) {
                Iterator<ApsMaterialProductGroupManagement> it = list.iterator();
                while (it.hasNext()) {
                    ApsMaterialProductGroupManagement item = it.next();
                    if (facCodeKey.contains(item.getKey())) {
                        LambdaUpdateWrapper<ApsMaterialProductGroupManagement> wrapper = new LambdaUpdateWrapper<>();
                        wrapper.eq(ApsMaterialProductGroupManagement::getFactory, item.getFactory());
                        wrapper.eq(ApsMaterialProductGroupManagement::getMaterialCode, item.getMaterialCode());
                        item.setCreateBy(null);
                        item.setCreateTime(null);
                        item.setId(null);
                        item.setUpdateBy(SecurityUtils.getUsername());
                        item.setUpdateTime(new Timestamp(System.currentTimeMillis()));
                        apsMaterialProductGroupManagementMapper.update(item, wrapper);
                        it.remove();
                    }
                }
            }
            if (!list.isEmpty()) {
                apsMaterialProductGroupManagementMapper.insert(list);
            }
        }
        return list.size();
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsMaterialStorageManagementServiceImpl.java
@@ -7,6 +7,7 @@
import com.aps.core.domain.ApsMaterialStorageManagement;
import com.aps.core.mapper.ApsMaterialStorageManagementMapper;
import com.aps.core.service.IApsMaterialStorageManagementService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@@ -21,6 +22,7 @@
 * @date 2025-04-17
 */
@Service
@Slf4j
public class ApsMaterialStorageManagementServiceImpl implements IApsMaterialStorageManagementService 
{
    @Autowired
@@ -150,6 +152,7 @@
    @Override
    public boolean setStorageDataToRedis(String orgCode) {
        try {
            log.info("开始同步 ç‰©æ–™åº“存至Redis!");
            Set<String> keys = redisTemplate.keys("MaterialStorage:Material_*");
            if (keys != null && !keys.isEmpty()) {
                redisTemplate.delete(keys);
@@ -169,14 +172,12 @@
                bulkData.put("MaterialStorage:Material_"+apsMaterialStorageManagement.getApplicableFactories()+"_"+apsMaterialStorageManagement.getItemNumber(), jsonObject);
            });
            redisTemplate.opsForValue().multiSet(bulkData);
            log.info("完成同步 ç‰©æ–™åº“存至Redis!");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("同步物料库存至Redis失败!"+e.getMessage());
            return false;
        }
//        Set<String> keys = redisTemplate.keys("MaterialStorage:Material_*");
//        if (keys != null && !keys.isEmpty()) {
//            redisTemplate.delete(keys);
//        }
        return true;
    }
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsPlanTaskServiceImpl.java
@@ -1,7 +1,6 @@
package com.aps.core.service.impl;
import cn.hutool.core.util.IdUtil;
import com.aps.common.core.domain.R;
import com.aps.common.core.utils.DateUtils;
import com.aps.common.core.web.domain.AjaxResult;
import com.aps.common.redis.service.RedisLockUtils;
@@ -10,9 +9,9 @@
import com.aps.core.enums.PLAN_TASK_TYPE;
import com.aps.core.enums.REDIS_LOCK_KEY;
import com.aps.core.mapper.ApsPlateStandardRequireOrderEndDayMapper;
import com.aps.core.service.ApsPlate.IApsPlateProcessShopStatService;
import com.aps.core.service.ApsPlate.IApsPlateStandardRequireBatchService;
import com.aps.core.service.ApsPlate.IApsPlateStandardRequireService;
import com.aps.core.service.ApsPlateStandardRequireOrderEndDayService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -26,6 +25,7 @@
import static com.aps.common.core.web.domain.AjaxResult.success;
import static com.aps.core.enums.REDIS_LOCK_KEY.PLATE_ORDER_PLAN;
/**
* @author zhl
@@ -50,6 +50,9 @@
    @Resource
    ApsPlateStandardRequireOrderEndDayMapper  orderEndDayMapper;
    @Resource
    IApsPlateProcessShopStatService plateProcessShopStatService;
    @Override
    public Page<ApsPlanTask> pagingList(Page<ApsPlanTask> page ,ApsPlanTask task){
@@ -90,36 +93,69 @@
    }
    @Override
    public AjaxResult generatorPlan()
    {
    public AjaxResult generatorPlan() {
        String plateOrderPlanKey = PLATE_ORDER_PLAN.getKey();
        boolean existsLock = redisLockUtils.existLock(plateOrderPlanKey, PLAN_TASK_TYPE.PLATE_PLAN.getCode());
        if (existsLock){
        if (existsLock) {
            return AjaxResult.warn("钣金工单计划任务正在执行中!");
        }
        LambdaQueryWrapper<ApsPlanTask> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(ApsPlanTask::getTaskType,PLAN_TASK_TYPE.PLATE_PLAN.getCode());
        queryWrapper.eq(ApsPlanTask::getTaskStatus,PLAN_TASK_STATUS.IN_PROCESS.getCode());
        LambdaQueryWrapper<ApsPlanTask> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApsPlanTask::getTaskType, PLAN_TASK_TYPE.PLATE_PLAN.getCode());
        queryWrapper.eq(ApsPlanTask::getTaskStatus, PLAN_TASK_STATUS.IN_PROCESS.getCode());
        boolean existsDbTask = mapper.exists(queryWrapper);
        if (existsDbTask){
        if (existsDbTask) {
            return AjaxResult.warn("钣金工单计划任务正在执行中!!");
        }
        String currentBatchNum = requireBatchService.getNewBatchNumber();
        try {
            redisLockUtils.getLock(plateOrderPlanKey,PLAN_TASK_TYPE.PLATE_PLAN.getCode(), 3*60L);
            String batchNum= requireBatchService.getNewBatchNumber();
            this.savePlanTask(batchNum);
            apsPlateStandardRequireService.generatorPlan(batchNum);
            this.updateTaskStatus(batchNum, PLAN_TASK_STATUS.FINISHED);
            redisLockUtils.getLock(plateOrderPlanKey, PLAN_TASK_TYPE.PLATE_PLAN.getCode(), 15 * 60L);
            this.savePlanTask(currentBatchNum);
            //Thread.sleep(60*1000);
            apsPlateStandardRequireService.generatorPlan(currentBatchNum);
            /*清除已经存在的 å·¥å•计划完工时间*/
            orderEndDayMapper.batchRemove();
            log.info("计划任务执行完成!"+batchNum);
            this.updateTaskStatus(currentBatchNum, PLAN_TASK_STATUS.FINISHED);
            log.info("计划任务执行完成!" + currentBatchNum);
            return success();
        }catch (Exception e){
            redisLockUtils.releaseLock(plateOrderPlanKey,PLAN_TASK_TYPE.PLATE_PLAN.getCode());
            log.error("计划任务执行失败!"+e.getMessage());
            return AjaxResult.error("计划任务执行失败!"+e.getMessage());
        }finally {
            redisLockUtils.releaseLock(plateOrderPlanKey,PLAN_TASK_TYPE.PLATE_PLAN.getCode());
        } catch (Exception e) {
            redisLockUtils.releaseLock(plateOrderPlanKey, PLAN_TASK_TYPE.PLATE_PLAN.getCode());
            log.error("计划任务执行失败!" + e.getMessage());
            this.updateTaskStatus(currentBatchNum, PLAN_TASK_STATUS.ERROR);
            return AjaxResult.error("计划任务执行失败!" + e.getMessage());
        } finally {
            redisLockUtils.releaseLock(plateOrderPlanKey, PLAN_TASK_TYPE.PLATE_PLAN.getCode());
        }
    }
    @Override
    public AjaxResult generatorPlatePlanTable() {
        String plateOrderPlanKey = REDIS_LOCK_KEY.PLATE_SHOP_PLAN_TABLE.getKey();
        boolean existsLock = redisLockUtils.existLock(plateOrderPlanKey, PLAN_TASK_TYPE.PLATE_SHOP_PLAN_TABLE.getCode());
        if (existsLock) {
            return AjaxResult.warn("钣金计划大表计划任务正在执行中!");
        }
        LambdaQueryWrapper<ApsPlanTask> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApsPlanTask::getTaskType, PLAN_TASK_TYPE.PLATE_SHOP_PLAN_TABLE.getCode());
        queryWrapper.eq(ApsPlanTask::getTaskStatus, PLAN_TASK_STATUS.IN_PROCESS.getCode());
        boolean existsDbTask = mapper.exists(queryWrapper);
        if (existsDbTask) {
            return AjaxResult.warn("钣金计划大表任务正在执行中!!");
        }
        String currentBatchNum =  String.valueOf(IdUtil.getSnowflakeNextId()) ;
        try {
            redisLockUtils.getLock(plateOrderPlanKey, PLAN_TASK_TYPE.PLATE_SHOP_PLAN_TABLE.getCode(), 15 * 60L);
            this.savePlanTask( currentBatchNum);
            Thread.sleep(60000);
            plateProcessShopStatService.saveShopStat();
            this.updateTaskStatus(currentBatchNum, PLAN_TASK_STATUS.FINISHED);
            log.info("钣金计划大表任务执行完成!" + currentBatchNum);
            return success();
        } catch (Exception e) {
            redisLockUtils.releaseLock(plateOrderPlanKey, PLAN_TASK_TYPE.PLATE_SHOP_PLAN_TABLE.getCode());
            log.error("钣金计划大表任务执行失败!" + e.getMessage());
            this.updateTaskStatus(currentBatchNum, PLAN_TASK_STATUS.ERROR);
            return AjaxResult.error("钣金计划大表任务执行失败!" + e.getMessage());
        } finally {
            redisLockUtils.releaseLock(plateOrderPlanKey, PLAN_TASK_TYPE.PLATE_SHOP_PLAN_TABLE.getCode());
        }
    }
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsPlate/ApsPlatePlanServiceImpl.java
@@ -13,6 +13,7 @@
import com.aps.core.mapper.ApsPlatePlanTempMapper;
import com.aps.core.service.ApsPlate.IApsPlatePlanService;
import com.aps.system.api.domain.SysDictData;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -29,6 +30,7 @@
 * @author ruoyi
 * @date 2025-04-08
 */
@Slf4j
@Service
public class ApsPlatePlanServiceImpl implements IApsPlatePlanService
{
@@ -221,6 +223,7 @@
    @Override
    public boolean setSubPlansToRedis() {
        try {
            log.info("开始设置钣金子计划到redis");
            Set<String> keys = redisTemplate.keys("PLATE_SUB_PLAN:*");
            if (keys != null && !keys.isEmpty()) {
                redisTemplate.delete(keys);
@@ -235,9 +238,11 @@
                bulkData.put("PLATE_SUB_PLAN:"+key, value);
            }
            redisTemplate.opsForValue().multiSet(bulkData);
            log.info("设置钣金子计划到redis完成");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("设置钣金子计划到redis失败"+e.getMessage());
            return false;
        }
    }
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsPlate/ApsPlateProcessShopStatServiceImpl.java
@@ -5,6 +5,8 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.alibaba.nacos.common.utils.JacksonUtils;
@@ -18,6 +20,7 @@
import com.aps.core.domain.ApsPlate.ApsPlateProcessShopStat;
import com.aps.core.domain.ApsPlate.ApsPlateProcessStat;
import com.aps.core.mapper.*;
import com.aps.core.service.ApsPlate.IApsPlateProcessStatService;
import com.aps.system.api.domain.SysDictData;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -59,6 +62,9 @@
    @Resource
    private ApsPlatePlanMapper apsPlatePlanMapper;
    @Autowired
    private IApsPlateProcessStatService apsPlateProcessStatService;
    /**
@@ -132,61 +138,73 @@
    /**
     * ä¿å­˜é’£é‡‘车间统计
     */
    @Transactional
    @Transactional( rollbackFor =Exception.class)
    @Override
    public void saveShopStat() {
        try {
            // å¼€å§‹ä¹‹å‰å…ˆåˆ é™¤æ‰€æœ‰åŽ†å²æ•°æ®
        // å®šä¹‰è¯¥åŠŸèƒ½ä½¿ç”¨æ•°æ®æºä¸ºå—é€šçš„å·¥åŽ‚
        final String plant = "FORTUNA";
        final String major="BJ";
        // æŸ¥è¯¢ç›¸å…³æ•°æ®
        ApsPlatePlan platePlan = new ApsPlatePlan();
        platePlan.setPlant(plant);
        log.info("开始执行钣金计划大表");
        List<ApsPlatePlan> planList = apsPlatePlanMapper.selectApsPlatePlanList(platePlan);
        ApsShop apsShop = new ApsShop();
        apsShop.setPlantCode(plant);
        List<ApsShop> shopList = shopMapper.selectApsShopList(apsShop);
        ApsStandardProcess process = new ApsStandardProcess();
        process.setPlant(plant);
        process.setMajor(major);
        List<ApsStandardProcess> shopProcesses = standardProcessMapper.selectApsStandardProcessList(process);
        if (!planList.isEmpty() &&  !shopList.isEmpty() &&  !shopProcesses.isEmpty()) {
            log.info("钣金计划大表:删除所有历史数据");
            apsPlateProcessStatMapper.deleteAll();
            apsPlateProcessShopStatMapper.deleteAll();
            // å®šä¹‰è¯¥åŠŸèƒ½ä½¿ç”¨æ•°æ®æºä¸ºå—é€šçš„å·¥åŽ‚
            final String plant = "FORTUNA";
            final String major="钣金";
            // æŸ¥è¯¢ç›¸å…³æ•°æ®
            ApsPlatePlan platePlan = new ApsPlatePlan();
            platePlan.setPlant(plant);
            List<ApsPlatePlan> planList = apsPlatePlanMapper.selectApsPlatePlanList(platePlan);
            List<ApsPlateProcessStat> statList = apsPlateProcessStatMapper.selectApsPlateProcessStatList(new ApsPlateProcessStat());
            ApsShop apsShop = new ApsShop();
            apsShop.setPlantCode(plant);
            List<ApsShop> shopList = shopMapper.selectApsShopList(apsShop);
            ApsStandardProcess process = new ApsStandardProcess();
            process.setPlant(plant);
            process.setMajor(major);
            List<ApsStandardProcess> shopProcesses = standardProcessMapper.selectApsStandardProcessList(process);
            if (planList.isEmpty() || shopList.isEmpty() || shopProcesses.isEmpty()) {
                log.warn("计划列表、车间列表或工序列表为空,无法生成统计信息");
                return;
            }
            // æž„建车间名称到工序名称的映射
            Map<String, List<String>> shopToProcessNames = shopProcesses.stream()
            log.info("钣金计划大表:推算倒排钣金工序计划完工日期和计划开工时间");
            List<ApsPlateProcessStat> statList =apsPlateProcessStatService.computePlateProcessStat();
                // æž„建车间名称到工序名称的映射
            Map<String, List<String>> shopToProcessNames = shopProcesses.stream().filter(x -> null!=x.getWorkShop())
                    .collect(Collectors.groupingBy(ApsStandardProcess::getWorkShop,
                            Collectors.mapping(ApsStandardProcess::getProcessName, Collectors.toList())
                    ));
            // æ‰¹é‡æ’入统计数据
            log.info("钣金计划大表:计算每个工单中每个车间的开始、结束时间");
            List<ApsPlateProcessShopStat> statsToInsert = new ArrayList<>();
            for (ApsPlatePlan plan : planList) {
                for (ApsShop shop : shopList) {
            log.info("钣金计划大表V1:开始计算每个工单车间工时");
            planList.stream().parallel().forEach(plan -> {
                shopList.stream().parallel().forEach(shop -> {
                    ApsPlateProcessShopStat stat = createShopStat(plan, shop, shopToProcessNames, statList);
                    statsToInsert.add(stat);
                }
                });
            });
            log.info("钣金计划大表:批量保存工序开工和完工时间");
            List<List<ApsPlateProcessStat>> processStatBatchList = ListUtil.split(statList, 1000);
            processStatBatchList.stream().parallel().forEach(batch -> apsPlateProcessStatMapper.batchInsertPlateStat(batch));
            log.info("钣金计划大表:批量保存工单-车间时间信息");
            List<List<ApsPlateProcessShopStat>> shopStatBatchList = ListUtil.split(statsToInsert, 1000);
            shopStatBatchList.stream().parallel().forEach(batch -> apsPlateProcessShopStatMapper.batchInsert(batch));
        }else {
            if(shopProcesses.isEmpty()){
                log.error("钣金计划大表:未找到标准工序数据!");
                throw  new RuntimeException("未找到标准工序数据!");
            }
            // æ‰¹é‡æ’入以提高性能
            if (!statsToInsert.isEmpty()) {
                int batchSize = 1000;
                for (int i = 0; i < statsToInsert.size(); i += batchSize) {
                    int end = Math.min(i + batchSize, statsToInsert.size());
                    List<ApsPlateProcessShopStat> batch = statsToInsert.subList(i, end);
                    apsPlateProcessShopStatMapper.batchInsert(batch);
                }
            if(shopList.isEmpty()){
                log.error("钣金计划大表:未找到车间数据!");
                throw  new RuntimeException("未找到车间数据!");
            }
        } catch (Exception e) {
            log.error("保存钣金车间统计时发生异常", e);
            throw new RuntimeException("保存钣金车间统计失败", e);
            if(planList.isEmpty()){
                log.error("钣金计划大表:未找到工单数据!");
                throw  new RuntimeException("未找到工单数据!");
            }
        }
        log.info("钣金计划大表:完成");
    }
    /**
@@ -205,7 +223,6 @@
        stat.setWorkCenter(plan.getWorkCenter());
        stat.setProcessNumber(plan.getProcessNumber());
        try {
            List<String> processNames = shopToProcessNames.getOrDefault(shopName, Collections.emptyList());
            if (!processNames.isEmpty()) {
@@ -247,7 +264,8 @@
                }
            }
        } catch (Exception e) {
            log.error("computer error:"+ JSONObject.toJSONString(stat));
            log.error("钣金计划大表 error:"+ JSONObject.toJSONString(stat));
            throw new RuntimeException("计算车间统计数据异常!");
        }
        return stat;
    }
@@ -286,7 +304,7 @@
        List<SysDictData> documentStatusDic = DictUtils.getDictCache("aps_document_status");
        // æž„建结果列表
        planList.forEach(
        planList.stream().parallel().forEach(
                 plan -> {
                    // æ ¹æ® docNo èŽ·å–å¯¹åº”çš„ shopStatList
                    List<ApsPlateProcessShopStat> shopStatList = shopStatesByDocNo.getOrDefault(plan.getDocumentNumber(), Collections.emptyList());
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsPlate/ApsPlateProcessStatServiceImpl.java
@@ -2,12 +2,15 @@
import java.math.BigDecimal;
import java.time.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import cn.hutool.core.util.IdUtil;
import com.aps.common.core.utils.uuid.IdUtils;
import com.aps.common.security.utils.SecurityUtils;
import com.aps.core.domain.ApsPlate.ApsPlateStandardRequireBomOrderDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.aps.core.mapper.ApsPlateProcessStatMapper;
@@ -104,16 +107,18 @@
    /**
     * ä¿å­˜é’£é‡‘统计数据
     */
    @Transactional
    @Override
    public void savePlateProcessStat() {
    public List<ApsPlateProcessStat> computePlateProcessStat() {
        String batchNum = IdUtils.fastSimpleUUID();
        List<ApsPlateProcessStat> tempList = apsPlateProcessStatMapper.queryTempStat();
        Map<String, List<ApsPlateProcessStat>> groupByOrderNo = tempList.stream().collect(groupingBy(ApsPlateProcessStat::getWorkOrderNo));
        Boolean hasBefore = false;
        LocalDateTime now = LocalDateTime.now();
        for (Map.Entry<String, List<ApsPlateProcessStat>> entry : groupByOrderNo.entrySet()) {
            List<ApsPlateProcessStat> statPerOrder = entry.getValue();
        List<ApsPlateProcessStat> totalList=new ArrayList<>();
        ArrayList<Map.Entry<String, List<ApsPlateProcessStat>>> orderProcessRoutes = new ArrayList<>(groupByOrderNo.entrySet());
        orderProcessRoutes.stream().parallel().forEach(x->{
            boolean hasBefore = false;
            List<ApsPlateProcessStat>  statPerOrder = x.getValue();
            /*num ä¸ºæ ¹æ®å®Œå·¥æ—¶é—´æŽ’序出的序号,按此排序,可保证是按完工时间倒叙排列*/
            statPerOrder.sort((a, b)->a.getNum().compareTo(b.getNum()));
            ApsPlateProcessStat last=null;
@@ -176,13 +181,11 @@
                    }
                }
                last = stat;
                apsPlateProcessStatMapper.insertApsPlateProcessStat(stat);
                totalList.add(stat);
            }
            hasBefore=false;
        }
        apsPlateProcessStatMapper.removeOtherStat(batchNum);
        });
        return totalList;
    }
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsPlate/ApsPlateStandardRequireBatchServiceImpl.java
@@ -136,16 +136,12 @@
    @Transactional
    @Override
    public void initRequireBatch() {
        ApsPlateStandardRequireBatch batch=apsPlateStandardRequireBatchMapper.selectLastRequireBatch();
        if (batch!=null){
            String batchNumber = batch.getBatchNumber();
            apsPlateStandardRequireMapper.deleteLastPatch(batchNumber);
            apsPlateStandardRequireBomOrderDetailMapper.deleteLastPatch(batchNumber);
            apsPlateStandardRequireBomStockDetailMapper.deleteLastPatch(batchNumber);
            apsPlateStandardRequireErrorMapper.deleteLastPatch(batchNumber);
            apsPlatePlanMapper.initUnMatchQty();
            apsMaterialStorageManagementMapper.initRemainderStock();
        }
    public void initRequireBatch(String currentBatchNumber) {
        apsPlateStandardRequireMapper.deleteLastPatch(currentBatchNumber);
        apsPlateStandardRequireBomOrderDetailMapper.deleteLastPatch(currentBatchNumber);
        apsPlateStandardRequireBomStockDetailMapper.deleteLastPatch(currentBatchNumber);
        apsPlateStandardRequireErrorMapper.deleteLastPatch(currentBatchNumber);
        apsPlatePlanMapper.initUnMatchQty();
        apsMaterialStorageManagementMapper.initRemainderStock();
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsPlate/ApsPlateStandardRequireErrorServiceImpl.java
@@ -1,7 +1,11 @@
package com.aps.core.service.impl.ApsPlate;
import java.util.List;
import cn.hutool.core.util.IdUtil;
import com.aps.common.core.utils.DateUtils;
import com.aps.common.security.utils.SecurityUtils;
import com.aps.core.domain.ApsPlate.ApsPlateStandardRequire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.aps.core.mapper.ApsPlateStandardRequireErrorMapper;
@@ -93,4 +97,21 @@
    {
        return apsPlateStandardRequireErrorMapper.deleteApsPlateStandardRequireErrorById(id);
    }
    @Override
    public void saveRequireError(ApsPlateStandardRequire require, String message) {
        ApsPlateStandardRequireError data = ApsPlateStandardRequireError.builder()
                .id(IdUtil.getSnowflakeNextId())
                .requireId(require.getId())
                .batchNumber(require.getBatchNumber())
                .docNum(require.getDocNum())
                .itemNum(require.getBomLineCode())
                .orgCode(require.getOrgCode())
                .message(message)
                .delFlag("0")
                .build();
        data.setCreateBy(SecurityUtils.getUsername());
        data.setCreateTime(DateUtils.getNowDate());
        apsPlateStandardRequireErrorMapper.insertApsPlateStandardRequireError(data);
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsPlate/ApsPlateStandardRequireServiceImpl.java
@@ -1,29 +1,27 @@
package com.aps.core.service.impl.ApsPlate;
import java.math.BigDecimal;
import java.util.*;
import cn.hutool.core.util.IdUtil;
import com.aps.common.core.utils.DateUtils;
import com.aps.common.security.utils.DictUtils;
import com.aps.common.security.utils.SecurityUtils;
import com.aps.core.domain.*;
import com.aps.core.domain.ApsPlate.ApsPlatePlan;
import com.aps.core.domain.ApsPlate.ApsPlateStandardRequireBomOrderDetail;
import com.aps.core.domain.ApsPlate.ApsPlateStandardRequireBomStockDetail;
import com.aps.core.domain.ApsBom;
import com.aps.core.domain.ApsMaterialStorageManagement;
import com.aps.core.domain.ApsPlate.*;
import com.aps.core.domain.ApsStandardProcessRouteLine;
import com.aps.core.mapper.*;
import com.aps.core.service.*;
import com.aps.core.service.ApsPlate.*;
import com.aps.core.service.IApsBomService;
import com.aps.core.service.IApsMaterialStorageManagementService;
import com.aps.core.service.IApsStandardProcessRouteLineService;
import com.aps.system.api.domain.SysDictData;
import jakarta.annotation.Resource;
import com.aps.core.domain.ApsPlate.ApsPlateStandardRequire;
import com.aps.core.mapper.ApsPlateStandardRequireMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.math.BigDecimal;
import java.util.*;
/**
 * é’£é‡‘工单标准需求Service业务层处理
@@ -39,29 +37,17 @@
    private ApsPlateStandardRequireMapper apsPlateStandardRequireMapper;
    @Resource
    private ApsPlateStandardRequireBatchMapper requireBatchMapper;
    @Resource
    ApsPlatePlanMapper platePlanMapper;
    @Resource
    ApsBomHeaderMapper bomHeaderMapper;
    @Resource
    IApsBomService bomLineService;
    @Resource
    ApsMaterialStorageManagementMapper itemStorageMapper;
    @Resource
    ApsPlateStandardRequireBomStockDetailMapper plateBomStockDetailMapper;
    @Resource
    IApsPlateStandardRequireBomStockDetailService bomStockDetailService;
    @Resource
    ApsStandardProcessRouteHeaderMapper standardProcessRouteHeaderMapper;
    @Resource
    ApsStandardProcessRouteLineMapper ApsStandardProcessRouteLineMapper;
    @Resource
    ApsPlateStandardRequireBomOrderDetailMapper plateBomOrderDetailMapper;
@@ -76,10 +62,11 @@
    IApsStandardProcessRouteLineService routeLineService;
    @Resource
    IApsPlateStandardRequireBatchService requireBatchService;
    IApsPlateStandardRequireErrorService requireErrorService;
    @Resource
    private IApsMaterialStorageManagementService storageManagementService;
    @Resource
    IApsPlateStandardRequireBatchService requireBatchService;
    /**
     * æŸ¥è¯¢é’£é‡‘工单标准需求
     * 
@@ -167,9 +154,7 @@
    @Transactional
    @Override
    public void generatorPlan(String batchNum){
        /*初始化数据*/
        requireBatchService.initRequireBatch();
        requireBatchService.initRequireBatch(batchNum);
        /*定义工厂为南通 */
        String plantCode="FORTUNA";
        /*获取钣金主单信息*/
@@ -296,7 +281,10 @@
        if (itemStorageOpt.isPresent()) {
            ApsMaterialStorageManagement     itemStorage=itemStorageOpt.get();
            BigDecimal remainderStock =itemStorage.getRemainderStock();
            BigDecimal remainderStock =BigDecimal.ZERO;
            if(null!=itemStorage.getRemainderStock()){
                remainderStock = itemStorage.getRemainderStock();
            }
            /*计算净需求 é»˜è®¤=需求数量*/
            if (remainderStock.compareTo(BigDecimal.ZERO) == 0) {
                require.setNetRequirement(require.getBomUseAmount());
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsShopServiceImpl.java
@@ -1,9 +1,13 @@
package com.aps.core.service.impl;
import java.util.List;
import java.util.Set;
import com.aps.common.core.utils.DateUtils;
import com.aps.common.core.utils.uuid.IdUtils;
import com.aps.common.security.utils.SecurityUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.aps.core.mapper.ApsShopMapper;
@@ -97,4 +101,19 @@
    {
        return apsShopMapper.deleteApsShopById(id);
    }
    @Override
    public List<ApsShop> findAllShops() {
        return apsShopMapper.selectList(new QueryWrapper<>());
    }
    @Override
    public List<ApsShop> findShopByFactory(String orgCode) {
        return apsShopMapper.selectApsByFactory(orgCode);
    }
    @Override
    public List<ApsShop> findShopByCodes(@NotNull Set<String> codes) {
        return apsShopMapper.selectByCodes(codes);
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsStandardProcessRouteHeaderServiceImpl.java
@@ -5,6 +5,7 @@
import com.aps.core.domain.ApsStandardProcessRouteHeader;
import com.aps.core.mapper.ApsStandardProcessRouteHeaderMapper;
import com.aps.core.service.IApsStandardProcessRouteHeaderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@@ -21,6 +22,7 @@
 * @date 2025-05-06
 */
@Service
@Slf4j
public class ApsStandardProcessRouteHeaderServiceImpl implements IApsStandardProcessRouteHeaderService 
{
    @Autowired
@@ -106,6 +108,7 @@
    @Override
    public boolean setProcessRouteDataToRedis(String orgCode) {
        try {
            log.info("开始同步标准工艺路线数据至Redis");
            Set<String> keys = redisTemplate.keys("ROUTE:ROUTE_*");
            if (keys != null && !keys.isEmpty()) {
                redisTemplate.delete(keys);
@@ -116,9 +119,11 @@
                bulkData.put("ROUTE:ROUTE_"+jsonObject.getString("org_code")+"_"+jsonObject.getString("item_code"), jsonObject.getBigDecimal("standardtime"));
            }
            redisTemplate.opsForValue().multiSet(bulkData);
            log.info("完成同步标准工艺路线数据至Redis");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("同步标准工艺路线数据至Redis失败"+e.getMessage());
            return false;
        }
    }
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsStandardProcessRouteLineServiceImpl.java
@@ -12,6 +12,7 @@
import com.aps.core.domain.ApsStandardProcessRouteHeader;
import com.aps.core.mapper.ApsPlateStandardRequireErrorMapper;
import com.aps.core.mapper.ApsStandardProcessRouteHeaderMapper;
import com.aps.core.service.ApsPlate.IApsPlateStandardRequireErrorService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
@@ -34,7 +35,7 @@
    @Resource
    ApsStandardProcessRouteHeaderMapper standardProcessRouteHeaderMapper;
    @Resource
    ApsPlateStandardRequireErrorMapper requireErrorMapper;
    IApsPlateStandardRequireErrorService requireErrorService;
    @Resource
    private RedisTemplate redisTemplate;
@@ -141,7 +142,7 @@
            ret.setRouteTime(totalRouteTime);
            ret.setRouteId(routeHeader.getRouteId());
        }else {
            saveRequireError(require,"标准工艺路线不存在");
            requireErrorService.saveRequireError(require,"标准工艺路线不存在");
        }
        // è¿”回总工时
        return ret;
@@ -170,7 +171,7 @@
            ret.setRouteTime(totalRouteTime.multiply(netRequirement));
            return  ret;
        } else {
            saveRequireError(require,"标准工艺路线不存在");
            requireErrorService.saveRequireError(require,"标准工艺路线不存在");
            /*// æŸ¥è¯¢æ ‡å‡†å·¥è‰ºè·¯çº¿å¤´éƒ¨ä¿¡æ¯
            Optional<ApsStandardProcessRouteHeader> firstProcessRoute = standardProcessRouteHeaderMapper.queryStandardProcessRouteHeaderByPlantAndItemCode(plant, itemCode).stream().findFirst();
            if (firstProcessRoute.isPresent()) {
@@ -193,19 +194,4 @@
        }
    }
    private void saveRequireError(ApsPlateStandardRequire require,String message) {
        ApsPlateStandardRequireError data = ApsPlateStandardRequireError.builder()
                .id(IdUtil.getSnowflakeNextId())
                .requireId(require.getId())
                .batchNumber(require.getBatchNumber())
                .docNum(require.getDocNum())
                .itemNum(require.getBomLineCode())
                .orgCode(require.getOrgCode())
                .message(message)
                .delFlag("0")
                .build();
        data.setCreateBy(SecurityUtils.getUsername());
        data.setCreateTime(DateUtils.getNowDate());
        requireErrorMapper.insertApsPlateStandardRequireError(data);
    }
}
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsStandardProcessServiceImpl.java
@@ -1,60 +1,65 @@
package com.aps.core.service.impl;
import com.aps.common.core.utils.DateUtils;
import com.aps.common.core.utils.StringUtils;
import com.aps.common.security.utils.DictUtils;
import com.aps.common.security.utils.SecurityUtils;
import com.aps.core.domain.ApsShop;
import com.aps.core.domain.ApsStandardProcess;
import com.aps.core.mapper.ApsShopMapper;
import com.aps.core.mapper.ApsStandardProcessMapper;
import com.aps.core.service.IApsStandardProcessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
 * æ ‡å‡†å·¥åºService业务层处理
 *
 *
 * @author hjy
 * @date 2025-04-23
 */
@Service
public class ApsStandardProcessServiceImpl implements IApsStandardProcessService
{
public class ApsStandardProcessServiceImpl implements IApsStandardProcessService {
    @Autowired
    private ApsStandardProcessMapper apsStandardProcessMapper;
    @Autowired
    private ApsShopMapper apsShopMapper;
    /**
     * æŸ¥è¯¢æ ‡å‡†å·¥åº
     *
     *
     * @param id æ ‡å‡†å·¥åºä¸»é”®
     * @return æ ‡å‡†å·¥åº
     */
    @Override
    public ApsStandardProcess selectApsStandardProcessById(Long id)
    {
    public ApsStandardProcess selectApsStandardProcessById(Long id) {
        return apsStandardProcessMapper.selectApsStandardProcessById(id);
    }
    /**
     * æŸ¥è¯¢æ ‡å‡†å·¥åºåˆ—表
     *
     *
     * @param apsStandardProcess æ ‡å‡†å·¥åº
     * @return æ ‡å‡†å·¥åº
     */
    @Override
    public List<ApsStandardProcess> selectApsStandardProcessList(ApsStandardProcess apsStandardProcess)
    {
    public List<ApsStandardProcess> selectApsStandardProcessList(ApsStandardProcess apsStandardProcess) {
        return apsStandardProcessMapper.selectApsStandardProcessList(apsStandardProcess);
    }
    /**
     * æ–°å¢žæ ‡å‡†å·¥åº
     *
     *
     * @param apsStandardProcess æ ‡å‡†å·¥åº
     * @return ç»“æžœ
     */
    @Override
    public int insertApsStandardProcess(ApsStandardProcess apsStandardProcess)
    {
    public int insertApsStandardProcess(ApsStandardProcess apsStandardProcess) {
        apsStandardProcess.setCreateTime(DateUtils.getNowDate());
        apsStandardProcess.setCreateBy(SecurityUtils.getUsername());
        return apsStandardProcessMapper.insertApsStandardProcess(apsStandardProcess);
@@ -62,13 +67,12 @@
    /**
     * ä¿®æ”¹æ ‡å‡†å·¥åº
     *
     *
     * @param apsStandardProcess æ ‡å‡†å·¥åº
     * @return ç»“æžœ
     */
    @Override
    public int updateApsStandardProcess(ApsStandardProcess apsStandardProcess)
    {
    public int updateApsStandardProcess(ApsStandardProcess apsStandardProcess) {
        apsStandardProcess.setUpdateTime(DateUtils.getNowDate());
        apsStandardProcess.setUpdateBy(SecurityUtils.getUsername());
        return apsStandardProcessMapper.updateApsStandardProcess(apsStandardProcess);
@@ -76,30 +80,29 @@
    /**
     * æ‰¹é‡åˆ é™¤æ ‡å‡†å·¥åº
     *
     *
     * @param ids éœ€è¦åˆ é™¤çš„æ ‡å‡†å·¥åºä¸»é”®
     * @return ç»“æžœ
     */
    @Override
    public int deleteApsStandardProcessByIds(Long[] ids)
    {
    public int deleteApsStandardProcessByIds(Long[] ids) {
        return apsStandardProcessMapper.deleteApsStandardProcessByIds(ids);
    }
    /**
     * åˆ é™¤æ ‡å‡†å·¥åºä¿¡æ¯
     *
     *
     * @param id æ ‡å‡†å·¥åºä¸»é”®
     * @return ç»“æžœ
     */
    @Override
    public int deleteApsStandardProcessById(Long id)
    {
    public int deleteApsStandardProcessById(Long id) {
        return apsStandardProcessMapper.deleteApsStandardProcessById(id);
    }
    /**
     * å¯¼å…¥æ•°æ®
     *
     * @param tempList
     * @return true/false
     */
@@ -107,11 +110,26 @@
    public boolean importData(List<ApsStandardProcess> tempList) {
        try {
            if (!tempList.isEmpty()) {
                tempList.forEach(temp->{
                DictUtils.CacheValue cacheFactory = DictUtils.getCacheValue("aps_factory");
                DictUtils.CacheValue cacheDomain = DictUtils.getCacheValue("aps_domain");
                List<ApsShop> shops = apsShopMapper.selectApsByName(tempList.stream()
                        .map(ApsStandardProcess::getWorkShop)
                        .filter(StringUtils::isNotEmpty)
                        .collect(Collectors.toSet()));
                tempList.forEach(temp -> {
                    temp.setCreateBy(SecurityUtils.getUsername());
                    temp.setCreateTime(DateUtils.getNowDate());
                    apsStandardProcessMapper.insertApsStandardProcess(temp);
                    temp.setMajor(cacheDomain.get(temp.getMajor()));
                    temp.setPlant(cacheFactory.get(temp.getPlant()));
                    temp.setWorkShop(shops.stream()
                            .filter(shop -> Objects.equals(shop.getShopName(), temp.getWorkShop()))
                            .filter(shop -> Objects.equals(shop.getPlantCode(), temp.getPlant()))
                            .map(ApsShop::getShopCode)
                            .findFirst()
                            .orElse(null));
                });
                apsStandardProcessMapper.insert(tempList);
            }
        } catch (Exception e) {
            e.printStackTrace();
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsWorkCalendarServiceImpl.java
@@ -177,7 +177,7 @@
                //休息日
                org.postgresql.util.PGobject pgObjectHolidays = (org.postgresql.util.PGobject) apsWorkCalendarTemp.getHolidays();
                if(pgObjectHolidays!=null){
                    JSONArray holidays = (JSON.parseObject(pgObjectHolidays.getValue())).getJSONArray("holidays");
                    JSONArray holidays = JSONArray.parse(pgObjectHolidays.getValue());
                    for (int i = 0; i < holidays.size(); i++){
                        JSONObject h = holidays.getJSONObject(i);
                        List<LocalDate> datesTempHolidays = getDatesBetween(h.getObject("startdate", LocalDate.class), h.getObject("enddate", LocalDate.class));
aps-modules/aps-core/src/main/java/com/aps/core/service/mainPlan/IApsWeldSeamStatisticsV2Service.java
@@ -1,6 +1,9 @@
package com.aps.core.service.mainPlan;
import com.aps.core.domain.mainPlan.ApsWeldSeamStatisticsV2;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
@@ -32,4 +35,6 @@
     * @return å—影响的记录数
     */
    public int refreshWeldSeamStatistics(String username);
}
    void exportWeldSeamStatistics(HttpServletResponse response) throws IOException;
}
aps-modules/aps-core/src/main/java/com/aps/core/service/mainPlan/impl/ApsWeldSeamStatisticsV2ServiceImpl.java
@@ -1,22 +1,36 @@
package com.aps.core.service.mainPlan.impl;
import com.aps.common.core.annotation.Excel;
import com.aps.common.core.utils.DateUtils;
import com.aps.common.core.utils.poi.ExcelUtil;
import com.aps.common.core.utils.uuid.IdUtils;
import com.aps.common.core.web.page.TableDataInfo;
import com.aps.common.security.utils.DictUtils;
import com.aps.common.security.utils.SecurityUtils;
import com.aps.core.controller.basicData.ApsGasPipelineCapacityPlanController;
import com.aps.core.domain.ApsGasPipelineCapacityPlan;
import com.aps.core.domain.mainPlan.ApsWeldSeamStatisticsV2;
import com.aps.core.mapper.mainPlan.ApsWeldSeamStatisticsV2Mapper;
import com.aps.core.service.IApsGasPipelineCapacityPlanService;
import com.aps.core.service.mainPlan.IApsWeldSeamStatisticsV2Service;
import com.aps.system.api.domain.SysDictData;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.util.CellRangeAddress;
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 org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * ç„Šç¼ç»Ÿè®¡è¡¨V2Service业务层处理
@@ -203,4 +217,118 @@
        
        return count;
    }
    @Override
    public void exportWeldSeamStatistics(HttpServletResponse response) throws IOException {
        //1. èŽ·å–æ•°æ®æº
        List<ApsWeldSeamStatisticsV2> list = apsWeldSeamStatisticsV2Mapper.selectApsWeldSeamStatisticsV2List(new ApsWeldSeamStatisticsV2());
        List<SysDictData> isRequireDic = DictUtils.getDictCache("aps_task_is_require");
        List<SysDictData> factoryDic = DictUtils.getDictCache("aps_factory");
        //2. åˆ›å»ºExcel工作簿
        SXSSFWorkbook wb = new SXSSFWorkbook(500);
        CellStyle titleStyle = ExcelUtil.getCommonHeaderStyle(wb);
        CellStyle dataStyle =ExcelUtil.getDataCellStyle(wb);
        SXSSFSheet sheet = wb.createSheet("焊缝统计表");
        List<LinkedHashMap<String,String>> titleList=  initRowTitle();
        //3. æž„建表头
        for (int i = 0; i < titleList.size(); i++) {
            SXSSFRow titleRow = sheet.createRow(i);
            LinkedHashMap<String, String> map = titleList.get(i);
            AtomicInteger index = new AtomicInteger();
            titleList.get(i).forEach((key,value)->{
                SXSSFCell cell = titleRow.createCell(index.get());
                cell.setCellValue(value);
                cell.setCellStyle(titleStyle);
                index.getAndIncrement();
            });
        }
        //5. æž„建数据行
        LinkedHashMap<String, String> first = titleList.get(0);
        ArrayList<Map.Entry<String, String>> titles = new ArrayList<>(first.entrySet());
        for (int rowInx = 0; rowInx < list.size(); rowInx++) {
            SXSSFRow dataRow = sheet.createRow(rowInx + 2);
            ApsWeldSeamStatisticsV2 statistics = list.get(rowInx);
            ObjectMapper mapper = new ObjectMapper();
            ObjectNode node = mapper.valueToTree(statistics);
            for (int colInx = 0; colInx < titles.size(); colInx++) {
                Map.Entry<String, String> entry = titles.get(colInx);
                String filedKey = entry.getKey();
                SXSSFCell cell = dataRow.createCell(colInx);
                JsonNode jsonNode = node.get(filedKey);
                if(filedKey.equals("productionBase")){
                    factoryDic.stream().filter(x->x.getDictValue().equals(jsonNode.textValue())).findFirst().ifPresent(
                            sysDictData -> cell.setCellValue(sysDictData.getDictLabel())
                    );
                }else if(filedKey.equals("isSatisfy")){
                    isRequireDic.stream().filter(x->x.getDictValue().equals(jsonNode.textValue())).findFirst().ifPresent(
                            sysDictData -> cell.setCellValue(sysDictData.getDictLabel())
                    );
                }else{
                    cell.setCellValue(jsonNode.longValue());
                }
                cell.setCellStyle(dataStyle);
            }
        }
        for (int i = 0; i <  sheet.getRow(0).getLastCellNum(); i++) {
            sheet.setColumnWidth(i, 20 * 256);
        }
        //4.合并表头
        sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 0));
        sheet.addMergedRegion(new CellRangeAddress(0, 1, 1, 1));
        sheet.addMergedRegion(new CellRangeAddress(0, 1, 2, 2));
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 3, 4));
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 5, 6));
        sheet.addMergedRegion(new CellRangeAddress(0, 1, 7, 7));
        sheet.addMergedRegion(new CellRangeAddress(0, 1, 8, 8));
        sheet.addMergedRegion(new CellRangeAddress(0, 1, 9, 9));
        sheet.addMergedRegion(new CellRangeAddress(0, 1, 10, 10));
        sheet.addMergedRegion(new CellRangeAddress(0, 1, 11, 11));
        sheet.addMergedRegion(new CellRangeAddress(0, 1, 12, 12));
        //3. è®¾ç½®å“åº”头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        wb.write(response.getOutputStream());
    }
    private  List<LinkedHashMap<String,String>>  initRowTitle(){
        List<LinkedHashMap<String,String>> list = new ArrayList<>();
        LinkedHashMap<String,String> level1 = new LinkedHashMap<>();
        level1.put("year","年份");
        level1.put("month","月份");
        level1.put("productionBase","生产基地");
        level1.put("pipingOrderRequirement","订单需求");
        level1.put("gasOrderRequirement","订单需求");
        level1.put("pipingPredictionRequirement","预测需求");
        level1.put("gasPredictionRequirement","预测需求");
        level1.put("reserveEmergencyOrderOutput","预留紧急订单产出");
        level1.put("total","合计");
        level1.put("days","天数");
        level1.put("requirementDayWeldSeam","需求日焊缝");
        level1.put("productionDayWeldSeam","生产日焊缝");
        level1.put("isSatisfy","是否满足");
        list.add(level1);
        LinkedHashMap<String,String> level2 = new LinkedHashMap<>();
        level2.put("year","年份");
        level2.put("month","月份");
        level2.put("productionBase","生产基地");
        level2.put("pipingOrderRequirement","管路");
        level2.put("gasOrderRequirement","气柜");
        level2.put("pipingPredictionRequirement","管路");
        level2.put("gasPredictionRequirement","气柜");
        level2.put("reserveEmergencyOrderOutput","预留紧急订单产出");
        level2.put("total","合计");
        level2.put("days","天数");
        level2.put("requirementDayWeldSeam","需求日焊缝");
        level2.put("productionDayWeldSeam","生产日焊缝");
        level2.put("isSatisfy","是否满足");
        list.add(level2);
        return list;
    }
aps-modules/aps-core/src/main/resources/mapper/core/ApsBomHeaderMapper.xml
@@ -109,13 +109,10 @@
        LEFT JOIN aps_bom_line b on a.bom_header_id=b.bom_header_id
        LEFT JOIN aps_material_management d on b.item_code=d.item_number
        LEFT JOIN aps_material_management c on a.item_code=c.item_number
        <where>
            <if test="orgCode != null and orgCode != ''">
                and a.org_code=#{orgCode} and d.applicable_factories=#{orgCode}
            </if>
            and d.material_type='制造件'
            and c.material_type='制造件'
        </where>
        where   d.material_type='制造件' and c.material_type='制造件'
        <if test="orgCode != null and orgCode != ''">
            and a.org_code=#{orgCode} and d.applicable_factories=#{orgCode}
        </if>
        ORDER BY mainItemCode
    </select>
</mapper>
aps-modules/aps-core/src/main/resources/mapper/core/ApsGasPipelineCapacityPlanMapper.xml
@@ -10,6 +10,7 @@
        <result property="year"    column="year"    />
        <result property="month"    column="month"    />
        <result property="major"    column="major"    />
        <result property="workshop"    column="workshop"    />
        <result property="dayProduceType"    column="day_produce_type"    />
        <result property="dayProduceNum"    column="day_produce_num"    />
        <result property="dayProduceUnit"    column="day_produce_unit"    />
@@ -26,7 +27,7 @@
    </resultMap>
    <sql id="selectApsGasPipelineCapacityPlanVo">
        select id, process_name, year, month, major, day_produce_type, day_produce_num, day_produce_unit, personnel_number, day_produce_all_num, days, month_produce_all_num, remark, create_by, create_time, update_by, update_time, org_code from aps_gas_pipeline_capacity_plan
        select id, process_name, year, month, major, workshop, day_produce_type, day_produce_num, day_produce_unit, personnel_number, day_produce_all_num, days, month_produce_all_num, remark, create_by, create_time, update_by, update_time, org_code from aps_gas_pipeline_capacity_plan
    </sql>
    <select id="selectApsGasPipelineCapacityPlanList" parameterType="com.aps.core.domain.ApsGasPipelineCapacityPlan" resultMap="ApsGasPipelineCapacityPlanResult">
@@ -36,6 +37,7 @@
            <if test="year != null  and year != ''"> and year = #{year}</if>
            <if test="month != null  and month != ''"> and month = #{month}</if>
            <if test="major != null  and major != ''"> and major = #{major}</if>
            <if test="workshop != null  and workshop != ''"> and workshop = #{workshop}</if>
            <if test="dayProduceType != null  and dayProduceType != ''"> and day_produce_type = #{dayProduceType}</if>
            <if test="dayProduceNum != null "> and day_produce_num = #{dayProduceNum}</if>
            <if test="dayProduceUnit != null  and dayProduceUnit != ''"> and day_produce_unit = #{dayProduceUnit}</if>
@@ -63,6 +65,7 @@
            <if test="year != null">year,</if>
            <if test="month != null">month,</if>
            <if test="major != null">major,</if>
            <if test="workshop != null">workshop,</if>
            <if test="dayProduceType != null">day_produce_type,</if>
            <if test="dayProduceNum != null">day_produce_num,</if>
            <if test="dayProduceUnit != null">day_produce_unit,</if>
@@ -83,6 +86,7 @@
            <if test="year != null">#{year},</if>
            <if test="month != null">#{month},</if>
            <if test="major != null">#{major},</if>
            <if test="workshop != null">workshop,</if>
            <if test="dayProduceType != null">#{dayProduceType},</if>
            <if test="dayProduceNum != null">#{dayProduceNum},</if>
            <if test="dayProduceUnit != null">#{dayProduceUnit},</if>
@@ -106,6 +110,7 @@
            <if test="year != null">year = #{year},</if>
            <if test="month != null">month = #{month},</if>
            <if test="major != null">major = #{major},</if>
            <if test="workshop != null">workshop,</if>
            <if test="dayProduceType != null">day_produce_type = #{dayProduceType},</if>
            <if test="dayProduceNum != null">day_produce_num = #{dayProduceNum},</if>
            <if test="dayProduceUnit != null">day_produce_unit = #{dayProduceUnit},</if>
@@ -133,4 +138,34 @@
            #{id}
        </foreach>
    </delete>
    <delete id="deleteByDateAndFactory" >
        delete from aps_gas_pipeline_capacity_plan
               where year = #{year}
                   and month = #{month}
                   and org_code = #{factory}
                   and major = #{major}
    </delete>
    <!-- æŸ¥è¯¢è®¾è®¡äº§èƒ½æ•°æ® - ä¸“用于接口二功能 -->
    <select id="selectDesignCapacityForInterface2" resultMap="ApsGasPipelineCapacityPlanResult">
        <include refid="selectApsGasPipelineCapacityPlanVo"/>
        <where>
            <if test="processName != null and processName != ''">
                and process_name = #{processName}
            </if>
            <if test="year != null and year != ''">
                and year = #{year}
            </if>
            <if test="month != null and month != ''">
                and CAST(month AS INTEGER) = CAST(#{month} AS INTEGER)
            </if>
            <if test="major != null and major != ''">
                and major = #{major}
            </if>
            <if test="orgCode != null and orgCode != ''">
                and org_code = #{orgCode}
            </if>
        </where>
    </select>
</mapper>
aps-modules/aps-core/src/main/resources/mapper/core/ApsGasPipingRouteStatMapper.xml
@@ -28,8 +28,10 @@
        <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"    />
        <result property="plant"    column="plant"    />
        <result property="workshop"    column="workshop"    />
        <result property="batchNumber"    column="batch_number"    />
    </resultMap>
    <sql id="selectApsGasPipingRouteStatVo">
@@ -38,27 +40,27 @@
               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, plant
               plan_start_month, plan_start_day, process_plan_end_day, order_plan_end_day,
               warning, plant, workshop, batch_number
        from aps_gas_piping_route_stat
    </sql>
    <select id="selectApsGasPipingRouteStatList" parameterType="com.aps.core.domain.ApsGasPipingRouteStat" resultMap="ApsGasPipingRouteStatResult">
        <include refid="selectApsGasPipingRouteStatVo"/>
        <where>
        <where>
            <if test="workOrderNo != null  and workOrderNo != ''"> and work_order_no = #{workOrderNo}</if>
            <if test="roadProcessNumber != null  and roadProcessNumber != ''"> and road_process_number = #{roadProcessNumber}</if>
            <if test="currentProcessNumber != null  and currentProcessNumber != ''"> and current_process_number = #{currentProcessNumber}</if>
            <if test="productionQuantity != null  and productionQuantity != ''"> and production_quantity = #{productionQuantity}</if>
            <if test="standardTime != null  and standardTime != ''"> and standard_time = #{standardTime}</if>
            <if test="processTotalTime != null  and processTotalTime != ''"> and process_total_time = #{processTotalTime}</if>
            <if test="processPlanStartDay != null  and processPlanStartDay != ''"> and process_plan_start_day = #{processPlanStartDay}</if>
            <if test="roadProcessNumber != null "> and road_process_number = #{roadProcessNumber}</if>
            <if test="currentProcessNumber != null "> and current_process_number = #{currentProcessNumber}</if>
            <if test="productionQuantity != null "> and production_quantity = #{productionQuantity}</if>
            <if test="standardTime != null "> and standard_time = #{standardTime}</if>
            <if test="processTotalTime != null "> and process_total_time = #{processTotalTime}</if>
            <if test="processPlanStartDay != null "> and process_plan_start_day = #{processPlanStartDay}</if>
            <if test="designTimes != null "> and design_times = #{designTimes}</if>
            <if test="processName != null  and processName != ''"> and process_name like '%' || #{processName} || '%')</if>
            <if test="major != null and major != ''"> and major = #{major} </if>
            <if test="planStartYear != null and planStartYear != ''"> and plan_start_year = #{planStartYear} </if>
            <if test="planStartMonth != null and planStartMonth != ''"> and plan_start_month = #{planStartMonth} </if>
            <if test="planStartDay != null and planStartDay != ''"> and plan_start_day = #{planStartDay} </if>
            <if test="searchStartDate != null and searchStartDate != '' and searchEndDate != null and searchEndDate != ''"> and (process_plan_start_day &gt;= #{searchStartDate} and process_plan_start_day &lt;= #{searchEndDate}) </if>
            <if test="processName != null  and processName != ''"> and process_name = #{processName}</if>
            <if test="itemNumber != null  and itemNumber != ''"> and item_number = #{itemNumber}</if>
            <if test="standardDosage != null "> and standard_dosage = #{standardDosage}</if>
            <if test="processTotalDosage != null "> and process_total_dosage = #{processTotalDosage}</if>
            <if test="designCapacity != null "> and design_capacity = #{designCapacity}</if>
            <if test="major != null and major != ''">
                <if test="major == 'piping'">
                    and process_name in (select process_name from aps_standard_process where major='管路')
@@ -66,8 +68,19 @@
                <if test="major == 'gas'">
                    and process_name in (select process_name from aps_standard_process where major='气柜')
                </if>
                <if test="major != 'piping' and major != 'gas'">
                    and major = #{major}
                </if>
            </if>
            <if test="plant != null and plant != ''"> and plant = #{plant} </if>
            <if test="planStartYear != null  and planStartYear != ''"> and plan_start_year = #{planStartYear}</if>
            <if test="planStartMonth != null  and planStartMonth != ''"> and plan_start_month = #{planStartMonth}</if>
            <if test="planStartDay != null  and planStartDay != ''"> and plan_start_day = #{planStartDay}</if>
            <if test="processPlanEndDay != null "> and process_plan_end_day = #{processPlanEndDay}</if>
            <if test="orderPlanEndDay != null "> and order_plan_end_day = #{orderPlanEndDay}</if>
            <if test="warning != null "> and warning = #{warning}</if>
            <if test="plant != null and plant != ''"> and plant = #{plant}</if>
            <if test="workshop != null and workshop != ''"> and workshop = #{workshop}</if>
            <if test="batchNumber != null and batchNumber != ''"> and batch_number = #{batchNumber}</if>
        </where>
    </select>
    
@@ -81,12 +94,12 @@
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">id,</if>
            <if test="workOrderNo != null">work_order_no,</if>
            <if test="roadProcessNumber != null and roadProcessNumber != ''">road_process_number,</if>
            <if test="roadProcessNumber != null">road_process_number,</if>
            <if test="currentProcessNumber != null">current_process_number,</if>
            <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 ">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>
@@ -102,18 +115,20 @@
            <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>
            <if test="plant != null">plant,</if>
            <if test="workshop != null">workshop,</if>
            <if test="batchNumber != null">batch_number,</if>
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="id != null">#{id},</if>
            <if test="workOrderNo != null">#{workOrderNo},</if>
            <if test="roadProcessNumber != null and roadProcessNumber != ''">#{roadProcessNumber},</if>
            <if test="roadProcessNumber != null">#{roadProcessNumber},</if>
            <if test="currentProcessNumber != null">#{currentProcessNumber},</if>
            <if test="productionQuantity != null">#{productionQuantity},</if>
            <if test="standardTime != null">#{standardTime},</if>
            <if test="processTotalTime != null">#{processTotalTime},</if>
            <if test="processPlanStartDay != null ">#{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>
@@ -129,8 +144,10 @@
            <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>
            <if test="plant != null">#{plant},</if>
            <if test="workshop != null">#{workshop},</if>
            <if test="batchNumber != null">#{batchNumber},</if>
         </trim>
    </insert>
@@ -138,12 +155,12 @@
        update aps_gas_piping_route_stat
        <trim prefix="SET" suffixOverrides=",">
            <if test="workOrderNo != null">work_order_no = #{workOrderNo},</if>
            <if test="roadProcessNumber != null and roadProcessNumber != ''">road_process_number = #{roadProcessNumber},</if>
            <if test="roadProcessNumber != null">road_process_number = #{roadProcessNumber},</if>
            <if test="currentProcessNumber != null">current_process_number = #{currentProcessNumber},</if>
            <if test="productionQuantity != null">production_quantity = #{productionQuantity},</if>
            <if test="standardTime != null">standard_time = #{standardTime},</if>
            <if test="processTotalTime != null">process_total_time = #{processTotalTime},</if>
            <if test="processPlanStartDay != null and processPlanStartDay != ''">process_plan_start_day = #{processPlanStartDay},</if>
            <if test="processPlanStartDay != null">process_plan_start_day = #{processPlanStartDay},</if>
            <if test="designTimes != null">design_times = #{designTimes},</if>
            <if test="delFlag != null">del_flag = #{delFlag},</if>
            <if test="createBy != null">create_by = #{createBy},</if>
@@ -157,6 +174,12 @@
            <if test="planStartYear != null">plan_start_year = #{planStartYear},</if>
            <if test="planStartMonth != null">plan_start_month = #{planStartMonth},</if>
            <if test="planStartDay != null">plan_start_day = #{planStartDay},</if>
            <if test="processPlanEndDay != null">process_plan_end_day = #{processPlanEndDay},</if>
            <if test="orderPlanEndDay != null">order_plan_end_day = #{orderPlanEndDay},</if>
            <if test="warning != null">warning = #{warning},</if>
            <if test="plant != null">plant = #{plant},</if>
            <if test="workshop != null">workshop = #{workshop},</if>
            <if test="batchNumber != null">batch_number = #{batchNumber},</if>
        </trim>
        where id = #{id}
    </update>
@@ -171,31 +194,37 @@
            #{id}
        </foreach>
    </delete>
    <delete id="deleteApsGasPipingRouteStatByBatchNum" parameterType="String">
        delete from aps_gas_piping_route_stat where batch_number != #{batchNumber}
    </delete>
    <insert id="insertApsGasPipingRouteStatBatch">
        INSERT INTO aps_gas_piping_route_stat
        (
        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,warning,order_plan_end_day,plant
        )
        VALUES
        <foreach collection="apsGasPipingRouteStatList" item="stat" separator=",">
    <insert id="insertApsGasPipingRouteStatBatch" parameterType="java.util.List">
        insert into aps_gas_piping_route_stat (
            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, process_plan_end_day, order_plan_end_day,
            warning, plant, workshop, batch_number
        ) values
        <foreach item="item" index="index" collection="list" separator=",">
            (
            #{stat.id},#{stat.workOrderNo}, #{stat.roadProcessNumber}, #{stat.currentProcessNumber}, #{stat.productionQuantity},
            #{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.warning},#{stat.orderPlanEndDay},#{stat.plant}
                #{item.id}, #{item.workOrderNo}, #{item.roadProcessNumber}, #{item.currentProcessNumber},
                #{item.productionQuantity}, #{item.standardTime}, #{item.processTotalTime},
                #{item.processPlanStartDay}, #{item.designTimes}, #{item.delFlag}, #{item.createBy},
                #{item.processName}, #{item.createTime}, #{item.itemNumber}, #{item.standardDosage},
                #{item.processTotalDosage}, #{item.designCapacity}, #{item.major}, #{item.planStartYear},
                #{item.planStartMonth}, #{item.planStartDay}, #{item.processPlanEndDay}, #{item.orderPlanEndDay},
                #{item.warning}, #{item.plant}, #{item.workshop}, #{item.batchNumber}
            )
        </foreach>
    </insert>
    <delete id="deleteAll">
        delete from aps_gas_piping_route_stat
    </delete>
    <select id="queryTempStat"  resultMap="ApsGasPipingRouteStatResult" >
        select row_number() over (partition by rt.work_order_no order by rt.process_number desc ) as num,
@@ -219,5 +248,218 @@
        where pl.document_number is not null and rt.work_order_no is not null and pl.plan_end_day is not null
        order by rt.work_order_no asc, rt.process_number desc
    </select>
    <!-- è”合查询手工气体预测数据相关信息 -->
    <select id="selectPredictionRouteData" resultType="java.util.Map">
        SELECT
            p.id as prediction_id,
            p.material_code,
            p.factory,
            p.predict_quantity,
            p.predict_date,
            h.route_id,
            l.route_name as process_name,
            l.route_num as process_number,
            l.standard_time,
            string_agg(DISTINCT m.domain, ';') as domain,
            string_agg(DISTINCT s.work_shop, ';') as workshop
        FROM aps_gas_pipeline_prediction p
        JOIN aps_standard_process_route_header h ON p.material_code = h.item_code AND p.factory = h.org_code
        JOIN aps_standard_process_route_line l ON h.route_id = l.route_id
        LEFT JOIN aps_material_product_group_management m ON p.material_code = m.material_code AND p.factory = m.factory
        LEFT JOIN aps_standard_process s ON l.route_name = s.process_name
        GROUP BY p.id, p.material_code, p.factory, p.predict_quantity, p.predict_date, h.route_id, l.route_name, l.route_num, l.standard_time
        ORDER BY p.material_code, l.route_num
    </select>
    <!-- è”合查询手工气体工单数据相关信息 -->
    <select id="selectMoRouteData" resultType="java.util.Map">
        SELECT
            mo.id as mo_id,
            mo.mo as work_order_no,
            mo.material_code,
            mo.factory,
            mo.quantity,
            mo.plan_end,
            r.process_name,
            r.process_number,
            r.standard_time,
            string_agg(DISTINCT m.domain, ';') as domain,
            string_agg(DISTINCT s.work_shop, ';') as workshop
        FROM aps_gas_pipeline_mo mo
        JOIN aps_process_route r ON mo.mo = r.work_order_no
        LEFT JOIN aps_material_product_group_management m ON mo.material_code = m.material_code AND mo.factory = m.factory
        LEFT JOIN aps_standard_process s ON r.process_name = s.process_name
        GROUP BY mo.id, mo.mo, mo.material_code, mo.factory, mo.quantity, mo.plan_end, r.process_name, r.process_number, r.standard_time
        ORDER BY mo.mo, r.process_number
    </select>
    <!-- èšåˆæŸ¥è¯¢ç»Ÿè®¡æ•°æ® - æŒ‰å·¥åºåç§°å’Œæ—¶é—´èšåˆ -->
    <select id="selectAggregatedStatData" parameterType="java.util.Map" resultType="java.util.Map">
        SELECT
            process_name AS "processName",
            plan_start_year AS "year",
            plan_start_month AS "month",
            <choose>
                <when test="timeGranularity != null and timeGranularity == 'day'">
                    plan_start_day AS "day"
                </when>
                <otherwise>
                    '01' AS "day"
                </otherwise>
            </choose>,
            plant AS "plant",
            major AS "major",
            workshop AS "workshop",
            SUM(process_total_time) AS "totalProcessTime"
        FROM aps_gas_piping_route_stat
        <where>
            <if test="yearStart != null and monthStart != null">
                (plan_start_year > #{yearStart} OR
                 (plan_start_year = #{yearStart} AND plan_start_month >= #{monthStart}))
                AND
                (plan_start_year &lt; #{yearEnd} OR
                 (plan_start_year = #{yearEnd} AND plan_start_month &lt;= #{monthEnd}))
            </if>
            <if test="plant != null and plant != ''">
                AND plant = #{plant}
            </if>
            <if test="major != null and major != ''">
                AND major = #{major}
            </if>
            <if test="workshop != null and workshop != ''">
                AND workshop = #{workshop}
            </if>
        </where>
        GROUP BY
            process_name,
            plan_start_year,
            plan_start_month
            <if test="timeGranularity != null and timeGranularity == 'day'">
                , plan_start_day
            </if>,
            plant,
            major,
            workshop
        ORDER BY
            process_name,
            plan_start_year,
            plan_start_month
            <if test="timeGranularity != null and timeGranularity == 'day'">
                , plan_start_day
            </if>
    </select>
    <!-- æŸ¥è¯¢åŽŸå§‹ç»Ÿè®¡æ•°æ®ï¼ˆä¸è¿›è¡Œèšåˆï¼‰- ç”¨äºŽåœ¨Service层自行处理聚合逻辑 -->
    <select id="selectRawStatData" parameterType="java.util.Map" resultType="java.util.Map">
        SELECT
            process_name AS "processName",
            process_plan_start_day AS "processPlanStartDay",
            plant AS "plant",
            major AS "major",
            workshop AS "workshop",
            process_total_time AS "processTotalTime"
        FROM aps_gas_piping_route_stat
        <where>
            <if test="yearStart != null and monthStart != null">
                (EXTRACT(YEAR FROM process_plan_start_day) > #{yearStart} OR
                 (EXTRACT(YEAR FROM process_plan_start_day) = #{yearStart} AND EXTRACT(MONTH FROM process_plan_start_day) >= #{monthStart}))
                AND
                (EXTRACT(YEAR FROM process_plan_start_day) &lt; #{yearEnd} OR
                 (EXTRACT(YEAR FROM process_plan_start_day) = #{yearEnd} AND EXTRACT(MONTH FROM process_plan_start_day) &lt;= #{monthEnd}))
            </if>
            <if test="plants != null and plants.size() > 0">
                AND plant IN
                <foreach collection="plants" item="item" open="(" separator="," close=")">
                    #{item}
                </foreach>
            </if>
            <if test="plant != null and plant != ''">
                AND plant = #{plant}
            </if>
            <if test="majors != null and majors.size() > 0">
                AND major IN
                <foreach collection="majors" item="item" open="(" separator="," close=")">
                    #{item}
                </foreach>
            </if>
            <if test="major != null and major != ''">
                AND major = #{major}
            </if>
            <if test="workshops != null and workshops.size() > 0">
                AND workshop IN
                <foreach collection="workshops" item="item" open="(" separator="," close=")">
                    #{item}
                </foreach>
            </if>
            <if test="workshop != null and workshop != ''">
                AND workshop = #{workshop}
            </if>
        </where>
        ORDER BY
            process_name,
            process_plan_start_day
    </select>
    <!-- æŸ¥è¯¢æ‰€æœ‰æ‰‹å·¥æ°”体工单数据 -->
    <select id="selectAllMoData" resultType="java.util.Map">
        SELECT
            id,
            mo,
            factory,
            material_code,
            plan_end,
            quantity
        FROM aps_gas_pipeline_mo
    </select>
    <!-- æŸ¥è¯¢åŸºç¡€ç»Ÿè®¡æ•°æ®ï¼ˆä¸åŒ…含时间限制),用于获取所有可能的工序名和车间 -->
    <select id="selectBaseStatData" parameterType="java.util.Map" resultType="java.util.Map">
        SELECT DISTINCT
            process_name AS "processName",
            plant AS "plant",
            major AS "major",
            workshop AS "workshop"
        FROM aps_gas_piping_route_stat
        <where>
            <if test="plants != null and plants.size() > 0">
                AND plant IN
                <foreach collection="plants" item="item" open="(" separator="," close=")">
                    #{item}
                </foreach>
            </if>
            <if test="plant != null and plant != ''">
                AND plant = #{plant}
            </if>
            <if test="majors != null and majors.size() > 0">
                AND major IN
                <foreach collection="majors" item="item" open="(" separator="," close=")">
                    #{item}
                </foreach>
            </if>
            <if test="major != null and major != ''">
                AND major = #{major}
            </if>
            <if test="workshops != null and workshops.size() > 0">
                AND workshop IN
                <foreach collection="workshops" item="item" open="(" separator="," close=")">
                    #{item}
                </foreach>
            </if>
            <if test="workshop != null and workshop != ''">
                AND workshop = #{workshop}
            </if>
        </where>
    </select>
    <!-- æŸ¥è¯¢æ‰€æœ‰åŽ»é‡çš„å·¥åºåç§° -->
    <select id="selectDistinctProcessNames" resultType="java.lang.String">
        SELECT DISTINCT process_name FROM aps_gas_piping_route_stat WHERE process_name IS NOT NULL AND process_name != ''
    </select>
    <!-- æŸ¥è¯¢æ‰€æœ‰åŽ»é‡çš„è½¦é—´ -->
    <select id="selectDistinctWorkshops" resultType="java.lang.String">
        SELECT DISTINCT workshop FROM aps_gas_piping_route_stat WHERE workshop IS NOT NULL AND workshop != ''
    </select>
</mapper>
aps-modules/aps-core/src/main/resources/mapper/core/ApsPlate/ApsPlateProcessShopStatMapper.xml
@@ -141,9 +141,16 @@
                     left join aps_process_route as pr on ap.document_number=pr.work_order_no
            where cast(pr.process_number as numeric) > cast(ap.process_number as numeric)
            group by ap.document_number
        ),
        b as (
            select app.doc_no, string_agg(  app.require_track_id  ,',') as require_track_id
            from aps_plate_standard_require_bom_order_detail as  app
            where del_flag='0'
            group by app.doc_no
        )
        select
            app.id,
            b.require_track_id,
            app.main_part_number,
            app.customer,
            app.business_type,
@@ -168,6 +175,7 @@
            a.remained_process
        from aps_plate_plan as app
                 left join a on app.document_number=a.document_number
                 left join  b on app.document_number=b.doc_no
        where app.del_flag='0';
    </select>
</mapper>
aps-modules/aps-core/src/main/resources/mapper/core/ApsPlate/ApsPlateProcessStatMapper.xml
@@ -160,7 +160,9 @@
    <update id="removeOtherStat" parameterType="String">
        delete from aps_plate_process_stat where batch_number != #{batchNumber}
    </update>
    <update id="deleteAll" parameterType="String">
        delete from aps_plate_process_stat
    </update>
    <insert id="batchInsertPlateStat" parameterType="com.aps.core.domain.ApsPlate.ApsPlateProcessStat">
        insert into aps_plate_process_stat
        (
@@ -173,10 +175,13 @@
            production_quantity,
            standard_time,
            process_total_time,
            process_plan_start_day,
            process_plan_end_day,
            order_plan_end_day,
            batch_number,
            create_by,
            del_flag
            del_flag,
            warning
        )
        values
        <foreach collection="list" item="item" index="index" separator=",">
@@ -190,10 +195,13 @@
            #{item.productionQuantity},
            #{item.standardTime},
            #{item.processTotalTime},
            #{item.processPlanStartDay},
            #{item.processPlanEndDay},
            #{item.orderPlanEndDay},
            #{item.batchNumber},
            #{item.createBy},
            '0'
            '0',
            #{item.warning}
        )
        </foreach>
    </insert>
aps-modules/aps-core/src/main/resources/mapper/core/ApsPlate/ApsPlateStandardRequireBomOrderDetailMapper.xml
@@ -127,7 +127,7 @@
    </delete>
    <update id="deleteLastPatch" parameterType="String">
        update aps_plate_standard_require_bom_order_detail set del_flag = '1' where batch_number = #{batchNumber}
        update aps_plate_standard_require_bom_order_detail set del_flag = '1' where del_flag = '0' and batch_number != #{batchNumber}
    </update>
    <insert id="batchInsert" parameterType="com.aps.core.domain.ApsPlate.ApsPlateStandardRequireBomOrderDetail">
aps-modules/aps-core/src/main/resources/mapper/core/ApsPlate/ApsPlateStandardRequireBomStockDetailMapper.xml
@@ -120,7 +120,9 @@
    </delete>
    <update id="deleteLastPatch" parameterType="String">
        update aps_plate_standard_require_bom_stock_detail set del_flag = '1' where batch_number = #{batchNumber}
        update aps_plate_standard_require_bom_stock_detail
        set del_flag = '1'
        where del_flag = '0' and batch_number != #{batchNumber}
    </update>
    <insert id="batchInsert" parameterType="com.aps.core.domain.ApsPlate.ApsPlateStandardRequireBomStockDetail">
aps-modules/aps-core/src/main/resources/mapper/core/ApsPlate/ApsPlateStandardRequireErrorMapper.xml
@@ -103,6 +103,22 @@
        </foreach>
    </delete>
    <update id="deleteLastPatch" parameterType="String">
        update aps_plate_standard_require_error set del_flag = '1' where batch_number = #{batchNumber}
        update aps_plate_standard_require_error
        set del_flag = '1'
        where del_flag = '0' and batch_number != #{batchNumber}
    </update>
    <insert id="batchInsert" parameterType="java.util.List">
        insert into aps_plate_standard_require_error(
            id, batch_number, require_id, doc_num, item_num, org_code,
            message, del_flag, create_by, create_time
        ) values
        <foreach collection="list" item="item" separator=",">
            (
            #{item.id}, #{item.batchNumber}, #{item.requireId}, #{item.docNum},
            #{item.itemNum}, #{item.orgCode}, #{item.message}, #{item.delFlag},
            #{item.createBy}, #{item.createTime}
            )
        </foreach>
    </insert>
</mapper>
aps-modules/aps-core/src/main/resources/mapper/core/ApsPlate/ApsPlateStandardRequireMapper.xml
@@ -226,6 +226,6 @@
        </foreach>
    </insert>
    <update id="deleteLastPatch" parameterType="String">
        update aps_plate_standard_require set del_flag = '1' where batch_number = #{batchNumber}
        update aps_plate_standard_require set del_flag = '1' where del_flag = '0' and batch_number != #{batchNumber}
    </update>
</mapper>
aps-modules/aps-core/src/main/resources/mapper/core/ApsWeldSeamStatisticsV2Mapper.xml
@@ -153,95 +153,95 @@
    </insert>
    <select id="queryWeldSeamStatistics" resultMap="ApsWeldSeamStatisticsV2Result">
        WITH å·¥å•焊缝计算 AS (
        WITH order_weld_calc AS (
            -- è®¡ç®—工单的焊缝数量
            SELECT 
                mo.factory as ç”Ÿäº§åŸºåœ°,
                mo.material_code as æ–™å·,
                EXTRACT(YEAR FROM mo.plan_end) as å¹´ä»½,
                EXTRACT(MONTH FROM mo.plan_end) as æœˆä»½,
                mo.quantity * COALESCE(ws.hup_qty, 0) as å·¥å•焊缝数,
                mgm.domain as ä¸“业
                mo.factory as production_base,
                mo.material_code as material_no,
                EXTRACT(YEAR FROM mo.plan_end) as year,
                EXTRACT(MONTH FROM mo.plan_end) as month,
                mo.quantity * COALESCE(ws.hup_qty, 0) as order_weld_count,
                mgm.domain as domain
            FROM aps_gas_pipeline_mo mo
            LEFT JOIN aps_weld_seam_standard ws ON mo.material_code = ws.item_code AND ws.del_flag = 0
            LEFT JOIN aps_material_product_group_management mgm ON mo.material_code = mgm.material_code AND mo.factory = mgm.factory
        ),
        é¢„测焊缝计算 AS (
        predict_weld_calc AS (
            -- è®¡ç®—预测的焊缝数量
            SELECT 
                gp.factory as ç”Ÿäº§åŸºåœ°,
                gp.material_code as æ–™å·,
                EXTRACT(YEAR FROM gp.predict_date) as å¹´ä»½,
                EXTRACT(MONTH FROM gp.predict_date) as æœˆä»½,
                gp.predict_quantity * COALESCE(ws.hup_qty, 0) as é¢„测焊缝数,
                mgm.domain as ä¸“业
                gp.factory as production_base,
                gp.material_code as material_no,
                EXTRACT(YEAR FROM gp.predict_date) as year,
                EXTRACT(MONTH FROM gp.predict_date) as month,
                gp.predict_quantity * COALESCE(ws.hup_qty, 0) as predict_weld_count,
                mgm.domain as domain
            FROM aps_gas_pipeline_prediction gp
            LEFT JOIN aps_weld_seam_standard ws ON gp.material_code = ws.item_code AND ws.del_flag = 0
            LEFT JOIN aps_material_product_group_management mgm ON gp.material_code = mgm.material_code AND gp.factory = mgm.factory
        ),
        æ±‡æ€»æ•°æ® AS (
        summary_data AS (
            SELECT 
                å¹´ä»½,
                æœˆä»½,
                ç”Ÿäº§åŸºåœ°,
                year,
                month,
                production_base,
                -- ç®¡è·¯è®¢å•需求
                COALESCE(SUM(CASE 
                    WHEN ä¸“业 = 'GL' AND ç±»åž‹ = '工单'
                    THEN ç„Šç¼æ•° ELSE 0
                END), 0) as ç®¡è·¯è®¢å•需求,
                    WHEN domain = 'GL' AND type = 'order'
                    THEN weld_count ELSE 0
                END), 0) as piping_order_requirement,
                -- æ°”柜订单需求
                COALESCE(SUM(CASE 
                    WHEN ä¸“业 = 'QG' AND ç±»åž‹ = '工单'
                    THEN ç„Šç¼æ•° ELSE 0
                END), 0) as æ°”柜订单需求,
                    WHEN domain = 'QG' AND type = 'order'
                    THEN weld_count ELSE 0
                END), 0) as gas_order_requirement,
                -- ç®¡è·¯é¢„测需求
                COALESCE(SUM(CASE 
                    WHEN ä¸“业 = 'GL' AND ç±»åž‹ = '预测'
                    THEN ç„Šç¼æ•° ELSE 0
                END), 0) as ç®¡è·¯é¢„测需求,
                    WHEN domain = 'GL' AND type = 'predict'
                    THEN weld_count ELSE 0
                END), 0) as piping_predict_requirement,
                -- æ°”柜预测需求
                COALESCE(SUM(CASE 
                    WHEN ä¸“业 = 'QG' AND ç±»åž‹ = '预测'
                    THEN ç„Šç¼æ•° ELSE 0
                END), 0) as æ°”柜预测需求
                    WHEN domain = 'QG' AND type = 'predict'
                    THEN weld_count ELSE 0
                END), 0) as gas_predict_requirement
            FROM (
                SELECT 
                    å¹´ä»½,
                    æœˆä»½,
                    ç”Ÿäº§åŸºåœ°,
                    å·¥å•焊缝数 as ç„Šç¼æ•°,
                    '工单' as ç±»åž‹,
                    ä¸“业
                FROM å·¥å•焊缝计算
                    year,
                    month,
                    production_base,
                    order_weld_count as weld_count,
                    'order' as type,
                    domain
                FROM order_weld_calc
                UNION ALL
                SELECT 
                    å¹´ä»½,
                    æœˆä»½,
                    ç”Ÿäº§åŸºåœ°,
                    é¢„测焊缝数 as ç„Šç¼æ•°,
                    '预测' as ç±»åž‹,
                    ä¸“业
                FROM é¢„测焊缝计算
            ) åˆå¹¶æ•°æ®
            GROUP BY å¹´ä»½, æœˆä»½, ç”Ÿäº§åŸºåœ°
                    year,
                    month,
                    production_base,
                    predict_weld_count as weld_count,
                    'predict' as type,
                    domain
                FROM predict_weld_calc
            ) merged_data
            GROUP BY year, month, production_base
        )
        SELECT 
            s.年份 as "year",
            s.月份 as "month",
            s.生产基地 as "production_base",
            ROUND(s.管路订单需求, 4) as "piping_order_requirement",
            ROUND(s.气柜订单需求, 4) as "gas_order_requirement",
            ROUND(s.管路预测需求, 4) as "piping_prediction_requirement",
            ROUND(s.气柜预测需求, 4) as "gas_prediction_requirement",
            s.year as "year",
            s.month as "month",
            s.production_base as "production_base",
            ROUND(s.piping_order_requirement, 4) as "piping_order_requirement",
            ROUND(s.gas_order_requirement, 4) as "gas_order_requirement",
            ROUND(s.piping_predict_requirement, 4) as "piping_prediction_requirement",
            ROUND(s.gas_predict_requirement, 4) as "gas_prediction_requirement",
            0 as "reserve_emergency_order_output",
            ROUND(s.管路订单需求 + s.气柜订单需求 + s.管路预测需求 + s.气柜预测需求, 4) as "total",
            ROUND(s.piping_order_requirement + s.gas_order_requirement + s.piping_predict_requirement + s.gas_predict_requirement, 4) as "total",
            0 as "days",
            0 as "requirement_day_weld_seam",
            0 as "production_day_weld_seam",
            '0' as "is_satisfy",
            'system' as "create_by",
            CURRENT_TIMESTAMP as "create_time"
        FROM æ±‡æ€»æ•°æ® s
        ORDER BY s.年份, s.月份, s.生产基地
        FROM summary_data s
        ORDER BY s.year, s.month, s.production_base
    </select>
</mapper> 
aps-modules/aps-core/src/main/resources/templates/±ê×¼¹¤ÐòÊý¾ÝÄ£°åv1.0.xlsx
Binary files differ
aps-modules/aps-core/src/main/resources/templates/ÆøÌ幤µ¥Êý¾ÝÄ£°åv1.0.xlsx
Binary files differ
aps-modules/aps-core/src/main/resources/templates/ÆøÌåÔ¤²âÊý¾ÝÄ£°åv1.0.xlsx
Binary files differ
aps-modules/aps-job/src/main/java/com/aps/job/domain/ApsWeldSeamStandardJob.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
package com.aps.job.domain;
import com.aps.common.core.annotation.Excel;
import com.aps.common.core.web.domain.BaseEntity;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
 * ç„Šç¼æ ‡å‡†å¯¹è±¡ aps_weld_seam_standard_job
 *
 * @author user
 * @date 2023-11-05
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ApsWeldSeamStandardJob extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    /** ä¸»é”®ID */
    private Long id;
    /** æ–™å·ï¼ˆæŽ¥å£ä¸­å¯¹åº”plantCount或verId) */
    @Excel(name = "料号")
    private String itemCode;
    /** å›¾å· */
    @Excel(name = "图号")
    private String itemFigure;
    /** ç‰ˆæœ¬å· */
    @Excel(name = "版本号")
    private String itemFigureVersion;
    /** å•件焊缝数(Hup) */
    @Excel(name = "单件焊缝数(Hup)")
    private BigDecimal hupQty;
    /** å•件焊缝数(LOD) */
    @Excel(name = "单件焊缝数(LOD)")
    private BigDecimal lodQty;
    /** ç„ŠæŽ¥å½¢å¼(hup\lod) */
    @Excel(name = "焊接形式")
    private String type;
    /** æ˜¯å¦åˆ é™¤(0否,1是) */
    private Integer delFlag;
}
aps-modules/aps-job/src/main/java/com/aps/job/mapper/ApsBomHeaderJobMapper.java
@@ -1,6 +1,7 @@
package com.aps.job.mapper;
import com.aps.job.domain.ApsBomHeaderJob;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -11,6 +12,7 @@
 * @author hjy
 * @date 2025-05-08
 */
@Mapper
public interface ApsBomHeaderJobMapper 
{
    /**
aps-modules/aps-job/src/main/java/com/aps/job/mapper/ApsBomLineJobMapper.java
@@ -1,6 +1,7 @@
package com.aps.job.mapper;
import com.aps.job.domain.ApsBomLineJob;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -11,6 +12,7 @@
 * @author hjy
 * @date 2025-05-08
 */
@Mapper
public interface ApsBomLineJobMapper 
{
    /**
aps-modules/aps-job/src/main/java/com/aps/job/mapper/ApsWeldSeamStandardJobMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
package com.aps.job.mapper;
import com.aps.job.domain.ApsWeldSeamStandardJob;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
 * ç„Šç¼æ ‡å‡†Job Mapper接口
 *
 * @author user
 * @date 2023-11-05
 */
@Mapper
public interface ApsWeldSeamStandardJobMapper
{
    /**
     * æŸ¥è¯¢ç„Šç¼æ ‡å‡†åˆ—表
     *
     * @param apsWeldSeamStandardJob ç„Šç¼æ ‡å‡†
     * @return ç„Šç¼æ ‡å‡†é›†åˆ
     */
    public List<ApsWeldSeamStandardJob> selectApsWeldSeamStandardJobList(ApsWeldSeamStandardJob apsWeldSeamStandardJob);
    /**
     * åˆ é™¤æ‰€æœ‰ç„Šç¼æ ‡å‡†Job数据
     *
     * @return ç»“æžœ
     */
    public int deleteAllApsWeldSeamStandardJob();
    /**
     * æ‰¹é‡æ–°å¢žç„Šç¼æ ‡å‡†Job
     *
     * @param list ç„Šç¼æ ‡å‡†Job列表
     * @return ç»“æžœ
     */
    public int batchInsertApsWeldSeamStandardJob(List<ApsWeldSeamStandardJob> list);
}
aps-modules/aps-job/src/main/java/com/aps/job/mapper/ApsWeldSeamStandardMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
package com.aps.job.mapper;
import com.aps.job.domain.ApsWeldSeamStandardJob;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
 * ç„Šç¼æ ‡å‡†ä¸šåŠ¡è¡¨ Mapper接口
 *
 * @author user
 * @date 2023-11-05
 */
@Mapper
public interface ApsWeldSeamStandardMapper
{
    /**
     * åˆ é™¤æ‰€æœ‰ç„Šç¼æ ‡å‡†æ•°æ®
     *
     * @return ç»“æžœ
     */
    public int deleteAllApsWeldSeamStandard();
    /**
     * æ‰¹é‡æ–°å¢žç„Šç¼æ ‡å‡†
     *
     * @param list ç„Šç¼æ ‡å‡†Job列表
     * @return ç»“æžœ
     */
    public int batchInsertApsWeldSeamStandard(List<ApsWeldSeamStandardJob> list);
}
aps-modules/aps-job/src/main/java/com/aps/job/service/IApsWeldSeamStandardJobService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
package com.aps.job.service;
import com.aps.job.domain.ApsWeldSeamStandardJob;
import java.util.List;
/**
 * ç„Šç¼æ ‡å‡†Job Service接口
 *
 * @author user
 * @date 2023-11-05
 */
public interface IApsWeldSeamStandardJobService
{
    /**
     * æŸ¥è¯¢ç„Šç¼æ ‡å‡†åˆ—表
     *
     * @param apsWeldSeamStandardJob ç„Šç¼æ ‡å‡†
     * @return ç„Šç¼æ ‡å‡†é›†åˆ
     */
    public List<ApsWeldSeamStandardJob> selectApsWeldSeamStandardJobList(ApsWeldSeamStandardJob apsWeldSeamStandardJob);
    /**
     * åˆ é™¤æ‰€æœ‰ç„Šç¼æ ‡å‡†Job数据
     *
     * @return ç»“æžœ
     */
    public int deleteAllApsWeldSeamStandardJob();
    /**
     * æ‰¹é‡æ–°å¢žç„Šç¼æ ‡å‡†Job
     *
     * @param list ç„Šç¼æ ‡å‡†Job列表
     * @return ç»“æžœ
     */
    public int batchInsertApsWeldSeamStandardJob(List<ApsWeldSeamStandardJob> list);
    /**
     * åŒæ­¥ç‰©æ–™æ ‡å‡†ç„Šç¼æ•°æ®
     *
     * @return ç»“æžœ
     */
    public boolean syncWeldSeamStandardData();
}
aps-modules/aps-job/src/main/java/com/aps/job/service/impl/ApsBomHeaderJobServiceImpl.java
@@ -3,6 +3,7 @@
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.aps.common.core.constant.SecurityConstants;
import com.aps.common.core.utils.DateUtils;
import com.aps.common.core.utils.StringUtils;
@@ -15,6 +16,7 @@
import com.aps.job.mapper.ApsWorkOrderJobLogMapper;
import com.aps.job.service.IApsBomHeaderJobService;
import com.aps.system.api.RemoteCoreService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
@@ -35,6 +37,7 @@
 * @date 2025-05-08
 */
@Service
@Slf4j
public class ApsBomHeaderJobServiceImpl implements IApsBomHeaderJobService 
{
    @Autowired
@@ -213,6 +216,8 @@
                        jobLog.setResult("header:"+headerList.size() + " line:"+lineList.size());
                        jobLog.setCreateBy(batchNum);
                        jobLogMapper.insertApsWorkOrderJobLog(jobLog);
                        log.info("BOM同步:"+ JSON.toJSONString(jobLog));
                        pageIndex++;
                    }else{
                        break;
@@ -227,6 +232,7 @@
                    jobLog.setResult("error");
                    jobLog.setCreateBy(batchNum);
                    jobLogMapper.insertApsWorkOrderJobLog(jobLog);
                    log.info("BOM同步:"+ JSON.toJSONString(jobLog));
                    break;
                }
            }
@@ -241,6 +247,7 @@
            jobLog.setResult("error");
            jobLog.setCreateBy(batchNum);
            jobLogMapper.insertApsWorkOrderJobLog(jobLog);
            log.info("BOM同步异常信息:"+ JSON.toJSONString(jobLog));
            return false;
        }
        return true;
@@ -258,16 +265,24 @@
    @Override
    public boolean syncBomDataJob(Integer pageIndex, Integer pageSize, String orgCode, String itemCodeList){
        try {
            log.info("全量同步BOM数据定时任务开始");
            log.info(" DELETE FROM aps_bom_header_job");
            apsBomHeaderJobMapper.deleteApsBomHeaderJob();
            log.info(" DELETE FROM aps_bom_line_job");
            apsBomLineJobMapper.deleteApsBomLineJob();
            boolean res = syncBomData(pageIndex, pageSize, orgCode, itemCodeList);
            if(!res){
                return false;
            }
            log.info("将BOM同步到Redis");
            remoteCoreService.setBomDataToRedis(SecurityConstants.INNER);
            log.info("deleteApsBomHeader");
            apsBomHeaderJobMapper.deleteApsBomHeader();
            log.info("deleteApsBomLine");
            apsBomLineJobMapper.deleteApsBomLine();
            log.info("insertIntoApsBomHeader");
            apsBomHeaderJobMapper.insertIntoApsBomHeader();
            log.info("insertIntoApsBomLine");
            apsBomLineJobMapper.insertIntoApsBomLine();
        } catch (Exception e) {
            e.printStackTrace();
aps-modules/aps-job/src/main/java/com/aps/job/service/impl/ApsMaterialManagementJobServiceImpl.java
@@ -3,6 +3,7 @@
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.aps.common.core.utils.DateUtils;
import com.aps.common.core.utils.StringUtils;
import com.aps.common.core.utils.uuid.IdUtils;
@@ -11,6 +12,7 @@
import com.aps.job.mapper.ApsMaterialManagementJobMapper;
import com.aps.job.mapper.ApsWorkOrderJobLogMapper;
import com.aps.job.service.IApsMaterialManagementJobService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
@@ -31,6 +33,7 @@
 * @date 2025-05-10
 */
@Service
@Slf4j
public class ApsMaterialManagementJobServiceImpl implements IApsMaterialManagementJobService 
{
    @Autowired
@@ -182,6 +185,7 @@
                        jobLog.setResult("material:"+materialList.size());
                        jobLog.setCreateBy(batchNum);
                        jobLogMapper.insertApsWorkOrderJobLog(jobLog);
                        log.info("物料同步:"+ JSON.toJSONString(jobLog));
                        pageIndex++;
                    }else{
                        break;
@@ -196,6 +200,7 @@
                    jobLog.setResult("error");
                    jobLog.setCreateBy(batchNum);
                    jobLogMapper.insertApsWorkOrderJobLog(jobLog);
                    log.info("物料同步:"+ JSON.toJSONString(jobLog));
                    break;
                }
            }
@@ -210,6 +215,7 @@
            jobLog.setResult("error");
            jobLog.setCreateBy(batchNum);
            jobLogMapper.insertApsWorkOrderJobLog(jobLog);
            log.info("物料同步:"+ JSON.toJSONString(jobLog));
            return false;
        }
        return true;
@@ -219,12 +225,16 @@
    @Override
    public boolean syncApsMaterialDataJob(int pageIndex, int pageSize, String orgCode, String itemCodeList) {
        try {
            log.info("开始清除物料中间表aps_material_management_job");
            apsMaterialManagementJobMapper.deleteApsMaterialJob();
            log.info("开始同步物料信息");
            boolean res = syncApsMaterialData(pageIndex, pageSize, orgCode, itemCodeList);
            if(!res){
                return false;
            }
            log.info("开始清除物料表 aps_material_management");
            apsMaterialManagementJobMapper.deleteApsMaterial();
            log.info("插入数据到 aps_material_management");
            apsMaterialManagementJobMapper.insertIntoApsMaterialManagement();
            return true;
        } catch (Exception e) {
aps-modules/aps-job/src/main/java/com/aps/job/service/impl/ApsMaterialStorageManagementJobServiceImpl.java
@@ -1,6 +1,7 @@
package com.aps.job.service.impl;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aps.common.core.utils.DateUtils;
@@ -11,6 +12,7 @@
import com.aps.job.mapper.ApsMaterialStorageManagementJobMapper;
import com.aps.job.mapper.ApsWorkOrderJobLogMapper;
import com.aps.job.service.IApsMaterialStorageManagementJobService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
@@ -31,6 +33,7 @@
 * @date 2025-05-08
 */
@Service
@Slf4j
public class ApsMaterialStorageManagementJobServiceImpl implements IApsMaterialStorageManagementJobService 
{
    @Autowired
@@ -174,6 +177,7 @@
                        jobLog.setResult("storage:"+storageList.size());
                        jobLog.setCreateBy(batchNum);
                        jobLogMapper.insertApsWorkOrderJobLog(jobLog);
                        log.info("物料同步:"+ JSON.toJSONString(jobLog));
                        pageIndex++;
                    }else{
                        break;
@@ -188,6 +192,7 @@
                    jobLog.setResult("error");
                    jobLog.setCreateBy(batchNum);
                    jobLogMapper.insertApsWorkOrderJobLog(jobLog);
                    log.info("物料同步异常:"+ JSON.toJSONString(jobLog));
                    break;
                }
            }
@@ -202,6 +207,7 @@
            jobLog.setResult("error");
            jobLog.setCreateBy(batchNum);
            jobLogMapper.insertApsWorkOrderJobLog(jobLog);
            log.info("物料同步异常:"+ JSON.toJSONString(jobLog));
            return false;
        }
        return true;
@@ -211,12 +217,17 @@
    @Override
    public boolean syncApsMaterialStorageDataJob(int pageIndex, int pageSize, String orgCode, String itemCodeList) {
        try {
            log.info("开始同步库存数据");
            log.info("delete ApsMaterialStorageJob");
            apsMaterialStorageManagementJobMapper.deleteApsMaterialStorageJob();
            log.info("sync ApsMaterialStorageData");
            boolean res = syncApsMaterialStorageData(pageIndex, pageSize, orgCode, itemCodeList);
            if(!res){
                return false;
            }
            log.info("delete ApsMaterialStorage");
            apsMaterialStorageManagementJobMapper.deleteApsMaterialStorage();
            log.info("insertInto ApsMaterialStorage ");
            apsMaterialStorageManagementJobMapper.insertIntoApsMaterialStorage();
            return true;
        } catch (Exception e) {
aps-modules/aps-job/src/main/java/com/aps/job/service/impl/ApsStandardProcessRouteHeaderJobServiceImpl.java
@@ -1,6 +1,7 @@
package com.aps.job.service.impl;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aps.common.core.constant.SecurityConstants;
@@ -15,6 +16,7 @@
import com.aps.job.mapper.ApsWorkOrderJobLogMapper;
import com.aps.job.service.IApsStandardProcessRouteHeaderJobService;
import com.aps.system.api.RemoteCoreService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
@@ -34,6 +36,7 @@
 * @author hjy
 * @date 2025-05-09
 */
@Slf4j
@Service
public class ApsStandardProcessRouteHeaderJobServiceImpl implements IApsStandardProcessRouteHeaderJobService 
{
@@ -213,6 +216,7 @@
                        jobLog.setResult("header:"+headerList.size() + " line:"+lineList.size());
                        jobLog.setCreateBy(batchNum);
                        jobLogMapper.insertApsWorkOrderJobLog(jobLog);
                        log.info("标准工艺路线同步:"+ JSON.toJSONString(jobLog));
                        pageIndex++;
                    }else{
                        break;
@@ -226,6 +230,7 @@
                    jobLog.setBizType("processRoute");
                    jobLog.setResult("error");
                    jobLog.setCreateBy(batchNum);
                    log.info("标准工艺路线同步:"+ JSON.toJSONString(jobLog));
                    jobLogMapper.insertApsWorkOrderJobLog(jobLog);
                    break;
                }
@@ -240,6 +245,7 @@
            jobLog.setBizType("processRoute");
            jobLog.setResult("error");
            jobLog.setCreateBy(batchNum);
            log.info("标准工艺路线同步:"+ JSON.toJSONString(jobLog));
            jobLogMapper.insertApsWorkOrderJobLog(jobLog);
            return false;
        }
@@ -250,6 +256,7 @@
    @Override
    public boolean syncProcessRouteDataJob(Integer pageIndex, Integer pageSize, String orgCode, String itemCodeList) {
        try {
            apsStandardProcessRouteHeaderJobMapper.deleteProcessRouteHeaderJob();
            apsStandardProcessRouteLineJobMapper.deleteProcessRouteLineJob();
            boolean res = syncProcessRouteData(pageIndex, pageSize, orgCode, itemCodeList);
aps-modules/aps-job/src/main/java/com/aps/job/service/impl/ApsWeldSeamStandardJobServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,223 @@
package com.aps.job.service.impl;
import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.aps.common.core.utils.StringUtils;
import com.aps.common.security.utils.SecurityUtils;
import com.aps.job.domain.ApsWeldSeamStandardJob;
import com.aps.job.mapper.ApsWeldSeamStandardMapper;
import com.aps.job.mapper.ApsWeldSeamStandardJobMapper;
import com.aps.job.service.IApsWeldSeamStandardJobService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
/**
 * ç„Šç¼æ ‡å‡†Job Service业务层处理
 *
 * @author user
 * @date 2023-11-05
 */
@Slf4j
@Service
public class ApsWeldSeamStandardJobServiceImpl implements IApsWeldSeamStandardJobService
{
    @Autowired
    private ApsWeldSeamStandardJobMapper apsWeldSeamStandardJobMapper;
    @Autowired
    private ApsWeldSeamStandardMapper apsWeldSeamStandardMapper;
    @Autowired
    private RestTemplate restTemplate;
    @Value("${pipingIntegrationplatform.apsWeldSeamStandard}")
    private String apsWeldSeamStandardUrl;
    /**
     * æŸ¥è¯¢ç„Šç¼æ ‡å‡†åˆ—表
     *
     * @param apsWeldSeamStandardJob ç„Šç¼æ ‡å‡†
     * @return ç„Šç¼æ ‡å‡†é›†åˆ
     */
    @Override
    public List<ApsWeldSeamStandardJob> selectApsWeldSeamStandardJobList(ApsWeldSeamStandardJob apsWeldSeamStandardJob)
    {
        return apsWeldSeamStandardJobMapper.selectApsWeldSeamStandardJobList(apsWeldSeamStandardJob);
    }
    /**
     * åˆ é™¤æ‰€æœ‰ç„Šç¼æ ‡å‡†Job数据
     *
     * @return ç»“æžœ
     */
    @Override
    public int deleteAllApsWeldSeamStandardJob()
    {
        return apsWeldSeamStandardJobMapper.deleteAllApsWeldSeamStandardJob();
    }
    /**
     * æ‰¹é‡æ–°å¢žç„Šç¼æ ‡å‡†Job
     *
     * @param list ç„Šç¼æ ‡å‡†Job列表
     * @return ç»“æžœ
     */
    @Override
    public int batchInsertApsWeldSeamStandardJob(List<ApsWeldSeamStandardJob> list)
    {
        return apsWeldSeamStandardJobMapper.batchInsertApsWeldSeamStandardJob(list);
    }
    /**
     * åŒæ­¥ç‰©æ–™æ ‡å‡†ç„Šç¼æ•°æ®
     *
     * @return ç»“æžœ
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean syncWeldSeamStandardData()
    {
        try {
            log.info("开始同步物料标准焊缝数据");
            // ä½¿ç”¨POST方法调用接口
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            // å‡†å¤‡è¯·æ±‚参数 - ä¼ é€’工厂代码字符串数组,设置为空数组
            String[] plantCodeArray = new String[0];
            // ç›´æŽ¥ä½¿ç”¨å­—符串数组作为请求体
            HttpEntity<String[]> requestEntity = new HttpEntity<>(plantCodeArray, headers);
            ResponseEntity<String> responseEntity = restTemplate.postForEntity(apsWeldSeamStandardUrl, requestEntity, String.class);
            if (!responseEntity.getStatusCode().is2xxSuccessful()) {
                log.error("获取物料标准焊缝数据失败");
                return false;
            }
            String responseBody = responseEntity.getBody();
            if (StringUtils.isEmpty(responseBody)) {
                return false;
            }
            JSONObject responseJson = JSON.parseObject(responseBody);
            // æ£€æŸ¥è¿”回码
            if (responseJson.getIntValue("code") != 0) {
                return false;
            }
            // èŽ·å–æŽ¥å£è¿”å›žçš„æ•°æ®
            JSONArray weldSeamList = responseJson.getJSONArray("ok");
            if (weldSeamList == null || weldSeamList.isEmpty()) {
                return false;
            }
            // è§£æžæ•°æ®å¹¶è½¬æ¢ä¸ºå®žä½“对象
            List<ApsWeldSeamStandardJob> jobList = new ArrayList<>();
            AtomicLong idCounter = new AtomicLong(System.currentTimeMillis()); // ä½¿ç”¨å½“前时间戳作为起始ID
            for (int i = 0; i < weldSeamList.size(); i++) {
                JSONObject item = weldSeamList.getJSONObject(i);
                // ä½¿ç”¨æ­£ç¡®çš„字段名称 plantCode
                String plantCode = item.getString("plantCode");
                // èŽ·å–UHP和LOD数量
                BigDecimal uhpCount = null;
                BigDecimal lodCount = null;
                try {
                    uhpCount = item.getBigDecimal("uhpCount");
                } catch (Exception e) {
                    // å¿½ç•¥å¼‚常
                }
                try {
                    lodCount = item.getBigDecimal("lodCount");
                } catch (Exception e) {
                    // å¿½ç•¥å¼‚常
                }
                // åˆ¤æ–­æ•°æ®æ˜¯å¦å®Œæ•´
                if (StringUtils.isEmpty(plantCode)) {
                    continue;
                }
                ApsWeldSeamStandardJob job = new ApsWeldSeamStandardJob();
                // ä¸ºid赋值,使用自增长整型
                job.setId(idCounter.incrementAndGet());
                job.setItemCode(plantCode);  // æ˜ å°„关系: plantCode -> itemCode
                job.setHupQty(uhpCount);     // æ˜ å°„关系: uhpCount -> hupQty
                job.setLodQty(lodCount);     // æ˜ å°„关系: lodCount -> lodQty
                job.setDelFlag(0);
                // ä¸å†è®¾ç½®createBy和createTime
                jobList.add(job);
            }
            if (jobList.isEmpty()) {
                return false;
            }
            log.info("清空旧数据 deleteAllApsWeldSeamStandardJob");
            // æ¸…空旧数据
            deleteAllApsWeldSeamStandardJob();
            // æ‰¹é‡æ’入新数据
            List<List<ApsWeldSeamStandardJob>> dataGroup = ListUtil.split(jobList, 1000);
            for (List<ApsWeldSeamStandardJob> data : dataGroup) {
                batchInsertApsWeldSeamStandardJob(data);
            }
            // åˆ é™¤ä¸šåŠ¡è¡¨æ•°æ®ï¼ˆå…¨é‡è¦†ç›–ï¼‰
            deleteAllApsWeldSeamStandard();
            // åŒæ­¥æ•°æ®åˆ°ä¸šåŠ¡è¡¨
            for (List<ApsWeldSeamStandardJob> data : dataGroup) {
                syncToBizTable(data);
            }
            return true;
        } catch (Exception e) {
            log.error("同步物料标准焊缝数据异常", e);
            throw e;
        }
    }
    private void deleteAllApsWeldSeamStandard() {
        apsWeldSeamStandardMapper.deleteAllApsWeldSeamStandard();
    }
    /**
     * åŒæ­¥æ•°æ®åˆ°ä¸šåŠ¡è¡¨
     *
     * @param jobList ç„Šç¼æ ‡å‡†Job数据列表
     */
    private void syncToBizTable(List<ApsWeldSeamStandardJob> jobList) {
        try {
            if (jobList == null || jobList.isEmpty()) {
                return;
            }
            // æ‰¹é‡æ’入数据到业务表
            apsWeldSeamStandardMapper.batchInsertApsWeldSeamStandard(jobList);
        } catch (Exception e) {
            log.error("同步物料标准焊缝数据到业务表异常", e);
            throw e;
        }
    }
}
aps-modules/aps-job/src/main/java/com/aps/job/service/impl/ApsWorkOrderProcessServiceImpl.java
@@ -23,6 +23,7 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
@@ -131,6 +132,7 @@
        return apsWorkOrderProcessMapper.deleteApsWorkOrderProcessById(id);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void getWorkOrderProcessFromU9(List<String> docNos) throws Exception {
        List<String> noProcessDocNos = new ArrayList<>(docNos);
@@ -220,7 +222,7 @@
                            }
                            if(!addList.isEmpty()){
                                apsWorkOrderProcessMapper.insertApsWorkOrderProcessBatch(addList);
                                apsWorkOrderJobLog.setResult("ok insert "+updateList.size());
                                apsWorkOrderJobLog.setResult("ok insert "+addList.size());
                                apsWorkOrderJobLog.setUpdateTime(DateUtils.getNowDate());
                                apsWorkOrderJobLogService.updateApsWorkOrderJobLog(apsWorkOrderJobLog);
                                logger.info("【INSERT】获取并插入U9工序成功!【工单号:{}】", docNos);
aps-modules/aps-job/src/main/java/com/aps/job/task/RyTask.java
@@ -43,6 +43,9 @@
    @Autowired
    private IApsMaterialManagementJobService apsMaterialManagementJobService;
    @Autowired
    private IApsWeldSeamStandardJobService apsWeldSeamStandardJobService;
    public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i)
    {
@@ -62,7 +65,7 @@
    /**
     * åŒæ­¥å·¥å•工序数据
     */
    @Transactional(rollbackFor = Exception.class)
    public void syncWorkOrderProcessData(String status, Integer pageSize)
    {
        iApsWorkOrderProcessService.deleteApsWorkOrderProcess();
@@ -202,5 +205,12 @@
    public void setPlateSubPlansToRedis(){
        remoteCoreService.setPlateSubPlansToRedis(SecurityConstants.INNER);
    }
    /**
     * åŒæ­¥ç‰©æ–™æ ‡å‡†ç„Šç¼æ•°æ®
     */
    public void syncWeldSeamStandardData() {
        apsWeldSeamStandardJobService.syncWeldSeamStandardData();
    }
}
aps-modules/aps-job/src/main/java/com/aps/job/util/AbstractQuartzJob.java
@@ -78,7 +78,11 @@
        sysJobLog.setStartTime(startTime);
        sysJobLog.setStopTime(new Date());
        long runMs = sysJobLog.getStopTime().getTime() - sysJobLog.getStartTime().getTime();
        sysJobLog.setJobMessage(sysJobLog.getJobName() + " æ€»å…±è€—时:" + runMs + "毫秒");
        long totalSeconds = runMs / 1000;
        long minutes = totalSeconds / 60;
        long seconds = totalSeconds % 60;
        String formattedTime = minutes + "分" + seconds + "秒";
        sysJobLog.setJobMessage(sysJobLog.getJobName() + " æ€»å…±è€—时:" +formattedTime);
        if (e != null)
        {
            sysJobLog.setStatus("1");
aps-modules/aps-job/src/main/resources/mapper/job/ApsWeldSeamStandardJobMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.aps.job.mapper.ApsWeldSeamStandardJobMapper">
    <resultMap type="com.aps.job.domain.ApsWeldSeamStandardJob" id="ApsWeldSeamStandardJobResult">
        <result property="id"    column="id"    />
        <result property="itemCode"    column="item_code"    />
        <result property="itemFigure"    column="item_figure"    />
        <result property="itemFigureVersion"    column="item_figure_version"    />
        <result property="hupQty"    column="hup_qty"    />
        <result property="lodQty"    column="lod_qty"    />
        <result property="type"    column="type"    />
        <result property="delFlag"    column="del_flag"    />
    </resultMap>
    <sql id="selectApsWeldSeamStandardJobVo">
        select id, item_code, item_figure, item_figure_version, hup_qty, lod_qty, type, del_flag from aps_weld_seam_standard_job
    </sql>
    <select id="selectApsWeldSeamStandardJobList" parameterType="com.aps.job.domain.ApsWeldSeamStandardJob" resultMap="ApsWeldSeamStandardJobResult">
        <include refid="selectApsWeldSeamStandardJobVo"/>
        <where>
            <if test="itemCode != null  and itemCode != ''"> and item_code LIKE '%' || #{itemCode} || '%'</if>
            <if test="itemFigure != null  and itemFigure != ''"> and item_figure = #{itemFigure}</if>
            <if test="itemFigureVersion != null  and itemFigureVersion != ''"> and item_figure_version = #{itemFigureVersion}</if>
            <if test="hupQty != null "> and hup_qty = #{hupQty}</if>
            <if test="lodQty != null "> and lod_qty = #{lodQty}</if>
            <if test="type != null  and type != ''"> and type = #{type}</if>
            and del_flag = 0
        </where>
    </select>
    <delete id="deleteAllApsWeldSeamStandardJob">
        delete from aps_weld_seam_standard_job
    </delete>
    <insert id="batchInsertApsWeldSeamStandardJob" parameterType="java.util.List">
        insert into aps_weld_seam_standard_job(
        id,
        item_code,
        item_figure,
        item_figure_version,
        hup_qty,
        lod_qty,
        type,
        del_flag)
        values
        <foreach collection="list" item="item" index="index" separator=",">
        (
            #{item.id},
            #{item.itemCode},
            #{item.itemFigure},
            #{item.itemFigureVersion},
            #{item.hupQty},
            #{item.lodQty},
            #{item.type},
            0
        )
        </foreach>
    </insert>
</mapper>
aps-modules/aps-job/src/main/resources/mapper/job/ApsWeldSeamStandardMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.aps.job.mapper.ApsWeldSeamStandardMapper">
    <delete id="deleteAllApsWeldSeamStandard">
        delete from aps_weld_seam_standard
    </delete>
    <insert id="batchInsertApsWeldSeamStandard" parameterType="java.util.List">
        insert into aps_weld_seam_standard(
        id,
        item_code,
        item_figure,
        item_figure_version,
        hup_qty,
        lod_qty,
        type,
        del_flag)
        values
        <foreach collection="list" item="item" index="index" separator=",">
        (
            #{item.id},
            #{item.itemCode},
            #{item.itemFigure},
            #{item.itemFigureVersion},
            #{item.hupQty},
            #{item.lodQty},
            #{item.type},
            0
        )
        </foreach>
    </insert>
</mapper>