Compare commits

...

284 Commits

Author SHA1 Message Date
砂糖
5ec293fc94 feat(物料管理): 添加质量状态多选查询功能
在物料管理模块中新增质量状态多选查询功能,包括:
1. 后端添加qualityStatusCsv字段支持多选查询
2. 前端CoilSelector组件增加品质多选下拉框
3. 服务层实现多选条件过滤逻辑
2026-04-02 14:24:52 +08:00
砂糖
d31bd14692 feat(字典组件): 添加DictSelect组件并替换多处muti-select
添加DictSelect组件作为全局组件,并在多个报表模板中替换原有的muti-select组件
优化字典项筛选逻辑,调整样式和提示文本
2026-04-02 09:10:58 +08:00
821af42976 fix(export): 修正导出VO中的字段标签
- 将WmsMaterialCoilAllExportVo中的打包状态字段标签修正为原料材质
- 将WmsMaterialCoilExportVo中的打包状态字段标签修正为原料材质
2026-04-01 18:20:45 +08:00
砂糖
579bf3796f feat(wms): 新增钢卷表面处理字段及相关功能
在钢卷相关实体类、前端页面和查询逻辑中新增钢卷表面处理字段,包括:
1. 在WmsMaterialCoil、WmsMaterialCoilVo、WmsMaterialCoilBo中新增coilSurfaceTreatment字段
2. 在前端多个页面中新增钢卷表面处理的展示和编辑功能
3. 在查询逻辑中新增对钢卷表面处理的过滤条件
4. 新增仓库操作记录页面及相关统计图表功能
2026-04-01 14:50:56 +08:00
砂糖
f959f97099 feat(contract): 新增合同预览和列表组件
refactor(QRCode): 优化二维码组件并修复空值检查
将QRCode组件从print目录移动到components目录,并添加空值检查防止错误

feat(crm): 在合同模型中添加交货日期字段
在CrmContract、CrmContractVo、CrmContractBo及相关Mapper中添加deliveryDate字段

refactor(wms): 统一使用全局QRCode组件路径
将多个文件中的QRCode引用路径从相对路径改为@/components/QRCode

style(order): 调整订单页面标签顺序
调整操作记录和发货配卷标签的顺序

chore: 删除废弃的打印相关文件
移除print目录下不再使用的QRCode、CodeRenderer等组件和页面
2026-04-01 10:44:51 +08:00
砂糖
800cf0c8d1 fix(wms报表): 修正异常率计算逻辑并统一百分比格式
- 在异常率计算中增加质量状态判断条件
- 将分母从totalCount改为outCount以匹配业务需求
- 统一异常率和正品率的百分比格式输出
2026-03-31 18:54:56 +08:00
砂糖
0223102269 feat(wms/report): 添加差值计算和异常信息展示功能
refactor(wms/report): 替换合计信息为差值显示
feat(wms/coil): 增加创建时间和创建人字段
feat(crm/contract): 添加合同导出按钮
2026-03-31 18:37:17 +08:00
砂糖
abcc644f74 feat(crm/contract): 添加状态变更功能并优化代码
在合同管理页面添加状态变更下拉选择功能,支持草稿、已生效、已作废和已完成四种状态切换。同时移除base.vue中无用的注释代码。
2026-03-31 14:16:08 +08:00
砂糖
62444ef743 feat(crm): 添加订单和合同的发货配卷查询功能
添加新的API接口和组件用于查询订单和合同下的发货配卷情况
在订单和合同详情页中新增"发货配卷"标签页展示相关数据
2026-03-31 13:49:00 +08:00
砂糖
a253d1ccea feat(crm): 传递合同ID至订单页面并完善标签逻辑
在合同页面将合同ID传递给订单页面,确保订单与合同关联
优化标签渲染逻辑,根据仓库类型显示不同标签
移除无用注释和代码
2026-03-31 11:32:16 +08:00
砂糖
aca10bcd45 feat(客户管理): 新增税号字段并优化客户信息展示
feat(订单管理): 增加宽度和厚度公差字段,优化销售员选择方式

feat(合同管理): 新增合同管理模块及相关API接口

refactor(文件列表): 重构文件列表组件样式和布局

fix(QRCode): 修复内容为空时仍触发生成的bug

perf(线圈管理): 优化用户列表加载条件,减少不必要请求

style(代码): 移除多余的空行和注释代码
2026-03-31 11:16:48 +08:00
b7d8463198 fix(crm): 修复客户查询条件匹配逻辑
- 将联系人姓名字段从精确匹配改为模糊匹配
- 将联系方式字段从精确匹配改为模糊匹配
- 将地址字段从精确匹配改为模糊匹配
- 将银行信息字段从精确匹配改为模糊匹配
- 将税号字段从精确匹配改为模糊匹配
- 提升客户搜索功能的灵活性和准确性
2026-03-30 15:07:41 +08:00
砂糖
4617328b8e Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-30 14:34:55 +08:00
砂糖
070b0aea8d fix(wms): 修复异常表单和报表导出功能
修正异常表单中的产线字段名从line改为productionLine
优化报表导出功能,使用actionIds替代coilIds
为异常管理添加程度字典显示和产线字段
移除冗余代码并统一报表模板中的导出逻辑
2026-03-30 14:34:51 +08:00
6835a35c02 feat(crm): 订单ID数据类型优化及配卷查询功能扩展
- 将CrmOrder、CrmOrderItem及其相关BO、VO类中的orderId和itemId字段从String类型改为Long类型
- 修改selectOrderItemsByOrderIds方法参数类型为List<Long>
- 在CrmOrderItemController中新增根据订单ID和合同ID查询配卷的接口
- 实现queryCoilsByOrderId和queryCoilsByContractId服务方法
- 移除WmsMaterialCoilServiceImpl中冗余的嵌套对象构建逻辑
- 更新销售报表中订单ID的类型转换和分组逻辑以适配Long类型
2026-03-30 14:33:06 +08:00
02469383f4 fix(exception): 修改全局异常处理器返回具体错误信息
- 修改 RuntimeException 处理器返回具体的异常消息而不是通用提示
- 修改 Exception 处理器返回具体的异常消息而不是通用提示
- 移除了硬编码的"系统异常,请联系管理员处理"消息
- 保留了原有的错误日志记录功能
2026-03-30 13:57:35 +08:00
15a3f843f1 feat(crm): 添加某一合同下财务和异议信息查询功能
- 在CrmOrderItemController中新增getContractFinance接口用于查询合同关联的财务和异议数据
- 在CrmOrderItemService及其实现类中添加queryFinanceAndObjectionByContractId方法
- 创建CrmContractOrderFinanceVo数据传输对象封装异议列表和应收款列表
- 实现通过合同ID查询其下属订单的销售异议和财务信息的完整逻辑
- 修改全局异常处理器统一返回系统异常提示信息
2026-03-30 13:47:10 +08:00
8a5f2bc4df feat(crm): 添加订单关联合同ID和附件字段支持
- 在CrmOrder实体类中新增contractId和annexFiles字段
- 在CrmOrderBo业务对象中同步添加对应字段
- 更新CrmOrderMapper.xml映射文件中的结果映射和查询字段
- 在CrmOrderServiceImpl服务实现中添加字段查询条件支持
- 在CrmOrderVo视图对象中增加Excel导出注解配置
2026-03-30 13:39:27 +08:00
ca176de4ef feat(crm): 添加合同管理功能模块
- 新增合同信息实体类、业务对象和视图对象
- 创建合同产品明细相关的实体、业务对象和视图对象
- 实现合同信息的增删改查和分页查询功能
- 实现合同产品明细的增删改查和分页查询功能
- 添加合同信息和产品明细的导出Excel功能
- 创建合同信息和产品明细的数据库映射配置
- 实现合同服务层业务逻辑和数据校验功能
- 配置合同相关控制器接口和请求映射关系
2026-03-30 13:28:37 +08:00
d26bdb38ca Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-30 13:19:26 +08:00
2dff94c3bd feat(order): 添加订单项宽度公差和厚度公差字段
- 在CrmOrderItem实体类中新增widthTolerance和thicknessTolerance字段
- 在CrmOrderItemBo业务对象中添加对应的公差字段定义
- 更新CrmOrderItemMapper.xml映射文件中的结果映射和查询字段
- 在服务实现类中添加公差字段的查询条件支持
- 在CrmOrderItemVo视图对象中增加Excel导出支持的公差字段
2026-03-30 13:19:17 +08:00
砂糖
bb9252e3a2 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-30 13:13:49 +08:00
砂糖
aacf433462 feat: 修改打包状态为原料材质并优化异常管理功能
修改所有打包状态字段为原料材质,统一业务术语
重构异常管理功能,新增异常记录列表和删除功能
优化分条钢卷面板显示更多物料信息
将切边要求和包装要求改为下拉选择框
2026-03-30 13:13:46 +08:00
e553bfcb22 feat(crm): 添加客户纳税人识别号字段支持
- 在 CrmCustomer 实体类中新增 taxNumber 字段
- 在 CrmCustomerBo 业务对象中添加 taxNumber 属性
- 在 CrmCustomerVo 视图对象中增加 taxNumber 并配置 Excel 导出
- 更新 MyBatis 映射文件 CrmCustomerMapper.xml 添加字段映射
- 在查询条件构建中加入纳税人识别号的过滤逻辑
2026-03-30 12:57:57 +08:00
cb9998e0c4 feat(wms): 添加钢卷异常记录中的产线名称字段
- 在 WmsCoilAbnormal 实体类中新增 productionLine 字段
- 在 WmsCoilAbnormalBo 中添加 productionLine 查询条件字段
- 更新数据库映射文件 WmsCoilAbnormalMapper.xml 映射关系
- 在服务层实现类中添加产线名称查询过滤逻辑
- 在 WmsCoilAbnormalVo 视图对象中添加产线名称导出支持
2026-03-30 12:57:19 +08:00
15058727d0 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-30 11:10:52 +08:00
ab7af2ade8 feat(wms): 添加配送单详情中的原材料和产品信息字段
- 在 WmsDeliveryWaybillDetailVo 中新增物品名称、规格、材质等属性
- 添加厂家、表面处理描述、镀层等原材料/产品相关信息
- 在 Mapper 中增加原材料和产品的关联查询逻辑
- 实现原材料和产品表的左连接查询支持
- 添加状态描述字段用于显示库存状态信息
- 完善 Excel 导出功能中的新字段映射配置
2026-03-30 11:10:44 +08:00
砂糖
9cf0d289c3 feat(wms): 添加表面处理字段显示和查询功能
在发货单明细表和钢卷选择器中添加表面处理字段的显示和查询功能
同时优化钢卷选择时的品质状态校验逻辑
2026-03-30 11:02:36 +08:00
砂糖
4988630db9 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-30 10:29:07 +08:00
cdf49ab8fe feat(wms): 添加发货单明细查询功能支持导出功能
- 在WmsDeliveryWaybillDetailMapper中新增VO查询方法
- 实现联查发货单、计划、钢卷信息的数据映射
- 更新WmsDeliveryWaybillDetailVo实体类字段结构
- 优化服务层查询逻辑并添加分页支持
- 配置MyBatis XML映射文件查询语句
- 整合多表关联数据展示完整业务信息
2026-03-30 10:15:10 +08:00
砂糖
a43cedc00f feat(wms/delivery): 改进发货单页面布局和交互
添加可拖拽分割线调整表格和详情区域高度
固定顶部操作栏和表格区域滚动
优化页面整体样式和用户体验
2026-03-30 09:50:52 +08:00
砂糖
667c411997 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-30 09:29:46 +08:00
砂糖
05fb0358a2 fix(wms): 在导出功能中添加waybillId参数
确保导出功能包含必要的waybillId参数以正确过滤数据
2026-03-30 09:29:40 +08:00
e767502d7b Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-28 18:10:29 +08:00
112cdce0d0 feat(wms): 完善物料卷VO结构并优化运单查询排序
- 在WmsMaterialCoilVo中新增actualWarehouse字段存储仓库信息
- 为WmsMaterialCoilVo补充WmsActualWarehouse导入声明
- 在物料卷服务实现中设置仓库名称和实际仓库信息
- 为运单查询条件添加按创建时间降序排列功能
2026-03-28 18:10:21 +08:00
砂糖
49427608ad Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-28 17:52:03 +08:00
砂糖
97cb78bbbe feat(wms): 在钢卷修正页面添加实测厚度输入框
为钢卷修正功能添加实测厚度(m)的输入框,使用户能够输入钢卷的实测厚度数据
2026-03-28 17:52:00 +08:00
086d01fa3f Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-28 16:39:41 +08:00
c3f2f5ef83 refactor(WmsTransferOrderItemService): 优化调拨单明细查询速率
- 简化导入语句,使用通配符导入相关域类和映射器
- 添加WmsWarehouseMapper依赖注入以支持仓库信息批量查询
- 将原有的分步查询逻辑重构为统一的fillBatchInfo方法
- 实现批量查询钢卷、原料、产品和仓库信息以提高性能
- 添加物料类型名称映射和前后置物料信息填充功能
- 在创建和更新钢卷时设置物料类型字段
2026-03-28 16:39:33 +08:00
砂糖
8d6c3302a3 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-28 15:58:27 +08:00
砂糖
97cc86c6c4 feat(钢卷操作): 将操作类型显示从静态文本改为可编辑的下拉选择框
修改操作类型显示方式,从静态文本替换为可编辑的下拉选择框,支持用户直接修改操作类型。同时保留原有字典类型的选项支持,提升用户体验和操作便捷性。
2026-03-28 15:58:23 +08:00
f3d5e1f0bf feat(transfer): 添加调拨订单项确认功能中的订单项ID参数支持
- 在confirmTransfer方法中添加orderItemId参数获取
- 更新查询条件以支持根据订单项ID进行筛选
- 添加对orderItemId和transferId为null的安全检查
- 优化查询包装器的条件判断逻辑
2026-03-28 15:27:35 +08:00
砂糖
499654907b feat(调拨单): 新增调拨单管理功能
- 新增调拨单主表和明细表相关API接口
- 新增调拨单主表和明细表前端页面
- 新增钢卷选择器组件和调拨明细表格组件
- 修改产品信息和原料信息渲染组件支持更多字段
- 修改产品选择和原料选择组件支持数值类型值
- 修改钢卷号渲染组件支持更多字段和外部数据
- 新增调拨单匹配物料接口
2026-03-28 14:08:27 +08:00
00939dae2f refactor(wms): 优化调拨单项目物料信息填充逻辑
- 将通用的fillMaterialInfo方法拆分为fillMaterialInfoBefore和fillMaterialInfoAfter两个专用方法
- 修复了物料信息填充时字段映射错误问题,确保Before和After字段正确设置
- 增强了代码可读性和维护性,明确区分前后物料信息处理逻辑
- 保持了原有的业务逻辑不变,仅优化方法结构和字段赋值准确性
2026-03-28 13:35:48 +08:00
6e23e932da refactor(transfer): 优化转库订单项目确认逻辑
- 移除 WmsTransferOrderItemBo 中的 itemType 字段
- 将 itemType 替换为 materialTypeAfter 的转换逻辑
- 添加对 itemId、itemType 和 warehouseId 的空值检查
- 实现字段选择性更新机制
- 修复查询条件添加 transferId 筛选
- 完善默认值回退逻辑
2026-03-28 11:47:33 +08:00
c554508000 feat(transfer): 添加调拨订单项目中的钢卷详情查询和重复检查功能
- 优化导入语句,使用java.util.*统一导入
- 在分页查询中添加钢卷详情关联查询逻辑
- 通过coilId收集并查询对应的钢卷信息并建立映射关系
- 为每个调拨订单项目设置关联的钢卷详情信息
- 添加调拨单内钢卷重复性检查机制
- 防止同一调拨单下添加相同coilId的重复项目
- 提供详细的重复钢卷号错误提示信息
2026-03-28 11:33:19 +08:00
317b7187f5 perf(WmsTransferOrderItemService): 优化调拨明细信息查询性能
- 使用流式处理批量获取钢卷ID并去重
- 通过单次查询获取所有相关钢卷信息
- 使用Map映射避免循环中的重复数据库查询
- 移除原有的逐条查询逻辑减少数据库交互次数
- 提升列表查询的整体性能表现
2026-03-28 10:58:15 +08:00
d28f50ba65 feat(wms): 完善调拨单明细查询功能
- 新增钢卷信息查询和服务注入
- 新增库房服务依赖以获取库区名称
- 实现调拨单明细详情信息填充功能
- 添加改前后物料信息的完整查询支持
- 扩展VO类以包含物料类型名称和库区名称字段
- 优化查询方法以自动填充关联的物料和库房信息
- 实现物料类型转换显示为中文描述功能
- 添加异常处理确保库房信息查询失败时不影响主流程
2026-03-28 10:39:43 +08:00
862efcfabd Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-28 09:27:38 +08:00
d51b555fa2 fix(excel): 修复排产表导出功能中的日期格式和表格合并问题
- 添加SimpleDateFormat用于日期格式化处理
- 将计划日期格式化为yyyy-MM-dd格式避免显示异常
- 修正表格合并区域从38列扩展到40列
- 为整个合并区域的所有单元格应用标题样式
- 确保合并单元格后样式的一致性显示
2026-03-28 09:27:30 +08:00
砂糖
f685ea4cea Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-28 09:09:55 +08:00
砂糖
9c2d8cfb4a feat(计划单): 添加序号字段并在表格中显示
在计划单详情表单中添加序号输入字段,并在详情表格中新增序号列显示。移除不再使用的修改按钮代码。
2026-03-28 09:09:50 +08:00
ba722e0439 refactor(aps): 重构排产单查询和导出功能
- 移除日期范围、产线ID和客户名称查询条件
- 修改排序规则为按业务序号升序排列
- 删除查询请求DTO中的废弃字段
- 优化Excel导出功能,添加标题动态显示和表头样式
- 实现前7列数据居中对齐和自动合并功能
- 修复POI依赖导入路径问题
- 更新转储订单项映射配置
2026-03-27 18:21:53 +08:00
砂糖
bc00846f14 feat(排产单): 新增只读模式并优化导出功能
添加只读视图组件 read.vue,修改 detail.vue 和 index.vue 以支持 readonly 属性
将导出按钮移至行操作列并支持单行导出
优化排产日期列宽度和操作列布局
2026-03-27 17:27:06 +08:00
1c9a59636a feat(wms): 添加调拨单明细取消功能并优化字段映射
- 在IWmsTransferOrderItemService中新增cancelTransfer方法
- 修改WmsTransferOrderItem实体类将itemId字段重命名为orderItemId
- 在WmsTransferOrderItemBo和WmsTransferOrderItemVo中同步字段名称变更
- 为WmsTransferOrderBo的transferTime字段添加日期格式化注解
- 在WmsTransferOrderItemController中添加cancel接口支持取消操作
- 实现WmsTransferOrderItemServiceImpl的cancelTransfer业务逻辑
- 移除未使用的工具类依赖和冗余的coilService注入
- 修复confirmTransfer方法中的字段赋值错误
2026-03-27 17:13:45 +08:00
b842f267cc feat(transfer): 新增调拨单明细确认功能
- 在IWmsTransferOrderItemService接口中添加confirmTransfer方法
- 在WmsTransferOrderItemBo中增加itemType字段用于物料类型标识
- 创建WmsTransferOrderItemController的confirm端点处理确认请求
- 实现WmsTransferOrderItemServiceImpl中的confirmTransfer业务逻辑
- 集成IWmsMaterialCoilService服务更新钢卷相关状态信息
- 完成调拨单明细数据同步更新确保数据一致性
2026-03-27 16:59:20 +08:00
5be8f2857e Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-27 16:44:03 +08:00
62eb5aedfb feat(wms): 添加调拨单明细批量新增功能
- 在 IWmsTransferOrderItemService 中添加 batchInsert 方法
- 在 WmsTransferOrderItemBo 中新增 coilIds 字段用于接收钢卷id列表
- 在 WmsTransferOrderItemController 中添加 /batch 接口支持批量新增
- 在 WmsTransferOrderItemServiceImpl 中实现批量插入业务逻辑
- 新增 WmsMaterialCoil 相关依赖注入和数据查询操作
- 实现根据 itemType 自动设置 materialType 的转换逻辑
2026-03-27 16:43:42 +08:00
砂糖
cd00b9562d refactor(wms/report): 重构报表模块数据获取逻辑,提取公共方法到fetch.js
feat(wms/report): 新增报表结果存储页面,支持JSON数据横向对比

style(wms/coil/do): 调整钢卷修正页面样式和代码格式

fix(wms/coil/do): 修复操作记录查询参数传递问题,优化钢卷选择逻辑
2026-03-27 16:37:59 +08:00
c294149274 feat(wms): 新增调拨单明细物料匹配或创建功能
- 在IWmsTransferOrderItemService接口中添加matchOrCreateMaterial方法
- 在WmsTransferOrderItemController中添加/matchOrCreate接口端点
- 实现matchOrCreateMaterial业务逻辑,支持根据itemId和itemType匹配或新增物料
- 添加从原料到产品的转换匹配逻辑
- 添加从产品到原料的转换匹配逻辑
- 集成WmsRawMaterialMapper和WmsProductMapper数据访问层
- 实现基于名称、规格、制造商等字段的精确匹配机制
- 支持itemType参数区分原料(material)和成品(product)处理流程
2026-03-27 16:32:32 +08:00
0d3bde95f3 feat(wms): 添加调拨单功能模块
- 创建调拨单主表实体类、业务对象类和视图对象类
- 创建调拨单明细表实体类、业务对象类和视图对象类
- 实现调拨单主表和明细表的数据库映射和XML配置文件
- 开发调拨单主表和明细表的服务接口及实现类
- 创建调拨单主表和明细表的控制器,提供CRUD操作接口
- 实现分页查询、新增、修改、删除和导出功能
- 添加参数验证和数据校验机制
- 集成MyBatis-Plus进行数据库操作
- 配置Excel导出功能支持调拨单数据导出
2026-03-27 16:15:17 +08:00
15a2920053 feat(WmsCoilPendingAction): 添加按钢卷ID列表查询功能
- 在WmsCoilPendingActionBo中新增coilIds字段用于存储钢卷ID列表
- 实现字符串形式的钢卷ID逗号分隔解析为Long类型列表
- 扩展buildQueryWrapperPlus方法支持按多个钢卷ID批量查询
- 添加非空验证确保coilIds参数有效时才进行in条件构建
- 保持原有单个coilId查询逻辑不变,实现向后兼容
- 提供更灵活的批量查询接口以提升数据检索效率
2026-03-27 16:08:59 +08:00
砂糖
ab3914811a feat(wms): 新增报结果存储API及页面
refactor(aps): 修改导出接口为POST并调整表格高度
2026-03-27 13:00:58 +08:00
砂糖
19b48d711a Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-27 09:57:27 +08:00
砂糖
1e6be8cd76 feat(aps): 新增排产单管理功能模块
添加排产单主表和明细表的API接口
实现排产单列表、新增、修改、删除功能
添加排产单明细表单和列表展示组件
2026-03-27 09:57:24 +08:00
2041cb3e5d fix(wms): 删除钢卷时同步更新二维码状态为失效
- 在删除钢卷操作中添加二维码状态更新逻辑
- 遍历钢卷列表检查是否存在关联的二维码记录ID
- 将关联的二维码记录状态设置为0表示失效
- 通过generateRecordService更新二维码记录状态
- 确保删除钢卷后对应的二维码同步失效
2026-03-27 09:55:09 +08:00
d4b5f09882 fix(wms): 解决合卷操作中钢卷重复检查问题
- 添加钢卷ID去重验证逻辑
- 防止相同钢卷重复参与合卷操作
- 抛出明确的业务异常提示重复问题
2026-03-27 09:43:14 +08:00
278cb24d54 feat(aps): 添加日期时间格式化注解支持
- 在 ApsPlanDetail 实体类中为 startTime 和 endTime 字段添加 JsonFormat 和 DateTimeFormat 注解
- 在 ApsPlanDetailBo 业务对象中为 startTime 和 endTime 字段添加 JsonFormat 和 DateTimeFormat 注解
- 在 ApsPlanDetailVo 视图对象中为 startTime 和 endTime 字段添加 JsonFormat 和 DateTimeFormat 注解
- 在 ApsPlanSheet 实体类中为 planDate 字段添加 JsonFormat 和 DateTimeFormat 注解
- 在 ApsPlanSheetBo 业务对象中为 planDate 字段添加 JsonFormat 和 DateTimeFormat 注解
- 在 ApsPlanSheetVo 视图对象中为 planDate 字段添加 JsonFormat 和 DateTimeFormat 注解
- 统一日期时间字段的序列化和反序列化格式配置
2026-03-26 16:21:40 +08:00
1b9787f983 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-26 15:14:06 +08:00
0f760e90b5 feat(aps): 添加根据排产单ID删除明细功能
- 在ApsPlanDetailMapper中新增deleteByPlanSheetIds方法
- 在ApsPlanDetailMapper.xml中添加对应的DELETE语句实现软删除
- 在ApsPlanDetailServiceImpl中实现deleteByPlanSheetIds方法
- 在ApsPlanSheetServiceImpl中注入IApsPlanDetailService依赖
- 在排产单删除时调用planDetailService.deleteByPlanSheetIds方法
- 在IApsPlanDetailService接口中定义deleteByPlanSheetIds方法
2026-03-26 15:13:54 +08:00
砂糖
5d3cbde044 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-26 15:13:11 +08:00
砂糖
a389a98664 feat(wms): 新增分条报表配置及功能优化
- 添加分条报表相关配置及视图组件
- 优化标签打印尺寸及布局
- 增加实测厚度字段及相关展示逻辑
- 重构报表数据获取逻辑,统一处理异常情况
- 完善分条操作表单,增加异常信息管理
2026-03-26 15:13:08 +08:00
38862cf0ea feat(aps): 添加排产单导出功能
- 新增 ApsPlanSheetQueryReq 查询参数类
- 新增 ApsPlanSheetRowVo 数据传输对象
- 实现 controller 层 exportAll 接口
- 实现 service 层 exportExcel 导出逻辑
- 添加 mapper 层 selectList 查询方法
- 配置 mybatis xml 查询映射
- 优化 Excel 导出样式和数据处理
2026-03-26 14:59:33 +08:00
281f86ca8c feat(aps): 添加排产单和排产明细功能模块
- 创建排产单主实体类 ApsPlanSheet 和业务对象 ApsPlanSheetBo
- 创建排产单明细实体类 ApsPlanDetail 和业务对象 ApsPlanDetailBo
- 实现排产单主和明细的控制器、服务层和数据访问层
- 添加排产单主和明细的查询、新增、修改、删除和导出功能
- 配置 MyBatis Plus 映射和 XML 结果映射
- 实现分页查询和条件筛选功能
- 添加数据校验和业务逻辑处理
2026-03-26 11:35:33 +08:00
fb0dfb0d76 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-26 10:42:32 +08:00
7e7f03e19f feat(domain): 添加材料卷实测厚度字段支持
- 在WmsMaterialCoil实体类中新增actualThickness字段
- 在WmsMaterialCoilAllExportVo导出对象中添加厚度导出映射
- 在WmsMaterialCoilBo业务对象中增加厚度查询条件支持
- 在WmsMaterialCoilExportVo导出对象中补充厚度字段定义
- 更新WmsMaterialCoilMapper.xml映射文件中的厚度字段映射
- 在WmsMaterialCoilServiceImpl服务实现中加入厚度查询逻辑
- 在WmsMaterialCoilVo视图对象中添加厚度字段定义
2026-03-26 10:41:50 +08:00
砂糖
feb50e038d refactor(ems/dashboard): 重构能源类型选择为标签页形式并设置默认值
将能源类型选择从下拉框改为标签页形式,提升用户体验
移除未使用的标签页代码,并设置默认选中的能源类型
2026-03-26 10:41:27 +08:00
砂糖
c2ba4b0193 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-25 17:22:24 +08:00
砂糖
564086c72a fix(wms报表): 修复fetchLossList参数传递及规格分割处理
修复fetchLossList函数未正确处理传入的actionTypes参数问题,并添加时间参数。同时处理规格分割时的空值情况,避免报错。
2026-03-25 17:22:21 +08:00
9dc8d589f0 feat(wms): 添加报表结果存储功能支持JSON和横向对比
- 创建WmsReportResultStorage实体类用于存储报表结果数据
- 实现IWmsReportResultStorageService服务接口及其实现类
- 添加WmsReportResultStorageController控制器提供CRUD操作
- 创建WmsReportResultStorageMapper数据访问层
- 配置WmsReportResultStorageMapper.xml映射文件
- 定义WmsReportResultStorageBo业务对象和WmsReportResultStorageVo视图对象
- 实现报表数据按日期、类型、产线进行查询和去重逻辑
- 添加Excel导出功能支持报表数据导出
2026-03-25 16:23:39 +08:00
e8568b6ec7 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-25 14:37:00 +08:00
31bbdedb8f feat(wms): 获取消耗钢卷接口,用作报表或者导出
- 在IWmsCoilPendingActionService中新增queryActionIdCoilIdList方法
- 在WmsCoilPendingActionController中新增/actionCoilIdList端点
- 在WmsCoilPendingActionMapper中新增selectActionIdCoilIdList查询方法
- 在WmsCoilPendingActionMapper.xml中添加对应的SQL查询语句
- 在WmsCoilPendingActionServiceImpl中实现查询逻辑
- 创建WmsCoilPendingActionIdCoilVo数据传输对象,仅包含actionId和coilId字段
2026-03-25 14:36:53 +08:00
砂糖
e47d6e159e Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-25 14:34:29 +08:00
砂糖
33c003d2ca refactor(mes/eqp): 重构备件和辅料库存变动页面
优化库存变动功能,增加新增变动记录弹窗
统一备件和辅料变动操作逻辑
移除不再使用的报表组件
2026-03-25 14:34:26 +08:00
b98b4593f6 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-25 13:50:13 +08:00
7afc9ac04f feat(eqp): 修改辅料和备品备件新增接口返回值
- 将 EqpAuxiliaryMaterialController 的 add 方法返回值从 R<Void> 改为 R<Long>
- 将 EqpAuxiliaryMaterialService 和实现类的 insertByBo 方法返回值从 Boolean 改为 Long
- 将 EqpSparePartController 的 add 方法返回值从 R<Void> 改为 R<Long>
- 将 EqpSparePartService 和实现类的 insertByBo 方法返回值从 Boolean 改为 Long
- 新增操作成功后返回具体的 ID 值而非布尔值
- 统一了接口返回格式,便于前端获取新增记录的主键信息
2026-03-25 13:50:05 +08:00
砂糖
8e2159a6cf feat(LogTable): 添加日志导出功能并优化日期处理
- 新增导出按钮及导出功能实现
- 默认设置查询时间为昨天0点到今天23:59:59
- 优化表格高度适应页面
- 重置功能现在保留coilId并重置为默认时间范围
2026-03-25 10:21:40 +08:00
8baf165840 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-25 10:16:48 +08:00
c01074582d feat(controller): 修复吞吐各个接口的查询时间问题
- 引入 Jackson 的 @JsonFormat 注解用于日期格式化
- 添加 Spring 的 @DateTimeFormat 注解用于日期参数解析
- 配置 startTime 和 endTime 参数的日期时间格式为 yyyy-MM-dd HH:mm:ss
- 确保日期参数在请求中的正确序列化和反序列化
2026-03-25 10:16:19 +08:00
砂糖
519e91b299 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-25 09:04:54 +08:00
砂糖
bb79b02ee4 refactor(wms): 优化报表查询逻辑和界面显示
- 将查询参数中的 updateBy 改为 createBy 以匹配实际业务需求
- 移除不再使用的 selectType 参数
- 优化员工信息页面显示,调整离职时间展示
- 提取公共的 fetch 逻辑到单独文件
- 重构报表查询逻辑,使用 Promise.all 并行请求
- 调整钢卷文档页面,增加创建人选择功能
2026-03-25 09:04:48 +08:00
6cb78bd3bf feat(wms): 添加钢卷报表汇总功能
- 新增 WmsMaterialCoilReportSummaryBo 请求参数类
- 新增 WmsMaterialCoilReportSummaryVo 响应结果类
- 在 IWmsMaterialCoilService 中添加 reportSummary 方法定义
- 在 WmsMaterialCoilController 中添加 /reportSummary 接口
- 实现 reportSummary 业务逻辑,支持待操作条件和钢卷条件组合筛选
- 实现钢卷ID合并、异常库汇总、班组汇总等统计功能
- 提供空数据情况下的默认汇总结果处理
2026-03-24 18:01:46 +08:00
45f58a7d3e Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-24 15:42:48 +08:00
b31c3284b6 feat(WmsCoilPendingActionService): 添加创建人筛选功能
- 根据创建人筛选待处理钢卷操作记录
- 在查询条件中新增 create_by 字段匹配
2026-03-24 15:42:38 +08:00
砂糖
602b10b689 feat(wms): 重构报表配置并添加销售员管理功能
重构各报表模块配置,将重复配置提取到config.js统一管理
在打包记录和打包页面添加销售员选择和显示功能
新增销售员管理页面,支持销售员标签的增删改查
2026-03-24 15:38:30 +08:00
砂糖
0e808964c9 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-24 14:52:50 +08:00
砂糖
062bcd0b71 feat(标签打印): 添加分条成品标签类型及打印组件
新增分条成品标签类型,支持在特定仓库中自动识别并打印分条成品标签。添加SplitTag.vue组件用于分条成品标签的渲染,并更新相关逻辑以支持新的标签类型。
2026-03-24 14:52:47 +08:00
876bb48b1d feat(employee): 添加员工离职时间字段及查询功能
- 在WmsEmployeeInfo实体类中添加离职时间字段
- 在WmsEmployeeInfoBo业务对象中添加离职时间及相关查询条件字段
- 在WmsEmployeeInfoVo视图对象中添加离职时间字段并配置日期格式
- 更新MyBatis映射文件添加离职时间字段映射
- 实现离职时间范围查询功能支持
2026-03-24 14:48:45 +08:00
890c6dd01d feat(wms): 添加操作类型多选筛选功能
- 在 WmsCoilPendingActionBo 中新增 actionTypes 字段支持多选
- 修改查询逻辑以支持单个操作类型或多个操作类型的筛选条件
- 使用 in 条件查询实现多选筛选功能
- 保持原有单选功能的兼容性
- 更新 Lambda 查询方式下的多选逻辑处理
2026-03-24 14:21:28 +08:00
砂糖
cbc4334db9 refactor(wms): 移除调试代码和注释,优化规格分割逻辑
移除console.log调试语句和已注释的代码
为specification.split添加空值保护,防止undefined错误
简化标签类型判断逻辑
2026-03-24 14:05:07 +08:00
砂糖
ae68b40ee6 refactor(wms): 重构物料信息展示逻辑,移除冗余组件
重构物料信息展示逻辑,统一使用itemName等字段替代原有的product和rawMaterial嵌套结构
删除不再使用的BomInfo、CategoryRenderer等冗余组件
新增report模块配置集中管理
优化代码结构,提升可维护性
2026-03-24 13:55:10 +08:00
9738a32d9d refactor(controller): 优化发货单详情控制器中的钢卷绑定列表查询
- 移除 WmsMaterialCoilVo 导入并添加 WmsMaterialCoilBindVo 导入
- 将 boundCoilList 方法返回类型从 WmsMaterialCoilVo 更改为 WmsMaterialCoilBindVo
- 调用 queryPageListWithBindInfo 方法替代 queryPageList 方法以获取绑定信息
2026-03-24 13:51:47 +08:00
66e529a068 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-24 13:25:19 +08:00
b39471ddac refactor(material-coil): 重构钢卷物料查询服务
- 移除 WmsMaterialCoilVo 中的嵌套对象结构(rawMaterial、product、bomItemList)
- 新增 WmsMaterialCoilBindVo 视图对象专门处理发货绑定信息
- 添加 queryPageListWithBindInfo 方法支持发货绑定增强字段查询
- 将联查字段改为扁平化结构,直接填充基础物料属性
- 优化分页查询逻辑,分离通用查询和绑定信息查询流程
- 移除 BOM 项批量查询功能,简化服务依赖关系
2026-03-24 13:25:10 +08:00
砂糖
e76799f4e0 feat(coil): 添加钢卷加工流程图组件并优化界面
- 新增ProcessFlow组件展示钢卷加工流程
- 在base面板中添加流程图显示开关
- 调整DragResizeBox的z-index确保显示层级
- 修复部分样式问题和代码格式
- 更新字典项从warehouse_sync改为wms_next_warehouse
2026-03-24 10:51:09 +08:00
74cf838844 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-24 10:36:59 +08:00
ad100083ed feat(wms): 添加钢卷库区操作记录导出功能以及优化查询速率
- 在服务接口中新增 exportBySecondWarehouseIdAndTimeRange 方法用于导出功能
- 在控制器中新增 exportByWarehouseAndTime 接口支持报表导出
- 在映射器中新增 selectVoListWithJoin 查询方法优化关联查询
- 在 XML 映射文件中新增完整的关联查询 SQL 和结果映射配置
- 在服务实现类中重构查询逻辑使用新的关联查询方法
- 新增 WmsCoilWarehouseOperationLogExportVo 导出数据对象
- 实现导出逻辑将操作记录转换为 Excel 格式并支持多表关联
- 添加状态描述转换方法支持中文显示
- 更新 VO 类继承 BaseEntity 基础实体类
2026-03-24 10:35:57 +08:00
砂糖
ccb0e2683a feat(waybill): 添加车牌号搜索功能并修改查询条件为模糊匹配
refactor(CoilSelector): 增加已选钢卷统计信息显示并优化样式

fix(report): 将actionQueryParams中的updateBy改为createBy
2026-03-24 10:01:14 +08:00
1fc85c990f Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-24 09:49:15 +08:00
e843cd7488 fix(wms): 修复运单查询中车牌号匹配逻辑
- 将车牌号精确匹配改为模糊匹配以支持部分查询
- 保留原有的非空检查逻辑确保查询条件正确应用
2026-03-24 09:49:05 +08:00
砂糖
396f861882 feat(打包模块): 新增打包单据功能及相关组件
refactor(CoilSelector): 修改change事件返回参数包含完整钢卷信息

chore: 添加打包模块相关图标和API文件

test: 添加打包模块单元测试

docs: 更新打包模块API文档
2026-03-24 09:16:22 +08:00
f5a8d35831 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-23 15:52:23 +08:00
b06e16aab6 feat(wms): 完善钢卷打包功能的事务处理和数据一致性
- 添加事务注解确保新增、修改、删除操作的数据一致性
- 新增对打包主表ID和钢卷ID的空值校验
- 实现打包记录重量自动更新功能,包括总毛重、总净重和钢卷数量
- 在删除打包记录时自动还原钢卷到原库区状态
- 添加对钢卷销售名称的同步更新处理
- 完善删除操作中的关联明细记录清理逻辑
- 新增钢卷存在性验证确保数据完整性
2026-03-23 15:52:13 +08:00
f87ac6149c 快速排查新增字段与前端保存逻辑 2026-03-23 15:39:02 +08:00
7f8a927502 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-23 15:33:46 +08:00
31f85e7cd6 快速排查新增字段与前端保存逻辑 2026-03-23 15:33:12 +08:00
84583bb052 feat(wms): 添加钢卷打包明细关联钢卷信息查询功能
- 在 WmsCoilPackingDetailServiceImpl 中新增 IWmsMaterialCoilService 依赖注入
- 为分页查询和列表查询方法添加钢卷信息丰富逻辑
- 实现 enrichCoilInfo 方法通过钢卷ID批量获取钢卷完整信息
- 重构 WmsCoilPackingRecordServiceImpl 中的详情查询逻辑
- 移除 WmsCoilPackingDetailVo 中冗余的钢卷字段定义
- 使用关联查询替代原有的独立字段存储方式
2026-03-23 15:23:01 +08:00
6029256b42 feat(WmsMaterialCoil): 添加排除已打包钢卷功能
- 在 WmsMaterialCoilBo 中新增 excludePacked 字段用于控制是否排除已打包钢卷
- 在 WmsMaterialCoilServiceImpl 的查询逻辑中添加对已打包钢卷的过滤条件
- 实现通过 excludePacked 参数防止钢卷重复打包的业务需求
- 优化查询性能避免返回不必要的已打包钢卷数据
2026-03-23 14:04:54 +08:00
ca8596cab7 fix(wms): 修复印章申请查询时根据创建人进行筛选
- 添加 StringUtils 工具类导入用于字符串判空
- 在查询条件中增加对 createBy 字段的非空字符串验证
- 防止空字符串作为查询条件导致的数据库异常
2026-03-23 13:10:46 +08:00
7a14cf7cb6 feat(wms): 扩展钢卷打包记录详情功能
- 在 WmsCoilPackingDetailVo 中新增钢卷相关字段包括入场钢卷号、当前钢卷号、厂家原料卷号等
- 添加 WmsMaterialCoilVo 引用到 WmsCoilPackingDetailVo 中存储钢卷完整信息
- 在 WmsCoilPackingRecordVo 中增加明细列表用于存储打包详情
- 实现服务层查询时自动关联钢卷详细信息并填充到返回结果中
- 优化查询逻辑支持分页和列表查询时同时获取关联的钢卷详情数据
2026-03-23 10:57:09 +08:00
3ed5b6a6ab feat(wms): 添加钢卷打包功能
- 在IWmsCoilPackingRecordService中新增packing方法接口
- 为WmsCoilPackingDetailBo添加saleName字段
- 为WmsCoilPackingRecordBo添加details列表字段
- 在WmsCoilPackingRecordController中新增executePacking接口
- 实现WmsCoilPackingRecordServiceImpl的packing方法,包含事务处理
- 添加钢卷打包的核心业务逻辑,包括重量计算、库存转移等
- 集成日志记录和重复提交防护功能
2026-03-23 10:39:50 +08:00
c1fe964d20 feat(wms): 添加钢卷打包记录功能模块
- 创建钢卷打包明细实体类WmsCoilPackingDetail及业务对象WmsCoilPackingDetailBo
- 创建钢卷打包记录主实体类WmsCoilPackingRecord及业务对象WmsCoilPackingRecordBo
- 实现钢卷打包明细服务接口IWmsCoilPackingDetailService及其实现类
- 实现钢卷打包记录主服务接口IWmsCoilPackingRecordService及其实现类
- 添加钢卷打包明细和记录的控制器WmsCoilPackingDetailController和WmsCoilPackingRecordController
- 创建对应的MyBatis映射器WmsCoilPackingDetailMapper和WmsCoilPackingRecordMapper
- 实现数据库映射文件WmsCoilPackingDetailMapper.xml和WmsCoilPackingRecordMapper.xml
- 添加视图对象WmsCoilPackingDetailVo和WmsCoilPackingRecordVo支持Excel导出功能
2026-03-23 10:10:36 +08:00
080fe1dd0f feat(material): 添加销售人员信息功能
- 在 WmsMaterialCoil 实体中新增 saleName 字段
- 在导出 VO 类中添加销售人员导出映射
- 在 Bo 类中添加销售人员查询条件字段
- 更新 MyBatis 映射文件中的查询结果映射
- 实现销售人员姓名模糊查询功能
- 添加销售关联数据的查询逻辑
2026-03-23 10:02:33 +08:00
dcff086f72 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-23 09:20:28 +08:00
e1dd76ee4a feat(employee): 添加员工信息和变动记录的排序功能
- 在WmsEmployeeInfoBo中新增sortByRegularTime和sortByEntryTime字段
- 实现员工信息按入职时间、转正时间或创建时间的倒序排序
- 添加员工变动记录按变动时间的倒序排序
- 实现员工转岗记录按转岗时间的倒序排序
- 优化查询条件构建逻辑,支持多维度排序需求
2026-03-23 09:20:19 +08:00
砂糖
ea73305ebb feat(员工信息): 添加时间范围筛选功能并新增员工报表页面
在员工信息各页面添加入职/转正/调岗/离职时间范围筛选功能
新增员工报表页面,包含统计卡片、图表和数据表格
2026-03-21 17:45:37 +08:00
99488b828a feat(employee): 添加员工转正时间范围查询功能
- 在 WmsEmployeeInfoBo 中新增转正开始时间和转正结束时间字段
- 为新字段添加 JSON 格式化和日期时间格式化注解
- 在服务实现中添加按转正时间范围查询的条件构建逻辑
- 支持通过转正开始时间和结束时间进行员工信息筛选查询
2026-03-21 15:25:40 +08:00
92c2fb2f28 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-21 15:20:13 +08:00
0eba0b5def feat(employee): 添加员工管理模块中的时间范围查询功能
- 在WmsEmployeeChangeBo中新增异动时间范围字段changeStartTime和changeEndTime
- 在WmsEmployeeInfoBo中新增入职时间范围字段entryStartTime和entryEndTime
- 在WmsEmployeeTransferBo中新增转岗时间范围字段transferStartTime和transferEndTime
- 为所有时间字段添加DateTimeFormat注解支持日期格式化
- 在对应的服务实现类中添加时间范围查询条件
- 实现时间段筛选逻辑以支持更精确的数据查询需求
2026-03-21 15:19:13 +08:00
砂糖
a48b148756 feat(报表组件): 为线圈表格添加筛选、排序和分页功能
添加关键词筛选、多列选择筛选、字段排序和分页控制功能
优化表格布局和响应式设计
重构数据处理逻辑实现前端筛选和排序
2026-03-21 14:10:01 +08:00
砂糖
e266f36e39 feat(员工信息): 添加转正记录查看功能并优化状态显示
- 在员工信息页面添加转正记录查看按钮和对话框
- 将超过90天未转正的状态显示从warning改为danger
- 移除表单中未使用的备注和附件字段
- 修改综合报表的时间参数命名以保持一致性
2026-03-21 13:47:58 +08:00
砂糖
69c43a7edf Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-21 10:40:17 +08:00
砂糖
1b22ec6173 feat(分条/更新): 添加复制源卷信息功能
在分条和更新页面添加复制源卷信息按钮,方便用户快速填充表单。复制时自动排除卷号等特定字段,并处理数值类型转换。同时优化了复制逻辑,确保相关字段的联动更新。
2026-03-21 10:40:14 +08:00
09de6e4e62 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-21 10:17:12 +08:00
14df649282 feat(wms): 优化卷材数据类型显示
- 移除 ExcelDictFormat 注解,改用文本字段显示数据类型
- 添加 dataTypeText 字段用于存储历史/现存文本描述
- 添加 isRelatedToOrderText 字段用于存储是/否文本描述
- 在服务层实现数据类型转换逻辑,将数字值转为对应文本
- 在服务层实现订单关联状态转换逻辑,将数字值转为对应文本
- 保持原有的 Excel 导出功能完整性
2026-03-21 10:17:02 +08:00
砂糖
0c86b80fb2 feat(标签打印): 统一标签字体样式并增强镀锌分步加工功能
- 为所有标签组件添加统一的粗体黑体字体样式
- 修改getGalvanize1TypingPrefill方法参数以支持分页查询
- 在分步加工面板中增加镀锌二级数据展示功能
- 优化分步加工逻辑,支持根据actionType动态加载数据
2026-03-21 10:10:21 +08:00
砂糖
4478921d9b feat(报表): 增强报表功能并优化标签显示
- 新增镀锌1预填接口和报表字段
- 优化标签材质显示逻辑,移除content前缀
- 增加报表分页大小选项和耗时格式化
- 扩展报表可选列和默认列配置
- 改进报表统计计算逻辑,考虑质量状态
- 调整报表页面大小限制为99999
2026-03-20 17:56:08 +08:00
25e4ce9b76 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-20 17:41:11 +08:00
0da1386a5d feat(material): 优化钢卷物料导出功能
- 添加Excel字典格式注解支持数据类型转换
- 新增钢卷ID字段用于数据关联
- 增加操作完成时间字段显示
- 实现根据操作ID查询钢卷待办动作完成时间
- 添加钢卷ID到数据库查询映射
- 重构导出查询逻辑支持操作完成时间获取
2026-03-20 17:39:41 +08:00
砂糖
3f503eab0c refactor(标签渲染): 将输入框替换为静态文本显示
移除标签渲染组件中的可编辑输入框,统一使用静态文本显示内容
恢复修正按钮功能,移除质量状态表单字段
注释掉未使用的统计信息组件
2026-03-20 15:15:51 +08:00
195df97521 二级更新计划新增软推荐,计划录入和实绩内容添加入场钢卷号信息 2026-03-20 14:46:10 +08:00
b2b1eed8a9 二级更新计划新增软推荐,计划录入和实绩内容添加入场钢卷号信息 2026-03-20 14:43:06 +08:00
d14e5d2a1d Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-20 13:37:14 +08:00
017961e3b2 OEE添加镀锌接口 2026-03-20 13:36:42 +08:00
砂糖
d6e30d4d50 feat(报表): 新增综合报表模板及M卷统计功能
新增综合报表模板,支持按不同仓库类型展示统计信息。添加M卷处理功能,在统计中自动过滤并计算M卷数据。优化报表展示顺序,默认显示产出钢卷。修复异常率计算问题,完善统计信息展示。

新增仓库特定报表页面,包括镀铬、拉矫、脱脂、双机架、镀锌和酸连轧成品库报表。调整KLPTable组件支持高度设置,优化基础面板显示逻辑。

修复API请求超时问题,统一设置超时时间为10分钟。调整标签显示文本,优化用户体验。
2026-03-20 13:34:56 +08:00
076b0e8e24 fix(wms): 修正钢卷列表异常排序逻辑
- 将异常钢卷排序从降序改为升序,确保异常钢卷始终排在前面
- 保持非异常钢卷按创建时间倒序排列的原有逻辑不变
2026-03-20 12:57:04 +08:00
dba9a02636 feat(WmsMaterialCoil): 添加钢卷按异常数量排序功能
- 在WmsMaterialCoilBo中新增orderByAbnormal字段用于控制排序方式
- 实现按异常数量排序逻辑:异常钢卷在前按创建时间倒序,无异常钢卷在后按创建时间倒序
- 使用CASE语句实现异常状态的条件排序
- 保持原有创建时间排序作为默认选项
2026-03-20 11:18:54 +08:00
b5d1dd64e6 fix(wms): 添加质量状态检查防止不合格钢卷发货
- 实现质量状态为O时的发货限制功能
- 添加"当前钢卷为质检未通过,请勿发货!"错误提示
- 确保只有合格钢卷才能进行发货操作
2026-03-20 11:04:08 +08:00
砂糖
e1cb4683af feat(wms报表): 添加正品率显示并优化异常统计
在报表模板中添加正品率(passRate2)显示项
重构getLossList调用逻辑,改为在getList完成后调用
优化calc.js中的异常统计计算,添加各异常库占比数据
2026-03-20 10:33:51 +08:00
7e1e4b7b62 OEE重构完成 2026-03-19 18:46:27 +08:00
52b77991d5 OEE添加合格品次品待判级内容 2026-03-19 18:41:08 +08:00
a858abccea Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-19 18:17:56 +08:00
ca14b88b18 OEE重构完成 2026-03-19 18:17:08 +08:00
砂糖
10cb260a2b refactor(employeeInfo): 移除家庭住址列并添加转正时间列
移除不再需要的家庭住址列,同时添加转正时间列以显示员工转正信息
2026-03-19 17:59:13 +08:00
砂糖
2c4f5b3e53 feat(钢卷异常): 重构钢卷异常表单组件并集成到各相关页面
新增AbnormalForm组件统一管理钢卷异常表单,减少代码重复
在合卷、分条、打字等页面添加异常信息管理功能
优化异常信息展示样式,支持添加、编辑和删除操作
2026-03-19 17:50:37 +08:00
砂糖
f4518be3f4 feat: 更新审批逻辑、分页功能及表格列显示
fix(leave): 将请假天数审批阈值从3天改为72小时
feat(coilTable): 添加分页大小和当前页改变处理方法
refactor(column): 简化发货相关表格列标题
feat(eqp): 在备件和辅料管理中添加机组筛选和显示
2026-03-19 16:14:56 +08:00
35cd5b03ff feat(eqp): 添加机组字段支持
- 在EqpAuxiliaryMaterial实体类中添加unitTeam字段
- 在EqpAuxiliaryMaterialBo业务对象中添加unitTeam字段
- 更新EqpAuxiliaryMaterialMapper.xml映射文件添加unitTeam映射
- 在EqpAuxiliaryMaterialServiceImpl服务实现中添加机组查询条件
- 在EqpAuxiliaryMaterialVo视图对象中添加unitTeam字段并配置Excel导出
- 在EqpSparePart实体类中添加unitTeam字段
- 在EqpSparePartBo业务对象中添加unitTeam字段
- 更新EqpSparePartMapper.xml映射文件添加unitTeam映射和查询字段
- 在EqpSparePartServiceImpl服务实现中添加机组查询条件
- 在EqpSparePartVo视图对象中添加unitTeam字段并配置Excel导出
2026-03-19 15:46:20 +08:00
f7b2d2c3bf Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-19 15:30:41 +08:00
1207072092 feat(wms): 新增用印审批功能
- 在审批API中添加按业务ID查询审批信息的方法
- 配置用印详情页面路由,支持通过业务ID查看用印详情
- 修改待办列表,为用印类型申请隐藏同意驳回按钮
- 在待办列表数据中添加业务ID字段,完善申请类型映射
- 更新审批服务接口和实现类,添加queryByBizId方法
- 重构用印详情页面,集成审批信息加载和权限校验逻辑
- 更新领域模型中的申请类型枚举,添加用印类型支持
- 完善审批任务服务,支持用印申请详情查询和申请人姓名显示
2026-03-19 15:30:28 +08:00
砂糖
5b6ad4796e feat(wms报表): 添加列设置功能并重构表格组件
引入可配置的列设置功能,允许用户自定义表格显示列
创建CoilTable通用组件替换原有表格实现
添加列设置对话框和默认列配置初始化逻辑
2026-03-19 15:08:04 +08:00
2a4fc70b72 feat(wms): 钢卷加工时添加异常信息
- 在 WmsMaterialCoilBo 中新增 abnormals 字段用于存储钢卷异常信息列表
- 注入 IWmsCoilAbnormalService 服务用于处理异常信息插入操作
- 在更新钢卷时同步插入关联的异常信息记录
- 在分卷操作中为子钢卷插入对应的异常信息
- 在合卷操作中为新钢卷插入合并的异常信息
- 在创建子钢卷时同时插入其异常信息记录
2026-03-19 11:52:35 +08:00
7f35c77590 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-19 10:54:38 +08:00
fe164edae1 feat(wms): 消耗报表拿到完成时间
- 在WmsMaterialCoilBo中新增actionIds字段用于存储操作记录ID列表
- 在WmsMaterialCoilVo中新增actionCompleteTime字段用于显示操作完成时间
- 修改listByPost接口支持通过actionIds查询钢卷数据并关联完成时间
- 添加对wms_coil_pending_action表的查询逻辑以获取钢卷ID和完成时间映射
- 实现actionIds解析、过滤和转换为Long类型的处理逻辑
- 添加coilPendingActionService和coilPendingActionMapper依赖注入
2026-03-19 10:54:21 +08:00
砂糖
d918ed2496 feat(员工信息): 添加转正和在情况筛选功能并增强员工信息管理
refactor(员工信息): 重构员工转正页面,增加更多查询条件和信息展示
feat(报表): 为合并报表添加规格计算功能
2026-03-19 10:33:53 +08:00
砂糖
9c9f2fa84d fix: 修改O卷标签并添加禁用O卷功能
更新优品卷标签为O卷,同时在CoilSelector组件中添加disableO属性以禁用O卷选择
在发货单相关组件中设置disableO为true,防止选择O卷
2026-03-18 18:14:29 +08:00
砂糖
fbe2340423 feat(wms报表): 新增各仓库的损耗、出库及日报表等组件
添加镀铬、拉矫、脱脂和双机架仓库的损耗报表、出库报表、日报表、月报表、年报表和班组报表组件
使用模板组件统一结构,根据不同仓库配置不同的actionTypes和queryParams
2026-03-18 17:07:20 +08:00
砂糖
dd32b86445 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-18 16:32:53 +08:00
砂糖
f46cee495a fix(wms): 修复酸轧判断条件格式错误
修复酸轧判断条件中的格式错误,移除多余的空行并添加括号以提升代码可读性
2026-03-18 16:32:50 +08:00
8df6ff1576 用印 2026-03-18 16:23:54 +08:00
砂糖
8f8729d2b2 feat(卷管理): 在技术页面添加优品卷标签页
添加优品卷标签页并设置默认激活,同时新增对应的查询参数配置
2026-03-18 16:05:54 +08:00
砂糖
0b451a9fb9 feat(报表): 添加宽度和厚度列并调整产品类型列宽
在合并报表页面中新增宽度和厚度显示列,同时将产品类型列的宽度从250调整为150以优化布局
2026-03-18 15:59:41 +08:00
砂糖
43d75de61f feat(wms报表): 添加宽度和厚度列并调整产品类型列宽
在团队、日、月、年和合并报表模板中,添加了宽度和厚度列,并将产品类型列的宽度从250调整为150,以优化表格布局并显示更多产品维度信息
2026-03-18 15:50:03 +08:00
砂糖
55af6de20b refactor(wms/report): 重构报表页面,提取公共组件和逻辑
将多个报表页面的公共逻辑提取到模板组件中,包括:
1. 创建out.vue和loss.vue作为基础模板
2. 重构zha.vue、zinc.vue等页面使用模板组件
3. 统一处理规格解析逻辑,添加宽度和厚度显示列
4. 优化仓库选择和查询参数处理
2026-03-18 15:41:09 +08:00
砂糖
69d2c4acc3 fix(hrm): 将请假时长单位从天改为小时
修改所有相关组件中的请假时长显示单位,从"天"改为"小时",包括图表、表格和表单中的标签。同时调整时间差计算逻辑,直接计算小时数而非天数。
2026-03-18 13:36:51 +08:00
砂糖
49331dcc24 feat(员工管理): 新增员工转正、转岗和离职功能
- 添加员工转正API和页面
- 新增员工转岗功能及相关API和页面
- 实现员工离职功能及相关API和页面
- 在员工信息页面添加在职天数显示
- 调整接收报表页面分页大小
- 完善员工入职补录表单
2026-03-18 13:09:40 +08:00
8fe459dae5 feat(wms): 添加员工转岗功能
- 在IWmsEmployeeTransferService中新增employeeTransfer方法
- 在WmsEmployeeTransferController中添加transfer接口
- 实现WmsEmployeeTransferServiceImpl中的员工转岗业务逻辑
- 添加事务注解确保数据一致性
- 在查询方法中关联员工信息表获取完整数据
- 验证员工状态确保在职员工才能转岗
- 记录转岗前后的部门和岗位信息
- 更新WmsEmployeeTransferVo以包含员工信息字段
2026-03-18 11:03:43 +08:00
7dcb779412 feat(employee): 添加员工转正状态管理功能
- 在WmsEmployeeInfo实体类中新增isRegular和regularTime字段
- 在WmsEmployeeInfoBo业务对象中添加转正相关属性定义
- 配置MyBatis映射文件中的转正状态字段映射关系
- 实现员工服务层中的转正状态查询条件过滤逻辑
- 在WmsEmployeeInfoVo视图对象中添加转正状态返回字段
2026-03-18 10:56:27 +08:00
70097733f6 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-18 10:53:22 +08:00
f7fdc03b5b feat(wms): 添加员工转正接口
- 在员工异动类型中新增转正选项(类型值为2)
- 更新数据库实体和业务对象中的异动类型定义
- 实现员工转正业务逻辑,包括状态验证和数据更新
- 添加转正API接口和相应的控制器方法
- 更新相关注释和文档以反映新的转正功能
- 修改Excel导出功能以支持转正类型的显示
2026-03-18 10:53:14 +08:00
砂糖
891f83f743 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-18 10:24:33 +08:00
砂糖
8e6f89ee55 feat(生产时间): 添加生产开始时间自动填充功能
在卷材操作的各个页面中,自动将待操作任务的创建时间设置为生产开始时间。同时在生产面板中新增生产时间相关字段的显示列
2026-03-18 10:24:28 +08:00
9c11ce7c9d Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-18 10:06:57 +08:00
8414d48dc8 feat(wms): 添加员工转岗记录管理功能
- 创建员工转岗记录实体类 WmsEmployeeTransfer
- 实现员工转岗记录服务接口 IWmsEmployeeTransferService
- 添加员工转岗记录控制器 WmsEmployeeTransferController
- 创建员工转岗记录数据访问层 WmsEmployeeTransferMapper
- 实现员工转岗记录业务逻辑 WmsEmployeeTransferServiceImpl
- 定义员工转岗记录业务对象 WmsEmployeeTransferBo 和视图对象 WmsEmployeeTransferVo
- 配置员工转岗记录 MyBatis 映射文件
- 实现员工转岗记录的增删改查功能
- 添加员工转岗记录导出功能
2026-03-18 10:06:48 +08:00
砂糖
3d6391bf32 feat(钢卷管理): 新增生产时间记录及耗时计算功能
添加TimeInput组件用于时间输入,并在钢卷合并、分条、打字、分步操作中增加生产开始/结束时间字段
实现生产耗时自动计算功能,支持显示xx天xx小时xx分钟格式
在基础面板中增加生产时间修正对话框,支持批量修改时间
2026-03-17 18:01:46 +08:00
砂糖
3c9f82add4 feat: 添加开始时间列并优化发货单打印功能
- 在coil面板的do.vue中添加开始时间列
- 新增widthEdit.vue组件用于宽度编辑
- 修改MaterialTag.vue中的标签显示为厂家名称
- 合并发货单打印功能,添加吨数统计显示
2026-03-17 17:07:49 +08:00
砂糖
b6387a53d8 feat(钢卷异常): 重构异常记录功能,增加开始/结束位置字段
refactor(发货单): 添加发货计划选择功能

feat(报表): 新增合并报表页面,支持投入产出钢卷统计

style: 移除多余的空格和注释代码
2026-03-17 14:52:54 +08:00
3c745b8ce4 feat(wms): 更新钢卷异常实体类增加缺陷详细信息字段
- 将lengthCoord字段替换为length、startPosition、endPosition三个精确数值字段
- 新增defectType缺陷类型字段用于详细分类(如划痕、边裂、厚度超标等)
- 新增defectRate缺陷率字段用于记录百分比数据
- 新增defectWeight缺陷重量字段用于记录具体重量值
- 新增mainMark主标记字段标识是否为主要缺陷
- 新增wholeCoilMark整卷标记字段标识是否影响整卷
- 更新Mapper映射文件适配新的实体字段结构
- 更新查询条件构造器支持新增字段的筛选功能
- 更新VO类Excel导出配置适配新的业务字段需求
2026-03-17 13:59:13 +08:00
76aff879c7 feat(WmsMaterialCoil): 添加生产时间和预留宽度字段支持
- 在 WmsMaterialCoil 实体类中新增生产开始时间、生产结束时间、生产耗时和预留宽度字段
- 在 WmsMaterialCoilBo 业务对象中添加对应的生产时间相关字段和格式化注解
- 在 WmsMaterialCoilVo 视图对象中增加生产时间字段和 Excel 导出支持
- 更新 MyBatis 映射文件中的结果映射和查询字段列表
- 在服务实现类中添加生产时间相关的查询条件过滤逻辑
2026-03-17 13:54:17 +08:00
7632c63185 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-17 10:07:13 +08:00
f8b2d2458c refactor(WmsFurnacePlanService): 移除逻辑库位禁用功能
- 删除了设置仓库为禁用状态的相关代码
- 移除了updateById调用以禁用指定warehouseId的仓库记录
- 简化了炉计划服务中的仓库状态管理逻辑
2026-03-17 10:05:28 +08:00
砂糖
347ec849ae feat(annealPlan): 添加钢卷绑定信息更新功能并优化界面
- 新增updateAnnealPlanCoil API用于更新钢卷绑定信息
- 移除加入计划按钮的状态限制
- 将实际库位改为钢卷去向选择器并添加钢卷层级输入
- 实现钢卷信息变更自动保存功能
- 按层级排序钢卷列表
- 完善完成处理时的库位校验逻辑
2026-03-17 09:48:17 +08:00
0aee6cecaa feat(wms): 添加退火计划钢卷关系管理功能
- 创建了IWmsFurnacePlanCoilService接口定义CRUD操作方法
- 实现了WmsFurnacePlanCoilServiceImpl业务逻辑处理类
- 添加了WmsFurnacePlanCoilController REST控制器提供API接口
- 配置了WmsFurnacePlanCoilMapper.xml数据库映射文件
- 实现了分页查询、新增、修改、删除和导出功能
- 集成了数据验证、日志记录和重复提交防护机制
2026-03-17 09:23:28 +08:00
砂糖
65d7e4a1fd feat(wms): 新增退火计划控制页面并优化性能展示
refactor(anneal): 重构退火计划页面布局和交互逻辑
style(anneal): 调整表单元素换行和表格列宽
2026-03-16 17:54:56 +08:00
砂糖
53692fd024 fix(EmployeeSelector): 修复员工选择器中重复员工的问题
因为员工可能出现重名情况,添加去重逻辑确保selectedEmployees中每个员工的keyField是唯一的
2026-03-16 17:32:28 +08:00
砂糖
b6b460386e refactor(wms): 移除导出文件名中的日期参数
文件名已使用时间戳保证唯一性,移除冗余的日期参数以简化命名
2026-03-16 17:06:26 +08:00
砂糖
cff26eaac7 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-16 16:58:08 +08:00
砂糖
bb78fba24e feat(wms/report): 新增合并报表模板及多个物料类型页面
添加合并报表通用模板组件merge.vue,包含统计信息展示、明细查询及导出功能
创建acid/duge/zinc/lajiao/shuang/tuozhi等物料类型的报表页面,通过actionType区分不同物料类型
2026-03-16 16:58:06 +08:00
95987d352c refactor(wms): 完成退火选逻辑库位而不是实际库位
- 修改 WmsFurnacePlanLocationItemBo 中的 actualWarehouseId 字段为 warehouseId
- 更新验证注解消息从"实际库位"改为"逻辑库位"
- 修改 occupyActualWarehouse 方法为 occupyWarehouse 并调整参数
- 替换 ActualWarehouse 相关操作为 Warehouse 操作
- 在占用库位时同步更新 wmsfurnace_plan_coil 表中的逻辑库区信息
- 更新服务实现中所有相关字段引用和方法调用
2026-03-16 16:45:52 +08:00
4c26e708da Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-16 15:58:19 +08:00
10a28f8c62 feat(analytics): 更新炉火实绩功能以支持详细的钢卷信息以及层级和库区信息
- 在 WmsAnnealPerformanceDetailVo 中新增逻辑库区ID、库区名称、炉火层级和钢卷列表字段
- 修改 WmsAnnealPerformanceMapper.xml 查询语句以优化性能并移除冗余字段
- 在 WmsAnnealPerformanceServiceImpl 中实现批量查询逻辑,包括钢卷关联、库区信息和钢卷详情
- 新增仓库映射器和服务依赖注入以支持数据获取
- 在 WmsMaterialCoilVo 中添加炉火层级字段以存储钢卷在炉内的层数信息
- 实现按计划ID分组处理钢卷数据并设置相应的库区和层级属性
2026-03-16 15:58:10 +08:00
砂糖
71e2467572 feat(wms): 优化退火炉界面和修复钢卷合卷功能
- 重构退火炉界面为卡片式布局,增加可视化状态展示
- 修复钢卷合卷API路径和方法,添加操作ID和类型参数
- 移除标签打印中冗余的itemName字段
- 修复退火计划物料卡片布局自适应问题
2026-03-16 15:38:11 +08:00
砂糖
e5821a3f68 fix(wms): 提高html2canvas缩放比例并优化发货单页面布局
调整wayBill和wayBill2组件的html2canvas缩放比例从3提高到6,以获得更清晰的打印效果
重构发货单页面布局,将表格和分页组件放入滚动容器,表单区域设为固定位置
2026-03-16 15:34:53 +08:00
d8821db4b2 refactor(WmsMaterialCoilService): 优化合卷操作的待办事项处理流程
- 调整代码执行顺序,先创建待操作记录再执行合卷操作
- 引入中间步骤收集原始钢卷与操作ID的映射关系
- 修改待办事项状态更新时机,在合卷完成后统一更新为已完成
- 为新创建的待办事项设置初始状态为处理中而不是直接完成
- 修复空指针检查逻辑,同时验证coilId和actionType非空
- 重构操作记录更新流程,确保在合卷成功后再更新processedCoilIds
2026-03-16 15:29:05 +08:00
a51c5a4d88 feat(wms): 添加钢卷退火计划中的逻辑库区和炉火层级功能
- 在 WmsFurnacePlanCoil 实体类中新增逻辑库区ID和炉火层级字段
- 在 WmsFurnacePlanCoilBo 中添加对应的业务对象属性
- 在 WmsFurnacePlanCoilVo 中增加Excel导出相关字段和映射
- 更新 WmsFurnacePlanServiceImpl 服务实现类中的依赖注入
- 实现逻辑库区信息的查询和名称设置功能
- 将逻辑库区ID和炉火层级信息保存到数据库中
2026-03-16 14:47:02 +08:00
275f6181ce feat(wms): 在操作记录中添加合卷之后的钢卷
- 在 IWmsMaterialCoilService 中新增 mergeCoils 方法实现合卷操作
- 扩展 WmsMaterialCoilBo 类添加 actionId、actionType 和 mergedCoilId 字段
- 在 WmsMaterialCoilController 中添加 /merge 接口支持合卷新功能
- 实现合卷逻辑为 newCoils 中每个被合的卷添加 actionId 和 actionType
- 支持通过 actionId 更新操作记录状态并设置完成时间
- 实现合卷后新钢卷 ID 的返回和操作记录的自动创建更新
2026-03-16 14:10:17 +08:00
58653da48b Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-16 13:20:50 +08:00
f84168396c feat(wms): 添加加工后钢卷ID字段支持
- 在WmsCoilPendingAction实体类中新增processedCoilIds字段
- 在WmsCoilPendingActionBo业务对象中添加processedCoilIds属性
- 更新WmsCoilPendingActionMapper.xml映射文件中的结果映射
- 在WmsCoilPendingActionServiceImpl服务实现中添加模糊查询条件
- 在WmsCoilPendingActionVo视图对象中增加processedCoilIds字段
2026-03-16 13:20:40 +08:00
砂糖
3b26b060db Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-16 13:15:57 +08:00
砂糖
b27f246fa0 feat(钢卷): 重构标签打印逻辑并添加合卷操作功能
重构钢卷标签打印逻辑,提取公共方法到coilPrint.js
添加合卷操作区功能,支持200-299操作类型
为合卷表单添加验证规则
2026-03-16 13:15:54 +08:00
e84e41b20f Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-16 10:56:55 +08:00
a22d79b858 feat(wms): 入炉钢卷不能被操作
- 在退火计划取消时将钢卷独占状态设置为2(退火中)
- 在实际库位占用时将钢卷独占状态设置为0(未独占)
- 扩展独占状态枚举值:0=未独占,1=单步分卷中,2=退火中
- 修改钢卷独占状态检查方法为获取完整状态值
- 增强钢卷操作权限验证,支持多种独占状态判断
2026-03-16 10:56:39 +08:00
砂糖
d613058104 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-16 10:41:53 +08:00
砂糖
c8f576dea3 refactor(wms): 优化合卷逻辑和员工选择组件
- 移除合卷流程中的箭头图示和最小源卷数量限制
- 修改处理时间显示为完成时间并更新相关字段
- 优化员工选择组件的前端筛选和取消操作处理
2026-03-16 10:41:50 +08:00
4d21c43416 refactor(KLPApplication): 移除Flyway自动配置 删除数据库表
- 移除了对FlywayAutoConfiguration的排除配置
- 恢复默认的Spring Boot自动配置行为
- 简化了应用程序启动配置
2026-03-16 09:41:12 +08:00
8972a45fcc refactor(database): 移除Flyway数据库迁移配置
- 从application.yml中移除flyway相关配置项
- 从application-dev.yml中移除flyway相关配置项
- 从application-prod.yml中移除flyway相关配置项
- 将EmsEnergyConsumptionController中的StringUtils替换为Spring工具类
- 删除FlywayConfig配置类及其命令行启动器实现
- 从klp-common模块的pom.xml中移除flyway依赖
- 从根pom.xml中移除flyway核心依赖
2026-03-16 09:29:53 +08:00
砂糖
319553702e Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-16 09:05:16 +08:00
砂糖
f2c7e20eb6 feat(标签打印): 添加钢卷标签打印功能并调整标签样式
- 在入库页面添加打印按钮及处理逻辑
- 修改标签样式,使用黑体并设置黑色字体
- 添加隐藏的label-render组件用于打印
2026-03-16 09:05:12 +08:00
bd565aba8e Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-15 15:10:38 +08:00
5487f04cf5 完成wip-退火模块 2026-03-15 15:10:17 +08:00
砂糖
3ff82f85dc Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-15 11:03:53 +08:00
砂糖
5a3ff60fca refactor(wms): 优化物料标签显示布局并调整样式
- 将仓库名称从输入框改为直接显示文本
- 移除未使用的库区和班组输入框
- 新增规格和班组显示行
- 调整值单元格的字体加粗样式
2026-03-15 11:03:49 +08:00
9a645100df 更新wip-退火 缺少实际库区选择,重新占据库位能力 2026-03-14 18:39:19 +08:00
砂糖
8c2b85edf1 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-14 18:09:45 +08:00
砂糖
c30c755df0 feat(合卷操作): 扩展合卷操作类型范围支持200-299
fix(文件上传): 添加docx到默认支持文件类型列表
refactor(员工信息): 统一部门字段命名并修复备注字段
feat(酸轧合卷): 实现酸轧合卷页面功能
feat(员工入职): 新增员工入职页面及功能
style(合卷页面): 优化合卷页面布局和样式
2026-03-14 18:07:30 +08:00
7740531fc5 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-14 15:16:40 +08:00
8cc5549850 更新快速排查功能 2026-03-14 15:06:18 +08:00
砂糖
27dbed7b35 feat(wms): 新增员工异动管理功能并优化员工信息界面
refactor(员工信息): 重构员工信息界面,使用下拉选择替代输入框
feat(员工异动): 新增员工入职和离职功能及相关API
fix(合卷): 修复扫码日期格式化问题
style(交付): 统一结算类型为卷重结算
2026-03-14 15:00:02 +08:00
9b82d7230a feat(wms): 新增员工入职离职功能
- 在 IWmsEmployeeChangeService 中添加 employeeEntry 和 employeeLeave 方法
- 扩展 WmsEmployeeChangeBo 类增加员工详细信息字段
- 在 WmsEmployeeChangeController 中添加入职和离职接口
- 实现 WmsEmployeeChangeServiceImpl 的入职离职业务逻辑
- 集成员工信息查询功能并在查询结果中关联员工详情
- 添加事务管理确保数据一致性操作
2026-03-14 10:40:44 +08:00
0091a46811 feat(employee): 添加员工离职状态字段
- 在WmsEmployeeInfo实体类中添加isLeave字段
- 在WmsEmployeeInfoBo业务对象中添加isLeave字段
- 在WmsEmployeeInfoVo视图对象中添加isLeave字段
- 在MyBatis映射文件中添加isLeave字段映射
- 在查询条件构造器中添加离职状态筛选逻辑
2026-03-14 09:57:31 +08:00
e0b4d16701 feat(wms): 添加员工异动管理功能
- 创建员工异动实体类 WmsEmployeeChange,包含异动记录主键、员工信息关联、异动类型等字段
- 定义员工异动业务对象 WmsEmployeeChangeBo 和视图对象 WmsEmployeeChangeVo
- 实现员工异动服务接口 IWmsEmployeeChangeService 及其具体实现类 WmsEmployeeChangeServiceImpl
- 添加员工异动数据访问层 WmsEmployeeChangeMapper 及对应的 MyBatis XML 映射文件
- 开发员工异动控制器 WmsEmployeeChangeController,提供增删改查及导出功能
- 集成分页查询、数据校验、重复提交防护等通用功能
2026-03-14 09:54:40 +08:00
砂糖
80640b5b39 feat(钢卷管理): 添加钢卷追溯功能并调整次品标签顺序
在correct.vue中添加钢卷追溯功能,包括追溯对话框和API调用
调整scrap.vue中次品标签的位置,使其显示在第一个标签页
在correct.vue中新增逻辑库区查询条件
2026-03-13 17:43:24 +08:00
砂糖
8f1e8c9381 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-13 11:25:04 +08:00
砂糖
60576864bf fix(coil): 修复工序面板显示及仓库选择逻辑
修复镀锌工序面板中无进行中工序的显示问题,使用动态label替代硬编码
修复currentTab为0时仓库ID未清空的问题
添加纵剪分条工序的仓库选项并更新特殊分割逻辑
2026-03-13 11:25:00 +08:00
砂糖
f4be9312c3 feat(钢卷修正): 添加钢卷类型筛选和强制入库功能
- 在搜索栏新增钢卷类型下拉选择框,支持按不同类型筛选钢卷
- 为未入库钢卷添加强制入库按钮及处理逻辑
- 根据选择的钢卷类型动态调整查询参数
2026-03-13 11:24:50 +08:00
56b05a02a1 fix(wms): 解决已发货钢卷占用实际库区的问题
- 添加了对已发货钢卷的状态检查,防止其占用实际库区
- 实现了已发货钢卷释放旧库区的功能
- 优化了库区状态更新逻辑,增加了对-1标识的判断
- 在钢卷占用库区时添加了发货状态验证

refactor(da): 优化酸轧OEE月度任务初始化方式

- 将@PostConstruct替换为ApplicationRunner接口实现
- 添加@Async注解实现异步执行,避免阻塞项目启动
- 重构了启动时OEE汇总计算的执行时机和方式
2026-03-13 10:58:59 +08:00
64d1d4683b feat(mapper): 添加根据操作ID和删除标志查询功能
- 在WmsCoilPendingActionMapper接口中新增selectByActionIdAndDelFlag方法
- 在WmsCoilPendingActionMapper.xml中添加对应的SQL查询语句
- 修改WmsCoilPendingActionServiceImpl中的查询逻辑使用新方法
- 移除原有的QueryWrapper查询方式并导入UpdateWrapper依赖
2026-03-12 17:24:14 +08:00
93e3a71c50 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-12 17:05:31 +08:00
bfba3ce49a feat(warehouse): 添加库位排序号修正功能并优化钢卷查询排序
- 在 IWmsActualWarehouseService 中新增 fixSortNoByParentId 方法用于修正库位排序号
- 在 WmsActualWarehouseController 中新增 /fixSortNo/{parentId} 接口
- 实现 WmsActualWarehouseServiceImpl 中的 fixSortNoByParentId 业务逻辑
- 添加正则表达式处理库位编码的排序键解析
- 新增 WmsMaterialCoilMapper 的 selectVoPagePlusOrderBy 查询方法
- 重构 WmsMaterialCoilMapper.xml 中的排序辅助字段查询逻辑
- 修改 WmsMaterialCoilServiceImpl 中的分页查询逻辑以支持排序功能
2026-03-12 17:05:22 +08:00
砂糖
3e9a08308f feat(卷材管理): 添加实测长度和实测宽度字段
在卷材管理的多个组件和视图中添加实测长度(actualLength)和实测宽度(actualWidth)字段,包括显示、表单输入和数据模型。这些字段用于记录卷材的实际测量尺寸,提高数据记录的准确性。
2026-03-12 17:03:02 +08:00
e589bb6496 feat(mapper): 添加删除标志更新功能到WmsCoilPendingActionMapper
- 新增updateDelFlag方法用于直接更新删除标志
- 绕过@TableLogic注解限制实现逻辑删除
- 添加方法参数验证和返回值定义
- 完善JavaDoc注释说明方法
2026-03-12 16:51:54 +08:00
db8696f9e7 feat(wms): 添加钢卷待操作记录恢复功能
- 在restoreAction方法中添加actionId参数非空验证
- 添加updateDelFlag自定义SQL方法绕过@TableLogic注解限制
- 修改restoreAction逻辑使用新的updateDelFlag方法更新删除标志
- 优化异常处理使用ServiceException替换RuntimeException
- 修正查询条件将del_flag检查从2改为1表示已删除状态
2026-03-12 16:48:16 +08:00
2b213f7475 feat(wms): 添加钢卷实测尺寸功能并优化库位排序
- 在WmsMaterialCoil实体类中新增actualLength和actualWidth字段
- 在WmsMaterialCoilBo业务对象中添加实测长度宽度属性
- 在WmsMaterialCoilVo视图对象中增加Excel导出注解配置
- 更新MyBatis映射文件添加实测尺寸数据库字段映射
- 实现根据实测长度宽度的查询过滤功能
- 优化库位排序逻辑,增加全局交错排序辅助字段
- 添加库位层级排序键和库位ID键用于精确排序控制
2026-03-12 16:32:09 +08:00
0abec84a2e feat(domain): 添加删除逻辑注解到待处理
- 在WmsCoilPendingAction实体的delFlag字段上添加@TableLogic注解
- 实现软删除功能以支持数据恢复操作
2026-03-12 16:30:25 +08:00
砂糖
223a745991 feat(钢卷待操作): 新增还原已删除记录功能并优化查询
新增还原已删除钢卷待操作记录的功能,包括前后端接口实现。优化查询逻辑,支持查看已删除记录。调整页面操作状态显示为下拉选择,并增加删除/还原按钮的显示控制。同时修改多处报表页面的分页参数为9999以提高数据展示量。

修改删除标志查询条件,将已删除状态从1改为2以区分逻辑删除状态。在钢卷待操作页面增加"查看被删除操作"复选框,支持切换显示正常/已删除记录。
2026-03-12 16:23:45 +08:00
5f8ec04a17 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-12 14:29:40 +08:00
ae410d85e5 feat(wms): 添加钢卷待操作列表查询功能支持已删除记录
- 新增listPendingActionWithDeleted方法用于查询包含已删除记录的钢卷待操作列表
- 新增listDeletedPendingAction方法用于仅查询已删除的钢卷待操作列表
- 在WmsCoilPendingActionBo中添加includeDeleted字段支持三种查询模式
- 修改WmsCoilPendingActionServiceImpl实现支持includeDeleted参数的逻辑删除过滤
- 支持includeDeleted参数值为0(不包含已删除)、1(包含已删除)、2(仅查询已删除)三种模式
2026-03-12 14:29:28 +08:00
砂糖
016e5dc246 feat(钢卷管理): 新增钢卷物料添加功能并优化修正功能
将新增按钮从基础面板移至修正页面,并实现新增钢卷物料的功能
优化修正功能,根据操作类型动态显示标题
新增时隐藏创建时间和创建人字段
2026-03-12 11:49:46 +08:00
砂糖
c766904b45 feat(组件): 为DragResizeBox添加localStorage持久化功能
添加storageKey属性支持将位置和尺寸保存到localStorage
初始化时优先读取存储值,拖动结束后自动保存
同时优化了CoilSelector的钢卷地图显示逻辑
2026-03-12 10:41:19 +08:00
砂糖
3c96211cc5 feat(wms): 添加订单号显示并改进日期格式化功能
1. 在发货单组件中增加订单号显示,替换原有电话字段
2. 实现统一的日期格式化工具函数,修复参数冲突问题
3. 发货操作后自动添加待操作记录
4. 优化钢卷操作中的日期处理逻辑
2026-03-12 09:20:23 +08:00
砂糖
5b6286326b feat(HRM): 添加附件显示组件并优化表单逻辑
添加FileList组件用于显示附件列表
在请假和外出申请详情页中显示附件
优化审批部门选择逻辑,仅在新增时显示
修复请假申请编辑时的审批类型校验问题
2026-03-11 16:48:44 +08:00
砂糖
f561b4eb0b feat(审批): 添加撤回审批功能并优化审批状态显示
- 在approval.js中添加withdrawApproval API方法
- 在leave.vue和goout.vue中启用撤回按钮并调用新API
- 在todo/index.vue中优化审批状态显示逻辑
2026-03-11 16:03:14 +08:00
30a06d297b feat(approval): 添加审批撤销功能
- 在IWmsApprovalService中新增cancelApproval方法定义
- 在IWmsApprovalTaskService中新增deleteByApprovalId方法定义
- 在WmsApprovalController中新增cancelApproval接口
- 在WmsApprovalServiceImpl中实现撤销审批业务逻辑
- 在WmsApprovalTaskServiceImpl中实现按审批ID删除任务功能
- 添加撤销审批的权限验证和重复提交限制
- 实现审批状态校验和关联任务清理机制
2026-03-11 15:52:28 +08:00
70b9d620b2 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-11 15:21:37 +08:00
71c7876bf9 feat(wms): 添加审批流程按创建人筛选功能
- 在WmsApprovalServiceImpl中增加根据创建人筛选条件
- 使用StringUtils判断创建人参数是否为空避免查询异常
- 保持原有查询逻辑不变仅增加创建人筛选功能
- 按照创建时间倒序排序逻辑不受影响
2026-03-11 15:21:29 +08:00
砂糖
fb96148d1f feat(钢卷管理): 添加厂家原料卷号校验功能
在钢卷入库表单中,将厂家原料卷号设为必填项并添加远程校验逻辑,防止重复卷号入库
2026-03-11 15:10:17 +08:00
砂糖
8d73342e9e feat(wms): 添加镀锌纵剪分条原料库支持并扩展分条功能
扩展分条功能以支持更多工序类型,包括镀锌、脱脂、拉矫平整等。添加镀锌纵剪分条原料库选项,并改进分条按钮样式和操作流程。同时调整时间格式显示为更易读的形式。

新增镀铬工序分条支持,优化分条操作界面显示当前工序名称。修复分条列表加载逻辑,确保在操作类型有效时才进行加载。添加新的分条操作页面用于管理分条任务。
2026-03-11 14:52:59 +08:00
b61cea837a Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-11 14:18:19 +08:00
09c8b9cc4a feat(material): 钢卷特殊分卷功能新增操作类型参数
- 在IWmsMaterialCoilService接口中为startSpecialSplit方法添加actionType参数
- 在WmsMaterialCoilController控制器中接收前端传递的操作类型参数
- 在WmsMaterialCoilServiceImpl实现类中将操作类型参数传递给待处理动作对象
- 修改事务处理逻辑以支持动态操作类型设置
2026-03-11 14:18:11 +08:00
砂糖
aa286d66f2 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-11 13:10:14 +08:00
砂糖
6f6acf0c3c feat(发货单): 添加简单打印功能
新增简单打印功能按钮,支持选择不同打印模板。引入WayBill2组件作为简单打印模板,通过printType控制显示不同模板。
2026-03-11 13:10:11 +08:00
18bffc4325 feat(employee): 添加员工社保类型字段
- 在 WmsEmployeeInfo 实体类中新增 socialInsuranceType 字段
- 在 WmsEmployeeInfoBo 业务对象中新增 socialInsuranceType 字段
- 在 WmsEmployeeInfoVo 视图对象中新增 socialInsuranceType 字段
- 在 MyBatis 映射文件中添加社保类型字段映射配置
- 在查询条件构建器中添加社保类型筛选条件
2026-03-11 11:15:37 +08:00
12207aa421 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-11 11:15:08 +08:00
7679b0475a fix(wms): 修复待处理查询的时间字段改为更新时间
- 将查询条件从 update_time 修改为 complete_time 字段
- 确保开始时间和结束时间筛选使用正确的完成时间字段
2026-03-11 11:15:01 +08:00
砂糖
b6add4e739 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-03-11 10:47:52 +08:00
砂糖
e1fbb7805f feat(CoilSelector): 添加可拖拽库位视图和品质列显示
refactor(WarehouseInterlaced): 修复props格式问题
fix(DuGeTag): 修正电话号码格式
2026-03-11 10:47:49 +08:00
ba6b2e201f fix(wms): 解决钢卷删除时二维码状态未同步失效的问题
- 在删除合卷钢卷时将对应的二维码记录状态更新为失效
- 在删除子钢卷时将对应的二维码记录状态更新为失效
- 在删除普通钢卷时将对应的二维码记录状态更新为失效
- 确保钢卷删除后二维码无法继续使用避免重复操作
2026-03-11 10:42:58 +08:00
7133ac4225 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-11 09:14:23 +08:00
3afc296e40 feat(service): 扩展钢卷号重复检查功能支持厂家原料卷号
- 在 checkCoilNoDuplicate 方法中新增 supplierCoilNo 参数
- 添加厂家原料卷号重复检查逻辑并排除自身记录
- 更新重复类型判断增加 supplier 选项
- 完善返回结果包含厂家原料卷号重复状态
- 同步更新控制器层接口参数传递
- 修正方法注释文档说明新增参数和返回值字段
2026-03-11 09:14:13 +08:00
砂糖
a6efe02046 feat(透视表): 添加检查今日透视表是否存在的功能并优化空状态显示
添加checkCoilStatisticsSummaryExist接口检查今日是否已创建同类型透视表
在创建透视表前进行校验并提示用户是否覆盖
优化空状态显示为el-empty组件
2026-03-10 17:02:11 +08:00
1862908eb1 refactor(service): 修改统计记录检查方法返回类型
- 将 checkExistsByStatTypeToday 方法返回值从 Boolean 改为 Long
- 服务层实现中返回存在的记录ID,不存在则返回null
- 控制器接口同步更新返回类型和文档注释
- 优化查询逻辑直接返回记录ID而不是布尔值
2026-03-10 16:50:08 +08:00
9e5e7cf0af Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-10 16:28:17 +08:00
927cbf9586 feat(wms): 添加钢卷统计记录存在性检查功能
- 在服务接口中新增 checkExistsByStatTypeToday 方法用于检查当天指定类型统计记录的存在性
- 在控制器中新增 /checkToday 接口提供统计记录存在性检查服务
- 在服务实现类中实现具体的数据库查询逻辑,使用日期函数过滤当天数据
- 添加参数校验确保统计类型参数不为空
- 使用分页限制优化查询性能,仅返回是否存在标识
2026-03-10 16:28:07 +08:00
砂糖
da2caa1c46 fix(wms): 修复透视表数据展示和边料统计问题
修复透视表预览条件判断错误,将currentRow.summaryId改为liveData
修正边料统计接口调用错误,将listCoilTrimStatistics改为listMaterialCoil
添加可选链操作符处理可能为null的数据遍历
2026-03-10 16:18:21 +08:00
砂糖
6e909212bf feat(标签系统): 添加脱脂原料库标签类型并优化透视表功能
新增脱脂原料库标签类型6及相关组件TuoZhiTag
优化透视表功能,增加保存明细选项和导出功能
在标签渲染组件中添加对脱脂原料库类型的判断
更新相关API调用和UI交互逻辑
2026-03-10 15:38:22 +08:00
e937ff50f6 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-10 14:03:48 +08:00
891ec659de refactor(service): 修改钢卷统计汇总服务返回值类型
- 将 insertByBo 方法返回值从 Boolean 改为 WmsCoilStatisticsSummaryVo
- 更新控制器方法返回完整的业务对象而不是布尔值
- 实现新增后查询并返回完整的汇总记录信息
- 提供更丰富的新增操作响应数据
2026-03-10 14:03:38 +08:00
砂糖
730148e966 feat(wms): 新增导出功能并优化发货单显示
- 在base.vue中新增导出按钮和按库区排序选项
- 添加exportCoilWithAll API接口用于批量导出
- 在waybill.vue中新增showNewExport属性控制导出按钮显示
- 优化发货单页面显示,增加订单编号和备注显示
- 新增delivery/canuse页面用于展示可用钢卷
- 修复发货单修改时订单编号显示问题
2026-03-10 13:33:30 +08:00
8927760eb1 refactor(WmsMaterialCoilService): 替换查询包装器实现以优化导出功能
- 将 queryExportList 方法中的 buildQueryWrapper 替换为 buildQueryWrapperPlus
- 移除旧的 buildQueryWrapper 方法及其完整的查询条件构建逻辑
- 保留导出列表的基本查询和数据处理流程
2026-03-10 13:14:09 +08:00
328c46b8b8 refactor(material): 优化材料卷查询导出功能
- 将查询包装器构建方法从 buildQueryWrapper 替换为 buildQueryWrapperPlus
- 提升导出列表查询的数据完整性和准确性
2026-03-10 11:58:34 +08:00
c21f5dc813 feat(material): 添加钢卷物料完整字段导出功能
- 新增 WmsMaterialCoilAllExportVo 完整字段导出 VO 类
- 在 IWmsMaterialCoilService 中添加 queryExportListAll 方法
- 实现 queryExportListAll 方法支持完整字段导出
- 添加 /exportAll 接口支持完整字段导出
- 更新数据库查询映射添加班组和发货人字段
- 修改 WmsMaterialCoilExportVo 添加班组、业务用途等字段
- 调整导出接口注释从完整字段改为精简字段描述
2026-03-10 11:47:42 +08:00
c5089faaea Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-03-10 10:43:08 +08:00
f5017443d5 feat(wms): 新增卷材统计摘要附件功能
- 在 WmsCoilStatisticsSummary 实体中添加 attachmentInfo 字段
- 在 WmsCoilStatisticsSummaryBo 中添加 attachmentInfo 字段
- 在 WmsCoilStatisticsSummaryVo 中添加 attachmentInfo 字段
- 更新 Mapper XML 映射文件中的结果映射配置
- 修改 Vo 类继承 BaseEntity 基类
2026-03-10 10:42:57 +08:00
砂糖
f5904fa7f3 feat(wms): 添加次品标签页并优化钢卷统计表格
refactor(LeftList): 移除表单包装简化对话框结构
feat(Perspective): 新增宽度分类统计组件
perf(TrimStatistics): 优化表格宽度分组和过滤逻辑
2026-03-09 17:19:06 +08:00
砂糖
3f4ee0fce3 fix(wms): 更新镀锌原料标签判断逻辑并调整标签尺寸
修改多个文件中的镀锌原料仓库判断条件,增加新的仓库ID支持
调整DuGeTag.vue中标签的高度为100mm
更新base.vue中的标签类型判断逻辑,增加更多产品类型处理
修正DuGeTag.vue中的联系电话信息
2026-03-09 16:33:52 +08:00
566 changed files with 48451 additions and 12585 deletions

View File

@@ -11,7 +11,7 @@ import org.springframework.boot.context.metrics.buffering.BufferingApplicationSt
*/
//@SpringBootApplication
@SpringBootApplication(exclude = org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.class)
@SpringBootApplication
public class KLPApplication {
public static void main(String[] args) {

View File

@@ -130,10 +130,6 @@ spring:
# 多久检查一次连接的活性
keepaliveTime: 30000
flyway:
baseline-on-migrate: true # 第一次运行时建立记录,不执行历史脚本
clean-disabled: true # 禁止清空库
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
spring:
redis:

View File

@@ -124,10 +124,6 @@ spring:
# 多久检查一次连接的活性
keepaliveTime: 30000
flyway:
baseline-on-migrate: true # 第一次运行时建立记录,不执行历史脚本
clean-disabled: true # 禁止清空库
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
spring:
redis:

View File

@@ -101,11 +101,6 @@ spring:
deserialization:
# 允许对象忽略json中不存在的属性
fail_on_unknown_properties: false
# 实时更新数据库结构
flyway:
enabled: true
locations: classpath:db/migration
table: flyway_schema_history
# Sa-Token配置
sa-token:
@@ -342,3 +337,9 @@ stamp:
base-url: http://python-stamp-service.example.com # 替换为实际地址
api-key: changeme # 替换为实际鉴权信息
timeout-ms: 5000 # 可按需调整
# OEE配置
oee:
acid:
# 酸轧入场卷创建人wms_material_coil.create_by
coil-create-by: suanzhakuguan

View File

@@ -0,0 +1,28 @@
CREATE TABLE IF NOT EXISTS aps_quick_sheet (
quick_sheet_id BIGINT AUTO_INCREMENT PRIMARY KEY,
plan_date DATE NOT NULL COMMENT '计划日期',
line_id BIGINT NULL COMMENT '产线ID',
line_name VARCHAR(120) NULL COMMENT '产线名称',
plan_code VARCHAR(60) NOT NULL COMMENT '计划号',
order_code VARCHAR(80) NULL COMMENT '订单号',
customer_name VARCHAR(120) NULL COMMENT '客户',
salesman VARCHAR(60) NULL COMMENT '业务员',
product_name VARCHAR(120) NULL COMMENT '产品',
raw_material_id VARCHAR(64) NULL COMMENT '原料钢卷',
raw_coil_nos VARCHAR(255) NULL COMMENT '原料卷号',
raw_location VARCHAR(120) NULL COMMENT '钢卷位置',
raw_packaging VARCHAR(120) NULL COMMENT '包装要求',
raw_edge_req VARCHAR(120) NULL COMMENT '切边要求',
raw_coating_type VARCHAR(120) NULL COMMENT '镀层种类',
raw_net_weight DECIMAL(18, 3) NULL COMMENT '原料净重',
plan_qty DECIMAL(18, 3) NULL COMMENT '计划数量',
start_time DATETIME NULL COMMENT '开始时间',
end_time DATETIME NULL COMMENT '结束时间',
del_flag TINYINT DEFAULT 0 COMMENT '删除标记(0正常 1删除)',
create_by VARCHAR(64) NULL,
update_by VARCHAR(64) NULL,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_aps_quick_sheet_plan_date (plan_date),
INDEX idx_aps_quick_sheet_line_id (line_id)
) COMMENT = '快速排产表(Excel样式)';

View File

@@ -0,0 +1,47 @@
CREATE TABLE IF NOT EXISTS wms_furnace (
furnace_id BIGINT AUTO_INCREMENT PRIMARY KEY,
furnace_code VARCHAR(50) NOT NULL COMMENT '炉编号',
furnace_name VARCHAR(100) NOT NULL COMMENT '名称',
busy_flag TINYINT DEFAULT 0 COMMENT '是否忙碌(0否1是)',
status TINYINT DEFAULT 1 COMMENT '状态(0停用1启用)',
remark VARCHAR(500) NULL COMMENT '备注',
del_flag TINYINT DEFAULT 0 COMMENT '删除标记(0正常 1删除)',
create_by VARCHAR(64) NULL,
update_by VARCHAR(64) NULL,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_wms_furnace_code (furnace_code)
) COMMENT = '退火炉信息表';
CREATE TABLE IF NOT EXISTS wms_furnace_plan (
plan_id BIGINT AUTO_INCREMENT PRIMARY KEY,
plan_no VARCHAR(60) NOT NULL COMMENT '计划号',
plan_start_time DATETIME NULL COMMENT '计划开始时间',
actual_start_time DATETIME NULL COMMENT '实际开始时间',
end_time DATETIME NULL COMMENT '结束时间',
target_furnace_id BIGINT NOT NULL COMMENT '目标炉子ID',
status TINYINT DEFAULT 0 COMMENT '计划状态(0未开始 1进行中 2已完成)',
remark VARCHAR(500) NULL COMMENT '备注',
del_flag TINYINT DEFAULT 0 COMMENT '删除标记(0正常 1删除)',
create_by VARCHAR(64) NULL,
update_by VARCHAR(64) NULL,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_wms_furnace_plan_no (plan_no),
INDEX idx_wms_furnace_plan_furnace (target_furnace_id),
INDEX idx_wms_furnace_plan_status (status)
) COMMENT = '退火计划表';
CREATE TABLE IF NOT EXISTS wms_furnace_plan_coil (
plan_coil_id BIGINT AUTO_INCREMENT PRIMARY KEY,
plan_id BIGINT NOT NULL COMMENT '计划ID',
coil_id BIGINT NOT NULL COMMENT '钢卷ID',
del_flag TINYINT DEFAULT 0 COMMENT '删除标记(0正常 1删除)',
create_by VARCHAR(64) NULL,
update_by VARCHAR(64) NULL,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_wms_furnace_plan_coil (plan_id, coil_id),
INDEX idx_wms_furnace_plan_coil_plan (plan_id),
INDEX idx_wms_furnace_plan_coil_coil (coil_id)
) COMMENT = '退火计划钢卷关系表';

View File

@@ -0,0 +1,99 @@
package com.klp.aps.controller;
import java.util.List;
import java.util.Arrays;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.klp.common.annotation.RepeatSubmit;
import com.klp.common.annotation.Log;
import com.klp.common.core.controller.BaseController;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.R;
import com.klp.common.core.validate.AddGroup;
import com.klp.common.core.validate.EditGroup;
import com.klp.common.enums.BusinessType;
import com.klp.common.utils.poi.ExcelUtil;
import com.klp.aps.domain.vo.ApsPlanDetailVo;
import com.klp.aps.domain.bo.ApsPlanDetailBo;
import com.klp.aps.service.IApsPlanDetailService;
import com.klp.common.core.page.TableDataInfo;
/**
* 排产单明细
*
* @author klp
* @date 2026-03-26
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/aps/planDetail")
public class ApsPlanDetailController extends BaseController {
private final IApsPlanDetailService iApsPlanDetailService;
/**
* 查询排产单明细列表
*/
@GetMapping("/list")
public TableDataInfo<ApsPlanDetailVo> list(ApsPlanDetailBo bo, PageQuery pageQuery) {
return iApsPlanDetailService.queryPageList(bo, pageQuery);
}
/**
* 导出排产单明细列表
*/
@Log(title = "排产单明细", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(ApsPlanDetailBo bo, HttpServletResponse response) {
List<ApsPlanDetailVo> list = iApsPlanDetailService.queryList(bo);
ExcelUtil.exportExcel(list, "排产单明细", ApsPlanDetailVo.class, response);
}
/**
* 获取排产单明细详细信息
*
* @param planDetailId 主键
*/
@GetMapping("/{planDetailId}")
public R<ApsPlanDetailVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long planDetailId) {
return R.ok(iApsPlanDetailService.queryById(planDetailId));
}
/**
* 新增排产单明细
*/
@Log(title = "排产单明细", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody ApsPlanDetailBo bo) {
return toAjax(iApsPlanDetailService.insertByBo(bo));
}
/**
* 修改排产单明细
*/
@Log(title = "排产单明细", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ApsPlanDetailBo bo) {
return toAjax(iApsPlanDetailService.updateByBo(bo));
}
/**
* 删除排产单明细
*
* @param planDetailIds 主键串
*/
@Log(title = "排产单明细", businessType = BusinessType.DELETE)
@DeleteMapping("/{planDetailIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] planDetailIds) {
return toAjax(iApsPlanDetailService.deleteWithValidByIds(Arrays.asList(planDetailIds), true));
}
}

View File

@@ -0,0 +1,105 @@
package com.klp.aps.controller;
import java.util.List;
import java.util.Arrays;
import com.klp.aps.domain.dto.ApsPlanSheetQueryReq;
import com.klp.aps.domain.dto.ApsQuickSheetQueryReq;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.klp.common.annotation.RepeatSubmit;
import com.klp.common.annotation.Log;
import com.klp.common.core.controller.BaseController;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.R;
import com.klp.common.core.validate.AddGroup;
import com.klp.common.core.validate.EditGroup;
import com.klp.common.enums.BusinessType;
import com.klp.common.utils.poi.ExcelUtil;
import com.klp.aps.domain.vo.ApsPlanSheetVo;
import com.klp.aps.domain.bo.ApsPlanSheetBo;
import com.klp.aps.service.IApsPlanSheetService;
import com.klp.common.core.page.TableDataInfo;
/**
* 排产单主
*
* @author klp
* @date 2026-03-26
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/aps/planSheet")
public class ApsPlanSheetController extends BaseController {
private final IApsPlanSheetService iApsPlanSheetService;
/**
* 查询排产单主列表
*/
@GetMapping("/list")
public TableDataInfo<ApsPlanSheetVo> list(ApsPlanSheetBo bo, PageQuery pageQuery) {
return iApsPlanSheetService.queryPageList(bo, pageQuery);
}
/**
* 导出排产单主列表
*/
@Log(title = "排产单主", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(ApsPlanSheetBo bo, HttpServletResponse response) {
List<ApsPlanSheetVo> list = iApsPlanSheetService.queryList(bo);
ExcelUtil.exportExcel(list, "排产单主", ApsPlanSheetVo.class, response);
}
@PostMapping("/exportAll")
public void export(@Validated ApsPlanSheetQueryReq req, javax.servlet.http.HttpServletResponse response) {
iApsPlanSheetService.exportExcel(req, response);
}
/**
* 获取排产单主详细信息
*
* @param planSheetId 主键
*/
@GetMapping("/{planSheetId}")
public R<ApsPlanSheetVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long planSheetId) {
return R.ok(iApsPlanSheetService.queryById(planSheetId));
}
/**
* 新增排产单主
*/
@Log(title = "排产单主", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody ApsPlanSheetBo bo) {
return toAjax(iApsPlanSheetService.insertByBo(bo));
}
/**
* 修改排产单主
*/
@Log(title = "排产单主", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ApsPlanSheetBo bo) {
return toAjax(iApsPlanSheetService.updateByBo(bo));
}
/**
* 删除排产单主
*
* @param planSheetIds 主键串
*/
@Log(title = "排产单主", businessType = BusinessType.DELETE)
@DeleteMapping("/{planSheetIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] planSheetIds) {
return toAjax(iApsPlanSheetService.deleteWithValidByIds(Arrays.asList(planSheetIds), true));
}
}

View File

@@ -0,0 +1,55 @@
package com.klp.aps.controller;
import com.klp.aps.domain.dto.ApsQuickSheetQueryReq;
import com.klp.aps.domain.dto.ApsQuickSheetSaveReq;
import com.klp.aps.domain.vo.ApsQuickSheetRowVo;
import com.klp.aps.service.ApsQuickSheetService;
import com.klp.common.core.controller.BaseController;
import com.klp.common.core.domain.R;
import com.klp.common.helper.LoginHelper;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RequiredArgsConstructor
@RestController
@RequestMapping("/aps/quick-sheet")
public class ApsQuickSheetController extends BaseController {
private final ApsQuickSheetService quickSheetService;
@GetMapping("/list")
public R<List<ApsQuickSheetRowVo>> list(@Validated ApsQuickSheetQueryReq req) {
return R.ok(quickSheetService.queryList(req));
}
@GetMapping("/preset")
public R<List<ApsQuickSheetRowVo>> preset(@RequestParam(value = "lineId", required = false) Long lineId) {
String salesman = LoginHelper.getNickName();
return R.ok(quickSheetService.buildPresetRows(lineId, salesman));
}
@PostMapping("/save")
public R<Void> save(@Validated @RequestBody ApsQuickSheetSaveReq req) {
quickSheetService.saveRows(req, getUsername());
return R.ok();
}
@GetMapping("/export")
public void export(@Validated ApsQuickSheetQueryReq req, javax.servlet.http.HttpServletResponse response) {
quickSheetService.exportExcel(req, response);
}
@PostMapping("/delete")
public R<Void> delete(@RequestParam("quickSheetId") Long quickSheetId) {
quickSheetService.deleteById(quickSheetId, getUsername());
return R.ok();
}
}

View File

@@ -0,0 +1,224 @@
package com.klp.aps.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 排产单明细业务对象 aps_plan_detail
*
* @author klp
* @date 2026-03-26
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class ApsPlanDetailBo extends BaseEntity {
/**
* 排产明细主键ID
*/
private Long planDetailId;
/**
* 关联排产单ID
*/
private Long planSheetId;
/**
* 内容序号
*/
private String bizSeqNo;
/**
* 订单ID
*/
private Long orderId;
/**
* 销售内容:订单号
*/
private String orderCode;
/**
* 销售内容:订单合同号
*/
private String contractCode;
/**
* 销售内容:客户
*/
private String customerName;
/**
* 销售内容:业务员
*/
private String salesman;
/**
* 原料信息:厂家
*/
private String rawManufacturer;
/**
* 原料信息:材质
*/
private String rawMaterial;
/**
* 原料信息:厚度mm
*/
private BigDecimal rawThick;
/**
* 原料信息:宽度mm
*/
private BigDecimal rawWidth;
/**
* 原料钢卷ID
*/
private Long rawMaterialId;
/**
* 原料卷号
*/
private String rawCoilNos;
/**
* 钢卷位置
*/
private String rawLocation;
/**
* 包装要求
*/
private String rawPackaging;
/**
* 宽度要求
*/
private String rawEdgeReq;
/**
* 镀层种类
*/
private String rawCoatingType;
/**
* 原料净重
*/
private BigDecimal rawNetWeight;
/**
* 成品信息:成品名称
*/
private String productName;
/**
* 成品信息:材质
*/
private String productMaterial;
/**
* 成品信息:镀层g
*/
private BigDecimal coatingG;
/**
* 成品信息:成品宽度
*/
private BigDecimal productWidth;
/**
* 成品信息:轧制厚度
*/
private BigDecimal rollingThick;
/**
* 成品信息:标签厚度
*/
private BigDecimal markCoatThick;
/**
* 成品信息:吨钢长度区间m
*/
private String tonSteelLengthRange;
/**
* 成品信息:数量
*/
private BigDecimal planQty;
/**
* 成品信息:重量
*/
private BigDecimal planWeight;
/**
* 成品信息:表面处理
*/
private String surfaceTreatment;
/**
* 成品信息:切边要求
*/
private String widthReq;
/**
* 成品信息:包装要求
*/
private String productPackaging;
/**
* 成品信息:宽度要求
*/
private String productEdgeReq;
/**
* 成品信息:用途
*/
private String usageReq;
/**
* 后处理
*/
private String postProcess;
/**
* 下工序
*/
private String nextProcess;
/**
* 取样
*/
private String sampleReq;
/**
* 生产开始时间
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date startTime;
/**
* 生产结束时间
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date endTime;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,66 @@
package com.klp.aps.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 排产单主业务对象 aps_plan_sheet
*
* @author klp
* @date 2026-03-26
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class ApsPlanSheetBo extends BaseEntity {
/**
* 排产单主键ID
*/
private Long planSheetId;
/**
* 排产日期
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date planDate;
/**
* 产线ID
*/
private Long lineId;
/**
* 产线名称
*/
private String lineName;
/**
* 排产单号
*/
private String planCode;
/**
* 排产类型
*/
private String planType;
/**
* 排产人
*/
private String scheduler;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,13 @@
package com.klp.aps.domain.dto;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
@Data
public class ApsPlanSheetQueryReq {
// planSheetId
private Long planSheetId;
}

View File

@@ -0,0 +1,59 @@
package com.klp.aps.domain.dto;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.util.List;
@Data
public class ApsPlanSheetSaveReq {
@NotEmpty(message = "rows 不能为空")
private List<ApsQuickSheetSaveReq.Row> rows;
@Data
public static class Row {
private Long quickSheetId;
private Long lineId;
private String lineName;
private String planCode;
private String planType;
private String scheduler;
private String remark;
private String bizSeqNo;
private String orderCode;
private String contractCode;
private String customerName;
private String salesman;
private String productName;
private String productMaterial;
private String coatingG;
private String productWidth;
private String rollingThick;
private String markCoatThick;
private String tonSteelLengthRange;
private String planQty;
private String planWeight;
private String surfaceTreatment;
private String widthReq;
private String usageReq;
private String postProcess;
private String nextProcess;
private String sampleReq;
private String rawManufacturer;
private String rawMaterial;
private String rawThick;
private String rawWidth;
private String rawMaterialId;
private String rawCoilNos;
private String rawLocation;
private String rawPackaging;
private String rawEdgeReq;
private String rawCoatingType;
private String rawNetWeight;
private String startTime;
private String endTime;
}
}

View File

@@ -0,0 +1,20 @@
package com.klp.aps.domain.dto;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
@Data
public class ApsQuickSheetQueryReq {
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate startDate;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate endDate;
private Long lineId;
private String customerName;
}

View File

@@ -0,0 +1,60 @@
package com.klp.aps.domain.dto;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.util.List;
@Data
public class ApsQuickSheetSaveReq {
@NotEmpty(message = "rows 不能为空")
private List<Row> rows;
@Data
public static class Row {
private Long quickSheetId;
private Long lineId;
private String lineName;
private String planCode;
private String planType;
private String scheduler;
private String remark;
private String bizSeqNo;
private String orderCode;
private String contractCode;
private String customerName;
private String salesman;
private String productName;
private String productMaterial;
private String coatingG;
private String productWidth;
private String rollingThick;
private String markCoatThick;
private String tonSteelLengthRange;
private String planQty;
private String planWeight;
private String surfaceTreatment;
private String widthReq;
private String usageReq;
private String postProcess;
private String nextProcess;
private String sampleReq;
private String rawManufacturer;
private String rawMaterial;
private String rawThick;
private String rawWidth;
private String rawMaterialId;
private String rawCoilNos;
private String rawLocation;
private String rawPackaging;
private String rawEdgeReq;
private String rawCoatingType;
private String rawNetWeight;
private String startTime;
private String endTime;
}
}

View File

@@ -0,0 +1,193 @@
package com.klp.aps.domain.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.util.Date;
/**
* 排产单明细对象 aps_plan_detail
*
* @author klp
* @date 2026-03-26
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("aps_plan_detail")
public class ApsPlanDetail extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 排产明细主键ID
*/
@TableId(value = "plan_detail_id")
private Long planDetailId;
/**
* 关联排产单ID
*/
private Long planSheetId;
/**
* 内容序号
*/
private String bizSeqNo;
/**
* 订单ID
*/
private Long orderId;
/**
* 销售内容:订单号
*/
private String orderCode;
/**
* 销售内容:订单合同号
*/
private String contractCode;
/**
* 销售内容:客户
*/
private String customerName;
/**
* 销售内容:业务员
*/
private String salesman;
/**
* 原料信息:厂家
*/
private String rawManufacturer;
/**
* 原料信息:材质
*/
private String rawMaterial;
/**
* 原料信息:厚度mm
*/
private BigDecimal rawThick;
/**
* 原料信息:宽度mm
*/
private BigDecimal rawWidth;
/**
* 原料钢卷ID
*/
private Long rawMaterialId;
/**
* 原料卷号
*/
private String rawCoilNos;
/**
* 钢卷位置
*/
private String rawLocation;
/**
* 包装要求
*/
private String rawPackaging;
/**
* 宽度要求
*/
private String rawEdgeReq;
/**
* 镀层种类
*/
private String rawCoatingType;
/**
* 原料净重
*/
private BigDecimal rawNetWeight;
/**
* 成品信息:成品名称
*/
private String productName;
/**
* 成品信息:材质
*/
private String productMaterial;
/**
* 成品信息:镀层g
*/
private BigDecimal coatingG;
/**
* 成品信息:成品宽度
*/
private BigDecimal productWidth;
/**
* 成品信息:轧制厚度
*/
private BigDecimal rollingThick;
/**
* 成品信息:标签厚度
*/
private BigDecimal markCoatThick;
/**
* 成品信息:吨钢长度区间m
*/
private String tonSteelLengthRange;
/**
* 成品信息:数量
*/
private BigDecimal planQty;
/**
* 成品信息:重量
*/
private BigDecimal planWeight;
/**
* 成品信息:表面处理
*/
private String surfaceTreatment;
/**
* 成品信息:切边要求
*/
private String widthReq;
/**
* 成品信息:包装要求
*/
private String productPackaging;
/**
* 成品信息:宽度要求
*/
private String productEdgeReq;
/**
* 成品信息:用途
*/
private String usageReq;
/**
* 后处理
*/
private String postProcess;
/**
* 下工序
*/
private String nextProcess;
/**
* 取样
*/
private String sampleReq;
/**
* 生产开始时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
/**
* 生产结束时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
/**
* 备注
*/
private String remark;
/**
* 删除标记(0正常 1删除)
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,66 @@
package com.klp.aps.domain.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* 排产单主对象 aps_plan_sheet
*
* @author klp
* @date 2026-03-26
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("aps_plan_sheet")
public class ApsPlanSheet extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 排产单主键ID
*/
@TableId(value = "plan_sheet_id")
private Long planSheetId;
/**
* 排产日期
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date planDate;
/**
* 产线ID
*/
private Long lineId;
/**
* 产线名称
*/
private String lineName;
/**
* 排产单号
*/
private String planCode;
/**
* 排产类型
*/
private String planType;
/**
* 排产人
*/
private String scheduler;
/**
* 备注
*/
private String remark;
/**
* 删除标记(0正常 1删除)
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,60 @@
package com.klp.aps.domain.entity;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
public class ApsQuickSheetEntity {
private Long quickSheetId;
private LocalDate planDate;
private Long lineId;
private String lineName;
private String planCode;
private String planType;
private String scheduler;
private String remark;
private String bizSeqNo;
private String orderCode;
private String contractCode;
private String customerName;
private String salesman;
private String productName;
private String productMaterial;
private BigDecimal coatingG;
private BigDecimal productWidth;
private BigDecimal rollingThick;
private BigDecimal markCoatThick;
private String tonSteelLengthRange;
private BigDecimal planQty;
private BigDecimal planWeight;
private String surfaceTreatment;
private String widthReq;
private String usageReq;
private String postProcess;
private String nextProcess;
private String sampleReq;
private String rawManufacturer;
private String rawMaterial;
private BigDecimal rawThick;
private BigDecimal rawWidth;
private String rawMaterialId;
private String rawCoilNos;
private String rawLocation;
private String rawPackaging;
private String rawEdgeReq;
private String rawCoatingType;
private BigDecimal rawNetWeight;
private LocalDateTime startTime;
private LocalDateTime endTime;
private String createBy;
private String updateBy;
private LocalDateTime createTime;
private LocalDateTime updateTime;
private Integer delFlag;
}

View File

@@ -0,0 +1,265 @@
package com.klp.aps.domain.vo;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.klp.common.annotation.ExcelDictFormat;
import com.klp.common.convert.ExcelDictConvert;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 排产单明细视图对象 aps_plan_detail
*
* @author klp
* @date 2026-03-26
*/
@Data
@ExcelIgnoreUnannotated
public class ApsPlanDetailVo {
private static final long serialVersionUID = 1L;
/**
* 排产明细主键ID
*/
@ExcelProperty(value = "排产明细主键ID")
private Long planDetailId;
/**
* 关联排产单ID
*/
@ExcelProperty(value = "关联排产单ID")
private Long planSheetId;
/**
* 内容序号
*/
@ExcelProperty(value = "内容序号")
private String bizSeqNo;
/**
* 订单ID
*/
@ExcelProperty(value = "订单ID")
private Long orderId;
/**
* 销售内容:订单号
*/
@ExcelProperty(value = "销售内容:订单号")
private String orderCode;
/**
* 销售内容:订单合同号
*/
@ExcelProperty(value = "销售内容:订单合同号")
private String contractCode;
/**
* 销售内容:客户
*/
@ExcelProperty(value = "销售内容:客户")
private String customerName;
/**
* 销售内容:业务员
*/
@ExcelProperty(value = "销售内容:业务员")
private String salesman;
/**
* 原料信息:厂家
*/
@ExcelProperty(value = "原料信息:厂家")
private String rawManufacturer;
/**
* 原料信息:材质
*/
@ExcelProperty(value = "原料信息:材质")
private String rawMaterial;
/**
* 原料信息:厚度mm
*/
@ExcelProperty(value = "原料信息:厚度mm")
private BigDecimal rawThick;
/**
* 原料信息:宽度mm
*/
@ExcelProperty(value = "原料信息:宽度mm")
private BigDecimal rawWidth;
/**
* 原料钢卷ID
*/
@ExcelProperty(value = "原料钢卷ID")
private Long rawMaterialId;
/**
* 原料卷号
*/
@ExcelProperty(value = "原料卷号")
private String rawCoilNos;
/**
* 钢卷位置
*/
@ExcelProperty(value = "钢卷位置")
private String rawLocation;
/**
* 包装要求
*/
@ExcelProperty(value = "包装要求")
private String rawPackaging;
/**
* 宽度要求
*/
@ExcelProperty(value = "宽度要求")
private String rawEdgeReq;
/**
* 镀层种类
*/
@ExcelProperty(value = "镀层种类")
private String rawCoatingType;
/**
* 原料净重
*/
@ExcelProperty(value = "原料净重")
private BigDecimal rawNetWeight;
/**
* 成品信息:成品名称
*/
@ExcelProperty(value = "成品信息:成品名称")
private String productName;
/**
* 成品信息:材质
*/
@ExcelProperty(value = "成品信息:材质")
private String productMaterial;
/**
* 成品信息:镀层g
*/
@ExcelProperty(value = "成品信息:镀层g")
private BigDecimal coatingG;
/**
* 成品信息:成品宽度
*/
@ExcelProperty(value = "成品信息:成品宽度")
private BigDecimal productWidth;
/**
* 成品信息:轧制厚度
*/
@ExcelProperty(value = "成品信息:轧制厚度")
private BigDecimal rollingThick;
/**
* 成品信息:标签厚度
*/
@ExcelProperty(value = "成品信息:标签厚度")
private BigDecimal markCoatThick;
/**
* 成品信息:吨钢长度区间m
*/
@ExcelProperty(value = "成品信息:吨钢长度区间m")
private String tonSteelLengthRange;
/**
* 成品信息:数量
*/
@ExcelProperty(value = "成品信息:数量")
private BigDecimal planQty;
/**
* 成品信息:重量
*/
@ExcelProperty(value = "成品信息:重量")
private BigDecimal planWeight;
/**
* 成品信息:表面处理
*/
@ExcelProperty(value = "成品信息:表面处理")
private String surfaceTreatment;
/**
* 成品信息:切边要求
*/
@ExcelProperty(value = "成品信息:切边要求")
private String widthReq;
/**
* 成品信息:包装要求
*/
@ExcelProperty(value = "成品信息:包装要求")
private String productPackaging;
/**
* 成品信息:宽度要求
*/
@ExcelProperty(value = "成品信息:宽度要求")
private String productEdgeReq;
/**
* 成品信息:用途
*/
@ExcelProperty(value = "成品信息:用途")
private String usageReq;
/**
* 后处理
*/
@ExcelProperty(value = "后处理")
private String postProcess;
/**
* 下工序
*/
@ExcelProperty(value = "下工序")
private String nextProcess;
/**
* 取样
*/
@ExcelProperty(value = "取样")
private String sampleReq;
/**
* 生产开始时间
*/
@ExcelProperty(value = "生产开始时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
/**
* 生产结束时间
*/
@ExcelProperty(value = "生产结束时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -0,0 +1,56 @@
package com.klp.aps.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
public class ApsPlanSheetRowVo {
private Long detailSheetId;
private java.time.LocalDate planDate;
private Long lineId;
private String lineName;
private String planCode;
private String planType;
private String scheduler;
private String masterRemark;
private String updateBy;
private String bizSeqNo;
private String orderCode;
private String contractCode;
private String customerName;
private String salesman;
private String productName;
private String productMaterial;
private BigDecimal coatingG;
private BigDecimal productWidth;
private BigDecimal rollingThick;
private BigDecimal markCoatThick;
private String tonSteelLengthRange;
private BigDecimal planQty;
private BigDecimal planWeight;
private String surfaceTreatment;
private String widthReq;
private String usageReq;
private String postProcess;
private String nextProcess;
private String sampleReq;
private String rawManufacturer;
private String rawMaterial;
private BigDecimal rawThick;
private BigDecimal rawWidth;
private String rawMaterialId;
private String rawCoilNos;
private String rawLocation;
private String rawPackaging;
private String rawEdgeReq;
private String rawCoatingType;
private BigDecimal rawNetWeight;
private LocalDateTime startTime;
private LocalDateTime endTime;
private String detailRemark;
}

View File

@@ -0,0 +1,76 @@
package com.klp.aps.domain.vo;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.klp.common.annotation.ExcelDictFormat;
import com.klp.common.convert.ExcelDictConvert;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 排产单主视图对象 aps_plan_sheet
*
* @author klp
* @date 2026-03-26
*/
@Data
@ExcelIgnoreUnannotated
public class ApsPlanSheetVo {
private static final long serialVersionUID = 1L;
/**
* 排产单主键ID
*/
@ExcelProperty(value = "排产单主键ID")
private Long planSheetId;
/**
* 排产日期
*/
@ExcelProperty(value = "排产日期")
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date planDate;
/**
* 产线ID
*/
@ExcelProperty(value = "产线ID")
private Long lineId;
/**
* 产线名称
*/
@ExcelProperty(value = "产线名称")
private String lineName;
/**
* 排产单号
*/
@ExcelProperty(value = "排产单号")
private String planCode;
/**
* 排产类型
*/
@ExcelProperty(value = "排产类型")
private String planType;
/**
* 排产人
*/
@ExcelProperty(value = "排产人")
private String scheduler;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -0,0 +1,54 @@
package com.klp.aps.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
public class ApsQuickSheetRowVo {
private Long quickSheetId;
private java.time.LocalDate planDate;
private Long lineId;
private String lineName;
private String planCode;
private String planType;
private String scheduler;
private String remark;
private String bizSeqNo;
private String orderCode;
private String contractCode;
private String customerName;
private String salesman;
private String productName;
private String productMaterial;
private BigDecimal coatingG;
private BigDecimal productWidth;
private BigDecimal rollingThick;
private BigDecimal markCoatThick;
private String tonSteelLengthRange;
private BigDecimal planQty;
private BigDecimal planWeight;
private String surfaceTreatment;
private String widthReq;
private String usageReq;
private String postProcess;
private String nextProcess;
private String sampleReq;
private String rawManufacturer;
private String rawMaterial;
private BigDecimal rawThick;
private BigDecimal rawWidth;
private String rawMaterialId;
private String rawCoilNos;
private String rawLocation;
private String rawPackaging;
private String rawEdgeReq;
private String rawCoatingType;
private BigDecimal rawNetWeight;
private LocalDateTime startTime;
private LocalDateTime endTime;
}

View File

@@ -0,0 +1,18 @@
package com.klp.aps.mapper;
import com.klp.aps.domain.entity.ApsPlanDetail;
import com.klp.aps.domain.vo.ApsPlanDetailVo;
import com.klp.common.core.mapper.BaseMapperPlus;
import java.util.Collection;
/**
* 排产单明细Mapper接口
*
* @author klp
* @date 2026-03-26
*/
public interface ApsPlanDetailMapper extends BaseMapperPlus<ApsPlanDetailMapper, ApsPlanDetail, ApsPlanDetailVo> {
int deleteByPlanSheetIds(Collection<Long> planSheetIds);
}

View File

@@ -0,0 +1,22 @@
package com.klp.aps.mapper;
import com.klp.aps.domain.dto.ApsPlanSheetQueryReq;
import com.klp.aps.domain.dto.ApsQuickSheetQueryReq;
import com.klp.aps.domain.entity.ApsPlanSheet;
import com.klp.aps.domain.vo.ApsPlanSheetRowVo;
import com.klp.aps.domain.vo.ApsPlanSheetVo;
import com.klp.aps.domain.vo.ApsQuickSheetRowVo;
import com.klp.common.core.mapper.BaseMapperPlus;
import java.util.List;
/**
* 排产单主Mapper接口
*
* @author klp
* @date 2026-03-26
*/
public interface ApsPlanSheetMapper extends BaseMapperPlus<ApsPlanSheetMapper, ApsPlanSheet, ApsPlanSheetVo> {
List<ApsPlanSheetRowVo> selectList(ApsPlanSheetQueryReq req);
}

View File

@@ -0,0 +1,111 @@
package com.klp.aps.mapper;
import com.klp.aps.domain.dto.ApsQuickSheetQueryReq;
import com.klp.aps.domain.vo.ApsQuickSheetRowVo;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
public interface ApsQuickSheetMapper {
List<ApsQuickSheetRowVo> selectList(ApsQuickSheetQueryReq req);
int countToday(@Param("planDate") LocalDate planDate);
Long selectIdByPlanCode(@Param("planCode") String planCode);
int insertRow(@Param("lineId") Long lineId,
@Param("lineName") String lineName,
@Param("planDate") LocalDate planDate,
@Param("planCode") String planCode,
@Param("planType") String planType,
@Param("scheduler") String scheduler,
@Param("remark") String remark,
@Param("bizSeqNo") String bizSeqNo,
@Param("orderCode") String orderCode,
@Param("contractCode") String contractCode,
@Param("customerName") String customerName,
@Param("salesman") String salesman,
@Param("productName") String productName,
@Param("productMaterial") String productMaterial,
@Param("coatingG") BigDecimal coatingG,
@Param("productWidth") BigDecimal productWidth,
@Param("rollingThick") BigDecimal rollingThick,
@Param("markCoatThick") BigDecimal markCoatThick,
@Param("tonSteelLengthRange") String tonSteelLengthRange,
@Param("planQty") BigDecimal planQty,
@Param("planWeight") BigDecimal planWeight,
@Param("surfaceTreatment") String surfaceTreatment,
@Param("widthReq") String widthReq,
@Param("usageReq") String usageReq,
@Param("postProcess") String postProcess,
@Param("nextProcess") String nextProcess,
@Param("sampleReq") String sampleReq,
@Param("rawManufacturer") String rawManufacturer,
@Param("rawMaterial") String rawMaterial,
@Param("rawThick") BigDecimal rawThick,
@Param("rawWidth") BigDecimal rawWidth,
@Param("rawMaterialId") String rawMaterialId,
@Param("rawCoilNos") String rawCoilNos,
@Param("rawLocation") String rawLocation,
@Param("rawPackaging") String rawPackaging,
@Param("rawEdgeReq") String rawEdgeReq,
@Param("rawCoatingType") String rawCoatingType,
@Param("rawNetWeight") BigDecimal rawNetWeight,
@Param("startTime") LocalDateTime startTime,
@Param("endTime") LocalDateTime endTime,
@Param("createBy") String createBy,
@Param("updateBy") String updateBy);
int updateRow(@Param("id") Long id,
@Param("lineId") Long lineId,
@Param("lineName") String lineName,
@Param("planCode") String planCode,
@Param("planType") String planType,
@Param("scheduler") String scheduler,
@Param("remark") String remark,
@Param("bizSeqNo") String bizSeqNo,
@Param("orderCode") String orderCode,
@Param("contractCode") String contractCode,
@Param("customerName") String customerName,
@Param("salesman") String salesman,
@Param("productName") String productName,
@Param("productMaterial") String productMaterial,
@Param("coatingG") BigDecimal coatingG,
@Param("productWidth") BigDecimal productWidth,
@Param("rollingThick") BigDecimal rollingThick,
@Param("markCoatThick") BigDecimal markCoatThick,
@Param("tonSteelLengthRange") String tonSteelLengthRange,
@Param("planQty") BigDecimal planQty,
@Param("planWeight") BigDecimal planWeight,
@Param("surfaceTreatment") String surfaceTreatment,
@Param("widthReq") String widthReq,
@Param("usageReq") String usageReq,
@Param("postProcess") String postProcess,
@Param("nextProcess") String nextProcess,
@Param("sampleReq") String sampleReq,
@Param("rawManufacturer") String rawManufacturer,
@Param("rawMaterial") String rawMaterial,
@Param("rawThick") BigDecimal rawThick,
@Param("rawWidth") BigDecimal rawWidth,
@Param("rawMaterialId") String rawMaterialId,
@Param("rawCoilNos") String rawCoilNos,
@Param("rawLocation") String rawLocation,
@Param("rawPackaging") String rawPackaging,
@Param("rawEdgeReq") String rawEdgeReq,
@Param("rawCoatingType") String rawCoatingType,
@Param("rawNetWeight") BigDecimal rawNetWeight,
@Param("startTime") LocalDateTime startTime,
@Param("endTime") LocalDateTime endTime,
@Param("updateBy") String updateBy);
int deleteRow(@Param("id") Long id, @Param("updateBy") String updateBy);
int softDelete(@Param("id") Long id,
@Param("updateBy") String updateBy);
int deleteById(@Param("id") Long id, @Param("updateBy") String updateBy);
}

View File

@@ -0,0 +1,20 @@
package com.klp.aps.service;
import com.klp.aps.domain.dto.ApsQuickSheetQueryReq;
import com.klp.aps.domain.dto.ApsQuickSheetSaveReq;
import com.klp.aps.domain.vo.ApsQuickSheetRowVo;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
public interface ApsQuickSheetService {
List<ApsQuickSheetRowVo> queryList(ApsQuickSheetQueryReq req);
void saveRows(ApsQuickSheetSaveReq req, String operator);
List<ApsQuickSheetRowVo> buildPresetRows(Long lineId, String salesman);
void exportExcel(ApsQuickSheetQueryReq req, HttpServletResponse response);
void deleteById(Long id, String operator);
}

View File

@@ -0,0 +1,53 @@
package com.klp.aps.service;
import com.klp.aps.domain.vo.ApsPlanDetailVo;
import com.klp.aps.domain.bo.ApsPlanDetailBo;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 排产单明细Service接口
*
* @author klp
* @date 2026-03-26
*/
public interface IApsPlanDetailService {
/**
* 查询排产单明细
*/
ApsPlanDetailVo queryById(Long planDetailId);
/**
* 查询排产单明细列表
*/
TableDataInfo<ApsPlanDetailVo> queryPageList(ApsPlanDetailBo bo, PageQuery pageQuery);
/**
* 查询排产单明细列表
*/
List<ApsPlanDetailVo> queryList(ApsPlanDetailBo bo);
/**
* 新增排产单明细
*/
Boolean insertByBo(ApsPlanDetailBo bo);
/**
* 修改排产单明细
*/
Boolean updateByBo(ApsPlanDetailBo bo);
/**
* 校验并批量删除排产单明细信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 根据排产单ID删除明细
*/
int deleteByPlanSheetIds(Collection<Long> planSheetIds);
}

View File

@@ -0,0 +1,54 @@
package com.klp.aps.service;
import com.klp.aps.domain.dto.ApsPlanSheetQueryReq;
import com.klp.aps.domain.dto.ApsQuickSheetQueryReq;
import com.klp.aps.domain.vo.ApsPlanSheetVo;
import com.klp.aps.domain.bo.ApsPlanSheetBo;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.List;
/**
* 排产单主Service接口
*
* @author klp
* @date 2026-03-26
*/
public interface IApsPlanSheetService {
/**
* 查询排产单主
*/
ApsPlanSheetVo queryById(Long planSheetId);
/**
* 查询排产单主列表
*/
TableDataInfo<ApsPlanSheetVo> queryPageList(ApsPlanSheetBo bo, PageQuery pageQuery);
/**
* 查询排产单主列表
*/
List<ApsPlanSheetVo> queryList(ApsPlanSheetBo bo);
/**
* 新增排产单主
*/
Boolean insertByBo(ApsPlanSheetBo bo);
/**
* 修改排产单主
*/
Boolean updateByBo(ApsPlanSheetBo bo);
/**
* 校验并批量删除排产单主信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
void exportExcel(ApsPlanSheetQueryReq req, HttpServletResponse response);
}

View File

@@ -0,0 +1,150 @@
package com.klp.aps.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.klp.aps.domain.bo.ApsPlanDetailBo;
import com.klp.aps.domain.vo.ApsPlanDetailVo;
import com.klp.aps.domain.entity.ApsPlanDetail;
import com.klp.aps.mapper.ApsPlanDetailMapper;
import com.klp.aps.service.IApsPlanDetailService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 排产单明细Service业务层处理
*
* @author klp
* @date 2026-03-26
*/
@RequiredArgsConstructor
@Service
public class ApsPlanDetailServiceImpl implements IApsPlanDetailService {
private final ApsPlanDetailMapper baseMapper;
/**
* 查询排产单明细
*/
@Override
public ApsPlanDetailVo queryById(Long planDetailId){
return baseMapper.selectVoById(planDetailId);
}
/**
* 查询排产单明细列表
*/
@Override
public TableDataInfo<ApsPlanDetailVo> queryPageList(ApsPlanDetailBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<ApsPlanDetail> lqw = buildQueryWrapper(bo);
Page<ApsPlanDetailVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询排产单明细列表
*/
@Override
public List<ApsPlanDetailVo> queryList(ApsPlanDetailBo bo) {
LambdaQueryWrapper<ApsPlanDetail> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<ApsPlanDetail> buildQueryWrapper(ApsPlanDetailBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<ApsPlanDetail> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getPlanSheetId() != null, ApsPlanDetail::getPlanSheetId, bo.getPlanSheetId());
lqw.eq(StringUtils.isNotBlank(bo.getBizSeqNo()), ApsPlanDetail::getBizSeqNo, bo.getBizSeqNo());
lqw.eq(bo.getOrderId() != null, ApsPlanDetail::getOrderId, bo.getOrderId());
lqw.eq(StringUtils.isNotBlank(bo.getOrderCode()), ApsPlanDetail::getOrderCode, bo.getOrderCode());
lqw.eq(StringUtils.isNotBlank(bo.getContractCode()), ApsPlanDetail::getContractCode, bo.getContractCode());
lqw.like(StringUtils.isNotBlank(bo.getCustomerName()), ApsPlanDetail::getCustomerName, bo.getCustomerName());
lqw.eq(StringUtils.isNotBlank(bo.getSalesman()), ApsPlanDetail::getSalesman, bo.getSalesman());
lqw.eq(StringUtils.isNotBlank(bo.getRawManufacturer()), ApsPlanDetail::getRawManufacturer, bo.getRawManufacturer());
lqw.eq(StringUtils.isNotBlank(bo.getRawMaterial()), ApsPlanDetail::getRawMaterial, bo.getRawMaterial());
lqw.eq(bo.getRawThick() != null, ApsPlanDetail::getRawThick, bo.getRawThick());
lqw.eq(bo.getRawWidth() != null, ApsPlanDetail::getRawWidth, bo.getRawWidth());
lqw.eq(bo.getRawMaterialId() != null, ApsPlanDetail::getRawMaterialId, bo.getRawMaterialId());
lqw.eq(StringUtils.isNotBlank(bo.getRawCoilNos()), ApsPlanDetail::getRawCoilNos, bo.getRawCoilNos());
lqw.eq(StringUtils.isNotBlank(bo.getRawLocation()), ApsPlanDetail::getRawLocation, bo.getRawLocation());
lqw.eq(StringUtils.isNotBlank(bo.getRawPackaging()), ApsPlanDetail::getRawPackaging, bo.getRawPackaging());
lqw.eq(StringUtils.isNotBlank(bo.getRawEdgeReq()), ApsPlanDetail::getRawEdgeReq, bo.getRawEdgeReq());
lqw.eq(StringUtils.isNotBlank(bo.getRawCoatingType()), ApsPlanDetail::getRawCoatingType, bo.getRawCoatingType());
lqw.eq(bo.getRawNetWeight() != null, ApsPlanDetail::getRawNetWeight, bo.getRawNetWeight());
lqw.like(StringUtils.isNotBlank(bo.getProductName()), ApsPlanDetail::getProductName, bo.getProductName());
lqw.eq(StringUtils.isNotBlank(bo.getProductMaterial()), ApsPlanDetail::getProductMaterial, bo.getProductMaterial());
lqw.eq(bo.getCoatingG() != null, ApsPlanDetail::getCoatingG, bo.getCoatingG());
lqw.eq(bo.getProductWidth() != null, ApsPlanDetail::getProductWidth, bo.getProductWidth());
lqw.eq(bo.getRollingThick() != null, ApsPlanDetail::getRollingThick, bo.getRollingThick());
lqw.eq(bo.getMarkCoatThick() != null, ApsPlanDetail::getMarkCoatThick, bo.getMarkCoatThick());
lqw.eq(StringUtils.isNotBlank(bo.getTonSteelLengthRange()), ApsPlanDetail::getTonSteelLengthRange, bo.getTonSteelLengthRange());
lqw.eq(bo.getPlanQty() != null, ApsPlanDetail::getPlanQty, bo.getPlanQty());
lqw.eq(bo.getPlanWeight() != null, ApsPlanDetail::getPlanWeight, bo.getPlanWeight());
lqw.eq(StringUtils.isNotBlank(bo.getSurfaceTreatment()), ApsPlanDetail::getSurfaceTreatment, bo.getSurfaceTreatment());
lqw.eq(StringUtils.isNotBlank(bo.getWidthReq()), ApsPlanDetail::getWidthReq, bo.getWidthReq());
lqw.eq(StringUtils.isNotBlank(bo.getProductPackaging()), ApsPlanDetail::getProductPackaging, bo.getProductPackaging());
lqw.eq(StringUtils.isNotBlank(bo.getProductEdgeReq()), ApsPlanDetail::getProductEdgeReq, bo.getProductEdgeReq());
lqw.eq(StringUtils.isNotBlank(bo.getUsageReq()), ApsPlanDetail::getUsageReq, bo.getUsageReq());
lqw.eq(StringUtils.isNotBlank(bo.getPostProcess()), ApsPlanDetail::getPostProcess, bo.getPostProcess());
lqw.eq(StringUtils.isNotBlank(bo.getNextProcess()), ApsPlanDetail::getNextProcess, bo.getNextProcess());
lqw.eq(StringUtils.isNotBlank(bo.getSampleReq()), ApsPlanDetail::getSampleReq, bo.getSampleReq());
lqw.eq(bo.getStartTime() != null, ApsPlanDetail::getStartTime, bo.getStartTime());
lqw.eq(bo.getEndTime() != null, ApsPlanDetail::getEndTime, bo.getEndTime());
return lqw;
}
/**
* 新增排产单明细
*/
@Override
public Boolean insertByBo(ApsPlanDetailBo bo) {
ApsPlanDetail add = BeanUtil.toBean(bo, ApsPlanDetail.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setPlanDetailId(add.getPlanDetailId());
}
return flag;
}
/**
* 修改排产单明细
*/
@Override
public Boolean updateByBo(ApsPlanDetailBo bo) {
ApsPlanDetail update = BeanUtil.toBean(bo, ApsPlanDetail.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(ApsPlanDetail entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除排产单明细
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
@Override
public int deleteByPlanSheetIds(Collection<Long> planSheetIds) {
return baseMapper.deleteByPlanSheetIds(planSheetIds);
}
}

View File

@@ -0,0 +1,329 @@
package com.klp.aps.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.klp.aps.domain.dto.ApsPlanSheetQueryReq;
import com.klp.aps.domain.dto.ApsQuickSheetQueryReq;
import com.klp.aps.domain.vo.ApsPlanSheetRowVo;
import com.klp.aps.domain.vo.ApsQuickSheetRowVo;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.exception.ServiceException;
import com.klp.common.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import com.klp.aps.domain.bo.ApsPlanSheetBo;
import com.klp.aps.domain.vo.ApsPlanSheetVo;
import com.klp.aps.domain.entity.ApsPlanSheet;
import com.klp.aps.mapper.ApsPlanSheetMapper;
import com.klp.aps.service.IApsPlanSheetService;
import com.klp.aps.service.IApsPlanDetailService;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 排产单主Service业务层处理
*
* @author klp
* @date 2026-03-26
*/
@RequiredArgsConstructor
@Service
public class ApsPlanSheetServiceImpl implements IApsPlanSheetService {
private final ApsPlanSheetMapper baseMapper;
private final IApsPlanDetailService planDetailService;
/**
* 查询排产单主
*/
@Override
public ApsPlanSheetVo queryById(Long planSheetId) {
return baseMapper.selectVoById(planSheetId);
}
/**
* 查询排产单主列表
*/
@Override
public TableDataInfo<ApsPlanSheetVo> queryPageList(ApsPlanSheetBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<ApsPlanSheet> lqw = buildQueryWrapper(bo);
Page<ApsPlanSheetVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询排产单主列表
*/
@Override
public List<ApsPlanSheetVo> queryList(ApsPlanSheetBo bo) {
LambdaQueryWrapper<ApsPlanSheet> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<ApsPlanSheet> buildQueryWrapper(ApsPlanSheetBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<ApsPlanSheet> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getPlanDate() != null, ApsPlanSheet::getPlanDate, bo.getPlanDate());
lqw.eq(bo.getLineId() != null, ApsPlanSheet::getLineId, bo.getLineId());
lqw.like(StringUtils.isNotBlank(bo.getLineName()), ApsPlanSheet::getLineName, bo.getLineName());
lqw.eq(StringUtils.isNotBlank(bo.getPlanCode()), ApsPlanSheet::getPlanCode, bo.getPlanCode());
lqw.eq(StringUtils.isNotBlank(bo.getPlanType()), ApsPlanSheet::getPlanType, bo.getPlanType());
lqw.eq(StringUtils.isNotBlank(bo.getScheduler()), ApsPlanSheet::getScheduler, bo.getScheduler());
return lqw;
}
/**
* 新增排产单主
*/
@Override
public Boolean insertByBo(ApsPlanSheetBo bo) {
ApsPlanSheet add = BeanUtil.toBean(bo, ApsPlanSheet.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setPlanSheetId(add.getPlanSheetId());
}
return flag;
}
/**
* 修改排产单主
*/
@Override
public Boolean updateByBo(ApsPlanSheetBo bo) {
ApsPlanSheet update = BeanUtil.toBean(bo, ApsPlanSheet.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(ApsPlanSheet entity) {
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除排产单主
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
planDetailService.deleteByPlanSheetIds(ids);
return baseMapper.deleteBatchIds(ids) > 0;
}
@Override
public void exportExcel(ApsPlanSheetQueryReq req, HttpServletResponse response) {
List<ApsPlanSheetRowVo> rows = queryListAll(req);
try (Workbook wb = new XSSFWorkbook()) {
Sheet sheet = wb.createSheet("快速排产表");
int r = 0;
Row title = sheet.createRow(r++);
title.setHeightInPoints(36f);
Cell t0 = title.createCell(0);
Long planSheetId = req.getPlanSheetId();
if (planSheetId != null) {
ApsPlanSheetVo planSheet = queryById(planSheetId);
// 格式化日期
String dateStr = "";
if (planSheet.getPlanDate() != null) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
dateStr = sdf.format(planSheet.getPlanDate());
}
t0.setCellValue(dateStr + "————" + planSheet.getLineName() + "————" + planSheet.getPlanCode());
} else {
t0.setCellValue("快速排产表");
}
// 1. 先创建标题样式
CellStyle titleStyle = wb.createCellStyle();
titleStyle.setAlignment(HorizontalAlignment.CENTER);
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
XSSFFont titleFont = ((XSSFWorkbook) wb).createFont();
titleFont.setBold(true);
titleFont.setFontHeightInPoints((short) 15);
titleStyle.setFont(titleFont);
// 2. 合并区域
CellRangeAddress titleRegion = new CellRangeAddress(0, 0, 0, 40);
sheet.addMergedRegion(titleRegion);
// 3. 给【整个合并区域】设置样式
for (int i = titleRegion.getFirstColumn(); i <= titleRegion.getLastColumn(); i++) {
Cell cell = title.getCell(i);
if (cell == null) {
cell = title.createCell(i);
}
cell.setCellStyle(titleStyle);
}
String[] headers = new String[]{
"产线", "排产日期", "排产单号", "排产类型", "排产人", "修改人", "计划备注",
"内容序号", "销售内容", "订单合同号", "客户", "业务员",
"成品名称", "材质", "镀层g", "成品宽度", "轧制厚度", "标丝厚度", "吨钢长度区间m",
"数量", "重量", "表面处理", "切边要求", "宽度要求", "用途", "后处理", "下工序", "取样",
"厂家", "原料信息", "原料厚度mm", "宽度mm", "原料钢卷", "原料卷号", "钢卷位置", "包装要求", "镀层种类", "原料净重",
"开始时间", "结束时间", "明细备注"
};
// ===================== 【绝对不报错】表头样式 =====================
org.apache.poi.ss.usermodel.CellStyle headStyle = wb.createCellStyle();
org.apache.poi.ss.usermodel.Font headFont = wb.createFont();
// 1. 字体加粗
headFont.setBold(true);
headStyle.setFont(headFont);
// 2. 居中
headStyle.setAlignment(org.apache.poi.ss.usermodel.HorizontalAlignment.CENTER);
headStyle.setVerticalAlignment(org.apache.poi.ss.usermodel.VerticalAlignment.CENTER);
// 3. 背景颜色(浅蓝色)
headStyle.setFillPattern(org.apache.poi.ss.usermodel.FillPatternType.SOLID_FOREGROUND);
headStyle.setFillForegroundColor(org.apache.poi.ss.usermodel.IndexedColors.PALE_BLUE.getIndex());
// 4. 自动换行
headStyle.setWrapText(true);
// 创建表头行
org.apache.poi.ss.usermodel.Row head = sheet.createRow(r++);
head.setHeightInPoints(24);
// 设置表头内容 + 样式
for (int i = 0; i < headers.length; i++) {
org.apache.poi.ss.usermodel.Cell cell = head.createCell(i);
cell.setCellValue(headers[i]);
cell.setCellStyle(headStyle);
}
// ================== 【统一样式前7列居中】 ==================
CellStyle centerStyle = wb.createCellStyle();
centerStyle.setAlignment(HorizontalAlignment.CENTER);
centerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// ================== 数据行 ==================
int dataStartRow = r;
if (rows != null && !rows.isEmpty()) {
for (ApsPlanSheetRowVo row : rows) {
Row rr = sheet.createRow(r++);
int cc = 0;
// ====== 前7列相同内容需要居中 + 后续合并 ======
rr.createCell(cc++).setCellValue(nvl(row.getLineName(), row.getLineId()));
rr.createCell(cc++).setCellValue(row.getPlanDate() == null ? "" : row.getPlanDate().toString());
rr.createCell(cc++).setCellValue(nvl(row.getPlanCode(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getPlanType(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getScheduler(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getUpdateBy(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getMasterRemark(), ""));
// 前7列设置居中
for (int i = 0; i < 7; i++) {
rr.getCell(i).setCellStyle(centerStyle);
}
// ====== 后面列不变 ======
rr.createCell(cc++).setCellValue(nvl(row.getBizSeqNo(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getOrderCode(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getContractCode(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getCustomerName(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getSalesman(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getProductName(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getProductMaterial(), ""));
rr.createCell(cc++).setCellValue(row.getCoatingG() == null ? "" : row.getCoatingG().toPlainString());
rr.createCell(cc++).setCellValue(row.getProductWidth() == null ? "" : row.getProductWidth().toPlainString());
rr.createCell(cc++).setCellValue(row.getRollingThick() == null ? "" : row.getRollingThick().toPlainString());
rr.createCell(cc++).setCellValue(row.getMarkCoatThick() == null ? "" : row.getMarkCoatThick().toPlainString());
rr.createCell(cc++).setCellValue(nvl(row.getTonSteelLengthRange(), ""));
rr.createCell(cc++).setCellValue(row.getPlanQty() == null ? "" : row.getPlanQty().toPlainString());
rr.createCell(cc++).setCellValue(row.getPlanWeight() == null ? "" : row.getPlanWeight().toPlainString());
rr.createCell(cc++).setCellValue(nvl(row.getSurfaceTreatment(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getWidthReq(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getRawEdgeReq(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getUsageReq(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getPostProcess(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getNextProcess(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getSampleReq(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getRawManufacturer(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getRawMaterial(), ""));
rr.createCell(cc++).setCellValue(row.getRawThick() == null ? "" : row.getRawThick().toPlainString());
rr.createCell(cc++).setCellValue(row.getRawWidth() == null ? "" : row.getRawWidth().toPlainString());
rr.createCell(cc++).setCellValue(nvl(row.getRawMaterialId(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getRawCoilNos(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getRawLocation(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getRawPackaging(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getRawCoatingType(), ""));
rr.createCell(cc++).setCellValue(row.getRawNetWeight() == null ? "" : row.getRawNetWeight().toPlainString());
rr.createCell(cc++).setCellValue(row.getStartTime() == null ? "" : row.getStartTime().toString());
rr.createCell(cc++).setCellValue(row.getEndTime() == null ? "" : row.getEndTime().toString());
rr.createCell(cc++).setCellValue(nvl(row.getDetailRemark(), ""));
}
}
// ================== 【核心前7列自动合并】 ==================
int dataEndRow = r - 1;
if (dataStartRow <= dataEndRow) {
for (int col = 0; col < 7; col++) { // 0~6 共7列
CellRangeAddress region = new CellRangeAddress(
dataStartRow,
dataEndRow,
col,
col
);
sheet.addMergedRegion(region);
}
}
// 自适应列宽
for (int i = 0; i < headers.length; i++) {
sheet.autoSizeColumn(i, true);
int w = sheet.getColumnWidth(i);
sheet.setColumnWidth(i, Math.min(Math.max(w, 3000), 12000));
}
String filename = "aps_quick_sheet_" + System.currentTimeMillis() + ".xlsx";
String encoded = URLEncoder.encode(filename, StandardCharsets.UTF_8.name());
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encoded);
try (ServletOutputStream os = response.getOutputStream()) {
wb.write(os);
os.flush();
}
} catch (IOException e) {
throw new ServiceException("导出失败:" + e.getMessage());
}
}
private List<ApsPlanSheetRowVo> queryListAll(ApsPlanSheetQueryReq req) {
return baseMapper.selectList(req);
}
private String nvl(Object v, Object fallback) {
if (v == null) return String.valueOf(fallback);
String s = String.valueOf(v);
return s == null ? String.valueOf(fallback) : s;
}
}

View File

@@ -0,0 +1,290 @@
package com.klp.aps.service.impl;
import com.klp.aps.domain.dto.ApsQuickSheetSaveReq;
import com.klp.aps.domain.vo.ApsQuickSheetRowVo;
import com.klp.aps.mapper.ApsQuickSheetMapper;
import com.klp.aps.service.ApsQuickSheetService;
import com.klp.common.exception.ServiceException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
@RequiredArgsConstructor
@Service
public class ApsQuickSheetServiceImpl implements ApsQuickSheetService {
private final ApsQuickSheetMapper quickSheetMapper;
private static final DateTimeFormatter DATE_CODE = DateTimeFormatter.ofPattern("yyyyMMdd");
@Override
public List<ApsQuickSheetRowVo> queryList(com.klp.aps.domain.dto.ApsQuickSheetQueryReq req) {
return quickSheetMapper.selectList(req);
}
@Override
public void saveRows(ApsQuickSheetSaveReq req, String operator) {
if (req == null || req.getRows() == null) {
throw new ServiceException("保存数据不能为空");
}
for (ApsQuickSheetSaveReq.Row row : req.getRows()) {
if (row == null) continue;
Long id = row.getQuickSheetId();
Long lineId = row.getLineId();
String lineName = row.getLineName();
String planCode = row.getPlanCode();
String planType = row.getPlanType();
String scheduler = row.getScheduler();
String remark = row.getRemark();
String bizSeqNo = row.getBizSeqNo();
String orderCode = row.getOrderCode();
String contractCode = row.getContractCode();
String customerName = row.getCustomerName();
String salesman = row.getSalesman();
String productName = row.getProductName();
String productMaterial = row.getProductMaterial();
BigDecimal coatingG = parseQty(row.getCoatingG());
BigDecimal productWidth = parseQty(row.getProductWidth());
BigDecimal rollingThick = parseQty(row.getRollingThick());
BigDecimal markCoatThick = parseQty(row.getMarkCoatThick());
String tonSteelLengthRange = row.getTonSteelLengthRange();
BigDecimal planQty = parseQty(row.getPlanQty());
BigDecimal planWeight = parseQty(row.getPlanWeight());
String surfaceTreatment = row.getSurfaceTreatment();
String widthReq = row.getWidthReq();
String usageReq = row.getUsageReq();
String postProcess = row.getPostProcess();
String nextProcess = row.getNextProcess();
String sampleReq = row.getSampleReq();
String rawManufacturer = row.getRawManufacturer();
String rawMaterial = row.getRawMaterial();
BigDecimal rawThick = parseQty(row.getRawThick());
BigDecimal rawWidth = parseQty(row.getRawWidth());
String rawMaterialId = row.getRawMaterialId();
String rawCoilNos = row.getRawCoilNos();
String rawLocation = row.getRawLocation();
String rawPackaging = row.getRawPackaging();
String rawEdgeReq = row.getRawEdgeReq();
String rawCoatingType = row.getRawCoatingType();
BigDecimal rawNetWeight = parseQty(row.getRawNetWeight());
LocalDateTime startTime = parseTime(row.getStartTime());
LocalDateTime endTime = parseTime(row.getEndTime());
boolean hasAny = lineId != null || isNotBlank(lineName) || isNotBlank(planCode) || isNotBlank(planType)
|| isNotBlank(scheduler) || isNotBlank(remark)
|| isNotBlank(bizSeqNo) || isNotBlank(orderCode) || isNotBlank(contractCode)
|| isNotBlank(customerName) || isNotBlank(salesman)
|| isNotBlank(productName) || isNotBlank(productMaterial)
|| coatingG != null || productWidth != null || rollingThick != null || markCoatThick != null
|| isNotBlank(tonSteelLengthRange) || planQty != null || planWeight != null
|| isNotBlank(surfaceTreatment) || isNotBlank(widthReq) || isNotBlank(usageReq)
|| isNotBlank(postProcess) || isNotBlank(nextProcess) || isNotBlank(sampleReq)
|| isNotBlank(rawManufacturer) || isNotBlank(rawMaterial)
|| rawThick != null || rawWidth != null
|| isNotBlank(rawMaterialId) || isNotBlank(rawCoilNos) || isNotBlank(rawLocation)
|| isNotBlank(rawPackaging) || isNotBlank(rawEdgeReq) || isNotBlank(rawCoatingType)
|| rawNetWeight != null || startTime != null || endTime != null;
if (!hasAny) {
continue;
}
if (id == null) {
if (!isNotBlank(planCode)) {
planCode = buildPlanCode();
}
quickSheetMapper.insertRow(lineId, lineName, LocalDate.now(), planCode, planType, scheduler, remark,
bizSeqNo, orderCode, contractCode, customerName, salesman,
productName, productMaterial, coatingG, productWidth, rollingThick, markCoatThick,
tonSteelLengthRange, planQty, planWeight, surfaceTreatment, widthReq, usageReq,
postProcess, nextProcess, sampleReq,
rawManufacturer, rawMaterial, rawThick, rawWidth, rawMaterialId, rawCoilNos,
rawLocation, rawPackaging, rawEdgeReq, rawCoatingType, rawNetWeight,
startTime, endTime, operator, operator);
} else {
quickSheetMapper.updateRow(id, lineId, lineName, planCode, planType, scheduler, remark,
bizSeqNo, orderCode, contractCode, customerName, salesman,
productName, productMaterial, coatingG, productWidth, rollingThick, markCoatThick,
tonSteelLengthRange, planQty, planWeight, surfaceTreatment, widthReq, usageReq,
postProcess, nextProcess, sampleReq,
rawManufacturer, rawMaterial, rawThick, rawWidth, rawMaterialId, rawCoilNos,
rawLocation, rawPackaging, rawEdgeReq, rawCoatingType, rawNetWeight,
startTime, endTime, operator);
}
}
}
@Override
public List<ApsQuickSheetRowVo> buildPresetRows(Long lineId, String salesman) {
List<ApsQuickSheetRowVo> rows = new ArrayList<>();
LocalDateTime now = LocalDateTime.now();
LocalDateTime end = now.plusHours(1);
for (int i = 0; i < 3; i++) {
ApsQuickSheetRowVo row = new ApsQuickSheetRowVo();
row.setLineId(lineId);
row.setLineName(lineId == null ? null : ("产线" + lineId));
row.setSalesman(salesman);
row.setPlanQty(BigDecimal.ZERO);
row.setStartTime(now);
row.setEndTime(end);
row.setPlanCode(buildPlanCode());
rows.add(row);
}
return rows;
}
@Override
public void exportExcel(com.klp.aps.domain.dto.ApsQuickSheetQueryReq req, javax.servlet.http.HttpServletResponse response) {
List<ApsQuickSheetRowVo> rows = queryList(req);
try (org.apache.poi.ss.usermodel.Workbook wb = new org.apache.poi.xssf.usermodel.XSSFWorkbook()) {
org.apache.poi.ss.usermodel.Sheet sheet = wb.createSheet("快速排产表");
int r = 0;
org.apache.poi.ss.usermodel.Row title = sheet.createRow(r++);
title.setHeightInPoints(36f);
org.apache.poi.ss.usermodel.Cell t0 = title.createCell(0);
t0.setCellValue("快速排产表Excel录入");
sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(0, 0, 0, 39));
org.apache.poi.ss.usermodel.CellStyle titleStyle = wb.createCellStyle();
titleStyle.setAlignment(org.apache.poi.ss.usermodel.HorizontalAlignment.CENTER);
titleStyle.setVerticalAlignment(org.apache.poi.ss.usermodel.VerticalAlignment.CENTER);
org.apache.poi.xssf.usermodel.XSSFFont titleFont = ((org.apache.poi.xssf.usermodel.XSSFWorkbook) wb).createFont();
titleFont.setBold(true);
titleFont.setFontHeightInPoints((short) 15);
titleStyle.setFont(titleFont);
t0.setCellStyle(titleStyle);
String[] headers = new String[]{
"产线", "排产日期", "排产单号", "排产类型", "排产人", "修改人", "备注",
"内容序号", "销售内容", "订单合同号", "客户", "业务员",
"成品名称", "材质", "镀层g", "成品宽度", "轧制厚度", "标丝厚度", "吨钢长度区间m",
"数量", "重量", "表面处理", "切边要求", "宽度要求", "用途", "后处理", "下工序", "取样",
"厂家", "原料信息", "原料厚度mm", "宽度mm", "原料钢卷", "原料卷号", "钢卷位置", "包装要求", "镀层种类", "原料净重",
"开始时间", "结束时间"
};
org.apache.poi.ss.usermodel.Row head = sheet.createRow(r++);
for (int i = 0; i < headers.length; i++) {
head.createCell(i).setCellValue(headers[i]);
}
if (rows != null) {
for (ApsQuickSheetRowVo row : rows) {
org.apache.poi.ss.usermodel.Row rr = sheet.createRow(r++);
int cc = 0;
rr.createCell(cc++).setCellValue(nvl(row.getLineName(), row.getLineId()));
rr.createCell(cc++).setCellValue(row.getPlanDate() == null ? "" : row.getPlanDate().toString());
rr.createCell(cc++).setCellValue(nvl(row.getPlanCode(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getPlanType(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getScheduler(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getRemark(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getBizSeqNo(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getOrderCode(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getContractCode(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getCustomerName(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getSalesman(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getProductName(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getProductMaterial(), ""));
rr.createCell(cc++).setCellValue(row.getCoatingG() == null ? "" : row.getCoatingG().toPlainString());
rr.createCell(cc++).setCellValue(row.getProductWidth() == null ? "" : row.getProductWidth().toPlainString());
rr.createCell(cc++).setCellValue(row.getRollingThick() == null ? "" : row.getRollingThick().toPlainString());
rr.createCell(cc++).setCellValue(row.getMarkCoatThick() == null ? "" : row.getMarkCoatThick().toPlainString());
rr.createCell(cc++).setCellValue(nvl(row.getTonSteelLengthRange(), ""));
rr.createCell(cc++).setCellValue(row.getPlanQty() == null ? "" : row.getPlanQty().toPlainString());
rr.createCell(cc++).setCellValue(row.getPlanWeight() == null ? "" : row.getPlanWeight().toPlainString());
rr.createCell(cc++).setCellValue(nvl(row.getSurfaceTreatment(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getWidthReq(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getRawEdgeReq(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getUsageReq(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getPostProcess(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getNextProcess(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getSampleReq(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getRawManufacturer(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getRawMaterial(), ""));
rr.createCell(cc++).setCellValue(row.getRawThick() == null ? "" : row.getRawThick().toPlainString());
rr.createCell(cc++).setCellValue(row.getRawWidth() == null ? "" : row.getRawWidth().toPlainString());
rr.createCell(cc++).setCellValue(nvl(row.getRawMaterialId(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getRawCoilNos(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getRawLocation(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getRawPackaging(), ""));
rr.createCell(cc++).setCellValue(nvl(row.getRawCoatingType(), ""));
rr.createCell(cc++).setCellValue(row.getRawNetWeight() == null ? "" : row.getRawNetWeight().toPlainString());
rr.createCell(cc++).setCellValue(row.getStartTime() == null ? "" : row.getStartTime().toString());
rr.createCell(cc++).setCellValue(row.getEndTime() == null ? "" : row.getEndTime().toString());
}
}
for (int i = 0; i < headers.length; i++) {
sheet.autoSizeColumn(i, true);
int w = sheet.getColumnWidth(i);
sheet.setColumnWidth(i, Math.min(Math.max(w, 3000), 12000));
}
String filename = "aps_quick_sheet_" + System.currentTimeMillis() + ".xlsx";
String encoded = java.net.URLEncoder.encode(filename, java.nio.charset.StandardCharsets.UTF_8.name());
response.setCharacterEncoding(java.nio.charset.StandardCharsets.UTF_8.name());
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encoded);
try (javax.servlet.ServletOutputStream os = response.getOutputStream()) {
wb.write(os);
os.flush();
}
} catch (java.io.IOException e) {
throw new ServiceException("导出失败:" + e.getMessage());
}
}
private String buildPlanCode() {
LocalDate today = LocalDate.now();
int seq = quickSheetMapper.countToday(today) + 1;
return today.format(DATE_CODE) + String.format("%03d", seq);
}
private String nvl(Object v, Object fallback) {
if (v == null) return String.valueOf(fallback);
String s = String.valueOf(v);
return s == null ? String.valueOf(fallback) : s;
}
@Override
public void deleteById(Long id, String operator) {
if (id == null) return;
quickSheetMapper.deleteRow(id, operator);
}
private BigDecimal parseQty(String val) {
if (val == null || val.trim().isEmpty()) return null;
try {
return new BigDecimal(val.trim());
} catch (Exception e) {
return null;
}
}
private boolean isNotBlank(String val) {
return val != null && !val.trim().isEmpty();
}
private LocalDateTime parseTime(String val) {
if (val == null || val.trim().isEmpty()) return null;
String v = val.trim();
if (v.length() == 16) v = v + ":00";
try {
return LocalDateTime.parse(v, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
} catch (Exception e) {
return null;
}
}
}

View File

@@ -0,0 +1,61 @@
<?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.klp.aps.mapper.ApsPlanDetailMapper">
<resultMap type="com.klp.aps.domain.entity.ApsPlanDetail" id="ApsPlanDetailResult">
<result property="planDetailId" column="plan_detail_id"/>
<result property="planSheetId" column="plan_sheet_id"/>
<result property="bizSeqNo" column="biz_seq_no"/>
<result property="orderId" column="order_id"/>
<result property="orderCode" column="order_code"/>
<result property="contractCode" column="contract_code"/>
<result property="customerName" column="customer_name"/>
<result property="salesman" column="salesman"/>
<result property="rawManufacturer" column="raw_manufacturer"/>
<result property="rawMaterial" column="raw_material"/>
<result property="rawThick" column="raw_thick"/>
<result property="rawWidth" column="raw_width"/>
<result property="rawMaterialId" column="raw_material_id"/>
<result property="rawCoilNos" column="raw_coil_nos"/>
<result property="rawLocation" column="raw_location"/>
<result property="rawPackaging" column="raw_packaging"/>
<result property="rawEdgeReq" column="raw_edge_req"/>
<result property="rawCoatingType" column="raw_coating_type"/>
<result property="rawNetWeight" column="raw_net_weight"/>
<result property="productName" column="product_name"/>
<result property="productMaterial" column="product_material"/>
<result property="coatingG" column="coating_g"/>
<result property="productWidth" column="product_width"/>
<result property="rollingThick" column="rolling_thick"/>
<result property="markCoatThick" column="mark_coat_thick"/>
<result property="tonSteelLengthRange" column="ton_steel_length_range"/>
<result property="planQty" column="plan_qty"/>
<result property="planWeight" column="plan_weight"/>
<result property="surfaceTreatment" column="surface_treatment"/>
<result property="widthReq" column="width_req"/>
<result property="productPackaging" column="product_packaging"/>
<result property="productEdgeReq" column="product_edge_req"/>
<result property="usageReq" column="usage_req"/>
<result property="postProcess" column="post_process"/>
<result property="nextProcess" column="next_process"/>
<result property="sampleReq" column="sample_req"/>
<result property="startTime" column="start_time"/>
<result property="endTime" column="end_time"/>
<result property="remark" column="remark"/>
<result property="delFlag" column="del_flag"/>
<result property="createBy" column="create_by"/>
<result property="updateBy" column="update_by"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
</resultMap>
<delete id="deleteByPlanSheetIds">
UPDATE aps_plan_detail SET del_flag = 2 WHERE plan_sheet_id IN
<foreach collection="collection" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@@ -0,0 +1,77 @@
<?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.klp.aps.mapper.ApsPlanSheetMapper">
<resultMap type="com.klp.aps.domain.entity.ApsPlanSheet" id="ApsPlanSheetResult">
<result property="planSheetId" column="plan_sheet_id"/>
<result property="planDate" column="plan_date"/>
<result property="lineId" column="line_id"/>
<result property="lineName" column="line_name"/>
<result property="planCode" column="plan_code"/>
<result property="planType" column="plan_type"/>
<result property="scheduler" column="scheduler"/>
<result property="remark" column="remark"/>
<result property="delFlag" column="del_flag"/>
<result property="createBy" column="create_by"/>
<result property="updateBy" column="update_by"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
</resultMap>
<select id="selectList" parameterType="com.klp.aps.domain.dto.ApsPlanSheetQueryReq" resultType="com.klp.aps.domain.vo.ApsPlanSheetRowVo">
SELECT
d.plan_detail_id AS detailSheetId,
s.plan_date AS planDate,
s.line_id AS lineId,
s.line_name AS lineName,
s.plan_code AS planCode,
s.plan_type AS planType,
s.scheduler AS scheduler,
s.remark AS masterRemark,
d.remark AS detailRemark,
s.update_by AS updateBy,
d.biz_seq_no AS bizSeqNo,
d.order_code AS orderCode,
d.contract_code AS contractCode,
d.customer_name AS customerName,
d.salesman AS salesman,
d.product_name AS productName,
d.product_material AS productMaterial,
d.coating_g AS coatingG,
d.product_width AS productWidth,
d.rolling_thick AS rollingThick,
d.mark_coat_thick AS markCoatThick,
d.ton_steel_length_range AS tonSteelLengthRange,
d.plan_qty AS planQty,
d.plan_weight AS planWeight,
d.surface_treatment AS surfaceTreatment,
d.width_req AS widthReq,
d.usage_req AS usageReq,
d.post_process AS postProcess,
d.next_process AS nextProcess,
d.sample_req AS sampleReq,
d.raw_manufacturer AS rawManufacturer,
d.raw_material AS rawMaterial,
d.raw_thick AS rawThick,
d.raw_width AS rawWidth,
CAST(d.raw_material_id AS CHAR) AS rawMaterialId,
d.raw_coil_nos AS rawCoilNos,
d.raw_location AS rawLocation,
d.raw_packaging AS rawPackaging,
d.raw_edge_req AS rawEdgeReq,
d.raw_coating_type AS rawCoatingType,
d.raw_net_weight AS rawNetWeight,
d.start_time AS startTime,
d.end_time AS endTime
FROM aps_plan_sheet s
INNER JOIN aps_plan_detail d ON d.plan_sheet_id = s.plan_sheet_id AND d.del_flag = 0
WHERE s.del_flag = 0
<if test="planSheetId != null">
AND s.plan_sheet_id = #{planSheetId}
</if>
ORDER BY CAST(d.biz_seq_no AS UNSIGNED) ASC
</select>
</mapper>

View File

@@ -0,0 +1,176 @@
<?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.klp.aps.mapper.ApsQuickSheetMapper">
<select id="selectList" parameterType="com.klp.aps.domain.dto.ApsQuickSheetQueryReq" resultType="com.klp.aps.domain.vo.ApsQuickSheetRowVo">
SELECT
quick_sheet_id AS quickSheetId,
plan_date AS planDate,
line_id AS lineId,
line_name AS lineName,
plan_code AS planCode,
plan_type AS planType,
scheduler,
remark,
biz_seq_no AS bizSeqNo,
order_code AS orderCode,
contract_code AS contractCode,
customer_name AS customerName,
salesman,
product_name AS productName,
product_material AS productMaterial,
coating_g AS coatingG,
product_width AS productWidth,
rolling_thick AS rollingThick,
mark_coat_thick AS markCoatThick,
ton_steel_length_range AS tonSteelLengthRange,
plan_qty AS planQty,
plan_weight AS planWeight,
surface_treatment AS surfaceTreatment,
width_req AS widthReq,
usage_req AS usageReq,
post_process AS postProcess,
next_process AS nextProcess,
sample_req AS sampleReq,
raw_manufacturer AS rawManufacturer,
raw_material AS rawMaterial,
raw_thick AS rawThick,
raw_width AS rawWidth,
raw_material_id AS rawMaterialId,
raw_coil_nos AS rawCoilNos,
raw_location AS rawLocation,
raw_packaging AS rawPackaging,
raw_edge_req AS rawEdgeReq,
raw_coating_type AS rawCoatingType,
raw_net_weight AS rawNetWeight,
start_time AS startTime,
end_time AS endTime
FROM aps_quick_sheet
WHERE del_flag = 0
<if test="startDate != null">
AND start_time <![CDATA[>=]]> CONCAT(#{startDate}, ' 00:00:00')
</if>
<if test="endDate != null">
AND start_time <![CDATA[<=]]> CONCAT(#{endDate}, ' 23:59:59')
</if>
<if test="lineId != null">
AND line_id = #{lineId}
</if>
<if test="customerName != null and customerName != ''">
AND customer_name LIKE CONCAT('%', #{customerName}, '%')
</if>
ORDER BY quick_sheet_id DESC
</select>
<select id="countToday" resultType="int">
SELECT COUNT(1)
FROM aps_quick_sheet
WHERE del_flag = 0
AND plan_date = #{planDate}
</select>
<select id="selectIdByPlanCode" resultType="long">
SELECT quick_sheet_id
FROM aps_quick_sheet
WHERE plan_code = #{planCode}
AND del_flag = 0
LIMIT 1
</select>
<insert id="insertRow">
INSERT INTO aps_quick_sheet (
line_id, line_name, plan_date, plan_code, plan_type, scheduler, remark,
biz_seq_no, order_code, contract_code, customer_name, salesman,
product_name, product_material, coating_g, product_width, rolling_thick, mark_coat_thick,
ton_steel_length_range, plan_qty, plan_weight, surface_treatment, width_req, usage_req,
post_process, next_process, sample_req,
raw_manufacturer, raw_material, raw_thick, raw_width, raw_material_id, raw_coil_nos,
raw_location, raw_packaging, raw_edge_req, raw_coating_type, raw_net_weight,
start_time, end_time,
create_by, update_by, create_time, update_time, del_flag
) VALUES (
#{lineId}, #{lineName}, #{planDate}, #{planCode}, #{planType}, #{scheduler}, #{remark},
#{bizSeqNo}, #{orderCode}, #{contractCode}, #{customerName}, #{salesman},
#{productName}, #{productMaterial}, #{coatingG}, #{productWidth}, #{rollingThick}, #{markCoatThick},
#{tonSteelLengthRange}, #{planQty}, #{planWeight}, #{surfaceTreatment}, #{widthReq}, #{usageReq},
#{postProcess}, #{nextProcess}, #{sampleReq},
#{rawManufacturer}, #{rawMaterial}, #{rawThick}, #{rawWidth}, #{rawMaterialId}, #{rawCoilNos},
#{rawLocation}, #{rawPackaging}, #{rawEdgeReq}, #{rawCoatingType}, #{rawNetWeight},
#{startTime}, #{endTime},
#{createBy}, #{updateBy}, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 0
)
</insert>
<update id="updateRow">
UPDATE aps_quick_sheet
SET line_id = #{lineId},
line_name = #{lineName},
plan_code = #{planCode},
plan_type = #{planType},
scheduler = #{scheduler},
remark = #{remark},
biz_seq_no = #{bizSeqNo},
order_code = #{orderCode},
contract_code = #{contractCode},
customer_name = #{customerName},
salesman = #{salesman},
product_name = #{productName},
product_material = #{productMaterial},
coating_g = #{coatingG},
product_width = #{productWidth},
rolling_thick = #{rollingThick},
mark_coat_thick = #{markCoatThick},
ton_steel_length_range = #{tonSteelLengthRange},
plan_qty = #{planQty},
plan_weight = #{planWeight},
surface_treatment = #{surfaceTreatment},
width_req = #{widthReq},
usage_req = #{usageReq},
post_process = #{postProcess},
next_process = #{nextProcess},
sample_req = #{sampleReq},
raw_manufacturer = #{rawManufacturer},
raw_material = #{rawMaterial},
raw_thick = #{rawThick},
raw_width = #{rawWidth},
raw_material_id = #{rawMaterialId},
raw_coil_nos = #{rawCoilNos},
raw_location = #{rawLocation},
raw_packaging = #{rawPackaging},
raw_edge_req = #{rawEdgeReq},
raw_coating_type = #{rawCoatingType},
raw_net_weight = #{rawNetWeight},
start_time = #{startTime},
end_time = #{endTime},
update_by = #{updateBy},
update_time = CURRENT_TIMESTAMP
WHERE quick_sheet_id = #{id}
</update>
<update id="deleteRow">
UPDATE aps_quick_sheet
SET del_flag = 1,
update_by = #{updateBy},
update_time = CURRENT_TIMESTAMP
WHERE quick_sheet_id = #{id}
</update>
<update id="softDelete">
UPDATE aps_quick_sheet
SET del_flag = 1,
update_by = #{updateBy},
update_time = CURRENT_TIMESTAMP
WHERE quick_sheet_id = #{id}
</update>
<update id="deleteById">
UPDATE aps_quick_sheet
SET del_flag = 1,
update_by = #{updateBy},
update_time = CURRENT_TIMESTAMP
WHERE quick_sheet_id = #{id}
</update>
</mapper>

View File

@@ -170,16 +170,6 @@
<artifactId>ip2region</artifactId>
</dependency>
<!-- 引入flyway -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
<!-- 动态数据源依赖 -->
<dependency>
<groupId>com.baomidou</groupId>

View File

@@ -1,68 +0,0 @@
package com.klp.common.config;
import javax.annotation.Resource;
import javax.sql.DataSource;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.output.MigrateResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FlywayConfig {
@Value("${spring.profiles.active}")
private String activeProfile;
@Value("${spring.flyway.baseline-on-migrate}")
private boolean baselineOnMigrate;
@Value("${spring.flyway.locations}")
private String locations;
@Value("${spring.flyway.table}")
private String table;
@Resource
private DataSource dataSource;
@Bean
public Flyway flyway() {
DataSource masterDataSource = ((DynamicRoutingDataSource) dataSource).getDataSource("master");
System.out.println("masterDataSource class: " + masterDataSource.getClass().getName());
// // 如果想显式拿底层 HikariDataSource
// if (masterDataSource instanceof ItemDataSource) {
// masterDataSource = ((ItemDataSource) masterDataSource).getRealDataSource();
// }
System.out.println("masterDataSource class: " + masterDataSource.getClass().getName());
return Flyway.configure()
.dataSource(masterDataSource) // 注意这里是真实主库 DataSource
.baselineOnMigrate(baselineOnMigrate)
.locations(locations)
.table(table)
.load();
}
@Bean
public CommandLineRunner flywayRunner(Flyway flyway) {
return args -> {
System.out.println("========== 当前环境: " + activeProfile + " ==========");
System.out.println("========== 开始执行 Flyway 数据库迁移 ==========");
MigrateResult result = flyway.migrate();
System.out.println("迁移成功版本数: " + result.migrationsExecuted);
result.migrations.forEach(m -> {
System.out.println("执行版本: " + m.version + ",描述: " + m.description);
});
System.out.println("========== Flyway 数据库迁移完成 ==========");
};
}
}

View File

@@ -0,0 +1,99 @@
package com.klp.crm.controller;
import java.util.List;
import java.util.Arrays;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.klp.common.annotation.RepeatSubmit;
import com.klp.common.annotation.Log;
import com.klp.common.core.controller.BaseController;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.R;
import com.klp.common.core.validate.AddGroup;
import com.klp.common.core.validate.EditGroup;
import com.klp.common.enums.BusinessType;
import com.klp.common.utils.poi.ExcelUtil;
import com.klp.crm.domain.vo.CrmContractVo;
import com.klp.crm.domain.bo.CrmContractBo;
import com.klp.crm.service.ICrmContractService;
import com.klp.common.core.page.TableDataInfo;
/**
* 合同信息
*
* @author klp
* @date 2026-03-30
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/crm/contract")
public class CrmContractController extends BaseController {
private final ICrmContractService iCrmContractService;
/**
* 查询合同信息列表
*/
@GetMapping("/list")
public TableDataInfo<CrmContractVo> list(CrmContractBo bo, PageQuery pageQuery) {
return iCrmContractService.queryPageList(bo, pageQuery);
}
/**
* 导出合同信息列表
*/
@Log(title = "合同信息", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(CrmContractBo bo, HttpServletResponse response) {
List<CrmContractVo> list = iCrmContractService.queryList(bo);
ExcelUtil.exportExcel(list, "合同信息", CrmContractVo.class, response);
}
/**
* 获取合同信息详细信息
*
* @param contractId 主键
*/
@GetMapping("/{contractId}")
public R<CrmContractVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long contractId) {
return R.ok(iCrmContractService.queryById(contractId));
}
/**
* 新增合同信息
*/
@Log(title = "合同信息", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody CrmContractBo bo) {
return toAjax(iCrmContractService.insertByBo(bo));
}
/**
* 修改合同信息
*/
@Log(title = "合同信息", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CrmContractBo bo) {
return toAjax(iCrmContractService.updateByBo(bo));
}
/**
* 删除合同信息
*
* @param contractIds 主键串
*/
@Log(title = "合同信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{contractIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] contractIds) {
return toAjax(iCrmContractService.deleteWithValidByIds(Arrays.asList(contractIds), true));
}
}

View File

@@ -0,0 +1,99 @@
package com.klp.crm.controller;
import java.util.List;
import java.util.Arrays;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.klp.common.annotation.RepeatSubmit;
import com.klp.common.annotation.Log;
import com.klp.common.core.controller.BaseController;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.R;
import com.klp.common.core.validate.AddGroup;
import com.klp.common.core.validate.EditGroup;
import com.klp.common.enums.BusinessType;
import com.klp.common.utils.poi.ExcelUtil;
import com.klp.crm.domain.vo.CrmContractProductVo;
import com.klp.crm.domain.bo.CrmContractProductBo;
import com.klp.crm.service.ICrmContractProductService;
import com.klp.common.core.page.TableDataInfo;
/**
* 合同产品明细
*
* @author klp
* @date 2026-03-30
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/crm/contractProduct")
public class CrmContractProductController extends BaseController {
private final ICrmContractProductService iCrmContractProductService;
/**
* 查询合同产品明细列表
*/
@GetMapping("/list")
public TableDataInfo<CrmContractProductVo> list(CrmContractProductBo bo, PageQuery pageQuery) {
return iCrmContractProductService.queryPageList(bo, pageQuery);
}
/**
* 导出合同产品明细列表
*/
@Log(title = "合同产品明细", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(CrmContractProductBo bo, HttpServletResponse response) {
List<CrmContractProductVo> list = iCrmContractProductService.queryList(bo);
ExcelUtil.exportExcel(list, "合同产品明细", CrmContractProductVo.class, response);
}
/**
* 获取合同产品明细详细信息
*
* @param contractProductId 主键
*/
@GetMapping("/{contractProductId}")
public R<CrmContractProductVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long contractProductId) {
return R.ok(iCrmContractProductService.queryById(contractProductId));
}
/**
* 新增合同产品明细
*/
@Log(title = "合同产品明细", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody CrmContractProductBo bo) {
return toAjax(iCrmContractProductService.insertByBo(bo));
}
/**
* 修改合同产品明细
*/
@Log(title = "合同产品明细", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CrmContractProductBo bo) {
return toAjax(iCrmContractProductService.updateByBo(bo));
}
/**
* 删除合同产品明细
*
* @param contractProductIds 主键串
*/
@Log(title = "合同产品明细", businessType = BusinessType.DELETE)
@DeleteMapping("/{contractProductIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] contractProductIds) {
return toAjax(iCrmContractProductService.deleteWithValidByIds(Arrays.asList(contractProductIds), true));
}
}

View File

@@ -18,8 +18,10 @@ import com.klp.common.core.validate.EditGroup;
import com.klp.common.enums.BusinessType;
import com.klp.common.utils.poi.ExcelUtil;
import com.klp.crm.domain.vo.CrmOrderItemVo;
import com.klp.crm.domain.vo.CrmContractOrderFinanceVo;
import com.klp.crm.domain.bo.CrmOrderItemBo;
import com.klp.crm.service.ICrmOrderItemService;
import com.klp.domain.vo.WmsMaterialCoilVo;
import com.klp.common.core.page.TableDataInfo;
/**
@@ -96,4 +98,24 @@ public class CrmOrderItemController extends BaseController {
@PathVariable String[] itemIds) {
return toAjax(iCrmOrderItemService.deleteWithValidByIds(Arrays.asList(itemIds), true));
}
// 根据合同id查询该合同下属订单关联的异议和财务信息。。
@GetMapping("/contractFinance/{contractId}")
public R<CrmContractOrderFinanceVo> getContractFinance(@NotNull(message = "合同ID不能为空")
@PathVariable Long contractId) {
return R.ok(iCrmOrderItemService.queryFinanceAndObjectionByContractId(contractId));
}
// 根据订单id查询发货单据中的配卷。
@GetMapping("/coils/order/{orderId}")
public R<List<WmsMaterialCoilVo>> getCoilsByOrderId(@NotNull(message = "订单ID不能为空")
@PathVariable Long orderId) {
return R.ok(iCrmOrderItemService.queryCoilsByOrderId(orderId));
}
// 根据合同id查询发货单据中的配卷。
@GetMapping("/coils/contract/{contractId}")
public R<List<WmsMaterialCoilVo>> getCoilsByContractId(@NotNull(message = "合同ID不能为空")
@PathVariable Long contractId) {
return R.ok(iCrmOrderItemService.queryCoilsByContractId(contractId));
}
}

View File

@@ -0,0 +1,131 @@
package com.klp.crm.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 合同信息对象 crm_contract
*
* @author klp
* @date 2026-03-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("crm_contract")
public class CrmContract extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 合同主键ID
*/
@TableId(value = "contract_id")
private Long contractId;
/**
* 合同名称
*/
private String contractName;
/**
* 合同编号
*/
private String contractNo;
/**
* 供方
*/
private String supplier;
/**
* 需方
*/
private String customer;
/**
* 签订时间
*/
private Date signTime;
/**
* 交货日期
*/
private Date deliveryDate;
/**
* 签订地点
*/
private String signLocation;
/**
* 产品内容
*/
private String productContent;
/**
* 合同内容
*/
private String contractContent;
/**
* 供方地址
*/
private String supplierAddress;
/**
* 供方电话
*/
private String supplierPhone;
/**
* 供方开户行
*/
private String supplierBank;
/**
* 供方账号
*/
private String supplierAccount;
/**
* 供方税号
*/
private String supplierTaxNo;
/**
* 需方地址
*/
private String customerAddress;
/**
* 需方电话
*/
private String customerPhone;
/**
* 需方开户行
*/
private String customerBank;
/**
* 需方账号
*/
private String customerAccount;
/**
* 需方税号
*/
private String customerTaxNo;
/**
* 技术附件
*/
private String techAnnex;
/**
* 商务附件
*/
private String businessAnnex;
/**
* 排产函
*/
private String productionSchedule;
/**
* 合同状态 0=草稿 1=生效 2=作废 3=已完成
*/
private Long status;
/**
* 备注
*/
private String remark;
/**
* 删除标识 0正常 2删除
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,74 @@
package com.klp.crm.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
/**
* 合同产品明细对象 crm_contract_product
*
* @author klp
* @date 2026-03-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("crm_contract_product")
public class CrmContractProduct extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 合同产品主键ID
*/
@TableId(value = "contract_product_id")
private Long contractProductId;
/**
* 关联合同ID绑定wms_contract表主键
*/
private Long contractId;
/**
* 产品名称
*/
private String productName;
/**
* 规格最小值(mm)
*/
private BigDecimal specMin;
/**
* 规格最大值(mm)
*/
private BigDecimal specMax;
/**
* 材质
*/
private String material;
/**
* 数量(吨)
*/
private BigDecimal quantity;
/**
* 含税单价(元/吨)
*/
private BigDecimal taxInclusiveUnitPrice;
/**
* 不含税单价(元/吨)
*/
private BigDecimal exTaxUnitPrice;
/**
* 含税总额(元)
*/
private BigDecimal taxInclusiveAmount;
/**
* 删除标识 0正常 2删除
*/
@TableLogic
private Long delFlag;
/**
* 备注
*/
private String remark;
}

View File

@@ -56,6 +56,10 @@ public class CrmCustomer extends BaseEntity {
* 银行信息多条需权限查看JSON格式存储
*/
private String bankInfo;
/**
* 纳税人识别号/税号
*/
private String taxNumber;
/**
* 备注
*/

View File

@@ -26,7 +26,7 @@ public class CrmOrder extends BaseEntity {
* 订单ID主键
*/
@TableId(value = "order_id")
private String orderId;
private Long orderId;
/**
* 订单编号
*/
@@ -85,6 +85,16 @@ public class CrmOrder extends BaseEntity {
*/
private String contractCode;
/**
* 关联合同IDwms_contract.contract_id
*/
private Long contractId;
/**
* 附件多个文件URL用逗号分隔
*/
private String annexFiles;
/**
* 删除标识 0正常 2删除
*/

View File

@@ -24,11 +24,11 @@ public class CrmOrderItem extends BaseEntity {
* 正式订单明细ID主键
*/
@TableId(value = "item_id")
private String itemId;
private Long itemId;
/**
* 关联正式订单ID外键
*/
private String orderId;
private Long orderId;
/**
* 产品类型
*/
@@ -69,6 +69,14 @@ public class CrmOrderItem extends BaseEntity {
* 重量
*/
private BigDecimal weight;
/**
* 宽度公差
*/
private BigDecimal widthTolerance;
/**
* 厚度公差
*/
private BigDecimal thicknessTolerance;
/**
* 合同定价
*/
@@ -91,4 +99,4 @@ public class CrmOrderItem extends BaseEntity {
@TableLogic
private Long delFlag;
}
}

View File

@@ -0,0 +1,151 @@
package com.klp.crm.domain.bo;
import org.springframework.format.annotation.DateTimeFormat;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 合同信息业务对象 crm_contract
*
* @author klp
* @date 2026-03-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CrmContractBo extends BaseEntity {
/**
* 合同主键ID
*/
private Long contractId;
/**
* 合同名称
*/
private String contractName;
/**
* 合同编号
*/
private String contractNo;
/**
* 供方
*/
private String supplier;
/**
* 需方
*/
private String customer;
/**
* 签订时间
*/
private Date signTime;
/**
* 交货日期
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date deliveryDate;
/**
* 签订地点
*/
private String signLocation;
/**
* 产品内容
*/
private String productContent;
/**
* 合同内容
*/
private String contractContent;
/**
* 供方地址
*/
private String supplierAddress;
/**
* 供方电话
*/
private String supplierPhone;
/**
* 供方开户行
*/
private String supplierBank;
/**
* 供方账号
*/
private String supplierAccount;
/**
* 供方税号
*/
private String supplierTaxNo;
/**
* 需方地址
*/
private String customerAddress;
/**
* 需方电话
*/
private String customerPhone;
/**
* 需方开户行
*/
private String customerBank;
/**
* 需方账号
*/
private String customerAccount;
/**
* 需方税号
*/
private String customerTaxNo;
/**
* 技术附件
*/
private String techAnnex;
/**
* 商务附件
*/
private String businessAnnex;
/**
* 排产函
*/
private String productionSchedule;
/**
* 合同状态 0=草稿 1=生效 2=作废 3=已完成
*/
private Long status;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,77 @@
package com.klp.crm.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
import java.math.BigDecimal;
/**
* 合同产品明细业务对象 crm_contract_product
*
* @author klp
* @date 2026-03-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CrmContractProductBo extends BaseEntity {
/**
* 合同产品主键ID
*/
private Long contractProductId;
/**
* 关联合同ID绑定wms_contract表主键
*/
private Long contractId;
/**
* 产品名称
*/
private String productName;
/**
* 规格最小值(mm)
*/
private BigDecimal specMin;
/**
* 规格最大值(mm)
*/
private BigDecimal specMax;
/**
* 材质
*/
private String material;
/**
* 数量(吨)
*/
private BigDecimal quantity;
/**
* 含税单价(元/吨)
*/
private BigDecimal taxInclusiveUnitPrice;
/**
* 不含税单价(元/吨)
*/
private BigDecimal exTaxUnitPrice;
/**
* 含税总额(元)
*/
private BigDecimal taxInclusiveAmount;
/**
* 备注
*/
private String remark;
}

View File

@@ -62,6 +62,11 @@ public class CrmCustomerBo extends BaseEntity {
*/
private String bankInfo;
/**
* 纳税人识别号/税号
*/
private String taxNumber;
/**
* 备注
*/

View File

@@ -23,7 +23,7 @@ public class CrmOrderBo extends BaseEntity {
/**
* 订单ID主键
*/
private String orderId;
private Long orderId;
/**
* 订单编号
@@ -95,5 +95,15 @@ public class CrmOrderBo extends BaseEntity {
*/
private String contractCode;
/**
* 关联合同IDwms_contract.contract_id
*/
private Long contractId;
/**
* 附件多个文件URL用逗号分隔
*/
private String annexFiles;
}

View File

@@ -21,12 +21,12 @@ public class CrmOrderItemBo extends BaseEntity {
/**
* 正式订单明细ID主键
*/
private String itemId;
private Long itemId;
/**
* 关联正式订单ID外键
*/
private String orderId;
private Long orderId;
/**
* 产品类型
@@ -57,7 +57,7 @@ public class CrmOrderItemBo extends BaseEntity {
* 备注
*/
private String remark;
/**
* 成品规格
*/
@@ -78,6 +78,16 @@ public class CrmOrderItemBo extends BaseEntity {
*/
private BigDecimal weight;
/**
* 宽度公差
*/
private BigDecimal widthTolerance;
/**
* 厚度公差
*/
private BigDecimal thicknessTolerance;
/**
* 合同定价
*/
@@ -99,4 +109,4 @@ public class CrmOrderItemBo extends BaseEntity {
private String productionBatch;
}
}

View File

@@ -0,0 +1,14 @@
package com.klp.crm.domain.vo;
import com.klp.domain.vo.WmsReceivableVo;
import lombok.Data;
import java.util.List;
@Data
public class CrmContractOrderFinanceVo {
private List<CrmSalesObjectionVo> objectionList;
private List<WmsReceivableVo> receivableList;
}

View File

@@ -0,0 +1,91 @@
package com.klp.crm.domain.vo;
import java.math.BigDecimal;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.klp.common.annotation.ExcelDictFormat;
import com.klp.common.convert.ExcelDictConvert;
import lombok.Data;
/**
* 合同产品明细视图对象 crm_contract_product
*
* @author klp
* @date 2026-03-30
*/
@Data
@ExcelIgnoreUnannotated
public class CrmContractProductVo {
private static final long serialVersionUID = 1L;
/**
* 合同产品主键ID
*/
@ExcelProperty(value = "合同产品主键ID")
private Long contractProductId;
/**
* 关联合同ID绑定wms_contract表主键
*/
@ExcelProperty(value = "关联合同ID", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "绑=定wms_contract表主键")
private Long contractId;
/**
* 产品名称
*/
@ExcelProperty(value = "产品名称")
private String productName;
/**
* 规格最小值(mm)
*/
@ExcelProperty(value = "规格最小值(mm)")
private BigDecimal specMin;
/**
* 规格最大值(mm)
*/
@ExcelProperty(value = "规格最大值(mm)")
private BigDecimal specMax;
/**
* 材质
*/
@ExcelProperty(value = "材质")
private String material;
/**
* 数量(吨)
*/
@ExcelProperty(value = "数量(吨)")
private BigDecimal quantity;
/**
* 含税单价(元/吨)
*/
@ExcelProperty(value = "含税单价(元/吨)")
private BigDecimal taxInclusiveUnitPrice;
/**
* 不含税单价(元/吨)
*/
@ExcelProperty(value = "不含税单价(元/吨)")
private BigDecimal exTaxUnitPrice;
/**
* 含税总额(元)
*/
@ExcelProperty(value = "含税总额(元)")
private BigDecimal taxInclusiveAmount;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -0,0 +1,174 @@
package com.klp.crm.domain.vo;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.klp.common.annotation.ExcelDictFormat;
import com.klp.common.convert.ExcelDictConvert;
import lombok.Data;
/**
* 合同信息视图对象 crm_contract
*
* @author klp
* @date 2026-03-30
*/
@Data
@ExcelIgnoreUnannotated
public class CrmContractVo {
private static final long serialVersionUID = 1L;
/**
* 合同主键ID
*/
@ExcelProperty(value = "合同主键ID")
private Long contractId;
/**
* 合同名称
*/
@ExcelProperty(value = "合同名称")
private String contractName;
/**
* 合同编号
*/
@ExcelProperty(value = "合同编号")
private String contractNo;
/**
* 供方
*/
@ExcelProperty(value = "供方")
private String supplier;
/**
* 需方
*/
@ExcelProperty(value = "需方")
private String customer;
/**
* 签订时间
*/
@ExcelProperty(value = "签订时间")
private Date signTime;
/**
* 交货日期
*/
@ExcelProperty(value = "交货日期")
private Date deliveryDate;
/**
* 签订地点
*/
@ExcelProperty(value = "签订地点")
private String signLocation;
/**
* 产品内容
*/
@ExcelProperty(value = "产品内容")
private String productContent;
/**
* 合同内容
*/
@ExcelProperty(value = "合同内容")
private String contractContent;
/**
* 供方地址
*/
@ExcelProperty(value = "供方地址")
private String supplierAddress;
/**
* 供方电话
*/
@ExcelProperty(value = "供方电话")
private String supplierPhone;
/**
* 供方开户行
*/
@ExcelProperty(value = "供方开户行")
private String supplierBank;
/**
* 供方账号
*/
@ExcelProperty(value = "供方账号")
private String supplierAccount;
/**
* 供方税号
*/
@ExcelProperty(value = "供方税号")
private String supplierTaxNo;
/**
* 需方地址
*/
@ExcelProperty(value = "需方地址")
private String customerAddress;
/**
* 需方电话
*/
@ExcelProperty(value = "需方电话")
private String customerPhone;
/**
* 需方开户行
*/
@ExcelProperty(value = "需方开户行")
private String customerBank;
/**
* 需方账号
*/
@ExcelProperty(value = "需方账号")
private String customerAccount;
/**
* 需方税号
*/
@ExcelProperty(value = "需方税号")
private String customerTaxNo;
/**
* 技术附件
*/
@ExcelProperty(value = "技术附件")
private String techAnnex;
/**
* 商务附件
*/
@ExcelProperty(value = "商务附件")
private String businessAnnex;
/**
* 排产函
*/
@ExcelProperty(value = "排产函")
private String productionSchedule;
/**
* 合同状态 0=草稿 1=生效 2=作废 3=已完成
*/
@ExcelProperty(value = "合同状态 0=草稿 1=生效 2=作废 3=已完成")
private Long status;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -78,6 +78,12 @@ public class CrmCustomerVo {
@ExcelDictFormat(readConverterExp = "多=条需权限查看JSON格式存储")
private String bankInfo;
/**
* 纳税人识别号/税号
*/
@ExcelProperty(value = "纳税人识别号/税号")
private String taxNumber;
/**
* 备注
*/

View File

@@ -25,14 +25,14 @@ public class CrmOrderItemVo {
*/
@ExcelProperty(value = "正式订单明细ID", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "主=键")
private String itemId;
private Long itemId;
/**
* 关联正式订单ID外键
*/
@ExcelProperty(value = "关联正式订单ID", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "外=键")
private String orderId;
private Long orderId;
/**
* 产品类型
@@ -95,6 +95,18 @@ public class CrmOrderItemVo {
@ExcelProperty(value = "重量")
private BigDecimal weight;
/**
* 宽度公差
*/
@ExcelProperty(value = "宽度公差")
private BigDecimal widthTolerance;
/**
* 厚度公差
*/
@ExcelProperty(value = "厚度公差")
private BigDecimal thicknessTolerance;
/**
* 合同定价
*/
@@ -120,4 +132,4 @@ public class CrmOrderItemVo {
private String productionBatch;
}
}

View File

@@ -28,7 +28,7 @@ public class CrmOrderVo extends BaseEntity {
*/
@ExcelProperty(value = "订单ID", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "主=键")
private String orderId;
private Long orderId;
/**
* 订单编号
@@ -114,6 +114,18 @@ public class CrmOrderVo extends BaseEntity {
@ExcelProperty(value = "合同号")
private String contractCode;
/**
* 关联合同IDwms_contract.contract_id
*/
@ExcelProperty(value = "关联合同ID")
private Long contractId;
/**
* 附件多个文件URL用逗号分隔
*/
@ExcelProperty(value = "附件")
private String annexFiles;
// @ExcelProperty(value = "客户编号")
private String customerCode;

View File

@@ -98,7 +98,7 @@ public class CrmSalesReportVo {
/**
* 订单ID
*/
private String orderId;
private Long orderId;
/**
* 订单编号

View File

@@ -0,0 +1,15 @@
package com.klp.crm.mapper;
import com.klp.crm.domain.CrmContract;
import com.klp.crm.domain.vo.CrmContractVo;
import com.klp.common.core.mapper.BaseMapperPlus;
/**
* 合同信息Mapper接口
*
* @author klp
* @date 2026-03-30
*/
public interface CrmContractMapper extends BaseMapperPlus<CrmContractMapper, CrmContract, CrmContractVo> {
}

View File

@@ -0,0 +1,15 @@
package com.klp.crm.mapper;
import com.klp.crm.domain.CrmContractProduct;
import com.klp.crm.domain.vo.CrmContractProductVo;
import com.klp.common.core.mapper.BaseMapperPlus;
/**
* 合同产品明细Mapper接口
*
* @author klp
* @date 2026-03-30
*/
public interface CrmContractProductMapper extends BaseMapperPlus<CrmContractProductMapper, CrmContractProduct, CrmContractProductVo> {
}

View File

@@ -21,5 +21,5 @@ public interface CrmOrderItemMapper extends BaseMapperPlus<CrmOrderItemMapper, C
* @param orderIds 订单ID列表
* @return 订单明细列表
*/
List<CrmOrderItem> selectOrderItemsByOrderIds(@Param("orderIds") List<String> orderIds);
List<CrmOrderItem> selectOrderItemsByOrderIds(@Param("orderIds") List<Long> orderIds);
}

View File

@@ -0,0 +1,49 @@
package com.klp.crm.service;
import com.klp.crm.domain.CrmContractProduct;
import com.klp.crm.domain.vo.CrmContractProductVo;
import com.klp.crm.domain.bo.CrmContractProductBo;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 合同产品明细Service接口
*
* @author klp
* @date 2026-03-30
*/
public interface ICrmContractProductService {
/**
* 查询合同产品明细
*/
CrmContractProductVo queryById(Long contractProductId);
/**
* 查询合同产品明细列表
*/
TableDataInfo<CrmContractProductVo> queryPageList(CrmContractProductBo bo, PageQuery pageQuery);
/**
* 查询合同产品明细列表
*/
List<CrmContractProductVo> queryList(CrmContractProductBo bo);
/**
* 新增合同产品明细
*/
Boolean insertByBo(CrmContractProductBo bo);
/**
* 修改合同产品明细
*/
Boolean updateByBo(CrmContractProductBo bo);
/**
* 校验并批量删除合同产品明细信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,49 @@
package com.klp.crm.service;
import com.klp.crm.domain.CrmContract;
import com.klp.crm.domain.vo.CrmContractVo;
import com.klp.crm.domain.bo.CrmContractBo;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 合同信息Service接口
*
* @author klp
* @date 2026-03-30
*/
public interface ICrmContractService {
/**
* 查询合同信息
*/
CrmContractVo queryById(Long contractId);
/**
* 查询合同信息列表
*/
TableDataInfo<CrmContractVo> queryPageList(CrmContractBo bo, PageQuery pageQuery);
/**
* 查询合同信息列表
*/
List<CrmContractVo> queryList(CrmContractBo bo);
/**
* 新增合同信息
*/
Boolean insertByBo(CrmContractBo bo);
/**
* 修改合同信息
*/
Boolean updateByBo(CrmContractBo bo);
/**
* 校验并批量删除合同信息信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -9,6 +9,10 @@ import com.klp.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
import com.klp.crm.domain.vo.CrmContractOrderFinanceVo;
import com.klp.domain.vo.WmsMaterialCoilVo;
import java.util.List;
/**
* 正式订单明细Service接口
*
@@ -46,4 +50,19 @@ public interface ICrmOrderItemService {
* 校验并批量删除正式订单明细信息
*/
Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid);
/**
* 根据合同ID查询下属订单的异议和财务信息
*/
CrmContractOrderFinanceVo queryFinanceAndObjectionByContractId(Long contractId);
/**
* 根据订单ID查询发货单配卷
*/
List<WmsMaterialCoilVo> queryCoilsByOrderId(Long orderId);
/**
* 根据合同ID查询发货单配卷
*/
List<WmsMaterialCoilVo> queryCoilsByContractId(Long contractId);
}

View File

@@ -0,0 +1,117 @@
package com.klp.crm.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.klp.crm.domain.bo.CrmContractProductBo;
import com.klp.crm.domain.vo.CrmContractProductVo;
import com.klp.crm.domain.CrmContractProduct;
import com.klp.crm.mapper.CrmContractProductMapper;
import com.klp.crm.service.ICrmContractProductService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 合同产品明细Service业务层处理
*
* @author klp
* @date 2026-03-30
*/
@RequiredArgsConstructor
@Service
public class CrmContractProductServiceImpl implements ICrmContractProductService {
private final CrmContractProductMapper baseMapper;
/**
* 查询合同产品明细
*/
@Override
public CrmContractProductVo queryById(Long contractProductId){
return baseMapper.selectVoById(contractProductId);
}
/**
* 查询合同产品明细列表
*/
@Override
public TableDataInfo<CrmContractProductVo> queryPageList(CrmContractProductBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<CrmContractProduct> lqw = buildQueryWrapper(bo);
Page<CrmContractProductVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询合同产品明细列表
*/
@Override
public List<CrmContractProductVo> queryList(CrmContractProductBo bo) {
LambdaQueryWrapper<CrmContractProduct> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<CrmContractProduct> buildQueryWrapper(CrmContractProductBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<CrmContractProduct> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getContractId() != null, CrmContractProduct::getContractId, bo.getContractId());
lqw.like(StringUtils.isNotBlank(bo.getProductName()), CrmContractProduct::getProductName, bo.getProductName());
lqw.eq(bo.getSpecMin() != null, CrmContractProduct::getSpecMin, bo.getSpecMin());
lqw.eq(bo.getSpecMax() != null, CrmContractProduct::getSpecMax, bo.getSpecMax());
lqw.eq(StringUtils.isNotBlank(bo.getMaterial()), CrmContractProduct::getMaterial, bo.getMaterial());
lqw.eq(bo.getQuantity() != null, CrmContractProduct::getQuantity, bo.getQuantity());
lqw.eq(bo.getTaxInclusiveUnitPrice() != null, CrmContractProduct::getTaxInclusiveUnitPrice, bo.getTaxInclusiveUnitPrice());
lqw.eq(bo.getExTaxUnitPrice() != null, CrmContractProduct::getExTaxUnitPrice, bo.getExTaxUnitPrice());
lqw.eq(bo.getTaxInclusiveAmount() != null, CrmContractProduct::getTaxInclusiveAmount, bo.getTaxInclusiveAmount());
return lqw;
}
/**
* 新增合同产品明细
*/
@Override
public Boolean insertByBo(CrmContractProductBo bo) {
CrmContractProduct add = BeanUtil.toBean(bo, CrmContractProduct.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setContractProductId(add.getContractProductId());
}
return flag;
}
/**
* 修改合同产品明细
*/
@Override
public Boolean updateByBo(CrmContractProductBo bo) {
CrmContractProduct update = BeanUtil.toBean(bo, CrmContractProduct.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(CrmContractProduct entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除合同产品明细
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -0,0 +1,131 @@
package com.klp.crm.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.klp.crm.domain.bo.CrmContractBo;
import com.klp.crm.domain.vo.CrmContractVo;
import com.klp.crm.domain.CrmContract;
import com.klp.crm.mapper.CrmContractMapper;
import com.klp.crm.service.ICrmContractService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 合同信息Service业务层处理
*
* @author klp
* @date 2026-03-30
*/
@RequiredArgsConstructor
@Service
public class CrmContractServiceImpl implements ICrmContractService {
private final CrmContractMapper baseMapper;
/**
* 查询合同信息
*/
@Override
public CrmContractVo queryById(Long contractId){
return baseMapper.selectVoById(contractId);
}
/**
* 查询合同信息列表
*/
@Override
public TableDataInfo<CrmContractVo> queryPageList(CrmContractBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<CrmContract> lqw = buildQueryWrapper(bo);
Page<CrmContractVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询合同信息列表
*/
@Override
public List<CrmContractVo> queryList(CrmContractBo bo) {
LambdaQueryWrapper<CrmContract> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<CrmContract> buildQueryWrapper(CrmContractBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<CrmContract> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getContractName()), CrmContract::getContractName, bo.getContractName());
lqw.eq(StringUtils.isNotBlank(bo.getContractNo()), CrmContract::getContractNo, bo.getContractNo());
lqw.eq(StringUtils.isNotBlank(bo.getSupplier()), CrmContract::getSupplier, bo.getSupplier());
lqw.eq(StringUtils.isNotBlank(bo.getCustomer()), CrmContract::getCustomer, bo.getCustomer());
lqw.eq(bo.getSignTime() != null, CrmContract::getSignTime, bo.getSignTime());
lqw.eq(bo.getDeliveryDate() != null, CrmContract::getDeliveryDate, bo.getDeliveryDate());
lqw.eq(StringUtils.isNotBlank(bo.getSignLocation()), CrmContract::getSignLocation, bo.getSignLocation());
lqw.eq(StringUtils.isNotBlank(bo.getProductContent()), CrmContract::getProductContent, bo.getProductContent());
lqw.eq(StringUtils.isNotBlank(bo.getContractContent()), CrmContract::getContractContent, bo.getContractContent());
lqw.eq(StringUtils.isNotBlank(bo.getSupplierAddress()), CrmContract::getSupplierAddress, bo.getSupplierAddress());
lqw.eq(StringUtils.isNotBlank(bo.getSupplierPhone()), CrmContract::getSupplierPhone, bo.getSupplierPhone());
lqw.eq(StringUtils.isNotBlank(bo.getSupplierBank()), CrmContract::getSupplierBank, bo.getSupplierBank());
lqw.eq(StringUtils.isNotBlank(bo.getSupplierAccount()), CrmContract::getSupplierAccount, bo.getSupplierAccount());
lqw.eq(StringUtils.isNotBlank(bo.getSupplierTaxNo()), CrmContract::getSupplierTaxNo, bo.getSupplierTaxNo());
lqw.eq(StringUtils.isNotBlank(bo.getCustomerAddress()), CrmContract::getCustomerAddress, bo.getCustomerAddress());
lqw.eq(StringUtils.isNotBlank(bo.getCustomerPhone()), CrmContract::getCustomerPhone, bo.getCustomerPhone());
lqw.eq(StringUtils.isNotBlank(bo.getCustomerBank()), CrmContract::getCustomerBank, bo.getCustomerBank());
lqw.eq(StringUtils.isNotBlank(bo.getCustomerAccount()), CrmContract::getCustomerAccount, bo.getCustomerAccount());
lqw.eq(StringUtils.isNotBlank(bo.getCustomerTaxNo()), CrmContract::getCustomerTaxNo, bo.getCustomerTaxNo());
lqw.eq(StringUtils.isNotBlank(bo.getTechAnnex()), CrmContract::getTechAnnex, bo.getTechAnnex());
lqw.eq(StringUtils.isNotBlank(bo.getBusinessAnnex()), CrmContract::getBusinessAnnex, bo.getBusinessAnnex());
lqw.eq(StringUtils.isNotBlank(bo.getProductionSchedule()), CrmContract::getProductionSchedule, bo.getProductionSchedule());
lqw.eq(bo.getStatus() != null, CrmContract::getStatus, bo.getStatus());
return lqw;
}
/**
* 新增合同信息
*/
@Override
public Boolean insertByBo(CrmContractBo bo) {
CrmContract add = BeanUtil.toBean(bo, CrmContract.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setContractId(add.getContractId());
}
return flag;
}
/**
* 修改合同信息
*/
@Override
public Boolean updateByBo(CrmContractBo bo) {
CrmContract update = BeanUtil.toBean(bo, CrmContract.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(CrmContract entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除合同信息
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -63,12 +63,13 @@ public class CrmCustomerServiceImpl implements ICrmCustomerService {
LambdaQueryWrapper<CrmCustomer> lqw = Wrappers.lambdaQuery();
lqw.eq(StringUtils.isNotBlank(bo.getCustomerCode()), CrmCustomer::getCustomerCode, bo.getCustomerCode());
lqw.like(StringUtils.isNotBlank(bo.getCompanyName()), CrmCustomer::getCompanyName, bo.getCompanyName());
lqw.eq(StringUtils.isNotBlank(bo.getContactPerson()), CrmCustomer::getContactPerson, bo.getContactPerson());
lqw.eq(StringUtils.isNotBlank(bo.getContactWay()), CrmCustomer::getContactWay, bo.getContactWay());
lqw.like(StringUtils.isNotBlank(bo.getContactPerson()), CrmCustomer::getContactPerson, bo.getContactPerson());
lqw.like(StringUtils.isNotBlank(bo.getContactWay()), CrmCustomer::getContactWay, bo.getContactWay());
lqw.eq(StringUtils.isNotBlank(bo.getIndustry()), CrmCustomer::getIndustry, bo.getIndustry());
lqw.eq(StringUtils.isNotBlank(bo.getCustomerLevel()), CrmCustomer::getCustomerLevel, bo.getCustomerLevel());
lqw.eq(StringUtils.isNotBlank(bo.getAddress()), CrmCustomer::getAddress, bo.getAddress());
lqw.eq(StringUtils.isNotBlank(bo.getBankInfo()), CrmCustomer::getBankInfo, bo.getBankInfo());
lqw.like(StringUtils.isNotBlank(bo.getAddress()), CrmCustomer::getAddress, bo.getAddress());
lqw.like(StringUtils.isNotBlank(bo.getBankInfo()), CrmCustomer::getBankInfo, bo.getBankInfo());
lqw.like(StringUtils.isNotBlank(bo.getTaxNumber()), CrmCustomer::getTaxNumber, bo.getTaxNumber());
return lqw;
}

View File

@@ -7,17 +7,33 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.utils.StringUtils;
import com.klp.crm.domain.CrmSalesObjection;
import com.klp.domain.WmsReceivable;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.klp.crm.domain.bo.CrmOrderItemBo;
import com.klp.crm.domain.vo.CrmOrderItemVo;
import com.klp.crm.domain.vo.CrmContractOrderFinanceVo;
import com.klp.crm.domain.vo.CrmSalesObjectionVo;
import com.klp.domain.vo.WmsReceivableVo;
import com.klp.domain.vo.WmsMaterialCoilVo;
import com.klp.domain.bo.WmsMaterialCoilBo;
import com.klp.crm.domain.CrmOrderItem;
import com.klp.crm.domain.CrmOrder;
import com.klp.domain.WmsDeliveryWaybill;
import com.klp.domain.WmsDeliveryWaybillDetail;
import com.klp.crm.mapper.CrmOrderItemMapper;
import com.klp.crm.mapper.CrmOrderMapper;
import com.klp.crm.mapper.CrmSalesObjectionMapper;
import com.klp.crm.service.ICrmOrderItemService;
import com.klp.mapper.WmsReceivableMapper;
import com.klp.mapper.WmsDeliveryWaybillMapper;
import com.klp.mapper.WmsDeliveryWaybillDetailMapper;
import com.klp.service.IWmsMaterialCoilService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.*;
import java.util.stream.Collectors;
/**
* 正式订单明细Service业务层处理
@@ -30,12 +46,18 @@ import java.util.Collection;
public class CrmOrderItemServiceImpl implements ICrmOrderItemService {
private final CrmOrderItemMapper baseMapper;
private final CrmOrderMapper crmOrderMapper;
private final CrmSalesObjectionMapper crmSalesObjectionMapper;
private final WmsReceivableMapper wmsReceivableMapper;
private final WmsDeliveryWaybillMapper wmsDeliveryWaybillMapper;
private final WmsDeliveryWaybillDetailMapper wmsDeliveryWaybillDetailMapper;
private final IWmsMaterialCoilService iWmsMaterialCoilService;
/**
* 查询正式订单明细
*/
@Override
public CrmOrderItemVo queryById(String itemId){
public CrmOrderItemVo queryById(String itemId) {
return baseMapper.selectVoById(itemId);
}
@@ -61,7 +83,7 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService {
private LambdaQueryWrapper<CrmOrderItem> buildQueryWrapper(CrmOrderItemBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<CrmOrderItem> lqw = Wrappers.lambdaQuery();
lqw.eq(StringUtils.isNotBlank(bo.getOrderId()), CrmOrderItem::getOrderId, bo.getOrderId());
lqw.eq(bo.getOrderId() != null, CrmOrderItem::getOrderId, bo.getOrderId());
lqw.eq(StringUtils.isNotBlank(bo.getProductType()), CrmOrderItem::getProductType, bo.getProductType());
lqw.eq(StringUtils.isNotBlank(bo.getRawMaterialSpec()), CrmOrderItem::getRawMaterialSpec, bo.getRawMaterialSpec());
lqw.eq(bo.getProductNum() != null, CrmOrderItem::getProductNum, bo.getProductNum());
@@ -71,6 +93,8 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService {
lqw.eq(StringUtils.isNotBlank(bo.getMaterial()), CrmOrderItem::getMaterial, bo.getMaterial());
lqw.eq(StringUtils.isNotBlank(bo.getGrade()), CrmOrderItem::getGrade, bo.getGrade());
lqw.eq(bo.getWeight() != null, CrmOrderItem::getWeight, bo.getWeight());
lqw.eq(bo.getWidthTolerance() != null, CrmOrderItem::getWidthTolerance, bo.getWidthTolerance());
lqw.eq(bo.getThicknessTolerance() != null, CrmOrderItem::getThicknessTolerance, bo.getThicknessTolerance());
lqw.eq(bo.getContractPrice() != null, CrmOrderItem::getContractPrice, bo.getContractPrice());
lqw.eq(StringUtils.isNotBlank(bo.getCustomizer()), CrmOrderItem::getCustomizer, bo.getCustomizer());
lqw.eq(StringUtils.isNotBlank(bo.getShipper()), CrmOrderItem::getShipper, bo.getShipper());
@@ -106,7 +130,7 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService {
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(CrmOrderItem entity){
private void validEntityBeforeSave(CrmOrderItem entity) {
//TODO 做一些数据校验,如唯一约束
}
@@ -115,9 +139,114 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService {
*/
@Override
public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
if(isValid){
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}
@Override
public CrmContractOrderFinanceVo queryFinanceAndObjectionByContractId(Long contractId) {
CrmContractOrderFinanceVo result = new CrmContractOrderFinanceVo();
LambdaQueryWrapper<CrmOrder> orderWrapper = new LambdaQueryWrapper<>();
orderWrapper.eq(CrmOrder::getContractId, contractId);
List<CrmOrder> orders = crmOrderMapper.selectList(orderWrapper);
if (orders == null || orders.isEmpty()) {
return result;
}
List<Long> orderIds = orders.stream()
.map(CrmOrder::getOrderId)
.collect(Collectors.toList());
LambdaQueryWrapper<CrmSalesObjection> objectionWrapper = new LambdaQueryWrapper<>();
objectionWrapper.in(CrmSalesObjection::getOrderId, orderIds);
List<CrmSalesObjectionVo> objectionList = crmSalesObjectionMapper.selectVoList(objectionWrapper);
result.setObjectionList(objectionList);
LambdaQueryWrapper<com.klp.domain.WmsReceivable> receivableWrapper = new LambdaQueryWrapper<>();
receivableWrapper.in(WmsReceivable::getOrderId, orderIds);
List<WmsReceivableVo> receivableList = wmsReceivableMapper.selectVoList(receivableWrapper);
result.setReceivableList(receivableList);
return result;
}
@Override
public List<WmsMaterialCoilVo> queryCoilsByOrderId(Long orderId) {
LambdaQueryWrapper<WmsDeliveryWaybill> waybillWrapper = new LambdaQueryWrapper<>();
waybillWrapper.eq(WmsDeliveryWaybill::getOrderId, orderId);
List<WmsDeliveryWaybill> waybills = wmsDeliveryWaybillMapper.selectList(waybillWrapper);
if (waybills == null || waybills.isEmpty()) {
return Collections.emptyList();
}
List<Long> waybillIds = waybills.stream()
.map(WmsDeliveryWaybill::getWaybillId)
.collect(Collectors.toList());
LambdaQueryWrapper<WmsDeliveryWaybillDetail> detailWrapper = new LambdaQueryWrapper<>();
detailWrapper.in(WmsDeliveryWaybillDetail::getWaybillId, waybillIds);
List<WmsDeliveryWaybillDetail> details = wmsDeliveryWaybillDetailMapper.selectList(detailWrapper);
if (details == null || details.isEmpty()) {
return Collections.emptyList();
}
String coilIds = details.stream()
.map(WmsDeliveryWaybillDetail::getCoilId)
.map(String::valueOf)
.collect(Collectors.joining(","));
WmsMaterialCoilBo coilBo = new WmsMaterialCoilBo();
coilBo.setCoilIds(coilIds);
return iWmsMaterialCoilService.queryList(coilBo);
}
@Override
public List<WmsMaterialCoilVo> queryCoilsByContractId(Long contractId) {
LambdaQueryWrapper<CrmOrder> orderWrapper = new LambdaQueryWrapper<>();
orderWrapper.eq(CrmOrder::getContractId, contractId);
List<CrmOrder> orders = crmOrderMapper.selectList(orderWrapper);
if (orders == null || orders.isEmpty()) {
return Collections.emptyList();
}
List<Long> orderIds = orders.stream()
.map(CrmOrder::getOrderId)
.collect(Collectors.toList());
LambdaQueryWrapper<WmsDeliveryWaybill> waybillWrapper = new LambdaQueryWrapper<>();
waybillWrapper.in(WmsDeliveryWaybill::getOrderId, orderIds);
List<WmsDeliveryWaybill> waybills = wmsDeliveryWaybillMapper.selectList(waybillWrapper);
if (waybills == null || waybills.isEmpty()) {
return Collections.emptyList();
}
List<Long> waybillIds = waybills.stream()
.map(WmsDeliveryWaybill::getWaybillId)
.collect(Collectors.toList());
LambdaQueryWrapper<WmsDeliveryWaybillDetail> detailWrapper = new LambdaQueryWrapper<>();
detailWrapper.in(WmsDeliveryWaybillDetail::getWaybillId, waybillIds);
List<WmsDeliveryWaybillDetail> details = wmsDeliveryWaybillDetailMapper.selectList(detailWrapper);
if (details == null || details.isEmpty()) {
return Collections.emptyList();
}
String coilIds = details.stream()
.map(WmsDeliveryWaybillDetail::getCoilId)
.map(String::valueOf)
.collect(Collectors.joining(","));
WmsMaterialCoilBo coilBo = new WmsMaterialCoilBo();
coilBo.setCoilIds(coilIds);
return iWmsMaterialCoilService.queryList(coilBo);
}
}

View File

@@ -95,6 +95,8 @@ public class CrmOrderServiceImpl implements ICrmOrderService {
qw.eq(bo.getFinanceStatus() != null, "co.finance_status", bo.getFinanceStatus());
qw.eq(bo.getUnpaidAmount() != null, "co.unpaid_amount", bo.getUnpaidAmount());
qw.like(StringUtils.isNotBlank(bo.getContractCode()), "co.contract_code", bo.getContractCode());
qw.eq(bo.getContractId() != null, "co.contract_id", bo.getContractId());
qw.like(StringUtils.isNotBlank(bo.getAnnexFiles()), "co.annex_files", bo.getAnnexFiles());
//逻辑删除
qw.eq("co.del_flag", 0);
//根据orderType排序预订单是0 正是订单是1 0排在前面 1排在后面 升序
@@ -128,6 +130,8 @@ public class CrmOrderServiceImpl implements ICrmOrderService {
lqw.eq(bo.getFinanceStatus() != null, CrmOrder::getFinanceStatus, bo.getFinanceStatus());
lqw.eq(bo.getUnpaidAmount() != null, CrmOrder::getUnpaidAmount, bo.getUnpaidAmount());
lqw.like(StringUtils.isNotBlank(bo.getContractCode()), CrmOrder::getContractCode, bo.getContractCode());
lqw.eq(bo.getContractId() != null, CrmOrder::getContractId, bo.getContractId());
lqw.like(StringUtils.isNotBlank(bo.getAnnexFiles()), CrmOrder::getAnnexFiles, bo.getAnnexFiles());
return lqw;
}

View File

@@ -59,7 +59,7 @@ public class CrmSalesReportServiceImpl implements ICrmSalesReportService {
List<CrmSalesReportVo.OrderDetail> orderDetails = baseMapper.selectOrderDetailList(bo);
if (StringUtils.isNotNull(orderDetails) && !orderDetails.isEmpty()) {
// 提取所有订单ID
List<String> orderIds = orderDetails.stream()
List<Long> orderIds = orderDetails.stream()
.map(CrmSalesReportVo.OrderDetail::getOrderId)
.filter(StringUtils::isNotNull)
.distinct()
@@ -70,7 +70,7 @@ public class CrmSalesReportServiceImpl implements ICrmSalesReportService {
List<CrmOrderItem> orderItems = crmOrderItemMapper.selectOrderItemsByOrderIds(orderIds);
// 将明细按订单ID分组
Map<String, List<CrmOrderItem>> orderItemMap = orderItems.stream()
Map<Long, List<CrmOrderItem>> orderItemMap = orderItems.stream()
.collect(Collectors.groupingBy(CrmOrderItem::getOrderId));
// 为每个订单设置对应的明细列表

View File

@@ -0,0 +1,41 @@
<?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.klp.crm.mapper.CrmContractMapper">
<resultMap type="com.klp.crm.domain.CrmContract" id="CrmContractResult">
<result property="contractId" column="contract_id"/>
<result property="contractName" column="contract_name"/>
<result property="contractNo" column="contract_no"/>
<result property="supplier" column="supplier"/>
<result property="customer" column="customer"/>
<result property="deliveryDate" column="delivery_date"/>
<result property="signTime" column="sign_time"/>
<result property="signLocation" column="sign_location"/>
<result property="productContent" column="product_content"/>
<result property="contractContent" column="contract_content"/>
<result property="supplierAddress" column="supplier_address"/>
<result property="supplierPhone" column="supplier_phone"/>
<result property="supplierBank" column="supplier_bank"/>
<result property="supplierAccount" column="supplier_account"/>
<result property="supplierTaxNo" column="supplier_tax_no"/>
<result property="customerAddress" column="customer_address"/>
<result property="customerPhone" column="customer_phone"/>
<result property="customerBank" column="customer_bank"/>
<result property="customerAccount" column="customer_account"/>
<result property="customerTaxNo" column="customer_tax_no"/>
<result property="techAnnex" column="tech_annex"/>
<result property="businessAnnex" column="business_annex"/>
<result property="productionSchedule" column="production_schedule"/>
<result property="status" column="status"/>
<result property="remark" column="remark"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,27 @@
<?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.klp.crm.mapper.CrmContractProductMapper">
<resultMap type="com.klp.crm.domain.CrmContractProduct" id="CrmContractProductResult">
<result property="contractProductId" column="contract_product_id"/>
<result property="contractId" column="contract_id"/>
<result property="productName" column="product_name"/>
<result property="specMin" column="spec_min"/>
<result property="specMax" column="spec_max"/>
<result property="material" column="material"/>
<result property="quantity" column="quantity"/>
<result property="taxInclusiveUnitPrice" column="tax_inclusive_unit_price"/>
<result property="exTaxUnitPrice" column="ex_tax_unit_price"/>
<result property="taxInclusiveAmount" column="tax_inclusive_amount"/>
<result property="delFlag" column="del_flag"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="remark" column="remark"/>
</resultMap>
</mapper>

View File

@@ -14,6 +14,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="customerLevel" column="customer_level"/>
<result property="address" column="address"/>
<result property="bankInfo" column="bank_info"/>
<result property="taxNumber" column="tax_number"/>
<result property="remark" column="remark"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>

View File

@@ -17,6 +17,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="material" column="material"/>
<result property="grade" column="grade"/>
<result property="weight" column="weight"/>
<result property="widthTolerance" column="width_tolerance"/>
<result property="thicknessTolerance" column="thickness_tolerance"/>
<result property="contractPrice" column="contract_price"/>
<result property="customizer" column="customizer"/>
<result property="shipper" column="shipper"/>
@@ -42,6 +44,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
material,
grade,
weight,
width_tolerance,
thickness_tolerance,
contract_price,
customizer,
shipper,

View File

@@ -20,6 +20,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="unpaidAmount" column="unpaid_amount"/>
<result property="remark" column="remark"/>
<result property="contractCode" column="contract_code"/>
<result property="contractId" column="contract_id"/>
<result property="annexFiles" column="annex_files"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
@@ -43,6 +45,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
co.unpaid_amount AS unpaidAmount,
co.remark,
co.contract_code AS contractCode,
co.contract_id AS contractId,
co.annex_files AS annexFiles,
co.create_by AS createBy,
co.create_time AS createTime,
co.update_by AS updateBy,
@@ -75,6 +79,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
co.unpaid_amount AS unpaidAmount,
co.remark,
co.contract_code AS contractCode,
co.contract_id AS contractId,
co.annex_files AS annexFiles,
co.create_by AS createBy,
co.create_time AS createTime,
co.update_by AS updateBy,

View File

@@ -12,6 +12,7 @@ import com.klp.pocket.acid.domain.vo.AcidOeeIdealCycleVo;
import com.klp.pocket.acid.domain.vo.AcidOeeLoss7Vo;
import com.klp.pocket.acid.domain.vo.Klptcm1ProStoppageVo;
import com.klp.pocket.acid.service.IAcidOeeService;
import com.klp.pocket.galvanize1.service.IGalvanizeOeeService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
@@ -61,6 +62,7 @@ import java.util.stream.Collectors;
public class OeeReportController extends BaseController {
private final IAcidOeeService acidOeeService;
private final IGalvanizeOeeService galvanizeOeeService;
private final StringRedisTemplate stringRedisTemplate;
private final OeeReportJobService oeeReportJobService;
private final OeeWordAiAnalysisService oeeWordAiAnalysisService;
@@ -76,26 +78,20 @@ public class OeeReportController extends BaseController {
*
* 路由GET /oee/line/acid/summary
* 说明:
* - 不接受 start/end 参数固定返回“当前月份1号~今天)”的当月预计算结果
* - 优先从 Redis 当月缓存读取;若缓存缺失则实时计算一次当前月。
* - 支持 startDate/endDate 参数yyyy-MM-dd
* - 若不传则默认查询当前月份1号~今天);
* - 仅实时计算,不走缓存。
*/
@GetMapping("/acid/summary")
public R<List<AcidOeeDailySummaryVo>> getAcidSummary() {
String yyyyMM = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
String summaryKey = String.format("oee:report:month:summary:%s:SY", yyyyMM);
// 1. 优先从 Redis 读取当月预计算结果
String json = stringRedisTemplate.opsForValue().get(summaryKey);
if (StringUtils.isNotBlank(json)) {
List<AcidOeeDailySummaryVo> cached =
JSON.parseArray(json, AcidOeeDailySummaryVo.class);
return R.ok(cached);
}
// 2. 缓存缺失时,回退为实时计算当前月
String[] range = resolveDateRange(null, null);
List<AcidOeeDailySummaryVo> dailyList =
acidOeeService.getDailySummary(range[0], range[1]);
public R<List<AcidOeeDailySummaryVo>> getAcidSummary(
@RequestParam(required = false) String startDate,
@RequestParam(required = false) String endDate,
@RequestParam(required = false, defaultValue = "acid") String lineType
) {
String[] range = resolveDateRange(startDate, endDate);
List<AcidOeeDailySummaryVo> dailyList = isGalvanize(lineType)
? galvanizeOeeService.getDailySummary(range[0], range[1])
: acidOeeService.getDailySummary(range[0], range[1]);
return R.ok(dailyList);
}
@@ -109,21 +105,15 @@ public class OeeReportController extends BaseController {
*/
@GetMapping("/acid/loss7")
public R<List<AcidOeeLoss7Vo>> getAcidLoss7(
@RequestParam(required = false, defaultValue = "50") Integer topN
@RequestParam(required = false, defaultValue = "50") Integer topN,
@RequestParam(required = false) String startDate,
@RequestParam(required = false) String endDate,
@RequestParam(required = false, defaultValue = "acid") String lineType
) {
String yyyyMM = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
String loss7Key = String.format("oee:report:month:loss7:%s:SY", yyyyMM);
// 1. 优先从 Redis 读取当月 7 大损失预计算结果
String json = stringRedisTemplate.opsForValue().get(loss7Key);
List<AcidOeeLoss7Vo> lossList;
if (StringUtils.isNotBlank(json)) {
lossList = JSON.parseArray(json, AcidOeeLoss7Vo.class);
} else {
// 2. 缓存缺失时,回退为实时计算当前月
String[] range = resolveDateRange(null, null);
lossList = acidOeeService.getLoss7Summary(range[0], range[1]);
}
String[] range = resolveDateRange(startDate, endDate);
List<AcidOeeLoss7Vo> lossList = isGalvanize(lineType)
? galvanizeOeeService.getLoss7Summary(range[0], range[1])
: acidOeeService.getLoss7Summary(range[0], range[1]);
if (topN != null && topN > 0 && lossList.size() > topN) {
lossList = new ArrayList<>(lossList.subList(0, topN));
@@ -147,14 +137,16 @@ public class OeeReportController extends BaseController {
@RequestParam(required = false) String stopType,
@RequestParam(required = false) String keyword,
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
@RequestParam(required = false, defaultValue = "10") Integer pageSize
@RequestParam(required = false, defaultValue = "10") Integer pageSize,
@RequestParam(required = false, defaultValue = "acid") String lineType
) {
// 事件明细底层按「日期」查询,这里从时间字符串中截取日期部分
String startDate = extractDateOrDefault(startTime, true);
String endDate = extractDateOrDefault(endTime, false);
List<Klptcm1ProStoppageVo> events =
acidOeeService.getStoppageEvents(startDate, endDate);
List<Klptcm1ProStoppageVo> events = isGalvanize(lineType)
? galvanizeOeeService.getStoppageEvents(startDate, endDate)
: acidOeeService.getStoppageEvents(startDate, endDate);
// 业务筛选stopType、关键字目前对 stopType / remark 做 contains 匹配)
List<Klptcm1ProStoppageVo> filtered = events.stream()
@@ -200,9 +192,12 @@ public class OeeReportController extends BaseController {
@GetMapping("/acid/idealCycle")
public R<AcidOeeIdealCycleVo> getAcidIdealCycle(
@RequestParam String startDate,
@RequestParam String endDate
@RequestParam String endDate,
@RequestParam(required = false, defaultValue = "acid") String lineType
) {
AcidOeeIdealCycleVo data = acidOeeService.getIdealCycle(startDate, endDate);
AcidOeeIdealCycleVo data = isGalvanize(lineType)
? galvanizeOeeService.getIdealCycle(startDate, endDate)
: acidOeeService.getIdealCycle(startDate, endDate);
return R.ok(data);
}
@@ -423,6 +418,10 @@ public class OeeReportController extends BaseController {
/**
* 若未显式传入日期范围,则默认当前月 [1号, 今天]。
*/
private boolean isGalvanize(String lineType) {
return "galvanize1".equalsIgnoreCase(lineType) || "galvanize".equalsIgnoreCase(lineType) || "dx".equalsIgnoreCase(lineType);
}
private String[] resolveDateRange(String startDate, String endDate) {
if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
return new String[]{startDate, endDate};

View File

@@ -1,137 +0,0 @@
package com.klp.da.task;
import com.alibaba.fastjson2.JSON;
import com.klp.pocket.acid.domain.vo.AcidOeeDailySummaryVo;
import com.klp.pocket.acid.service.IAcidOeeService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 酸轧线 OEE 当月预计算任务
*
* 需求对应 docs/oee-report-design.md 第 12.2 节:
* - 项目启动完成后即计算当月 OEE 聚合结果并写入 Redis
* - 每天凌晨 04:00 重新计算当月数据并覆盖缓存。
*
* 当前仅实现酸轧线SY的当月日汇总预计算
* key 约定:
* - 汇总结果oee:report:month:summary:{yyyyMM}:SY
* - 元信息: oee:report:month:meta:{yyyyMM}:SY
*/
@Slf4j
@RequiredArgsConstructor
@Component
public class AcidOeeMonthTask {
/** Redis 缓存 key 模板:当月 OEE 汇总(酸轧线) */
private static final String SUMMARY_KEY_PATTERN = "oee:report:month:summary:%s:SY";
/** Redis 缓存 key 模板:当月元信息(酸轧线) */
private static final String META_KEY_PATTERN = "oee:report:month:meta:%s:SY";
private static final DateTimeFormatter YEAR_MONTH_FMT = DateTimeFormatter.ofPattern("yyyyMM");
private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ISO_DATE;
private static final DateTimeFormatter DATE_TIME_FMT = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
private final IAcidOeeService acidOeeService;
private final StringRedisTemplate stringRedisTemplate;
/**
* 项目启动完成后立即计算一次当月酸轧 OEE 汇总并写入 Redis。
*/
@PostConstruct
public void init() {
try {
computeCurrentMonth("startup");
} catch (Exception e) {
log.error("[AcidOeeMonthTask] startup compute failed", e);
}
}
/**
* 每天凌晨 04:00 重新计算当月酸轧 OEE 汇总并覆盖 Redis 缓存。
*/
@Scheduled(cron = "0 0 4 * * ?")
public void scheduleDaily() {
try {
computeCurrentMonth("schedule-04");
} catch (Exception e) {
log.error("[AcidOeeMonthTask] 4am compute failed", e);
}
}
/**
* 计算当前月份从当月1号到今天的酸轧 OEE 日汇总,并写入 Redis。
*
* @param trigger 触发来源标记startup / schedule-04 等)
*/
private void computeCurrentMonth(String trigger) {
long startNs = System.nanoTime();
LocalDate now = LocalDate.now();
String yyyyMM = now.format(YEAR_MONTH_FMT);
LocalDate startDate = now.withDayOfMonth(1);
LocalDate endDate = now;
String startStr = startDate.format(DATE_FMT);
String endStr = endDate.format(DATE_FMT);
log.info("[AcidOeeMonthTask] trigger={}, computing acid OEE month summary for {} ({} ~ {})",
trigger, yyyyMM, startStr, endStr);
// 1. 调用 pocket 的 AcidOeeService 获取当月日汇总
List<AcidOeeDailySummaryVo> dailySummaryList = acidOeeService.getDailySummary(startStr, endStr);
// 2. 写入 Redissummary
String summaryKey = String.format(SUMMARY_KEY_PATTERN, yyyyMM);
String summaryJson = JSON.toJSONString(dailySummaryList);
stringRedisTemplate.opsForValue().set(summaryKey, summaryJson, 1, TimeUnit.DAYS);
long durationMs = (System.nanoTime() - startNs) / 1_000_000L;
// 3. 写入 Redismeta
Meta meta = new Meta();
meta.setComputedAt(LocalDateTime.now().format(DATE_TIME_FMT));
meta.setDurationMs(durationMs);
meta.setStartDate(startStr);
meta.setEndDate(endStr);
meta.setTrigger(trigger);
String metaKey = String.format(META_KEY_PATTERN, yyyyMM);
stringRedisTemplate.opsForValue().set(metaKey, JSON.toJSONString(meta), 1, TimeUnit.DAYS);
log.info("[AcidOeeMonthTask] compute finish for {} dailySize={}, durationMs={}ms, summaryKey={}",
yyyyMM, dailySummaryList.size(), durationMs, summaryKey);
}
/**
* 当月预计算元信息
*/
@Data
private static class Meta {
/** 计算完成时间ISO-8601 字符串) */
private String computedAt;
/** 计算耗时(毫秒) */
private long durationMs;
/** 统计起始日期yyyy-MM-dd */
private String startDate;
/** 统计结束日期yyyy-MM-dd */
private String endDate;
/** 触发来源startup / schedule-04 等) */
private String trigger;
}
}

View File

@@ -10,7 +10,7 @@ import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import org.flywaydb.core.internal.util.StringUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.klp.common.annotation.RepeatSubmit;

View File

@@ -71,8 +71,8 @@ public class EqpAuxiliaryMaterialController extends BaseController {
@Log(title = "辅料", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody EqpAuxiliaryMaterialBo bo) {
return toAjax(iEqpAuxiliaryMaterialService.insertByBo(bo));
public R<Long> add(@Validated(AddGroup.class) @RequestBody EqpAuxiliaryMaterialBo bo) {
return R.ok(iEqpAuxiliaryMaterialService.insertByBo(bo));
}
/**

View File

@@ -71,8 +71,8 @@ public class EqpSparePartController extends BaseController {
@Log(title = "备品备件", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody EqpSparePartBo bo) {
return toAjax(iEqpSparePartService.insertByBo(bo));
public R<Long> add(@Validated(AddGroup.class) @RequestBody EqpSparePartBo bo) {
return R.ok(iEqpSparePartService.insertByBo(bo));
}
/**

View File

@@ -44,6 +44,10 @@ public class EqpAuxiliaryMaterial extends BaseEntity {
* 关联设备ID可为空通用辅料
*/
private Long equipmentId;
/**
* 机组1#机组、2#机组、公用机组等)
*/
private String unitTeam;
/**
* 当前库存数量
*/

View File

@@ -44,6 +44,10 @@ public class EqpSparePart extends BaseEntity {
* 关联设备ID可为空通用备件
*/
private Long equipmentId;
/**
* 机组1#机组、2#机组、公用机组等)
*/
private String unitTeam;
/**
* 当前库存数量
*/

View File

@@ -47,6 +47,11 @@ public class EqpAuxiliaryMaterialBo extends BaseEntity {
*/
private Long equipmentId;
/**
* 机组1#机组、2#机组、公用机组等)
*/
private String unitTeam;
/**
* 当前库存数量
*/

View File

@@ -47,6 +47,11 @@ public class EqpSparePartBo extends BaseEntity {
*/
private Long equipmentId;
/**
* 机组1#机组、2#机组、公用机组等)
*/
private String unitTeam;
/**
* 当前库存数量
*/

View File

@@ -56,6 +56,12 @@ public class EqpAuxiliaryMaterialVo {
@ExcelDictFormat(readConverterExp = "可=为空,通用辅料")
private Long equipmentId;
/**
* 机组1#机组、2#机组、公用机组等)
*/
@ExcelProperty(value = "机组")
private String unitTeam;
/**
* 当前库存数量
*/

View File

@@ -56,6 +56,12 @@ public class EqpSparePartVo {
@ExcelDictFormat(readConverterExp = "可=为空,通用备件")
private Long equipmentId;
/**
* 机组1#机组、2#机组、公用机组等)
*/
@ExcelProperty(value = "机组")
private String unitTeam;
/**
* 当前库存数量
*/

View File

@@ -35,7 +35,7 @@ public interface IEqpAuxiliaryMaterialService {
/**
* 新增辅料
*/
Boolean insertByBo(EqpAuxiliaryMaterialBo bo);
Long insertByBo(EqpAuxiliaryMaterialBo bo);
/**
* 修改辅料

View File

@@ -35,7 +35,7 @@ public interface IEqpSparePartService {
/**
* 新增备品备件
*/
Boolean insertByBo(EqpSparePartBo bo);
Long insertByBo(EqpSparePartBo bo);
/**
* 修改备品备件

View File

@@ -66,6 +66,7 @@ public class EqpAuxiliaryMaterialServiceImpl implements IEqpAuxiliaryMaterialSer
lqw.eq(StringUtils.isNotBlank(bo.getAuxiliaryModel()), EqpAuxiliaryMaterial::getAuxiliaryModel, bo.getAuxiliaryModel());
lqw.eq(StringUtils.isNotBlank(bo.getUnit()), EqpAuxiliaryMaterial::getUnit, bo.getUnit());
lqw.eq(bo.getEquipmentId() != null, EqpAuxiliaryMaterial::getEquipmentId, bo.getEquipmentId());
lqw.like(StringUtils.isNotBlank(bo.getUnitTeam()), EqpAuxiliaryMaterial::getUnitTeam, bo.getUnitTeam());
lqw.eq(bo.getQuantity() != null, EqpAuxiliaryMaterial::getQuantity, bo.getQuantity());
return lqw;
}
@@ -74,14 +75,14 @@ public class EqpAuxiliaryMaterialServiceImpl implements IEqpAuxiliaryMaterialSer
* 新增辅料
*/
@Override
public Boolean insertByBo(EqpAuxiliaryMaterialBo bo) {
public Long insertByBo(EqpAuxiliaryMaterialBo bo) {
EqpAuxiliaryMaterial add = BeanUtil.toBean(bo, EqpAuxiliaryMaterial.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setAuxiliaryId(add.getAuxiliaryId());
}
return flag;
return add.getAuxiliaryId();
}
/**

View File

@@ -58,6 +58,7 @@ public class EqpSparePartServiceImpl implements IEqpSparePartService {
qw.eq(StringUtils.isNotBlank(bo.getModel()), "sp.model", bo.getModel());
qw.eq(StringUtils.isNotBlank(bo.getUnit()), "sp.unit", bo.getUnit());
qw.eq(bo.getEquipmentId() != null, "sp.equipment_id", bo.getEquipmentId());
qw.like(StringUtils.isNotBlank(bo.getUnitTeam()), "sp.unit_team", bo.getUnitTeam());
qw.eq(bo.getQuantity() != null, "sp.quantity", bo.getQuantity());
//逻辑删除
qw.eq("sp.del_flag", 0);
@@ -81,6 +82,7 @@ public class EqpSparePartServiceImpl implements IEqpSparePartService {
lqw.eq(StringUtils.isNotBlank(bo.getModel()), EqpSparePart::getModel, bo.getModel());
lqw.eq(StringUtils.isNotBlank(bo.getUnit()), EqpSparePart::getUnit, bo.getUnit());
lqw.eq(bo.getEquipmentId() != null, EqpSparePart::getEquipmentId, bo.getEquipmentId());
lqw.like(StringUtils.isNotBlank(bo.getUnitTeam()), EqpSparePart::getUnitTeam, bo.getUnitTeam());
lqw.eq(bo.getQuantity() != null, EqpSparePart::getQuantity, bo.getQuantity());
return lqw;
}
@@ -89,14 +91,14 @@ public class EqpSparePartServiceImpl implements IEqpSparePartService {
* 新增备品备件
*/
@Override
public Boolean insertByBo(EqpSparePartBo bo) {
public Long insertByBo(EqpSparePartBo bo) {
EqpSparePart add = BeanUtil.toBean(bo, EqpSparePart.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setPartId(add.getPartId());
}
return flag;
return add.getPartId();
}
/**

View File

@@ -11,6 +11,7 @@
<result property="auxiliaryModel" column="auxiliary_model"/>
<result property="unit" column="unit"/>
<result property="equipmentId" column="equipment_id"/>
<result property="unitTeam" column="unit_team"/>
<result property="quantity" column="quantity"/>
<result property="createBy" column="create_by"/>
<result property="updateBy" column="update_by"/>

View File

@@ -11,6 +11,7 @@
<result property="model" column="model"/>
<result property="unit" column="unit"/>
<result property="equipmentId" column="equipment_id"/>
<result property="unitTeam" column="unit_team"/>
<result property="quantity" column="quantity"/>
<result property="createBy" column="create_by"/>
<result property="updateBy" column="update_by"/>
@@ -27,6 +28,7 @@
sp.model,
sp.unit,
sp.equipment_id,
sp.unit_team,
em.equipment_name AS equipmentName,
sp.quantity,
sp.remark

View File

@@ -0,0 +1,24 @@
package com.klp.pocket.acid.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
* 酸轧OEE按日钢卷信息主库来源
*/
@Data
public class AcidOeeCoilInfoByDateVo {
/** 统计日期 yyyy-MM-dd */
private String statDate;
/** 当前钢卷号 */
private String coilNo;
/** 重量(吨) */
private BigDecimal weight;
/** 判级 */
private String qualityStatus;
}

View File

@@ -3,7 +3,6 @@ package com.klp.pocket.acid.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 酸轧线OEE日汇总视图对象
@@ -45,18 +44,36 @@ public class AcidOeeDailySummaryVo {
/** 总产量(卷) */
private Long totalOutputCoil;
/** 良品量(吨) */
/** 良品量(A系列吨) */
private BigDecimal goodOutputTon;
/** 良品量(卷) */
/** 良品量(A系列卷) */
private Long goodOutputCoil;
/** 不良量(吨)= total_output_ton - good_output_ton */
/** 合格品量B系列 */
private BigDecimal qualifiedOutputTon;
/** 合格品量B系列 */
private Long qualifiedOutputCoil;
/** 合格品合计A+B */
private BigDecimal abOutputTon;
/** 合格品合计A+B */
private Long abOutputCoil;
/** 次品量C/D系列 */
private BigDecimal defectOutputTon;
/** 不良量(卷)= total_output_coil - good_output_coil */
/** 次品量C/D系列 */
private Long defectOutputCoil;
/** 待判级量O系列 */
private BigDecimal pendingOutputTon;
/** 待判级量O系列 */
private Long pendingOutputCoil;
/** 理论节拍min/吨;回归斜率) */
private BigDecimal idealCycleTimeMinPerTon;
@@ -72,9 +89,18 @@ public class AcidOeeDailySummaryVo {
/** 派生指标:性能稼动率(卷维度) */
private BigDecimal performanceCoil;
/** 派生指标:良品率 */
/** 派生指标:良品率A/总量) */
private BigDecimal quality;
/** 派生指标合格品率A+B/总量) */
private BigDecimal qualifiedRate;
/** 派生指标次品率C/D系列/总量) */
private BigDecimal defectRate;
/** 派生指标待判级率O系列/总量) */
private BigDecimal pendingRate;
/** 派生指标OEE建议以吨维度为主 */
private BigDecimal oee;
}

View File

@@ -0,0 +1,22 @@
package com.klp.pocket.acid.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.List;
/**
* 酸轧线OEE酸轧库Mapper。
*/
@Mapper
@DS("acid")
public interface AcidOeeAcidMapper {
/**
* 查询卷级生产节拍min/吨),用于理论节拍计算。
*/
List<BigDecimal> selectCoilCycleMinPerTon(@Param("startDate") String startDate,
@Param("endDate") String endDate);
}

View File

@@ -1,65 +0,0 @@
package com.klp.pocket.acid.mapper;
import com.klp.pocket.acid.domain.vo.AcidOeeDailySummaryVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 酸轧线OEE Mapper接口
*
* @author klp
* @date 2026-01-30
*/
@Mapper
public interface AcidOeeMapper {
/**
* 查询OEE日汇总按日期范围
* 聚合产量(吨/卷)、停机时间等
*
* @param startDate 开始日期yyyy-MM-dd
* @param endDate 结束日期yyyy-MM-dd
* @return 日汇总列表
*/
List<AcidOeeDailySummaryVo> selectDailySummary(@Param("startDate") String startDate,
@Param("endDate") String endDate);
/**
* 查询每日的钢卷号和重量(用于良品/次品判定)
*
* @param startDate 开始日期yyyy-MM-dd
* @param endDate 结束日期yyyy-MM-dd
* @return Map列表key为日期value为卷号和重量信息
*/
List<CoilInfoByDate> selectCoilInfoByDate(@Param("startDate") String startDate,
@Param("endDate") String endDate);
/**
* 查询卷级生产节拍min/吨),用于理论节拍计算。
*
* @param startDate 开始日期yyyy-MM-dd
* @param endDate 结束日期yyyy-MM-dd
* @return 每卷的生产节拍列表min/吨)
*/
List<java.math.BigDecimal> selectCoilCycleMinPerTon(@Param("startDate") String startDate,
@Param("endDate") String endDate);
/**
* 卷号信息内部类用于Mapper返回
*/
class CoilInfoByDate {
private String statDate;
private String coilNo;
private java.math.BigDecimal weight;
public String getStatDate() { return statDate; }
public void setStatDate(String statDate) { this.statDate = statDate; }
public String getCoilNo() { return coilNo; }
public void setCoilNo(String coilNo) { this.coilNo = coilNo; }
public java.math.BigDecimal getWeight() { return weight; }
public void setWeight(java.math.BigDecimal weight) { this.weight = weight; }
}
}

View File

@@ -0,0 +1,32 @@
package com.klp.pocket.acid.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.klp.pocket.acid.domain.vo.AcidOeeCoilInfoByDateVo;
import com.klp.pocket.acid.domain.vo.AcidOeeDailySummaryVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 酸轧线OEE主库Mapper。
*/
@Mapper
@DS("master")
public interface AcidOeeMasterMapper {
/**
* 查询OEE日汇总总产量来自主库 wms_material_coil
*/
List<AcidOeeDailySummaryVo> selectDailySummary(@Param("startDate") String startDate,
@Param("endDate") String endDate,
@Param("createBy") String createBy);
/**
* 查询每日钢卷重量与判级(来自主库 wms_material_coil
*/
List<AcidOeeCoilInfoByDateVo> selectCoilInfoByDate(@Param("startDate") String startDate,
@Param("endDate") String endDate,
@Param("createBy") String createBy);
}

View File

@@ -1,25 +1,34 @@
package com.klp.pocket.acid.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.klp.common.utils.StringUtils;
import com.klp.pocket.acid.domain.vo.AcidOeeCoilInfoByDateVo;
import com.klp.pocket.acid.domain.vo.AcidOeeDailySummaryVo;
import com.klp.pocket.acid.domain.vo.AcidOeeIdealCycleVo;
import com.klp.pocket.acid.domain.vo.AcidOeeLoss7Vo;
import com.klp.pocket.acid.domain.vo.Klptcm1ProStoppageVo;
import com.klp.pocket.acid.domain.bo.Klptcm1ProStoppageBo;
import com.klp.pocket.acid.mapper.AcidOeeMapper;
import com.klp.pocket.acid.mapper.AcidOeeMasterMapper;
import com.klp.pocket.acid.service.IAcidOeeService;
import com.klp.pocket.acid.service.IKlptcm1ProStoppageService;
import com.klp.pocket.common.service.ICoilQualityJudgeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 酸轧线OEE Service实现类
@@ -29,53 +38,65 @@ import java.util.Calendar;
*/
@Slf4j
@RequiredArgsConstructor
@DS("acid")
@Service
public class AcidOeeServiceImpl implements IAcidOeeService {
/** 酸轧成品库库区ID */
private static final Long ACID_FINISHED_WAREHOUSE_ID = 1988150099140866050L;
/** 固定理论节拍min/吨) */
private static final BigDecimal FIXED_IDEAL_CYCLE = BigDecimal.valueOf(0.47);
private final AcidOeeMapper acidOeeMapper;
/** 次品判级集合C/D系列 */
private static final Set<String> CD_SERIES = new HashSet<>(
Arrays.asList("C+", "C", "C-", "D+", "D", "D-")
);
private final AcidOeeMasterMapper acidOeeMasterMapper;
private final IKlptcm1ProStoppageService stoppageService;
private final ICoilQualityJudgeService coilQualityJudgeService;
@Value("${oee.acid.coil-create-by}")
private String acidCreateName;
@Override
public List<AcidOeeDailySummaryVo> getDailySummary(String startDate, String endDate) {
// 1. 查询基础日汇总(产量、停机时间等)
List<AcidOeeDailySummaryVo> summaries = acidOeeMapper.selectDailySummary(startDate, endDate);
List<AcidOeeDailySummaryVo> summaries = acidOeeMasterMapper.selectDailySummary(
startDate,
endDate,
acidCreateName
);
if (summaries == null || summaries.isEmpty()) {
return Collections.emptyList();
}
// 2. 查询停机事件,按日期聚合停机时间
Map<String, Long> downtimeByDate = aggregateDowntimeByDate(startDate, endDate);
// 3. 查询产量明细,用于良品/次品判定
Map<String, List<CoilInfo>> coilInfoByDate = getCoilNosByDate(startDate, endDate);
// 4. 理论节拍使用固定值0.47
BigDecimal idealCycleTon = FIXED_IDEAL_CYCLE;
// 5. 填充每个日汇总的完整数据
// 4. 先按天计算 dailyCycle = runTime/totalOutputTon再取中位数作为理论节拍
List<BigDecimal> dailyCycles = new ArrayList<>();
for (AcidOeeDailySummaryVo summary : summaries) {
String statDate = summary.getStatDate();
summary.setLineId("SY");
summary.setLineName("酸轧线");
// 填充停机时间
Long downtime = downtimeByDate.getOrDefault(statDate, 0L);
summary.setDowntimeMin(downtime);
// 计算运转时间
Long loadingTime = summary.getLoadingTimeMin() != null ? summary.getLoadingTimeMin() : 0L;
Long runTime = Math.max(0, loadingTime - downtime);
summary.setRunTimeMin(runTime);
// 理论节拍:若尚未填充,则统一使用“优良日统计”得到的节拍
if (summary.getIdealCycleTimeMinPerTon() == null && idealCycleTon != null) {
BigDecimal totalOutputTon = summary.getTotalOutputTon();
if (runTime > 0 && totalOutputTon != null && totalOutputTon.compareTo(BigDecimal.ZERO) > 0) {
BigDecimal dailyCycle = BigDecimal.valueOf(runTime)
.divide(totalOutputTon, 6, RoundingMode.HALF_UP);
dailyCycles.add(dailyCycle);
}
}
dailyCycles.sort(BigDecimal::compareTo);
BigDecimal idealCycleTon = applyEightyPercent(median(dailyCycles));
// 5. 回填理论节拍、良品次品并计算派生指标
for (AcidOeeDailySummaryVo summary : summaries) {
String statDate = summary.getStatDate();
if (idealCycleTon != null) {
summary.setIdealCycleTimeMinPerTon(idealCycleTon);
}
@@ -84,18 +105,19 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
List<CoilInfo> coilInfos = coilInfoByDate.get(statDate);
calculateQualityOutput(summary, coilInfos);
} else {
// 如果没有卷号,默认全部为良品(或根据业务规则处理)
summary.setGoodOutputTon(summary.getTotalOutputTon());
summary.setGoodOutputCoil(summary.getTotalOutputCoil());
// 没有卷明细时,全部归待判级
summary.setGoodOutputTon(BigDecimal.ZERO);
summary.setGoodOutputCoil(0L);
summary.setQualifiedOutputTon(BigDecimal.ZERO);
summary.setQualifiedOutputCoil(0L);
summary.setAbOutputTon(BigDecimal.ZERO);
summary.setAbOutputCoil(0L);
summary.setDefectOutputTon(BigDecimal.ZERO);
summary.setDefectOutputCoil(0L);
summary.setPendingOutputTon(summary.getTotalOutputTon());
summary.setPendingOutputCoil(summary.getTotalOutputCoil());
}
// 填充理论节拍(从回归数据或缓存获取,这里暂时留空,由调用方填充)
// summary.setIdealCycleTimeMinPerTon(...);
// summary.setIdealCycleTimeMinPerCoil(...);
// 计算派生指标
calculateDerivedMetrics(summary);
}
@@ -127,7 +149,11 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
@Override
public AcidOeeIdealCycleVo getIdealCycle(String startDate, String endDate) {
// 1) 取基础日汇总(产量、负荷时间等)
List<AcidOeeDailySummaryVo> daily = acidOeeMapper.selectDailySummary(startDate, endDate);
List<AcidOeeDailySummaryVo> daily = acidOeeMasterMapper.selectDailySummary(
startDate,
endDate,
acidCreateName
);
AcidOeeIdealCycleVo rsp = new AcidOeeIdealCycleVo();
rsp.setLineId("SY");
rsp.setLineName("酸轧线");
@@ -151,23 +177,31 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
d.setRunTimeMin(Math.max(0, loading - downtime));
}
// 3) 卷级节拍 = (END_DATE - START_DATE)/出口重量,计算中位数用于展示不用于OEE计算
List<BigDecimal> coilCycles = acidOeeMapper.selectCoilCycleMinPerTon(startDate, endDate);
coilCycles.removeIf(c -> c == null || c.compareTo(BigDecimal.ZERO) <= 0);
coilCycles.sort(BigDecimal::compareTo);
BigDecimal medianCycle = median(coilCycles);
// 理论节拍使用固定值0.47用于OEE计算
rsp.setIdealCycleTimeMinPerTon(FIXED_IDEAL_CYCLE);
// 中位数理论节拍(用于展示)
// 3) 理论节拍按“天维度”:每天(运转时间/总吨),再按日样本统计中位数用于展示
List<BigDecimal> dailyCycles = new ArrayList<>();
for (AcidOeeDailySummaryVo d : daily) {
Long run = d.getRunTimeMin();
BigDecimal ton = d.getTotalOutputTon();
if (run == null || run <= 0 || ton == null || ton.compareTo(BigDecimal.ZERO) <= 0) {
continue;
}
dailyCycles.add(BigDecimal.valueOf(run).divide(ton, 6, RoundingMode.HALF_UP));
}
dailyCycles.sort(BigDecimal::compareTo);
BigDecimal medianCycle = median(dailyCycles);
// 理论节拍:按“当天运转时间/当天总吨”逐日计算接口返回前乘以80%
BigDecimal idealCycle = applyEightyPercent(medianCycle);
rsp.setIdealCycleTimeMinPerTon(idealCycle);
// 展示字段保持为中位数
rsp.setMedianCycleTimeMinPerTon(medianCycle);
// 样本天数:当前查询区间内有产量的自然日数量(与传入的日期范围一一对应)
rsp.setSampleDays(daily.size());
// 4) 日粒度对比数据:理论耗时 vs 实际运转时间(用于前端展示"有效性"
// 使用固定值0.47计算理论耗时
// 使用“中间50%样本平均理论节拍”计算理论耗时
List<AcidOeeIdealCycleVo.DailyComparePointVo> compare = new ArrayList<>();
if (FIXED_IDEAL_CYCLE != null) {
if (idealCycle != null) {
for (AcidOeeDailySummaryVo d : daily) {
BigDecimal ton = d.getTotalOutputTon();
Long run = d.getRunTimeMin();
@@ -175,7 +209,7 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
AcidOeeIdealCycleVo.DailyComparePointVo p = new AcidOeeIdealCycleVo.DailyComparePointVo();
p.setStatDate(d.getStatDate());
p.setActualRunTimeMin(run);
p.setTheoreticalTimeMin(FIXED_IDEAL_CYCLE.multiply(ton));
p.setTheoreticalTimeMin(idealCycle.multiply(ton));
compare.add(p);
}
}
@@ -270,25 +304,25 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = Calendar.getInstance();
for (Klptcm1ProStoppageVo event : events) {
if (event.getStartDate() == null || event.getDuration() == null || event.getDuration() <= 0) {
continue;
}
Date eventStart = event.getStartDate();
long durationSec = event.getDuration();
long durationMin = (durationSec + 59) / 60; // 向上取整,避免丢失秒数
// 计算停机结束时间
cal.setTime(eventStart);
cal.add(Calendar.SECOND, (int) durationSec);
Date eventEnd = cal.getTime();
// 如果停机事件在同一天,直接累加
String startDateStr = dateFormat.format(eventStart);
String endDateStr = dateFormat.format(eventEnd);
if (startDateStr.equals(endDateStr)) {
// 同一天,直接累加
downtimeMap.merge(startDateStr, durationMin, Long::sum);
@@ -300,23 +334,23 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Date dayStart = cal.getTime();
Date currentDayStart = dayStart;
while (currentDayStart.before(eventEnd)) {
cal.setTime(currentDayStart);
cal.add(Calendar.DAY_OF_MONTH, 1);
Date nextDayStart = cal.getTime();
// 计算当前天的停机分钟数
Date dayEnd = nextDayStart.before(eventEnd) ? nextDayStart : eventEnd;
long dayMinutes = Math.max(0, (dayEnd.getTime() - Math.max(currentDayStart.getTime(), eventStart.getTime())) / (1000 * 60));
if (dayMinutes > 0) {
String dateKey = dateFormat.format(currentDayStart);
downtimeMap.merge(dateKey, dayMinutes, Long::sum);
}
currentDayStart = nextDayStart;
}
}
@@ -329,13 +363,18 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
* 获取每日的钢卷号和重量(用于良品/次品判定)
*/
private Map<String, List<CoilInfo>> getCoilNosByDate(String startDate, String endDate) {
List<AcidOeeMapper.CoilInfoByDate> coilInfoList = acidOeeMapper.selectCoilInfoByDate(startDate, endDate);
List<AcidOeeCoilInfoByDateVo> coilInfoList = acidOeeMasterMapper.selectCoilInfoByDate(
startDate,
endDate,
acidCreateName
);
Map<String, List<CoilInfo>> result = new HashMap<>();
for (AcidOeeMapper.CoilInfoByDate info : coilInfoList) {
for (AcidOeeCoilInfoByDateVo info : coilInfoList) {
String date = info.getStatDate();
result.computeIfAbsent(date, k -> new ArrayList<>())
.add(new CoilInfo(info.getCoilNo(), info.getWeight()));
.add(new CoilInfo(info.getCoilNo(), info.getWeight(), info.getQualityStatus()));
}
return result;
@@ -345,50 +384,64 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
* 卷号信息内部类
*/
private static class CoilInfo {
final String coilNo;
final BigDecimal weight;
final String qualityStatus;
CoilInfo(String coilNo, BigDecimal weight) {
this.coilNo = coilNo;
CoilInfo(String coilNo, BigDecimal weight, String qualityStatus) {
this.weight = weight;
this.qualityStatus = qualityStatus;
}
}
/**
* 计算良品/次品产量
* 计算质量细分产量A良品、B合格品、C/D次品、O待判级。
*/
private void calculateQualityOutput(AcidOeeDailySummaryVo summary, List<CoilInfo> coilInfos) {
BigDecimal goodTon = BigDecimal.ZERO;
long goodCoil = 0L;
BigDecimal defectTon = BigDecimal.ZERO;
long defectCoil = 0L;
BigDecimal aTon = BigDecimal.ZERO;
long aCoil = 0L;
BigDecimal bTon = BigDecimal.ZERO;
long bCoil = 0L;
BigDecimal cdTon = BigDecimal.ZERO;
long cdCoil = 0L;
BigDecimal oTon = BigDecimal.ZERO;
long oCoil = 0L;
for (CoilInfo coilInfo : coilInfos) {
String coilNo = coilInfo.coilNo;
BigDecimal coilWeight = coilInfo.weight != null ? coilInfo.weight : BigDecimal.ZERO;
String qualityStatus = StringUtils.upperCase(StringUtils.trim(coilInfo.qualityStatus));
// 通过WMS判定良品/次品
Boolean isScrap = coilQualityJudgeService.isScrap(ACID_FINISHED_WAREHOUSE_ID, coilNo);
if (isScrap == null) {
// 匹配不到,忽略不计
if (StringUtils.isBlank(qualityStatus) || "O".equals(qualityStatus)) {
oTon = oTon.add(coilWeight);
oCoil++;
continue;
}
if (Boolean.TRUE.equals(isScrap)) {
// 次品
defectTon = defectTon.add(coilWeight);
defectCoil++;
if (qualityStatus.startsWith("A")) {
aTon = aTon.add(coilWeight);
aCoil++;
} else if (qualityStatus.startsWith("B")) {
bTon = bTon.add(coilWeight);
bCoil++;
} else if (CD_SERIES.contains(qualityStatus)) {
cdTon = cdTon.add(coilWeight);
cdCoil++;
} else {
// 良品
goodTon = goodTon.add(coilWeight);
goodCoil++;
// 未识别等级统一归待判级
oTon = oTon.add(coilWeight);
oCoil++;
}
}
summary.setGoodOutputTon(goodTon);
summary.setGoodOutputCoil(goodCoil);
summary.setDefectOutputTon(defectTon);
summary.setDefectOutputCoil(defectCoil);
summary.setGoodOutputTon(aTon);
summary.setGoodOutputCoil(aCoil);
summary.setQualifiedOutputTon(bTon);
summary.setQualifiedOutputCoil(bCoil);
summary.setAbOutputTon(aTon.add(bTon));
summary.setAbOutputCoil(aCoil + bCoil);
summary.setDefectOutputTon(cdTon);
summary.setDefectOutputCoil(cdCoil);
summary.setPendingOutputTon(oTon);
summary.setPendingOutputCoil(oCoil);
}
/**
@@ -406,6 +459,7 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
}
// 性能稼动率(吨维度)
// 口径:理论节拍单位为 min/吨 时,性能稼动率 = (理论节拍 × 实际产量) / 实际运转时间 × 100
Long runTime = summary.getRunTimeMin() != null ? summary.getRunTimeMin() : 0L;
BigDecimal idealCycleTon = summary.getIdealCycleTimeMinPerTon();
BigDecimal totalOutputTon = summary.getTotalOutputTon();
@@ -415,12 +469,14 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
&& totalOutputTon != null
&& totalOutputTon.compareTo(BigDecimal.ZERO) > 0) {
BigDecimal idealTime = idealCycleTon.multiply(totalOutputTon);
BigDecimal performanceTon = idealTime.divide(BigDecimal.valueOf(runTime), 4, RoundingMode.HALF_UP)
BigDecimal performanceTon = idealTime
.divide(BigDecimal.valueOf(runTime), 4, RoundingMode.HALF_UP)
.multiply(BigDecimal.valueOf(100));
summary.setPerformanceTon(performanceTon);
}
// 性能稼动率(卷维度)
// 口径:理论节拍单位为 min/卷 时,性能稼动率 = (理论节拍 × 实际产量) / 实际运转时间 × 100
Long totalOutputCoil = summary.getTotalOutputCoil() != null ? summary.getTotalOutputCoil() : 0L;
BigDecimal idealCycleCoil = summary.getIdealCycleTimeMinPerCoil();
if (runTime > 0
@@ -428,17 +484,35 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
&& idealCycleCoil.compareTo(BigDecimal.ZERO) > 0
&& totalOutputCoil > 0) {
BigDecimal idealTime = idealCycleCoil.multiply(BigDecimal.valueOf(totalOutputCoil));
BigDecimal performanceCoil = idealTime.divide(BigDecimal.valueOf(runTime), 4, RoundingMode.HALF_UP)
BigDecimal performanceCoil = idealTime
.divide(BigDecimal.valueOf(runTime), 4, RoundingMode.HALF_UP)
.multiply(BigDecimal.valueOf(100));
summary.setPerformanceCoil(performanceCoil);
}
// 良品
// 质量细分比
if (totalOutputTon != null && totalOutputTon.compareTo(BigDecimal.ZERO) > 0) {
BigDecimal goodOutputTon = summary.getGoodOutputTon() != null ? summary.getGoodOutputTon() : BigDecimal.ZERO;
BigDecimal quality = goodOutputTon.divide(totalOutputTon, 4, RoundingMode.HALF_UP)
BigDecimal aTon = summary.getGoodOutputTon() != null ? summary.getGoodOutputTon() : BigDecimal.ZERO;
BigDecimal bTon = summary.getQualifiedOutputTon() != null ? summary.getQualifiedOutputTon() : BigDecimal.ZERO;
BigDecimal cdTon = summary.getDefectOutputTon() != null ? summary.getDefectOutputTon() : BigDecimal.ZERO;
BigDecimal oTon = summary.getPendingOutputTon() != null ? summary.getPendingOutputTon() : BigDecimal.ZERO;
BigDecimal quality = aTon.divide(totalOutputTon, 4, RoundingMode.HALF_UP)
.multiply(BigDecimal.valueOf(100));
summary.setQuality(quality);
BigDecimal qualifiedRate = aTon.add(bTon)
.divide(totalOutputTon, 4, RoundingMode.HALF_UP)
.multiply(BigDecimal.valueOf(100));
summary.setQualifiedRate(qualifiedRate);
BigDecimal defectRate = cdTon.divide(totalOutputTon, 4, RoundingMode.HALF_UP)
.multiply(BigDecimal.valueOf(100));
summary.setDefectRate(defectRate);
BigDecimal pendingRate = oTon.divide(totalOutputTon, 4, RoundingMode.HALF_UP)
.multiply(BigDecimal.valueOf(100));
summary.setPendingRate(pendingRate);
}
// OEE以吨维度为主
@@ -463,6 +537,15 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
return a.add(b).divide(BigDecimal.valueOf(2), 6, RoundingMode.HALF_UP);
}
/** 理论节拍返回前按业务口径乘以70% */
private BigDecimal applyEightyPercent(BigDecimal cycle) {
if (cycle == null) {
return null;
}
return cycle.multiply(BigDecimal.valueOf(0.7)).setScale(6, RoundingMode.HALF_UP);
}
/**
* 解析日期字符串为Date对象
*/

View File

@@ -18,6 +18,7 @@ public class CrmPdiPlan {
private Integer seqid;
private String coilid;
private String enterCoilNo;
private Integer dummyCoilFlag;
private String status;
private String planid;

View File

@@ -19,6 +19,7 @@ public class CrmPdoExcoil {
private String exitMatId;
private String entryMatId;
private String enterCoilNo;
private Integer subId;
private Double startPosition;
private Double endPosition;

View File

@@ -15,6 +15,7 @@ public class CrmPdiPlanBo extends BaseEntity {
private Integer seqid;
private String coilid;
private String enterCoilNo;
private Integer dummyCoilFlag;
private String status;
private String planid;

View File

@@ -15,6 +15,7 @@ public class CrmPdoExcoilBo extends BaseEntity {
private String exitMatId;
private String entryMatId;
private String enterCoilNo;
private Integer subId;
private Double startPosition;
private Double endPosition;

Some files were not shown because too many files have changed in this diff Show More