From f582aad4d86f811649d5b1f2c17f0ed84ab150df Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期二, 26 五月 2026 09:32:09 +0800
Subject: [PATCH] Merge branch 'dev_New_pro' into dev_襄垣县洁鑫商贸有限公司
---
src/main/java/com/ruoyi/approve/controller/ApprovalTaskController.java | 18
src/main/java/com/ruoyi/approve/mapper/ApprovalInstanceMapper.java | 24
src/main/java/com/ruoyi/purchase/service/PurchaseReportService.java | 14
src/main/java/com/ruoyi/project/system/controller/SysMenuController.java | 270
src/main/java/com/ruoyi/approve/controller/ApprovalTemplateNodeController.java | 18
src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java | 89
src/main/java/com/ruoyi/purchase/vo/SupplierTransactionsVo.java | 30
src/main/java/com/ruoyi/ai/controller/SalesAiController.java | 12
src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java | 1
src/main/resources/mapper/basic/ProductModelMapper.xml | 1
src/main/java/com/ruoyi/warehouse/mapper/DocumentationFileMapper.java | 3
doc/financial-ai-front-integration.md | 192
src/main/java/com/ruoyi/approve/service/ApprovalTemplateNodeService.java | 20
src/main/resources/application-dev.yml | 3
src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeDeptMapper.xml | 13
src/main/java/com/ruoyi/account/service/purchase/AccountPaymentApplicationService.java | 33
src/main/java/com/ruoyi/quality/controller/QualityReportController.java | 34
src/main/java/com/ruoyi/technology/controller/TechnologyOperationController.java | 8
src/main/java/com/ruoyi/project/common/CaptchaController.java | 196
src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeDept.java | 59
doc/20260522_财务助手提问优化前端变更文档.md | 59
src/main/resources/mapper/procurementrecord/ReturnManagementMapper.xml | 3
src/main/java/com/ruoyi/account/controller/sales/AccountSalesInvoiceController.java | 72
src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java | 4
src/main/java/com/ruoyi/approve/mapper/ApprovalTaskMapper.java | 18
src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateServiceImpl.java | 250
src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnManagementServiceImpl.java | 17
src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java | 45
src/main/java/com/ruoyi/approve/pojo/ApprovalInstance.java | 152
src/main/java/com/ruoyi/account/controller/sales/AccountSalesCollectionController.java | 79
src/main/java/com/ruoyi/account/bean/vo/purchase/AccountPurchasePaymentVo.java | 34
src/main/java/com/ruoyi/approve/mapper/FinReimbursementMapper.java | 24
src/main/java/com/ruoyi/account/controller/AccountStatementController.java | 71
src/main/java/com/ruoyi/project/system/controller/SysConfigController.java | 254
src/main/java/com/ruoyi/project/monitor/controller/ServerController.java | 54
src/main/java/com/ruoyi/approve/mapper/FinReimbursementDetailMapper.java | 18
src/main/java/com/ruoyi/account/controller/sales/AccountInvoiceApplicationController.java | 86
src/main/java/com/ruoyi/approve/bean/dto/ApprovalTemplateDto.java | 12
src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java | 27
src/main/java/com/ruoyi/basic/mapper/SupplierManageMapper.java | 6
src/main/java/com/ruoyi/account/bean/dto/purchase/PurchaseInboundDto.java | 8
src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java | 311
src/main/resources/mapper/approve/ApprovalInstanceMapper.xml | 58
src/main/java/com/ruoyi/approve/pojo/ApprovalTask.java | 128
src/main/resources/mapper/sales/SalesQuotationMapper.xml | 26
src/main/java/com/ruoyi/approve/controller/FinReimbursementController.java | 60
src/main/java/com/ruoyi/approve/service/ApprovalRecordService.java | 16
src/main/resources/mapper/account/purchase/AccountPaymentApplicationMapper.xml | 98
src/main/java/com/ruoyi/project/monitor/controller/CacheController.java | 222
src/main/java/com/ruoyi/approve/bean/vo/ApprovalTemplateNodeVo.java | 13
src/main/java/com/ruoyi/sales/service/ISalesLedgerProductService.java | 7
src/main/java/com/ruoyi/approve/controller/ApprovalInstanceNodeController.java | 19
src/main/java/com/ruoyi/account/controller/AccountingController.java | 24
src/main/resources/financial-agent-prompt.txt | 11
src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeUserMapper.xml | 13
src/main/java/com/ruoyi/sales/service/impl/SalesQuotationServiceImpl.java | 54
src/main/java/com/ruoyi/account/pojo/purchase/AccountPurchaseInvoice.java | 168
src/main/java/com/ruoyi/approve/service/FinReimbursementTravelService.java | 16
src/main/resources/mapper/staff/StaffLeaveMapper.xml | 21
src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java | 9
src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java | 129
src/main/resources/mapper/account/sales/AccountSalesInvoiceMapper.xml | 47
doc/20260522_首页财务接口升级前端变更文档.md | 120
src/main/java/com/ruoyi/account/bean/dto/purchase/AccountPaymentApplicationDto.java | 34
src/main/java/com/ruoyi/account/bean/vo/sales/AccountInvoiceApplicationVo.java | 23
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java | 2
src/main/java/com/ruoyi/purchase/mapper/PurchaseLedgerMapper.java | 3
src/main/java/com/ruoyi/approve/service/impl/FinReimbursementDetailServiceImpl.java | 20
src/main/java/com/ruoyi/project/system/controller/SysRoleController.java | 510
src/main/java/com/ruoyi/purchase/vo/PurchaseReportVo.java | 44
src/main/java/com/ruoyi/project/monitor/controller/SysUserOnlineController.java | 166
src/main/resources/mapper/approve/ApproveProcessMapper.xml | 4
src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java | 3
src/main/resources/sales-agent-prompt.txt | 2
doc/20260520_首页生产看板性能优化前端变更文档.md | 107
src/main/resources/mapper/approve/ApprovalTemplateNodeMapper.xml | 15
src/main/java/com/ruoyi/quality/controller/QualityInspectController.java | 47
src/main/java/com/ruoyi/account/mapper/purchase/AccountPaymentApplicationMapper.java | 32
src/main/java/com/ruoyi/ai/controller/XiaozhiController.java | 11
src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java | 159
src/main/java/com/ruoyi/warehouse/service/DocumentationFileService.java | 3
src/main/java/com/ruoyi/approve/controller/ApprovalRecordController.java | 18
src/main/resources/mapper/approve/ApprovalRecordMapper.xml | 20
src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java | 20
src/main/java/com/ruoyi/procurementrecord/controller/ReturnManagementController.java | 14
src/main/java/com/ruoyi/purchase/vo/SupplierTransactionsDetailsVo.java | 33
src/main/java/com/ruoyi/account/bean/dto/purchase/AccountPurchaseInvoiceDto.java | 32
src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java | 16
src/main/java/com/ruoyi/account/mapper/AccountStatementMapper.java | 28
src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java | 25
src/main/resources/mapper/account/AccountStatementMapper.xml | 78
src/main/java/com/ruoyi/account/bean/dto/sales/AccountSalesCollectionDto.java | 34
src/main/java/com/ruoyi/common/enums/TypeEnums.java | 70
src/main/java/com/ruoyi/project/system/service/ISysUserService.java | 7
src/main/java/com/ruoyi/account/mapper/sales/AccountSalesInvoiceMapper.java | 24
src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java | 31
src/main/resources/manufacturing-agent-prompt.txt | 2
src/main/java/com/ruoyi/account/pojo/purchase/AccountPurchasePayment.java | 127
src/main/java/com/ruoyi/approve/controller/ApprovalTemplateNodeApproverController.java | 18
src/main/java/com/ruoyi/approve/service/impl/FinReimbursementServiceImpl.java | 544 +
src/main/java/com/ruoyi/account/service/sales/AccountInvoiceApplicationService.java | 33
src/main/java/com/ruoyi/sales/vo/CustomerTransactionsDetailsVo.java | 33
src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java | 5
src/main/resources/mapper/staff/StaffOnJobMapper.xml | 91
src/main/java/com/ruoyi/purchase/service/impl/PurchaseReportServiceImpl.java | 32
src/main/java/com/ruoyi/ai/tools/FinancialAgentTools.java | 2226 +++++
src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingController.java | 2
src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java | 40
src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java | 240
src/main/java/com/ruoyi/ai/tools/SalesAgentTools.java | 426
src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java | 21
src/main/java/com/ruoyi/basic/pojo/ProductModel.java | 6
src/main/java/com/ruoyi/account/bean/vo/sales/SalesOutboundVo.java | 7
src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeUser.java | 59
src/main/java/com/ruoyi/approve/controller/FinReimbursementTravelController.java | 18
src/main/java/com/ruoyi/ai/assistant/PurchaseAgent.java | 3
src/main/java/com/ruoyi/basic/service/impl/SupplierServiceImpl.java | 12
src/main/java/com/ruoyi/approve/bean/vo/ApprovalInstanceVo.java | 28
src/main/resources/mapper/stock/StockOutRecordMapper.xml | 4
src/main/java/com/ruoyi/account/bean/dto/purchase/PurchaseReturnDto.java | 8
src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeUserController.java | 18
src/main/java/com/ruoyi/staff/mapper/StaffOnJobMapper.java | 4
src/main/java/com/ruoyi/CodeGenerator.java | 6
src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java | 12
src/main/java/com/ruoyi/account/bean/vo/AccountReportVo.java | 66
src/main/java/com/ruoyi/warehouse/controller/DocumentationFileController.java | 3
src/main/java/com/ruoyi/production/mapper/ProductionOrderMapper.java | 21
src/main/resources/mapper/account/sales/AccountInvoiceApplicationMapper.xml | 73
src/main/java/com/ruoyi/approve/pojo/ApprovalTemplateNodeApprover.java | 76
src/main/java/com/ruoyi/account/pojo/AccountStatementDetails.java | 115
src/main/java/com/ruoyi/account/service/AccountStatementDetailsService.java | 16
src/main/java/com/ruoyi/ai/assistant/PurchaseIntentExecutor.java | 249
src/main/java/com/ruoyi/account/service/AccountStatementService.java | 32
src/main/java/com/ruoyi/account/bean/dto/sales/AccountSalesInvoiceDto.java | 33
src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNews.java | 88
doc/20260522_采购台账入库状态_销售产品入库审核状态前端联调文档.md | 127
src/main/java/com/ruoyi/account/service/impl/sales/AccountInvoiceApplicationServiceImpl.java | 97
src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java | 67
src/main/java/com/ruoyi/approve/controller/FinReimbursementDetailController.java | 18
src/main/java/com/ruoyi/sales/pojo/SalesLedger.java | 26
src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java | 14
src/main/resources/mapper/purchase/PurchaseReturnOrdersMapper.xml | 3
src/main/java/com/ruoyi/quality/controller/QualityInspectParamController.java | 25
src/main/java/com/ruoyi/stock/controller/StockInRecordController.java | 11
src/main/java/com/ruoyi/approve/service/FinReimbursementService.java | 31
src/main/java/com/ruoyi/approve/utils/ApproveProcessConfigNodeUtils.java | 363
src/main/java/com/ruoyi/collaborativeApproval/vo/EnterpriseNewsVo.java | 15
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java | 198
src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsServiceImpl.java | 409
src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java | 32
src/main/java/com/ruoyi/purchase/dto/VatDto.java | 17
src/main/java/com/ruoyi/ai/service/PurchaseAiService.java | 88
src/main/java/com/ruoyi/account/controller/purchase/AccountPaymentApplicationController.java | 86
src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java | 22
src/main/java/com/ruoyi/account/bean/vo/sales/AccountSalesCollectionVo.java | 26
src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java | 17
src/main/resources/mapper/stock/StockInventoryMapper.xml | 13
src/main/resources/mapper/approve/ApprovalInstanceNodeMapper.xml | 21
doc/20260522_StockInRecord列表源单号前端联调文档_276补充.md | 65
src/main/java/com/ruoyi/account/service/sales/AccountSalesCollectionService.java | 33
src/main/java/com/ruoyi/approve/service/impl/FinReimbursementTravelServiceImpl.java | 20
src/main/java/com/ruoyi/basic/service/ICustomerService.java | 18
src/main/resources/application-hqjc.yml | 268
src/main/java/com/ruoyi/account/service/impl/purchase/AccountPaymentApplicationServiceImpl.java | 96
src/main/java/com/ruoyi/account/service/impl/sales/AccountSalesCollectionServiceImpl.java | 96
src/main/java/com/ruoyi/production/service/ProductionOrderRoutingOperationService.java | 3
src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java | 16
src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsController.java | 61
src/main/java/com/ruoyi/account/mapper/sales/AccountSalesCollectionMapper.java | 35
src/main/java/com/ruoyi/account/service/impl/AccountStatementServiceImpl.java | 298
src/main/java/com/ruoyi/ai/assistant/SalesAgent.java | 4
src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java | 4
src/main/java/com/ruoyi/account/service/sales/AccountSalesInvoiceService.java | 28
src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java | 508
src/main/java/com/ruoyi/approve/pojo/FinReimbursementTravel.java | 162
src/main/java/com/ruoyi/account/service/impl/sales/AccountSalesInvoiceServiceImpl.java | 53
src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeDeptMapper.java | 18
src/main/java/com/ruoyi/account/pojo/AccountStatement.java | 127
src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml | 200
src/main/java/com/ruoyi/account/bean/dto/StatementAccountDto.java | 35
src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsMapper.java | 24
src/main/java/com/ruoyi/project/monitor/controller/SysJobController.java | 372
src/main/java/com/ruoyi/stock/service/StockInRecordService.java | 2
src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java | 12
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java | 588
src/main/java/com/ruoyi/account/service/purchase/AccountPurchaseInvoiceService.java | 31
src/main/resources/mapper/sales/SalesLedgerProductMapper.xml | 122
src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateNodeServiceImpl.java | 62
src/main/java/com/ruoyi/approve/pojo/FinReimbursementDetail.java | 157
src/main/resources/mapper/approve/FinReimbursementTravelMapper.xml | 29
src/main/java/com/ruoyi/account/pojo/sales/AccountSalesCollection.java | 127
src/main/java/com/ruoyi/technology/controller/TechnologyOperationParamController.java | 2
src/main/java/com/ruoyi/account/mapper/AccountStatementDetailsMapper.java | 18
src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeUserMapper.java | 18
src/main/java/com/ruoyi/project/system/controller/SysRegisterController.java | 66
doc/20260522_财务升级AI模块前端变更联调文档.md | 150
src/main/java/com/ruoyi/quality/controller/QualityTestStandardController.java | 57
src/main/java/com/ruoyi/staff/service/IStaffOnJobService.java | 2
src/main/java/com/ruoyi/approve/service/impl/ApprovalTaskServiceImpl.java | 20
src/main/java/com/ruoyi/common/enums/ApprovalStatusEnum.java | 49
src/main/java/com/ruoyi/approve/bean/vo/FinReimbursementVo.java | 34
src/main/java/com/ruoyi/project/system/controller/SysProfileController.java | 266
src/main/java/com/ruoyi/approve/service/ApprovalInstanceNodeService.java | 16
src/main/java/com/ruoyi/sales/controller/MetricStatisticsController.java | 24
src/main/java/com/ruoyi/sales/excel/InvoiceLedgerExcelDto.java | 7
src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java | 205
src/main/java/com/ruoyi/account/bean/dto/sales/SalesOutboundDto.java | 8
src/main/java/com/ruoyi/ai/controller/FinancialAiController.java | 112
src/main/java/com/ruoyi/approve/bean/vo/ApproveProcessVO.java | 9
src/main/java/com/ruoyi/production/util/TaskPlanQuantityUtil.java | 137
src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java | 5
src/main/resources/mapper/approve/FinReimbursementMapper.xml | 61
src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java | 264
src/main/java/com/ruoyi/account/pojo/purchase/AccountPaymentApplication.java | 141
src/main/java/com/ruoyi/approve/pojo/FinReimbursement.java | 210
src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceNodeServiceImpl.java | 20
src/main/resources/mapper/sales/SalesLedgerMapper.xml | 16
src/main/resources/mapper/basic/SupplierManageMapper.xml | 92
src/main/java/com/ruoyi/quality/utils/QualityInspectHelper.java | 73
src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java | 82
src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java | 753 +
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java | 79
doc/20260521_首页HomeController接口升级前端变更文档.md | 113
src/main/java/com/ruoyi/approve/pojo/ApprovalRecord.java | 98
src/main/java/com/ruoyi/approve/mapper/ApprovalInstanceNodeMapper.java | 18
src/main/resources/mapper/account/purchase/AccountPurchaseInvoiceMapper.xml | 86
src/main/java/com/ruoyi/approve/service/impl/ApprovalRecordServiceImpl.java | 20
src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java | 29
src/main/java/com/ruoyi/ai/assistant/ApproveTodoAgent.java | 3
src/main/java/com/ruoyi/approve/pojo/ApprovalTemplateNode.java | 66
src/main/java/com/ruoyi/approve/mapper/ApprovalTemplateMapper.java | 24
src/main/java/com/ruoyi/approve/mapper/ApprovalTemplateNodeMapper.java | 18
src/main/java/com/ruoyi/ai/assistant/FinancialIntentExecutor.java | 266
src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeUserServiceImpl.java | 20
src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateNodeApproverServiceImpl.java | 20
src/main/java/com/ruoyi/account/bean/dto/AccountReportDto.java | 19
src/main/java/com/ruoyi/approve/pojo/ApprovalInstanceNode.java | 106
src/main/resources/purchase-agent-prompt.txt | 9
src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java | 192
src/main/resources/mapper/quality/QualityInspectMapper.xml | 52
src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java | 55
src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeDeptServiceImpl.java | 20
src/main/java/com/ruoyi/ai/assistant/ManufacturingAgent.java | 3
src/main/resources/mapper/approve/ApprovalTemplateMapper.xml | 33
src/main/java/com/ruoyi/account/mapper/purchase/AccountPurchaseInvoiceMapper.java | 29
src/main/java/com/ruoyi/basic/service/ISupplierService.java | 21
src/main/resources/mapper/approve/ApprovalTemplateNodeApproverMapper.xml | 16
src/main/java/com/ruoyi/approve/mapper/ApprovalTemplateNodeApproverMapper.java | 18
src/main/java/com/ruoyi/account/bean/vo/purchase/AccountPurchaseInvoiceVo.java | 19
src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java | 28
src/main/java/com/ruoyi/staff/dto/StaffOnJobDto.java | 2
src/main/java/com/ruoyi/account/service/impl/purchase/AccountPurchasePaymentServiceImpl.java | 90
src/main/resources/mapper/basic/CustomerMapper.xml | 83
src/main/java/com/ruoyi/approve/bean/dto/FinReimbursementDto.java | 21
src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeDeptController.java | 18
src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java | 6
src/main/java/com/ruoyi/account/bean/dto/purchase/AccountPurchasePaymentDto.java | 34
src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java | 7
src/main/java/com/ruoyi/approve/service/ApprovalTemplateNodeApproverService.java | 16
src/main/resources/mapper/approve/ApprovalTaskMapper.xml | 24
src/main/resources/mapper/system/SysNoticeMapper.xml | 5
src/main/java/com/ruoyi/common/enums/ShippingStatusEnum.java | 42
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java | 70
src/main/java/com/ruoyi/project/system/controller/SysLoginController.java | 310
src/main/java/com/ruoyi/project/system/controller/SysDeptController.java | 268
src/main/java/com/ruoyi/approve/service/ApprovalTaskService.java | 16
src/main/java/com/ruoyi/approve/mapper/ApprovalRecordMapper.java | 18
src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java | 29
src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsService.java | 29
src/main/java/com/ruoyi/sales/dto/SalesLedgerImportDto.java | 4
src/main/java/com/ruoyi/project/system/controller/SysUserController.java | 581
src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java | 149
src/main/java/com/ruoyi/sales/vo/CustomerTransactionsVo.java | 30
src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java | 11
src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java | 4
src/main/resources/approve-todo-agent-prompt.txt | 2
src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeUserService.java | 16
src/main/java/com/ruoyi/approve/pojo/ApprovalTemplate.java | 107
src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java | 1
src/main/resources/static/销售台账导入模板.xlsx | 0
src/main/java/com/ruoyi/account/service/impl/AccountStatementDetailsServiceImpl.java | 20
src/main/java/com/ruoyi/account/service/purchase/AccountPurchasePaymentService.java | 30
src/main/java/com/ruoyi/account/service/AccountingService.java | 19
src/main/java/com/ruoyi/project/monitor/controller/SysOperlogController.java | 140
src/main/resources/mapper/collaborativeApproval/EnterpriseNewsMapper.xml | 46
src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java | 91
src/main/java/com/ruoyi/approve/bean/vo/ApproveGetAndUpdateVo.java | 9
doc/20260522_StockInRecord列表源单号前端联调文档.md | 75
src/main/java/com/ruoyi/account/pojo/sales/AccountInvoiceApplication.java | 138
src/main/java/com/ruoyi/approve/bean/dto/ApprovalTemplateNodeDto.java | 12
src/main/java/com/ruoyi/staff/controller/StaffOnJobController.java | 2
src/main/resources/mapper/stock/StockInRecordMapper.xml | 92
src/main/java/com/ruoyi/account/pojo/financial/AccountSubject.java | 4
src/main/java/com/ruoyi/quality/pojo/QualityInspect.java | 5
src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java | 128
src/main/resources/mapper/production/ProductionOperationTaskMapper.xml | 5
src/main/java/com/ruoyi/ai/config/FinancialAgentConfig.java | 20
src/main/java/com/ruoyi/common/enums/EnterpriseNewsStatusEnum.java | 143
src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java | 17
src/main/java/com/ruoyi/quality/controller/QualityTestStandardBindingController.java | 27
src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java | 3
src/main/java/com/ruoyi/ai/assistant/FinancialAgent.java | 22
src/main/java/com/ruoyi/approve/bean/vo/ApprovalTemplateNodeApproverVo.java | 9
src/main/java/com/ruoyi/project/monitor/controller/SysJobLogController.java | 186
src/main/java/com/ruoyi/collaborativeApproval/dto/EnterpriseNewsDto.java | 26
src/main/java/com/ruoyi/home/controller/HomeController.java | 586 +
src/main/java/com/ruoyi/account/bean/dto/sales/SalesReturnDto.java | 8
src/main/java/com/ruoyi/account/mapper/sales/AccountInvoiceApplicationMapper.java | 32
src/main/java/com/ruoyi/approve/controller/ApprovalTemplateController.java | 74
src/main/java/com/ruoyi/device/service/IDeviceLedgerService.java | 6
src/main/java/com/ruoyi/account/bean/vo/StatementAccountVo.java | 25
src/main/java/com/ruoyi/account/bean/dto/sales/AccountInvoiceApplicationDto.java | 34
src/main/java/com/ruoyi/account/service/impl/purchase/AccountPurchaseInvoiceServiceImpl.java | 59
src/main/java/com/ruoyi/approve/service/FinReimbursementDetailService.java | 16
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java | 79
src/main/java/com/ruoyi/project/monitor/controller/SysLogininforController.java | 140
src/main/java/com/ruoyi/common/enums/SalesQuotationStatusEnum.java | 43
src/main/resources/mapper/approve/FinReimbursementDetailMapper.xml | 29
doc/20260521_采购智能体优化前端变更文档.md | 85
src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java | 63
src/main/java/com/ruoyi/account/bean/vo/purchase/AccountPaymentApplicationVo.java | 23
src/main/java/com/ruoyi/sales/dto/SalesLedgerProductImportDto.java | 7
src/main/java/com/ruoyi/account/pojo/sales/AccountSalesInvoice.java | 168
src/main/java/com/ruoyi/sales/dto/SalesQuotationDto.java | 2
src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java | 11
src/main/java/com/ruoyi/account/controller/purchase/AccountPurchasePaymentController.java | 71
src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeDeptService.java | 16
src/main/java/com/ruoyi/account/bean/vo/purchase/PurchaseInboundVo.java | 4
src/main/resources/mapper/account/purchase/AccountPurchasePaymentMapper.xml | 57
src/main/java/com/ruoyi/account/controller/purchase/AccountPurchaseInvoiceController.java | 79
src/main/java/com/ruoyi/ai/controller/ManufacturingAiController.java | 12
src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java | 10
src/main/java/com/ruoyi/project/system/controller/SysPostController.java | 266
src/main/java/com/ruoyi/account/bean/vo/sales/AccountSalesInvoiceVo.java | 19
src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java | 1
src/main/java/com/ruoyi/stock/pojo/StockInRecord.java | 3
src/main/resources/mapper/account/sales/AccountSalesCollectionMapper.xml | 101
doc/20260520_首页生产看板前端联调文档.md | 160
src/main/java/com/ruoyi/approve/service/ApprovalTemplateService.java | 34
src/main/resources/mapper/production/ProductionOrderMapper.xml | 81
/dev/null | 454 -
src/main/java/com/ruoyi/approve/mapper/FinReimbursementTravelMapper.java | 18
src/main/java/com/ruoyi/approve/bean/vo/ApprovalTemplateVo.java | 14
src/main/java/com/ruoyi/approve/service/ApprovalInstanceService.java | 31
src/main/java/com/ruoyi/quality/controller/QualityTestStandardParamController.java | 33
doc/20260523_ 协同审批新增出差时间和结束时间.sql | 3
src/main/java/com/ruoyi/account/mapper/purchase/AccountPurchasePaymentMapper.java | 29
src/main/java/com/ruoyi/approve/service/impl/ApproveBusinessStatusService.java | 175
src/main/java/com/ruoyi/approve/bean/dto/ApprovalTemplateNodeApproverDto.java | 8
349 files changed, 21,353 insertions(+), 5,208 deletions(-)
diff --git "a/doc/20260520_\351\246\226\351\241\265\347\224\237\344\272\247\347\234\213\346\235\277\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243.md" "b/doc/20260520_\351\246\226\351\241\265\347\224\237\344\272\247\347\234\213\346\235\277\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..aaa6055
--- /dev/null
+++ "b/doc/20260520_\351\246\226\351\241\265\347\224\237\344\272\247\347\234\213\346\235\277\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243.md"
@@ -0,0 +1,160 @@
+# 棣栭〉鐢熶骇鐪嬫澘鍓嶇鑱旇皟鏂囨。
+
+鏇存柊鏃堕棿锛�2026-05-20
+妯″潡锛歚/home`锛堥椤碉級
+
+## 1. 鎺ュ彛娓呭崟
+
+1. `GET /home/productionOverview`锛氱敓浜ф�昏
+2. `GET /home/productionRealtimeBoard`锛氱敓浜у疄鏃剁湅鏉�
+3. `GET /home/productionOrderProgress`锛氱敓浜ц鍗曡繘搴�
+4. `GET /home/todayProductionPlan`锛氫粖鏃ョ敓浜ц鍒�
+
+鎵�鏈夋帴鍙g粺涓�杩斿洖 `AjaxResult`锛�
+
+```json
+{
+ "code": 200,
+ "msg": "鎿嶄綔鎴愬姛",
+ "data": {}
+}
+```
+
+## 2. 鐢熶骇鎬昏
+
+### 2.1 璇锋眰
+
+```http
+GET /home/productionOverview
+```
+
+### 2.2 杩斿洖 `data`
+
+```json
+{
+ "totalOutput": 1280.00,
+ "totalScrap": 25.00,
+ "yieldRate": 98.08
+}
+```
+
+瀛楁璇存槑锛�
+
+- `totalOutput`锛氱疮璁′骇鍑猴紙浠讹紝鍚堟牸鏁帮級
+- `totalScrap`锛氱疮璁℃姤搴燂紙浠讹級
+- `yieldRate`锛氳壇鐜囷紙0-100锛屽墠绔睍绀烘椂鍙嫾鎺� `%`锛�
+
+## 3. 鐢熶骇瀹炴椂鐪嬫澘
+
+### 3.1 璇锋眰
+
+```http
+GET /home/productionRealtimeBoard
+```
+
+### 3.2 杩斿洖 `data`
+
+```json
+{
+ "deviceOee": {
+ "value": 74.00,
+ "compareYesterday": 2.50
+ },
+ "orderAchievementRate": {
+ "value": 81.30,
+ "compareYesterday": -1.20
+ },
+ "defectRate": {
+ "value": 1.40,
+ "compareYesterday": 0.30
+ }
+}
+```
+
+瀛楁璇存槑锛�
+
+- `value`锛氬綋鏃ユ寚鏍囧�硷紙0-100锛�
+- `compareYesterday`锛氳緝鏄ㄦ棩鍙樺寲鍊硷紙鍙鍙礋锛涘墠绔寜姝h礋鍐冲畾绠ご鏂瑰悜鍜岄鑹诧級
+
+## 4. 鐢熶骇璁㈠崟杩涘害
+
+### 4.1 璇锋眰
+
+```http
+GET /home/productionOrderProgress?tab=all&pageNum=1&pageSize=10
+```
+
+鍙傛暟锛�
+
+- `tab`锛歚all` / `inProgress` / `completed` / `paused`
+- `pageNum`锛氶〉鐮侊紙榛樿 `1`锛�
+- `pageSize`锛氭瘡椤垫潯鏁帮紙榛樿 `10`锛屾渶澶� `50`锛�
+
+### 4.2 杩斿洖 `data`
+
+```json
+{
+ "tab": "all",
+ "total": 24,
+ "pageNum": 1,
+ "pageSize": 10,
+ "inProgressCount": 6,
+ "completedCount": 12,
+ "pausedCount": 2,
+ "records": [
+ {
+ "orderNo": "MO-20260518-001",
+ "productName": "鏅鸿兘鎺у埗鍣�",
+ "plannedQuantity": 1000.00,
+ "completedQuantity": 860.00,
+ "completionRate": 86.00,
+ "dueDate": "2026-05-20",
+ "status": 2,
+ "statusLabel": "杩涜涓�"
+ }
+ ]
+}
+```
+
+瀛楁璇存槑锛�
+
+- `completionRate`锛氬畬鎴愮巼锛�0-100锛�
+- `status`锛氬悗绔姸鎬佺爜锛坄1`寰呭紑濮嬶紝`2`杩涜涓紝`3`宸插畬鎴愶紝`4`宸叉殏鍋滐級
+- `statusLabel`锛氱姸鎬佷腑鏂囧睍绀哄��
+
+## 5. 浠婃棩鐢熶骇璁″垝
+
+### 5.1 璇锋眰
+
+```http
+GET /home/todayProductionPlan?limit=4
+```
+
+鍙傛暟锛�
+
+- `limit`锛氳繑鍥炴潯鏁帮紙榛樿 `4`锛屾渶澶� `20`锛�
+
+### 5.2 杩斿洖 `data`
+
+```json
+{
+ "total": 9,
+ "records": [
+ {
+ "orderNo": "MO-20260518-004",
+ "productName": "缁撴瀯浠禔",
+ "plannedQuantity": 1200.00,
+ "dueDate": "2026-05-15",
+ "status": 2,
+ "statusLabel": "杩涜涓�"
+ }
+ ]
+}
+```
+
+## 6. 鍓嶇灞曠ず绾﹀畾
+
+- 鐧惧垎姣斿瓧娈电粺涓�鏄暟鍊硷紙濡� `74.00`锛夛紝鍓嶇鑷鎷兼帴 `%`銆�
+- 鎵�鏈夋暟鍊间繚鐣欎袱浣嶅皬鏁般��
+- `dueDate` 鍙兘涓� `null`锛屽墠绔渶鍏滃簳灞曠ず锛堝 `--`锛夈��
+- `compareYesterday` 姝h礋閮藉彲鑳藉嚭鐜帮紝寤鸿鎸� `>0` 涓婂崌銆乣<0` 涓嬮檷銆乣=0` 鎸佸钩澶勭悊銆�
diff --git "a/doc/20260520_\351\246\226\351\241\265\347\224\237\344\272\247\347\234\213\346\235\277\346\200\247\350\203\275\344\274\230\345\214\226\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md" "b/doc/20260520_\351\246\226\351\241\265\347\224\237\344\272\247\347\234\213\346\235\277\346\200\247\350\203\275\344\274\230\345\214\226\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..730dbf1
--- /dev/null
+++ "b/doc/20260520_\351\246\226\351\241\265\347\224\237\344\272\247\347\234\213\346\235\277\346\200\247\350\203\275\344\274\230\345\214\226\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md"
@@ -0,0 +1,107 @@
+# 棣栭〉鐢熶骇鐪嬫澘鎬ц兘浼樺寲鍓嶇鍙樻洿鏂囨。
+
+鏇存柊鏃堕棿锛�2026-05-20
+閫傜敤椤甸潰锛氶椤�
+娑夊強鍖哄潡锛�
+
+1. 鐢熶骇璁㈠崟杩涘害
+2. 浠婃棩鐢熶骇璁″垝
+
+## 1. 鏈浼樺寲鐩爣
+
+閽堝澶ф暟鎹噺鍦烘櫙锛堣鍗曟暟閲忓銆佺敓浜у巻鍙查暱锛変紭鍖栨煡璇㈡�ц兘锛岄檷浣庨椤垫帴鍙e搷搴旀椂闂村拰鍐呭瓨鍗犵敤銆�
+
+## 2. 娑夊強鎺ュ彛
+
+1. `GET /home/productionOrderProgress`
+2. `GET /home/todayProductionPlan`
+
+## 3. 鍓嶇鏄惁闇�瑕佹敼浠g爜
+
+缁撹锛�**鏃犲己鍒舵敼鍔紝鎺ュ彛鍏ュ弬涓庤繑鍥炵粨鏋勪繚鎸佸吋瀹�**銆�
+浣犵幇鏈夐〉闈㈠彲浠ョ洿鎺ヨ仈璋冿紝涓嶉渶瑕佹敼瀛楁鏄犲皠銆�
+
+## 4. 鎺ュ彛璇存槑锛堜繚鎸佷笉鍙橈級
+
+### 4.1 鐢熶骇璁㈠崟杩涘害
+
+璇锋眰锛�
+
+```http
+GET /home/productionOrderProgress?tab=all&pageNum=1&pageSize=10
+```
+
+鍙傛暟锛�
+
+- `tab`锛歚all` / `inProgress` / `completed` / `paused`
+- `pageNum`锛氶〉鐮侊紝榛樿 `1`
+- `pageSize`锛氭瘡椤垫潯鏁帮紝榛樿 `10`锛屾渶澶� `50`
+
+杩斿洖 `data`锛堢粨鏋勪笉鍙橈級锛�
+
+```json
+{
+ "tab": "all",
+ "total": 1200,
+ "pageNum": 1,
+ "pageSize": 10,
+ "inProgressCount": 180,
+ "completedCount": 900,
+ "pausedCount": 20,
+ "records": [
+ {
+ "orderNo": "MO-20260518-001",
+ "productName": "鏅鸿兘鎺у埗鍣�",
+ "plannedQuantity": 1000.00,
+ "completedQuantity": 860.00,
+ "completionRate": 86.00,
+ "dueDate": "2026-05-20",
+ "status": 2,
+ "statusLabel": "杩涜涓�"
+ }
+ ]
+}
+```
+
+### 4.2 浠婃棩鐢熶骇璁″垝
+
+璇锋眰锛�
+
+```http
+GET /home/todayProductionPlan?limit=4
+```
+
+鍙傛暟锛�
+
+- `limit`锛氳繑鍥炴潯鏁帮紝榛樿 `4`锛屾渶澶� `20`
+
+杩斿洖 `data`锛堢粨鏋勪笉鍙橈級锛�
+
+```json
+{
+ "total": 230,
+ "records": [
+ {
+ "orderNo": "MO-20260518-004",
+ "productName": "缁撴瀯浠禔",
+ "plannedQuantity": 1200.00,
+ "dueDate": "2026-05-15",
+ "status": 2,
+ "statusLabel": "杩涜涓�"
+ }
+ ]
+}
+```
+
+## 5. 鍚庣浼樺寲鐐癸紙渚涘墠绔煡鎮夛級
+
+1. 璁㈠崟杩涘害涓庝粖鏃ヨ鍒掓敼涓鸿交閲� SQL锛屼粎鏌ヨ棣栭〉蹇呴渶瀛楁銆�
+2. 鍘绘帀浜嗛椤垫煡璇㈣矾寰勪腑涓嶅繀瑕佺殑澶у叧鑱斻�佸浘鐗囧~鍏呭拰瀵硅薄瑁呴厤銆�
+3. 鐘舵�佺粺璁℃敼涓烘暟鎹簱鑱氬悎璁℃暟锛屼笉鍐嶉�愭潯鎷夊彇璁$畻銆�
+4. 鍒嗛〉涓庢潯鏁颁笂闄愪繚鐣欙紙`pageSize <= 50`, `limit <= 20`锛夈��
+
+## 6. 鍓嶇寤鸿
+
+1. 鍒囨崲 `tab` 鏃朵繚鐣欑幇鏈夎皟鐢ㄦ柟寮忓嵆鍙��
+2. `dueDate` 鍙兘涓虹┖锛岀户缁寜 `--` 鍏滃簳灞曠ず銆�
+3. 鐧惧垎姣斿瓧娈典粛涓烘暟鍊硷紝鍓嶇缁х画杩藉姞 `%` 灞曠ず銆�
diff --git "a/doc/20260521_\351\207\207\350\264\255\346\231\272\350\203\275\344\275\223\344\274\230\345\214\226\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md" "b/doc/20260521_\351\207\207\350\264\255\346\231\272\350\203\275\344\275\223\344\274\230\345\214\226\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..58089e8
--- /dev/null
+++ "b/doc/20260521_\351\207\207\350\264\255\346\231\272\350\203\275\344\275\223\344\274\230\345\214\226\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md"
@@ -0,0 +1,85 @@
+# 閲囪喘鏅鸿兘浣撲紭鍖栧墠绔彉鏇存枃妗�
+
+## 1. 鍙樻洿鑳屾櫙
+
+鏈閽堝閲囪喘鏅鸿兘浣撳仛浜嗗榻愪紭鍖栵紙鍙傝�冮攢鍞�/瀹℃壒/鍒堕�犳櫤鑳戒綋锛夛細
+
+1. 鎻愬崌 `quickPrompts` 鍛戒腑绋冲畾鎬с��
+2. 澧炲己鐩稿鏃堕棿璇嗗埆锛堜粖澶�/鏄ㄥぉ/鏈懆/涓婂懆/鏈湀/涓婃湀/浠婂勾/鍘诲勾/杩慛澶╃瓑锛夈��
+3. 澧炲姞涓氬姟鎰忓浘鏈瘑鍒椂鐨勭粨鏋勫寲鍏滃簳鍝嶅簲锛岄伩鍏嶇紪閫犳暟鎹��
+4. 琛ュ厖寰呬粯娆炬煡璇㈢殑姹囨�诲瓧娈碉紝渚夸簬鍓嶇鐩存帴娓叉煋缁熻鍗$墖銆�
+
+## 2. 鎺ュ彛褰卞搷姒傝
+
+| 鎺ュ彛 | 鏂规硶 | 鏄惁鏀硅矾寰� | 鏄惁鏀瑰叆鍙� | 鏄惁鏀硅繑鍥炵粨鏋� |
+| --- | --- | --- | --- | --- |
+| `/purchase-ai/chat` | POST(SSE) | 鍚� | 鍚� | 鏄紙鏂板鍏滃簳 JSON 绫诲瀷锛� |
+| `/purchase-ai/analyze-files` | POST(SSE) | 鍚� | 鍚� | 鍚︼紙浠呭唴閮ㄦ彁绀鸿瘝澧炲己锛� |
+
+## 3. 鏂板鍏滃簳鍝嶅簲锛堥噸鐐癸級
+
+褰撶敤鎴锋槑鏄惧湪闂噰璐笟鍔★紝浣嗘潯浠朵笉鍏呭垎涓旀湭鍛戒腑鍙墽琛屾剰鍥炬椂锛宍/purchase-ai/chat` 浼氱洿鎺ヨ繑鍥炵粨鏋勫寲 JSON锛堣�屼笉鏄嚜鐢辨枃鏈級锛�
+
+```json
+{
+ "success": false,
+ "type": "purchase_intent_not_recognized",
+ "description": "鏈瘑鍒埌鍙墽琛岀殑閲囪喘鏌ヨ鏉′欢銆備负淇濊瘉缁撴灉鍑嗙‘锛屽綋鍓嶄笉浼氭帹娴嬫垨缂栭�犳暟鎹紝璇疯ˉ鍏呮槑纭椂闂磋寖鍥淬�佷緵搴斿晢銆侀噰璐悎鍚屽彿鎴栫墿鏂欏悗鍐嶆煡璇€��",
+ "summary": {},
+ "data": {
+ "quickPrompts": [
+ "鏈湀閲囪喘閲戦鎺掑悕鍓嶅崄鐨勭墿鏂欐湁鍝簺锛�",
+ "鍝簺閲囪喘璁㈠崟杩樻湭鍏ュ簱锛�",
+ "鏈�杩�7澶╀緵搴斿晢鍒拌揣寮傚父鏈夊摢浜涳紵",
+ "甯垜缁熻寰呬粯娆鹃噰璐崟锛�",
+ "鍒楀嚭鏈湀閲囪喘閫�璐ф儏鍐�"
+ ]
+ },
+ "charts": {}
+}
+```
+
+鍓嶇澶勭悊寤鸿锛�
+
+1. 褰� `type === "purchase_intent_not_recognized"` 鏃讹紝灞曠ず `description`銆�
+2. 璇诲彇 `data.quickPrompts` 浣滀负蹇嵎鎻愰棶鎸夐挳锛堝彲鐩存帴鍥炲~杈撳叆妗嗭級銆�
+
+## 4. 寰呬粯娆捐繑鍥炴柊澧炴眹鎬诲瓧娈�
+
+鎺ュ彛绫诲瀷锛歚type = "purchase_pending_payment_list"`
+浣嶇疆锛歚summary`
+
+鏂板瀛楁锛�
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+| --- | --- | --- |
+| pendingOrderCount | number | 寰呬粯娆捐鍗曟暟 |
+| totalContractAmount | number | 寰呬粯娆捐鍗曞悎鍚屾�婚 |
+| totalPaidAmount | number | 宸蹭粯娆炬�婚 |
+| totalPendingAmount | number | 寰呬粯娆炬�婚 |
+
+璇存槑锛氬師鏈夊瓧娈典粛淇濈暀锛堝吋瀹癸級锛屾湰娆′负澧為噺瀛楁锛屼笉鐮村潖鐜版湁娓叉煋銆�
+
+## 5. 鏃堕棿鍙e緞浼樺寲
+
+閲囪喘鏅鸿兘浣撶幇鍦ㄧ粺涓�鎸変腑鍥芥椂鍖哄姩鎬佹棩鏈熸崲绠楃浉瀵规椂闂达紝鏀寔锛�
+
+- 浠婂ぉ銆佹槰澶�
+- 鏈懆銆佷笂鍛�
+- 鏈湀銆佷笂鏈�
+- 浠婂勾銆佸幓骞�
+- 杩慛澶�/鍛�/鏈�/骞淬�佽繎鍗婂勾銆佽繎鍗婁釜鏈�
+
+鍓嶇鏃犻渶鏀逛紶鍙傦紝浣嗗睍绀烘椂闂磋寖鍥存椂璇蜂互鍚庣杩斿洖 `summary.startDate/endDate/timeRange` 涓哄噯銆�
+
+## 6. 鍓嶇鑱旇皟妫�鏌ユ竻鍗�
+
+1. `chat` 娴佸紡缁撴灉鎷兼帴鍚庯紝浼樺厛鎸� JSON 瑙f瀽銆�
+2. 瑕嗙洊鏂扮被鍨� `purchase_intent_not_recognized` 鐨� UI 澶勭悊銆�
+3. 寰呬粯娆鹃〉闈㈣鍙栧苟灞曠ず `summary.totalPendingAmount` 绛夋柊澧炲瓧娈点��
+4. 楠岃瘉浠ヤ笅蹇嵎闂鍙ǔ瀹氳繑鍥炵粨鏋勫寲缁撴灉锛�
+ - 鏈湀閲囪喘閲戦鎺掑悕鍓嶅崄鐨勭墿鏂欐湁鍝簺锛�
+ - 鍝簺閲囪喘璁㈠崟杩樻湭鍏ュ簱锛�
+ - 鏈�杩�7澶╀緵搴斿晢鍒拌揣寮傚父鏈夊摢浜涳紵
+ - 甯垜缁熻寰呬粯娆鹃噰璐崟锛�
+ - 鍒楀嚭鏈湀閲囪喘閫�璐ф儏鍐�
diff --git "a/doc/20260521_\351\246\226\351\241\265HomeController\346\216\245\345\217\243\345\215\207\347\272\247\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md" "b/doc/20260521_\351\246\226\351\241\265HomeController\346\216\245\345\217\243\345\215\207\347\272\247\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..008660f
--- /dev/null
+++ "b/doc/20260521_\351\246\226\351\241\265HomeController\346\216\245\345\217\243\345\215\207\347\272\247\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md"
@@ -0,0 +1,113 @@
+# 棣栭〉 HomeController 鎺ュ彛鍗囩骇鍓嶇鍙樻洿鏂囨。
+
+鏇存柊鏃堕棿锛�2026-05-21
+閫傜敤妯″潡锛氶椤碉紙`/home`锛�
+
+## 1. 鍙樻洿姒傝
+
+鏈涓� **鍏煎寮忓崌绾�**锛屾棫璋冪敤鏂瑰紡浠嶅彲鐢ㄣ��
+閲嶇偣鏄粰鐢熶骇鐪嬫澘鎺ュ彛澧炲姞鏇存槑纭殑绛涢�夊弬鏁帮紝渚夸簬鍓嶇鎸夋棩鏈熷拰鐘舵�佹煡璇€��
+
+娑夊強鎺ュ彛锛�
+
+1. `GET /home/productionOrderProgress`
+2. `GET /home/todayProductionPlan`
+
+## 2. 鍙傛暟鍙樻洿
+
+### 2.1 鐢熶骇璁㈠崟杩涘害 `GET /home/productionOrderProgress`
+
+鏃у弬鏁帮紙浠嶅吋瀹癸級锛�
+
+- `tab`锛歚all` / `inProgress` / `completed` / `paused`
+- `pageNum`锛氶粯璁� `1`
+- `pageSize`锛氶粯璁� `10`锛屾渶澶� `50`
+
+鏂板鍙傛暟锛�
+
+- `status`锛堝彲閫夛級锛氱姸鎬佺瓫閫夛紝浼樺厛绾ч珮浜� `tab`
+ 鍙�夊�硷細`all` / `waiting` / `inProgress` / `completed` / `paused` / `1` / `2` / `3` / `4`
+- `bizDate`锛堝彲閫夛級锛氫笟鍔℃棩鏈熺瓫閫夛紝鏍煎紡 `yyyy-MM-dd`锛堟寜璁㈠崟鍒涘缓鏃堕棿杩囨护锛�
+
+鍙傛暟浼樺厛绾э細
+
+1. 濡傛灉浼犱簡 `status`锛屽悗绔紭鍏堟寜 `status` 瑙f瀽锛�
+2. 鏈紶 `status` 鏃讹紝娌跨敤鍘熸湁 `tab` 琛屼负锛�
+3. `status` 鎴� `bizDate` 鏍煎紡閿欒鏃惰繑鍥炲け璐ヤ俊鎭��
+
+璇锋眰绀轰緥锛�
+
+```http
+GET /home/productionOrderProgress?status=completed&bizDate=2026-05-20&pageNum=1&pageSize=10
+```
+
+### 2.2 浠婃棩鐢熶骇璁″垝 `GET /home/todayProductionPlan`
+
+鏃у弬鏁帮紙浠嶅吋瀹癸級锛�
+
+- `limit`锛氶粯璁� `4`锛屾渶澶� `20`
+
+鏂板鍙傛暟锛�
+
+- `planDate`锛堝彲閫夛級锛氳鍒掓棩鏈熺瓫閫夛紝鏍煎紡 `yyyy-MM-dd`锛堟寜 `plan_complete_time` 杩囨护锛�
+
+璇锋眰绀轰緥锛�
+
+```http
+GET /home/todayProductionPlan?limit=6&planDate=2026-05-21
+```
+
+## 3. 杩斿洖缁撴瀯鍙樻洿
+
+### 3.1 `productionOrderProgress` 杩斿洖鏂板瀛楁
+
+鏂板锛�
+
+- `status`锛氭爣鍑嗗寲鐘舵�佸洖鏄撅紙`all` / `waiting` / `inProgress` / `completed` / `paused`锛�
+- `bizDate`锛氭棩鏈熺瓫閫夊洖鏄撅紙鏈紶鏃朵负 `null`锛�
+- `waitingCount`锛氬緟寮�濮嬭鍗曟暟閲�
+
+鍏煎淇濈暀锛�
+
+- `tab` 瀛楁缁х画杩斿洖锛堣�侀〉闈㈡棤闇�鏀瑰姩鍙户缁娇鐢級
+
+杩斿洖绀轰緥锛�
+
+```json
+{
+ "tab": "completed",
+ "status": "completed",
+ "bizDate": "2026-05-20",
+ "total": 24,
+ "pageNum": 1,
+ "pageSize": 10,
+ "waitingCount": 3,
+ "inProgressCount": 6,
+ "completedCount": 12,
+ "pausedCount": 2,
+ "records": []
+}
+```
+
+### 3.2 `todayProductionPlan` 杩斿洖鏂板瀛楁
+
+鏂板锛�
+
+- `planDate`锛氭棩鏈熺瓫閫夊洖鏄撅紙鏈紶鏃朵负 `null`锛�
+
+杩斿洖绀轰緥锛�
+
+```json
+{
+ "planDate": "2026-05-21",
+ "total": 9,
+ "records": []
+}
+```
+
+## 4. 鍓嶇鏀归�犲缓璁�
+
+1. 鏂伴〉闈㈠缓璁紭鍏堜紶 `status`锛岄�愭鏇夸唬 `tab`銆�
+2. 闇�瑕佹寜鏃ユ湡澶嶇洏鐪嬫澘鏃讹紝浣跨敤 `bizDate` / `planDate`銆�
+3. 鑰侀〉闈㈠彲涓嶆敼锛岀户缁部鐢ㄥ師鍙傛暟涔熻兘姝e父鑱旇皟銆�
+
diff --git "a/doc/20260522_StockInRecord\345\210\227\350\241\250\346\272\220\345\215\225\345\217\267\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243.md" "b/doc/20260522_StockInRecord\345\210\227\350\241\250\346\272\220\345\215\225\345\217\267\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..56d1570
--- /dev/null
+++ "b/doc/20260522_StockInRecord\345\210\227\350\241\250\346\272\220\345\215\225\345\217\267\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243.md"
@@ -0,0 +1,75 @@
+# StockInRecord 鍒楄〃婧愬崟鍙峰墠绔仈璋冩枃妗�
+
+鏇存柊鏃堕棿锛�2026-05-22
+閫傜敤鎺ュ彛锛歚GET /stockInRecord/listPage`
+
+## 1. 鍙樻洿璇存槑
+
+鏈瀵瑰叆搴撶鐞嗗垪琛ㄦ帴鍙e鍔犺繑鍥炲瓧娈� `sourceOrderNo`锛堟簮鍗曞彿锛夛紝鐢ㄤ簬鍘熸潗鏂欏満鏅睍绀洪噰璐潵婧愬崟鍙枫��
+
+鐢熸晥鏉′欢锛�
+
+- 褰撹姹傚弬鏁� `topParentProductId = 278` 鏃讹紝鍚庣杩斿洖 `sourceOrderNo`銆�
+- 鍏朵粬 `topParentProductId` 鍦烘櫙涓嬶紝璇ュ瓧娈佃繑鍥� `null`锛堟垨涓嶅睍绀猴級銆�
+
+## 2. 瀛楁瀹氫箟
+
+鏂板瀛楁锛�
+
+- `sourceOrderNo`锛歚string`锛屾簮鍗曞彿锛堥噰璐悎鍚屽彿锛夈��
+
+## 3. 鍙栧�艰鍒�
+
+浠呭湪 `topParentProductId = 278` 鏃舵寜鈥滄潵婧愨�濊绠楋細
+
+1. 鏉ユ簮 = `閲囪喘-鍏ュ簱`锛坄recordType = 7`锛�
+ - 鍏堟寜 `recordId` 鏌ラ噰璐骇鍝佽〃 `sales_ledger_product`锛坄type=2`锛夛紱
+ - 鍐嶉�氳繃 `sales_ledger_product.sales_ledger_id` 鏌ラ噰璐彴璐﹁〃 `purchase_ledger`锛�
+ - 杩斿洖 `purchase_ledger.purchase_contract_number` 浣滀负 `sourceOrderNo`銆�
+ - 鍏煎鍏滃簳锛氳嫢鏈懡涓噰璐骇鍝侀摼璺紝鍒欐寜 `recordId` 鐩存帴鏌� `purchase_ledger.id` 鍙栧崟鍙枫��
+
+2. 鏉ユ簮 = `閲囪喘-璐ㄦ-鍚堟牸鍏ュ簱`锛坄recordType = 10`锛�
+ - 鍏堟寜 `recordId` 鏌ヨ川妫�琛� `quality_inspect`锛�
+ - 鍐嶉�氳繃 `quality_inspect.purchase_ledger_id` 鏌ラ噰璐彴璐﹁〃 `purchase_ledger`锛�
+ - 杩斿洖 `purchase_ledger.purchase_contract_number` 浣滀负 `sourceOrderNo`銆�
+
+## 4. 杩斿洖绀轰緥
+
+```json
+{
+ "code": 200,
+ "msg": "鎿嶄綔鎴愬姛",
+ "data": {
+ "records": [
+ {
+ "id": 1024,
+ "recordType": "7",
+ "productName": "閾滄帓",
+ "model": "T2-30x3",
+ "sourceOrderNo": "CG-2026-00128"
+ },
+ {
+ "id": 1025,
+ "recordType": "10",
+ "productName": "閾滄帓",
+ "model": "T2-30x3",
+ "sourceOrderNo": "CG-2026-00131"
+ }
+ ],
+ "total": 2
+ }
+}
+```
+
+## 5. 鍓嶇鑱旇皟寤鸿
+
+1. 鍒楄〃鍒楁柊澧炩�滄簮鍗曞彿鈥濓紝璇诲彇瀛楁 `sourceOrderNo`銆�
+2. 寤鸿浠呭湪 `topParentProductId = 278` 鐨勯〉闈�/绛涢�夋潯浠朵笅灞曠ず璇ュ垪銆�
+3. 褰� `sourceOrderNo` 涓虹┖鏃跺睍绀� `--`锛岄伩鍏嶇┖鐧姐��
+
+## 6. 鍥炲綊娓呭崟
+
+1. `topParentProductId=278` + `recordType=7`锛氬簲杩斿洖閲囪喘鍚堝悓鍙枫��
+2. `topParentProductId=278` + `recordType=10`锛氬簲杩斿洖閲囪喘鍚堝悓鍙凤紙缁忚川妫�閾捐矾锛夈��
+3. `topParentProductId!=278`锛歚sourceOrderNo` 搴斾负 `null` 鎴栧墠绔笉灞曠ず銆�
+4. 鍘熸湁瀛楁锛坄productName/model/unit/createBy` 绛夛級涓嶅彈褰卞搷銆�
diff --git "a/doc/20260522_StockInRecord\345\210\227\350\241\250\346\272\220\345\215\225\345\217\267\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243_276\350\241\245\345\205\205.md" "b/doc/20260522_StockInRecord\345\210\227\350\241\250\346\272\220\345\215\225\345\217\267\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243_276\350\241\245\345\205\205.md"
new file mode 100644
index 0000000..93d9b25
--- /dev/null
+++ "b/doc/20260522_StockInRecord\345\210\227\350\241\250\346\272\220\345\215\225\345\217\267\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243_276\350\241\245\345\205\205.md"
@@ -0,0 +1,65 @@
+# StockInRecord 鍒楄〃婧愬崟鍙峰墠绔仈璋冩枃妗o紙`topParentProductId=276`琛ュ厖锛�
+
+鏇存柊鏃堕棿锛�2026-05-22
+閫傜敤鎺ュ彛锛歚GET /stockInRecord/listPage`
+
+## 1. 鍙樻洿璇存槑
+
+鍦ㄥ凡鏈� `sourceOrderNo` 鍩虹涓婏紝鏂板 `topParentProductId = 276` 鐨勬簮鍗曞彿婧簮閫昏緫锛�
+
+- 鏍规嵁鈥滄潵婧愶紙recordType锛�+ recordId鈥濇函婧愶紱
+- 浼樺厛杩斿洖閿�鍞崟鍙凤紙閿�鍞悎鍚屽彿锛夛紱
+- 鑻ラ攢鍞崟鍙蜂负绌猴紝鍒欏洖閫�杩斿洖鐢熶骇璁㈠崟鍙凤紱
+- 涓嶈�冭檻鑷畾涔夊叆搴擄紙`recordType=0/9`锛夈��
+
+## 2. 杩斿洖瀛楁
+
+瀛楁鏃犳柊澧烇紝缁х画浣跨敤锛�
+
+- `sourceOrderNo`锛歚string`锛屾簮鍗曞彿銆�
+
+## 3. 276 鍦烘櫙鍙栧�艰鍒�
+
+璇锋眰鍙傛暟婊¤冻 `topParentProductId = 276` 鏃讹細
+
+1. `recordType = 14/15`锛堥攢鍞��璐�-鍚堟牸/涓嶅悎鏍煎叆搴擄級
+ - `stock_in_record.record_id -> return_sale_product.id -> return_management.shipping_id -> shipping_info.sales_ledger_id -> sales_ledger.sales_contract_no`
+ - 杩斿洖閿�鍞悎鍚屽彿銆�
+
+2. `recordType = 2/5`锛堢敓浜ф姤宸�-鍏ュ簱/鎶ュ簾锛�
+ - `stock_in_record.record_id -> production_product_main.id -> production_operation_task.production_order_id -> production_order`
+ - 鍏堝彇璇ョ敓浜ц鍗曞叧鑱旈攢鍞悎鍚屽彿锛堢敱鐢熶骇璁″垝鍏宠仈閿�鍞彴璐﹁仛鍚堬級锛�
+ - 閿�鍞悎鍚屽彿涓虹┖鏃讹紝杩斿洖 `production_order.nps_no`銆�
+
+3. `recordType = 6`锛堣川妫�-鍚堟牸鍏ュ簱锛�
+ - `stock_in_record.record_id -> quality_inspect.id -> quality_inspect.product_main_id -> production_product_main -> production_operation_task -> production_order`
+ - 鍏堝彇閿�鍞悎鍚屽彿锛岀┖鍒欏洖閫� `production_order.nps_no`銆�
+
+4. `recordType = 4/11`锛堜笉鍚堟牸澶勭悊-鎶ュ簾/璁╂鏀捐锛�
+ - `stock_in_record.record_id -> quality_unqualified.id -> quality_unqualified.inspect_id -> quality_inspect -> production_product_main -> production_operation_task -> production_order`
+ - 鍏堝彇閿�鍞悎鍚屽彿锛岀┖鍒欏洖閫� `production_order.nps_no`銆�
+
+5. `recordType = 20/22`锛堥鏂欓��鏂�/鐢熶骇閫�鏂�-鍚堟牸鍏ュ簱锛�
+ - `stock_in_record.record_id -> production_order_pick.id -> production_order`
+ - 鍏堝彇閿�鍞悎鍚屽彿锛岀┖鍒欏洖閫� `production_order.nps_no`銆�
+
+6. `recordType = 0/9`锛堣嚜瀹氫箟鍏ュ簱锛�
+ - 涓嶅弬涓庢函婧愶紝`sourceOrderNo = null`銆�
+
+## 4. 鍏朵粬鍦烘櫙璇存槑
+
+- `topParentProductId = 278` 鐨勯噰璐摼璺簮鍗曞彿閫昏緫淇濇寔涓嶅彉銆�
+- 鍏朵粬 `topParentProductId` 涓嶈Е鍙戞湰娆� 276 瑙勫垯锛宍sourceOrderNo` 涓虹┖銆�
+
+## 5. 鍓嶇鑱旇皟寤鸿
+
+1. 鍦� `topParentProductId=276` 鐨勫垪琛ㄥ満鏅睍绀衡�滄簮鍗曞彿鈥濆垪锛岃鍙� `sourceOrderNo`銆�
+2. 寤鸿绌哄�肩粺涓�灞曠ず `--`銆�
+3. 涓嶉渶瑕佹柊澧炶姹傚弬鏁帮紝娌跨敤鐜版湁 `/stockInRecord/listPage`銆�
+
+## 6. 鍥炲綊娓呭崟
+
+1. `topParentProductId=276` + `recordType=14/15`锛氬簲杩斿洖閿�鍞悎鍚屽彿銆�
+2. `topParentProductId=276` + `recordType=2/5/6/4/11/20/22`锛氫紭鍏堥攢鍞悎鍚屽彿锛岀己澶辨椂杩斿洖鐢熶骇璁㈠崟鍙枫��
+3. `topParentProductId=276` + `recordType=0/9`锛歚sourceOrderNo` 涓虹┖銆�
+4. `topParentProductId=278`锛氫粛鎸夐噰璐摼璺繑鍥為噰璐悎鍚屽彿銆�
diff --git "a/doc/20260522_\350\264\242\345\212\241\345\212\251\346\211\213\346\217\220\351\227\256\344\274\230\345\214\226\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md" "b/doc/20260522_\350\264\242\345\212\241\345\212\251\346\211\213\346\217\220\351\227\256\344\274\230\345\214\226\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..ad4656e
--- /dev/null
+++ "b/doc/20260522_\350\264\242\345\212\241\345\212\251\346\211\213\346\217\220\351\227\256\344\274\230\345\214\226\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md"
@@ -0,0 +1,59 @@
+# 璐㈠姟鍔╂墜鎻愰棶浼樺寲鍓嶇鍙樻洿鏂囨。
+
+鏇存柊鏃堕棿锛�2026-05-22
+閫傜敤妯″潡锛氳储鍔℃櫤鑳藉姪鎵嬶紙`/financial-ai`锛�
+
+## 1. 鑳屾櫙
+
+褰撳墠棣栭〉璐㈠姟鍔╂墜蹇嵎鎻愰棶涓猴細
+
+1. `鐢熸垚鏈懆缁忚惀鍛ㄦ姤`
+2. `涓轰粈涔堝埄娑︿笅闄峘
+3. `鍝釜瀹㈡埛鏈�璧氶挶`
+
+闂鐐癸細
+
+- 绗� 3 鏉¢棶娉曞湪閮ㄥ垎鍦烘櫙涓嬫剰鍥惧懡涓笉绋冲畾锛屽鏄撹蛋鏅�氭枃鏈洖绛旓紝瀵艰嚧鍥捐〃閾炬帴浠ュ師濮� Markdown 鏂囨湰灞曠ず锛堝 ``锛夈��
+- 蹇嵎鎻愰棶缂哄皯鏃堕棿鑼冨洿鍜屽垎鏋愮洰鏍囷紝缁撴灉绋冲畾鎬т笌鍙В閲婃�ц緝寮便��
+
+## 2. 鍓嶇蹇嵎鎻愰棶鏂囨浼樺寲锛堝繀鏀癸級
+
+寤鸿灏嗛粯璁や笁鏉″揩鎹锋彁闂皟鏁翠负锛�
+
+1. `鐢熸垚鏈懆缁忚惀鍛ㄦ姤锛堝埄娑︿笌鐜伴噾娴侊級`
+2. `鍒嗘瀽鏈湀鍒╂鼎涓嬮檷鍘熷洜`
+3. `杩�30澶╁摢涓鎴峰埄娑﹁础鐚渶楂榒
+
+璇存槑锛�
+
+- 涓夋潯闂硶鍧囧甫鏃堕棿鑼冨洿鎴栧垎鏋愮洰鏍囷紝鍚庣鍛戒腑鏇寸ǔ瀹氥��
+- 绗� 3 鏉′笌鈥滄渶璧氶挶瀹㈡埛鈥濊涔変竴鑷达紝浣嗏�滃埄娑﹁础鐚渶楂樷�濇洿鏄庣‘锛岄�傚悎鐩存帴椹卞姩鍒╂鼎鍒嗘瀽缁撴灉椤点��
+
+## 3. 涓庡悗绔兘鍔涙槧灏�
+
+| 蹇嵎鎻愰棶 | 棰勬湡鍛戒腑鑳藉姏 | 棰勬湡 `type` |
+| --- | --- | --- |
+| 鐢熸垚鏈懆缁忚惀鍛ㄦ姤锛堝埄娑︿笌鐜伴噾娴侊級 | 缁忚惀鎶ュ憡鐢熸垚 | `financial_operation_report` |
+| 鍒嗘瀽鏈湀鍒╂鼎涓嬮檷鍘熷洜 | 璁㈠崟鍒╂鼎鍒嗘瀽 | `financial_order_profit_analysis` |
+| 杩�30澶╁摢涓鎴峰埄娑﹁础鐚渶楂� | 璁㈠崟鍒╂鼎鍒嗘瀽 | `financial_order_profit_analysis` |
+
+鍚庣宸插悓姝ュ寮衡�滄渶璧氶挶瀹㈡埛/瀹㈡埛鍒╂鼎鏈�楂�/鍒╂鼎璐$尞鏈�楂樷�濈瓑鍚屼箟闂硶璇嗗埆锛屽墠绔寜浠ヤ笂鏂囨鏀归�犲悗鍙洿鎺ヨ仈璋冦��
+
+## 4. 鑱婂ぉ鍐呭娓叉煋鍏滃簳锛堝缓璁敼锛�
+
+閽堝鑱婂ぉ杩斿洖鏂囨湰涓嚭鐜扮殑鍥捐〃 Markdown 閾炬帴锛坄https://local/generate_chart?options=...`锛夛紝寤鸿鍓嶇澧炲姞鍏滃簳澶勭悊锛�
+
+1. 璇嗗埆 Markdown 鍥剧墖璇硶涓殑 `local/generate_chart` 閾炬帴銆�
+2. 瑙f瀽 `options` 鍙傛暟骞惰浆鎹负 ECharts `option` 鍚庢覆鏌撳浘琛ㄧ粍浠躲��
+3. 瑙f瀽澶辫触鏃朵笉灞曠ず鍘熷闀块摼鎺ユ枃鏈紝灞曠ず缁熶竴绌烘�佹彁绀恒��
+
+## 5. 鑱旇皟鍥炲綊娓呭崟
+
+1. 鐐瑰嚮蹇嵎鎻愰棶 `鐢熸垚鏈懆缁忚惀鍛ㄦ姤锛堝埄娑︿笌鐜伴噾娴侊級`
+ - 鏍¢獙杩斿洖 `type=financial_operation_report`锛屽苟姝e父娓叉煋鎽樿/寤鸿/鍥捐〃銆�
+2. 鐐瑰嚮蹇嵎鎻愰棶 `鍒嗘瀽鏈湀鍒╂鼎涓嬮檷鍘熷洜`
+ - 鏍¢獙杩斿洖 `type=financial_order_profit_analysis`锛屽苟灞曠ず浜忔崯璁㈠崟涓庡鎴峰埄娑︽帓琛屻��
+3. 鐐瑰嚮蹇嵎鎻愰棶 `杩�30澶╁摢涓鎴峰埄娑﹁础鐚渶楂榒
+ - 鏍¢獙杩斿洖 `type=financial_order_profit_analysis`锛宍summary.topCustomerByProfit` 鏈夊�笺��
+4. 鎵嬪伐杈撳叆 `鍝釜瀹㈡埛鏈�璧氶挶`銆乣鍝釜瀹㈡埛鍒╂鼎鏈�楂榒
+ - 鏍¢獙浠嶅懡涓� `financial_order_profit_analysis`锛屼笉鍐嶅嚭鐜板師濮嬪浘琛� Markdown 閾炬帴鐩村嚭銆�
diff --git "a/doc/20260522_\350\264\242\345\212\241\345\215\207\347\272\247AI\346\250\241\345\235\227\345\211\215\347\253\257\345\217\230\346\233\264\350\201\224\350\260\203\346\226\207\346\241\243.md" "b/doc/20260522_\350\264\242\345\212\241\345\215\207\347\272\247AI\346\250\241\345\235\227\345\211\215\347\253\257\345\217\230\346\233\264\350\201\224\350\260\203\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..e011374
--- /dev/null
+++ "b/doc/20260522_\350\264\242\345\212\241\345\215\207\347\272\247AI\346\250\241\345\235\227\345\211\215\347\253\257\345\217\230\346\233\264\350\201\224\350\260\203\346\226\207\346\241\243.md"
@@ -0,0 +1,150 @@
+# 璐㈠姟妯″潡鍗囩骇鍚� AI 妯″潡鍓嶇鍙樻洿鑱旇皟鏂囨。锛堥噰璐�/閿�鍞�/鐢熶骇/寰呭姙锛�
+
+鏇存柊鏃ユ湡锛�2026-05-22
+閫傜敤鑼冨洿锛歚/sales-ai`銆乣/purchase-ai`銆乣/manufacturing-ai`銆乣/xiaozhi`锛堝鎵瑰緟鍔烇級
+
+## 1. 鍙樻洿鎬昏
+
+| 妯″潡 | 瀵瑰鎺ュ彛 | 鏄惁闇�瑕佸墠绔敼閫� | 缁撹 |
+| --- | --- | --- | --- |
+| 閿�鍞� AI | `POST /sales-ai/chat` | 鏄� | 璐㈠姟鍙e緞鍒囨崲鍒版柊鏀舵妯″瀷锛岄儴鍒� `type` 鐨勫瓧娈佃涔夊彉鍖� |
+| 閲囪喘 AI | `POST /purchase-ai/chat` | 鏄� | 浠樻/鍙戠エ/寰呬粯娆捐绠楀垏鎹㈠埌鏂拌储鍔¢摼璺紝缁熻鍊间粠鍗犱綅鏀逛负鐪熷疄鍊� |
+| 鐢熶骇 AI | `POST /manufacturing-ai/chat` | 鍚� | 宸叉牳鏌ワ紝鏃犳棫璐㈠姟閫昏緫渚濊禆锛屾棤瀛楁鍙樻洿 |
+| 寰呭姙 AI | `POST /xiaozhi/chat` | 鍚� | 宸叉牳鏌ワ紝鏃犳棫璐㈠姟閫昏緫渚濊禆锛屾棤瀛楁鍙樻洿 |
+
+## 2. 閿�鍞� AI 鍙樻洿锛坄/sales-ai/chat`锛�
+
+### 2.1 `type = sales_return_list`锛堥攢鍞��娆�/鍥炴璁板綍锛�
+
+褰撳墠杩斿洖鏁版嵁鏉ユ簮缁熶竴涓烘柊璐㈠姟琛� `account_sales_collection`锛屼笉鍐嶈蛋鏃ф敹娆鹃��璐ч�昏緫銆�
+
+`data.items[]` 鍏抽敭瀛楁锛�
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+| --- | --- | --- |
+| id | number | 鏀舵璁板綍ID |
+| refundId | string | 鏄犲皠 `collectionNumber`锛屽墠绔彲缁х画浣滀负鈥滈��娆�/鍥炴鍗曞彿鈥濆睍绀� |
+| collectionNumber | string | 鏀舵鍗曞彿 |
+| paymentMethod | string | 鏀舵鏂瑰紡 |
+| actualAmount | number | 鏀舵閲戦锛堜笌 `collectionAmount` 鍚屽�硷級 |
+| collectionAmount | number | 鏀舵閲戦锛堟帹鑽愪富灞曠ず瀛楁锛� |
+| customerId | number | 瀹㈡埛ID |
+| remark | string | 澶囨敞 |
+| createTime | string | 鏀舵鏃ユ湡锛坹yyy-MM-dd锛� |
+
+`summary` 澧為噺鍏虫敞锛�
+- `returnAmount`锛氭椂闂磋寖鍥村唴閲戦姹囨�伙紙鎸� `collectionAmount` 缁熻锛�
+
+### 2.2 `type = sales_customer_interaction_list`锛堝鎴峰線鏉ワ級
+
+褰撳墠杩斿洖鍩轰簬鏂伴摼璺細
+`account_sales_collection.stock_out_record_ids -> stock_out_record(record_type=13) -> shipping_info -> sales_ledger`
+
+杩斿洖绾﹀畾锛�
+- 鏃犳暟鎹椂锛歚description = "no_customer_interactions"`
+- 鏈夋暟鎹椂锛歚description = "ok"`
+
+`summary` 鍏抽敭瀛楁锛�
+- `totalReceiptAmount`
+- `customerCount`
+
+`data.items[]` 鍏抽敭瀛楁锛�
+- `salesLedgerId`
+- `salesContractNo`
+- `customerName`
+- `projectName`
+- `receiptPaymentDate`
+- `receiptPaymentAmount`
+- `receiptPaymentType`
+- `collectionNumber`
+- `registrant`
+- `remark`
+
+### 2.3 `type = sales_ledger_list`锛堥攢鍞彴璐︼級
+
+瀛楁缁撴瀯涓嶅彉锛屼絾閲戦鍙e緞宸插垏鎹細
+- `receivedAmount` 鐢辨柊鏀舵妯″瀷姹囨�诲緱鍒帮紱
+- `pendingAmount = max(0, invoicedAmount - receivedAmount)`锛�
+- 鑻ユ敹娆捐褰曟湭鏄惧紡鍏宠仈鍙拌处锛屽垯鎸夊鎴风淮搴﹀厹搴曞綊闆嗐��
+
+鍓嶇鏀归�犲缓璁細
+- 涓嶆敼瀛楁鍚嶏紱
+- 閲嶇偣鍥炲綊鈥滃凡鏀堕噾棰�/寰呭洖娆鹃噾棰濃�濇槸鍚︿笌璐㈠姟鍙拌处涓�鑷淬��
+
+## 3. 閲囪喘 AI 鍙樻洿锛坄/purchase-ai/chat`锛�
+
+### 3.1 `type = purchase_stats`锛堥噰璐粺璁★級
+
+浠ヤ笅瀛楁宸蹭粠鍗犱綅鍊兼敼涓虹湡瀹炵粺璁″�硷細
+- `summary.paymentCount`
+- `summary.invoiceCount`
+- `summary.paymentAmount`
+- `summary.invoiceAmount`
+
+鍙戠エ閲戦鍙e緞锛�
+- 浼樺厛 `taxInclusivePrice`
+- 鑻ヤ负绌�/0锛屽垯浣跨敤 `taxExclusivelPrice + taxPrice`
+
+### 3.2 `type = purchase_pending_payment_list`锛堝緟浠樻閲囪喘鍗曪級
+
+鏍稿績璁$畻宸插垏鎹㈠埌鏂拌储鍔¢摼璺細
+
+`account_purchase_payment -> account_payment_application -> stock_in_record -> (purchase_ledger / quality_inspect) -> purchase_ledger_id`
+
+鏄犲皠瑙勫垯锛�
+1. `stock_in_record.record_type = 7`锛歚record_id` 鐩存帴瑙嗕负 `purchase_ledger_id`
+2. `stock_in_record.record_type = 10`锛氶�氳繃 `quality_inspect.id = record_id` 鍙� `quality_inspect.purchase_ledger_id`
+
+閲戦瀛楁鍙e緞锛�
+- `paidAmount`锛氭柊閾捐矾绱宸蹭粯娆鹃噾棰�
+- `pendingAmount = contractAmount - paidAmount`锛�<=0 鐨勮褰曚笉杩斿洖锛�
+
+`summary` 鍏抽敭瀛楁锛堝潎涓虹湡瀹炲�硷級锛�
+- `pendingOrderCount`
+- `totalContractAmount`
+- `totalPaidAmount`
+- `totalPendingAmount`
+
+### 3.3 鏁版嵁娓呮礂淇
+
+宸蹭慨澶� `record_type` 甯︾┖鏍煎鑷寸殑鏄犲皠涓㈠け闂锛堝悗绔粺涓� `trim()` 鍚庡啀鍒ゆ柇 `7/10`锛夈��
+
+## 4. 鐢熶骇 AI / 寰呭姙 AI 鏍告煡缁撹
+
+宸叉牳鏌ヤ互涓嬫ā鍧椾唬鐮侊紝鏈彂鐜版棫璐㈠姟閫昏緫鑰﹀悎鐐癸細
+- `ManufacturingAgentTools`锛堢敓浜э級
+- `ApproveTodoTools`锛堝緟鍔炲鎵癸級
+
+缁撹锛�
+- 瀵瑰 `type` 涓庡瓧娈电粨鏋勬棤鍙樻洿锛�
+- 鍓嶇鏃犻渶鍋氬吋瀹规敼閫狅紝浠呴渶鍋氫竴娆″洖褰掗獙璇併��
+
+## 5. 鍓嶇鑱旇皟瑕佺偣
+
+1. `/sales-ai/chat`銆乣/purchase-ai/chat` 缁х画鎸� SSE 鏂囨湰娴佹嫾鎺ュ悗鍋� JSON 瑙f瀽銆�
+2. 鎸� `type` 璺敱娓叉煋锛屼笉瑕佷粎渚濊禆 `description` 鏂囨銆�
+3. `sales_customer_interaction_list` 闇�鍏煎 `description` 鏋氫妇锛歚ok` / `no_customer_interactions`銆�
+4. `sales_return_list` 閲戦灞曠ず缁熶竴鐢� `collectionAmount`锛坄actualAmount` 淇濈暀鍏煎锛夈��
+5. `purchase_pending_payment_list` 鐨勬眹鎬诲崱鐗囪鐩存帴璇诲彇 `summary.totalPendingAmount` 绛夊瓧娈碉紝涓嶅啀鍓嶇浜屾浼扮畻銆�
+
+## 6. 鍥炲綊娓呭崟锛堝缓璁級
+
+### 閿�鍞�
+1. 鎻愰棶锛氣�滆繎30澶╁摢涓鍗曞洖娆炬渶灏戔��
+ - 鏍¢獙 `sales_ledger_list` 鐨� `receivedAmount/pendingAmount`銆�
+2. 鎻愰棶锛氣�滄煡璇㈡湰鏈堥攢鍞��娆锯��
+ - 鏍¢獙 `sales_return_list` 鐨� `collectionNumber/collectionAmount/returnAmount`銆�
+3. 鎻愰棶锛氣�滄煡璇㈡湰鏈堝鎴峰線鏉モ��
+ - 鏍¢獙 `sales_customer_interaction_list` 鐨� `totalReceiptAmount/customerCount`銆�
+
+### 閲囪喘
+1. 鎻愰棶锛氣�滅粺璁℃湰鏈堥噰璐暟鎹��
+ - 鏍¢獙 `purchase_stats` 鐨� `paymentCount/invoiceCount/paymentAmount/invoiceAmount` 闈炲浐瀹�0銆�
+2. 鎻愰棶锛氣�滃垪鍑哄緟浠樻閲囪喘鍗曗��
+ - 鏍¢獙 `purchase_pending_payment_list` 鐨� `paidAmount/pendingAmount` 涓庤储鍔″疄闄呬竴鑷淬��
+
+### 鐢熶骇/寰呭姙
+1. 鐢熶骇鎻愰棶锛氣�滄煡璇㈡湰鍛ㄨ澶囩淮淇褰曗��
+2. 寰呭姙鎻愰棶锛氣�滄煡璇㈡垜鐨勫緟瀹℃壒鍒楄〃鈥�
+ - 鏍¢獙杩斿洖缁撴瀯涓庡崌绾у墠涓�鑷达紙鏃犲瓧娈电牬鍧忥級銆�
+
diff --git "a/doc/20260522_\351\207\207\350\264\255\345\217\260\350\264\246\345\205\245\345\272\223\347\212\266\346\200\201_\351\224\200\345\224\256\344\272\247\345\223\201\345\205\245\345\272\223\345\256\241\346\240\270\347\212\266\346\200\201\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243.md" "b/doc/20260522_\351\207\207\350\264\255\345\217\260\350\264\246\345\205\245\345\272\223\347\212\266\346\200\201_\351\224\200\345\224\256\344\272\247\345\223\201\345\205\245\345\272\223\345\256\241\346\240\270\347\212\266\346\200\201\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..ae212fc
--- /dev/null
+++ "b/doc/20260522_\351\207\207\350\264\255\345\217\260\350\264\246\345\205\245\345\272\223\347\212\266\346\200\201_\351\224\200\345\224\256\344\272\247\345\223\201\345\205\245\345\272\223\345\256\241\346\240\270\347\212\266\346\200\201\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243.md"
@@ -0,0 +1,127 @@
+# 閲囪喘鍏ュ簱鐘舵�佸墠绔仈璋冩枃妗�
+鏇存柊鏃堕棿锛�2026-05-22
+閫傜敤鐗堟湰锛氭湰娆″悗绔彉鏇村悗
+
+## 1. 鍙樻洿鑼冨洿
+
+1. `GET /purchaseLedger/listPage`
+ - 鏂板鏌ヨ鏉′欢锛歚stockInStatus`锛堝叆搴撶姸鎬侊級
+ - 鏂板杩斿洖瀛楁锛歚stockInStatus`锛堝叆搴撶姸鎬侊級
+2. `GET /salesLedgerProduct/list`
+ - 鏂板杩斿洖瀛楁锛歚stockInApprovalStatus`锛堟瘡涓骇鍝佺殑鍏ュ簱瀹℃牳鐘舵�侊級
+
+---
+
+## 2. 鍏ュ簱鐘舵�佹灇涓撅紙涓ゆ帴鍙d竴鑷达級
+
+- `寰呭叆搴揱
+- `鍏ュ簱涓璥
+- `瀹屽叏鍏ュ簱`
+
+璇存槑锛氬墠绔瓫閫夊�艰鐩存帴浣跨敤浠ヤ笂涓枃鏋氫妇鍊笺��
+
+---
+
+## 3. 鎺ュ彛涓�锛歚GET /purchaseLedger/listPage`
+
+### 3.1 鏂板璇锋眰鍙傛暟
+
+- `stockInStatus`锛歚string`锛屽彲閫�
+ 鍙紶鍊硷細`寰呭叆搴揱 / `鍏ュ簱涓璥 / `瀹屽叏鍏ュ簱`
+
+### 3.2 鏂板杩斿洖瀛楁
+
+- `stockInStatus`锛歚string`锛岄噰璐彴璐︾淮搴﹀叆搴撶姸鎬�
+
+### 3.3 鐘舵�佽绠楄鍒欙紙閲囪喘鍙拌处缁村害锛�
+
+浠ヨ閲囪喘鍙拌处涓� `sales_ledger_product.type = 2` 鐨勯噰璐骇鍝佷负璁$畻鑼冨洿锛�
+
+1. 鍏ㄩ儴浜у搧閮借揪鍒扳�滃畬鍏ㄥ叆搴撯�� => 鍙拌处鐘舵�� `瀹屽叏鍏ュ簱`
+2. 鑷冲皯鏈変竴涓骇鍝佸瓨鍦ㄢ�滃鏍搁�氳繃鍏ュ簱鈥濓紝浣嗘湭鍏ㄩ儴瀹屽叏鍏ュ簱 => 鍙拌处鐘舵�� `鍏ュ簱涓璥
+3. 娌℃湁浠讳綍浜у搧瀛樺湪鈥滃鏍搁�氳繃鍏ュ簱鈥� => 鍙拌处鐘舵�� `寰呭叆搴揱
+
+鈥滃鏍搁�氳繃鍏ュ簱鈥濈粺璁″彛寰勶細`stock_in_record.approval_status = 1`锛屽苟鎸変互涓嬫潵婧愭函婧愶細
+- `record_type = 7`锛堥噰璐�-鍏ュ簱锛夛細鎸夐噰璐彴璐�+浜у搧鍏宠仈缁熻
+- `record_type = 10`锛堥噰璐�-璐ㄦ-鍚堟牸鍏ュ簱锛夛細閫氳繃 `quality_inspect` 鍥炴函鍒伴噰璐彴璐�+浜у搧缁熻
+
+### 3.4 杩斿洖绀轰緥锛堣妭閫夛級
+
+```json
+{
+ "code": 200,
+ "msg": "鎿嶄綔鎴愬姛",
+ "data": {
+ "records": [
+ {
+ "id": 1201,
+ "purchaseContractNumber": "CG20260522001",
+ "supplierName": "XX渚涘簲鍟�",
+ "stockInStatus": "鍏ュ簱涓�"
+ }
+ ],
+ "total": 1
+ }
+}
+```
+
+---
+
+## 4. 鎺ュ彛浜岋細`GET /salesLedgerProduct/list`
+
+### 4.1 鏂板杩斿洖瀛楁
+
+- `stockInApprovalStatus`锛歚string`锛屽綋鍓嶄骇鍝佽鐨勫叆搴撳鏍哥姸鎬�
+
+### 4.2 鐘舵�佽绠楄鍒欙紙浜у搧缁村害锛�
+
+浠呭綋浜у搧 `type = 2`锛堥噰璐骇鍝侊級鏃惰绠楀苟杩斿洖锛�
+
+1. 瀹℃牳閫氳繃鍏ュ簱鏁伴噺 `<= 0` => `寰呭叆搴揱
+2. 瀹℃牳閫氳繃鍏ュ簱鏁伴噺 `>= 浜у搧閲囪喘鏁伴噺` => `瀹屽叏鍏ュ簱`
+3. 鍏朵粬鎯呭喌 => `鍏ュ簱涓璥
+
+鍏朵腑鈥滃鏍搁�氳繃鍏ュ簱鏁伴噺鈥濈粺璁″悓鏍峰熀浜庯細
+- `stock_in_record.approval_status = 1`
+- 鏉ユ簮 `record_type = 7 / 10` 鐨勬函婧愬叧鑱旈�昏緫
+
+`type != 2` 鐨勪骇鍝侊紝璇ュ瓧娈佃繑鍥� `null`銆�
+
+### 4.3 杩斿洖绀轰緥锛堣妭閫夛級
+
+```json
+{
+ "code": 200,
+ "msg": "鎿嶄綔鎴愬姛",
+ "data": [
+ {
+ "id": 5566,
+ "type": 2,
+ "productCategory": "閾滄潗",
+ "specificationModel": "T2-30x3",
+ "quantity": 100,
+ "stockInApprovalStatus": "寰呭叆搴�"
+ }
+ ]
+}
+```
+
+---
+
+## 5. 鍓嶇鏀归�犲缓璁�
+
+1. 閲囪喘鍙拌处鍒楄〃鏂板鈥滃叆搴撶姸鎬佲�濈瓫閫夐」锛屽�煎浐瀹氾細`寰呭叆搴�/鍏ュ簱涓�/瀹屽叏鍏ュ簱`銆�
+2. 閲囪喘鍙拌处鍒楄〃鏂板鈥滃叆搴撶姸鎬佲�濆垪锛屽睍绀� `stockInStatus`銆�
+3. 閲囪喘浜у搧鍒楄〃鏂板鈥滃叆搴撳鏍哥姸鎬佲�濆垪锛屽睍绀� `stockInApprovalStatus`銆�
+4. 绌哄�硷紙濡� `type != 2`锛夊缓璁睍绀轰负 `--`銆�
+
+---
+
+## 6. 鑱旇皟妫�鏌ユ竻鍗�
+
+1. `/purchaseLedger/listPage` 涓嶄紶 `stockInStatus`锛氬簲姝e父杩斿洖鍏ㄩ儴鏁版嵁锛屽苟甯� `stockInStatus`銆�
+2. `/purchaseLedger/listPage?stockInStatus=寰呭叆搴揱锛氫粎杩斿洖寰呭叆搴撳彴璐︺��
+3. `/purchaseLedger/listPage?stockInStatus=鍏ュ簱涓璥锛氫粎杩斿洖鍏ュ簱涓彴璐︺��
+4. `/purchaseLedger/listPage?stockInStatus=瀹屽叏鍏ュ簱`锛氫粎杩斿洖瀹屽叏鍏ュ簱鍙拌处銆�
+5. `/salesLedgerProduct/list` 鍦ㄩ噰璐骇鍝侊紙`type=2`锛変笅杩斿洖 `stockInApprovalStatus`銆�
+6. `/salesLedgerProduct/list` 鍦ㄩ潪閲囪喘浜у搧锛坄type!=2`锛変笅 `stockInApprovalStatus` 涓� `null`銆�
diff --git "a/doc/20260522_\351\246\226\351\241\265\350\264\242\345\212\241\346\216\245\345\217\243\345\215\207\347\272\247\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md" "b/doc/20260522_\351\246\226\351\241\265\350\264\242\345\212\241\346\216\245\345\217\243\345\215\207\347\272\247\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..532eba7
--- /dev/null
+++ "b/doc/20260522_\351\246\226\351\241\265\350\264\242\345\212\241\346\216\245\345\217\243\345\215\207\347\272\247\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md"
@@ -0,0 +1,120 @@
+# 棣栭〉璐㈠姟鎺ュ彛鍗囩骇鍓嶇鍙樻洿鏂囨。
+
+鏇存柊鏃堕棿锛�2026-05-22
+閫傜敤妯″潡锛氶椤碉紙`/home`锛�
+
+## 1. 鍙樻洿姒傝
+
+鏈涓� **鍏煎寮忓崌绾�**锛屾帴鍙� URL銆佽姹傚弬鏁般�佽繑鍥炲瓧娈典繚鎸佷笉鍙樸��
+涓昏鍙樻洿鏄椤佃储鍔℃暟鎹粠鍗犱綅/鍗婃垚鍝侀�昏緫锛屽垏鎹负鎸夎储鍔$湡瀹炴暟鎹彛寰勮绠椼��
+
+娑夊強鎺ュ彛锛�
+
+1. `GET /home/statisticsReceivablePayable`
+2. `GET /home/monthlyIncome`
+3. `GET /home/monthlyExpenditure`
+
+## 2. 鍙傛暟璇存槑锛堟棤鏂板锛�
+
+### 2.1 `GET /home/statisticsReceivablePayable`
+
+- `type`锛歚1` 鏈懆锛宍2` 鏈湀锛宍3` 鏈搴︼紙榛樿 `1`锛�
+
+### 2.2 `GET /home/monthlyIncome`
+
+- 鏃犲弬鏁�
+
+### 2.3 `GET /home/monthlyExpenditure`
+
+- 鏃犲弬鏁�
+
+## 3. 杩斿洖瀛楁鍙e緞鍙樻洿
+
+### 3.1 搴旀敹搴斾粯缁熻 `statisticsReceivablePayable`
+
+杩斿洖瀛楁涓嶅彉锛�
+
+- `receivableMoney`
+- `payableMoney`
+- `advanceMoney`
+- `prepayMoney`
+
+鏂板彛寰勶細
+
+- `receivableMoney = max(閿�鍞悎鍚岄噾棰濆悎璁� - 鏀舵閲戦鍚堣, 0)`
+- `payableMoney = max(閲囪喘鍚堝悓閲戦鍚堣 - 浠樻閲戦鍚堣, 0)`
+- `advanceMoney = 鏀舵閲戦鍚堣`
+- `prepayMoney = 浠樻閲戦鍚堣`
+
+浠ヤ笂閲戦鍧囨寜 `type` 瀵瑰簲鏃堕棿鑼冨洿缁熻锛屼繚鐣欎袱浣嶅皬鏁般��
+
+杩斿洖绀轰緥锛�
+
+```json
+{
+ "receivableMoney": 128000.00,
+ "payableMoney": 76000.00,
+ "advanceMoney": 42000.00,
+ "prepayMoney": 31000.00
+}
+```
+
+### 3.2 鏈堝害鏀跺叆 `monthlyIncome`
+
+杩斿洖瀛楁涓嶅彉锛�
+
+- `monthlyIncome`
+- `collectionRate`
+- `overdueNum`
+- `overdueRate`
+
+鏂板彛寰勶細
+
+- `monthlyIncome`锛氬綋鏈堟敹娆惧悎璁�
+- `collectionRate`锛歚褰撴湀鏀舵鍚堣 / 褰撴湀閿�鍞悎鍚岄噾棰濆悎璁� * 100`
+- `overdueNum`锛氬巻鍙插簲鏀跺璐﹀崟锛坄account_statement.account_type=1`锛変腑锛屾棭浜庡綋鏈堜笖 `closing_balance > 0` 鐨勬暟閲�
+- `overdueRate`锛歚overdueNum / 鍘嗗彶搴旀敹瀵硅处鍗曟�绘暟 * 100`
+
+杩斿洖绀轰緥锛�
+
+```json
+{
+ "monthlyIncome": 89500.00,
+ "collectionRate": "62.80",
+ "overdueNum": 4,
+ "overdueRate": "18.18"
+}
+```
+
+### 3.3 鏈堝害鏀嚭 `monthlyExpenditure`
+
+杩斿洖瀛楁涓嶅彉锛�
+
+- `monthlyExpenditure`
+- `paymentRate`
+- `grossProfit`
+- `profitMarginRate`
+
+鏂板彛寰勶細
+
+- `monthlyExpenditure`锛氬綋鏈堜粯娆惧悎璁�
+- `paymentRate`锛歚褰撴湀浠樻鍚堣 / 褰撴湀閲囪喘鍚堝悓閲戦鍚堣 * 100`
+- `grossProfit`锛歚褰撴湀鏀舵鍚堣 - 褰撴湀浠樻鍚堣`
+- `profitMarginRate`锛歚grossProfit / 褰撴湀鏀舵鍚堣 * 100`
+
+杩斿洖绀轰緥锛�
+
+```json
+{
+ "monthlyExpenditure": 73400.00,
+ "paymentRate": "57.34",
+ "grossProfit": 16100.00,
+ "profitMarginRate": "17.99"
+}
+```
+
+## 4. 鍓嶇鑱旇皟璇存槑
+
+1. 鍓嶇瀛楁鏄犲皠鏃犻渶璋冩暣锛屽彲鐩存帴娌跨敤鐜版湁瑙f瀽閫昏緫銆�
+2. 鐧惧垎姣斿瓧娈典粛涓轰笉甯� `%` 鐨勫瓧绗︿覆锛屽墠绔闇�灞曠ず `%` 璇风户缁墠绔嫾鎺ャ��
+3. 鏈鍚庣杩斿洖鍊肩敱鐪熷疄璐㈠姟鏁版嵁椹卞姩锛屽缓璁噸鐐瑰洖褰掑崱鐗囨眹鎬讳笌瓒嬪娍鍥剧殑鏁板�艰仈鍔ㄣ��
diff --git "a/doc/20260523_ \345\215\217\345\220\214\345\256\241\346\211\271\346\226\260\345\242\236\345\207\272\345\267\256\346\227\266\351\227\264\345\222\214\347\273\223\346\235\237\346\227\266\351\227\264.sql" "b/doc/20260523_ \345\215\217\345\220\214\345\256\241\346\211\271\346\226\260\345\242\236\345\207\272\345\267\256\346\227\266\351\227\264\345\222\214\347\273\223\346\235\237\346\227\266\351\227\264.sql"
new file mode 100644
index 0000000..0e0c5ce
--- /dev/null
+++ "b/doc/20260523_ \345\215\217\345\220\214\345\256\241\346\211\271\346\226\260\345\242\236\345\207\272\345\267\256\346\227\266\351\227\264\345\222\214\347\273\223\346\235\237\346\227\266\351\227\264.sql"
@@ -0,0 +1,3 @@
+ALTER TABLE approve_process
+ ADD COLUMN start_date_time datetime DEFAULT NULL COMMENT '鍑哄樊寮�濮嬫椂闂�',
+ ADD COLUMN end_date_time datetime DEFAULT NULL COMMENT '鍑哄樊缁撴潫鏃堕棿';
diff --git a/doc/financial-ai-front-integration.md b/doc/financial-ai-front-integration.md
new file mode 100644
index 0000000..f632c78
--- /dev/null
+++ b/doc/financial-ai-front-integration.md
@@ -0,0 +1,192 @@
+# 璐㈠姟鏅鸿兘浣撳墠绔仈璋冩枃妗�
+
+## 1. 妯″潡璇存槑
+
+璐㈠姟鏅鸿兘浣撳悗绔凡鏂板缁熶竴鍏ュ彛 `financial-ai`锛岀敤浜庝笟璐竴浣撳寲鍒嗘瀽锛岃鐩栵細
+
+- 鏅鸿兘鎴愭湰鏍哥畻
+- 璁㈠崟鍒╂鼎鍒嗘瀽
+- 搴撳瓨璧勯噾鍒嗘瀽
+- 搴旀敹搴斾粯涓庣幇閲戞祦棰勬祴
+- 缁忚惀寮傚父棰勮
+- AI 缁忚惀椹鹃┒鑸�
+- 鏃ユ姤/鍛ㄦ姤鑷姩鐢熸垚
+- 璐㈠姟鐭ヨ瘑妫�绱紙杞婚噺 RAG 涓婁笅鏂囷級
+
+鎺ュ彛閲囩敤 **SSE 娴佸紡杈撳嚭**锛屽伐鍏峰懡涓椂杩斿洖缁撴瀯鍖� JSON 瀛楃涓层��
+
+## 2. 鎺ュ彛娓呭崟
+
+### 2.1 瀵硅瘽鎺ュ彛锛圫SE锛�
+
+- `POST /financial-ai/chat`
+- `Content-Type: application/json`
+- `Accept: text/stream;charset=utf-8`
+
+璇锋眰浣擄細
+
+```json
+{
+ "memoryId": "finance-uuid-001",
+ "message": "鏌ヨ杩�30澶╀簭鎹熻鍗�"
+}
+```
+
+瀛楁璇存槑锛�
+
+- `memoryId`锛氫細璇濆敮涓�鏍囪瘑锛堝墠绔敓鎴� UUID锛屽崟浼氳瘽澶嶇敤锛�
+- `message`锛氳嚜鐒惰瑷�闂
+
+---
+
+### 2.2 浼氳瘽鍒楄〃
+
+- `GET /financial-ai/history/sessions`
+
+---
+
+### 2.3 浼氳瘽娑堟伅
+
+- `GET /financial-ai/history/messages/{memoryId}`
+
+---
+
+### 2.4 鍒犻櫎浼氳瘽
+
+- `DELETE /financial-ai/history/{memoryId}`
+
+## 3. SSE 杩斿洖澶勭悊瑙勮寖
+
+### 3.1 杩斿洖褰㈡��
+
+- 鏅�氶棶绛旓細娴佸紡鏂囨湰鐗囨
+- 宸ュ叿鍛戒腑锛氬畬鏁� JSON 瀛楃涓诧紙閫氬父涓�娆℃�ц緭鍑猴紝涔熷彲鑳藉垎鐗囷級
+
+鍓嶇寤鸿澶勭悊娴佺▼锛�
+
+1. 灏� SSE 鍒嗙墖鎸夐『搴忔嫾鎺ユ垚 `rawText`
+2. 瀵� `rawText` 灏濊瘯 `JSON.parse`
+3. 鑻ュ彲瑙f瀽锛屾寜 `type` 鍒嗗彂娓叉煋鍥捐〃/琛ㄦ牸
+4. 鑻ヤ笉鍙В鏋愶紝鎸夋櫘閫氭枃鏈睍绀�
+
+### 3.2 缁撴瀯鍖� JSON 閫氱敤鏍煎紡
+
+```json
+{
+ "success": true,
+ "type": "financial_order_profit_analysis",
+ "description": "宸插畬鎴愯鍗曞埄娑﹀垎鏋�",
+ "summary": {},
+ "data": {},
+ "charts": {}
+}
+```
+
+瀛楁璇存槑锛�
+
+- `type`锛氱粨鏋滅被鍨嬶紙鍓嶇娓叉煋鍒嗗彂閿級
+- `summary`锛氬ご閮ㄦ寚鏍�
+- `data`锛氳〃鏍兼槑缁�/寤鸿鍒楄〃
+- `charts`锛欵Charts `option` 鏁版嵁
+
+## 4. type 涓庡墠绔〉闈㈡槧灏�
+
+寤鸿鎸� `type` 寤虹珛娓叉煋绛栫暐锛�
+
+- `financial_cost_accounting`锛氭垚鏈牳绠楅〉
+- `financial_order_profit_analysis`锛氳鍗曞埄娑﹂〉
+- `financial_inventory_capital_analysis`锛氬簱瀛樿祫閲戦〉
+- `financial_cashflow_forecast`锛氱幇閲戞祦椤�
+- `financial_business_anomaly_warning`锛氶闄╅璀﹂〉
+- `financial_business_cockpit`锛氱粡钀ラ┚椹惰埍
+- `financial_operation_report`锛氭棩鎶ュ懆鎶ラ〉
+- `financial_rag_knowledge`锛氱煡璇嗘绱�/鍙e緞璇存槑鍗$墖
+
+## 5. 鍏抽敭鏁版嵁瀛楁锛堣仈璋冮噸鐐癸級
+
+### 5.1 鎴愭湰/鍒╂鼎绫�
+
+- `data.orders[]`锛�
+ - `salesContractNo`
+ - `customerName`
+ - `revenue`
+ - `materialCost`
+ - `laborCost`
+ - `depreciationCost`
+ - `scrapCost`
+ - `totalCost`
+ - `profit`
+ - `profitRate`
+ - `riskLevel`
+ - `reasons`
+ - `suggestion`
+
+### 5.2 搴撳瓨璧勯噾绫�
+
+- `data.items[]`锛�
+ - `productName`
+ - `model`
+ - `quantity`
+ - `inventoryValue`
+ - `stagnantDays`
+ - `overstock`
+ - `riskLevel`
+
+### 5.3 鐜伴噾娴佺被
+
+- `data.actualMonthly[]` / `data.forecastMonthly[]`锛�
+ - `month`
+ - `income`
+ - `expense`
+ - `netFlow`
+- `data.receivableRiskTop[]` / `data.payablePressureTop[]`
+
+### 5.4 寮傚父棰勮绫�
+
+- `data.items[]`锛�
+ - `riskLevel`
+ - `type`
+ - `message`
+ - `detail`
+
+### 5.5 鎶ュ憡绫�
+
+- `data.headline`
+- `data.conclusions[]`
+- `data.riskSuggestions[]`
+- `data.orderProfitTop[]`
+
+## 6. 鍥捐〃鑱旇皟瑙勮寖
+
+`charts` 鍐呭瓧娈靛潎涓� ECharts `option`锛屽彲鐩存帴鍠傜粰鍥捐〃缁勪欢銆�
+
+甯歌瀛楁锛�
+
+- 鏌辩姸鍥撅細`orderProfitBarOption` / `processCostBarOption` / `inventoryValueTopOption`
+- 楗煎浘锛歚costCompositionPieOption` / `inventoryAgingPieOption` / `anomalyLevelPieOption`
+- 瓒嬪娍鍥撅細`cashFlowTrendOption`
+- 浠〃鐩橈細`fundGapGaugeOption` / `inventoryTurnoverGauge`
+
+## 7. 鎺ㄨ崘鍓嶇闂彞锛堝洖褰掓祴璇曪級
+
+1. `鏌ョ湅鏈湀缁忚惀椹鹃┒鑸盽
+2. `鏌ヨ杩�30澶╀簭鎹熻鍗昤
+3. `鍒嗘瀽杩�30澶╁簱瀛樿祫閲戝崰鐢╜
+4. `棰勬祴鏈潵3涓湀鐜伴噾娴乣
+5. `鐢熸垚鏈懆缁忚惀鍛ㄦ姤`
+6. `涓轰粈涔堝埄娑︿笅闄峘
+7. `鍝釜瀹㈡埛鏈�璧氶挶`
+8. `鍝釜宸ュ簭鎴愭湰鏈�楂榒
+
+## 8. 寮傚父涓庡厹搴曞鐞�
+
+- `memoryId` 涓虹┖锛氳繑鍥炴枃鏈� `memoryId涓嶈兘涓虹┖`
+- `message` 涓虹┖锛氳繑鍥炴枃鏈� `message涓嶈兘涓虹┖`
+- 鏃犳暟鎹満鏅細`success=true` 涓� `data.items=[]`锛屽墠绔寜绌烘�佸睍绀�
+- 闈� JSON 娴佽繑鍥烇細鎸夋櫘閫氳亰澶╂枃鏈睍绀�
+
+## 9. 鑱旇皟寤鸿
+
+1. 鍏堝仛 `type` 鍒嗗彂鍣紙淇濊瘉鎵�鏈夌粨鏋勫寲缁撴灉鍙惤鍦帮級
+2. 鍐嶅仛鎽樿鍗$墖锛坄summary`锛�+ 琛ㄦ牸锛坄data`锛�+ 鍥捐〃锛坄charts`锛�
+3. 鏈�鍚庤ˉ浼氳瘽鍘嗗彶涓庡垹闄よ兘鍔涳紝褰㈡垚瀹屾暣瀵硅瘽闂幆
diff --git a/src/main/java/com/ruoyi/CodeGenerator.java b/src/main/java/com/ruoyi/CodeGenerator.java
index 721245b..e9f7110 100644
--- a/src/main/java/com/ruoyi/CodeGenerator.java
+++ b/src/main/java/com/ruoyi/CodeGenerator.java
@@ -20,11 +20,11 @@
// 婕旂ず渚嬪瓙锛屾墽琛� main 鏂规硶鎺у埗鍙拌緭鍏ユā鍧楄〃鍚嶅洖杞﹁嚜鍔ㄧ敓鎴愬搴旈」鐩洰褰曚腑
public class CodeGenerator {
- public static String database_url = "jdbc:mysql://localhost:3300/product-inventory-management-new-pro";
+ public static String database_url = "jdbc:mysql://localhost:3306/product-inventory-management-new-pro";
public static String database_username = "root";
- public static String database_password= "root";
+ public static String database_password= "123456";
public static String author = "鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃";
- public static String model = "sales"; // 妯″潡
+ public static String model = "account"; // 妯″潡
public static String setParent = "com.ruoyi."+ model; // 鍖呰矾寰�
public static String tablePrefix = ""; // 璁剧疆杩囨护琛ㄥ墠缂�
public static void main(String[] args) {
diff --git a/src/main/java/com/ruoyi/account/bean/dto/AccountDto.java b/src/main/java/com/ruoyi/account/bean/dto/AccountDto.java
deleted file mode 100644
index 5af0ca6..0000000
--- a/src/main/java/com/ruoyi/account/bean/dto/AccountDto.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.ruoyi.account.bean.dto;
-
-import lombok.Data;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.util.List;
-
-/**
- * 璐㈠姟绠$悊--璐㈠姟鎶ヨ〃
- */
-
-@Data
-public class AccountDto implements Serializable {
-
-
- /**
- * 鎬绘敹鍏�
- */
- private BigDecimal totalIncome;
-
- /**
- * 鍚勭被鍨嬫敹鍏ラ噾棰�(閿�鍞敹鍏ワ紝鏈嶅姟鏀跺叆锛屽叾浠栨敹鍏�)
- */
- private List<AccountDto2> incomeType;
-
-
- /**
- * 鏀跺叆绗旀暟
- */
- private Long incomeNumber;
-
- /**
- * 鎬绘敮鍑�
- */
- private BigDecimal totalExpense;
-
-
- /**
- * 鍚勭被鍨嬫敮鍑洪噾棰�(鍔炲叕鐢ㄥ搧锛屽憳宸ュ伐璧勶紝宸梾璐癸紝璁惧璐圭敤锛屽叾浠�)
- */
- private List<AccountDto2> expenseType;
-
- /**
- * 鏀嚭绗旀暟
- */
- private Long expenseNumber;
-
- /**
- * 鍑�鏀跺叆
- */
- private BigDecimal netRevenue;
-
-
-
-
-}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/AccountDto2.java b/src/main/java/com/ruoyi/account/bean/dto/AccountDto2.java
deleted file mode 100644
index 7c4e9e5..0000000
--- a/src/main/java/com/ruoyi/account/bean/dto/AccountDto2.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.ruoyi.account.bean.dto;
-
-import lombok.Data;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-
-/**
- * 璐㈠姟绠$悊--璐㈠姟鎶ヨ〃(绫诲瀷)
- */
-
-@Data
-public class AccountDto2 implements Serializable {
-
-
- /**
- * 绫诲瀷
- */
- private String typeName;
-
-
- /**
- * 鐧惧垎鍗犳瘮
- */
- private BigDecimal proportion;
-
-
-
- /**
- * 閲戦
- */
- private BigDecimal account;
-
-
-
-
-
-}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/AccountDto3.java b/src/main/java/com/ruoyi/account/bean/dto/AccountDto3.java
deleted file mode 100644
index 117fa77..0000000
--- a/src/main/java/com/ruoyi/account/bean/dto/AccountDto3.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.ruoyi.account.bean.dto;
-
-import lombok.Data;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.util.List;
-
-/**
- * 璐㈠姟绠$悊--璐㈠姟鎶ヨ〃(绫诲瀷)
- */
-
-@Data
-public class AccountDto3 implements Serializable {
-
-
- /**
- * 绫诲瀷
- */
- private String typeName;
-
-
- /**
- * 鐧惧垎鍗犳瘮
- */
- private BigDecimal proportion;
-
-
-
- /**
- * 閲戦
- */
- private List<BigDecimal> account;
-
-
-
-
-
-}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/ReportDateDto.java b/src/main/java/com/ruoyi/account/bean/dto/AccountReportDto.java
similarity index 70%
rename from src/main/java/com/ruoyi/account/bean/dto/ReportDateDto.java
rename to src/main/java/com/ruoyi/account/bean/dto/AccountReportDto.java
index 5e89162..8d4bf31 100644
--- a/src/main/java/com/ruoyi/account/bean/dto/ReportDateDto.java
+++ b/src/main/java/com/ruoyi/account/bean/dto/AccountReportDto.java
@@ -1,17 +1,16 @@
package com.ruoyi.account.bean.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
-/**
- * @author :yys
- * @date : 2026/1/16 16:57
- */
+
@Data
-public class ReportDateDto {
+@Schema(name = "AccountReportDto", description = "璐㈠姟鎶ヨ〃--鏃ユ湡鍙傛暟")
+public class AccountReportDto {
/**
* 寮�濮嬫椂闂�
@@ -26,15 +25,5 @@
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate entryDateEnd;
-
- /**
- * 寮�濮嬫湀浠�
- */
- private Integer startMonth;
-
- /**
- * 缁撴潫鏈堜唤
- */
- private Integer endMonth;
}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/StatementAccountDto.java b/src/main/java/com/ruoyi/account/bean/dto/StatementAccountDto.java
new file mode 100644
index 0000000..52b6513
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/dto/StatementAccountDto.java
@@ -0,0 +1,35 @@
+package com.ruoyi.account.bean.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+
+@Data
+@Schema(name = "StatementAccountDto", description = "璐㈠姟绠$悊--鐢熸垚瀵硅处鍗�(浼犲弬)")
+public class StatementAccountDto {
+
+ //涓氬姟绫诲瀷(1搴旀敹瀵硅处;2搴斾粯瀵硅处)
+ @Schema(name = "accountType", description = "涓氬姟绫诲瀷(1搴旀敹瀵硅处;2搴斾粯瀵硅处)")
+ private Integer accountType;
+
+ //閫夋嫨鐨勫鎴�(搴旀敹鏄鎴�,搴斾粯鏄緵搴斿晢supplierId)
+ @Schema(name = "customerId", description = "瀹㈡埛ID")
+ private Long customerId;
+
+ //瀵硅处鏈堜唤yyyy-MM
+ @Schema(name = "statementMonth", description = "瀵硅处鏈堜唤")
+ private String statementMonth;
+
+ @Schema(description = "寮�濮嬫棩鏈�")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate startDate;
+
+ @Schema(description = "缁撴潫鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate endDate;
+}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/purchase/AccountPaymentApplicationDto.java b/src/main/java/com/ruoyi/account/bean/dto/purchase/AccountPaymentApplicationDto.java
new file mode 100644
index 0000000..dfe0562
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/dto/purchase/AccountPaymentApplicationDto.java
@@ -0,0 +1,34 @@
+package com.ruoyi.account.bean.dto.purchase;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+
+@Data
+@Schema(name = "AccountPaymentApplicationDto", description = "璐㈠姟绠$悊--浠樻鐢宠鍙拌处(浼犲弬)")
+public class AccountPaymentApplicationDto {
+
+ @Schema(description = "渚涘簲鍟咺D")
+ private Integer supplierId;
+
+ @Schema(description = "鐢宠鍗曞彿")
+ private String invoiceApplicationNo;
+
+ @Schema(description = "瀹℃牳鐘舵��:0寰呭鏍�1瀹℃牳閫氳繃2瀹℃牳涓嶉�氳繃")
+ private Integer status;
+
+ @Schema(description = "寮�濮嬫棩鏈�")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate startDate;
+
+ @Schema(description = "缁撴潫鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate endDate;
+
+
+}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/purchase/AccountPurchaseInvoiceDto.java b/src/main/java/com/ruoyi/account/bean/dto/purchase/AccountPurchaseInvoiceDto.java
new file mode 100644
index 0000000..3a799eb
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/dto/purchase/AccountPurchaseInvoiceDto.java
@@ -0,0 +1,32 @@
+package com.ruoyi.account.bean.dto.purchase;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+
+@Data
+@Schema(name = "AccountPurchaseInvoiceDto", description = "璐㈠姟绠$悊--杩涢」鍙戠エ鍙拌处(浼犲弬)")
+public class AccountPurchaseInvoiceDto {
+
+ @Schema(description = "渚涘簲鍟咺D")
+ private Integer supplierId;
+
+ @Schema(description = "鍙戠エ鍙风爜")
+ private String invoiceNumber;
+
+ @Schema(description = "寮�濮嬫棩鏈�")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate startDate;
+
+ @Schema(description = "缁撴潫鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate endDate;
+
+ @Schema(description = "鐘舵��")
+ private Integer status;
+}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/purchase/AccountPurchasePaymentDto.java b/src/main/java/com/ruoyi/account/bean/dto/purchase/AccountPurchasePaymentDto.java
new file mode 100644
index 0000000..f01d241
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/dto/purchase/AccountPurchasePaymentDto.java
@@ -0,0 +1,34 @@
+package com.ruoyi.account.bean.dto.purchase;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+
+@Data
+@Schema(name = "AccountPurchasePaymentDto", description = "璐㈠姟绠$悊--浠樻鍗曞彴璐�(浼犲弬)")
+public class AccountPurchasePaymentDto {
+
+ @Schema(description = "渚涘簲鍟咺D")
+ private Integer supplierId;
+
+ @Schema(description = "浠樻鍗曞彿")
+ private String paymentNumber;
+
+ @Schema(description = "浠樻鏂瑰紡")
+ private String paymentMethod;
+
+ @Schema(description = "寮�濮嬫棩鏈�")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate startDate;
+
+ @Schema(description = "缁撴潫鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate endDate;
+
+
+}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/purchase/PurchaseInboundDto.java b/src/main/java/com/ruoyi/account/bean/dto/purchase/PurchaseInboundDto.java
index 9e0a027..cec0719 100644
--- a/src/main/java/com/ruoyi/account/bean/dto/purchase/PurchaseInboundDto.java
+++ b/src/main/java/com/ruoyi/account/bean/dto/purchase/PurchaseInboundDto.java
@@ -5,7 +5,7 @@
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
-import java.util.Date;
+import java.time.LocalDate;
@Data
@Schema(name = "PurchaseInboundDto", description = "璐㈠姟绠$悊--閲囪喘鍏ュ簱鍙拌处(浼犲弬)")
@@ -14,16 +14,18 @@
@Schema(description = "鍏ュ簱鍗曞彿")
private String inboundBatches;
+ private Long supplierId;
+
@Schema(description = "渚涘簲鍟�")
private String supplierName;
@Schema(description = "寮�濮嬫棩鏈�")
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
- private Date startDate;
+ private LocalDate startDate;
@Schema(description = "缁撴潫鏃ユ湡")
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
- private Date endDate;
+ private LocalDate endDate;
}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/purchase/PurchaseReturnDto.java b/src/main/java/com/ruoyi/account/bean/dto/purchase/PurchaseReturnDto.java
index f5adae5..eb6adec 100644
--- a/src/main/java/com/ruoyi/account/bean/dto/purchase/PurchaseReturnDto.java
+++ b/src/main/java/com/ruoyi/account/bean/dto/purchase/PurchaseReturnDto.java
@@ -5,7 +5,7 @@
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
-import java.util.Date;
+import java.time.LocalDate;
@Data
@Schema(name = "PurchaseReturnDto", description = "璐㈠姟绠$悊--閲囪喘閫�璐у彴璐�(浼犲弬)")
@@ -14,16 +14,18 @@
@Schema(description = "閫�璐у崟鍙�")
private String returnNo;
+ private Long supplierId;
+
@Schema(description = "渚涘簲鍟�")
private String supplierName;
@Schema(description = "寮�濮嬫棩鏈�")
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
- private Date startDate;
+ private LocalDate startDate;
@Schema(description = "缁撴潫鏃ユ湡")
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
- private Date endDate;
+ private LocalDate endDate;
}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/sales/AccountInvoiceApplicationDto.java b/src/main/java/com/ruoyi/account/bean/dto/sales/AccountInvoiceApplicationDto.java
new file mode 100644
index 0000000..d7917f3
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/dto/sales/AccountInvoiceApplicationDto.java
@@ -0,0 +1,34 @@
+package com.ruoyi.account.bean.dto.sales;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+
+@Data
+@Schema(name = "AccountInvoiceApplicationDto", description = "璐㈠姟绠$悊--寮�绁ㄧ敵璇峰彴璐�(浼犲弬)")
+public class AccountInvoiceApplicationDto {
+
+ @Schema(description = "瀹㈡埛ID")
+ private Integer customerId;
+
+ @Schema(description = "鐢宠鍗曞彿")
+ private String invoiceApplicationNo;
+
+ @Schema(description = "瀹℃牳鐘舵��:0寰呭鏍�1瀹℃牳閫氳繃2瀹℃牳涓嶉�氳繃")
+ private Integer status;
+
+ @Schema(description = "寮�濮嬫棩鏈�")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate startDate;
+
+ @Schema(description = "缁撴潫鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate endDate;
+
+
+}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/sales/AccountSalesCollectionDto.java b/src/main/java/com/ruoyi/account/bean/dto/sales/AccountSalesCollectionDto.java
new file mode 100644
index 0000000..ec3c042
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/dto/sales/AccountSalesCollectionDto.java
@@ -0,0 +1,34 @@
+package com.ruoyi.account.bean.dto.sales;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+
+@Data
+@Schema(name = "AccountSalesCollectionDto", description = "璐㈠姟绠$悊--鏀舵鍗曞彴璐�(浼犲弬)")
+public class AccountSalesCollectionDto {
+
+ @Schema(description = "瀹㈡埛ID")
+ private Integer customerId;
+
+ @Schema(description = "鏀舵鍗曞彿")
+ private String collectionNumber;
+
+ @Schema(description = "鏀舵鏂瑰紡")
+ private String collectionMethod;
+
+ @Schema(description = "寮�濮嬫棩鏈�")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate startDate;
+
+ @Schema(description = "缁撴潫鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate endDate;
+
+
+}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/sales/AccountSalesInvoiceDto.java b/src/main/java/com/ruoyi/account/bean/dto/sales/AccountSalesInvoiceDto.java
new file mode 100644
index 0000000..4774edb
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/dto/sales/AccountSalesInvoiceDto.java
@@ -0,0 +1,33 @@
+package com.ruoyi.account.bean.dto.sales;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+
+@Data
+@Schema(name = "AccountSalesInvoiceDto", description = "璐㈠姟绠$悊--閿�椤瑰彂绁ㄥ彴璐�(浼犲弬)")
+public class AccountSalesInvoiceDto {
+
+ @Schema(description = "瀹㈡埛ID")
+ private Integer customerId;
+
+ @Schema(description = "鍙戠エ鍙风爜")
+ private String invoiceNumber;
+
+ @Schema(description = "寮�濮嬫棩鏈�")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate startDate;
+
+ @Schema(description = "缁撴潫鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate endDate;
+
+ @Schema(description = "鐘舵��")
+ private Integer status;
+
+}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/sales/SalesOutboundDto.java b/src/main/java/com/ruoyi/account/bean/dto/sales/SalesOutboundDto.java
index ba762e3..b8c9cc6 100644
--- a/src/main/java/com/ruoyi/account/bean/dto/sales/SalesOutboundDto.java
+++ b/src/main/java/com/ruoyi/account/bean/dto/sales/SalesOutboundDto.java
@@ -5,7 +5,7 @@
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
-import java.util.Date;
+import java.time.LocalDate;
@Data
@Schema(name = "SalesOutboundDto", description = "璐㈠姟绠$悊--閿�鍞嚭搴撳彴璐�(浼犲弬)")
@@ -14,16 +14,18 @@
@Schema(description = "鍑哄簱鍗曞彿")
private String outboundBatches;
+ private Long customerId;
+
@Schema(description = "瀹㈡埛鍚嶇О")
private String customerName;
@Schema(description = "寮�濮嬫棩鏈�")
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
- private Date startDate;
+ private LocalDate startDate;
@Schema(description = "缁撴潫鏃ユ湡")
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
- private Date endDate;
+ private LocalDate endDate;
}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/sales/SalesReturnDto.java b/src/main/java/com/ruoyi/account/bean/dto/sales/SalesReturnDto.java
index 1c6e266..5a239ae 100644
--- a/src/main/java/com/ruoyi/account/bean/dto/sales/SalesReturnDto.java
+++ b/src/main/java/com/ruoyi/account/bean/dto/sales/SalesReturnDto.java
@@ -5,7 +5,7 @@
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
-import java.util.Date;
+import java.time.LocalDate;
@Data
@Schema(name = "SalesReturnDto", description = "璐㈠姟绠$悊--閿�鍞��璐у彴璐�(浼犲弬)")
@@ -14,16 +14,18 @@
@Schema(description = "閫�璐у崟鍙�")
private String returnNo;
+ private Long customerId;
+
@Schema(description = "瀹㈡埛鍚嶇О")
private String customerName;
@Schema(description = "寮�濮嬫棩鏈�")
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
- private Date startDate;
+ private LocalDate startDate;
@Schema(description = "缁撴潫鏃ユ湡")
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
- private Date endDate;
+ private LocalDate endDate;
}
diff --git a/src/main/java/com/ruoyi/account/bean/vo/AccountReportVo.java b/src/main/java/com/ruoyi/account/bean/vo/AccountReportVo.java
new file mode 100644
index 0000000..f7b39d8
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/vo/AccountReportVo.java
@@ -0,0 +1,66 @@
+package com.ruoyi.account.bean.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+
+@Data
+@Schema(name = "AccountReportVo", description = "璐㈠姟鎶ヨ〃--杩斿洖鍙傛暟")
+public class AccountReportVo {
+
+ @Schema(description = "鎬昏惀鏀�")
+ private BigDecimal totalIncome;
+
+ @Schema(description = "鎬绘敮鍑�")
+ private BigDecimal totalExpense;
+
+ @Schema(description = "搴旀敹璐︽")
+ private BigDecimal accountsReceivable;
+
+ @Schema(description = "搴斾粯璐︽")
+ private BigDecimal accountsPayable;
+
+ @Schema(description = "鍑�鏀跺叆")
+ private BigDecimal netRevenue;
+
+ // --- 鎶樼嚎鍥撅細鏈堝害瓒嬪娍鏁版嵁 ---
+ @Schema(description = "鏈堝害瓒嬪娍鏁版嵁鍒楄〃")
+ private List<MonthlyTrendVO> monthlyTrendList;
+
+ // --- 鏌辩姸鍥撅細搴旀敹搴斾粯鏈堝害鏁版嵁 ---
+ @Schema(description = "搴旀敹搴斾粯鏈堝害鏁版嵁鍒楄〃")
+ private List<ReceivablePayableVO> receivablePayableList;
+
+ @Data
+ @Schema(description = "鏈堝害瓒嬪娍VO锛堟姌绾垮浘鐢級")
+ public static class MonthlyTrendVO {
+ @Schema(description = "鏈堜唤锛屾牸寮忥細yyyy-MM")
+ private String month;
+
+ @Schema(description = "褰撴湀钀ユ敹")
+ private BigDecimal income;
+
+ @Schema(description = "褰撴湀鏀嚭")
+ private BigDecimal expense;
+
+ @Schema(description = "褰撴湀鍑�鍒╂鼎")
+ private BigDecimal profit;
+ }
+
+ @Data
+ @Schema(description = "搴旀敹搴斾粯鏈堝害VO锛堟煴鐘跺浘鐢級")
+ public static class ReceivablePayableVO {
+ @Schema(description = "鏈堜唤锛屾牸寮忥細yyyy-MM")
+ private String month;
+
+ @Schema(description = "搴旀敹璐︽閲戦")
+ private BigDecimal receivable;
+
+ @Schema(description = "搴斾粯璐︽閲戦")
+ private BigDecimal payable;
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/account/bean/vo/StatementAccountVo.java b/src/main/java/com/ruoyi/account/bean/vo/StatementAccountVo.java
new file mode 100644
index 0000000..4dd073c
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/vo/StatementAccountVo.java
@@ -0,0 +1,25 @@
+package com.ruoyi.account.bean.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.ruoyi.account.pojo.AccountStatement;
+import com.ruoyi.account.pojo.AccountStatementDetails;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@Schema(name = "StatementAccountVo", description = "璐㈠姟绠$悊--瀵硅处鍗曡鎯�(杩斿洖)")
+@ExcelIgnoreUnannotated
+public class StatementAccountVo extends AccountStatement {
+
+ //瀹㈡埛鍚嶇О(搴旀敹鏄鎴�,搴斾粯鏄緵搴斿晢)
+ @Schema(description = "瀹㈡埛鍚嶇О")
+ @Excel(name = "瀹㈡埛鍚嶇О")
+ private String customerName;
+
+ //瀵硅处鏄庣粏
+ @Schema(description = "瀵硅处鏄庣粏")
+ private List<AccountStatementDetails> accountStatementDetails;
+}
diff --git a/src/main/java/com/ruoyi/account/bean/vo/purchase/AccountPaymentApplicationVo.java b/src/main/java/com/ruoyi/account/bean/vo/purchase/AccountPaymentApplicationVo.java
new file mode 100644
index 0000000..26cae0e
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/vo/purchase/AccountPaymentApplicationVo.java
@@ -0,0 +1,23 @@
+package com.ruoyi.account.bean.vo.purchase;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.ruoyi.account.pojo.purchase.AccountPaymentApplication;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+@Schema(name = "AccountPaymentApplicationVo", description = "璐㈠姟绠$悊--浠樻鐢宠鍙拌处(杩斿洖)")
+@ExcelIgnoreUnannotated
+public class AccountPaymentApplicationVo extends AccountPaymentApplication {
+
+ @Schema(description = "渚涘簲鍟嗗悕绉�")
+ @Excel(name = "渚涘簲鍟嗗悕绉�")
+ private String supplierName;
+
+ @Schema(description = "鍏ュ簱鍗曞彿")
+ @Excel(name = "鍏ュ簱鍗曞彿")
+ private String inboundBatches;
+
+
+}
diff --git a/src/main/java/com/ruoyi/account/bean/vo/purchase/AccountPurchaseInvoiceVo.java b/src/main/java/com/ruoyi/account/bean/vo/purchase/AccountPurchaseInvoiceVo.java
new file mode 100644
index 0000000..9d753b2
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/vo/purchase/AccountPurchaseInvoiceVo.java
@@ -0,0 +1,19 @@
+package com.ruoyi.account.bean.vo.purchase;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.ruoyi.account.pojo.purchase.AccountPurchaseInvoice;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+@Schema(name = "AccountPurchaseInvoiceVo", description = "璐㈠姟绠$悊--杩涢」鍙戠エ鍙拌处(杩斿洖)")
+@ExcelIgnoreUnannotated
+public class AccountPurchaseInvoiceVo extends AccountPurchaseInvoice {
+
+ @Schema(description = "渚涘簲鍟嗗悕绉�")
+ @Excel(name = "渚涘簲鍟嗗悕绉�")
+ private String supplierName;
+
+
+}
diff --git a/src/main/java/com/ruoyi/account/bean/vo/purchase/AccountPurchasePaymentVo.java b/src/main/java/com/ruoyi/account/bean/vo/purchase/AccountPurchasePaymentVo.java
new file mode 100644
index 0000000..367e17a
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/vo/purchase/AccountPurchasePaymentVo.java
@@ -0,0 +1,34 @@
+package com.ruoyi.account.bean.vo.purchase;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+@Schema(name = "AccountPurchasePaymentVo", description = "璐㈠姟绠$悊--浠樻鍗曞彴璐�(杩斿洖)")
+@ExcelIgnoreUnannotated
+public class AccountPurchasePaymentVo extends AccountPurchasePayment {
+
+ @Schema(description = "渚涘簲鍟嗗悕绉�")
+ @Excel(name = "渚涘簲鍟嗗悕绉�")
+ private String supplierName;
+
+ @Schema(description = "浠樻鐢宠鍗曞彿")
+ @Excel(name = "浠樻鐢宠鍗曞彿")
+ private String invoiceApplicationNo;
+
+ @Schema(description = "寮�鎴疯")
+ @Excel(name = "寮�鎴疯")
+ private String bankAccountName;
+
+ @Schema(description = "閾惰璐﹀彿")
+ @Excel(name = "閾惰璐﹀彿")
+ private String bankAccountNum;
+
+ @Schema(description = "鏄惁鐢熸垚浜嗗璐﹀崟")
+ private boolean isAccountStatemen;
+
+
+}
diff --git a/src/main/java/com/ruoyi/account/bean/vo/purchase/PurchaseInboundVo.java b/src/main/java/com/ruoyi/account/bean/vo/purchase/PurchaseInboundVo.java
index 2160674..48831e1 100644
--- a/src/main/java/com/ruoyi/account/bean/vo/purchase/PurchaseInboundVo.java
+++ b/src/main/java/com/ruoyi/account/bean/vo/purchase/PurchaseInboundVo.java
@@ -7,7 +7,7 @@
import lombok.Data;
import java.math.BigDecimal;
-import java.util.Date;
+import java.time.LocalDate;
@Data
@Schema(name = "PurchaseInboundVo", description = "璐㈠姟绠$悊--閲囪喘鍏ュ簱鍙拌处(杩斿洖)")
@@ -28,7 +28,7 @@
@Schema(description = "鍏ュ簱鏃ユ湡")
@Excel(name = "鍏ュ簱鏃ユ湡")
@JsonFormat(pattern = "yyyy-MM-dd")
- private Date InboundDate;
+ private LocalDate InboundDate;
@Schema(description = "浜у搧鍚嶇О")
@Excel(name = "浜у搧鍚嶇О")
diff --git a/src/main/java/com/ruoyi/account/bean/vo/sales/AccountInvoiceApplicationVo.java b/src/main/java/com/ruoyi/account/bean/vo/sales/AccountInvoiceApplicationVo.java
new file mode 100644
index 0000000..55bf22b
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/vo/sales/AccountInvoiceApplicationVo.java
@@ -0,0 +1,23 @@
+package com.ruoyi.account.bean.vo.sales;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.ruoyi.account.pojo.sales.AccountInvoiceApplication;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+@Schema(name = "AccountInvoiceApplicationVo", description = "璐㈠姟绠$悊--寮�绁ㄧ敵璇峰彴璐�(杩斿洖)")
+@ExcelIgnoreUnannotated
+public class AccountInvoiceApplicationVo extends AccountInvoiceApplication {
+
+ @Schema(description = "瀹㈡埛鍚嶇О")
+ @Excel(name = "瀹㈡埛鍚嶇О")
+ private String customerName;
+
+ @Schema(description = "鍑哄簱鍗曞彿")
+ @Excel(name = "鍑哄簱鍗曞彿")
+ private String outboundBatches;
+
+
+}
diff --git a/src/main/java/com/ruoyi/account/bean/vo/sales/AccountSalesCollectionVo.java b/src/main/java/com/ruoyi/account/bean/vo/sales/AccountSalesCollectionVo.java
new file mode 100644
index 0000000..bde5fe0
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/vo/sales/AccountSalesCollectionVo.java
@@ -0,0 +1,26 @@
+package com.ruoyi.account.bean.vo.sales;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.ruoyi.account.pojo.sales.AccountSalesCollection;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+@Schema(name = "AccountSalesCollectionVo", description = "璐㈠姟绠$悊--鏀舵鍗曞彴璐�(杩斿洖)")
+@ExcelIgnoreUnannotated
+public class AccountSalesCollectionVo extends AccountSalesCollection {
+
+ @Schema(description = "瀹㈡埛鍚嶇О")
+ @Excel(name = "瀹㈡埛鍚嶇О")
+ private String customerName;
+
+ @Schema(description = "鍑哄簱鍗曞彿")
+ @Excel(name = "鍑哄簱鍗曞彿")
+ private String outboundBatches;
+
+ @Schema(description = "鏄惁鐢熸垚浜嗗璐﹀崟")
+ private boolean isAccountStatemen;
+
+
+}
diff --git a/src/main/java/com/ruoyi/account/bean/vo/sales/AccountSalesInvoiceVo.java b/src/main/java/com/ruoyi/account/bean/vo/sales/AccountSalesInvoiceVo.java
new file mode 100644
index 0000000..1dfd4e3
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/vo/sales/AccountSalesInvoiceVo.java
@@ -0,0 +1,19 @@
+package com.ruoyi.account.bean.vo.sales;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.ruoyi.account.pojo.sales.AccountSalesInvoice;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+@Schema(name = "AccountSalesInvoiceVo", description = "璐㈠姟绠$悊--閿�椤瑰彂绁ㄥ彴璐�(杩斿洖)")
+@ExcelIgnoreUnannotated
+public class AccountSalesInvoiceVo extends AccountSalesInvoice {
+
+ @Schema(description = "瀹㈡埛鍚嶇О")
+ @Excel(name = "瀹㈡埛鍚嶇О")
+ private String customerName;
+
+
+}
diff --git a/src/main/java/com/ruoyi/account/bean/vo/sales/SalesOutboundVo.java b/src/main/java/com/ruoyi/account/bean/vo/sales/SalesOutboundVo.java
index 90d4d53..13c1b27 100644
--- a/src/main/java/com/ruoyi/account/bean/vo/sales/SalesOutboundVo.java
+++ b/src/main/java/com/ruoyi/account/bean/vo/sales/SalesOutboundVo.java
@@ -7,7 +7,7 @@
import lombok.Data;
import java.math.BigDecimal;
-import java.util.Date;
+import java.time.LocalDate;
@Data
@Schema(name = "SalesOutboundVo", description = "璐㈠姟绠$悊--閿�鍞嚭搴撳彴璐�(杩斿洖)")
@@ -28,7 +28,7 @@
@Schema(description = "鍑哄簱鏃ユ湡")
@Excel(name = "鍑哄簱鏃ユ湡")
@JsonFormat(pattern = "yyyy-MM-dd")
- private Date shippingDate;
+ private LocalDate shippingDate;
@Schema(description = "浜у搧鍚嶇О")
@Excel(name = "浜у搧鍚嶇О")
@@ -42,6 +42,9 @@
@Excel(name = "閲戦")
private BigDecimal outboundAmount;
+ @Schema(description = "绋庣巼")
+ private BigDecimal taxRate;
+
@Schema(description = "鍙戣揣缂栧彿")
@Excel(name = "鍙戣揣缂栧彿")
private String shippingNo;
diff --git a/src/main/java/com/ruoyi/account/controller/AccountExpenseController.java b/src/main/java/com/ruoyi/account/controller/AccountExpenseController.java
deleted file mode 100644
index 9d49919..0000000
--- a/src/main/java/com/ruoyi/account/controller/AccountExpenseController.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package com.ruoyi.account.controller;
-
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.account.bean.dto.ReportDateDto;
-import com.ruoyi.account.pojo.AccountExpense;
-import com.ruoyi.account.service.AccountExpenseService;
-import com.ruoyi.account.service.AccountIncomeService;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.dto.DateQueryDto;
-import com.ruoyi.framework.security.LoginUser;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import io.swagger.v3.oas.annotations.Operation;
-import jakarta.annotation.Resource;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.bind.annotation.*;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.Date;
-import java.util.List;
-
-/**
- * 璐㈠姟绠$悊--鏀嚭绠$悊
- */
-@RestController
-@RequestMapping("/account/accountExpense")
-@Tag(name = "璐㈠姟绠$悊--鏀嚭绠$悊")
-public class AccountExpenseController {
-
- @Resource
- private AccountExpenseService accountExpenseService;
-
- @Resource
- private AccountIncomeService accountIncomeService;
-
-
- /**
- * 鏂板
- * @param accountExpense
- * @return
- */
- @PostMapping("/add")
- @Operation(summary = "鏂板")
- public AjaxResult add(@RequestBody AccountExpense accountExpense) {
- accountExpense.setInputTime(new Date());
- LoginUser loginUser = SecurityUtils.getLoginUser();
- accountExpense.setInputUser(loginUser.getNickName());
- return AjaxResult.success(accountExpenseService.save(accountExpense));
- }
-
- /**
- * 鍒犻櫎
- * @param ids
- * @return
- */
- @DeleteMapping("/del")
- @Operation(summary = "鍒犻櫎")
- public AjaxResult delQualityInspect(@RequestBody List<Integer> ids) {
- if(CollectionUtils.isEmpty(ids)){
- return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
- }
- //鍒犻櫎妫�楠屽崟
- return AjaxResult.success(accountExpenseService.removeBatchByIds(ids));
- }
-
- /**
- * 淇敼
- * @param accountExpense
- * @return
- */
- @PostMapping("/update")
- @Operation(summary = "淇敼")
- public AjaxResult update(@RequestBody AccountExpense accountExpense) {
- return AjaxResult.success(accountExpenseService.updateById(accountExpense));
- }
-
- /**
- *鍒嗛〉鏌ヨ
- * @param page
- * @param accountExpense
- * @return
- */
- @GetMapping("/listPage")
- @Operation(summary = "鍒嗛〉鏌ヨ")
- public AjaxResult accountExpenseListPage(Page page, AccountExpense accountExpense) {
- return AjaxResult.success(accountExpenseService.accountExpenseListPage(page, accountExpense));
- }
-
- /**
- * 璇︽儏
- * @param id
- * @return
- */
- @GetMapping("/{id}")
- @Operation(summary = "璇︽儏")
- public AjaxResult accountExpenseDetail(@PathVariable("id") Integer id) {
- return AjaxResult.success(accountExpenseService.getById(id));
- }
-
- /**
- * 瀵煎嚭
- * @param response
- * @param accountExpense
- */
- @PostMapping("/export")
- @Operation(summary = "瀵煎嚭")
- public void accountExpenseExport(HttpServletResponse response,AccountExpense accountExpense) {
- accountExpenseService.accountExpenseExport(response, accountExpense);
- }
-
- /**
- * 璐㈠姟鎶ヨ〃鍥捐〃鏌ヨ
- * @param dateQueryDto
- * @return
- */
- @GetMapping("/report/forms")
- @Operation(summary = "璐㈠姟鎶ヨ〃鍥捐〃鏌ヨ")
- public AjaxResult report(DateQueryDto dateQueryDto) {
- return AjaxResult.success(accountExpenseService.report(dateQueryDto));
- }
-
- /**
- * 璐㈠姟鎶ヨ〃-璐㈠姟鍒嗘瀽
- * @return
- */
- @GetMapping("/report/analysis")
- @Operation(summary = "璐㈠姟鎶ヨ〃-璐㈠姟鍒嗘瀽")
- public AjaxResult analysis() {
- return AjaxResult.success(accountExpenseService.analysis());
- }
-
- /**
- * 璐㈠姟鎶ヨ〃鍥捐〃鏀跺叆骞村害鏌ヨ
- * @param
- * @return
- */
- @GetMapping("/report/income")
- @Operation(summary = "璐㈠姟鎶ヨ〃鍥捐〃鏀跺叆骞村害鏌ヨ")
- public AjaxResult reportIncome(ReportDateDto reportDateDto) {
- return AjaxResult.success(accountIncomeService.reportIncome(reportDateDto));
- }
-
- /**
- * 璐㈠姟鎶ヨ〃鍥捐〃鏀嚭骞村害鏌ヨ
- * @param
- * @return
- */
- @GetMapping("/report/expense")
- @Operation(summary = "璐㈠姟鎶ヨ〃鍥捐〃鏀嚭骞村害鏌ヨ")
- public AjaxResult reportExpense(ReportDateDto reportDateDto) {
- return AjaxResult.success(accountExpenseService.reportExpense(reportDateDto));
- }
-
-
-}
diff --git a/src/main/java/com/ruoyi/account/controller/AccountFileController.java b/src/main/java/com/ruoyi/account/controller/AccountFileController.java
deleted file mode 100644
index 42c20d1..0000000
--- a/src/main/java/com/ruoyi/account/controller/AccountFileController.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.ruoyi.account.controller;
-
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.account.pojo.AccountFile;
-import com.ruoyi.account.service.AccountFileService;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.quality.pojo.QualityInspectFile;
-import com.ruoyi.quality.service.IQualityInspectFileService;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import io.swagger.v3.oas.annotations.Operation;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.bind.annotation.*;
-
-import jakarta.annotation.Resource;
-import java.util.List;
-
-/**
- * 璐㈠姟闄勪欢
- */
-@RestController
-@RequestMapping("/account/accountFile")
-@Tag(name = "璐㈠姟闄勪欢")
-public class AccountFileController {
-
-
- @Resource
- private AccountFileService accountFileService;
-
-
- /**
- * 鏂板
- * @param accountFile
- * @return
- */
- @PostMapping("/add")
- @Operation(summary = "鏂板")
- public AjaxResult add(@RequestBody AccountFile accountFile) {
- return AjaxResult.success(accountFileService.save(accountFile));
- }
-
- /**
- * 鍒犻櫎
- * @param ids
- * @return
- */
- @DeleteMapping("/del")
- @Operation(summary = "鍒犻櫎")
- public AjaxResult delAccountFile(@RequestBody List<Integer> ids) {
- if(CollectionUtils.isEmpty(ids)){
- return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
- }
- //鍒犻櫎妫�楠岄檮浠�
- return AjaxResult.success(accountFileService.removeBatchByIds(ids));
- }
-
- /**
- *鍒嗛〉鏌ヨ
- * @param page
- * @param accountFile
- * @return
- */
- @GetMapping("/listPage")
- @Operation(summary = "鍒嗛〉鏌ヨ")
- public AjaxResult accountFileListPage(Page page, AccountFile accountFile) {
- return AjaxResult.success(accountFileService.accountFileListPage(page, accountFile));
- }
-
-
-
-
-}
diff --git a/src/main/java/com/ruoyi/account/controller/AccountIncomeController.java b/src/main/java/com/ruoyi/account/controller/AccountIncomeController.java
deleted file mode 100644
index 690e75a..0000000
--- a/src/main/java/com/ruoyi/account/controller/AccountIncomeController.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package com.ruoyi.account.controller;
-
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.account.pojo.AccountIncome;
-import com.ruoyi.account.service.AccountFileService;
-import com.ruoyi.account.service.AccountIncomeService;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.framework.security.LoginUser;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.quality.pojo.QualityInspect;
-import com.ruoyi.quality.pojo.QualityInspectFile;
-import com.ruoyi.quality.pojo.QualityInspectParam;
-import com.ruoyi.quality.service.IQualityInspectFileService;
-import com.ruoyi.quality.service.IQualityInspectParamService;
-import com.ruoyi.quality.service.IQualityInspectService;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import io.swagger.v3.oas.annotations.Operation;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.bind.annotation.*;
-
-import jakarta.annotation.Resource;
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.Date;
-import java.util.List;
-
-/**
- * 璐㈠姟绠$悊--鏀跺叆绠$悊
- */
-@RestController
-@RequestMapping("/account/accountIncome")
-@Tag(name = "璐㈠姟绠$悊--鏀跺叆绠$悊")
-public class AccountIncomeController {
-
- @Resource
- private AccountIncomeService accountIncomeService;
-
-
- /**
- * 鏂板
- * @param accountIncome
- * @return
- */
- @PostMapping("/add")
- @Operation(summary = "鏂板")
- public AjaxResult add(@RequestBody AccountIncome accountIncome) {
- accountIncome.setInputTime(new Date());
- LoginUser loginUser = SecurityUtils.getLoginUser();
- accountIncome.setInputUser(loginUser.getNickName());
- return AjaxResult.success(accountIncomeService.save(accountIncome));
- }
-
- /**
- * 鍒犻櫎
- * @param ids
- * @return
- */
- @DeleteMapping("/del")
- @Operation(summary = "鍒犻櫎")
- public AjaxResult delQualityInspect(@RequestBody List<Integer> ids) {
- if(CollectionUtils.isEmpty(ids)){
- return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
- }
- //鍒犻櫎妫�楠屽崟
- return AjaxResult.success(accountIncomeService.removeBatchByIds(ids));
- }
-
- /**
- * 淇敼
- * @param accountIncome
- * @return
- */
- @PostMapping("/update")
- @Operation(summary = "淇敼")
- public AjaxResult update(@RequestBody AccountIncome accountIncome) {
- return AjaxResult.success(accountIncomeService.updateById(accountIncome));
- }
-
- /**
- *鍒嗛〉鏌ヨ
- * @param page
- * @param accountIncome
- * @return
- */
- @GetMapping("/listPage")
- @Operation(summary = "鍒嗛〉鏌ヨ")
- public AjaxResult accountIncomeListPage(Page page, AccountIncome accountIncome) {
- return AjaxResult.success(accountIncomeService.accountIncomeListPage(page, accountIncome));
- }
-
- /**
- * 璇︽儏
- * @param id
- * @return
- */
- @GetMapping("/{id}")
- @Operation(summary = "璇︽儏")
- public AjaxResult accountIncomeDetail(@PathVariable("id") Integer id) {
- return AjaxResult.success(accountIncomeService.getById(id));
- }
-
- /**
- * 瀵煎嚭
- * @param response
- * @param accountIncome
- */
- @PostMapping("/export")
- @Operation(summary = "瀵煎嚭")
- public void accountIncomeExport(HttpServletResponse response,AccountIncome accountIncome) {
- accountIncomeService.accountIncomeExport(response, accountIncome);
- }
-
-
-}
diff --git a/src/main/java/com/ruoyi/account/controller/AccountStatementController.java b/src/main/java/com/ruoyi/account/controller/AccountStatementController.java
new file mode 100644
index 0000000..b53f457
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/controller/AccountStatementController.java
@@ -0,0 +1,71 @@
+package com.ruoyi.account.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.StatementAccountDto;
+import com.ruoyi.account.bean.vo.StatementAccountVo;
+import com.ruoyi.account.service.AccountStatementService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+
+/**
+ * <p>
+ * 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 09:42:47
+ */
+@RestController
+@RequestMapping("/accountStatement")
+@RequiredArgsConstructor
+@Tag(name = "璐㈠姟绠$悊-瀵硅处鍗�")
+public class AccountStatementController {
+
+ private final AccountStatementService accountStatementService;
+
+ @GetMapping("/getAccountStatementDetailsByMonth")
+ @Log(title = "鏍规嵁瀹㈡埛鍜屾湀浠芥煡璇㈠璐﹀崟鏄庣粏", businessType = BusinessType.OTHER)
+ @Operation(summary = "璐㈠姟绠$悊--鏍规嵁瀹㈡埛鍜屾湀浠芥煡璇㈠璐﹀崟鏄庣粏")
+ public R getAccountStatementDetailsByMonth(StatementAccountDto statementAccountDto) {
+ return R.ok(accountStatementService.getAccountStatementDetailsByMonth(statementAccountDto));
+ }
+
+ @PostMapping("/addAccountStatement")
+ @Log(title = "鏂板瀵硅处鍗�", businessType = BusinessType.INSERT)
+ @Operation(summary = "璐㈠姟绠$悊--鏂板瀵硅处鍗�")
+ public R addAccountStatement(@RequestBody StatementAccountVo statementAccountVo) {
+ return R.ok(accountStatementService.addAccountStatement(statementAccountVo));
+ }
+
+ @DeleteMapping("/deleteAccountStatement")
+ @Log(title = "鍒犻櫎瀵硅处鍗�", businessType = BusinessType.DELETE)
+ @Operation(summary = "璐㈠姟绠$悊--鍒犻櫎瀵硅处鍗�")
+ public R deleteAccountStatement(@RequestParam("ids") Long[] ids) {
+ return R.ok(accountStatementService.deleteAccountStatement(Arrays.asList(ids)));
+ }
+
+ @GetMapping("/listPageAccountStatement")
+ @Log(title = "瀵硅处鍗曞彴璐�", businessType = BusinessType.OTHER)
+ @Operation(summary = "璐㈠姟绠$悊--瀵硅处鍗曞彴璐�")
+ public R<IPage<StatementAccountVo>> listPageAccountStatement(Page page, StatementAccountDto statementAccountDto) {
+ IPage<StatementAccountVo> listPage = accountStatementService.listPageAccountStatement(page,statementAccountDto);
+ return R.ok(listPage);
+ }
+
+ @PostMapping("/exportAccountStatement")
+ @Operation(summary = "瀵煎嚭瀵硅处鍗曟枃浠�")
+ @Log(title = "瀵煎嚭瀵硅处鍗曟枃浠�", businessType = BusinessType.EXPORT)
+ public void exportAccountStatement(HttpServletResponse response, StatementAccountDto statementAccountDto) {
+ accountStatementService.exportAccountStatement(response,statementAccountDto);
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/account/controller/AccountingController.java b/src/main/java/com/ruoyi/account/controller/AccountingController.java
index 4688942..9eeb208 100644
--- a/src/main/java/com/ruoyi/account/controller/AccountingController.java
+++ b/src/main/java/com/ruoyi/account/controller/AccountingController.java
@@ -1,12 +1,16 @@
package com.ruoyi.account.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.account.service.impl.AccountingServiceImpl;
+import com.ruoyi.account.bean.dto.AccountReportDto;
+import com.ruoyi.account.service.AccountingService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.v3.oas.annotations.tags.Tag;
+import com.ruoyi.framework.web.domain.R;
import io.swagger.v3.oas.annotations.Operation;
-import lombok.AllArgsConstructor;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@@ -19,11 +23,11 @@
@Tag(name = "浼氳鏍哥畻")
@RestController
@RequestMapping("/accounting")
-@AllArgsConstructor
+@RequiredArgsConstructor
public class AccountingController extends BaseController {
- private AccountingServiceImpl accountingService;
+ private final AccountingService accountingService;
@Operation(summary = "鎬昏")
@GetMapping("/total")
@@ -43,4 +47,14 @@
return accountingService.calculateDepreciation(page,year);
}
+ /*****************************************璐㈠姟鎶ヨ〃******************************************************************************/
+
+ @GetMapping("/accountStatementDetailsByMonth")
+ @Log(title = "璐㈠姟鎶ヨ〃", businessType = BusinessType.OTHER)
+ @Operation(summary = "璐㈠姟鎶ヨ〃")
+ public R getAccountStatementDetailsByMonth(AccountReportDto accountReportDto) {
+ return R.ok(accountingService.getAccountStatementDetailsByMonth(accountReportDto));
+ }
+
+
}
diff --git a/src/main/java/com/ruoyi/account/controller/BorrowInfoController.java b/src/main/java/com/ruoyi/account/controller/BorrowInfoController.java
deleted file mode 100644
index 7620c19..0000000
--- a/src/main/java/com/ruoyi/account/controller/BorrowInfoController.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.ruoyi.account.controller;
-
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.account.pojo.BorrowInfo;
-import com.ruoyi.account.service.BorrowInfoService;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import io.swagger.v3.oas.annotations.Operation;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.*;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.List;
-
-/**
- * <p>
- * 鍊熸淇℃伅琛� 鍓嶇鎺у埗鍣�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-15 02:57:29
- */
-@Tag(name = "鍊熸淇℃伅琛�")
-@RestController
-@RequestMapping("/borrowInfo")
-@AllArgsConstructor
-public class BorrowInfoController {
-
- private BorrowInfoService borrowInfoService;
-
- @GetMapping("/listPage")
- @Operation(summary = "鍒嗛〉鏌ヨ")
- public AjaxResult listPage(Page page, BorrowInfo borrowInfo) {
- return borrowInfoService.listPage(page,borrowInfo);
- }
-
- /**
- * 鏂板
- */
- @PostMapping("/add")
- @Transactional(rollbackFor = Exception.class)
- @Log(title = "鏂板鍊熸淇℃伅", businessType = BusinessType.INSERT)
- public AjaxResult add(@RequestBody BorrowInfo borrowInfo) {
- return borrowInfoService.add(borrowInfo);
- }
-
- /**
- * 淇敼
- */
- @PostMapping("/update")
- @Transactional(rollbackFor = Exception.class)
- @Log(title = "淇敼鍊熸淇℃伅", businessType = BusinessType.UPDATE)
- public AjaxResult updateBorrowInfo(@RequestBody BorrowInfo borrowInfo) {
- return borrowInfoService.updateBorrowInfo(borrowInfo);
- }
-
-
- /**
- * 鍒犻櫎
- */
- @DeleteMapping("/delete")
- @Transactional(rollbackFor = Exception.class)
- @Log(title = "鍒犻櫎鍊熸淇℃伅", businessType = BusinessType.DELETE)
- public AjaxResult delete(@RequestBody List<Long> ids) {
- return borrowInfoService.delete(ids);
- }
-
- /**
- * 瀵煎嚭
- */
- @PostMapping("/export")
- @Operation(summary = "瀵煎嚭鍊熸淇℃伅")
- public void export(HttpServletResponse response, BorrowInfo borrowInfo) {
- List<BorrowInfo> list = borrowInfoService.list();
- ExcelUtil<BorrowInfo> util = new ExcelUtil<>(BorrowInfo.class);
- util.exportExcel(response,list, "鍊熸淇℃伅鏁版嵁");
- }
-
-
-}
diff --git a/src/main/java/com/ruoyi/account/controller/purchase/AccountPaymentApplicationController.java b/src/main/java/com/ruoyi/account/controller/purchase/AccountPaymentApplicationController.java
new file mode 100644
index 0000000..423d0ef
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/controller/purchase/AccountPaymentApplicationController.java
@@ -0,0 +1,86 @@
+package com.ruoyi.account.controller.purchase;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.purchase.AccountPaymentApplicationDto;
+import com.ruoyi.account.bean.vo.purchase.AccountPaymentApplicationVo;
+import com.ruoyi.account.pojo.purchase.AccountPaymentApplication;
+import com.ruoyi.account.service.purchase.AccountPaymentApplicationService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--浠樻鐢宠 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 03:44:22
+ */
+@RestController
+@RequestMapping("/accountPaymentApplication")
+@Tag(name = "璐㈠姟绠$悊--浠樻鐢宠")
+@RequiredArgsConstructor
+public class AccountPaymentApplicationController {
+
+ private final AccountPaymentApplicationService accountPaymentApplicationService;
+
+ @GetMapping("/listPageAccountPaymentApplication")
+ @Log(title = "浠樻鐢宠鍙拌处", businessType = BusinessType.OTHER)
+ @Operation(summary = "璐㈠姟绠$悊--浠樻鐢宠鍙拌处")
+ public R<IPage<AccountPaymentApplicationVo>> listPageAccountPaymentApplication(Page page, AccountPaymentApplicationDto accountPaymentApplicationDto) {
+ IPage<AccountPaymentApplicationVo> listPage = accountPaymentApplicationService.listPageAccountPaymentApplication(page,accountPaymentApplicationDto);
+ return R.ok(listPage);
+ }
+
+ @GetMapping("/getInboundBatchesBySupplier")
+ @Log(title = "鏍规嵁渚涘簲鍟嗘煡璇㈠叆搴撳崟鍙�(浠樻鐢宠)", businessType = BusinessType.OTHER)
+ @Operation(summary = "璐㈠姟绠$悊--鏍规嵁渚涘簲鍟嗘煡璇㈠叆搴撳崟鍙�(浠樻鐢宠)")
+ public R getInboundBatchesBySupplier(Integer supplierId) {
+ return R.ok(accountPaymentApplicationService.getInboundBatchesBySupplier(supplierId));
+ }
+
+ @PostMapping("/addAccountPaymentApplication")
+ @Log(title = "鏂板浠樻鐢宠", businessType = BusinessType.INSERT)
+ @Operation(summary = "璐㈠姟绠$悊--鏂板浠樻鐢宠")
+ public R addAccountPaymentApplication(@RequestBody AccountPaymentApplication accountPaymentApplication) {
+ return R.ok(accountPaymentApplicationService.addAccountPaymentApplication(accountPaymentApplication));
+ }
+
+ @PutMapping("/updateAccountPaymentApplication")
+ @Log(title = "淇敼浠樻鐢宠", businessType = BusinessType.UPDATE)
+ @Operation(summary = "璐㈠姟绠$悊--淇敼浠樻鐢宠")
+ public R updateAccountPaymentApplication(@RequestBody AccountPaymentApplication accountPaymentApplication) {
+ return R.ok(accountPaymentApplicationService.updateById(accountPaymentApplication));
+ }
+
+ @PutMapping("/auditAccountPaymentApplication")
+ @Log(title = "瀹℃牳浠樻鐢宠", businessType = BusinessType.UPDATE)
+ @Operation(summary = "璐㈠姟绠$悊--瀹℃牳浠樻鐢宠")
+ public R auditAccountPaymentApplication(@RequestBody AccountPaymentApplication accountPaymentApplication) {
+ return R.ok(accountPaymentApplicationService.updateById(accountPaymentApplication));
+ }
+
+ @DeleteMapping("/deleteAccountPaymentApplication")
+ @Log(title = "鍒犻櫎浠樻鐢宠", businessType = BusinessType.DELETE)
+ @Operation(summary = "璐㈠姟绠$悊--鍒犻櫎浠樻鐢宠")
+ public R deleteAccountPaymentApplication(@RequestParam("ids") Long[] ids) {
+ return R.ok(accountPaymentApplicationService.deleteAccountPaymentApplication(Arrays.asList(ids)));
+ }
+
+ @PostMapping("/exportAccountPaymentApplication")
+ @Operation(summary = "瀵煎嚭浠樻鐢宠鏂囦欢")
+ @Log(title = "瀵煎嚭浠樻鐢宠鏂囦欢", businessType = BusinessType.EXPORT)
+ public void exportAccountPaymentApplication(HttpServletResponse response, AccountPaymentApplicationDto accountPaymentApplicationDto) {
+ accountPaymentApplicationService.exportAccountPaymentApplication(response,accountPaymentApplicationDto);
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/account/controller/purchase/AccountPurchaseInvoiceController.java b/src/main/java/com/ruoyi/account/controller/purchase/AccountPurchaseInvoiceController.java
new file mode 100644
index 0000000..c755aad
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/controller/purchase/AccountPurchaseInvoiceController.java
@@ -0,0 +1,79 @@
+package com.ruoyi.account.controller.purchase;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.purchase.AccountPurchaseInvoiceDto;
+import com.ruoyi.account.bean.vo.purchase.AccountPurchaseInvoiceVo;
+import com.ruoyi.account.pojo.purchase.AccountPurchaseInvoice;
+import com.ruoyi.account.service.purchase.AccountPurchaseInvoiceService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--杩涢」鍙戠エ 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 03:06:17
+ */
+@RestController
+@RequestMapping("/accountPurchaseInvoice")
+@Tag(name = "璐㈠姟绠$悊--杩涢」鍙戠エ")
+@RequiredArgsConstructor
+public class AccountPurchaseInvoiceController {
+
+ private final AccountPurchaseInvoiceService accountPurchaseInvoiceService;
+
+ @GetMapping("/listPageAccountPurchaseInvoice")
+ @Log(title = "杩涢」鍙戠エ鍙拌处", businessType = BusinessType.OTHER)
+ @Operation(summary = "璐㈠姟绠$悊--杩涢」鍙戠エ鍙拌处")
+ public R<IPage<AccountPurchaseInvoiceVo>> listPageAccountPurchaseInvoice(Page page, AccountPurchaseInvoiceDto accountPurchaseInvoiceDto) {
+ IPage<AccountPurchaseInvoiceVo> listPage = accountPurchaseInvoiceService.listPageAccountPurchaseInvoice(page,accountPurchaseInvoiceDto);
+ return R.ok(listPage);
+ }
+
+ @GetMapping("/getInboundBatchesBySupplier")
+ @Log(title = "鏍规嵁渚涘簲鍟嗘煡璇㈠叆搴撳崟鍙�(杩涢」鍙戠エ)", businessType = BusinessType.OTHER)
+ @Operation(summary = "璐㈠姟绠$悊--鏍规嵁渚涘簲鍟嗘煡璇㈠叆搴撳崟鍙�(杩涢」鍙戠エ)")
+ public R getInboundBatchesBySupplier(Integer supplierId) {
+ return R.ok(accountPurchaseInvoiceService.getInboundBatchesBySupplier(supplierId));
+ }
+
+ @PostMapping("/addAccountPurchaseInvoice")
+ @Log(title = "鏂板杩涢」鍙戠エ", businessType = BusinessType.INSERT)
+ @Operation(summary = "璐㈠姟绠$悊--鏂板杩涢」鍙戠エ")
+ public R addAccountPurchaseInvoice(@RequestBody AccountPurchaseInvoice accountPurchaseInvoice) {
+ return R.ok(accountPurchaseInvoiceService.save(accountPurchaseInvoice));
+ }
+
+ @PutMapping("/cancelAccountPurchaseInvoice")
+ @Log(title = "浣滃簾杩涢」鍙戠エ", businessType = BusinessType.INSERT)
+ @Operation(summary = "璐㈠姟绠$悊--浣滃簾閿�椤瑰彂绁�")
+ public R cancelAccountPurchaseInvoice(@RequestBody AccountPurchaseInvoice accountPurchaseInvoice) {
+ return R.ok(accountPurchaseInvoiceService.updateById(accountPurchaseInvoice));
+ }
+
+ @DeleteMapping("/deleteAccountPurchaseInvoice")
+ @Log(title = "鍒犻櫎杩涢」鍙戠エ", businessType = BusinessType.DELETE)
+ @Operation(summary = "璐㈠姟绠$悊--鍒犻櫎杩涢」鍙戠エ")
+ public R deleteAccountPurchaseInvoice(@RequestParam("ids") Long[] ids) {
+ return R.ok(accountPurchaseInvoiceService.deleteAccountPurchaseInvoice(Arrays.asList(ids)));
+ }
+
+ @PostMapping("/exportAccountPurchaseInvoice")
+ @Operation(summary = "瀵煎嚭杩涢」鍙戠エ鏂囦欢")
+ @Log(title = "瀵煎嚭杩涢」鍙戠エ鏂囦欢", businessType = BusinessType.EXPORT)
+ public void exportAccountPurchaseInvoice(HttpServletResponse response, AccountPurchaseInvoiceDto accountPurchaseInvoiceDto) {
+ accountPurchaseInvoiceService.exportAccountPurchaseInvoice(response,accountPurchaseInvoiceDto);
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/account/controller/purchase/AccountPurchasePaymentController.java b/src/main/java/com/ruoyi/account/controller/purchase/AccountPurchasePaymentController.java
new file mode 100644
index 0000000..c73e547
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/controller/purchase/AccountPurchasePaymentController.java
@@ -0,0 +1,71 @@
+package com.ruoyi.account.controller.purchase;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.purchase.AccountPurchasePaymentDto;
+import com.ruoyi.account.bean.vo.purchase.AccountPurchasePaymentVo;
+import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
+import com.ruoyi.account.service.purchase.AccountPurchasePaymentService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--浠樻鍗� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 04:14:51
+ */
+@RestController
+@RequestMapping("/accountPurchasePayment")
+@Tag(name = "璐㈠姟绠$悊--浠樻鍗�")
+@RequiredArgsConstructor
+public class AccountPurchasePaymentController {
+
+ private final AccountPurchasePaymentService accountPurchasePaymentService;
+
+ @GetMapping("/listPageAccountPurchasePayment")
+ @Log(title = "浠樻鍗曞彴璐�", businessType = BusinessType.OTHER)
+ @Operation(summary = "璐㈠姟绠$悊--浠樻鍗曞彴璐�")
+ public R<IPage<AccountPurchasePaymentVo>> listPageAccountPurchasePayment(Page page, AccountPurchasePaymentDto accountPurchasePaymentDto) {
+ IPage<AccountPurchasePaymentVo> listPage = accountPurchasePaymentService.listPageAccountPurchasePayment(page,accountPurchasePaymentDto);
+ return R.ok(listPage);
+ }
+
+ @PostMapping("/addAccountPurchasePayment")
+ @Log(title = "鏂板浠樻鍗�", businessType = BusinessType.INSERT)
+ @Operation(summary = "璐㈠姟绠$悊--鏂板浠樻鍗�")
+ public R addAccountPurchasePayment(@RequestBody AccountPurchasePayment accountPurchasePayment) {
+ return R.ok(accountPurchasePaymentService.addAccountPurchasePayment(accountPurchasePayment));
+ }
+
+ @PutMapping("/updateAccountPurchasePayment")
+ @Log(title = "缂栬緫浠樻鍗�", businessType = BusinessType.UPDATE)
+ @Operation(summary = "璐㈠姟绠$悊--缂栬緫浠樻鍗�")
+ public R updateAccountPurchasePayment(@RequestBody AccountPurchasePayment accountPurchasePayment) {
+ return R.ok(accountPurchasePaymentService.updateById(accountPurchasePayment));
+ }
+
+ @DeleteMapping("/deleteAccountPurchasePayment")
+ @Log(title = "鍒犻櫎浠樻鍗�", businessType = BusinessType.DELETE)
+ @Operation(summary = "璐㈠姟绠$悊--鍒犻櫎浠樻鍗�")
+ public R deleteAccountPurchasePayment(@RequestParam("ids") Long[] ids) {
+ return R.ok(accountPurchasePaymentService.deleteAccountPurchasePayment(Arrays.asList(ids)));
+ }
+
+ @PostMapping("/exportAccountPurchasePayment")
+ @Operation(summary = "瀵煎嚭浠樻鍗曟枃浠�")
+ @Log(title = "瀵煎嚭浠樻鍗曟枃浠�", businessType = BusinessType.EXPORT)
+ public void exportAccountPurchasePayment(HttpServletResponse response, AccountPurchasePaymentDto accountPurchasePaymentDto) {
+ accountPurchasePaymentService.exportAccountPurchasePayment(response,accountPurchasePaymentDto);
+ }
+}
diff --git a/src/main/java/com/ruoyi/account/controller/sales/AccountInvoiceApplicationController.java b/src/main/java/com/ruoyi/account/controller/sales/AccountInvoiceApplicationController.java
new file mode 100644
index 0000000..00b490f
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/controller/sales/AccountInvoiceApplicationController.java
@@ -0,0 +1,86 @@
+package com.ruoyi.account.controller.sales;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.sales.AccountInvoiceApplicationDto;
+import com.ruoyi.account.bean.vo.sales.AccountInvoiceApplicationVo;
+import com.ruoyi.account.pojo.sales.AccountInvoiceApplication;
+import com.ruoyi.account.service.sales.AccountInvoiceApplicationService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--寮�绁ㄧ敵璇� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 01:38:32
+ */
+@RestController
+@RequestMapping("/accountInvoiceApplication")
+@Tag(name = "璐㈠姟绠$悊--寮�绁ㄧ敵璇�")
+@RequiredArgsConstructor
+public class AccountInvoiceApplicationController {
+
+ private final AccountInvoiceApplicationService accountInvoiceApplicationService;
+
+ @GetMapping("/listPageAccountInvoiceApplication")
+ @Log(title = "寮�绁ㄧ敵璇峰彴璐�", businessType = BusinessType.OTHER)
+ @Operation(summary = "璐㈠姟绠$悊--寮�绁ㄧ敵璇峰彴璐�")
+ public R<IPage<AccountInvoiceApplicationVo>> listPageAccountInvoiceApplication(Page page, AccountInvoiceApplicationDto accountInvoiceApplicationDto) {
+ IPage<AccountInvoiceApplicationVo> listPage = accountInvoiceApplicationService.listPageAccountInvoiceApplication(page,accountInvoiceApplicationDto);
+ return R.ok(listPage);
+ }
+
+ @GetMapping("/getOutboundBatchesByCustomer")
+ @Log(title = "鏍规嵁瀹㈡埛鏌ヨ鍑哄簱鍗曞彿(寮�绁ㄧ敵璇�)", businessType = BusinessType.OTHER)
+ @Operation(summary = "璐㈠姟绠$悊--鏍规嵁瀹㈡埛鏌ヨ鍑哄簱鍗曞彿(寮�绁ㄧ敵璇�)")
+ public R getOutboundBatchesByCustomer(Integer customerId) {
+ return R.ok(accountInvoiceApplicationService.getOutboundBatchesByCustomer(customerId));
+ }
+
+ @PostMapping("/addAccountInvoiceApplication")
+ @Log(title = "鏂板寮�绁ㄧ敵璇�", businessType = BusinessType.INSERT)
+ @Operation(summary = "璐㈠姟绠$悊--鏂板寮�绁ㄧ敵璇�")
+ public R addAccountInvoiceApplication(@RequestBody AccountInvoiceApplication accountInvoiceApplication) {
+ return R.ok(accountInvoiceApplicationService.addAccountInvoiceApplication(accountInvoiceApplication));
+ }
+
+ @PutMapping("/updateAccountInvoiceApplication")
+ @Log(title = "淇敼寮�绁ㄧ敵璇�", businessType = BusinessType.UPDATE)
+ @Operation(summary = "璐㈠姟绠$悊--淇敼寮�绁ㄧ敵璇�")
+ public R updateAccountInvoiceApplication(@RequestBody AccountInvoiceApplication accountInvoiceApplication) {
+ return R.ok(accountInvoiceApplicationService.updateById(accountInvoiceApplication));
+ }
+
+ @PutMapping("/auditAccountInvoiceApplication")
+ @Log(title = "瀹℃牳寮�绁ㄧ敵璇�", businessType = BusinessType.UPDATE)
+ @Operation(summary = "璐㈠姟绠$悊--瀹℃牳寮�绁ㄧ敵璇�")
+ public R auditAccountInvoiceApplication(@RequestBody AccountInvoiceApplication accountInvoiceApplication) {
+ return R.ok(accountInvoiceApplicationService.updateById(accountInvoiceApplication));
+ }
+
+ @DeleteMapping("/deleteAccountInvoiceApplication")
+ @Log(title = "鍒犻櫎寮�绁ㄧ敵璇�", businessType = BusinessType.DELETE)
+ @Operation(summary = "璐㈠姟绠$悊--鍒犻櫎寮�绁ㄧ敵璇�")
+ public R deleteAccountInvoiceApplication(@RequestParam("ids") Long[] ids) {
+ return R.ok(accountInvoiceApplicationService.deleteAccountInvoiceApplication(Arrays.asList(ids)));
+ }
+
+ @PostMapping("/exportAccountInvoiceApplication")
+ @Operation(summary = "瀵煎嚭寮�绁ㄧ敵璇锋枃浠�")
+ @Log(title = "瀵煎嚭寮�绁ㄧ敵璇锋枃浠�", businessType = BusinessType.EXPORT)
+ public void exportAccountInvoiceApplication(HttpServletResponse response, AccountInvoiceApplicationDto accountInvoiceApplicationDto) {
+ accountInvoiceApplicationService.exportAccountInvoiceApplication(response,accountInvoiceApplicationDto);
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/account/controller/sales/AccountSalesCollectionController.java b/src/main/java/com/ruoyi/account/controller/sales/AccountSalesCollectionController.java
new file mode 100644
index 0000000..6ab1f2a
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/controller/sales/AccountSalesCollectionController.java
@@ -0,0 +1,79 @@
+package com.ruoyi.account.controller.sales;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.sales.AccountSalesCollectionDto;
+import com.ruoyi.account.bean.vo.sales.AccountSalesCollectionVo;
+import com.ruoyi.account.pojo.sales.AccountSalesCollection;
+import com.ruoyi.account.service.sales.AccountSalesCollectionService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--鏀舵鍗� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:49:56
+ */
+@RestController
+@RequestMapping("/accountSalesCollection")
+@Tag(name = "璐㈠姟绠$悊--鏀舵鍗�")
+@RequiredArgsConstructor
+public class AccountSalesCollectionController {
+
+ private final AccountSalesCollectionService accountSalesCollectionService;
+
+ @GetMapping("/listPageAccountSalesCollection")
+ @Log(title = "鏀舵鍗曞彴璐�", businessType = BusinessType.OTHER)
+ @Operation(summary = "璐㈠姟绠$悊--鏀舵鍗曞彴璐�")
+ public R<IPage<AccountSalesCollectionVo>> listPageAccountSalesCollection(Page page, AccountSalesCollectionDto accountSalesCollectionDto) {
+ IPage<AccountSalesCollectionVo> listPage = accountSalesCollectionService.listPageAccountSalesCollection(page,accountSalesCollectionDto);
+ return R.ok(listPage);
+ }
+
+ @GetMapping("/getOutboundBatchesByCustomer")
+ @Log(title = "鏍规嵁瀹㈡埛鏌ヨ鍑哄簱鍗曞彿(鏀舵鍗�)", businessType = BusinessType.OTHER)
+ @Operation(summary = "璐㈠姟绠$悊--鏍规嵁瀹㈡埛鏌ヨ鍑哄簱鍗曞彿(鏀舵鍗�)")
+ public R getOutboundBatchesByCustomer(Integer customerId) {
+ return R.ok(accountSalesCollectionService.getOutboundBatchesByCustomer(customerId));
+ }
+
+ @PostMapping("/addAccountSalesCollection")
+ @Log(title = "鏂板鏀舵鍗�", businessType = BusinessType.INSERT)
+ @Operation(summary = "璐㈠姟绠$悊--鏂板鏀舵鍗�")
+ public R addAccountSalesCollection(@RequestBody AccountSalesCollection accountSalesCollection) {
+ return R.ok(accountSalesCollectionService.addAccountSalesCollection(accountSalesCollection));
+ }
+
+ @PutMapping("/updateAccountSalesCollection")
+ @Log(title = "缂栬緫鏀舵鍗�", businessType = BusinessType.UPDATE)
+ @Operation(summary = "璐㈠姟绠$悊--缂栬緫鏀舵鍗�")
+ public R updateAccountSalesCollection(@RequestBody AccountSalesCollection accountSalesCollection) {
+ return R.ok(accountSalesCollectionService.updateById(accountSalesCollection));
+ }
+
+ @DeleteMapping("/deleteAccountSalesCollection")
+ @Log(title = "鍒犻櫎鏀舵鍗�", businessType = BusinessType.DELETE)
+ @Operation(summary = "璐㈠姟绠$悊--鍒犻櫎鏀舵鍗�")
+ public R deleteAccountSalesCollection(@RequestParam("ids") Long[] ids) {
+ return R.ok(accountSalesCollectionService.deleteAccountSalesCollection(Arrays.asList(ids)));
+ }
+
+ @PostMapping("/exportAccountSalesCollection")
+ @Operation(summary = "瀵煎嚭鏀舵鍗曟枃浠�")
+ @Log(title = "瀵煎嚭鏀舵鍗曟枃浠�", businessType = BusinessType.EXPORT)
+ public void exportAccountSalesCollection(HttpServletResponse response, AccountSalesCollectionDto accountSalesCollectionDto) {
+ accountSalesCollectionService.exportAccountSalesCollection(response,accountSalesCollectionDto);
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/account/controller/sales/AccountSalesInvoiceController.java b/src/main/java/com/ruoyi/account/controller/sales/AccountSalesInvoiceController.java
new file mode 100644
index 0000000..05c13b0
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/controller/sales/AccountSalesInvoiceController.java
@@ -0,0 +1,72 @@
+package com.ruoyi.account.controller.sales;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.sales.AccountSalesInvoiceDto;
+import com.ruoyi.account.bean.vo.sales.AccountSalesInvoiceVo;
+import com.ruoyi.account.pojo.sales.AccountSalesInvoice;
+import com.ruoyi.account.service.sales.AccountSalesInvoiceService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--閿�椤瑰彂绁� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:10:20
+ */
+@RestController
+@RequestMapping("/accountSalesInvoice")
+@Tag(name = "璐㈠姟绠$悊--閿�椤瑰彂绁�")
+@RequiredArgsConstructor
+public class AccountSalesInvoiceController {
+
+ private final AccountSalesInvoiceService accountSalesInvoiceService;
+
+ @GetMapping("/listPageAccountSalesInvoice")
+ @Log(title = "閿�椤瑰彂绁ㄥ彴璐�", businessType = BusinessType.OTHER)
+ @Operation(summary = "璐㈠姟绠$悊--閿�椤瑰彂绁ㄥ彴璐�")
+ public R<IPage<AccountSalesInvoiceVo>> listPageAccountSalesInvoice(Page page, AccountSalesInvoiceDto accountSalesInvoiceDto) {
+ IPage<AccountSalesInvoiceVo> listPage = accountSalesInvoiceService.listPageAccountSalesInvoice(page,accountSalesInvoiceDto);
+ return R.ok(listPage);
+ }
+
+ @PostMapping("/addAccountSalesInvoice")
+ @Log(title = "鏂板閿�椤瑰彂绁�", businessType = BusinessType.INSERT)
+ @Operation(summary = "璐㈠姟绠$悊--鏂板閿�椤瑰彂绁�")
+ public R addAccountSalesInvoice(@RequestBody AccountSalesInvoice accountSalesInvoice) {
+ return R.ok(accountSalesInvoiceService.save(accountSalesInvoice));
+ }
+
+ @PutMapping("/cancelAccountSalesInvoice")
+ @Log(title = "浣滃簾閿�椤瑰彂绁�", businessType = BusinessType.INSERT)
+ @Operation(summary = "璐㈠姟绠$悊--浣滃簾閿�椤瑰彂绁�")
+ public R cancelAccountSalesInvoice(@RequestBody AccountSalesInvoice accountSalesInvoice) {
+ return R.ok(accountSalesInvoiceService.updateById(accountSalesInvoice));
+ }
+
+ @DeleteMapping("/deleteAccountSalesInvoice")
+ @Log(title = "鍒犻櫎閿�椤瑰彂绁�", businessType = BusinessType.DELETE)
+ @Operation(summary = "璐㈠姟绠$悊--鍒犻櫎閿�椤瑰彂绁�")
+ public R deleteAccountSalesInvoice(@RequestParam("ids") Long[] ids) {
+ return R.ok(accountSalesInvoiceService.deleteAccountSalesInvoice(Arrays.asList(ids)));
+ }
+
+ @PostMapping("/exportAccountSalesInvoice")
+ @Operation(summary = "瀵煎嚭閿�椤瑰彂绁ㄦ枃浠�")
+ @Log(title = "瀵煎嚭閿�椤瑰彂绁ㄦ枃浠�", businessType = BusinessType.EXPORT)
+ public void exportAccountSalesInvoice(HttpServletResponse response, AccountSalesInvoiceDto accountSalesInvoiceDto) {
+ accountSalesInvoiceService.exportAccountSalesInvoice(response,accountSalesInvoiceDto);
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/account/mapper/AccountExpenseMapper.java b/src/main/java/com/ruoyi/account/mapper/AccountExpenseMapper.java
deleted file mode 100644
index 4876e7b..0000000
--- a/src/main/java/com/ruoyi/account/mapper/AccountExpenseMapper.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.ruoyi.account.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.account.bean.dto.AccountDto;
-import com.ruoyi.account.bean.dto.AccountDto2;
-import com.ruoyi.account.pojo.AccountExpense;
-import com.ruoyi.account.pojo.AccountIncome;
-import com.ruoyi.dto.DateQueryDto;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-import com.ruoyi.home.dto.IncomeExpenseAnalysisDto;
-
-import java.math.BigDecimal;
-import java.util.List;
-import java.util.Map;
-
-@Mapper
-public interface AccountExpenseMapper extends BaseMapper<AccountExpense> {
- IPage<AccountExpense> accountExpenseListPage(Page page, @Param("accountExpense") AccountExpense accountExpense);
-
- List<AccountExpense> accountExpenseExport(@Param("accountExpense") AccountExpense accountExpense);
-
-
- List<AccountDto2> report(@Param("dateQueryDto") DateQueryDto dateQueryDto);
- BigDecimal report1(@Param("dateQueryDto") DateQueryDto dateQueryDto, @Param("dictValue") String dictValue);
-
- List<IncomeExpenseAnalysisDto> selectAccountExpenseStats(@Param("startDate") String startDate, @Param("endDate") String endDate, @Param("dateFormat") String dateFormat);
-
- List<com.ruoyi.dto.MapDto> selectExpenseComposition(@Param("startDate") String startDate, @Param("endDate") String endDate);
-}
diff --git a/src/main/java/com/ruoyi/account/mapper/AccountFileMapper.java b/src/main/java/com/ruoyi/account/mapper/AccountFileMapper.java
deleted file mode 100644
index d5b55be..0000000
--- a/src/main/java/com/ruoyi/account/mapper/AccountFileMapper.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.ruoyi.account.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.account.pojo.AccountFile;
-import com.ruoyi.quality.pojo.QualityInspectFile;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-@Mapper
-public interface AccountFileMapper extends BaseMapper<AccountFile> {
-
- IPage<AccountFile> accountFileListPage(Page page, @Param("accountFile") AccountFile accountFile);
-}
diff --git a/src/main/java/com/ruoyi/account/mapper/AccountIncomeMapper.java b/src/main/java/com/ruoyi/account/mapper/AccountIncomeMapper.java
deleted file mode 100644
index 9bb3f3a..0000000
--- a/src/main/java/com/ruoyi/account/mapper/AccountIncomeMapper.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.ruoyi.account.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.account.bean.dto.AccountDto2;
-import com.ruoyi.account.pojo.AccountFile;
-import com.ruoyi.account.pojo.AccountIncome;
-import com.ruoyi.dto.DateQueryDto;
-import com.ruoyi.home.dto.IncomeExpenseAnalysisDto;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-import java.math.BigDecimal;
-import java.util.List;
-import java.util.Map;
-
-@Mapper
-public interface AccountIncomeMapper extends BaseMapper<AccountIncome> {
-
- IPage<AccountIncome> accountIncomeListPage(Page page, @Param("accountIncome") AccountIncome accountIncome);
-
- List<AccountIncome> accountIncomeExport(@Param("accountIncome") AccountIncome accountIncome);
-
- List<AccountDto2> report(@Param("dateQueryDto") DateQueryDto dateQueryDto);
- BigDecimal report1(@Param("dateQueryDto") DateQueryDto dateQueryDto, @Param("dictValue") String dictValue);
-
- List<IncomeExpenseAnalysisDto> selectIncomeStats(@Param("startDate") String startDate, @Param("endDate") String endDate, @Param("dateFormat") String dateFormat);
-
-}
diff --git a/src/main/java/com/ruoyi/account/mapper/AccountStatementDetailsMapper.java b/src/main/java/com/ruoyi/account/mapper/AccountStatementDetailsMapper.java
new file mode 100644
index 0000000..7b6e72f
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/mapper/AccountStatementDetailsMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.account.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.account.pojo.AccountStatementDetails;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--瀵硅处鍗曟槑缁� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 10:12:42
+ */
+@Mapper
+public interface AccountStatementDetailsMapper extends BaseMapper<AccountStatementDetails> {
+
+}
diff --git a/src/main/java/com/ruoyi/account/mapper/AccountStatementMapper.java b/src/main/java/com/ruoyi/account/mapper/AccountStatementMapper.java
new file mode 100644
index 0000000..89730cb
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/mapper/AccountStatementMapper.java
@@ -0,0 +1,28 @@
+package com.ruoyi.account.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.StatementAccountDto;
+import com.ruoyi.account.bean.vo.StatementAccountVo;
+import com.ruoyi.account.pojo.AccountStatement;
+import com.ruoyi.purchase.dto.VatDto;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 09:42:47
+ */
+@Mapper
+public interface AccountStatementMapper extends BaseMapper<AccountStatement> {
+
+
+ IPage<StatementAccountVo> listPageAccountStatement(Page page, @Param("req") StatementAccountDto statementAccountDto);
+
+ IPage<VatDto> selectVatDtoPage(Page page, @Param("month") String month);
+}
diff --git a/src/main/java/com/ruoyi/account/mapper/BorrowInfoMapper.java b/src/main/java/com/ruoyi/account/mapper/BorrowInfoMapper.java
deleted file mode 100644
index bcac543..0000000
--- a/src/main/java/com/ruoyi/account/mapper/BorrowInfoMapper.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.account.mapper;
-
-import com.ruoyi.account.pojo.BorrowInfo;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import org.apache.ibatis.annotations.Mapper;
-
-/**
- * <p>
- * 鍊熸淇℃伅琛� Mapper 鎺ュ彛
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-15 02:57:29
- */
-@Mapper
-public interface BorrowInfoMapper extends BaseMapper<BorrowInfo> {
-
-}
diff --git a/src/main/java/com/ruoyi/account/mapper/purchase/AccountPaymentApplicationMapper.java b/src/main/java/com/ruoyi/account/mapper/purchase/AccountPaymentApplicationMapper.java
new file mode 100644
index 0000000..f6d90f9
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/mapper/purchase/AccountPaymentApplicationMapper.java
@@ -0,0 +1,32 @@
+package com.ruoyi.account.mapper.purchase;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.purchase.AccountPaymentApplicationDto;
+import com.ruoyi.account.bean.vo.purchase.AccountPaymentApplicationVo;
+import com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo;
+import com.ruoyi.account.pojo.purchase.AccountPaymentApplication;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--浠樻鐢宠 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 03:44:22
+ */
+@Mapper
+public interface AccountPaymentApplicationMapper extends BaseMapper<AccountPaymentApplication> {
+
+ IPage<AccountPaymentApplicationVo> listPageAccountPaymentApplication(Page page, @Param("req") AccountPaymentApplicationDto accountPaymentApplicationDto);
+
+ List<PurchaseInboundVo> getInboundBatchesBySupplier(@Param("supplierId") Integer supplierId);
+
+ //鍒ゆ柇璇ュ嚭搴撹褰曟槸鍚︽湁寮�绁ㄧ敵璇�
+ boolean existsByStockInRecordId(@Param("stockInRecordIds") List<Long> stockInRecordIds);
+}
diff --git a/src/main/java/com/ruoyi/account/mapper/purchase/AccountPurchaseInvoiceMapper.java b/src/main/java/com/ruoyi/account/mapper/purchase/AccountPurchaseInvoiceMapper.java
new file mode 100644
index 0000000..bd8e25a
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/mapper/purchase/AccountPurchaseInvoiceMapper.java
@@ -0,0 +1,29 @@
+package com.ruoyi.account.mapper.purchase;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.purchase.AccountPurchaseInvoiceDto;
+import com.ruoyi.account.bean.vo.purchase.AccountPurchaseInvoiceVo;
+import com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo;
+import com.ruoyi.account.pojo.purchase.AccountPurchaseInvoice;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--杩涢」鍙戠エ Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 03:06:17
+ */
+@Mapper
+public interface AccountPurchaseInvoiceMapper extends BaseMapper<AccountPurchaseInvoice> {
+
+ IPage<AccountPurchaseInvoiceVo> listPageAccountPurchaseInvoice(Page page, @Param("req") AccountPurchaseInvoiceDto accountPurchaseInvoiceDto);
+
+ List<PurchaseInboundVo> getInboundBatchesBySupplier(@Param("supplierId") Integer supplierId);
+}
diff --git a/src/main/java/com/ruoyi/account/mapper/purchase/AccountPurchasePaymentMapper.java b/src/main/java/com/ruoyi/account/mapper/purchase/AccountPurchasePaymentMapper.java
new file mode 100644
index 0000000..f687c74
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/mapper/purchase/AccountPurchasePaymentMapper.java
@@ -0,0 +1,29 @@
+package com.ruoyi.account.mapper.purchase;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.purchase.AccountPurchasePaymentDto;
+import com.ruoyi.account.bean.vo.purchase.AccountPurchasePaymentVo;
+import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
+import com.ruoyi.home.dto.IncomeExpenseAnalysisDto;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--浠樻鍗� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 04:14:51
+ */
+@Mapper
+public interface AccountPurchasePaymentMapper extends BaseMapper<AccountPurchasePayment> {
+
+ IPage<AccountPurchasePaymentVo> listPageAccountPurchasePayment(Page page, @Param("req") AccountPurchasePaymentDto accountPurchasePaymentDto);
+
+ List<IncomeExpenseAnalysisDto> selectPayment(@Param("startStr") String startStr, @Param("endStr") String endStr, @Param("dateFormat") String dateFormat);
+}
diff --git a/src/main/java/com/ruoyi/account/mapper/sales/AccountInvoiceApplicationMapper.java b/src/main/java/com/ruoyi/account/mapper/sales/AccountInvoiceApplicationMapper.java
new file mode 100644
index 0000000..463f178
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/mapper/sales/AccountInvoiceApplicationMapper.java
@@ -0,0 +1,32 @@
+package com.ruoyi.account.mapper.sales;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.sales.AccountInvoiceApplicationDto;
+import com.ruoyi.account.bean.vo.sales.AccountInvoiceApplicationVo;
+import com.ruoyi.account.bean.vo.sales.SalesOutboundVo;
+import com.ruoyi.account.pojo.sales.AccountInvoiceApplication;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--寮�绁ㄧ敵璇� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 01:38:32
+ */
+@Mapper
+public interface AccountInvoiceApplicationMapper extends BaseMapper<AccountInvoiceApplication> {
+
+ IPage<AccountInvoiceApplicationVo> listPageAccountInvoiceApplication(Page page, @Param("req") AccountInvoiceApplicationDto accountInvoiceApplicationDto);
+
+ List<SalesOutboundVo> getOutboundBatchesByCustomer(@Param("customerId") Integer customerId);
+
+ //鍒ゆ柇璇ュ嚭搴撹褰曟槸鍚︽湁寮�绁ㄧ敵璇�
+ boolean existsByStockOutRecordId(@Param("stockOutRecordIds") List<Long> stockOutRecordIds);
+}
diff --git a/src/main/java/com/ruoyi/account/mapper/sales/AccountSalesCollectionMapper.java b/src/main/java/com/ruoyi/account/mapper/sales/AccountSalesCollectionMapper.java
new file mode 100644
index 0000000..2f1cf6e
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/mapper/sales/AccountSalesCollectionMapper.java
@@ -0,0 +1,35 @@
+package com.ruoyi.account.mapper.sales;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.sales.AccountSalesCollectionDto;
+import com.ruoyi.account.bean.vo.sales.AccountSalesCollectionVo;
+import com.ruoyi.account.bean.vo.sales.SalesOutboundVo;
+import com.ruoyi.account.pojo.sales.AccountSalesCollection;
+import com.ruoyi.home.dto.IncomeExpenseAnalysisDto;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--鏀舵鍗� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:49:56
+ */
+@Mapper
+public interface AccountSalesCollectionMapper extends BaseMapper<AccountSalesCollection> {
+
+ IPage<AccountSalesCollectionVo> listPageAccountSalesCollection(Page page, @Param("req") AccountSalesCollectionDto accountSalesCollectionDto);
+
+ //鍒ゆ柇璇ュ嚭搴撹褰曟槸鍚︽湁鏀舵鍗�
+ boolean existsByStockOutRecordId(@Param("stockOutRecordIds") List<Long> stockOutRecordIds);
+
+ List<SalesOutboundVo> getOutboundBatchesByCustomer(@Param("customerId") Integer customerId);
+
+ List<IncomeExpenseAnalysisDto> selectIncomeStats(@Param("startStr") String startStr, @Param("endStr") String endStr, @Param("dateFormat") String dateFormat);
+}
diff --git a/src/main/java/com/ruoyi/account/mapper/sales/AccountSalesInvoiceMapper.java b/src/main/java/com/ruoyi/account/mapper/sales/AccountSalesInvoiceMapper.java
new file mode 100644
index 0000000..ea88e8f
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/mapper/sales/AccountSalesInvoiceMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.account.mapper.sales;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.sales.AccountSalesInvoiceDto;
+import com.ruoyi.account.bean.vo.sales.AccountSalesInvoiceVo;
+import com.ruoyi.account.pojo.sales.AccountSalesInvoice;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--閿�椤瑰彂绁� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:10:20
+ */
+@Mapper
+public interface AccountSalesInvoiceMapper extends BaseMapper<AccountSalesInvoice> {
+
+ IPage<AccountSalesInvoiceVo> listPageAccountSalesInvoice(Page page, @Param("req") AccountSalesInvoiceDto accountSalesInvoiceDto);
+}
diff --git a/src/main/java/com/ruoyi/account/pojo/AccountExpense.java b/src/main/java/com/ruoyi/account/pojo/AccountExpense.java
deleted file mode 100644
index dcb6b4b..0000000
--- a/src/main/java/com/ruoyi/account/pojo/AccountExpense.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package com.ruoyi.account.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.dto.DateQueryDto;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import jakarta.validation.constraints.NotBlank;
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-import java.util.Date;
-
-/**
- * 璐㈠姟绠$悊--鏀嚭绠$悊
- * account_expense
- */
-@TableName(value = "account_expense")
-@Data
-public class AccountExpense extends DateQueryDto implements Serializable {
- private static final long serialVersionUID = 1L;
-
- /**
- * 搴忓彿
- */
- @TableId(type = IdType.AUTO)
- private Long id;
-
- /**
- * 涓氬姟id
- */
- private Long businessId;
-
- /**
- * 涓氬姟绫诲瀷 1-浠樻 2-杩樻 3-钖祫鍙戞斁
- */
- private Integer businessType;
-
- /**
- * 鏀嚭鏃ユ湡
- */
- @JsonFormat(pattern = "yyyy-MM-dd")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- @Excel(name = "鏀嚭鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
- private Date expenseDate;
-
- /**
- * 鏀嚭绫诲瀷(鍔炲叕鐢ㄥ搧锛屽憳宸ュ伐璧勶紝宸梾璐癸紝璁惧璐圭敤锛屾潵绁ㄤ粯娆撅紝鍏朵粬)
- */
- @Excel(name = "鏀嚭绫诲瀷",readConverterExp = "0=鍔炲叕鐢ㄥ搧,1=鍛樺伐宸ヨ祫,2=宸梾璐�,3=璁惧璐圭敤,4=鏉ョエ浠樻,5=鍏朵粬")
- @NotBlank(message = "鏀嚭绫诲瀷涓嶈兘涓虹┖!!")
- private String expenseType;
-
- /**
- * 渚涘簲鍟嗗悕绉�
- */
- @Excel(name = "渚涘簲鍟嗗悕绉�")
- private String supplierName;
-
- /**
- * 鏀嚭閲戦
- */
- @Excel(name = "鏀嚭閲戦")
- private BigDecimal expenseMoney;
-
- /**
- * 鏀嚭鎻忚堪
- */
- @Excel(name = "鏀嚭鎻忚堪")
- private String expenseDescribed;
-
- /**
- * 浠樻鏂瑰紡(鐜伴噾锛屾敮绁紝閾惰杞处锛屽叾浠�)
- */
- @Excel(name = "浠樻鏂瑰紡",readConverterExp = "0=鐜伴噾,1=鏀エ,2=閾惰杞处,3=鍏朵粬")
- private String expenseMethod;
-
- /**
- * 鍙戠エ鍙风爜
- */
- @Excel(name = "鍙戠エ鍙风爜")
- private String invoiceNumber;
-
- /**
- * 澶囨敞
- */
- @Excel(name = "澶囨敞")
- private String note;
-
- /**
- * 褰曞叆浜哄憳
- */
- @Excel(name = "褰曞叆浜哄憳")
- private String inputUser;
-
- /**
- * 褰曞叆鏃堕棿
- */
- @JsonFormat(pattern = "yyyy-MM-dd")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- @Excel(name = "褰曞叆鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd")
- private Date inputTime;
-
-
- @Schema(description = "鍒涘缓鏃堕棿")
- @TableField(fill = FieldFill.INSERT)
- private LocalDateTime createTime;
-
- @Schema(description = "鍒涘缓鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT)
- private Integer createUser;
-
- @Schema(description = "淇敼鏃堕棿")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private LocalDateTime updateTime;
-
- @Schema(description = "淇敼鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private Integer updateUser;
-
- @Schema(description = "绉熸埛ID")
- @TableField(fill = FieldFill.INSERT)
- private Long tenantId;
-
-
-
- @TableField(fill = FieldFill.INSERT)
- private Long deptId;
-}
diff --git a/src/main/java/com/ruoyi/account/pojo/AccountFile.java b/src/main/java/com/ruoyi/account/pojo/AccountFile.java
deleted file mode 100644
index b22ab91..0000000
--- a/src/main/java/com/ruoyi/account/pojo/AccountFile.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.ruoyi.account.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import jakarta.validation.constraints.NotBlank;
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * 璐㈠姟绠$悊--闄勪欢
- * account_file
- */
-@TableName(value = "account_file")
-@Data
-public class AccountFile implements Serializable {
- private static final long serialVersionUID = 1L;
-
- /**
- * 搴忓彿
- */
- @TableId(type = IdType.AUTO)
- private Long id;
-
- @Schema(description = "鏂囦欢鍚嶇О")
- private String name;
-
- @Schema(description = "鏂囦欢璺緞")
- private String url;
-
- @Schema(description = "鏂囦欢澶у皬")
- private int fileSize;
-
- @Schema(description = "璐㈠姟ID")
- @NotBlank(message = "璐㈠姟id涓嶈兘涓虹┖!")
- private Long accountId;
-
- /**
- * 绫诲瀷(鏀跺叆/鏀嚭)
- */
- @Schema(description = "绫诲瀷(鏀跺叆/鏀嚭)")
- private String accountType;
-
- @Schema(description = "鍒涘缓鏃堕棿")
- @TableField(fill = FieldFill.INSERT)
- private LocalDateTime createTime;
-
- @Schema(description = "淇敼鏃堕棿")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private LocalDateTime updateTime;
-
- @Schema(description = "鍒涘缓鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT)
- private Integer createUser;
-
- @Schema(description = "淇敼鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private Integer updateUser;
-
- @Schema(description = "绉熸埛ID")
- @TableField(fill = FieldFill.INSERT)
- private Long tenantId;
-
-
-
- @TableField(fill = FieldFill.INSERT)
- private Long deptId;
-}
diff --git a/src/main/java/com/ruoyi/account/pojo/AccountIncome.java b/src/main/java/com/ruoyi/account/pojo/AccountIncome.java
deleted file mode 100644
index d6ce79c..0000000
--- a/src/main/java/com/ruoyi/account/pojo/AccountIncome.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package com.ruoyi.account.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.dto.DateQueryDto;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import jakarta.validation.constraints.NotBlank;
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-import java.util.Date;
-import java.util.List;
-
-/**
- * 璐㈠姟绠$悊--鏀跺叆绠$悊
- * account_income
- */
-@TableName(value = "account_income")
-@Data
-public class AccountIncome extends DateQueryDto implements Serializable {
- private static final long serialVersionUID = 1L;
-
- /**
- * 搴忓彿
- */
- @TableId(type = IdType.AUTO)
- private Long id;
-
- /**
- * 涓氬姟id
- */
- private Long businessId;
-
- /**
- * 涓氬姟绫诲瀷 1-鍥炴 2-鍊熸
- */
- private Integer businessType;
-
- /**
- * 鏀跺叆鏃ユ湡
- */
- @JsonFormat(pattern = "yyyy-MM-dd")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- @Excel(name = "鏀跺叆鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
- private Date incomeDate;
-
- /**
- * 鏀跺叆绫诲瀷(閿�鍞敹鍏ワ紝鏈嶅姟鏀跺叆锛屽叾浠栨敹鍏�)
- */
- @Excel(name = "鏀跺叆绫诲瀷", readConverterExp = "0=閿�鍞敹鍏�,1=鏈嶅姟鏀跺叆,2=鍏朵粬鏀跺叆,3=鍥炴鏀跺叆")
- @NotBlank(message = "鏀跺叆绫诲瀷涓嶈兘涓虹┖!!")
- private String incomeType;
-
- /**
- * 瀹㈡埛鍚嶇О
- */
- @Excel(name = "瀹㈡埛鍚嶇О")
- private String customerName;
-
- /**
- * 鏀跺叆閲戦
- */
- @Excel(name = "鏀跺叆閲戦")
- private BigDecimal incomeMoney;
-
- /**
- * 鏀跺叆鎻忚堪
- */
- @Excel(name = "鏀跺叆鎻忚堪")
- private String incomeDescribed;
-
- /**
- * 鏀舵鏂瑰紡(鐜伴噾锛屾敮绁紝閾惰杞处锛屽叾浠�)
- */
- @Excel(name = "鏀舵鏂瑰紡", readConverterExp = "0=鐜伴噾,1=鏀エ,2=閾惰杞处,3=鍏朵粬")
- private String incomeMethod;
-
- /**
- * 鏀舵鏂瑰紡鏍囩
- */
- @TableField(exist = false)
- private String incomeMethodLabel;
-
- /**
- * payment_methods 瀛楀吀缂栫爜闆嗗悎锛坆usiness_type 涓虹┖鏃讹級
- */
- @TableField(exist = false)
- private List<String> paymentMethodList;
-
- /**
- * receipt_payment_type 瀛楀吀缂栫爜闆嗗悎锛坆usiness_type=1鏃讹級
- */
- @TableField(exist = false)
- private List<String> receiptPaymentMethodList;
-
- /**
- * 鍙戠エ鍙风爜
- */
- @Excel(name = "鍙戠エ鍙风爜")
- private String invoiceNumber;
-
- /**
- * 澶囨敞
- */
- @Excel(name = "澶囨敞")
- private String note;
-
- /**
- * 褰曞叆浜哄憳
- */
- @Excel(name = "褰曞叆浜哄憳")
- private String inputUser;
-
- /**
- * 褰曞叆鏃堕棿
- */
- @JsonFormat(pattern = "yyyy-MM-dd")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- @Excel(name = "褰曞叆鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd")
- private Date inputTime;
-
-
- @Schema(description = "鍒涘缓鏃堕棿")
- @TableField(fill = FieldFill.INSERT)
- private LocalDateTime createTime;
-
- @Schema(description = "鍒涘缓鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT)
- private Integer createUser;
-
- @Schema(description = "淇敼鏃堕棿")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private LocalDateTime updateTime;
-
- @Schema(description = "淇敼鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private Integer updateUser;
-
- @Schema(description = "绉熸埛ID")
- @TableField(fill = FieldFill.INSERT)
- private Long tenantId;
-
-
-
- @TableField(fill = FieldFill.INSERT)
- private Long deptId;
-}
diff --git a/src/main/java/com/ruoyi/account/pojo/AccountStatement.java b/src/main/java/com/ruoyi/account/pojo/AccountStatement.java
new file mode 100644
index 0000000..20d2495
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/pojo/AccountStatement.java
@@ -0,0 +1,127 @@
+package com.ruoyi.account.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ *
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 09:42:47
+ */
+@Getter
+@Setter
+@ToString
+@TableName("account_statement")
+@ApiModel(value = "AccountStatement瀵硅薄", description = "璐㈠姟绠$悊--瀵硅处鍗�")
+public class AccountStatement implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 瀹㈡埛id(搴旀敹鏄鎴穋ustomer,搴斾粯鏄緵搴斿晢supplier)
+ */
+ @ApiModelProperty("瀹㈡埛id")
+ private Integer customerId;
+
+ /**
+ * 瀵硅处鏈堜唤(yyyy-MM)
+ */
+ @ApiModelProperty("瀵硅处鏈堜唤(yyyy-MM)")
+ @Excel(name = "瀵硅处鏈堜唤")
+ private String statementMonth;
+
+ /**
+ * 涓氬姟绫诲瀷(1搴旀敹瀵硅处;2搴斾粯瀵硅处)
+ */
+ @ApiModelProperty("涓氬姟绫诲瀷(1搴旀敹瀵硅处;2搴斾粯瀵硅处)")
+ @Excel(name = "涓氬姟绫诲瀷",readConverterExp = "1=搴旀敹瀵硅处,2=搴斾粯瀵硅处")
+ private Integer accountType;
+
+ /**
+ * 瀵硅处鍗曞彿
+ */
+ @ApiModelProperty("瀵硅处鍗曞彿")
+ @Excel(name = "瀵硅处鍗曞彿")
+ private String statementNumber;
+
+ /**
+ * 鏈熷垵浣欓
+ */
+ @ApiModelProperty("鏈熷垵浣欓")
+ @Excel(name = "鏈熷垵浣欓")
+ private BigDecimal openingBalance;
+
+ /**
+ * 鏈湡搴旀敹/搴斾粯
+ */
+ @ApiModelProperty("鏈湡搴旀敹/搴斾粯")
+ @Excel(name = "鏈湡搴旀敹/搴斾粯")
+ private BigDecimal currentPlan;
+
+ /**
+ * 鏈湡鏀舵/浠樻
+ */
+ @ApiModelProperty("鏈湡鏀舵/浠樻")
+ @Excel(name = "鏈湡鏀舵/浠樻")
+ private BigDecimal currentActually;
+
+ /**
+ * 鏈熸湯浣欓
+ */
+ @ApiModelProperty("鏈熸湯浣欓")
+ @Excel(name = "鏈熸湯浣欓")
+ private BigDecimal closingBalance;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @ApiModelProperty("鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime createTime;
+
+ /**
+ * 淇敼浜�
+ */
+ @ApiModelProperty("淇敼浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ /**
+ * 淇敼鏃堕棿
+ */
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime updateTime;
+
+ /**
+ * 閮ㄩ棬ID
+ */
+ @ApiModelProperty("閮ㄩ棬ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/account/pojo/AccountStatementDetails.java b/src/main/java/com/ruoyi/account/pojo/AccountStatementDetails.java
new file mode 100644
index 0000000..016a099
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/pojo/AccountStatementDetails.java
@@ -0,0 +1,115 @@
+package com.ruoyi.account.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--瀵硅处鍗曟槑缁�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 10:12:42
+ */
+@Getter
+@Setter
+@ToString
+@TableName("account_statement_details")
+@ApiModel(value = "AccountStatementDetails瀵硅薄", description = "璐㈠姟绠$悊--瀵硅处鍗曟槑缁�")
+public class AccountStatementDetails implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 鍏宠仈瀵硅处鍗昳d
+ */
+ @ApiModelProperty("鍏宠仈瀵硅处鍗昳d")
+ private Integer accountStatementId;
+
+ /**
+ * 鏁版嵁鏃ユ湡
+ */
+ @ApiModelProperty("鏁版嵁鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate occurrenceDate;
+
+ /**
+ * 鍗曟嵁缂栧彿
+ */
+ @ApiModelProperty("鍗曟嵁缂栧彿")
+ private String receiptNumber;
+
+ /**
+ * 鏁版嵁绫诲瀷(1鍑哄簱;2鍏ュ簱;3鏀舵;4浠樻;5閫�璐�)
+ */
+ @ApiModelProperty("鏁版嵁绫诲瀷(1鍑哄簱;2鍏ュ簱;3鏀舵;4浠樻;5閫�璐�)")
+ private Integer type;
+
+ /**
+ * 閲戦
+ */
+ @ApiModelProperty("閲戦")
+ private BigDecimal amount;
+
+ /**
+ * 澶囨敞
+ */
+ @ApiModelProperty("澶囨敞")
+ private String remark;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @ApiModelProperty("鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime createTime;
+
+ /**
+ * 淇敼浜�
+ */
+ @ApiModelProperty("淇敼浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ /**
+ * 淇敼鏃堕棿
+ */
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime updateTime;
+
+ /**
+ * 閮ㄩ棬ID
+ */
+ @ApiModelProperty("閮ㄩ棬ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/account/pojo/BorrowInfo.java b/src/main/java/com/ruoyi/account/pojo/BorrowInfo.java
deleted file mode 100644
index 8e4d809..0000000
--- a/src/main/java/com/ruoyi/account/pojo/BorrowInfo.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package com.ruoyi.account.pojo;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.dto.DateQueryDto;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Getter;
-import lombok.Setter;
-import org.springframework.format.annotation.DateTimeFormat;
-
-/**
- * <p>
- * 鍊熸淇℃伅琛�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-15 02:57:29
- */
-@Getter
-@Setter
-@TableName("borrow_info")
-@Schema(name = "BorrowInfo瀵硅薄", description = "鍊熸淇℃伅琛�")
-public class BorrowInfo extends DateQueryDto implements Serializable{
-
- private static final long serialVersionUID = 1L;
-
- @Schema(description = "鍊熸璁板綍涓婚敭ID")
- @TableId(value = "id", type = IdType.AUTO)
- private Long id;
-
- @Schema(description = "鍊熸浜哄鍚�")
- @Excel(name = "鍊熸浜哄鍚�")
- private String borrowerName;
-
- @Schema(description = "鍊熸閲戦锛堝厓锛�")
- @Excel(name = "鍊熸閲戦锛堝厓锛�")
- private BigDecimal borrowAmount;
-
- @Schema(description = "鍊熸鍒╃巼锛堝锛�5.85 浠h〃5.85%锛�")
- @Excel(name = "鍊熸鍒╃巼")
- private BigDecimal interestRate;
-
- @Schema(description = "鍊熸鏃ユ湡")
- @JsonFormat(pattern = "yyyy-MM-dd")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- @Excel(name = "鍊熸鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
- private LocalDate borrowDate;
-
- @Schema(description = "瀹為檯杩樻鏃ユ湡锛堣繕娆惧悗濉厖锛�")
- @JsonFormat(pattern = "yyyy-MM-dd")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- @Excel(name = "瀹為檯杩樻鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
- private LocalDate repayDate;
-
- @Schema(description = "鍊熸鐘舵�侊細1=寰呰繕娆撅紝2=宸茶繕娆�")
- @Excel(name = "鍊熸鐘舵��", readConverterExp = "1=寰呰繕娆�,2=宸茶繕娆�")
- private Integer status;
-
- @Schema(description = "澶囨敞锛堝�熸璇存槑锛�")
- @Excel(name = "澶囨敞")
- private String remark;
-
- @Schema(description = "鍒涘缓鏃堕棿")
- @TableField(fill = FieldFill.INSERT)
- private LocalDateTime createTime;
-
- @Schema(description = "鍒涘缓鑰匢D")
- @TableField(fill = FieldFill.INSERT)
- private Integer createUser;
-
- @Schema(description = "淇敼鏃堕棿")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private LocalDateTime updateTime;
-
- @Schema(description = "淇敼鑰匢D")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private Integer updateUser;
-
- @Schema(description = "绉熸埛id")
- @TableField(fill = FieldFill.INSERT)
- private Long tenantId;
-
- @TableField(fill = FieldFill.INSERT)
- private Long deptId;
-}
diff --git a/src/main/java/com/ruoyi/account/pojo/financial/AccountSubject.java b/src/main/java/com/ruoyi/account/pojo/financial/AccountSubject.java
index 222ee6c..2548a9c 100644
--- a/src/main/java/com/ruoyi/account/pojo/financial/AccountSubject.java
+++ b/src/main/java/com/ruoyi/account/pojo/financial/AccountSubject.java
@@ -85,7 +85,7 @@
*/
@ApiModelProperty("鍒涘缓浜�")
@TableField(fill = FieldFill.INSERT)
- private String createUser;
+ private Integer createUser;
/**
* 鍒涘缓鏃堕棿
@@ -99,7 +99,7 @@
*/
@ApiModelProperty("淇敼浜�")
@TableField(fill = FieldFill.INSERT_UPDATE)
- private String updateUser;
+ private Integer updateUser;
/**
* 淇敼鏃堕棿
diff --git a/src/main/java/com/ruoyi/account/pojo/purchase/AccountPaymentApplication.java b/src/main/java/com/ruoyi/account/pojo/purchase/AccountPaymentApplication.java
new file mode 100644
index 0000000..9a01df7
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/pojo/purchase/AccountPaymentApplication.java
@@ -0,0 +1,141 @@
+package com.ruoyi.account.pojo.purchase;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--浠樻鐢宠
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 03:44:22
+ */
+@Getter
+@Setter
+@ToString
+@TableName("account_payment_application")
+@ApiModel(value = "AccountPaymentApplication瀵硅薄", description = "璐㈠姟绠$悊--浠樻鐢宠")
+public class AccountPaymentApplication implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @ApiModelProperty("鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime createTime;
+
+ /**
+ * 淇敼浜�
+ */
+ @ApiModelProperty("淇敼浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ /**
+ * 淇敼鏃堕棿
+ */
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime updateTime;
+
+ /**
+ * 閮ㄩ棬ID
+ */
+ @ApiModelProperty("閮ㄩ棬ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+
+ /**
+ * 渚涘簲鍟唅d
+ */
+ @ApiModelProperty("渚涘簲鍟唅d")
+ private Integer supplierId;
+
+ /**
+ * 鍏宠仈鍏ュ簱鍗昳d(澶氶��)
+ */
+ @ApiModelProperty("鍏宠仈鍏ュ簱鍗昳d(澶氶��)")
+ private String stockInRecordIds;
+
+ /**
+ * 浠樻鐢宠鍗曞彿
+ */
+ @ApiModelProperty("浠樻鐢宠鍗曞彿")
+ @Excel(name = "浠樻鐢宠鍗曞彿")
+ private String invoiceApplicationNo;
+
+ /**
+ * 浠樻鏂瑰紡
+ */
+ @ApiModelProperty("浠樻鏂瑰紡")
+ @Excel(name = "浠樻鏂瑰紡")
+ private String paymentMethod;
+
+ /**
+ * 浠樻浜嬬敱
+ */
+ @ApiModelProperty("浠樻浜嬬敱")
+ @Excel(name = "浠樻浜嬬敱")
+ private String paymentContent;
+
+ /**
+ * 鐢宠鏃ユ湡
+ */
+ @ApiModelProperty("鐢宠鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ @Excel(name = "鐢宠鏃ユ湡")
+ private LocalDate applyDate;
+
+ /**
+ * 澶囨敞
+ */
+ @ApiModelProperty("澶囨敞")
+ @Excel(name = "澶囨敞")
+ private String remark;
+
+ /**
+ * 瀹℃牳鐘舵��:0寰呭鏍�1瀹℃牳閫氳繃2瀹℃牳涓嶉�氳繃
+ */
+ @ApiModelProperty("瀹℃牳鐘舵��:0寰呭鏍�1瀹℃牳閫氳繃2瀹℃牳涓嶉�氳繃")
+ @Excel(name = "瀹℃牳鐘舵��",readConverterExp = "0=寰呭鏍�,1=瀹℃牳閫氳繃,2=瀹℃牳涓嶉�氳繃")
+ private Integer status;
+
+ /**
+ * 浠樻閲戦
+ */
+ @ApiModelProperty("浠樻閲戦")
+ @Excel(name = "浠樻閲戦")
+ private BigDecimal paymentAmount;
+}
diff --git a/src/main/java/com/ruoyi/account/pojo/purchase/AccountPurchaseInvoice.java b/src/main/java/com/ruoyi/account/pojo/purchase/AccountPurchaseInvoice.java
new file mode 100644
index 0000000..c71ecd0
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/pojo/purchase/AccountPurchaseInvoice.java
@@ -0,0 +1,168 @@
+package com.ruoyi.account.pojo.purchase;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--杩涢」鍙戠エ
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 03:06:17
+ */
+@Getter
+@Setter
+@ToString
+@TableName("account_purchase_invoice")
+@ApiModel(value = "AccountPurchaseInvoice瀵硅薄", description = "璐㈠姟绠$悊--杩涢」鍙戠エ")
+public class AccountPurchaseInvoice implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @ApiModelProperty("鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime createTime;
+
+ /**
+ * 淇敼浜�
+ */
+ @ApiModelProperty("淇敼浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ /**
+ * 淇敼鏃堕棿
+ */
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime updateTime;
+
+ /**
+ * 閮ㄩ棬ID
+ */
+ @ApiModelProperty("閮ㄩ棬ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+
+ /**
+ * 鍙戠エ鍙风爜
+ */
+ @ApiModelProperty("鍙戠エ鍙风爜")
+ @Excel(name = "鍙戠エ鍙风爜")
+ private String invoiceNumber;
+
+ /**
+ * 绋庣巼
+ */
+ @ApiModelProperty("绋庣巼")
+ @Excel(name = "绋庣巼")
+ private Integer taxRate;
+
+ /**
+ * 鍙戠エ绫诲瀷
+ */
+ @ApiModelProperty("鍙戠エ绫诲瀷")
+ @Excel(name = "鍙戠エ绫诲瀷")
+ private String invoiceType;
+
+ /**
+ * 寮�绁ㄦ棩鏈�
+ */
+ @ApiModelProperty("寮�绁ㄦ棩鏈�")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ @Excel(name = "寮�绁ㄦ棩鏈�")
+ private LocalDate issueDate;
+
+ /**
+ * 閲戦(涓嶅惈绋�)
+ */
+ @ApiModelProperty("閲戦(涓嶅惈绋�)")
+ @Excel(name = "閲戦(涓嶅惈绋�)")
+ private BigDecimal taxExclusivelPrice;
+
+ /**
+ * 绋庨
+ */
+ @ApiModelProperty("绋庨")
+ @Excel(name = "绋庨")
+ private BigDecimal taxPrice;
+
+ /**
+ * 浠风◣鍚堣
+ */
+ @ApiModelProperty("浠风◣鍚堣")
+ @Excel(name = "浠风◣鍚堣")
+ private BigDecimal taxInclusivePrice;
+
+ /**
+ * 澶囨敞
+ */
+ @ApiModelProperty("澶囨敞")
+ @Excel(name = "澶囨敞")
+ private String remark;
+
+ /**
+ * 鍙戠エ鍐呭
+ */
+ @ApiModelProperty("鍙戠エ鍐呭")
+ @Excel(name = "鍙戠エ鍐呭")
+ private String invoiceContent;
+
+ /**
+ * 渚涘簲鍟唅d
+ */
+ @ApiModelProperty("渚涘簲鍟唅d")
+ private Integer supplierId;
+
+ /**
+ * 鍏宠仈涓婁紶鐨勫彂绁ㄩ檮浠秈d
+ */
+ @ApiModelProperty("鍏宠仈涓婁紶鐨勫彂绁ㄩ檮浠秈d")
+ private Integer storageAttachmentId;
+
+ /**
+ * 鍏宠仈鍏ュ簱鍗昳d(澶氶��)
+ */
+ @ApiModelProperty("鍏宠仈鍏ュ簱鍗昳d(澶氶��)")
+ private String stockInRecordIds;
+
+ /**
+ * 鐘舵�� 0鍚敤 1绂佺敤
+ */
+ @ApiModelProperty("鐘舵�� 0鍚敤 1绂佺敤")
+ @Excel(name = "鐘舵��", readConverterExp = "0=姝e父,1=浣滃簾")
+ private Integer status;
+}
diff --git a/src/main/java/com/ruoyi/account/pojo/purchase/AccountPurchasePayment.java b/src/main/java/com/ruoyi/account/pojo/purchase/AccountPurchasePayment.java
new file mode 100644
index 0000000..7fc2d4e
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/pojo/purchase/AccountPurchasePayment.java
@@ -0,0 +1,127 @@
+package com.ruoyi.account.pojo.purchase;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--浠樻鍗�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 04:14:51
+ */
+@Getter
+@Setter
+@ToString
+@TableName("account_purchase_payment")
+@ApiModel(value = "AccountPurchasePayment瀵硅薄", description = "璐㈠姟绠$悊--浠樻鍗�")
+public class AccountPurchasePayment implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 鍏宠仈浠樻鐢宠id
+ */
+ @ApiModelProperty("鍏宠仈浠樻鐢宠id")
+ private Integer accountPaymentApplicationId;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @ApiModelProperty("鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime createTime;
+
+ /**
+ * 淇敼浜�
+ */
+ @ApiModelProperty("淇敼浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ /**
+ * 淇敼鏃堕棿
+ */
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime updateTime;
+
+ /**
+ * 閮ㄩ棬ID
+ */
+ @ApiModelProperty("閮ㄩ棬ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+
+ /**
+ * 渚涘簲鍟唅d
+ */
+ @ApiModelProperty("渚涘簲鍟唅d")
+ private Integer supplierId;
+
+ /**
+ * 浠樻鏃ユ湡
+ */
+ @ApiModelProperty("浠樻鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ @Excel(name = "浠樻鏃ユ湡")
+ private LocalDate paymentDate;
+
+ /**
+ * 浠樻鏂瑰紡
+ */
+ @ApiModelProperty("浠樻鏂瑰紡")
+ @Excel(name = "浠樻鏂瑰紡",dictType = "checkout_payment")
+ private String paymentMethod;
+
+ /**
+ * 浠樻閲戦
+ */
+ @ApiModelProperty("浠樻閲戦")
+ @Excel(name = "浠樻閲戦")
+ private BigDecimal paymentAmount;
+
+ /**
+ * 浠樻鍗曞彿
+ */
+ @ApiModelProperty("浠樻鍗曞彿")
+ @Excel(name = "浠樻鍗曞彿")
+ private String paymentNumber;
+
+ /**
+ * 澶囨敞
+ */
+ @ApiModelProperty("澶囨敞")
+ @Excel(name = "澶囨敞")
+ private String remark;
+}
diff --git a/src/main/java/com/ruoyi/account/pojo/sales/AccountInvoiceApplication.java b/src/main/java/com/ruoyi/account/pojo/sales/AccountInvoiceApplication.java
new file mode 100644
index 0000000..ed4b72a
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/pojo/sales/AccountInvoiceApplication.java
@@ -0,0 +1,138 @@
+package com.ruoyi.account.pojo.sales;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--寮�绁ㄧ敵璇�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 01:38:32
+ */
+@Getter
+@Setter
+@ToString
+@TableName("account_invoice_application")
+@ApiModel(value = "AccountInvoiceApplication瀵硅薄", description = "璐㈠姟绠$悊--寮�绁ㄧ敵璇�")
+public class AccountInvoiceApplication implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @ApiModelProperty("鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime createTime;
+
+ /**
+ * 淇敼浜�
+ */
+ @ApiModelProperty("淇敼浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ /**
+ * 淇敼鏃堕棿
+ */
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime updateTime;
+
+ /**
+ * 閮ㄩ棬ID
+ */
+ @ApiModelProperty("閮ㄩ棬ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+
+ /**
+ * 瀹㈡埛id
+ */
+ @ApiModelProperty("瀹㈡埛id")
+ private Integer customerId;
+
+ /**
+ * 鍏宠仈鍑哄簱鍗昳d(澶氶��)
+ */
+ @ApiModelProperty("鍏宠仈鍑哄簱鍗昳d(澶氶��)")
+ private String stockOutRecordIds;
+
+ /**
+ * 寮�绁ㄧ敵璇峰崟鍙�
+ */
+ @ApiModelProperty("寮�绁ㄧ敵璇峰崟鍙�")
+ @Excel(name = "寮�绁ㄧ敵璇峰崟鍙�")
+ private String invoiceApplicationNo;
+
+ /**
+ * 鍙戠エ绫诲瀷
+ */
+ @ApiModelProperty("鍙戠エ绫诲瀷")
+ @Excel(name = "鍙戠エ绫诲瀷")
+ private String invoiceType;
+
+ /**
+ * 鐢宠鏃ユ湡
+ */
+ @ApiModelProperty("鐢宠鏃ユ湡")
+ @Excel(name = "鐢宠鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate applyDate;
+
+ /**
+ * 鍙戠エ鍐呭
+ */
+ @ApiModelProperty("鍙戠エ鍐呭")
+ @Excel(name = "鍙戠エ鍐呭")
+ private String invoiceContent;
+
+ /**
+ * 澶囨敞
+ */
+ @ApiModelProperty("澶囨敞")
+ @Excel(name = "澶囨敞")
+ private String remark;
+
+ /**
+ * 瀹℃牳鐘舵��:0寰呭鏍�1瀹℃牳閫氳繃2瀹℃牳涓嶉�氳繃
+ */
+ @ApiModelProperty("瀹℃牳鐘舵��:0寰呭鏍�1瀹℃牳閫氳繃2瀹℃牳涓嶉�氳繃")
+ @Excel(name = "瀹℃牳鐘舵��",readConverterExp = "0=寰呭鏍�,1=瀹℃牳閫氳繃,2=瀹℃牳涓嶉�氳繃")
+ private Integer status;
+
+ @ApiModelProperty("寮�绁ㄩ噾棰�")
+ @Excel(name = "寮�绁ㄩ噾棰�")
+ private BigDecimal invoiceAmount;
+
+ @ApiModelProperty("绋庣巼")
+ @Excel(name = "绋庣巼")
+ private BigDecimal taxRate;
+}
diff --git a/src/main/java/com/ruoyi/account/pojo/sales/AccountSalesCollection.java b/src/main/java/com/ruoyi/account/pojo/sales/AccountSalesCollection.java
new file mode 100644
index 0000000..40ea9a8
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/pojo/sales/AccountSalesCollection.java
@@ -0,0 +1,127 @@
+package com.ruoyi.account.pojo.sales;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--鏀舵鍗�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:49:56
+ */
+@Getter
+@Setter
+@ToString
+@TableName("account_sales_collection")
+@ApiModel(value = "AccountSalesCollection瀵硅薄", description = "璐㈠姟绠$悊--鏀舵鍗�")
+public class AccountSalesCollection implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 鍏宠仈鍑哄簱鍗昳d(澶氶��)
+ */
+ @ApiModelProperty("鍏宠仈鍑哄簱鍗昳d(澶氶��)")
+ private String stockOutRecordIds;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @ApiModelProperty("鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime createTime;
+
+ /**
+ * 淇敼浜�
+ */
+ @ApiModelProperty("淇敼浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ /**
+ * 淇敼鏃堕棿
+ */
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime updateTime;
+
+ /**
+ * 閮ㄩ棬ID
+ */
+ @ApiModelProperty("閮ㄩ棬ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+
+ /**
+ * 瀹㈡埛id
+ */
+ @ApiModelProperty("瀹㈡埛id")
+ private Integer customerId;
+
+ /**
+ * 鏀舵鏃ユ湡
+ */
+ @ApiModelProperty("鏀舵鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ @Excel(name = "鏀舵鏃ユ湡")
+ private LocalDate collectionDate;
+
+ /**
+ * 鏀舵閲戦
+ */
+ @ApiModelProperty("鏀舵閲戦")
+ @Excel(name = "鏀舵閲戦")
+ private BigDecimal collectionAmount;
+
+ /**
+ * 鏀舵鏂瑰紡
+ */
+ @ApiModelProperty("鏀舵鏂瑰紡")
+ @Excel(name = "鏀舵鏂瑰紡",dictType = "payment_methods")
+ private String collectionMethod;
+
+ /**
+ * 鏀舵鍗曞彿
+ */
+ @ApiModelProperty("鏀舵鍗曞彿")
+ @Excel(name = "鏀舵鍗曞彿")
+ private String collectionNumber;
+
+ /**
+ * 澶囨敞
+ */
+ @ApiModelProperty("澶囨敞")
+ @Excel(name = "澶囨敞")
+ private String remark;
+}
diff --git a/src/main/java/com/ruoyi/account/pojo/sales/AccountSalesInvoice.java b/src/main/java/com/ruoyi/account/pojo/sales/AccountSalesInvoice.java
new file mode 100644
index 0000000..7551cb3
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/pojo/sales/AccountSalesInvoice.java
@@ -0,0 +1,168 @@
+package com.ruoyi.account.pojo.sales;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--閿�椤瑰彂绁�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:10:20
+ */
+@Getter
+@Setter
+@ToString
+@TableName("account_sales_invoice")
+@ApiModel(value = "AccountSalesInvoice瀵硅薄", description = "璐㈠姟绠$悊--閿�椤瑰彂绁�")
+public class AccountSalesInvoice implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 鍏宠仈寮�绁ㄧ敵璇穒d
+ */
+ @ApiModelProperty("鍏宠仈寮�绁ㄧ敵璇穒d")
+ private Integer accountInvoiceApplicationId;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @ApiModelProperty("鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime createTime;
+
+ /**
+ * 淇敼浜�
+ */
+ @ApiModelProperty("淇敼浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ /**
+ * 淇敼鏃堕棿
+ */
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime updateTime;
+
+ /**
+ * 閮ㄩ棬ID
+ */
+ @ApiModelProperty("閮ㄩ棬ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+
+ /**
+ * 鍙戠エ鍙风爜
+ */
+ @ApiModelProperty("鍙戠エ鍙风爜")
+ @Excel(name = "鍙戠エ鍙风爜")
+ private String invoiceNumber;
+
+ /**
+ * 绋庣巼
+ */
+ @ApiModelProperty("绋庣巼")
+ @Excel(name = "绋庣巼")
+ private BigDecimal taxRate;
+
+ /**
+ * 鍙戠エ绫诲瀷
+ */
+ @ApiModelProperty("鍙戠エ绫诲瀷")
+ @Excel(name = "鍙戠エ绫诲瀷")
+ private String invoiceType;
+
+ /**
+ * 寮�绁ㄦ棩鏈�
+ */
+ @ApiModelProperty("寮�绁ㄦ棩鏈�")
+ @Excel(name = "寮�绁ㄦ棩鏈�")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate issueDate;
+
+ /**
+ * 閲戦(涓嶅惈绋�)
+ */
+ @ApiModelProperty("閲戦(涓嶅惈绋�)")
+ @Excel(name = "閲戦(涓嶅惈绋�)")
+ private BigDecimal taxExclusivelPrice;
+
+ /**
+ * 绋庨
+ */
+ @ApiModelProperty("绋庨")
+ @Excel(name = "绋庨")
+ private BigDecimal taxPrice;
+
+ /**
+ * 浠风◣鍚堣
+ */
+ @ApiModelProperty("浠风◣鍚堣")
+ @Excel(name = "浠风◣鍚堣")
+ private BigDecimal taxInclusivePrice;
+
+ /**
+ * 澶囨敞
+ */
+ @ApiModelProperty("澶囨敞")
+ @Excel(name = "澶囨敞")
+ private String remark;
+
+ /**
+ * 鍙戠エ鍐呭
+ */
+ @ApiModelProperty("鍙戠エ鍐呭")
+ @Excel(name = "鍙戠エ鍐呭")
+ private String invoiceContent;
+
+ /**
+ * 瀹㈡埛id
+ */
+ @ApiModelProperty("瀹㈡埛id")
+ private Integer customerId;
+
+ /**
+ * 鍏宠仈涓婁紶鐨勫彂绁ㄩ檮浠秈d
+ */
+ @ApiModelProperty("鍏宠仈涓婁紶鐨勫彂绁ㄩ檮浠秈d")
+ private Integer storageAttachmentId;
+
+ /**
+ * 鐘舵�� 0鍚敤 1绂佺敤
+ */
+ @ApiModelProperty("鐘舵�� 0鍚敤 1绂佺敤")
+ @Excel(name = "鐘舵��", readConverterExp = "0=姝e父,1=浣滃簾")
+ private Integer status;
+}
diff --git a/src/main/java/com/ruoyi/account/service/AccountExpenseService.java b/src/main/java/com/ruoyi/account/service/AccountExpenseService.java
deleted file mode 100644
index b070485..0000000
--- a/src/main/java/com/ruoyi/account/service/AccountExpenseService.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.ruoyi.account.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.account.bean.dto.AccountDto;
-import com.ruoyi.account.bean.dto.AccountDto2;
-import com.ruoyi.account.bean.dto.AccountDto3;
-import com.ruoyi.account.bean.dto.ReportDateDto;
-import com.ruoyi.account.pojo.AccountExpense;
-import com.ruoyi.account.pojo.AccountIncome;
-import com.ruoyi.dto.DateQueryDto;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.List;
-import java.util.Map;
-
-public interface AccountExpenseService extends IService<AccountExpense> {
-
- IPage<AccountExpense> accountExpenseListPage(Page page, AccountExpense accountExpense);
-
- void accountExpenseExport(HttpServletResponse response, AccountExpense accountExpense);
-
- AccountDto report(DateQueryDto dateQueryDto);
-
- List<AccountDto3> reportExpense(ReportDateDto reportDateDto);
-
- Map<String,List<String>> analysis();
-
- AccountExpense getByInvoiceNumber(String purchaseContractNumber);
-
- List<AccountExpense> getByInvoiceNumberList(String purchaseContractNumber);
-}
diff --git a/src/main/java/com/ruoyi/account/service/AccountFileService.java b/src/main/java/com/ruoyi/account/service/AccountFileService.java
deleted file mode 100644
index fe24512..0000000
--- a/src/main/java/com/ruoyi/account/service/AccountFileService.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.ruoyi.account.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.account.pojo.AccountFile;
-import com.ruoyi.quality.pojo.QualityInspectFile;
-
-public interface AccountFileService extends IService<AccountFile> {
-
-
- IPage<AccountFile> accountFileListPage(Page page, AccountFile accountFile);
-}
diff --git a/src/main/java/com/ruoyi/account/service/AccountIncomeService.java b/src/main/java/com/ruoyi/account/service/AccountIncomeService.java
deleted file mode 100644
index 1f5d684..0000000
--- a/src/main/java/com/ruoyi/account/service/AccountIncomeService.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.ruoyi.account.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.account.bean.dto.AccountDto2;
-import com.ruoyi.account.bean.dto.AccountDto3;
-import com.ruoyi.account.bean.dto.ReportDateDto;
-import com.ruoyi.account.pojo.AccountIncome;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.List;
-
-public interface AccountIncomeService extends IService<AccountIncome> {
-
-
- IPage<AccountIncome> accountIncomeListPage(Page page, AccountIncome accountIncome);
-
- void accountIncomeExport(HttpServletResponse response, AccountIncome accountIncome);
-
- List<AccountDto3> reportIncome(ReportDateDto reportDateDto);
-
- AccountIncome getByInvoiceNumber(String purchaseContractNumber);
-
- List<AccountIncome> getByInvoiceNumberList(String purchaseContractNumber);
-}
diff --git a/src/main/java/com/ruoyi/account/service/AccountStatementDetailsService.java b/src/main/java/com/ruoyi/account/service/AccountStatementDetailsService.java
new file mode 100644
index 0000000..c9a4928
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/AccountStatementDetailsService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.account.service;
+
+import com.ruoyi.account.pojo.AccountStatementDetails;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--瀵硅处鍗曟槑缁� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 10:12:42
+ */
+public interface AccountStatementDetailsService extends IService<AccountStatementDetails> {
+
+}
diff --git a/src/main/java/com/ruoyi/account/service/AccountStatementService.java b/src/main/java/com/ruoyi/account/service/AccountStatementService.java
new file mode 100644
index 0000000..a0bc218
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/AccountStatementService.java
@@ -0,0 +1,32 @@
+package com.ruoyi.account.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.account.bean.dto.StatementAccountDto;
+import com.ruoyi.account.bean.vo.StatementAccountVo;
+import com.ruoyi.account.pojo.AccountStatement;
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 09:42:47
+ */
+public interface AccountStatementService extends IService<AccountStatement> {
+
+ StatementAccountVo getAccountStatementDetailsByMonth(StatementAccountDto statementAccountDto);
+
+ boolean addAccountStatement(StatementAccountVo statementAccountVo);
+
+ boolean deleteAccountStatement(List<Long> ids);
+
+ IPage<StatementAccountVo> listPageAccountStatement(Page page, StatementAccountDto statementAccountDto);
+
+ void exportAccountStatement(HttpServletResponse response, StatementAccountDto statementAccountDto);
+}
diff --git a/src/main/java/com/ruoyi/account/service/AccountingService.java b/src/main/java/com/ruoyi/account/service/AccountingService.java
new file mode 100644
index 0000000..6190dc8
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/AccountingService.java
@@ -0,0 +1,19 @@
+package com.ruoyi.account.service;
+
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.AccountReportDto;
+import com.ruoyi.account.bean.vo.AccountReportVo;
+import com.ruoyi.framework.web.domain.AjaxResult;
+
+public interface AccountingService {
+
+ AjaxResult total(Integer year);
+
+ AjaxResult deviceTypeDistribution(Integer year);
+
+ AjaxResult calculateDepreciation(Page page, Integer year);
+
+ AccountReportVo getAccountStatementDetailsByMonth(AccountReportDto accountReportDto);
+
+}
diff --git a/src/main/java/com/ruoyi/account/service/BorrowInfoService.java b/src/main/java/com/ruoyi/account/service/BorrowInfoService.java
deleted file mode 100644
index eb1c83b..0000000
--- a/src/main/java/com/ruoyi/account/service/BorrowInfoService.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.ruoyi.account.service;
-
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.account.pojo.BorrowInfo;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.framework.web.domain.AjaxResult;
-
-import java.util.List;
-
-/**
- * <p>
- * 鍊熸淇℃伅琛� 鏈嶅姟绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-15 02:57:29
- */
-public interface BorrowInfoService extends IService<BorrowInfo> {
-
- AjaxResult listPage(Page page, BorrowInfo borrowInfo);
-
- AjaxResult add(BorrowInfo borrowInfo);
-
- AjaxResult updateBorrowInfo(BorrowInfo borrowInfo);
-
- AjaxResult delete(List<Long> ids);
-}
diff --git a/src/main/java/com/ruoyi/account/service/impl/AccountExpenseServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/AccountExpenseServiceImpl.java
deleted file mode 100644
index 9d392a2..0000000
--- a/src/main/java/com/ruoyi/account/service/impl/AccountExpenseServiceImpl.java
+++ /dev/null
@@ -1,233 +0,0 @@
-package com.ruoyi.account.service.impl;
-
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.account.bean.dto.AccountDto;
-import com.ruoyi.account.bean.dto.AccountDto2;
-import com.ruoyi.account.bean.dto.AccountDto3;
-import com.ruoyi.account.bean.dto.ReportDateDto;
-import com.ruoyi.account.mapper.AccountExpenseMapper;
-import com.ruoyi.account.mapper.AccountIncomeMapper;
-import com.ruoyi.account.pojo.AccountExpense;
-import com.ruoyi.account.pojo.AccountIncome;
-import com.ruoyi.account.service.AccountExpenseService;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.dto.DateQueryDto;
-import com.ruoyi.project.system.domain.SysDictData;
-import com.ruoyi.project.system.mapper.SysDictDataMapper;
-import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.math.BigDecimal;
-import java.time.DayOfWeek;
-import java.time.LocalDate;
-import java.time.ZoneId;
-import java.time.format.DateTimeFormatter;
-import java.util.*;
-import java.util.stream.Collectors;
-
-@AllArgsConstructor
-@Service
-public class AccountExpenseServiceImpl extends ServiceImpl<AccountExpenseMapper, AccountExpense> implements AccountExpenseService {
-
- private AccountExpenseMapper accountExpenseMapper;
-
- private AccountIncomeMapper accountIncomeMapper;
-
- private SysDictDataMapper sysDictDataMapper;
-
-
- //鍒嗛〉鏌ヨ
- @Override
- public IPage<AccountExpense> accountExpenseListPage(Page page, AccountExpense accountExpense) {
- return accountExpenseMapper.accountExpenseListPage(page,accountExpense);
- }
-
- //瀵煎嚭
- @Override
- public void accountExpenseExport(HttpServletResponse response, AccountExpense accountExpense) {
- List<AccountExpense> accountExpenses =accountExpenseMapper.accountExpenseExport(accountExpense);
- ExcelUtil<AccountExpense> util = new ExcelUtil<AccountExpense>(AccountExpense.class);
- util.exportExcel(response, accountExpenses, "鏀嚭绠$悊瀵煎嚭");
- }
-
- //璐㈠姟鎶ヨ〃鍥捐〃
- @Override
- public AccountDto report(DateQueryDto dateQueryDto) {
- AccountDto accountDto = new AccountDto();
- //鑾峰彇璇ユ鏃堕棿鍐呯殑鎵�鏈夋敹鍏�
- List<AccountDto2> accountIncomes =accountIncomeMapper.report(dateQueryDto);
-
- Long incomeNumber = accountIncomeMapper.selectCount(Wrappers.<AccountIncome>lambdaQuery()
- .between(AccountIncome::getIncomeDate, dateQueryDto.getEntryDateStart(), dateQueryDto.getEntryDateEnd()));
- accountDto.setIncomeNumber(incomeNumber);
- BigDecimal totalIncome = accountIncomes.stream().map(AccountDto2::getAccount).reduce(BigDecimal.ZERO, BigDecimal::add);
- accountDto.setTotalIncome(totalIncome);
- accountIncomes.stream().forEach(accountDto2 -> {
- accountDto2.setProportion(accountDto2.getAccount().divide(totalIncome,2,BigDecimal.ROUND_HALF_UP));
- });
- accountDto.setIncomeType(accountIncomes);
- //鑾峰彇璇ユ鏃堕棿鍐呯殑鎵�鏈夋敮鍑�
- List<AccountDto2> accountExpenses =accountExpenseMapper.report(dateQueryDto);
- accountDto.setExpenseType(accountExpenses);
- Long expenseNumber = accountExpenseMapper.selectCount(Wrappers.<AccountExpense>lambdaQuery()
- .between(AccountExpense::getExpenseDate, dateQueryDto.getEntryDateStart(), dateQueryDto.getEntryDateEnd()));
- accountDto.setExpenseNumber(expenseNumber);
- BigDecimal totalExpense = accountExpenses.stream().map(AccountDto2::getAccount).reduce(BigDecimal.ZERO, BigDecimal::add);
- accountDto.setTotalExpense(totalExpense);
- accountExpenses.stream().forEach(accountDto2 -> {
- accountDto2.setProportion(accountDto2.getAccount().divide(totalExpense,2,BigDecimal.ROUND_HALF_UP));
- });
- accountDto.setExpenseType(accountExpenses);
- //鍑�鏀跺叆
- BigDecimal netRevenue = totalIncome.subtract(totalExpense);
- accountDto.setNetRevenue(netRevenue);
- return accountDto;
- }
-
- //璐㈠姟鎶ヨ〃骞存煡璇�
- @Override
- public List<AccountDto3> reportExpense(ReportDateDto reportDateDto) {
- List<AccountDto3> accountDto3s = new ArrayList<>();
- //鍏堟煡璇㈡敹鍏ョ被鍨嬫湁鍝簺
- List<SysDictData> incomeTypes = sysDictDataMapper.selectDictDataByType("expense_types");
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-// int currentYear = LocalDate.now().getYear(); // 鑾峰彇褰撳墠骞翠唤锛堝2025锛�
- for (SysDictData incomeType : incomeTypes) {
- AccountDto3 accountDto3 = new AccountDto3();
- accountDto3.setTypeName(incomeType.getDictLabel());//绫诲瀷
- List<BigDecimal> account=new ArrayList<>();
- LocalDate startDate = reportDateDto.getEntryDateStart();
- LocalDate endDate = reportDateDto.getEntryDateEnd();
-
- // 鍒濆鍖栧惊鐜彉閲忎负璧峰鏃ユ湡
- LocalDate currentDate = startDate;
-
- // 寰幆锛氬綋鍓嶆棩鏈熶笉瓒呰繃缁撴潫鏃ユ湡鏃剁户缁�
- while (!currentDate.isAfter(endDate)) {
- // 褰撴湀绗竴澶�
- LocalDate firstDay = currentDate.withDayOfMonth(1);
- DateQueryDto dateQueryDto = new DateQueryDto();
- dateQueryDto.setEntryDateStart(firstDay.format(formatter));
-
- // 褰撴湀鏈�鍚庝竴澶�
- LocalDate lastDay = firstDay.plusMonths(1).minusDays(1);
- dateQueryDto.setEntryDateEnd(lastDay.format(formatter));
-
- // 绱姞鏁版嵁
- account.add(accountExpenseMapper.report1(dateQueryDto, incomeType.getDictValue()));
-
- // 鏈堜唤鍔犱竴锛堣嚜鍔ㄥ鐞嗚法骞达紝姣斿12鏈堝姞1涓湀浼氬彉鎴愪笅涓�骞�1鏈堬級
- currentDate = currentDate.plusMonths(1);
- }
- accountDto3.setAccount(account);//绫诲瀷
- accountDto3s.add(accountDto3);
- }
- return accountDto3s;
- }
-
- @Override
- public Map<String, List<String>> analysis() {
- // 鑾峰彇鏈�杩戝洓涓湀锛堝綋鍓嶆湀 + 鍓�3涓湀锛夌殑鏃堕棿鑼冨洿
- LocalDate today = LocalDate.now();
- DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM"); // 骞存湀鏍煎紡鍖栧櫒
- Map<String, List<String>> result = new HashMap<>();
- List<String> months = new ArrayList<>(); // 瀛樺偍骞存湀锛堝 2025-12銆�2025-11锛�
- List<String> totalIncomeList = new ArrayList<>(); // 姣忔湀鎬绘敹鍏�
- List<String> totalExpenseList = new ArrayList<>(); // 姣忔湀鎬绘敮鍑�
- List<String> netIncomeList = new ArrayList<>(); // 姣忔湀鍑�鏀跺叆锛堟敹鍏�-鏀嚭锛�
-
- // 姝ラ1锛氳绠楄繎4涓湀鐨勫勾鏈堝垪琛紙褰撳墠鏈堛�佸墠1鏈堛�佸墠2鏈堛�佸墠3鏈堬級
- List<String> targetMonths = new ArrayList<>();
- for (int i = 0; i < 4; i++) {
- LocalDate currentMonth = today.minusMonths(i);
- String monthStr = currentMonth.format(monthFormatter);
- targetMonths.add(monthStr);
- }
- // 鍙嶈浆鍒楄〃锛岀‘淇濋『搴忎负銆屽墠3鏈� 鈫� 褰撳墠鏈堛�嶏紙鍙�夛紝鎸夐渶姹傝皟鏁撮『搴忥級
- Collections.reverse(targetMonths);
-
- // 姝ラ2锛氫竴娆℃�ф煡璇㈣繎4涓湀鎵�鏈夋敹鍏ユ暟鎹紝鎸夆�滃勾鏈堚�濆垎缁勬眹鎬�
- LocalDate fourMonthsAgo = today.minusMonths(3).withDayOfMonth(1); // 杩�4涓湀璧峰鏃ワ紙鍓�3鏈�1鍙凤級
- LocalDate currentMonthEnd = today.withDayOfMonth(today.lengthOfMonth()); // 褰撳墠鏈堢粨鏉熸棩
- ZoneId zoneId = ZoneId.of("Asia/Shanghai");
- // 鏌ヨ杩�4涓湀鎵�鏈夋敹鍏�
- List<AccountIncome> allIncomes = accountIncomeMapper.selectList(
- Wrappers.<AccountIncome>lambdaQuery()
- .ge(AccountIncome::getIncomeDate, fourMonthsAgo.toString()) // 澶т簬绛変簬璧峰鏃�
- .le(AccountIncome::getIncomeDate, currentMonthEnd.toString()) // 灏忎簬绛変簬缁撴潫鏃�
- );
-
- // 鏀跺叆鎸夆�滃勾鏈堚�濆垎缁勬眹鎬伙紙key锛氬勾鏈堝瓧绗︿覆锛寁alue锛氬綋鏈堟�绘敹鍏ワ級
- Map<String, BigDecimal> monthlyIncomeMap = allIncomes.stream()
- .filter(income -> income.getIncomeMoney() != null) // 杩囨护绌洪噾棰�
- .collect(Collectors.groupingBy(
- income -> {
- // 灏嗚緭鍏ユ椂闂达紙瀛楃涓诧級杞崲涓篖ocalDate锛屽啀鏍煎紡鍖栦负骞存湀
- LocalDate inputDate = income.getIncomeDate().toInstant().atZone(zoneId).toLocalDate();
- return inputDate.format(monthFormatter);
- },
- Collectors.reducing(BigDecimal.ZERO, AccountIncome::getIncomeMoney, BigDecimal::add)
- ));
-
- // 姝ラ3锛氫竴娆℃�ф煡璇㈣繎4涓湀鎵�鏈夋敮鍑烘暟鎹紝鎸夆�滃勾鏈堚�濆垎缁勬眹鎬�
- List<AccountExpense> allExpenses = accountExpenseMapper.selectList(
- Wrappers.<AccountExpense>lambdaQuery()
- .ge(AccountExpense::getExpenseDate, fourMonthsAgo.toString())
- .le(AccountExpense::getExpenseDate, currentMonthEnd.toString())
- );
-
- // 鏀嚭鎸夆�滃勾鏈堚�濆垎缁勬眹鎬�
- Map<String, BigDecimal> monthlyExpenseMap = allExpenses.stream()
- .filter(expense -> expense.getExpenseMoney() != null) // 杩囨护绌洪噾棰�
- .collect(Collectors.groupingBy(
- expense -> {
- LocalDate inputDate = expense.getExpenseDate().toInstant().atZone(zoneId).toLocalDate();
- return inputDate.format(monthFormatter);
- },
- Collectors.reducing(BigDecimal.ZERO, AccountExpense::getExpenseMoney, BigDecimal::add)
- ));
-
- // 姝ラ4锛氬惊鐜�4涓洰鏍囨湀浠斤紝濉厖缁熻鏁版嵁锛堟棤鏁版嵁鏃堕粯璁や负0锛�
- for (String month : targetMonths) {
- // 褰撴湀鎬绘敹鍏ワ紙鏃犳暟鎹垯涓�0锛�
- BigDecimal totalIncome = monthlyIncomeMap.getOrDefault(month, BigDecimal.ZERO);
- // 褰撴湀鎬绘敮鍑猴紙鏃犳暟鎹垯涓�0锛�
- BigDecimal totalExpense = monthlyExpenseMap.getOrDefault(month, BigDecimal.ZERO);
- // 褰撴湀鍑�鏀跺叆锛堟敹鍏� - 鏀嚭锛�
- BigDecimal netIncome = totalIncome.subtract(totalExpense);
-
- // 濉厖鍒楄〃
- months.add(month);
- totalIncomeList.add(totalIncome.toString());
- totalExpenseList.add(totalExpense.toString());
- netIncomeList.add(netIncome.toString());
- }
-
- // 缁勮缁撴灉
- result.put("days", months); // 骞存湀锛堝 ["2025-09", "2025-10", "2025-11", "2025-12"]锛�
- result.put("totalIncome", totalIncomeList); // 瀵瑰簲鏈堜唤鎬绘敹鍏�
- result.put("totalExpense", totalExpenseList); // 瀵瑰簲鏈堜唤鎬绘敮鍑�
- result.put("netIncome", netIncomeList); // 瀵瑰簲鏈堜唤鍑�鏀跺叆
-
- return result;
- }
-
- @Override
- public AccountExpense getByInvoiceNumber(String purchaseContractNumber) {
- return accountExpenseMapper.selectOne(Wrappers.<AccountExpense>lambdaQuery()
- .eq(AccountExpense::getInvoiceNumber, purchaseContractNumber));
- }
-
- @Override
- public List<AccountExpense> getByInvoiceNumberList(String purchaseContractNumber) {
- return accountExpenseMapper.selectList(Wrappers.<AccountExpense>lambdaQuery()
- .eq(AccountExpense::getInvoiceNumber, purchaseContractNumber));
- }
-
-
-}
diff --git a/src/main/java/com/ruoyi/account/service/impl/AccountFileServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/AccountFileServiceImpl.java
deleted file mode 100644
index b1e8f84..0000000
--- a/src/main/java/com/ruoyi/account/service/impl/AccountFileServiceImpl.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.ruoyi.account.service.impl;
-
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.account.mapper.AccountFileMapper;
-import com.ruoyi.account.pojo.AccountFile;
-import com.ruoyi.account.service.AccountFileService;
-import com.ruoyi.quality.mapper.QualityInspectFileMapper;
-import com.ruoyi.quality.pojo.QualityInspectFile;
-import com.ruoyi.quality.service.IQualityInspectFileService;
-import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Service;
-
-@AllArgsConstructor
-@Service
-public class AccountFileServiceImpl extends ServiceImpl<AccountFileMapper, AccountFile> implements AccountFileService {
-
- private AccountFileMapper accountFileMapper;
-
-
- @Override
- public IPage<AccountFile> accountFileListPage(Page page, AccountFile accountFile) {
- return accountFileMapper.accountFileListPage(page,accountFile);
- }
-}
diff --git a/src/main/java/com/ruoyi/account/service/impl/AccountIncomeServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/AccountIncomeServiceImpl.java
deleted file mode 100644
index e760a2d..0000000
--- a/src/main/java/com/ruoyi/account/service/impl/AccountIncomeServiceImpl.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.ruoyi.account.service.impl;
-
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.account.bean.dto.AccountDto3;
-import com.ruoyi.account.bean.dto.ReportDateDto;
-import com.ruoyi.account.mapper.AccountIncomeMapper;
-import com.ruoyi.account.pojo.AccountIncome;
-import com.ruoyi.account.service.AccountIncomeService;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.dto.DateQueryDto;
-import com.ruoyi.project.system.domain.SysDictData;
-import com.ruoyi.project.system.mapper.SysDictDataMapper;
-import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
-
-@AllArgsConstructor
-@Service
-public class AccountIncomeServiceImpl extends ServiceImpl<AccountIncomeMapper, AccountIncome> implements AccountIncomeService {
-
- private AccountIncomeMapper accountIncomeMapper;
-
- private SysDictDataMapper sysDictDataMapper;
-
-
- //鍒嗛〉鏌ヨ
- @Override
- public IPage<AccountIncome> accountIncomeListPage(Page page, AccountIncome accountIncome) {
- resolveIncomeMethodLabelFilter(accountIncome);
- return accountIncomeMapper.accountIncomeListPage(page,accountIncome);
- }
-
- private void resolveIncomeMethodLabelFilter(AccountIncome accountIncome) {
- if (accountIncome == null) {
- return;
- }
- if (accountIncome.getIncomeMethodLabel() == null || accountIncome.getIncomeMethodLabel().trim().isEmpty()) {
- return;
- }
- String targetLabel = accountIncome.getIncomeMethodLabel().trim();
- List<String> paymentMethodList = selectDictValuesByLabel("payment_methods", targetLabel);
- List<String> receiptPaymentMethodList = selectDictValuesByLabel("receipt_payment_type", targetLabel);
- if (paymentMethodList.isEmpty()) {
- paymentMethodList = Collections.singletonList("__NO_MATCH__");
- }
- if (receiptPaymentMethodList.isEmpty()) {
- receiptPaymentMethodList = Collections.singletonList("__NO_MATCH__");
- }
- accountIncome.setPaymentMethodList(paymentMethodList);
- accountIncome.setReceiptPaymentMethodList(receiptPaymentMethodList);
- accountIncome.setIncomeMethod(null);
- }
-
- private List<String> selectDictValuesByLabel(String dictType, String label) {
- return sysDictDataMapper.selectDictDataByType(dictType).stream()
- .filter(item -> label.equals(item.getDictLabel()))
- .map(SysDictData::getDictValue)
- .filter(v -> v != null && !v.trim().isEmpty())
- .distinct()
- .collect(Collectors.toList());
- }
-
- //瀵煎嚭
- @Override
- public void accountIncomeExport(HttpServletResponse response, AccountIncome accountIncome) {
- List<AccountIncome> accountIncomes =accountIncomeMapper.accountIncomeExport(accountIncome);
- ExcelUtil<AccountIncome> util = new ExcelUtil<AccountIncome>(AccountIncome.class);
- util.exportExcel(response, accountIncomes, "鏀跺叆绠$悊瀵煎嚭");
- }
-
- //璐㈠姟鎶ヨ〃骞存煡璇�
- @Override
- public List<AccountDto3> reportIncome(ReportDateDto reportDateDto) {
- List<AccountDto3> accountDto3s = new ArrayList<>();
- //鍏堟煡璇㈡敹鍏ョ被鍨嬫湁鍝簺
- List<SysDictData> incomeTypes = sysDictDataMapper.selectDictDataByType("income_types");
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-// int currentYear = LocalDate.now().getYear(); // 鑾峰彇褰撳墠骞翠唤锛堝2025锛�
- for (SysDictData incomeType : incomeTypes) {
- AccountDto3 accountDto3 = new AccountDto3();
- accountDto3.setTypeName(incomeType.getDictLabel());//绫诲瀷
- List<BigDecimal> account=new ArrayList<>();
- LocalDate startDate = reportDateDto.getEntryDateStart();
- LocalDate endDate = reportDateDto.getEntryDateEnd();
-
- // 鍒濆鍖栧惊鐜彉閲忎负璧峰鏃ユ湡
- LocalDate currentDate = startDate;
-
- // 寰幆锛氬綋鍓嶆棩鏈熶笉瓒呰繃缁撴潫鏃ユ湡鏃剁户缁�
- while (!currentDate.isAfter(endDate)) {
- // 褰撴湀绗竴澶�
- LocalDate firstDay = currentDate.withDayOfMonth(1);
- DateQueryDto dateQueryDto = new DateQueryDto();
- dateQueryDto.setEntryDateStart(firstDay.format(formatter));
-
- // 褰撴湀鏈�鍚庝竴澶�
- LocalDate lastDay = firstDay.plusMonths(1).minusDays(1);
- dateQueryDto.setEntryDateEnd(lastDay.format(formatter));
-
- // 绱姞鏁版嵁
- account.add(accountIncomeMapper.report1(dateQueryDto, incomeType.getDictValue()));
-
- // 鏈堜唤鍔犱竴锛堣嚜鍔ㄥ鐞嗚法骞达紝姣斿12鏈堝姞1涓湀浼氬彉鎴愪笅涓�骞�1鏈堬級
- currentDate = currentDate.plusMonths(1);
- }
- accountDto3.setAccount(account);//绫诲瀷
- accountDto3s.add(accountDto3);
- }
- return accountDto3s;
- }
-
- @Override
- public AccountIncome getByInvoiceNumber(String purchaseContractNumber) {
- AccountIncome accountIncome = accountIncomeMapper.selectOne(new LambdaQueryWrapper<AccountIncome>()
- .eq(AccountIncome::getInvoiceNumber, purchaseContractNumber));
- return accountIncome;
- }
-
- @Override
- public List<AccountIncome> getByInvoiceNumberList(String purchaseContractNumber) {
- return accountIncomeMapper.selectList(new LambdaQueryWrapper<AccountIncome>()
- .eq(AccountIncome::getInvoiceNumber, purchaseContractNumber));
- }
-}
diff --git a/src/main/java/com/ruoyi/account/service/impl/AccountStatementDetailsServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/AccountStatementDetailsServiceImpl.java
new file mode 100644
index 0000000..6d1ba1c
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/impl/AccountStatementDetailsServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.account.service.impl;
+
+import com.ruoyi.account.pojo.AccountStatementDetails;
+import com.ruoyi.account.mapper.AccountStatementDetailsMapper;
+import com.ruoyi.account.service.AccountStatementDetailsService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--瀵硅处鍗曟槑缁� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 10:12:42
+ */
+@Service
+public class AccountStatementDetailsServiceImpl extends ServiceImpl<AccountStatementDetailsMapper, AccountStatementDetails> implements AccountStatementDetailsService {
+
+}
diff --git a/src/main/java/com/ruoyi/account/service/impl/AccountStatementServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/AccountStatementServiceImpl.java
new file mode 100644
index 0000000..411d595
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/impl/AccountStatementServiceImpl.java
@@ -0,0 +1,298 @@
+package com.ruoyi.account.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.account.bean.dto.StatementAccountDto;
+import com.ruoyi.account.bean.dto.purchase.PurchaseInboundDto;
+import com.ruoyi.account.bean.dto.purchase.PurchaseReturnDto;
+import com.ruoyi.account.bean.dto.sales.SalesOutboundDto;
+import com.ruoyi.account.bean.dto.sales.SalesReturnDto;
+import com.ruoyi.account.bean.vo.StatementAccountVo;
+import com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo;
+import com.ruoyi.account.bean.vo.purchase.PurchaseReturnVo;
+import com.ruoyi.account.bean.vo.sales.SalesOutboundVo;
+import com.ruoyi.account.bean.vo.sales.SalesReturnVo;
+import com.ruoyi.account.mapper.AccountStatementDetailsMapper;
+import com.ruoyi.account.mapper.AccountStatementMapper;
+import com.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper;
+import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper;
+import com.ruoyi.account.pojo.AccountStatement;
+import com.ruoyi.account.pojo.AccountStatementDetails;
+import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
+import com.ruoyi.account.pojo.sales.AccountSalesCollection;
+import com.ruoyi.account.service.AccountStatementService;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.procurementrecord.mapper.ReturnManagementMapper;
+import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
+import com.ruoyi.stock.mapper.StockInRecordMapper;
+import com.ruoyi.stock.mapper.StockOutRecordMapper;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.YearMonth;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * <p>
+ * 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 09:42:47
+ */
+@Service
+@RequiredArgsConstructor
+@Transactional(rollbackFor = Exception.class)
+public class AccountStatementServiceImpl extends ServiceImpl<AccountStatementMapper, AccountStatement> implements AccountStatementService {
+
+ private final AccountStatementMapper accountStatementMapper;
+ private final AccountSalesCollectionMapper accountSalesCollectionMapper;
+ private final StockOutRecordMapper stockOutRecordMapper;
+ private final StockInRecordMapper stockInRecordMapper;
+ private final ReturnManagementMapper returnManagementMapper;
+ private final AccountStatementDetailsMapper accountStatementDetailsMapper;
+ private final AccountPurchasePaymentMapper accountPurchasePaymentMapper;
+ private final PurchaseReturnOrdersMapper purchaseReturnOrdersMapper;
+ private static final DateTimeFormatter CODE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyMMdd");
+
+ @Override
+ public StatementAccountVo getAccountStatementDetailsByMonth(StatementAccountDto statementAccountDto) {
+ //瀵硅处鏈堜唤杞崲鎴愬紑濮嬫棩鏈熷拰缁撴潫鏃ユ湡鍖洪棿
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
+ YearMonth yearMonth = YearMonth.parse(statementAccountDto.getStatementMonth(), formatter);
+ statementAccountDto.setStartDate(yearMonth.atDay(1));
+ statementAccountDto.setEndDate(yearMonth.atEndOfMonth());
+ if (statementAccountDto.getAccountType() == 1){
+ //搴旀敹瀵硅处--Customer
+ return getAccountStatementDetailsByCustomerAndMonth(statementAccountDto);
+ }else {
+ //搴斾粯瀵硅处--SupplierManage
+ return getAccountStatementDetailsBySupplierAndMonth(statementAccountDto);
+ }
+ }
+
+ @Override
+ public boolean addAccountStatement(StatementAccountVo statementAccountVo) {
+ //鍚屼竴瀹㈡埛鎴栬�呭悓涓�渚涘簲鍟�,涓�涓湀浠藉彧鑳芥湁涓�涓璐﹀崟
+ List<AccountStatement> accountStatements = accountStatementMapper.selectList(Wrappers.<AccountStatement>lambdaQuery()
+ .eq(AccountStatement::getStatementMonth, statementAccountVo.getStatementMonth())
+ .eq(AccountStatement::getAccountType, statementAccountVo.getAccountType())
+ .eq(AccountStatement::getCustomerId, statementAccountVo.getCustomerId()));
+ if (CollectionUtils.isNotEmpty(accountStatements)){
+ throw new ServiceException("鍚屼竴瀹㈡埛鎴栬�呭悓涓�渚涘簲鍟�,涓�涓湀浠藉彧鑳芥湁涓�涓璐﹀崟");
+ }
+ AccountStatement accountStatement = new AccountStatement();
+ BeanUtils.copyProperties(statementAccountVo, accountStatement);
+ accountStatement.setStatementNumber(genStatementAccountNo());
+ boolean save = save(accountStatement);
+ statementAccountVo.getAccountStatementDetails().stream().forEach(accountStatementDetails -> {
+ accountStatementDetails.setAccountStatementId(accountStatement.getId());
+ //娣诲姞瀵硅处鍗曟槑缁�
+ accountStatementDetailsMapper.insert(accountStatementDetails);
+ });
+ return save;
+ }
+
+ @Override
+ public boolean deleteAccountStatement(List<Long> ids) {
+ //鍒犻櫎瀵硅处鍗曟槑缁�
+ accountStatementDetailsMapper.delete(Wrappers.<AccountStatementDetails>lambdaQuery().in(AccountStatementDetails::getAccountStatementId, ids));
+ return removeByIds(ids);
+ }
+
+ @Override
+ public IPage<StatementAccountVo> listPageAccountStatement(Page page, StatementAccountDto statementAccountDto) {
+ return accountStatementMapper.listPageAccountStatement(page, statementAccountDto);
+ }
+
+ @Override
+ public void exportAccountStatement(HttpServletResponse response, StatementAccountDto statementAccountDto) {
+ List<StatementAccountVo> list = accountStatementMapper.listPageAccountStatement(new Page(1,-1),statementAccountDto).getRecords();
+ ExcelUtil<StatementAccountVo> util = new ExcelUtil<>(StatementAccountVo.class);
+ util.exportExcel(response, list , "瀵硅处鍗�");
+ }
+
+ //鏍规嵁瀹㈡埛鍜屾湀浠借幏鍙栧璐﹁鎯�(閿�鍞�)
+ private StatementAccountVo getAccountStatementDetailsByCustomerAndMonth(StatementAccountDto statementAccountDto) {
+ StatementAccountVo statementAccountVo = new StatementAccountVo();
+ statementAccountVo.setAccountType(1);//搴旀敹瀵硅处
+ List<AccountStatementDetails> accountStatementDetailsList = new ArrayList<>();
+ /*鏌ヨ鍑哄簱鏄庣粏*/
+ SalesOutboundDto salesOutboundDto = new SalesOutboundDto();
+ salesOutboundDto.setCustomerId(statementAccountDto.getCustomerId());
+ salesOutboundDto.setStartDate(statementAccountDto.getStartDate());
+ salesOutboundDto.setEndDate(statementAccountDto.getEndDate());
+ List<SalesOutboundVo> salesOutboundVos = stockOutRecordMapper.listPageAccountSales(new Page(1, -1), salesOutboundDto).getRecords();
+ salesOutboundVos.stream().forEach(salesOutboundVo -> {
+ AccountStatementDetails accountStatementDetails = new AccountStatementDetails();
+ //鏁版嵁鏃ユ湡=鍑哄簱鏃ユ湡
+ accountStatementDetails.setOccurrenceDate(salesOutboundVo.getShippingDate());
+ //鍗曟嵁缂栧彿=鍑哄簱鍗曞彿
+ accountStatementDetails.setReceiptNumber(salesOutboundVo.getOutboundBatches());
+ //绫诲瀷=鍑哄簱
+ accountStatementDetails.setType(1);
+ //閲戦=鍑哄簱閲戦
+ accountStatementDetails.setAmount(salesOutboundVo.getOutboundAmount());
+ //澶囨敞
+ accountStatementDetails.setRemark("浜у搧閿�鍞嚭搴擄紝浜у搧锛�"+salesOutboundVo.getProductName());
+ accountStatementDetailsList.add(accountStatementDetails);
+ });
+ /*鏌ヨ鏀舵鏄庣粏*/
+ List<AccountSalesCollection> accountSalesCollections = accountSalesCollectionMapper.selectList(Wrappers.<AccountSalesCollection>lambdaQuery()
+ .eq(AccountSalesCollection::getCustomerId, statementAccountDto.getCustomerId())
+ .between(AccountSalesCollection::getCollectionDate, statementAccountDto.getStartDate(), statementAccountDto.getEndDate()));
+ accountSalesCollections.stream().forEach(accountSalesCollection -> {
+ AccountStatementDetails accountStatementDetails = new AccountStatementDetails();
+ //鏁版嵁鏃ユ湡=鏀舵鏃ユ湡
+ accountStatementDetails.setOccurrenceDate(accountSalesCollection.getCollectionDate());
+ //鍗曟嵁缂栧彿=鏀舵鍗曞彿
+ accountStatementDetails.setReceiptNumber(accountSalesCollection.getCollectionNumber());
+ //绫诲瀷=鏀舵
+ accountStatementDetails.setType(3);
+ //閲戦=鏀舵閲戦
+ accountStatementDetails.setAmount(accountSalesCollection.getCollectionAmount());
+ //澶囨敞
+ accountStatementDetails.setRemark("瀹㈡埛鍥炴锛屽娉細"+accountSalesCollection.getRemark());
+ accountStatementDetailsList.add(accountStatementDetails);
+ });
+ /*鏌ヨ閫�璐ф槑缁�*/
+ SalesReturnDto salesReturnDto = new SalesReturnDto();
+ salesReturnDto.setCustomerId(statementAccountDto.getCustomerId());
+ salesReturnDto.setStartDate(statementAccountDto.getStartDate());
+ salesReturnDto.setEndDate(statementAccountDto.getEndDate());
+ List<SalesReturnVo> salesReturnVos = returnManagementMapper.listPageAccountSalesReturn(new Page(1, -1), salesReturnDto).getRecords();
+ salesReturnVos.stream().forEach(salesReturnVo -> {
+ AccountStatementDetails accountStatementDetails = new AccountStatementDetails();
+ //鏁版嵁鏃ユ湡=閫�璐ф棩鏈�
+ accountStatementDetails.setOccurrenceDate(salesReturnVo.getMakeTime().toLocalDate());
+ //鍗曟嵁缂栧彿=閫�璐у崟鍙�
+ accountStatementDetails.setReceiptNumber(salesReturnVo.getReturnNo());
+ //绫诲瀷=閫�璐�
+ accountStatementDetails.setType(5);
+ //閲戦=閫�娆鹃噾棰�
+ accountStatementDetails.setAmount(salesReturnVo.getRefundAmount());
+ //澶囨敞
+ accountStatementDetails.setRemark("浜у搧閫�璐э紝鍘熷洜锛�"+salesReturnVo.getReturnReason());
+ accountStatementDetailsList.add(accountStatementDetails);
+ });
+ //鏈熷垵浣欓=涓婁釜鏈堢殑鏈熸湯浣欓
+ statementAccountVo.setOpeningBalance(BigDecimal.ZERO);
+ List<AccountStatement> accountStatements = accountStatementMapper.selectList(Wrappers.<AccountStatement>lambdaQuery()
+ .eq(AccountStatement::getAccountType, 1)
+ .eq(AccountStatement::getCustomerId, statementAccountDto.getCustomerId())
+ .eq(AccountStatement::getStatementMonth,
+ YearMonth.parse(statementAccountDto.getStatementMonth()).minusMonths(1).toString()));
+ if (CollectionUtils.isNotEmpty(accountStatements)){
+ statementAccountVo.setOpeningBalance(accountStatements.get(accountStatements.size() - 1).getClosingBalance());
+ }
+ //鏈湡搴旀敹=鍑哄簱-閫�璐ч噾棰濈疮璁�
+ statementAccountVo.setCurrentPlan(salesOutboundVos.stream().map(SalesOutboundVo::getOutboundAmount).reduce(BigDecimal.ZERO, BigDecimal::add)
+ .subtract(salesReturnVos.stream().map(SalesReturnVo::getRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add)));
+ //鏈湡鏀舵=鏀舵閲戦绱
+ statementAccountVo.setCurrentActually(accountSalesCollections.stream().map(AccountSalesCollection::getCollectionAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
+ //鏈熸湯浣欓=鏈熷垵+搴旀敹-鏀舵
+ statementAccountVo.setClosingBalance(statementAccountVo.getOpeningBalance().add(statementAccountVo.getCurrentPlan()).subtract(statementAccountVo.getCurrentActually()));
+ statementAccountVo.setAccountStatementDetails(accountStatementDetailsList);
+ return statementAccountVo;
+ }
+
+ //鏍规嵁渚涘簲鍟嗗拰鏈堜唤鑾峰彇瀵硅处璇︽儏(閲囪喘)
+ private StatementAccountVo getAccountStatementDetailsBySupplierAndMonth(StatementAccountDto statementAccountDto) {
+ StatementAccountVo statementAccountVo = new StatementAccountVo();
+ statementAccountVo.setAccountType(2);//搴斾粯瀵硅处
+ List<AccountStatementDetails> accountStatementDetailsList = new ArrayList<>();
+ /*鏌ヨ鍏ュ簱鏄庣粏*/
+ PurchaseInboundDto purchaseInboundDto = new PurchaseInboundDto();
+ purchaseInboundDto.setSupplierId(statementAccountDto.getCustomerId());
+ purchaseInboundDto.setStartDate(statementAccountDto.getStartDate());
+ purchaseInboundDto.setEndDate(statementAccountDto.getEndDate());
+ List<PurchaseInboundVo> purchaseInboundVos = stockInRecordMapper.listPageAccountPurchase(new Page(1, -1), purchaseInboundDto).getRecords();
+ purchaseInboundVos.stream().forEach(purchaseInboundVo -> {
+ AccountStatementDetails accountStatementDetails = new AccountStatementDetails();
+ //鏁版嵁鏃ユ湡=鍏ュ簱鏃ユ湡
+ accountStatementDetails.setOccurrenceDate(purchaseInboundVo.getInboundDate());
+ //鍗曟嵁缂栧彿=鍏ュ簱鍗曞彿
+ accountStatementDetails.setReceiptNumber(purchaseInboundVo.getInboundBatches());
+ //绫诲瀷=鍏ュ簱
+ accountStatementDetails.setType(2);
+ //閲戦=鍏ュ簱閲戦
+ accountStatementDetails.setAmount(purchaseInboundVo.getInboundAmount());
+ //澶囨敞
+ accountStatementDetails.setRemark("浜у搧閲囪喘鍏ュ簱锛屼骇鍝侊細"+purchaseInboundVo.getProductName());
+ accountStatementDetailsList.add(accountStatementDetails);
+ });
+ /*鏌ヨ浠樻鏄庣粏*/
+ List<AccountPurchasePayment> accountPurchasePayments = accountPurchasePaymentMapper.selectList(Wrappers.<AccountPurchasePayment>lambdaQuery()
+ .eq(AccountPurchasePayment::getSupplierId, statementAccountDto.getCustomerId())
+ .between(AccountPurchasePayment::getPaymentDate, statementAccountDto.getStartDate(), statementAccountDto.getEndDate()));
+ accountPurchasePayments.stream().forEach(accountPurchasePayment -> {
+ AccountStatementDetails accountStatementDetails = new AccountStatementDetails();
+ //鏁版嵁鏃ユ湡=浠樻鏃ユ湡
+ accountStatementDetails.setOccurrenceDate(accountPurchasePayment.getPaymentDate());
+ //鍗曟嵁缂栧彿=浠樻鍗曞彿
+ accountStatementDetails.setReceiptNumber(accountPurchasePayment.getPaymentNumber());
+ //绫诲瀷=浠樻
+ accountStatementDetails.setType(4);
+ //閲戦=浠樻閲戦
+ accountStatementDetails.setAmount(accountPurchasePayment.getPaymentAmount());
+ //澶囨敞
+ accountStatementDetails.setRemark("鏀粯璐ф锛屽娉細"+accountPurchasePayment.getRemark());
+ accountStatementDetailsList.add(accountStatementDetails);
+ });
+ /*鏌ヨ閫�璐ф槑缁�*/
+ PurchaseReturnDto purchaseReturnDto = new PurchaseReturnDto();
+ purchaseReturnDto.setSupplierId(statementAccountDto.getCustomerId());
+ purchaseReturnDto.setStartDate(statementAccountDto.getStartDate());
+ purchaseReturnDto.setEndDate(statementAccountDto.getEndDate());
+ List<PurchaseReturnVo> purchaseReturnVos = purchaseReturnOrdersMapper.listPageAccountPurchaseReturn(new Page(1, -1), purchaseReturnDto).getRecords();
+ purchaseReturnVos.stream().forEach(purchaseReturnVo -> {
+ AccountStatementDetails accountStatementDetails = new AccountStatementDetails();
+ //鏁版嵁鏃ユ湡=閫�璐ф棩鏈�
+ accountStatementDetails.setOccurrenceDate(purchaseReturnVo.getPreparedAt().toLocalDate());
+ //鍗曟嵁缂栧彿=閫�璐у崟鍙�
+ accountStatementDetails.setReceiptNumber(purchaseReturnVo.getReturnNo());
+ //绫诲瀷=閫�璐�
+ accountStatementDetails.setType(5);
+ //閲戦=閫�娆鹃噾棰�
+ accountStatementDetails.setAmount(purchaseReturnVo.getTotalAmount());
+ //澶囨敞
+ accountStatementDetails.setRemark("浜у搧閫�璐э紝閫�璐ф柟寮忥細"+purchaseReturnVo.getReturnType());
+ accountStatementDetailsList.add(accountStatementDetails);
+ });
+ //鏈熷垵浣欓=涓婁釜鏈堢殑鏈熸湯浣欓
+ statementAccountVo.setOpeningBalance(BigDecimal.ZERO);
+ List<AccountStatement> accountStatements = accountStatementMapper.selectList(Wrappers.<AccountStatement>lambdaQuery()
+ .eq(AccountStatement::getAccountType, 2)
+ .eq(AccountStatement::getCustomerId, statementAccountDto.getCustomerId())
+ .eq(AccountStatement::getStatementMonth,
+ YearMonth.parse(statementAccountDto.getStatementMonth()).minusMonths(1).toString()));
+ if (CollectionUtils.isNotEmpty(accountStatements)){
+ statementAccountVo.setOpeningBalance(accountStatements.get(accountStatements.size() - 1).getClosingBalance());
+ }
+ //鏈湡搴斾粯=鍏ュ簱-閫�璐ч噾棰濈疮璁�
+ statementAccountVo.setCurrentPlan(purchaseInboundVos.stream().map(PurchaseInboundVo::getInboundAmount).reduce(BigDecimal.ZERO, BigDecimal::add)
+ .subtract(purchaseReturnVos.stream().map(PurchaseReturnVo::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add)));
+ //鏈湡浠樻=浠樻閲戦绱
+ statementAccountVo.setCurrentActually(accountPurchasePayments.stream().map(AccountPurchasePayment::getPaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
+ //鏈熸湯浣欓=鏈熷垵+搴旀敹-鏀舵
+ statementAccountVo.setClosingBalance(statementAccountVo.getOpeningBalance().add(statementAccountVo.getCurrentPlan()).subtract(statementAccountVo.getCurrentActually()));
+ statementAccountVo.setAccountStatementDetails(accountStatementDetailsList);
+ return statementAccountVo;
+ }
+
+ private String genStatementAccountNo() {
+ return "DZ" + LocalDateTime.now().format(CODE_TIME_FORMATTER) + new Random().nextInt(10);
+ }
+}
diff --git a/src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java
index ab38285..f42599a 100644
--- a/src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java
+++ b/src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java
@@ -3,27 +3,47 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.AccountReportDto;
import com.ruoyi.account.bean.dto.DeviceTypeDetail;
import com.ruoyi.account.bean.dto.DeviceTypeDistributionVO;
-import com.ruoyi.account.mapper.BorrowInfoMapper;
-import com.ruoyi.account.pojo.BorrowInfo;
+import com.ruoyi.account.bean.dto.purchase.PurchaseInboundDto;
+import com.ruoyi.account.bean.dto.purchase.PurchaseReturnDto;
+import com.ruoyi.account.bean.dto.sales.SalesOutboundDto;
+import com.ruoyi.account.bean.dto.sales.SalesReturnDto;
+import com.ruoyi.account.bean.vo.AccountReportVo;
+import com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo;
+import com.ruoyi.account.bean.vo.purchase.PurchaseReturnVo;
+import com.ruoyi.account.bean.vo.sales.SalesOutboundVo;
+import com.ruoyi.account.bean.vo.sales.SalesReturnVo;
+import com.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper;
+import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper;
+import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
+import com.ruoyi.account.pojo.sales.AccountSalesCollection;
+import com.ruoyi.account.service.AccountingService;
import com.ruoyi.device.mapper.DeviceLedgerMapper;
import com.ruoyi.device.pojo.DeviceLedger;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.procurementrecord.mapper.CustomStorageMapper;
import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper;
import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper;
+import com.ruoyi.procurementrecord.mapper.ReturnManagementMapper;
import com.ruoyi.procurementrecord.pojo.CustomStorage;
import com.ruoyi.procurementrecord.pojo.ProcurementRecordOut;
import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
+import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
+import com.ruoyi.stock.mapper.StockInRecordMapper;
+import com.ruoyi.stock.mapper.StockOutRecordMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
+import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Year;
+import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
@@ -35,14 +55,21 @@
@Service
@Slf4j
@RequiredArgsConstructor
-public class AccountingServiceImpl {
+public class AccountingServiceImpl implements AccountingService {
private final DeviceLedgerMapper deviceLedgerMapper;
- private final BorrowInfoMapper borrowInfoMapper;
private final CustomStorageMapper customStorageMapper;
private final ProcurementRecordMapper procurementRecordMapper;
private final ProcurementRecordOutMapper procurementRecordOutMapper;
+ private final AccountSalesCollectionMapper accountSalesCollectionMapper;
+ private final AccountPurchasePaymentMapper accountPurchasePaymentMapper;
+ private final StockOutRecordMapper stockOutRecordMapper;
+ private final ReturnManagementMapper returnManagementMapper;
+ private final StockInRecordMapper stockInRecordMapper;
+ private final PurchaseReturnOrdersMapper purchaseReturnOrdersMapper;
+
+ @Override
public AjaxResult total(Integer year) {
Map<String,Object> map = new HashMap<>();
map.put("deprAmount",0); // 鎶樻棫閲戦
@@ -75,17 +102,8 @@
map.put("netValue",reduce.subtract(total));
}
// 璐熷��
- LambdaQueryWrapper<BorrowInfo> borrowInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
- borrowInfoLambdaQueryWrapper.like(BorrowInfo::getCreateTime,year)
- .eq(BorrowInfo::getStatus,1);
- List<BorrowInfo> borrowInfos = borrowInfoMapper.selectList(borrowInfoLambdaQueryWrapper);
- if(CollectionUtils.isNotEmpty(borrowInfos)){
- BigDecimal reduce = borrowInfos.stream()
- .map(BorrowInfo::getBorrowAmount)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- map.put("debt",reduce);
- }
+ map.put("debt",BigDecimal.ZERO);
+
// 搴撳瓨璧勪骇
LambdaQueryWrapper<ProcurementRecordStorage> procurementRecordStorageLambdaQueryWrapper = new LambdaQueryWrapper<>();
procurementRecordStorageLambdaQueryWrapper.like(ProcurementRecordStorage::getCreateTime,year);
@@ -245,6 +263,7 @@
return totalDepreciation.setScale(2, BigDecimal.ROUND_HALF_UP);
}
+ @Override
public AjaxResult deviceTypeDistribution(Integer year) {
// 2. 缁勮杩斿洖VO
DeviceTypeDistributionVO vo = new DeviceTypeDistributionVO();
@@ -268,6 +287,7 @@
return AjaxResult.success(vo);
}
+ @Override
public AjaxResult calculateDepreciation(Page page, Integer year) {
LambdaQueryWrapper<DeviceLedger> deviceLedgerLambdaQueryWrapper = new LambdaQueryWrapper<>();
deviceLedgerLambdaQueryWrapper.like(DeviceLedger::getCreateTime,year)
@@ -279,4 +299,159 @@
}
return AjaxResult.success(deviceLedgerIPage);
}
+
+ @Override
+ public AccountReportVo getAccountStatementDetailsByMonth(AccountReportDto accountReportDto) {
+ AccountReportVo accountReportVo = new AccountReportVo();
+ LocalDate start = accountReportDto.getEntryDateStart();
+ LocalDate end = accountReportDto.getEntryDateEnd();
+ DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
+
+ // ========== 1. 椤堕儴鍗$墖鏁版嵁 ==========
+ // 1.1 鎬昏惀鏀� = 鏀舵鍗曟�婚噾棰�
+ List<AccountSalesCollection> accountSalesCollections = accountSalesCollectionMapper.selectList(
+ Wrappers.<AccountSalesCollection>lambdaQuery()
+ .between(AccountSalesCollection::getCollectionDate, start, end)
+ );
+ BigDecimal totalIncome = Optional.of(
+ accountSalesCollections.stream()
+ .map(AccountSalesCollection::getCollectionAmount)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add)
+ ).orElse(BigDecimal.ZERO);
+ accountReportVo.setTotalIncome(totalIncome);
+ // 1.2 鎬绘敮鍑� = 浠樻鍗曟�婚噾棰�
+ List<AccountPurchasePayment> accountPurchasePayments = accountPurchasePaymentMapper.selectList(
+ Wrappers.<AccountPurchasePayment>lambdaQuery()
+ .between(AccountPurchasePayment::getPaymentDate, start, end)
+ );
+ BigDecimal totalExpense = Optional.of(
+ accountPurchasePayments.stream()
+ .map(AccountPurchasePayment::getPaymentAmount)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add)
+ ).orElse(BigDecimal.ZERO);
+ accountReportVo.setTotalExpense(totalExpense);
+ // 1.3 搴旀敹璐︽ = 閿�鍞嚭搴撻噾棰濆悎璁� - 閿�鍞��璐ч噾棰濆悎璁�
+ SalesOutboundDto salesOutboundDto = new SalesOutboundDto();
+ salesOutboundDto.setStartDate(accountReportDto.getEntryDateStart());
+ salesOutboundDto.setEndDate(accountReportDto.getEntryDateEnd());
+ List<SalesOutboundVo> salesOutboundVos = stockOutRecordMapper.listPageAccountSales(new Page(1, -1), salesOutboundDto).getRecords();
+ BigDecimal salesOutAmount = Optional.of(
+ salesOutboundVos.stream()
+ .map(SalesOutboundVo::getOutboundAmount)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add)
+ ).orElse(BigDecimal.ZERO);
+ SalesReturnDto salesReturnDto = new SalesReturnDto();
+ salesReturnDto.setStartDate(accountReportDto.getEntryDateStart());
+ salesReturnDto.setEndDate(accountReportDto.getEntryDateEnd());
+ List<SalesReturnVo> salesReturnVos = returnManagementMapper.listPageAccountSalesReturn(new Page(1, -1), salesReturnDto).getRecords();
+ BigDecimal salesReturnAmount = Optional.of(
+ salesReturnVos.stream()
+ .map(SalesReturnVo::getRefundAmount)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add)
+ ).orElse(BigDecimal.ZERO);
+ accountReportVo.setAccountsReceivable(salesOutAmount.subtract(salesReturnAmount));
+ // 1.4 搴斾粯璐︽ = 閲囪喘鍏ュ簱閲戦鍚堣 - 閲囪喘閫�璐ч噾棰濆悎璁�
+ PurchaseInboundDto purchaseInboundDto = new PurchaseInboundDto();
+ purchaseInboundDto.setStartDate(accountReportDto.getEntryDateStart());
+ purchaseInboundDto.setEndDate(accountReportDto.getEntryDateEnd());
+ List<PurchaseInboundVo> purchaseInboundVos = stockInRecordMapper.listPageAccountPurchase(new Page(1, -1), purchaseInboundDto).getRecords();
+ BigDecimal purchaseInAmount = Optional.of(
+ purchaseInboundVos.stream()
+ .map(PurchaseInboundVo::getInboundAmount)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add)
+ ).orElse(BigDecimal.ZERO);
+ PurchaseReturnDto purchaseReturnDto = new PurchaseReturnDto();
+ purchaseReturnDto.setStartDate(accountReportDto.getEntryDateStart());
+ purchaseReturnDto.setEndDate(accountReportDto.getEntryDateEnd());
+ List<PurchaseReturnVo> purchaseReturnVos = purchaseReturnOrdersMapper.listPageAccountPurchaseReturn(new Page(1, -1), purchaseReturnDto).getRecords();
+ BigDecimal purchaseReturnAmount = Optional.of(
+ purchaseReturnVos.stream()
+ .map(PurchaseReturnVo::getTotalAmount)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add)
+ ).orElse(BigDecimal.ZERO);
+ accountReportVo.setAccountsPayable(purchaseInAmount.subtract(purchaseReturnAmount));
+ // 1.5 鍑�鍒╂鼎 = 鎬昏惀鏀� - 鎬绘敮鍑�
+ BigDecimal netProfit = totalIncome.subtract(totalExpense);
+ accountReportVo.setNetRevenue(netProfit);
+
+ // ========== 2. 鎶樼嚎鍥撅細鏈堝害钀ユ敹/鏀嚭/鍑�鍒╂鼎瓒嬪娍 ==========
+ Map<String, BigDecimal> monthIncomeMap = new HashMap<>();
+ Map<String, BigDecimal> monthExpenseMap = new HashMap<>();
+ // 鏈堝害钀ユ敹
+ accountSalesCollections.forEach(item -> {
+ String month = item.getCollectionDate().format(monthFormatter);
+ monthIncomeMap.put(month, monthIncomeMap.getOrDefault(month, BigDecimal.ZERO)
+ .add(Optional.ofNullable(item.getCollectionAmount()).orElse(BigDecimal.ZERO)));
+ });
+ // 鏈堝害鏀嚭
+ accountPurchasePayments.forEach(item -> {
+ String month = item.getPaymentDate().format(monthFormatter);
+ monthExpenseMap.put(month, monthExpenseMap.getOrDefault(month, BigDecimal.ZERO)
+ .add(Optional.ofNullable(item.getPaymentAmount()).orElse(BigDecimal.ZERO)));
+ });
+ // 鐢熸垚杩炵画鏈堜唤鍒楄〃
+ List<String> monthList = new ArrayList<>();
+ LocalDate current = start.withDayOfMonth(1);
+ while (!current.isAfter(end.withDayOfMonth(1))) {
+ monthList.add(current.format(monthFormatter));
+ current = current.plusMonths(1);
+ }
+ // 缁勮瓒嬪娍鏁版嵁
+ List<AccountReportVo.MonthlyTrendVO> trendList = new ArrayList<>();
+ for (String month : monthList) {
+ BigDecimal income = monthIncomeMap.getOrDefault(month, BigDecimal.ZERO);
+ BigDecimal expense = monthExpenseMap.getOrDefault(month, BigDecimal.ZERO);
+ AccountReportVo.MonthlyTrendVO trend = new AccountReportVo.MonthlyTrendVO();
+ trend.setMonth(month);
+ trend.setIncome(income);
+ trend.setExpense(expense);
+ trend.setProfit(income.subtract(expense));
+ trendList.add(trend);
+ }
+ accountReportVo.setMonthlyTrendList(trendList);
+
+ // ========== 3. 鏌辩姸鍥撅細鏈堝害搴旀敹/搴斾粯鏁版嵁 ==========
+ Map<String, BigDecimal> monthReceivableMap = new HashMap<>();
+ Map<String, BigDecimal> monthPayableMap = new HashMap<>();
+ // 鏈堝害搴旀敹锛堥攢鍞嚭搴�-閫�璐э級
+ salesOutboundVos.forEach(item -> {
+ String month = item.getShippingDate().format(monthFormatter);
+ monthReceivableMap.put(month, monthReceivableMap.getOrDefault(month, BigDecimal.ZERO)
+ .add(Optional.ofNullable(item.getOutboundAmount()).orElse(BigDecimal.ZERO)));
+ });
+ salesReturnVos.forEach(item -> {
+ String month = item.getMakeTime().format(monthFormatter);
+ monthReceivableMap.put(month, monthReceivableMap.getOrDefault(month, BigDecimal.ZERO)
+ .subtract(Optional.ofNullable(item.getRefundAmount()).orElse(BigDecimal.ZERO)));
+ });
+
+ // 鏈堝害搴斾粯锛堥噰璐叆搴�-閫�璐э級
+ purchaseInboundVos.forEach(item -> {
+ String month = item.getInboundDate().format(monthFormatter);
+ monthPayableMap.put(month, monthPayableMap.getOrDefault(month, BigDecimal.ZERO)
+ .add(Optional.ofNullable(item.getInboundAmount()).orElse(BigDecimal.ZERO)));
+ });
+ purchaseReturnVos.forEach(item -> {
+ String month = item.getPreparedAt().format(monthFormatter);
+ monthPayableMap.put(month, monthPayableMap.getOrDefault(month, BigDecimal.ZERO)
+ .subtract(Optional.ofNullable(item.getTotalAmount()).orElse(BigDecimal.ZERO)));
+ });
+ // 缁勮搴旀敹搴斾粯鏁版嵁
+ List<AccountReportVo.ReceivablePayableVO> rpList = new ArrayList<>();
+ for (String month : monthList) {
+ AccountReportVo.ReceivablePayableVO rp = new AccountReportVo.ReceivablePayableVO();
+ rp.setMonth(month);
+ rp.setReceivable(monthReceivableMap.getOrDefault(month, BigDecimal.ZERO));
+ rp.setPayable(monthPayableMap.getOrDefault(month, BigDecimal.ZERO));
+ rpList.add(rp);
+ }
+ accountReportVo.setReceivablePayableList(rpList);
+ return accountReportVo;
+ }
}
diff --git a/src/main/java/com/ruoyi/account/service/impl/BorrowInfoServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/BorrowInfoServiceImpl.java
deleted file mode 100644
index 773799d..0000000
--- a/src/main/java/com/ruoyi/account/service/impl/BorrowInfoServiceImpl.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package com.ruoyi.account.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.account.mapper.BorrowInfoMapper;
-import com.ruoyi.account.pojo.AccountExpense;
-import com.ruoyi.account.pojo.AccountIncome;
-import com.ruoyi.account.pojo.BorrowInfo;
-import com.ruoyi.account.service.AccountExpenseService;
-import com.ruoyi.account.service.AccountIncomeService;
-import com.ruoyi.account.service.BorrowInfoService;
-import com.ruoyi.common.utils.DateUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-/**
- * <p>
- * 鍊熸淇℃伅琛� 鏈嶅姟瀹炵幇绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-15 02:57:29
- */
-@Service
-@Slf4j
-@RequiredArgsConstructor
-public class BorrowInfoServiceImpl extends ServiceImpl<BorrowInfoMapper, BorrowInfo> implements BorrowInfoService {
-
- private final BorrowInfoMapper borrowInfoMapper;
- private final AccountIncomeService accountIncomeService;
- private final AccountExpenseService accountExpenseService;
-
- @Override
- public AjaxResult listPage(Page page, BorrowInfo borrowInfo) {
- LambdaQueryWrapper<BorrowInfo> borrowInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
- if(borrowInfo != null){
- if(StringUtils.isNotEmpty(borrowInfo.getEntryDateStart()) && StringUtils.isNotEmpty(borrowInfo.getEntryDateEnd())){
- borrowInfoLambdaQueryWrapper.ge(BorrowInfo::getBorrowDate, borrowInfo.getEntryDateStart());
- borrowInfoLambdaQueryWrapper.le(BorrowInfo::getBorrowDate, borrowInfo.getEntryDateEnd());
- }
- if(borrowInfo.getStatus() != null){
- borrowInfoLambdaQueryWrapper.eq(BorrowInfo::getStatus, borrowInfo.getStatus());
- }
- if(StringUtils.isNotEmpty(borrowInfo.getBorrowerName())){
- borrowInfoLambdaQueryWrapper.like(BorrowInfo::getBorrowerName, borrowInfo.getBorrowerName());
- }
- }
- return AjaxResult.success(borrowInfoMapper.selectPage(page, borrowInfoLambdaQueryWrapper));
- }
-
- @Override
- public AjaxResult add(BorrowInfo borrowInfo) {
- int insert = borrowInfoMapper.insert(borrowInfo);
- if(insert > 0){
- // 娣诲姞鎴愬姛锛岃繘鍏ユ敹鍏ョ鐞�
- AccountIncome accountIncome = new AccountIncome();
- accountIncome.setBusinessId(borrowInfo.getId());
- accountIncome.setBusinessType(2);
- accountIncome.setIncomeDate(DateUtils.toDate(borrowInfo.getBorrowDate()));
- accountIncome.setIncomeType("2");
- accountIncome.setIncomeMoney(borrowInfo.getBorrowAmount());
- accountIncome.setIncomeDescribed("鍊熸");
- accountIncome.setIncomeMethod("3");
- accountIncome.setInputTime(DateUtils.getNowDate());
- accountIncome.setInputUser(borrowInfo.getBorrowerName());
- accountIncomeService.save(accountIncome);
- return AjaxResult.success("娣诲姞鎴愬姛");
- }
- return AjaxResult.success("娣诲姞澶辫触");
- }
-
- @Override
- public AjaxResult updateBorrowInfo(BorrowInfo borrowInfo) {
- int update = borrowInfoMapper.updateById(borrowInfo);
- if(update > 0){
- // 淇敼鎴愬姛锛屼慨鏀规敹鍏ョ鐞�
- AccountIncome one = accountIncomeService.getOne(new LambdaQueryWrapper<AccountIncome>()
- .eq(AccountIncome::getBusinessId, borrowInfo.getId())
- .eq(AccountIncome::getBusinessType, 2)
- .last("limit 1"));
- if(one != null){
- one.setIncomeMoney(borrowInfo.getBorrowAmount());
- accountIncomeService.updateById(one);
- }
- // 鏄惁涓鸿繕娆�
- if(borrowInfo.getStatus() != null && borrowInfo.getStatus() == 2){
- // 鏂板鏀嚭璁板綍
- AccountExpense accountExpense = new AccountExpense();
- accountExpense.setBusinessId(borrowInfo.getId());
- accountExpense.setBusinessType(2);
- accountExpense.setExpenseDate(DateUtils.toDate(borrowInfo.getRepayDate()));
- accountExpense.setExpenseType("5");
- accountExpense.setExpenseMoney(borrowInfo.getBorrowAmount());
- accountExpense.setExpenseDescribed("杩樻");
- accountExpense.setExpenseMethod("3");
- accountExpense.setInputTime(DateUtils.getNowDate());
- accountExpense.setInputUser(borrowInfo.getBorrowerName());
- accountExpenseService.save(accountExpense);
- }
- return AjaxResult.success("淇敼鎴愬姛");
- }
- return AjaxResult.success("淇敼澶辫触");
- }
-
- @Override
- public AjaxResult delete(List<Long> ids) {
- int delete = borrowInfoMapper.deleteBatchIds(ids);
- if(delete > 0){
- // 鍒犻櫎鎴愬姛锛屽垹闄ゆ敹鍏ョ鐞�
- accountIncomeService.remove(new LambdaQueryWrapper<AccountIncome>()
- .in(AccountIncome::getBusinessId, ids)
- .eq(AccountIncome::getBusinessType, 2));
- // 鍒犻櫎鏀嚭绠$悊
- accountExpenseService.remove(new LambdaQueryWrapper<AccountExpense>()
- .in(AccountExpense::getBusinessId, ids)
- .eq(AccountExpense::getBusinessType, 2));
- return AjaxResult.success("鍒犻櫎鎴愬姛");
- }
- return AjaxResult.success("鍒犻櫎澶辫触");
- }
-}
diff --git a/src/main/java/com/ruoyi/account/service/impl/purchase/AccountPaymentApplicationServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/purchase/AccountPaymentApplicationServiceImpl.java
new file mode 100644
index 0000000..9eecc49
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/impl/purchase/AccountPaymentApplicationServiceImpl.java
@@ -0,0 +1,96 @@
+package com.ruoyi.account.service.impl.purchase;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.account.bean.dto.purchase.AccountPaymentApplicationDto;
+import com.ruoyi.account.bean.vo.purchase.AccountPaymentApplicationVo;
+import com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo;
+import com.ruoyi.account.mapper.purchase.AccountPaymentApplicationMapper;
+import com.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper;
+import com.ruoyi.account.pojo.purchase.AccountPaymentApplication;
+import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
+import com.ruoyi.account.service.purchase.AccountPaymentApplicationService;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--浠樻鐢宠 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 03:44:22
+ */
+@Service
+@RequiredArgsConstructor
+public class AccountPaymentApplicationServiceImpl extends ServiceImpl<AccountPaymentApplicationMapper, AccountPaymentApplication> implements AccountPaymentApplicationService {
+
+ private final AccountPaymentApplicationMapper accountPaymentApplicationMapper;
+ private final AccountPurchasePaymentMapper accountPurchasePaymentMapper;
+ private static final DateTimeFormatter CODE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyMMddHHmmss");
+
+ @Override
+ public IPage<AccountPaymentApplicationVo> listPageAccountPaymentApplication(Page page, AccountPaymentApplicationDto accountPaymentApplicationDto) {
+ return accountPaymentApplicationMapper.listPageAccountPaymentApplication(page, accountPaymentApplicationDto);
+ }
+
+ @Override
+ public List<PurchaseInboundVo> getInboundBatchesBySupplier(Integer supplierId) {
+ return accountPaymentApplicationMapper.getInboundBatchesBySupplier(supplierId);
+ }
+
+ @Override
+ public boolean addAccountPaymentApplication(AccountPaymentApplication accountPaymentApplication) {
+ if (StringUtils.isEmpty(accountPaymentApplication.getInvoiceApplicationNo())) {
+ accountPaymentApplication.setInvoiceApplicationNo(genPaymentApplicationNo());
+ }
+ String stockInRecordIds= accountPaymentApplication.getStockInRecordIds();
+ if (stockInRecordIds != null && !stockInRecordIds.isEmpty()) {
+ List<Long> ids = Arrays.stream(stockInRecordIds.split(","))
+ .map(Long::valueOf)
+ .toList();
+ if (accountPaymentApplicationMapper.existsByStockInRecordId(ids)){
+ throw new ServiceException("瀛樺湪閲嶅鐨勫叆搴撳崟");
+ }
+ }
+ return save(accountPaymentApplication);
+ }
+
+ @Override
+ public boolean deleteAccountPaymentApplication(List<Long> ids) {
+ if (ids == null || ids.isEmpty()) {
+ throw new ServiceException("鍒犻櫎澶辫触锛岃閫夋嫨瑕佸垹闄ょ殑鏁版嵁");
+ }
+ //鍒ゆ柇鏄惁宸茬粡鏈夊搴旂殑浠樻鍗�,濡傛灉鏈夊垯鏃犳硶鍒犻櫎
+ List<AccountPurchasePayment> accountPurchasePayments = accountPurchasePaymentMapper.selectList(Wrappers.<AccountPurchasePayment>lambdaQuery().in(AccountPurchasePayment::getAccountPaymentApplicationId, ids));
+ if (CollectionUtils.isNotEmpty(accountPurchasePayments)){
+ throw new ServiceException("鍒犻櫎澶辫触锛屽凡缁忔湁鍏宠仈鐨勪粯娆惧崟");
+ }
+ //鍒犻櫎寮�绁ㄧ敵璇�
+ return removeBatchByIds(ids);
+ }
+
+ @Override
+ public void exportAccountPaymentApplication(HttpServletResponse response, AccountPaymentApplicationDto accountPaymentApplicationDto) {
+ List<AccountPaymentApplicationVo> list = accountPaymentApplicationMapper.listPageAccountPaymentApplication(new Page(1,-1),accountPaymentApplicationDto).getRecords();
+ ExcelUtil<AccountPaymentApplicationVo> util = new ExcelUtil<>(AccountPaymentApplicationVo.class);
+ util.exportExcel(response, list , "浠樻鐢宠");
+ }
+
+ private String genPaymentApplicationNo() {
+ return "FK" + LocalDateTime.now().format(CODE_TIME_FORMATTER) + new Random().nextInt(10);
+ }
+}
diff --git a/src/main/java/com/ruoyi/account/service/impl/purchase/AccountPurchaseInvoiceServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/purchase/AccountPurchaseInvoiceServiceImpl.java
new file mode 100644
index 0000000..5ca2efe
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/impl/purchase/AccountPurchaseInvoiceServiceImpl.java
@@ -0,0 +1,59 @@
+package com.ruoyi.account.service.impl.purchase;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.account.bean.dto.purchase.AccountPurchaseInvoiceDto;
+import com.ruoyi.account.bean.vo.purchase.AccountPurchaseInvoiceVo;
+import com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo;
+import com.ruoyi.account.mapper.purchase.AccountPurchaseInvoiceMapper;
+import com.ruoyi.account.pojo.purchase.AccountPurchaseInvoice;
+import com.ruoyi.account.service.purchase.AccountPurchaseInvoiceService;
+import com.ruoyi.basic.mapper.StorageAttachmentMapper;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--杩涢」鍙戠エ 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 03:06:17
+ */
+@Service
+@RequiredArgsConstructor
+public class AccountPurchaseInvoiceServiceImpl extends ServiceImpl<AccountPurchaseInvoiceMapper, AccountPurchaseInvoice> implements AccountPurchaseInvoiceService {
+
+ private final AccountPurchaseInvoiceMapper accountPurchaseInvoiceMapper;
+ private final StorageAttachmentMapper storageAttachmentMapper;
+
+ @Override
+ public IPage<AccountPurchaseInvoiceVo> listPageAccountPurchaseInvoice(Page page, AccountPurchaseInvoiceDto accountPurchaseInvoiceDto) {
+ return accountPurchaseInvoiceMapper.listPageAccountPurchaseInvoice(page, accountPurchaseInvoiceDto);
+ }
+
+ @Override
+ public boolean deleteAccountPurchaseInvoice(List<Long> ids) {
+ List<AccountPurchaseInvoice> accountPurchaseInvoices = accountPurchaseInvoiceMapper.selectByIds(ids);
+ //鍒犻櫎闄勪欢
+ storageAttachmentMapper.deleteBatchIds(accountPurchaseInvoices.stream().map(AccountPurchaseInvoice::getStorageAttachmentId).toList());
+ return removeBatchByIds(ids);
+ }
+
+ @Override
+ public void exportAccountPurchaseInvoice(HttpServletResponse response, AccountPurchaseInvoiceDto accountPurchaseInvoiceDto) {
+ List<AccountPurchaseInvoiceVo> list = accountPurchaseInvoiceMapper.listPageAccountPurchaseInvoice(new Page(1,-1),accountPurchaseInvoiceDto).getRecords();
+ ExcelUtil<AccountPurchaseInvoiceVo> util = new ExcelUtil<>(AccountPurchaseInvoiceVo.class);
+ util.exportExcel(response, list , "杩涢」鍙戠エ");
+ }
+
+ @Override
+ public List<PurchaseInboundVo> getInboundBatchesBySupplier(Integer supplierId) {
+ return accountPurchaseInvoiceMapper.getInboundBatchesBySupplier(supplierId);
+ }
+}
diff --git a/src/main/java/com/ruoyi/account/service/impl/purchase/AccountPurchasePaymentServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/purchase/AccountPurchasePaymentServiceImpl.java
new file mode 100644
index 0000000..b9953a0
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/impl/purchase/AccountPurchasePaymentServiceImpl.java
@@ -0,0 +1,90 @@
+package com.ruoyi.account.service.impl.purchase;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
+import com.ruoyi.account.bean.dto.purchase.AccountPurchasePaymentDto;
+import com.ruoyi.account.bean.vo.purchase.AccountPurchasePaymentVo;
+import com.ruoyi.account.mapper.AccountStatementDetailsMapper;
+import com.ruoyi.account.mapper.purchase.AccountPaymentApplicationMapper;
+import com.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper;
+import com.ruoyi.account.pojo.AccountStatementDetails;
+import com.ruoyi.account.pojo.purchase.AccountPaymentApplication;
+import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
+import com.ruoyi.account.service.purchase.AccountPurchasePaymentService;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--浠樻鍗� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 04:14:51
+ */
+@Service
+@RequiredArgsConstructor
+public class AccountPurchasePaymentServiceImpl extends ServiceImpl<AccountPurchasePaymentMapper, AccountPurchasePayment> implements AccountPurchasePaymentService {
+
+ private static final DateTimeFormatter CODE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyMMddHHmmss");
+ private final AccountPurchasePaymentMapper accountPurchasePaymentMapper;
+ private final AccountStatementDetailsMapper accountStatementDetailsMapper;
+ private final AccountPaymentApplicationMapper accountPaymentApplicationMapper;
+
+ @Override
+ public IPage<AccountPurchasePaymentVo> listPageAccountPurchasePayment(Page page, AccountPurchasePaymentDto accountPurchasePaymentDto) {
+ return accountPurchasePaymentMapper.listPageAccountPurchasePayment(page, accountPurchasePaymentDto);
+ }
+
+ @Override
+ public boolean addAccountPurchasePayment(AccountPurchasePayment accountPurchasePayment) {
+ if (StringUtils.isEmpty(accountPurchasePayment.getPaymentNumber())) {
+ accountPurchasePayment.setPaymentNumber(genAccountPurchasePaymentNo());
+ }
+ //鏍¢獙绱浠樻閲戦涓嶈兘瓒呰繃鐢宠閲戦
+ AccountPaymentApplication accountPaymentApplication = accountPaymentApplicationMapper.selectById(accountPurchasePayment.getAccountPaymentApplicationId());
+ List<AccountPurchasePayment> accountPurchasePayments = accountPurchasePaymentMapper.selectList(Wrappers.<AccountPurchasePayment>lambdaQuery().eq(AccountPurchasePayment::getAccountPaymentApplicationId, accountPurchasePayment.getAccountPaymentApplicationId()));
+ BigDecimal totalPaymentAmount = accountPurchasePayments.stream().map(AccountPurchasePayment::getPaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
+ if (accountPaymentApplication.getPaymentAmount().compareTo(totalPaymentAmount) < 0) {
+ throw new ServiceException("绱浠樻閲戦涓嶈兘瓒呰繃鐢宠閲戦");
+ }
+ return save(accountPurchasePayment);
+ }
+
+ @Override
+ public void exportAccountPurchasePayment(HttpServletResponse response, AccountPurchasePaymentDto accountPurchasePaymentDto) {
+ List<AccountPurchasePaymentVo> list = accountPurchasePaymentMapper.listPageAccountPurchasePayment(new Page(1,-1),accountPurchasePaymentDto).getRecords();
+ ExcelUtil<AccountPurchasePaymentVo> util = new ExcelUtil<>(AccountPurchasePaymentVo.class);
+ util.exportExcel(response, list , "浠樻鍗�");
+ }
+
+ @Override
+ public boolean deleteAccountPurchasePayment(List<Long> ids) {
+ //濡傛灉璇ヤ粯娆惧崟宸茬粡鐢熸垚瀵硅处鍗曞垯鏃犳硶鍒犻櫎
+ List<AccountPurchasePayment> accountPurchasePayments = accountPurchasePaymentMapper.selectByIds(ids);
+ List<String> strings = accountPurchasePayments.stream().map(AccountPurchasePayment::getPaymentNumber).toList();
+ List<AccountStatementDetails> accountStatementDetails = accountStatementDetailsMapper.selectList(Wrappers.<AccountStatementDetails>lambdaQuery()
+ .in(AccountStatementDetails::getReceiptNumber, strings));
+ if (CollectionUtils.isNotEmpty(accountStatementDetails)){
+ throw new ServiceException("璇ヤ粯娆惧崟宸茬粡鐢熸垚瀵硅处鍗曪紝鏃犳硶鍒犻櫎");
+ }
+ return removeByIds(ids);
+ }
+
+ private String genAccountPurchasePaymentNo() {
+ return "SK" + LocalDateTime.now().format(CODE_TIME_FORMATTER) + new Random().nextInt(10);
+ }
+}
diff --git a/src/main/java/com/ruoyi/account/service/impl/sales/AccountInvoiceApplicationServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/sales/AccountInvoiceApplicationServiceImpl.java
new file mode 100644
index 0000000..74cec42
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/impl/sales/AccountInvoiceApplicationServiceImpl.java
@@ -0,0 +1,97 @@
+package com.ruoyi.account.service.impl.sales;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.account.bean.dto.sales.AccountInvoiceApplicationDto;
+import com.ruoyi.account.bean.vo.sales.AccountInvoiceApplicationVo;
+import com.ruoyi.account.bean.vo.sales.SalesOutboundVo;
+import com.ruoyi.account.mapper.sales.AccountInvoiceApplicationMapper;
+import com.ruoyi.account.mapper.sales.AccountSalesInvoiceMapper;
+import com.ruoyi.account.pojo.sales.AccountInvoiceApplication;
+import com.ruoyi.account.pojo.sales.AccountSalesInvoice;
+import com.ruoyi.account.service.sales.AccountInvoiceApplicationService;
+import com.ruoyi.basic.mapper.StorageAttachmentMapper;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--寮�绁ㄧ敵璇� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 01:38:32
+ */
+@Service
+@RequiredArgsConstructor
+public class AccountInvoiceApplicationServiceImpl extends ServiceImpl<AccountInvoiceApplicationMapper, AccountInvoiceApplication> implements AccountInvoiceApplicationService {
+
+ private final AccountInvoiceApplicationMapper accountInvoiceApplicationMapper;
+ private final AccountSalesInvoiceMapper accountSalesInvoiceMapper;
+ private final StorageAttachmentMapper storageAttachmentMapper;
+ private static final DateTimeFormatter CODE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyMMddHHmmss");
+
+ @Override
+ public IPage<AccountInvoiceApplicationVo> listPageAccountInvoiceApplication(Page page, AccountInvoiceApplicationDto accountInvoiceApplicationDto) {
+ return accountInvoiceApplicationMapper.listPageAccountInvoiceApplication(page, accountInvoiceApplicationDto);
+ }
+
+ @Override
+ public List<SalesOutboundVo> getOutboundBatchesByCustomer(Integer customerId) {
+ return accountInvoiceApplicationMapper.getOutboundBatchesByCustomer(customerId);
+ }
+
+ @Override
+ public boolean addAccountInvoiceApplication(AccountInvoiceApplication accountInvoiceApplication) {
+ if (StringUtils.isEmpty(accountInvoiceApplication.getInvoiceApplicationNo())) {
+ accountInvoiceApplication.setInvoiceApplicationNo(genInvoiceApplicationNo());
+ }
+ String stockOutRecordIds = accountInvoiceApplication.getStockOutRecordIds();
+ if (stockOutRecordIds != null && !stockOutRecordIds.isEmpty()) {
+ List<Long> ids = Arrays.stream(stockOutRecordIds.split(","))
+ .map(Long::valueOf)
+ .toList();
+ if (accountInvoiceApplicationMapper.existsByStockOutRecordId(ids)){
+ throw new ServiceException("瀛樺湪閲嶅鐨勫嚭搴撳崟");
+ }
+ }
+ return save(accountInvoiceApplication);
+ }
+
+ @Override
+ public void exportAccountInvoiceApplication(HttpServletResponse response, AccountInvoiceApplicationDto accountInvoiceApplicationDto) {
+ List<AccountInvoiceApplicationVo> list = accountInvoiceApplicationMapper.listPageAccountInvoiceApplication(new Page(1,-1),accountInvoiceApplicationDto).getRecords();
+ ExcelUtil<AccountInvoiceApplicationVo> util = new ExcelUtil<>(AccountInvoiceApplicationVo.class);
+ util.exportExcel(response, list , "寮�绁ㄧ敵璇�");
+ }
+
+ @Override
+ public boolean deleteAccountInvoiceApplication(List<Long> ids) {
+ if (ids == null || ids.isEmpty()) {
+ throw new ServiceException("鍒犻櫎澶辫触锛岃閫夋嫨瑕佸垹闄ょ殑鏁版嵁");
+ }
+ //鍒犻櫎鐩稿叧闄勪欢
+ List<AccountSalesInvoice> accountSalesInvoices = accountSalesInvoiceMapper.selectList(Wrappers.<AccountSalesInvoice>lambdaQuery().in(AccountSalesInvoice::getAccountInvoiceApplicationId,ids));
+ storageAttachmentMapper.deleteBatchIds(accountSalesInvoices.stream().map(AccountSalesInvoice::getStorageAttachmentId).toList());
+ //鍒犻櫎鐩稿叧鐨勯攢椤瑰彂绁�
+ accountSalesInvoiceMapper.delete(Wrappers.<AccountSalesInvoice>lambdaQuery().in(AccountSalesInvoice::getAccountInvoiceApplicationId,ids));
+ //鍒犻櫎寮�绁ㄧ敵璇�
+ return removeBatchByIds(ids);
+ }
+
+ private String genInvoiceApplicationNo() {
+ return "KP" + LocalDateTime.now().format(CODE_TIME_FORMATTER) + new Random().nextInt(10);
+ }
+}
diff --git a/src/main/java/com/ruoyi/account/service/impl/sales/AccountSalesCollectionServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/sales/AccountSalesCollectionServiceImpl.java
new file mode 100644
index 0000000..5f328bc
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/impl/sales/AccountSalesCollectionServiceImpl.java
@@ -0,0 +1,96 @@
+package com.ruoyi.account.service.impl.sales;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.account.bean.dto.sales.AccountSalesCollectionDto;
+import com.ruoyi.account.bean.vo.sales.AccountSalesCollectionVo;
+import com.ruoyi.account.bean.vo.sales.SalesOutboundVo;
+import com.ruoyi.account.mapper.AccountStatementDetailsMapper;
+import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper;
+import com.ruoyi.account.pojo.AccountStatementDetails;
+import com.ruoyi.account.pojo.sales.AccountSalesCollection;
+import com.ruoyi.account.service.sales.AccountSalesCollectionService;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--鏀舵鍗� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:49:56
+ */
+@Service
+@RequiredArgsConstructor
+public class AccountSalesCollectionServiceImpl extends ServiceImpl<AccountSalesCollectionMapper, AccountSalesCollection> implements AccountSalesCollectionService {
+
+ private final AccountSalesCollectionMapper accountSalesCollectionMapper;
+ private final AccountStatementDetailsMapper accountStatementDetailsMapper;
+ private static final DateTimeFormatter CODE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyMMddHHmmss");
+
+
+ @Override
+ public IPage<AccountSalesCollectionVo> listPageAccountSalesCollection(Page page, AccountSalesCollectionDto accountSalesCollectionDto) {
+ return accountSalesCollectionMapper.listPageAccountSalesCollection(page, accountSalesCollectionDto);
+ }
+
+ @Override
+ public boolean addAccountSalesCollection(AccountSalesCollection accountSalesCollection) {
+ if (StringUtils.isEmpty(accountSalesCollection.getCollectionNumber())) {
+ accountSalesCollection.setCollectionNumber(genAccountSalesCollectionNo());
+ }
+ String stockOutRecordIds = accountSalesCollection.getStockOutRecordIds();
+ if (stockOutRecordIds != null && !stockOutRecordIds.isEmpty()) {
+ List<Long> ids = Arrays.stream(stockOutRecordIds.split(","))
+ .map(Long::valueOf)
+ .toList();
+ if (accountSalesCollectionMapper.existsByStockOutRecordId(ids)){
+ throw new ServiceException("瀛樺湪閲嶅鐨勫嚭搴撳崟");
+ }
+ }
+ return save(accountSalesCollection);
+ }
+
+ @Override
+ public void exportAccountSalesCollection(HttpServletResponse response, AccountSalesCollectionDto accountSalesCollectionDto) {
+ List<AccountSalesCollectionVo> list = accountSalesCollectionMapper.listPageAccountSalesCollection(new Page(1,-1),accountSalesCollectionDto).getRecords();
+ ExcelUtil<AccountSalesCollectionVo> util = new ExcelUtil<>(AccountSalesCollectionVo.class);
+ util.exportExcel(response, list , "鏀舵鍗�");
+ }
+
+ @Override
+ public boolean deleteAccountSalesCollection(List<Long> ids) {
+ //濡傛灉璇ユ敹娆惧崟宸茬粡鐢熸垚瀵硅处鍗曞垯鏃犳硶鍒犻櫎
+ List<AccountSalesCollection> accountSalesCollections = accountSalesCollectionMapper.selectByIds(ids);
+ List<String> strings = accountSalesCollections.stream().map(AccountSalesCollection::getCollectionNumber).toList();
+ List<AccountStatementDetails> accountStatementDetails = accountStatementDetailsMapper.selectList(Wrappers.<AccountStatementDetails>lambdaQuery()
+ .in(AccountStatementDetails::getReceiptNumber, strings));
+ if (CollectionUtils.isNotEmpty(accountStatementDetails)){
+ throw new ServiceException("璇ユ敹娆惧崟宸茬粡鐢熸垚瀵硅处鍗曪紝鏃犳硶鍒犻櫎");
+ }
+ return removeByIds(ids);
+ }
+
+ @Override
+ public List<SalesOutboundVo> getOutboundBatchesByCustomer(Integer customerId) {
+ return accountSalesCollectionMapper.getOutboundBatchesByCustomer(customerId);
+ }
+
+ private String genAccountSalesCollectionNo() {
+ return "SK" + LocalDateTime.now().format(CODE_TIME_FORMATTER) + new Random().nextInt(10);
+ }
+}
diff --git a/src/main/java/com/ruoyi/account/service/impl/sales/AccountSalesInvoiceServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/sales/AccountSalesInvoiceServiceImpl.java
new file mode 100644
index 0000000..b2fe7e3
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/impl/sales/AccountSalesInvoiceServiceImpl.java
@@ -0,0 +1,53 @@
+package com.ruoyi.account.service.impl.sales;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.account.bean.dto.sales.AccountSalesInvoiceDto;
+import com.ruoyi.account.bean.vo.sales.AccountSalesInvoiceVo;
+import com.ruoyi.account.mapper.sales.AccountSalesInvoiceMapper;
+import com.ruoyi.account.pojo.sales.AccountSalesInvoice;
+import com.ruoyi.account.service.sales.AccountSalesInvoiceService;
+import com.ruoyi.basic.mapper.StorageAttachmentMapper;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--閿�椤瑰彂绁� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:10:20
+ */
+@Service
+@RequiredArgsConstructor
+public class AccountSalesInvoiceServiceImpl extends ServiceImpl<AccountSalesInvoiceMapper, AccountSalesInvoice> implements AccountSalesInvoiceService {
+
+ private final AccountSalesInvoiceMapper accountSalesInvoiceMapper;
+ private final StorageAttachmentMapper storageAttachmentMapper;
+
+ @Override
+ public IPage<AccountSalesInvoiceVo> listPageAccountSalesInvoice(Page page, AccountSalesInvoiceDto accountSalesInvoiceDto) {
+ return accountSalesInvoiceMapper.listPageAccountSalesInvoice(page, accountSalesInvoiceDto);
+ }
+
+ @Override
+ public void exportAccountSalesInvoice(HttpServletResponse response, AccountSalesInvoiceDto accountSalesInvoiceDto) {
+ List<AccountSalesInvoiceVo> list = accountSalesInvoiceMapper.listPageAccountSalesInvoice(new Page(1,-1),accountSalesInvoiceDto).getRecords();
+ ExcelUtil<AccountSalesInvoiceVo> util = new ExcelUtil<>(AccountSalesInvoiceVo.class);
+ util.exportExcel(response, list , "閿�椤瑰彂绁�");
+ }
+
+ @Override
+ public boolean deleteAccountSalesInvoice(List<Long> ids) {
+ List<AccountSalesInvoice> accountSalesInvoices = accountSalesInvoiceMapper.selectByIds(ids);
+ //鍒犻櫎闄勪欢
+ storageAttachmentMapper.deleteBatchIds(accountSalesInvoices.stream().map(AccountSalesInvoice::getStorageAttachmentId).toList());
+ return removeBatchByIds(ids);
+ }
+}
diff --git a/src/main/java/com/ruoyi/account/service/purchase/AccountPaymentApplicationService.java b/src/main/java/com/ruoyi/account/service/purchase/AccountPaymentApplicationService.java
new file mode 100644
index 0000000..c2c5c66
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/purchase/AccountPaymentApplicationService.java
@@ -0,0 +1,33 @@
+package com.ruoyi.account.service.purchase;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.account.bean.dto.purchase.AccountPaymentApplicationDto;
+import com.ruoyi.account.bean.vo.purchase.AccountPaymentApplicationVo;
+import com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo;
+import com.ruoyi.account.pojo.purchase.AccountPaymentApplication;
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--浠樻鐢宠 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 03:44:22
+ */
+public interface AccountPaymentApplicationService extends IService<AccountPaymentApplication> {
+
+ IPage<AccountPaymentApplicationVo> listPageAccountPaymentApplication(Page page, AccountPaymentApplicationDto accountPaymentApplicationDto);
+
+ List<PurchaseInboundVo> getInboundBatchesBySupplier(Integer supplierId);
+
+ boolean addAccountPaymentApplication(AccountPaymentApplication accountPaymentApplication);
+
+ boolean deleteAccountPaymentApplication(List<Long> ids);
+
+ void exportAccountPaymentApplication(HttpServletResponse response, AccountPaymentApplicationDto accountPaymentApplicationDto);
+}
diff --git a/src/main/java/com/ruoyi/account/service/purchase/AccountPurchaseInvoiceService.java b/src/main/java/com/ruoyi/account/service/purchase/AccountPurchaseInvoiceService.java
new file mode 100644
index 0000000..d799c5e
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/purchase/AccountPurchaseInvoiceService.java
@@ -0,0 +1,31 @@
+package com.ruoyi.account.service.purchase;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.purchase.AccountPurchaseInvoiceDto;
+import com.ruoyi.account.bean.vo.purchase.AccountPurchaseInvoiceVo;
+import com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo;
+import com.ruoyi.account.pojo.purchase.AccountPurchaseInvoice;
+import com.baomidou.mybatisplus.extension.service.IService;
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--杩涢」鍙戠エ 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 03:06:17
+ */
+public interface AccountPurchaseInvoiceService extends IService<AccountPurchaseInvoice> {
+
+ IPage<AccountPurchaseInvoiceVo> listPageAccountPurchaseInvoice(Page page, AccountPurchaseInvoiceDto accountPurchaseInvoiceDto);
+
+ boolean deleteAccountPurchaseInvoice(List<Long> ids);
+
+ void exportAccountPurchaseInvoice(HttpServletResponse response, AccountPurchaseInvoiceDto accountPurchaseInvoiceDto);
+
+ List<PurchaseInboundVo> getInboundBatchesBySupplier(Integer supplierId);
+}
diff --git a/src/main/java/com/ruoyi/account/service/purchase/AccountPurchasePaymentService.java b/src/main/java/com/ruoyi/account/service/purchase/AccountPurchasePaymentService.java
new file mode 100644
index 0000000..018a497
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/purchase/AccountPurchasePaymentService.java
@@ -0,0 +1,30 @@
+package com.ruoyi.account.service.purchase;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.purchase.AccountPurchasePaymentDto;
+import com.ruoyi.account.bean.vo.purchase.AccountPurchasePaymentVo;
+import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
+import com.baomidou.mybatisplus.extension.service.IService;
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--浠樻鍗� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-19 04:14:51
+ */
+public interface AccountPurchasePaymentService extends IService<AccountPurchasePayment> {
+
+ IPage<AccountPurchasePaymentVo> listPageAccountPurchasePayment(Page page, AccountPurchasePaymentDto accountPurchasePaymentDto);
+
+ boolean addAccountPurchasePayment(AccountPurchasePayment accountPurchasePayment);
+
+ void exportAccountPurchasePayment(HttpServletResponse response, AccountPurchasePaymentDto accountPurchasePaymentDto);
+
+ boolean deleteAccountPurchasePayment(List<Long> ids);
+}
diff --git a/src/main/java/com/ruoyi/account/service/sales/AccountInvoiceApplicationService.java b/src/main/java/com/ruoyi/account/service/sales/AccountInvoiceApplicationService.java
new file mode 100644
index 0000000..7f55ba5
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/sales/AccountInvoiceApplicationService.java
@@ -0,0 +1,33 @@
+package com.ruoyi.account.service.sales;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.account.bean.dto.sales.AccountInvoiceApplicationDto;
+import com.ruoyi.account.bean.vo.sales.AccountInvoiceApplicationVo;
+import com.ruoyi.account.bean.vo.sales.SalesOutboundVo;
+import com.ruoyi.account.pojo.sales.AccountInvoiceApplication;
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--寮�绁ㄧ敵璇� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 01:38:32
+ */
+public interface AccountInvoiceApplicationService extends IService<AccountInvoiceApplication> {
+
+ IPage<AccountInvoiceApplicationVo> listPageAccountInvoiceApplication(Page page, AccountInvoiceApplicationDto accountInvoiceApplicationDto);
+
+ List<SalesOutboundVo> getOutboundBatchesByCustomer(Integer customerId);
+
+ boolean addAccountInvoiceApplication(AccountInvoiceApplication accountInvoiceApplication);
+
+ void exportAccountInvoiceApplication(HttpServletResponse response, AccountInvoiceApplicationDto accountInvoiceApplicationDto);
+
+ boolean deleteAccountInvoiceApplication(List<Long> ids);
+}
diff --git a/src/main/java/com/ruoyi/account/service/sales/AccountSalesCollectionService.java b/src/main/java/com/ruoyi/account/service/sales/AccountSalesCollectionService.java
new file mode 100644
index 0000000..d5172fb
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/sales/AccountSalesCollectionService.java
@@ -0,0 +1,33 @@
+package com.ruoyi.account.service.sales;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.sales.AccountSalesCollectionDto;
+import com.ruoyi.account.bean.vo.sales.AccountSalesCollectionVo;
+import com.ruoyi.account.bean.vo.sales.SalesOutboundVo;
+import com.ruoyi.account.pojo.sales.AccountSalesCollection;
+import com.baomidou.mybatisplus.extension.service.IService;
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--鏀舵鍗� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:49:56
+ */
+public interface AccountSalesCollectionService extends IService<AccountSalesCollection> {
+
+ IPage<AccountSalesCollectionVo> listPageAccountSalesCollection(Page page, AccountSalesCollectionDto accountSalesCollectionDto);
+
+ boolean addAccountSalesCollection(AccountSalesCollection accountSalesCollection);
+
+ void exportAccountSalesCollection(HttpServletResponse response, AccountSalesCollectionDto accountSalesCollectionDto);
+
+ boolean deleteAccountSalesCollection(List<Long> ids);
+
+ List<SalesOutboundVo> getOutboundBatchesByCustomer(Integer customerId);
+}
diff --git a/src/main/java/com/ruoyi/account/service/sales/AccountSalesInvoiceService.java b/src/main/java/com/ruoyi/account/service/sales/AccountSalesInvoiceService.java
new file mode 100644
index 0000000..1809177
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/sales/AccountSalesInvoiceService.java
@@ -0,0 +1,28 @@
+package com.ruoyi.account.service.sales;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.sales.AccountSalesInvoiceDto;
+import com.ruoyi.account.bean.vo.sales.AccountSalesInvoiceVo;
+import com.ruoyi.account.pojo.sales.AccountSalesInvoice;
+import com.baomidou.mybatisplus.extension.service.IService;
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璐㈠姟绠$悊--閿�椤瑰彂绁� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:10:20
+ */
+public interface AccountSalesInvoiceService extends IService<AccountSalesInvoice> {
+
+ IPage<AccountSalesInvoiceVo> listPageAccountSalesInvoice(Page page, AccountSalesInvoiceDto accountSalesInvoiceDto);
+
+ void exportAccountSalesInvoice(HttpServletResponse response, AccountSalesInvoiceDto accountSalesInvoiceDto);
+
+ boolean deleteAccountSalesInvoice(List<Long> ids);
+}
diff --git a/src/main/java/com/ruoyi/ai/assistant/ApproveTodoAgent.java b/src/main/java/com/ruoyi/ai/assistant/ApproveTodoAgent.java
index 3b37909..bad0e0a 100644
--- a/src/main/java/com/ruoyi/ai/assistant/ApproveTodoAgent.java
+++ b/src/main/java/com/ruoyi/ai/assistant/ApproveTodoAgent.java
@@ -3,6 +3,7 @@
import dev.langchain4j.service.MemoryId;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.V;
import dev.langchain4j.service.spring.AiService;
import reactor.core.publisher.Flux;
@@ -16,5 +17,5 @@
public interface ApproveTodoAgent {
@SystemMessage(fromResource = "approve-todo-agent-prompt.txt")
- Flux<String> chat(@MemoryId String memoryId, @UserMessage String userMessage);
+ Flux<String> chat(@MemoryId String memoryId, @UserMessage String userMessage, @V("currentDate") String currentDate);
}
diff --git a/src/main/java/com/ruoyi/ai/assistant/FinancialAgent.java b/src/main/java/com/ruoyi/ai/assistant/FinancialAgent.java
new file mode 100644
index 0000000..875b98d
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/assistant/FinancialAgent.java
@@ -0,0 +1,22 @@
+package com.ruoyi.ai.assistant;
+
+import dev.langchain4j.service.MemoryId;
+import dev.langchain4j.service.SystemMessage;
+import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.V;
+import dev.langchain4j.service.spring.AiService;
+import reactor.core.publisher.Flux;
+
+import static dev.langchain4j.service.spring.AiServiceWiringMode.EXPLICIT;
+
+@AiService(
+ wiringMode = EXPLICIT,
+ streamingChatModel = "qwenStreamingChatModel",
+ chatMemoryProvider = "chatMemoryProviderFinancial",
+ tools = "financialAgentTools"
+)
+public interface FinancialAgent {
+
+ @SystemMessage(fromResource = "financial-agent-prompt.txt")
+ Flux<String> chat(@MemoryId String memoryId, @UserMessage String userMessage, @V("currentDate") String currentDate);
+}
diff --git a/src/main/java/com/ruoyi/ai/assistant/FinancialIntentExecutor.java b/src/main/java/com/ruoyi/ai/assistant/FinancialIntentExecutor.java
new file mode 100644
index 0000000..9afadff
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/assistant/FinancialIntentExecutor.java
@@ -0,0 +1,266 @@
+package com.ruoyi.ai.assistant;
+
+import com.ruoyi.ai.tools.FinancialAgentTools;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.time.LocalDate;
+import java.time.YearMonth;
+import java.time.format.DateTimeFormatter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@Component
+public class FinancialIntentExecutor {
+
+ private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ private static final Pattern LIMIT_PATTERN = Pattern.compile("(鍓峾鏈�杩�)?\\s*(\\d{1,2})\\s*鏉�");
+ private static final Pattern DATE_PATTERN = Pattern.compile("(\\d{4}-\\d{2}-\\d{2})");
+ private static final Pattern RELATIVE_DAY_PATTERN = Pattern.compile("(杩憒鏈�杩�)?\\s*(\\d{1,3})\\s*澶�");
+
+ private final FinancialAgentTools financialAgentTools;
+
+ public FinancialIntentExecutor(FinancialAgentTools financialAgentTools) {
+ this.financialAgentTools = financialAgentTools;
+ }
+
+ public String tryExecute(String memoryId, String message) {
+ if (!StringUtils.hasText(message)) {
+ return null;
+ }
+ String text = message.trim();
+
+ String quickPromptResponse = tryExecuteQuickPrompt(memoryId, text);
+ if (StringUtils.hasText(quickPromptResponse)) {
+ return quickPromptResponse;
+ }
+
+ DateRange dateRange = extractDateRange(text);
+ Integer limit = extractLimit(text);
+ String keyword = extractKeyword(text);
+ String startDate = dateRange.startDate();
+ String endDate = dateRange.endDate();
+ String timeRange = dateRange.label();
+
+ if (containsAny(text, "鎴愭湰鏍哥畻", "浜у搧鎴愭湰", "宸ュ簭鎴愭湰", "浜哄伐鎴愭湰", "鎶樻棫", "鏉愭枡鎹熻��")) {
+ return financialAgentTools.calculateIntelligentCost(memoryId, startDate, endDate, timeRange, keyword, limit);
+ }
+ if (containsAny(text, "鍒╂鼎鍒嗘瀽", "璁㈠崟鍒╂鼎", "浜忔崯璁㈠崟", "浣庡埄娑�",
+ "鏈�璧氶挶瀹㈡埛", "鍝釜瀹㈡埛鏈�璧氶挶", "瀹㈡埛鏈�璧氶挶", "鍒╂鼎鏈�楂樺鎴�", "鍒╂鼎璐$尞鏈�楂樺鎴�", "鍒╂鼎涓嬮檷")) {
+ return financialAgentTools.analyzeOrderProfit(memoryId, startDate, endDate, timeRange, keyword, limit);
+ }
+ if (containsAny(text, "搴撳瓨璧勯噾", "搴撳瓨绉帇", "鍛嗘粸搴撳瓨", "璧勯噾鍗犵敤", "鍛ㄨ浆鐜�", "搴撳瓨鍛ㄨ浆")) {
+ return financialAgentTools.analyzeInventoryCapital(memoryId, startDate, endDate, timeRange, keyword, limit);
+ }
+ if (containsAny(text, "鐜伴噾娴�", "鍥炴椋庨櫓", "浠樻鍘嬪姏", "璧勯噾缂哄彛", "搴旀敹", "搴斾粯", "鍥炴棰勬祴")) {
+ return financialAgentTools.forecastCashFlow(memoryId, startDate, endDate, timeRange, limit);
+ }
+ if (containsAny(text, "寮傚父棰勮", "缁忚惀寮傚父", "椋庨櫓棰勮", "鎴愭湰寮傚父", "鍒╂鼎寮傚父", "鍥炴寮傚父", "璁㈠崟椋庨櫓")) {
+ return financialAgentTools.detectBusinessAnomalies(memoryId, startDate, endDate, timeRange, limit);
+ }
+ if (containsAny(text, "椹鹃┒鑸�", "缁忚惀鐪嬫澘", "缁忚惀鎬昏", "缁忚惀浠〃鐩�", "缁忚惀澶х洏")) {
+ return financialAgentTools.getBusinessCockpit(memoryId, startDate, endDate, timeRange);
+ }
+ if (containsAny(text, "鏃ユ姤", "鍛ㄦ姤", "缁忚惀鎶ュ憡", "鍒嗘瀽鎶ュ憡")) {
+ return financialAgentTools.generateOperationReport(memoryId, startDate, endDate, timeRange,
+ containsAny(text, "鍛ㄦ姤") ? "weekly" : "daily");
+ }
+ if (containsAny(text, "涓氳储铻嶅悎", "涓氳储鑱斿姩", "鍙e緞", "鎸囨爣瑙i噴", "涓轰粈涔�")) {
+ return financialAgentTools.retrieveFinancialKnowledge(memoryId, text);
+ }
+ return null;
+ }
+
+ private String tryExecuteQuickPrompt(String memoryId, String text) {
+ String normalized = normalizeForMatch(text);
+ if ("鏌ョ湅鏈湀缁忚惀椹鹃┒鑸�".equals(normalized) || "鏌ョ湅缁忚惀椹鹃┒鑸�".equals(normalized)) {
+ DateRange range = monthRange();
+ return financialAgentTools.getBusinessCockpit(memoryId, range.startDate(), range.endDate(), range.label());
+ }
+ if ("鏌ヨ杩�30澶╀簭鎹熻鍗�".equals(normalized) || "鍝釜璁㈠崟浜忔崯".equals(normalized)) {
+ DateRange range = recentDaysRange(30);
+ return financialAgentTools.analyzeOrderProfit(memoryId, range.startDate(), range.endDate(), range.label(), null, 20);
+ }
+ if ("鐢熸垚鏈懆缁忚惀鍛ㄦ姤".equals(normalized) || "鐢熸垚鍛ㄦ姤".equals(normalized)) {
+ DateRange range = weekRange();
+ return financialAgentTools.generateOperationReport(memoryId, range.startDate(), range.endDate(), range.label(), "weekly");
+ }
+ if ("涓轰粈涔堝埄娑︿笅闄�".equals(normalized)) {
+ DateRange range = monthRange();
+ return financialAgentTools.analyzeOrderProfit(memoryId, range.startDate(), range.endDate(), range.label(), null, 20);
+ }
+ if ("鍝釜瀹㈡埛鏈�璧氶挶".equals(normalized)
+ || "鏈�杩戝摢涓鎴锋渶璧氶挶".equals(normalized)
+ || "鏈湀鍝釜瀹㈡埛鏈�璧氶挶".equals(normalized)
+ || "杩�30澶╁摢涓鎴锋渶璧氶挶".equals(normalized)
+ || "鍝釜瀹㈡埛鍒╂鼎鏈�楂�".equals(normalized)
+ || "鍝釜瀹㈡埛鍒╂鼎璐$尞鏈�楂�".equals(normalized)) {
+ DateRange range = extractDateRange(text);
+ return financialAgentTools.analyzeOrderProfit(memoryId, range.startDate(), range.endDate(), range.label(), null, 20);
+ }
+ return null;
+ }
+
+ private boolean containsAny(String text, String... keywords) {
+ for (String keyword : keywords) {
+ if (text.contains(keyword)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private Integer extractLimit(String text) {
+ Matcher matcher = LIMIT_PATTERN.matcher(text);
+ return matcher.find() ? Integer.parseInt(matcher.group(2)) : 10;
+ }
+
+ private DateRange extractDateRange(String text) {
+ Matcher matcher = DATE_PATTERN.matcher(text);
+ if (matcher.find()) {
+ String first = matcher.group(1);
+ String second = matcher.find() ? matcher.group(1) : first;
+ return buildDateRange(first, second, first + "鑷�" + second);
+ }
+ if (text.contains("鏈湀")) {
+ return monthRange();
+ }
+ if (text.contains("涓婃湀")) {
+ return lastMonthRange();
+ }
+ if (text.contains("鏈勾") || text.contains("浠婂勾")) {
+ return yearRange();
+ }
+ if (text.contains("鏈懆")) {
+ return weekRange();
+ }
+ Matcher relativeDayMatcher = RELATIVE_DAY_PATTERN.matcher(text);
+ if (relativeDayMatcher.find()) {
+ int days = Integer.parseInt(relativeDayMatcher.group(2));
+ return recentDaysRange(days);
+ }
+ return new DateRange(null, null, "杩�30澶�");
+ }
+
+ private DateRange buildDateRange(String start, String end, String label) {
+ LocalDate startDate = parseDate(start);
+ LocalDate endDate = parseDate(end);
+ if (startDate == null || endDate == null) {
+ return new DateRange(null, null, "杩�30澶�");
+ }
+ if (startDate.isAfter(endDate)) {
+ LocalDate temp = startDate;
+ startDate = endDate;
+ endDate = temp;
+ }
+ return new DateRange(formatDate(startDate), formatDate(endDate), label);
+ }
+
+ private DateRange recentDaysRange(int days) {
+ LocalDate end = LocalDate.now();
+ int safeDays = Math.max(days, 1);
+ LocalDate start = end.minusDays(safeDays - 1L);
+ return new DateRange(formatDate(start), formatDate(end), "杩�" + safeDays + "澶�");
+ }
+
+ private DateRange monthRange() {
+ LocalDate today = LocalDate.now();
+ return new DateRange(formatDate(today.withDayOfMonth(1)), formatDate(today), "鏈湀");
+ }
+
+ private DateRange weekRange() {
+ LocalDate today = LocalDate.now();
+ LocalDate start = today.minusDays(today.getDayOfWeek().getValue() - 1L);
+ return new DateRange(formatDate(start), formatDate(today), "鏈懆");
+ }
+
+ private DateRange lastMonthRange() {
+ YearMonth lastMonth = YearMonth.now().minusMonths(1);
+ return new DateRange(formatDate(lastMonth.atDay(1)), formatDate(lastMonth.atEndOfMonth()), "涓婃湀");
+ }
+
+ private DateRange yearRange() {
+ LocalDate today = LocalDate.now();
+ return new DateRange(formatDate(today.withDayOfYear(1)), formatDate(today), "浠婂勾");
+ }
+
+ private LocalDate parseDate(String text) {
+ try {
+ return LocalDate.parse(text, DATE_FMT);
+ } catch (Exception ignored) {
+ return null;
+ }
+ }
+
+ private String formatDate(LocalDate date) {
+ return date == null ? null : date.format(DATE_FMT);
+ }
+
+ private String normalizeForMatch(String text) {
+ if (!StringUtils.hasText(text)) {
+ return "";
+ }
+ return text.replace("锛�", "")
+ .replace(",", "")
+ .replace("銆�", "")
+ .replace(".", "")
+ .replace("锛�", "")
+ .replace("!", "")
+ .replace("锛�", "")
+ .replace("?", "")
+ .replace("锛�", "")
+ .replace(":", "")
+ .replace("锛�", "")
+ .replace(";", "")
+ .replace(" ", "")
+ .trim();
+ }
+
+ private String extractKeyword(String text) {
+ String cleaned = text
+ .replace("鏌ヨ", "")
+ .replace("鏌ョ湅", "")
+ .replace("鐪嬩笅", "")
+ .replace("鐪嬬湅", "")
+ .replace("甯垜", "")
+ .replace("璇�", "")
+ .replace("涓�涓�", "")
+ .replace("涓轰粈涔�", "")
+ .replace("鍝釜瀹㈡埛鏈�璧氶挶", "")
+ .replace("鏈�杩戝摢涓鎴锋渶璧氶挶", "")
+ .replace("鏈湀鍝釜瀹㈡埛鏈�璧氶挶", "")
+ .replace("杩�30澶╁摢涓鎴锋渶璧氶挶", "")
+ .replace("鏈�璧氶挶瀹㈡埛", "")
+ .replace("瀹㈡埛鏈�璧氶挶", "")
+ .replace("鍝釜瀹㈡埛鍒╂鼎鏈�楂�", "")
+ .replace("鍒╂鼎鏈�楂樺鎴�", "")
+ .replace("鍝釜瀹㈡埛鍒╂鼎璐$尞鏈�楂�", "")
+ .replace("鍒╂鼎璐$尞鏈�楂樺鎴�", "")
+ .replace("鏈湀", "")
+ .replace("鏈懆", "")
+ .replace("鏈勾", "")
+ .replace("浠婂勾", "")
+ .replace("涓婃湀", "")
+ .replace("杩�30澶�", "")
+ .replace("杩�7澶�", "")
+ .replace("杩�90澶�", "")
+ .replace("鍓�10鏉�", "")
+ .replace("鏈�杩�10鏉�", "")
+ .replace("鍓�20鏉�", "")
+ .replace("鏈�杩�20鏉�", "")
+ .replace("璁㈠崟鍒╂鼎鍒嗘瀽", "")
+ .replace("鍒╂鼎鍒嗘瀽", "")
+ .replace("搴撳瓨璧勯噾鍒嗘瀽", "")
+ .replace("鐜伴噾娴侀娴�", "")
+ .replace("缁忚惀椹鹃┒鑸�", "")
+ .replace("鏃ユ姤", "")
+ .replace("鍛ㄦ姤", "")
+ .replace("寮傚父棰勮", "")
+ .replace("鏉�", "")
+ .trim();
+ return cleaned.length() >= 2 ? cleaned : null;
+ }
+
+ private record DateRange(String startDate, String endDate, String label) {
+ }
+}
diff --git a/src/main/java/com/ruoyi/ai/assistant/ManufacturingAgent.java b/src/main/java/com/ruoyi/ai/assistant/ManufacturingAgent.java
index f0e8cf7..0d16703 100644
--- a/src/main/java/com/ruoyi/ai/assistant/ManufacturingAgent.java
+++ b/src/main/java/com/ruoyi/ai/assistant/ManufacturingAgent.java
@@ -3,6 +3,7 @@
import dev.langchain4j.service.MemoryId;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.V;
import dev.langchain4j.service.spring.AiService;
import reactor.core.publisher.Flux;
@@ -17,5 +18,5 @@
public interface ManufacturingAgent {
@SystemMessage(fromResource = "manufacturing-agent-prompt.txt")
- Flux<String> chat(@MemoryId String memoryId, @UserMessage String userMessage);
+ Flux<String> chat(@MemoryId String memoryId, @UserMessage String userMessage, @V("currentDate") String currentDate);
}
diff --git a/src/main/java/com/ruoyi/ai/assistant/PurchaseAgent.java b/src/main/java/com/ruoyi/ai/assistant/PurchaseAgent.java
index 6a4ff4e..421261d 100644
--- a/src/main/java/com/ruoyi/ai/assistant/PurchaseAgent.java
+++ b/src/main/java/com/ruoyi/ai/assistant/PurchaseAgent.java
@@ -3,6 +3,7 @@
import dev.langchain4j.service.MemoryId;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.V;
import dev.langchain4j.service.spring.AiService;
import reactor.core.publisher.Flux;
@@ -17,5 +18,5 @@
public interface PurchaseAgent {
@SystemMessage(fromResource = "purchase-agent-prompt.txt")
- Flux<String> chat(@MemoryId String memoryId, @UserMessage String userMessage);
+ Flux<String> chat(@MemoryId String memoryId, @UserMessage String userMessage, @V("currentDate") String currentDate);
}
diff --git a/src/main/java/com/ruoyi/ai/assistant/PurchaseIntentExecutor.java b/src/main/java/com/ruoyi/ai/assistant/PurchaseIntentExecutor.java
index 5991fc3..c04915e 100644
--- a/src/main/java/com/ruoyi/ai/assistant/PurchaseIntentExecutor.java
+++ b/src/main/java/com/ruoyi/ai/assistant/PurchaseIntentExecutor.java
@@ -4,6 +4,9 @@
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -11,8 +14,12 @@
public class PurchaseIntentExecutor {
private static final Pattern ID_PATTERN = Pattern.compile("\\b\\d{1,12}\\b");
- private static final Pattern LIMIT_PATTERN = Pattern.compile("(鍓峾鏈�杩�)?(\\d{1,2})鏉�");
- private static final Pattern DATE_PATTERN = Pattern.compile("\\d{4}-\\d{2}-\\d{2}");
+ private static final Pattern LIMIT_PATTERN = Pattern.compile("(鍓峾鏈�杩�)?\\s*(\\d{1,2})\\s*鏉�");
+ private static final Pattern DATE_PATTERN = Pattern.compile("(\\d{4}-\\d{2}-\\d{2})");
+ private static final Pattern RELATIVE_RANGE_PATTERN = Pattern.compile("(杩憒鏈�杩�)\\s*(\\d{1,3})\\s*(澶﹟鍛▅涓湀|鏈坾骞�)");
+ private static final Pattern HALF_RANGE_PATTERN = Pattern.compile("(鏈�杩憒杩�)?鍗�(涓�)?(鏈坾骞�)");
+ private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ private static final ZoneId CHINA_ZONE_ID = ZoneId.of("Asia/Shanghai");
private final PurchaseAgentTools purchaseAgentTools;
@@ -25,71 +32,63 @@
return null;
}
String text = message.trim();
+ String quickPromptResponse = tryExecuteQuickPrompt(memoryId, text);
+ if (StringUtils.hasText(quickPromptResponse)) {
+ return quickPromptResponse;
+ }
- if (containsAny(text, "鎺掕", "鎺掑悕", "鍓嶅嚑", "鍓嶄簲", "鍓嶅崄") && containsAny(text, "鐗╂枡", "浜у搧", "鍘熸潗鏂�", "閲囪喘閲戦", "閲戦")) {
- return purchaseAgentTools.rankPurchaseMaterials(
- memoryId,
- extractStartDate(text),
- extractEndDate(text),
- text,
- extractLimit(text)
- );
+ String keyword = extractKeyword(text);
+ Integer limit = extractLimit(text);
+ DateRange dateRange = extractDateRange(text);
+ String startDate = dateRange.startDate();
+ String endDate = dateRange.endDate();
+
+ if (containsAny(text, "鎺掕", "鎺掑悕", "鍓嶅嚑", "鍓嶄簲", "鍓嶅崄")
+ && containsAny(text, "鐗╂枡", "浜у搧", "鍘熸潗鏂�", "閲囪喘閲戦", "閲戦")) {
+ return purchaseAgentTools.rankPurchaseMaterials(memoryId, startDate, endDate, text, limit);
}
if (containsAny(text, "鏈叆搴�", "寰呭叆搴�", "娌℃湁鍏ュ簱", "杩樻湭鍏ュ簱")) {
- return purchaseAgentTools.listUnstockedPurchaseOrders(
- memoryId,
- extractStartDate(text),
- extractEndDate(text),
- extractKeyword(text),
- extractLimit(text)
- );
+ return purchaseAgentTools.listUnstockedPurchaseOrders(memoryId, startDate, endDate, keyword, limit);
}
if (containsAny(text, "鍒拌揣寮傚父", "鍒拌揣鏈夊紓甯�", "寮傚父鍒拌揣", "鍒拌揣闂", "渚涘簲鍟嗗埌璐у紓甯�")) {
- return purchaseAgentTools.listArrivalExceptions(
- memoryId,
- extractStartDate(text),
- extractEndDate(text),
- text,
- extractLimit(text)
- );
+ return purchaseAgentTools.listArrivalExceptions(memoryId, startDate, endDate, text, limit);
}
if (containsAny(text, "寰呬粯娆�", "鏈粯娆�", "鏈粯娓�", "寰呮敮浠�", "搴斾粯")) {
- return purchaseAgentTools.listPendingPaymentOrders(
- memoryId,
- extractStartDate(text),
- extractEndDate(text),
- extractKeyword(text),
- extractLimit(text)
- );
+ return purchaseAgentTools.listPendingPaymentOrders(memoryId, startDate, endDate, keyword, limit);
}
if (containsAny(text, "閫�璐�", "閫�鏂�", "鎷掓敹")) {
- return purchaseAgentTools.listPurchaseReturns(
- memoryId,
- extractStartDate(text),
- extractEndDate(text),
- extractKeyword(text),
- extractLimit(text)
- );
+ return purchaseAgentTools.listPurchaseReturns(memoryId, startDate, endDate, keyword, limit);
}
if (isStatsIntent(text)) {
- return purchaseAgentTools.getPurchaseStats(
- memoryId,
- extractStartDate(text),
- extractEndDate(text),
- text
- );
+ return purchaseAgentTools.getPurchaseStats(memoryId, startDate, endDate, text);
}
- if (containsAny(text, "璇︽儏", "鏄庣粏") && extractId(text) != null) {
- return purchaseAgentTools.getPurchaseLedgerDetail(memoryId, extractId(text));
+
+ Long ledgerId = extractId(text);
+ if (containsAny(text, "璇︽儏", "鏄庣粏") && ledgerId != null) {
+ return purchaseAgentTools.getPurchaseLedgerDetail(memoryId, ledgerId);
}
if (containsAny(text, "鍙拌处", "閲囪喘鍗�", "閲囪喘璁㈠崟", "璁㈠崟", "鍚堝悓", "鍒楄〃", "鏌ヨ")) {
- return purchaseAgentTools.listPurchaseLedgers(
- memoryId,
- extractKeyword(text),
- extractStartDate(text),
- extractEndDate(text),
- extractLimit(text)
- );
+ return purchaseAgentTools.listPurchaseLedgers(memoryId, keyword, startDate, endDate, limit);
+ }
+ return null;
+ }
+
+ private String tryExecuteQuickPrompt(String memoryId, String text) {
+ String normalized = normalizeForMatch(text);
+ if ("鏈湀閲囪喘閲戦鎺掑悕鍓嶅崄鐨勭墿鏂欐湁鍝簺".equals(normalized)) {
+ return purchaseAgentTools.rankPurchaseMaterials(memoryId, null, null, "鏈湀", 10);
+ }
+ if ("鍝簺閲囪喘璁㈠崟杩樻湭鍏ュ簱".equals(normalized)) {
+ return purchaseAgentTools.listUnstockedPurchaseOrders(memoryId, null, null, null, 10);
+ }
+ if ("鏈�杩�7澶╀緵搴斿晢鍒拌揣寮傚父鏈夊摢浜�".equals(normalized)) {
+ return purchaseAgentTools.listArrivalExceptions(memoryId, null, null, "鏈�杩�7澶�", 10);
+ }
+ if ("甯垜缁熻寰呬粯娆鹃噰璐崟".equals(normalized)) {
+ return purchaseAgentTools.listPendingPaymentOrders(memoryId, null, null, null, 10);
+ }
+ if ("鍒楀嚭鏈湀閲囪喘閫�璐ф儏鍐�".equals(normalized)) {
+ return purchaseAgentTools.listPurchaseReturns(memoryId, null, null, null, 10);
}
return null;
}
@@ -100,8 +99,10 @@
}
boolean queryWord = containsAny(text, "鏌ヨ", "鏌ョ湅", "鐪嬩笅", "鐪嬬湅", "鑾峰彇");
boolean dataWord = containsAny(text, "鏁版嵁", "閲戦", "鏁伴噺", "鍚堝悓棰�", "浠樻棰�", "鍙戠エ棰�");
- boolean timeWord = containsAny(text, "浠婂ぉ", "鏈懆", "鏈湀", "涓婃湀", "浠婂勾", "鍘诲勾", "杩戝崐骞�", "鏈�杩戝崐涓湀", "鍗婁釜鏈�")
- || DATE_PATTERN.matcher(text).find();
+ boolean timeWord = containsAny(text, "浠婂ぉ", "鏄ㄥぉ", "鏈懆", "涓婂懆", "鏈湀", "涓婃湀", "浠婂勾", "鍘诲勾", "杩戝崐骞�", "鏈�杩戝崐涓湀", "鍗婁釜鏈�")
+ || DATE_PATTERN.matcher(text).find()
+ || RELATIVE_RANGE_PATTERN.matcher(text).find()
+ || HALF_RANGE_PATTERN.matcher(text).find();
return queryWord && dataWord && timeWord;
}
@@ -127,23 +128,125 @@
return matcher.find() ? Integer.parseInt(matcher.group(2)) : 10;
}
- private String extractStartDate(String text) {
+ private DateRange extractDateRange(String text) {
Matcher matcher = DATE_PATTERN.matcher(text);
- return matcher.find() ? matcher.group() : null;
+ if (matcher.find()) {
+ String first = matcher.group(1);
+ String second = matcher.find() ? matcher.group(1) : first;
+ return buildDateRange(first, second);
+ }
+
+ LocalDate today = LocalDate.now(CHINA_ZONE_ID);
+ if (text.contains("浠婂ぉ")) {
+ return new DateRange(formatDate(today), formatDate(today));
+ }
+ if (text.contains("鏄ㄥぉ")) {
+ LocalDate yesterday = today.minusDays(1);
+ return new DateRange(formatDate(yesterday), formatDate(yesterday));
+ }
+ if (text.contains("鏈懆")) {
+ LocalDate start = today.minusDays(today.getDayOfWeek().getValue() - 1L);
+ return new DateRange(formatDate(start), formatDate(today));
+ }
+ if (text.contains("涓婂懆")) {
+ LocalDate thisWeekStart = today.minusDays(today.getDayOfWeek().getValue() - 1L);
+ LocalDate start = thisWeekStart.minusWeeks(1);
+ LocalDate end = start.plusDays(6);
+ return new DateRange(formatDate(start), formatDate(end));
+ }
+ if (text.contains("鏈湀")) {
+ return new DateRange(formatDate(today.withDayOfMonth(1)), formatDate(today));
+ }
+ if (text.contains("涓婃湀")) {
+ LocalDate start = today.minusMonths(1).withDayOfMonth(1);
+ return new DateRange(formatDate(start), formatDate(start.withDayOfMonth(start.lengthOfMonth())));
+ }
+ if (text.contains("浠婂勾") || text.contains("鏈勾")) {
+ return new DateRange(formatDate(today.withDayOfYear(1)), formatDate(today));
+ }
+ if (text.contains("鍘诲勾")) {
+ LocalDate start = today.minusYears(1).withDayOfYear(1);
+ LocalDate end = start.withDayOfYear(start.lengthOfYear());
+ return new DateRange(formatDate(start), formatDate(end));
+ }
+ if (containsAny(text, "杩戝崐骞�", "鏈�杩戝崐骞�")) {
+ return new DateRange(formatDate(today.minusMonths(6).plusDays(1)), formatDate(today));
+ }
+ if (containsAny(text, "杩戝崐涓湀", "鏈�杩戝崐涓湀", "鍗婁釜鏈�")) {
+ return new DateRange(formatDate(today.minusDays(14)), formatDate(today));
+ }
+
+ Matcher relativeMatcher = RELATIVE_RANGE_PATTERN.matcher(text);
+ if (relativeMatcher.find()) {
+ int amount = Integer.parseInt(relativeMatcher.group(2));
+ String unit = relativeMatcher.group(3);
+ LocalDate start = switch (unit) {
+ case "澶�" -> today.minusDays(Math.max(amount - 1L, 0));
+ case "鍛�" -> today.minusWeeks(Math.max(amount, 1)).plusDays(1);
+ case "涓湀", "鏈�" -> today.minusMonths(Math.max(amount, 1)).plusDays(1);
+ case "骞�" -> today.minusYears(Math.max(amount, 1)).plusDays(1);
+ default -> today.minusDays(29);
+ };
+ return new DateRange(formatDate(start), formatDate(today));
+ }
+
+ return new DateRange(null, null);
}
- private String extractEndDate(String text) {
- Matcher matcher = DATE_PATTERN.matcher(text);
- if (!matcher.find()) {
+ private DateRange buildDateRange(String start, String end) {
+ LocalDate startDate = parseDate(start);
+ LocalDate endDate = parseDate(end);
+ if (startDate == null || endDate == null) {
+ return new DateRange(null, null);
+ }
+ if (startDate.isAfter(endDate)) {
+ LocalDate temp = startDate;
+ startDate = endDate;
+ endDate = temp;
+ }
+ return new DateRange(formatDate(startDate), formatDate(endDate));
+ }
+
+ private LocalDate parseDate(String text) {
+ try {
+ return LocalDate.parse(text, DATE_FMT);
+ } catch (Exception ignored) {
return null;
}
- return matcher.find() ? matcher.group() : null;
+ }
+
+ private String formatDate(LocalDate date) {
+ return date == null ? null : date.format(DATE_FMT);
+ }
+
+ private String normalizeForMatch(String text) {
+ if (!StringUtils.hasText(text)) {
+ return "";
+ }
+ return text.replace("锛�", "")
+ .replace(",", "")
+ .replace("銆�", "")
+ .replace(".", "")
+ .replace("锛�", "")
+ .replace("!", "")
+ .replace("锛�", "")
+ .replace("?", "")
+ .replace("锛�", "")
+ .replace(":", "")
+ .replace("锛�", "")
+ .replace(";", "")
+ .replace(" ", "")
+ .trim();
}
private String extractKeyword(String text) {
String cleaned = text
.replace("鏌ヨ", "")
.replace("鏌ョ湅", "")
+ .replace("鐪嬩笅", "")
+ .replace("鐪嬬湅", "")
+ .replace("璇�", "")
+ .replace("涓�涓�", "")
.replace("閲囪喘", "")
.replace("閲囪喘鍗�", "")
.replace("閲囪喘璁㈠崟", "")
@@ -153,9 +256,33 @@
.replace("鍝簺", "")
.replace("鍒楀嚭", "")
.replace("甯垜", "")
+ .replace("缁熻", "")
+ .replace("鍒嗘瀽", "")
+ .replace("鏈湀", "")
+ .replace("涓婃湀", "")
+ .replace("鏈勾", "")
+ .replace("浠婂勾", "")
+ .replace("鍘诲勾", "")
+ .replace("鏈懆", "")
+ .replace("涓婂懆", "")
+ .replace("浠婂ぉ", "")
+ .replace("鏄ㄥぉ", "")
+ .replace("杩�30澶�", "")
+ .replace("杩�7澶�", "")
+ .replace("杩�15澶�", "")
+ .replace("杩�60澶�", "")
+ .replace("鏈�杩�30澶�", "")
+ .replace("鏈�杩�7澶�", "")
+ .replace("鏈�杩�15澶�", "")
+ .replace("鏈�杩�60澶�", "")
.replace("鏈�杩�10鏉�", "")
.replace("鍓�10鏉�", "")
+ .replace("鍓�20鏉�", "")
+ .replace("鏈�杩�20鏉�", "")
.trim();
return cleaned.length() >= 2 ? cleaned : null;
}
+
+ private record DateRange(String startDate, String endDate) {
+ }
}
diff --git a/src/main/java/com/ruoyi/ai/assistant/SalesAgent.java b/src/main/java/com/ruoyi/ai/assistant/SalesAgent.java
index 1636239..e2f9a81 100644
--- a/src/main/java/com/ruoyi/ai/assistant/SalesAgent.java
+++ b/src/main/java/com/ruoyi/ai/assistant/SalesAgent.java
@@ -3,6 +3,7 @@
import dev.langchain4j.service.MemoryId;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.V;
import dev.langchain4j.service.spring.AiService;
import reactor.core.publisher.Flux;
@@ -17,6 +18,5 @@
public interface SalesAgent {
@SystemMessage(fromResource = "sales-agent-prompt.txt")
- Flux<String> chat(@MemoryId String memoryId, @UserMessage String userMessage);
+ Flux<String> chat(@MemoryId String memoryId, @UserMessage String userMessage, @V("currentDate") String currentDate);
}
-
diff --git a/src/main/java/com/ruoyi/ai/config/FinancialAgentConfig.java b/src/main/java/com/ruoyi/ai/config/FinancialAgentConfig.java
new file mode 100644
index 0000000..0706e74
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/config/FinancialAgentConfig.java
@@ -0,0 +1,20 @@
+package com.ruoyi.ai.config;
+
+import com.ruoyi.ai.store.MongoChatMemoryStore;
+import dev.langchain4j.memory.chat.ChatMemoryProvider;
+import dev.langchain4j.memory.chat.MessageWindowChatMemory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class FinancialAgentConfig {
+
+ @Bean
+ ChatMemoryProvider chatMemoryProviderFinancial(MongoChatMemoryStore mongoChatMemoryStore) {
+ return memoryId -> MessageWindowChatMemory.builder()
+ .id(memoryId)
+ .maxMessages(40)
+ .chatMemoryStore(mongoChatMemoryStore)
+ .build();
+ }
+}
diff --git a/src/main/java/com/ruoyi/ai/controller/FinancialAiController.java b/src/main/java/com/ruoyi/ai/controller/FinancialAiController.java
new file mode 100644
index 0000000..2a3089d
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/controller/FinancialAiController.java
@@ -0,0 +1,112 @@
+package com.ruoyi.ai.controller;
+
+import com.ruoyi.ai.assistant.FinancialAgent;
+import com.ruoyi.ai.assistant.FinancialIntentExecutor;
+import com.ruoyi.ai.bean.ChatForm;
+import com.ruoyi.ai.context.AiSessionUserContext;
+import com.ruoyi.ai.service.AiChatSessionService;
+import com.ruoyi.ai.store.MongoChatMemoryStore;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import dev.langchain4j.data.message.AiMessage;
+import dev.langchain4j.data.message.UserMessage;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+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.RestController;
+import reactor.core.publisher.Flux;
+
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+
+@Tag(name = "璐㈠姟鏅鸿兘浣�")
+@RestController
+@RequestMapping("/financial-ai")
+public class FinancialAiController extends BaseController {
+
+ private static final DateTimeFormatter CURRENT_DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ private static final ZoneId CHINA_ZONE_ID = ZoneId.of("Asia/Shanghai");
+
+ private final FinancialAgent financialAgent;
+ private final FinancialIntentExecutor financialIntentExecutor;
+ private final AiSessionUserContext aiSessionUserContext;
+ private final MongoChatMemoryStore mongoChatMemoryStore;
+ private final AiChatSessionService aiChatSessionService;
+
+ public FinancialAiController(FinancialAgent financialAgent,
+ FinancialIntentExecutor financialIntentExecutor,
+ AiSessionUserContext aiSessionUserContext,
+ MongoChatMemoryStore mongoChatMemoryStore,
+ AiChatSessionService aiChatSessionService) {
+ this.financialAgent = financialAgent;
+ this.financialIntentExecutor = financialIntentExecutor;
+ this.aiSessionUserContext = aiSessionUserContext;
+ this.mongoChatMemoryStore = mongoChatMemoryStore;
+ this.aiChatSessionService = aiChatSessionService;
+ }
+
+ @Operation(summary = "璐㈠姟鏅鸿兘浣撳璇�")
+ @PostMapping(value = "/chat", produces = "text/stream;charset=utf-8")
+ public Flux<String> chat(@RequestBody ChatForm chatForm) {
+ if (!StringUtils.hasText(chatForm.getMemoryId())) {
+ return Flux.just("memoryId涓嶈兘涓虹┖");
+ }
+ if (!StringUtils.hasText(chatForm.getMessage())) {
+ return Flux.just("message涓嶈兘涓虹┖");
+ }
+
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ String memoryId = chatForm.getMemoryId();
+ String userMessage = chatForm.getMessage();
+
+ aiSessionUserContext.bind(memoryId, loginUser);
+ aiChatSessionService.touchSession(memoryId, loginUser, userMessage);
+
+ String directResponse = financialIntentExecutor.tryExecute(memoryId, userMessage);
+ if (StringUtils.isNotEmpty(directResponse)) {
+ mongoChatMemoryStore.appendMessages(
+ memoryId,
+ List.of(UserMessage.from(userMessage), AiMessage.from(directResponse))
+ );
+ aiChatSessionService.refreshSessionStats(memoryId, loginUser);
+ return Flux.just(directResponse);
+ }
+
+ return financialAgent.chat(memoryId, userMessage, currentDateForPrompt())
+ .doOnComplete(() -> aiChatSessionService.refreshSessionStats(memoryId, loginUser))
+ .doOnError(ex -> aiChatSessionService.refreshSessionStats(memoryId, loginUser));
+ }
+
+ @Operation(summary = "璐㈠姟鏅鸿兘浣撲細璇濆垪琛�")
+ @GetMapping("/history/sessions")
+ public AjaxResult listSessions() {
+ return success(aiChatSessionService.listCurrentUserSessions(SecurityUtils.getLoginUser()));
+ }
+
+ @Operation(summary = "璐㈠姟鏅鸿兘浣撲細璇濇秷鎭�")
+ @GetMapping("/history/messages/{memoryId}")
+ public AjaxResult listMessages(@PathVariable String memoryId) {
+ return success(aiChatSessionService.listCurrentUserMessages(memoryId, SecurityUtils.getLoginUser()));
+ }
+
+ @Operation(summary = "鍒犻櫎璐㈠姟鏅鸿兘浣撲細璇�")
+ @DeleteMapping("/history/{memoryId}")
+ public AjaxResult deleteSession(@PathVariable String memoryId) {
+ aiSessionUserContext.remove(memoryId);
+ return toAjax(aiChatSessionService.deleteCurrentUserSession(memoryId, SecurityUtils.getLoginUser()));
+ }
+
+ private String currentDateForPrompt() {
+ return LocalDate.now(CHINA_ZONE_ID).format(CURRENT_DATE_FMT);
+ }
+}
diff --git a/src/main/java/com/ruoyi/ai/controller/ManufacturingAiController.java b/src/main/java/com/ruoyi/ai/controller/ManufacturingAiController.java
index cb7c0ba..87eb418 100644
--- a/src/main/java/com/ruoyi/ai/controller/ManufacturingAiController.java
+++ b/src/main/java/com/ruoyi/ai/controller/ManufacturingAiController.java
@@ -24,12 +24,18 @@
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
import java.util.List;
@Tag(name = "鍒堕�犳櫤鑳藉姪鎵�")
@RestController
@RequestMapping("/manufacturing-ai")
public class ManufacturingAiController extends BaseController {
+
+ private static final DateTimeFormatter CURRENT_DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ private static final ZoneId CHINA_ZONE_ID = ZoneId.of("Asia/Shanghai");
private final ManufacturingAgent manufacturingAgent;
private final ManufacturingIntentExecutor manufacturingIntentExecutor;
@@ -76,7 +82,7 @@
return Flux.just(directResponse);
}
- return manufacturingAgent.chat(memoryId, userMessage)
+ return manufacturingAgent.chat(memoryId, userMessage, currentDateForPrompt())
.doOnComplete(() -> aiChatSessionService.refreshSessionStats(memoryId, loginUser))
.doOnError(ex -> aiChatSessionService.refreshSessionStats(memoryId, loginUser));
}
@@ -99,4 +105,8 @@
aiSessionUserContext.remove(memoryId);
return toAjax(aiChatSessionService.deleteCurrentUserSession(memoryId, SecurityUtils.getLoginUser()));
}
+
+ private String currentDateForPrompt() {
+ return LocalDate.now(CHINA_ZONE_ID).format(CURRENT_DATE_FMT);
+ }
}
diff --git a/src/main/java/com/ruoyi/ai/controller/SalesAiController.java b/src/main/java/com/ruoyi/ai/controller/SalesAiController.java
index c3a569b..0c92ad6 100644
--- a/src/main/java/com/ruoyi/ai/controller/SalesAiController.java
+++ b/src/main/java/com/ruoyi/ai/controller/SalesAiController.java
@@ -24,12 +24,18 @@
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
import java.util.List;
@Tag(name = "閿�鍞姪鎵嬫櫤鑳戒綋")
@RestController
@RequestMapping("/sales-ai")
public class SalesAiController extends BaseController {
+
+ private static final DateTimeFormatter CURRENT_DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ private static final ZoneId CHINA_ZONE_ID = ZoneId.of("Asia/Shanghai");
private final SalesAgent salesAgent;
private final SalesIntentExecutor salesIntentExecutor;
@@ -86,7 +92,7 @@
return Flux.just(noGuessResponse);
}
- return salesAgent.chat(memoryId, userMessage)
+ return salesAgent.chat(memoryId, userMessage, currentDateForPrompt())
.doOnComplete(() -> aiChatSessionService.refreshSessionStats(memoryId, loginUser))
.doOnError(ex -> aiChatSessionService.refreshSessionStats(memoryId, loginUser));
}
@@ -128,4 +134,8 @@
}
return false;
}
+
+ private String currentDateForPrompt() {
+ return LocalDate.now(CHINA_ZONE_ID).format(CURRENT_DATE_FMT);
+ }
}
diff --git a/src/main/java/com/ruoyi/ai/controller/XiaozhiController.java b/src/main/java/com/ruoyi/ai/controller/XiaozhiController.java
index affa347..82d088c 100644
--- a/src/main/java/com/ruoyi/ai/controller/XiaozhiController.java
+++ b/src/main/java/com/ruoyi/ai/controller/XiaozhiController.java
@@ -29,6 +29,9 @@
import reactor.core.publisher.Flux;
import java.io.IOException;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.UUID;
@@ -39,6 +42,8 @@
public class XiaozhiController extends BaseController {
private static final String FILE_ANALYZE_MEMORY_PREFIX = "file-analyze::";
+ private static final DateTimeFormatter CURRENT_DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ private static final ZoneId CHINA_ZONE_ID = ZoneId.of("Asia/Shanghai");
private final ApproveTodoAgent approveTodoAgent;
private final ApproveTodoIntentExecutor approveTodoIntentExecutor;
@@ -100,7 +105,7 @@
return Flux.just(noGuessResponse);
}
- return approveTodoAgent.chat(memoryId, userMessage)
+ return approveTodoAgent.chat(memoryId, userMessage, currentDateForPrompt())
.doOnComplete(() -> aiChatSessionService.refreshSessionStats(memoryId, loginUser))
.doOnError(ex -> aiChatSessionService.refreshSessionStats(memoryId, loginUser));
}
@@ -190,4 +195,8 @@
}
return false;
}
+
+ private String currentDateForPrompt() {
+ return LocalDate.now(CHINA_ZONE_ID).format(CURRENT_DATE_FMT);
+ }
}
diff --git a/src/main/java/com/ruoyi/ai/service/PurchaseAiService.java b/src/main/java/com/ruoyi/ai/service/PurchaseAiService.java
index 0f24d64..cbc936c 100644
--- a/src/main/java/com/ruoyi/ai/service/PurchaseAiService.java
+++ b/src/main/java/com/ruoyi/ai/service/PurchaseAiService.java
@@ -1,5 +1,6 @@
package com.ruoyi.ai.service;
+import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -20,8 +21,6 @@
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.purchase.dto.PurchaseLedgerDto;
import com.ruoyi.purchase.dto.PurchaseReturnOrderDto;
-import com.ruoyi.purchase.pojo.PaymentRegistration;
-import com.ruoyi.purchase.service.IPaymentRegistrationService;
import com.ruoyi.purchase.service.IPurchaseLedgerService;
import com.ruoyi.purchase.service.PurchaseReturnOrdersService;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
@@ -48,7 +47,6 @@
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Base64;
-import java.util.Arrays;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
@@ -71,6 +69,8 @@
private static final int MAX_FILE_COUNT = 10;
private static final int MAX_SINGLE_FILE_TEXT_LENGTH = 8000;
private static final int MAX_TOTAL_FILE_TEXT_LENGTH = 30000;
+ private static final DateTimeFormatter CURRENT_DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ private static final ZoneId CHINA_ZONE_ID = ZoneId.of("Asia/Shanghai");
private final PurchaseAgent purchaseAgent;
private final PurchaseIntentExecutor purchaseIntentExecutor;
@@ -80,7 +80,6 @@
private final AiFileTextExtractor aiFileTextExtractor;
private final ObjectMapper objectMapper;
private final IPurchaseLedgerService purchaseLedgerService;
- private final IPaymentRegistrationService paymentRegistrationService;
private final PurchaseReturnOrdersService purchaseReturnOrdersService;
private final StorageBlobService storageBlobService;
private final SupplierManageMapper supplierManageMapper;
@@ -94,7 +93,6 @@
AiFileTextExtractor aiFileTextExtractor,
ObjectMapper objectMapper,
IPurchaseLedgerService purchaseLedgerService,
- IPaymentRegistrationService paymentRegistrationService,
PurchaseReturnOrdersService purchaseReturnOrdersService,
StorageBlobService storageBlobService,
SupplierManageMapper supplierManageMapper,
@@ -107,7 +105,6 @@
this.aiFileTextExtractor = aiFileTextExtractor;
this.objectMapper = objectMapper;
this.purchaseLedgerService = purchaseLedgerService;
- this.paymentRegistrationService = paymentRegistrationService;
this.purchaseReturnOrdersService = purchaseReturnOrdersService;
this.storageBlobService = storageBlobService;
this.supplierManageMapper = supplierManageMapper;
@@ -138,7 +135,17 @@
return Flux.just(directResponse);
}
- return purchaseAgent.chat(memoryId, userMessage)
+ if (isPurchaseBusinessIntent(userMessage)) {
+ String noGuessResponse = buildNoGuessResponse();
+ mongoChatMemoryStore.appendMessages(
+ memoryId,
+ List.of(UserMessage.from(userMessage), AiMessage.from(noGuessResponse))
+ );
+ aiChatSessionService.refreshSessionStats(memoryId, loginUser);
+ return Flux.just(noGuessResponse);
+ }
+
+ return purchaseAgent.chat(memoryId, userMessage, currentDateForPrompt())
.doOnComplete(() -> aiChatSessionService.refreshSessionStats(memoryId, loginUser))
.doOnError(ex -> aiChatSessionService.refreshSessionStats(memoryId, loginUser));
}
@@ -200,10 +207,10 @@
.doOnError(ex -> aiChatSessionService.refreshSessionStats(finalMemoryId, loginUser));
}
- return Flux.defer(() -> purchaseAgent.chat(finalMemoryId, userPrompt))
+ return Flux.defer(() -> purchaseAgent.chat(finalMemoryId, userPrompt, currentDateForPrompt()))
.onErrorResume(NoSuchElementException.class, ex -> {
mongoChatMemoryStore.deleteMessages(finalMemoryId);
- return purchaseAgent.chat(finalMemoryId, userPrompt);
+ return purchaseAgent.chat(finalMemoryId, userPrompt, currentDateForPrompt());
})
.doOnComplete(() -> aiChatSessionService.refreshSessionStats(finalMemoryId, loginUser))
.doOnError(ex -> aiChatSessionService.refreshSessionStats(finalMemoryId, loginUser));
@@ -221,7 +228,6 @@
String businessType = request.getBusinessType().trim();
return switch (businessType) {
case "purchase_ledger" -> processPurchaseLedger(request.getPayload());
- case "payment_registration" -> processPaymentRegistration(request.getPayload());
case "purchase_return_order" -> processPurchaseReturnOrder(request.getPayload());
default -> AjaxResult.error("鏆備笉鏀寔璇ヤ笟鍔$被鍨�: " + businessType);
};
@@ -471,6 +477,51 @@
};
}
+ private String currentDateForPrompt() {
+ return LocalDate.now(CHINA_ZONE_ID).format(CURRENT_DATE_FMT);
+ }
+
+ private boolean isPurchaseBusinessIntent(String message) {
+ if (!StringUtils.hasText(message)) {
+ return false;
+ }
+ String text = message.trim();
+ boolean hasDomainWord = containsAny(text,
+ "閲囪喘", "閲囪喘鍙拌处", "閲囪喘鍗�", "閲囪喘璁㈠崟", "渚涘簲鍟�", "鐗╂枡", "鍏ュ簱", "鍒拌揣", "寰呬粯娆�",
+ "浠樻", "閫�璐�", "閫�鏂�", "鍙戠エ", "鍚堝悓");
+ boolean hasIntentWord = containsAny(text,
+ "鏌ヨ", "鏌ョ湅", "缁熻", "鍒嗘瀽", "鎺掕", "鎺掑悕", "鍒楀嚭", "鏈夊摢浜�", "鎯呭喌", "鏄庣粏", "璇︽儏", "鎶ヨ〃");
+ return hasDomainWord && hasIntentWord;
+ }
+
+ private boolean containsAny(String text, String... keywords) {
+ for (String keyword : keywords) {
+ if (text.contains(keyword)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private String buildNoGuessResponse() {
+ Map<String, Object> result = new LinkedHashMap<>();
+ result.put("success", false);
+ result.put("type", "purchase_intent_not_recognized");
+ result.put("description", "鏈瘑鍒埌鍙墽琛岀殑閲囪喘鏌ヨ鏉′欢銆備负淇濊瘉缁撴灉鍑嗙‘锛屽綋鍓嶄笉浼氭帹娴嬫垨缂栭�犳暟鎹紝璇疯ˉ鍏呮槑纭椂闂磋寖鍥淬�佷緵搴斿晢銆侀噰璐悎鍚屽彿鎴栫墿鏂欏悗鍐嶆煡璇€��");
+ result.put("summary", Map.of());
+ result.put("data", Map.of(
+ "quickPrompts", List.of(
+ "鏈湀閲囪喘閲戦鎺掑悕鍓嶅崄鐨勭墿鏂欐湁鍝簺锛�",
+ "鍝簺閲囪喘璁㈠崟杩樻湭鍏ュ簱锛�",
+ "鏈�杩�7澶╀緵搴斿晢鍒拌揣寮傚父鏈夊摢浜涳紵",
+ "甯垜缁熻寰呬粯娆鹃噰璐崟锛�",
+ "鍒楀嚭鏈湀閲囪喘閫�璐ф儏鍐�"
+ )
+ ));
+ result.put("charts", Map.of());
+ return JSON.toJSONString(result);
+ }
+
private String buildPurchaseFileAnalyzePrompt(String message, String fileContent) {
return """
浣犳槸閲囪喘涓氬姟鏂囦欢鍒嗘瀽鍔╂墜銆傝涓ユ牸鏍规嵁鐢ㄦ埛涓婁紶鐨勫涓枃浠跺拰鐢ㄦ埛瑕佹眰鎻愬彇閲囪喘涓氬姟鏁版嵁銆�
@@ -482,7 +533,7 @@
1. 鍙緭鍑哄悎娉� JSON锛屼笉瑕� Markdown锛屼笉瑕侀澶栬В閲娿��
2. JSON 椤跺眰瀛楁鍥哄畾涓�:
- success: boolean
- - businessType: purchase_ledger | payment_registration | purchase_return_order | unknown
+ - businessType: purchase_ledger | purchase_return_order | unknown
- action: confirm_required
- description: 涓枃璇存槑
- confidence: 0鍒�1鐨勫皬鏁�
@@ -507,7 +558,7 @@
entryDateStart, entryDateEnd, id, purchaseContractNumber, supplierId, supplierName, isWhite, recorderId, recorderName, salesContractNo, salesContractNoId, projectName, entryDate, executionDate, remarks, attachmentMaterials, createdAt, updatedAt, salesLedgerId, hasChildren, Type, productData, tempFileIds, SalesLedgerFiles, phoneNumber, businessPersonId, productId, productModelId, invoiceNumber, invoiceAmount, ticketRegistrationId, contractAmount, receiptPaymentAmount, unReceiptPaymentAmount, type, paymentMethod, approvalStatus, templateName
- productData 姣忔潯浜у搧鍙娇鐢ㄨ繖浜� SalesLedgerProduct 瀛楁鍚�:
productCategory, specificationModel, unit, quantity, taxRate, taxInclusiveUnitPrice, taxInclusiveTotalPrice, taxExclusiveTotalPrice, invoiceType, productId, productModelId, isChecked, type
- 4. 濡傛灉鍙垽鏂负浠樻鐧昏锛宐usinessType 浣跨敤 payment_registration锛宲ayload.records 涓轰粯娆剧櫥璁版暟缁勶紝瀛楁灏介噺鍖呭惈 purchaseLedgerId銆乻alesLedgerProductId銆乧urrentPaymentAmount銆乸aymentMethod銆乸aymentDate銆�
+ 4. 濡傛灉鍙垽鏂负浠樻鐧昏锛宐usinessType 浣跨敤 payload.records 涓轰粯娆剧櫥璁版暟缁勶紝瀛楁灏介噺鍖呭惈 purchaseLedgerId銆乻alesLedgerProductId銆乧urrentPaymentAmount銆乸aymentMethod銆乸aymentDate銆�
5. 濡傛灉鍙垽鏂负閲囪喘閫�璐э紝businessType 浣跨敤 purchase_return_order锛宲ayload 鎸� PurchaseReturnOrderDto 缁勭粐锛屾槑缁嗘斁 purchaseReturnOrderProductsDtos銆�
6. 缂哄皯涓氬姟澶勭悊蹇呴』瀛楁鏃讹紝涓嶈缂栭�� ID锛屾妸瀛楁鏀惧叆 missingFields锛屽苟浠嶈繑鍥炲彲纭鐨勮崏绋挎暟鎹��
7. 鎵�鏈変腑鏂囧唴瀹圭洿鎺ヤ繚鐣欙紝涓嶈杞箟鎴� Unicode銆�
@@ -1008,19 +1059,6 @@
}
dto.setSupplierId(supplier.getId());
return null;
- }
-
- private AjaxResult processPaymentRegistration(Map<String, Object> payload) {
- Object recordsValue = payload.get("records");
- List<PaymentRegistration> records;
- if (recordsValue == null) {
- records = Collections.singletonList(objectMapper.convertValue(payload, PaymentRegistration.class));
- } else {
- records = objectMapper.convertValue(recordsValue, new TypeReference<List<PaymentRegistration>>() {
- });
- }
- int result = paymentRegistrationService.insertPaymentRegistration(records);
- return AjaxResult.success("浠樻鐧昏宸插鐞�", result);
}
private AjaxResult processPurchaseReturnOrder(Map<String, Object> payload) {
diff --git a/src/main/java/com/ruoyi/ai/tools/FinancialAgentTools.java b/src/main/java/com/ruoyi/ai/tools/FinancialAgentTools.java
new file mode 100644
index 0000000..900242b
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/tools/FinancialAgentTools.java
@@ -0,0 +1,2226 @@
+package com.ruoyi.ai.tools;
+
+import com.alibaba.fastjson2.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+import com.ruoyi.account.mapper.AccountStatementMapper;
+import com.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper;
+import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper;
+import com.ruoyi.account.pojo.AccountStatement;
+import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
+import com.ruoyi.account.pojo.sales.AccountSalesCollection;
+import com.ruoyi.account.service.impl.AccountingServiceImpl;
+import com.ruoyi.ai.context.AiSessionUserContext;
+import com.ruoyi.basic.mapper.CustomerMapper;
+import com.ruoyi.basic.mapper.ProductMapper;
+import com.ruoyi.basic.mapper.ProductModelMapper;
+import com.ruoyi.basic.mapper.SupplierManageMapper;
+import com.ruoyi.basic.pojo.Customer;
+import com.ruoyi.basic.pojo.Product;
+import com.ruoyi.basic.pojo.ProductModel;
+import com.ruoyi.basic.pojo.SupplierManage;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.device.mapper.DeviceLedgerMapper;
+import com.ruoyi.device.mapper.DeviceRepairMapper;
+import com.ruoyi.device.pojo.DeviceLedger;
+import com.ruoyi.device.pojo.DeviceRepair;
+import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper;
+import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper;
+import com.ruoyi.procurementrecord.pojo.ProcurementRecordOut;
+import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
+import com.ruoyi.production.mapper.ProductionAccountMapper;
+import com.ruoyi.production.mapper.ProductionOperationTaskMapper;
+import com.ruoyi.production.mapper.ProductionOrderMapper;
+import com.ruoyi.production.mapper.ProductionPlanMapper;
+import com.ruoyi.production.mapper.ProductionProductMainMapper;
+import com.ruoyi.production.mapper.ProductionProductOutputMapper;
+import com.ruoyi.production.pojo.ProductionAccount;
+import com.ruoyi.production.pojo.ProductionOperationTask;
+import com.ruoyi.production.pojo.ProductionOrder;
+import com.ruoyi.production.pojo.ProductionPlan;
+import com.ruoyi.production.pojo.ProductionProductMain;
+import com.ruoyi.production.pojo.ProductionProductOutput;
+import com.ruoyi.sales.mapper.SalesLedgerMapper;
+import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
+import com.ruoyi.sales.pojo.SalesLedger;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.stock.mapper.StockInventoryMapper;
+import com.ruoyi.stock.pojo.StockInventory;
+import com.ruoyi.technology.mapper.TechnologyOperationMapper;
+import com.ruoyi.technology.pojo.TechnologyOperation;
+import dev.langchain4j.agent.tool.P;
+import dev.langchain4j.agent.tool.Tool;
+import dev.langchain4j.agent.tool.ToolMemoryId;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.YearMonth;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+@Component
+public class FinancialAgentTools {
+
+ private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ private static final Pattern RELATIVE_PATTERN = Pattern.compile("(杩憒鏈�杩�)?\\s*(\\d+)\\s*(澶﹟鍛▅涓湀|鏈坾骞�)");
+ private static final Pattern DATE_PATTERN = Pattern.compile("(\\d{4}-\\d{2}-\\d{2})");
+ private static final BigDecimal ONE_HUNDRED = new BigDecimal("100");
+ private static final int DEFAULT_LIMIT = 10;
+ private static final int MAX_LIMIT = 50;
+ private static final BigDecimal DEFAULT_FALLBACK_MATERIAL_COST_RATE = new BigDecimal("0.65");
+
+ private final SalesLedgerMapper salesLedgerMapper;
+ private final SalesLedgerProductMapper salesLedgerProductMapper;
+ private final ProductionAccountMapper productionAccountMapper;
+ private final ProductionProductMainMapper productionProductMainMapper;
+ private final ProductionOperationTaskMapper productionOperationTaskMapper;
+ private final ProductionOrderMapper productionOrderMapper;
+ private final ProductionPlanMapper productionPlanMapper;
+ private final ProductionProductOutputMapper productionProductOutputMapper;
+ private final TechnologyOperationMapper technologyOperationMapper;
+ private final DeviceLedgerMapper deviceLedgerMapper;
+ private final DeviceRepairMapper deviceRepairMapper;
+ private final ProcurementRecordMapper procurementRecordMapper;
+ private final ProcurementRecordOutMapper procurementRecordOutMapper;
+ private final StockInventoryMapper stockInventoryMapper;
+ private final AccountSalesCollectionMapper accountSalesCollectionMapper;
+ private final AccountPurchasePaymentMapper accountPurchasePaymentMapper;
+ private final AccountStatementMapper accountStatementMapper;
+ private final CustomerMapper customerMapper;
+ private final SupplierManageMapper supplierManageMapper;
+ private final ProductModelMapper productModelMapper;
+ private final ProductMapper productMapper;
+ private final AiSessionUserContext aiSessionUserContext;
+
+ public FinancialAgentTools(SalesLedgerMapper salesLedgerMapper,
+ SalesLedgerProductMapper salesLedgerProductMapper,
+ ProductionAccountMapper productionAccountMapper,
+ ProductionProductMainMapper productionProductMainMapper,
+ ProductionOperationTaskMapper productionOperationTaskMapper,
+ ProductionOrderMapper productionOrderMapper,
+ ProductionPlanMapper productionPlanMapper,
+ ProductionProductOutputMapper productionProductOutputMapper,
+ TechnologyOperationMapper technologyOperationMapper,
+ DeviceLedgerMapper deviceLedgerMapper,
+ DeviceRepairMapper deviceRepairMapper,
+ ProcurementRecordMapper procurementRecordMapper,
+ ProcurementRecordOutMapper procurementRecordOutMapper,
+ StockInventoryMapper stockInventoryMapper,
+ AccountSalesCollectionMapper accountSalesCollectionMapper,
+ AccountPurchasePaymentMapper accountPurchasePaymentMapper,
+ AccountStatementMapper accountStatementMapper,
+ CustomerMapper customerMapper,
+ SupplierManageMapper supplierManageMapper,
+ ProductModelMapper productModelMapper,
+ ProductMapper productMapper,
+ AiSessionUserContext aiSessionUserContext) {
+ this.salesLedgerMapper = salesLedgerMapper;
+ this.salesLedgerProductMapper = salesLedgerProductMapper;
+ this.productionAccountMapper = productionAccountMapper;
+ this.productionProductMainMapper = productionProductMainMapper;
+ this.productionOperationTaskMapper = productionOperationTaskMapper;
+ this.productionOrderMapper = productionOrderMapper;
+ this.productionPlanMapper = productionPlanMapper;
+ this.productionProductOutputMapper = productionProductOutputMapper;
+ this.technologyOperationMapper = technologyOperationMapper;
+ this.deviceLedgerMapper = deviceLedgerMapper;
+ this.deviceRepairMapper = deviceRepairMapper;
+ this.procurementRecordMapper = procurementRecordMapper;
+ this.procurementRecordOutMapper = procurementRecordOutMapper;
+ this.stockInventoryMapper = stockInventoryMapper;
+ this.accountSalesCollectionMapper = accountSalesCollectionMapper;
+ this.accountPurchasePaymentMapper = accountPurchasePaymentMapper;
+ this.accountStatementMapper = accountStatementMapper;
+ this.customerMapper = customerMapper;
+ this.supplierManageMapper = supplierManageMapper;
+ this.productModelMapper = productModelMapper;
+ this.productMapper = productMapper;
+ this.aiSessionUserContext = aiSessionUserContext;
+ }
+
+ @Tool(name = "璐㈠姟鐭ヨ瘑妫�绱�", value = "鎸夎储鍔$粡钀ラ棶棰樻绱笟璐㈣瀺鍚堢煡璇嗙墖娈典笌鎸囨爣鍙e緞锛屼綔涓篟AG涓婁笅鏂囥��")
+ public String retrieveFinancialKnowledge(@ToolMemoryId String memoryId,
+ @P(value = "闂鎴栧叧閿瘝锛屼緥濡傚埄娑︿笅闄嶃�佸簱瀛樺懆杞�佽祫閲戠己鍙�") String question) {
+ List<KnowledgeDoc> knowledgeDocs = financeKnowledgeBase();
+ String normalized = normalizeForMatch(question);
+ List<KnowledgeDoc> ranked = knowledgeDocs.stream()
+ .sorted(Comparator.comparingInt((KnowledgeDoc doc) -> keywordHitCount(doc.keywords(), normalized)).reversed())
+ .filter(doc -> keywordHitCount(doc.keywords(), normalized) > 0 || !StringUtils.hasText(normalized))
+ .limit(5)
+ .toList();
+
+ List<Map<String, Object>> items = ranked.stream().map(doc -> {
+ Map<String, Object> map = new LinkedHashMap<>();
+ map.put("topic", doc.topic());
+ map.put("knowledge", doc.knowledge());
+ map.put("relatedTables", doc.relatedTables());
+ map.put("suggestedQuestions", doc.suggestedQuestions());
+ return map;
+ }).toList();
+
+ Map<String, Object> summary = new LinkedHashMap<>();
+ summary.put("question", safe(question));
+ summary.put("hitCount", items.size());
+ summary.put("retrievalMode", "keyword_rag");
+ return jsonResponse(true, "financial_rag_knowledge", "宸茶繑鍥炶储鍔$煡璇嗘绱㈢粨鏋�", summary, Map.of("items", items), Map.of());
+ }
+
+ @Tool(name = "鏅鸿兘鎴愭湰鏍哥畻", value = "鑷姩鏍哥畻浜у搧鎴愭湰銆佸伐搴忔垚鏈�佷汉宸ユ垚鏈�佽澶囨姌鏃с�佹潗鏂欐崯鑰椾笌璁㈠崟鍒╂鼎銆�")
+ public String calculateIntelligentCost(@ToolMemoryId String memoryId,
+ @P(value = "寮�濮嬫棩鏈� yyyy-MM-dd", required = false) String startDate,
+ @P(value = "缁撴潫鏃ユ湡 yyyy-MM-dd", required = false) String endDate,
+ @P(value = "鏃堕棿鑼冨洿鎻忚堪锛屽鏈湀銆佽繎30澶�", required = false) String timeRange,
+ @P(value = "鍏抽敭璇嶏紝鍙尮閰嶅悎鍚屽彿/瀹㈡埛/椤圭洰", required = false) String keyword,
+ @P(value = "杩斿洖鏉℃暟锛岄粯璁�10锛屾渶澶�50", required = false) Integer limit) {
+ LoginUser loginUser = currentLoginUser(memoryId);
+ DateRange range = resolveDateRange(startDate, endDate, timeRange, "杩�30澶�");
+ AnalysisBundle bundle = buildOrderProfitBundle(loginUser, range, keyword, limit);
+
+ Map<String, Object> summary = new LinkedHashMap<>();
+ summary.put("timeRange", range.label());
+ summary.put("startDate", range.start().toString());
+ summary.put("endDate", range.end().toString());
+ summary.put("orderCount", bundle.orderMetrics().size());
+ summary.put("totalRevenue", bundle.totalRevenue());
+ summary.put("totalMaterialCost", bundle.totalMaterialCost());
+ summary.put("totalLaborCost", bundle.totalLaborCost());
+ summary.put("totalDepreciationCost", bundle.totalDepreciationCost());
+ summary.put("totalScrapCost", bundle.totalScrapCost());
+ summary.put("totalCost", bundle.totalCost());
+ summary.put("totalProfit", bundle.totalProfit());
+ summary.put("profitRate", toPercent(rate(bundle.totalProfit(), bundle.totalRevenue())));
+
+ List<Map<String, Object>> orderItems = bundle.orderMetrics().stream()
+ .map(this::toOrderCostItem)
+ .toList();
+ List<Map<String, Object>> processItems = bundle.processCostRanking().entrySet().stream()
+ .map(entry -> {
+ Map<String, Object> map = new LinkedHashMap<>();
+ map.put("processName", entry.getKey());
+ map.put("cost", entry.getValue());
+ return map;
+ }).toList();
+
+ List<Map<String, Object>> topCustomerItems = buildCustomerProfitTop(bundle.orderMetrics(), 5);
+
+ Map<String, Object> charts = new LinkedHashMap<>();
+ charts.put("costCompositionPieOption",
+ buildCostCompositionPie(bundle.totalMaterialCost(), bundle.totalLaborCost(), bundle.totalDepreciationCost(), bundle.totalScrapCost()));
+ charts.put("orderProfitBarOption", buildOrderProfitBar(bundle.orderMetrics()));
+ charts.put("processCostBarOption", buildProcessCostBar(bundle.processCostRanking()));
+
+ return jsonResponse(true, "financial_cost_accounting", "宸插畬鎴愭櫤鑳芥垚鏈牳绠�", summary,
+ Map.of(
+ "orders", orderItems,
+ "processCostRanking", processItems,
+ "topCustomers", topCustomerItems
+ ),
+ charts
+ );
+ }
+
+ @Tool(name = "璁㈠崟鍒╂鼎鍒嗘瀽", value = "璇嗗埆浣庡埄娑�/浜忔崯璁㈠崟锛岃緭鍑哄師鍥犲垎鏋愬拰浼樺寲寤鸿銆�")
+ public String analyzeOrderProfit(@ToolMemoryId String memoryId,
+ @P(value = "寮�濮嬫棩鏈� yyyy-MM-dd", required = false) String startDate,
+ @P(value = "缁撴潫鏃ユ湡 yyyy-MM-dd", required = false) String endDate,
+ @P(value = "鏃堕棿鑼冨洿鎻忚堪锛屽鏈湀銆佽繎30澶�", required = false) String timeRange,
+ @P(value = "鍏抽敭璇嶏紝鍙尮閰嶅悎鍚屽彿/瀹㈡埛/椤圭洰", required = false) String keyword,
+ @P(value = "杩斿洖鏉℃暟锛岄粯璁�10锛屾渶澶�50", required = false) Integer limit) {
+ LoginUser loginUser = currentLoginUser(memoryId);
+ DateRange range = resolveDateRange(startDate, endDate, timeRange, "杩�30澶�");
+ AnalysisBundle bundle = buildOrderProfitBundle(loginUser, range, keyword, limit);
+ List<OrderProfitMetric> metrics = bundle.orderMetrics();
+
+ List<OrderProfitMetric> riskyOrders = metrics.stream()
+ .filter(item -> item.profit().compareTo(BigDecimal.ZERO) < 0 || item.profitRate().compareTo(new BigDecimal("0.08")) < 0)
+ .sorted(Comparator.comparing(OrderProfitMetric::profitRate)
+ .thenComparing(OrderProfitMetric::profit))
+ .toList();
+
+ Map<String, BigDecimal> customerProfitMap = new LinkedHashMap<>();
+ for (OrderProfitMetric metric : metrics) {
+ customerProfitMap.merge(metric.customerName(), metric.profit(), BigDecimal::add);
+ }
+ Map.Entry<String, BigDecimal> topCustomer = customerProfitMap.entrySet().stream()
+ .max(Map.Entry.comparingByValue())
+ .orElse(Map.entry("鏆傛棤鏁版嵁", BigDecimal.ZERO));
+
+ Map<String, Object> summary = new LinkedHashMap<>();
+ summary.put("timeRange", range.label());
+ summary.put("startDate", range.start().toString());
+ summary.put("endDate", range.end().toString());
+ summary.put("orderCount", metrics.size());
+ summary.put("lossOrderCount", metrics.stream().filter(item -> item.profit().compareTo(BigDecimal.ZERO) < 0).count());
+ summary.put("lowProfitOrderCount", riskyOrders.size());
+ summary.put("avgProfitRate", toPercent(avgRate(metrics)));
+ summary.put("topCustomerByProfit", topCustomer.getKey());
+ summary.put("topCustomerProfit", topCustomer.getValue());
+
+ List<Map<String, Object>> riskyItems = riskyOrders.stream()
+ .limit(normalizeLimit(limit))
+ .map(this::toRiskOrderItem)
+ .toList();
+
+ Map<String, Object> charts = new LinkedHashMap<>();
+ charts.put("profitDistributionOption", buildProfitDistributionBar(metrics));
+ charts.put("lossOrderTrendOption", buildLossOrderTrendLine(metrics));
+ charts.put("customerProfitTopOption", buildCustomerProfitBar(customerProfitMap));
+
+ return jsonResponse(true, "financial_order_profit_analysis", "宸插畬鎴愯鍗曞埄娑﹀垎鏋�", summary,
+ Map.of(
+ "riskOrders", riskyItems,
+ "allOrders", metrics.stream().map(this::toOrderCostItem).toList(),
+ "customerProfitTop", buildCustomerProfitTop(metrics, 10)
+ ),
+ charts
+ );
+ }
+
+ @Tool(name = "搴撳瓨璧勯噾鍒嗘瀽", value = "鍒嗘瀽搴撳瓨绉帇銆佸憜婊炲簱瀛樸�佽祫閲戝崰鐢ㄤ笌鍛ㄨ浆鐜囥��")
+ public String analyzeInventoryCapital(@ToolMemoryId String memoryId,
+ @P(value = "寮�濮嬫棩鏈� yyyy-MM-dd", required = false) String startDate,
+ @P(value = "缁撴潫鏃ユ湡 yyyy-MM-dd", required = false) String endDate,
+ @P(value = "鏃堕棿鑼冨洿鎻忚堪锛屽鏈湀銆佽繎30澶�", required = false) String timeRange,
+ @P(value = "鍏抽敭璇嶏紝鍙尮閰嶄骇鍝佸悕绉�/鍨嬪彿", required = false) String keyword,
+ @P(value = "杩斿洖鏉℃暟锛岄粯璁�10锛屾渶澶�50", required = false) Integer limit) {
+ LoginUser loginUser = currentLoginUser(memoryId);
+ DateRange range = resolveDateRange(startDate, endDate, timeRange, "杩�30澶�");
+ int finalLimit = normalizeLimit(limit);
+
+ List<StockInventory> inventoryRows = queryStockInventory(loginUser);
+ if (inventoryRows.isEmpty()) {
+ return jsonResponse(true, "financial_inventory_capital_analysis", "褰撳墠鏃犲簱瀛樻暟鎹�",
+ rangeSummary(range, 0, keyword), Map.of("items", List.of()), Map.of());
+ }
+
+ Set<Long> modelIds = inventoryRows.stream()
+ .map(StockInventory::getProductModelId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+ Map<Long, ProductModel> productModelMap = queryProductModels(modelIds);
+ Map<Long, Product> productMap = queryProducts(productModelMap.values());
+ Map<Long, BigDecimal> avgUnitCostByModelId = queryAverageUnitCostByModel(loginUser, modelIds);
+ OutboundStats outboundStats = queryOutboundStats(loginUser, modelIds, range);
+
+ List<InventoryMetric> metrics = buildInventoryMetrics(inventoryRows, productModelMap, productMap, avgUnitCostByModelId, outboundStats)
+ .stream()
+ .filter(metric -> matchInventoryKeyword(metric, keyword))
+ .sorted(Comparator.comparing(InventoryMetric::inventoryValue).reversed())
+ .toList();
+
+ BigDecimal totalInventoryValue = metrics.stream().map(InventoryMetric::inventoryValue).reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal stagnantValue = metrics.stream()
+ .filter(metric -> metric.stagnantDays() >= 90)
+ .map(InventoryMetric::inventoryValue)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ long stagnantCount = metrics.stream().filter(metric -> metric.stagnantDays() >= 90).count();
+ long overstockCount = metrics.stream().filter(InventoryMetric::overstock).count();
+ BigDecimal totalOutboundCost = outboundStats.totalOutboundCost();
+ BigDecimal turnoverDays = totalOutboundCost.compareTo(BigDecimal.ZERO) > 0
+ ? totalInventoryValue.multiply(BigDecimal.valueOf(daysBetween(range.start(), range.end()) + 1L))
+ .divide(totalOutboundCost, 2, RoundingMode.HALF_UP)
+ : BigDecimal.ZERO;
+
+ List<Map<String, Object>> items = metrics.stream()
+ .limit(finalLimit)
+ .map(this::toInventoryItem)
+ .toList();
+
+ Map<String, Object> summary = rangeSummary(range, metrics.size(), keyword);
+ summary.put("totalInventoryValue", totalInventoryValue);
+ summary.put("stagnantValue", stagnantValue);
+ summary.put("stagnantCount", stagnantCount);
+ summary.put("overstockCount", overstockCount);
+ summary.put("turnoverDays", turnoverDays);
+ summary.put("capitalOccupation", totalInventoryValue);
+ summary.put("totalOutboundCost", totalOutboundCost);
+
+ Map<String, Object> charts = new LinkedHashMap<>();
+ charts.put("inventoryValueTopOption", buildInventoryTopBar(metrics));
+ charts.put("inventoryAgingPieOption", buildInventoryAgingPie(metrics));
+ charts.put("inventoryTurnoverGauge", buildTurnoverGauge(turnoverDays));
+
+ return jsonResponse(true, "financial_inventory_capital_analysis", "宸插畬鎴愬簱瀛樿祫閲戝垎鏋�", summary, Map.of("items", items), charts);
+ }
+
+ @Tool(name = "搴旀敹搴斾粯涓庣幇閲戞祦棰勬祴", value = "棰勬祴鏈潵鐜伴噾娴併�佸洖娆鹃闄┿�佷粯娆惧帇鍔涗笌璧勯噾缂哄彛銆�")
+ public String forecastCashFlow(@ToolMemoryId String memoryId,
+ @P(value = "寮�濮嬫棩鏈� yyyy-MM-dd", required = false) String startDate,
+ @P(value = "缁撴潫鏃ユ湡 yyyy-MM-dd", required = false) String endDate,
+ @P(value = "鏃堕棿鑼冨洿鎻忚堪锛屽杩�90澶┿�佹湰骞�", required = false) String timeRange,
+ @P(value = "棰勬祴鏈堜唤鏁帮紝榛樿3锛屾渶澶�6", required = false) Integer forecastMonths) {
+ LoginUser loginUser = currentLoginUser(memoryId);
+ DateRange range = resolveDateRange(startDate, endDate, timeRange, "杩�90澶�");
+ int months = forecastMonths == null || forecastMonths <= 0 ? 3 : Math.min(forecastMonths, 6);
+
+ List<AccountSalesCollection> collections = queryCollections(loginUser, range);
+ List<AccountPurchasePayment> payments = queryPayments(loginUser, range);
+ List<MonthlyCashFlow> monthlyActual = buildMonthlyCashFlow(range, collections, payments);
+ List<MonthlyCashFlow> monthlyForecast = forecastMonthlyCashFlow(monthlyActual, months);
+
+ StatementSnapshot snapshot = buildStatementSnapshot(loginUser);
+ BigDecimal receivableTotal = snapshot.receivableTotal();
+ BigDecimal payableTotal = snapshot.payableTotal();
+ BigDecimal forecastNetSum = monthlyForecast.stream().map(MonthlyCashFlow::netFlow).reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal coverage = receivableTotal.add(maxZero(forecastNetSum));
+ BigDecimal fundGap = maxZero(payableTotal.subtract(coverage));
+
+ Map<String, String> customerNameMap = queryCustomerNameMap(snapshot.receivableTop().stream().map(StatementMetric::entityId).collect(Collectors.toSet()));
+ Map<String, String> supplierNameMap = querySupplierNameMap(snapshot.payableTop().stream().map(StatementMetric::entityId).collect(Collectors.toSet()));
+
+ List<Map<String, Object>> receivableRiskItems = snapshot.receivableTop().stream().map(item -> toStatementRiskItem(item, customerNameMap, "customer")).toList();
+ List<Map<String, Object>> payablePressureItems = snapshot.payableTop().stream().map(item -> toStatementRiskItem(item, supplierNameMap, "supplier")).toList();
+
+ Map<String, Object> summary = new LinkedHashMap<>();
+ summary.put("timeRange", range.label());
+ summary.put("startDate", range.start().toString());
+ summary.put("endDate", range.end().toString());
+ summary.put("actualIncomeTotal", collections.stream().map(AccountSalesCollection::getCollectionAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+ summary.put("actualExpenseTotal", payments.stream().map(AccountPurchasePayment::getPaymentAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+ summary.put("receivableBalance", receivableTotal);
+ summary.put("payableBalance", payableTotal);
+ summary.put("forecastNetSum", forecastNetSum);
+ summary.put("fundGap", fundGap);
+ summary.put("forecastMonths", months);
+ summary.put("collectionRiskLevel", riskLevelByAmount(receivableTotal));
+ summary.put("paymentPressureLevel", riskLevelByAmount(payableTotal));
+
+ Map<String, Object> charts = new LinkedHashMap<>();
+ charts.put("cashFlowTrendOption", buildCashflowTrend(monthlyActual, monthlyForecast));
+ charts.put("receivablePayableBarOption", buildReceivablePayableBar(receivableTotal, payableTotal));
+ charts.put("fundGapGaugeOption", buildFundGapGauge(fundGap));
+
+ return jsonResponse(true, "financial_cashflow_forecast", "宸插畬鎴愬簲鏀跺簲浠樹笌鐜伴噾娴侀娴�", summary,
+ Map.of(
+ "actualMonthly", monthlyActual.stream().map(this::toMonthlyCashFlowItem).toList(),
+ "forecastMonthly", monthlyForecast.stream().map(this::toMonthlyCashFlowItem).toList(),
+ "receivableRiskTop", receivableRiskItems,
+ "payablePressureTop", payablePressureItems
+ ),
+ charts
+ );
+ }
+
+ @Tool(name = "缁忚惀寮傚父棰勮", value = "璇嗗埆鎴愭湰寮傚父銆佸埄娑﹀紓甯搞�佸洖娆惧紓甯搞�佽鍗曢闄┿�佸簱瀛樺紓甯搞��")
+ public String detectBusinessAnomalies(@ToolMemoryId String memoryId,
+ @P(value = "寮�濮嬫棩鏈� yyyy-MM-dd", required = false) String startDate,
+ @P(value = "缁撴潫鏃ユ湡 yyyy-MM-dd", required = false) String endDate,
+ @P(value = "鏃堕棿鑼冨洿鎻忚堪锛屽杩�30澶�", required = false) String timeRange,
+ @P(value = "杩斿洖鏉℃暟锛岄粯璁�10锛屾渶澶�50", required = false) Integer limit) {
+ LoginUser loginUser = currentLoginUser(memoryId);
+ DateRange range = resolveDateRange(startDate, endDate, timeRange, "杩�30澶�");
+ int finalLimit = normalizeLimit(limit);
+
+ AnalysisBundle currentBundle = buildOrderProfitBundle(loginUser, range, null, Math.max(finalLimit, 30));
+ DateRange prevRange = previousSameLengthRange(range);
+ AnalysisBundle prevBundle = buildOrderProfitBundle(loginUser, prevRange, null, 50);
+
+ BigDecimal currentCostRate = rate(currentBundle.totalCost(), currentBundle.totalRevenue());
+ BigDecimal prevCostRate = rate(prevBundle.totalCost(), prevBundle.totalRevenue());
+ BigDecimal costRateDiff = currentCostRate.subtract(prevCostRate);
+
+ StatementSnapshot snapshot = buildStatementSnapshot(loginUser);
+ List<InventoryMetric> inventoryMetrics = buildInventoryMetrics(
+ queryStockInventory(loginUser),
+ queryProductModels(Collections.emptySet()),
+ Map.of(),
+ queryAverageUnitCostByModel(loginUser, Collections.emptySet()),
+ queryOutboundStats(loginUser, Collections.emptySet(), range)
+ );
+
+ List<Map<String, Object>> anomalyItems = new ArrayList<>();
+ if (costRateDiff.compareTo(new BigDecimal("0.10")) > 0) {
+ anomalyItems.add(anomalyItem("high", "鎴愭湰寮傚父", "鍗曚綅鏀跺叆鎴愭湰鐜囪緝涓婂懆鏈熶笂鍗囪秴杩�10%", Map.of(
+ "currentCostRate", toPercent(currentCostRate),
+ "previousCostRate", toPercent(prevCostRate),
+ "delta", toPercent(costRateDiff)
+ )));
+ }
+ long lossCount = currentBundle.orderMetrics().stream().filter(item -> item.profit().compareTo(BigDecimal.ZERO) < 0).count();
+ if (lossCount > 0) {
+ anomalyItems.add(anomalyItem("high", "鍒╂鼎寮傚父", "妫�娴嬪埌浜忔崯璁㈠崟", Map.of("lossOrderCount", lossCount)));
+ }
+ if (snapshot.receivableTotal().compareTo(snapshot.payableTotal().multiply(new BigDecimal("1.2"))) > 0) {
+ anomalyItems.add(anomalyItem("medium", "鍥炴寮傚父", "搴旀敹浣欓鏄捐憲楂樹簬搴斾粯锛屽洖娆惧帇鍔涘亸澶�", Map.of(
+ "receivableBalance", snapshot.receivableTotal(),
+ "payableBalance", snapshot.payableTotal()
+ )));
+ }
+ long overdueOrderCount = currentBundle.orderMetrics().stream()
+ .filter(item -> item.deliveryDate() != null && item.deliveryDate().isBefore(LocalDate.now()) && item.profitRate().compareTo(new BigDecimal("0.10")) < 0)
+ .count();
+ if (overdueOrderCount > 0) {
+ anomalyItems.add(anomalyItem("medium", "璁㈠崟椋庨櫓", "瀛樺湪浣庡埄娑︿笖浜や粯宸查�炬湡璁㈠崟", Map.of("overdueRiskOrderCount", overdueOrderCount)));
+ }
+ long stagnantCount = inventoryMetrics.stream().filter(item -> item.stagnantDays() >= 90).count();
+ if (stagnantCount > 0) {
+ anomalyItems.add(anomalyItem("medium", "搴撳瓨寮傚父", "瀛樺湪瓒呰繃90澶╂湭鍛ㄨ浆搴撳瓨", Map.of("stagnantCount", stagnantCount)));
+ }
+
+ List<Map<String, Object>> topAnomalies = anomalyItems.stream().limit(finalLimit).toList();
+ Map<String, Object> summary = new LinkedHashMap<>();
+ summary.put("timeRange", range.label());
+ summary.put("startDate", range.start().toString());
+ summary.put("endDate", range.end().toString());
+ summary.put("anomalyCount", topAnomalies.size());
+ summary.put("highRiskCount", topAnomalies.stream().filter(item -> "high".equals(item.get("riskLevel"))).count());
+ summary.put("mediumRiskCount", topAnomalies.stream().filter(item -> "medium".equals(item.get("riskLevel"))).count());
+
+ Map<String, Object> charts = new LinkedHashMap<>();
+ charts.put("anomalyLevelPieOption", buildAnomalyLevelPie(topAnomalies));
+ charts.put("anomalyTypeBarOption", buildAnomalyTypeBar(topAnomalies));
+ return jsonResponse(true, "financial_business_anomaly_warning", "宸插畬鎴愮粡钀ュ紓甯搁璀﹀垎鏋�", summary,
+ Map.of("items", topAnomalies), charts);
+ }
+
+ @Tool(name = "AI缁忚惀椹鹃┒鑸�", value = "瀹炴椂灞曠ず浜у�笺�佸埄娑︺�佸簱瀛樸�佸洖娆俱�佽澶囧埄鐢ㄧ巼銆佽鍗曞埄娑︾巼绛夋牳蹇冪粡钀ユ寚鏍囥��")
+ public String getBusinessCockpit(@ToolMemoryId String memoryId,
+ @P(value = "寮�濮嬫棩鏈� yyyy-MM-dd", required = false) String startDate,
+ @P(value = "缁撴潫鏃ユ湡 yyyy-MM-dd", required = false) String endDate,
+ @P(value = "鏃堕棿鑼冨洿鎻忚堪锛屽鏈湀銆佽繎30澶�", required = false) String timeRange) {
+ LoginUser loginUser = currentLoginUser(memoryId);
+ DateRange range = resolveDateRange(startDate, endDate, timeRange, "鏈湀");
+
+ AnalysisBundle profitBundle = buildOrderProfitBundle(loginUser, range, null, 30);
+ StatementSnapshot snapshot = buildStatementSnapshot(loginUser);
+ List<StockInventory> inventories = queryStockInventory(loginUser);
+ BigDecimal inventoryValue = estimateInventoryValue(loginUser, inventories);
+
+ long deviceTotal = countDevices(loginUser);
+ long repairingCount = countRepairingDevices(loginUser);
+ BigDecimal deviceUtilization = deviceTotal > 0
+ ? new BigDecimal(deviceTotal - repairingCount).multiply(ONE_HUNDRED).divide(new BigDecimal(deviceTotal), 2, RoundingMode.HALF_UP)
+ : BigDecimal.ZERO;
+
+ BigDecimal outputValue = profitBundle.totalRevenue();
+ BigDecimal profitRate = rate(profitBundle.totalProfit(), profitBundle.totalRevenue());
+ BigDecimal collectionRate = snapshot.receivableTotal().compareTo(BigDecimal.ZERO) > 0
+ ? ONE_HUNDRED.subtract(rate(snapshot.receivableTotal(), snapshot.receivableTotal().add(snapshot.payableTotal())).multiply(ONE_HUNDRED))
+ : BigDecimal.ZERO;
+
+ Map<String, Object> summary = new LinkedHashMap<>();
+ summary.put("timeRange", range.label());
+ summary.put("startDate", range.start().toString());
+ summary.put("endDate", range.end().toString());
+ summary.put("outputValue", outputValue);
+ summary.put("profit", profitBundle.totalProfit());
+ summary.put("profitRate", toPercent(profitRate));
+ summary.put("inventoryValue", inventoryValue);
+ summary.put("receivableBalance", snapshot.receivableTotal());
+ summary.put("payableBalance", snapshot.payableTotal());
+ summary.put("collectionRate", toPercent(collectionRate.divide(ONE_HUNDRED, 4, RoundingMode.HALF_UP)));
+ summary.put("deviceUtilizationRate", deviceUtilization + "%");
+ summary.put("orderProfitRate", toPercent(avgRate(profitBundle.orderMetrics())));
+
+ Map<String, Object> indicators = new LinkedHashMap<>();
+ indicators.put("浜у��", outputValue);
+ indicators.put("鍒╂鼎", profitBundle.totalProfit());
+ indicators.put("搴撳瓨璧勯噾鍗犵敤", inventoryValue);
+ indicators.put("搴旀敹浣欓", snapshot.receivableTotal());
+ indicators.put("璁惧鍒╃敤鐜�", deviceUtilization + "%");
+ indicators.put("璁㈠崟骞冲潎鍒╂鼎鐜�", toPercent(avgRate(profitBundle.orderMetrics())));
+
+ Map<String, Object> charts = new LinkedHashMap<>();
+ charts.put("kpiCardData", indicators);
+ charts.put("profitTrendOption", buildOrderProfitBar(profitBundle.orderMetrics()));
+ charts.put("receivablePayableBarOption", buildReceivablePayableBar(snapshot.receivableTotal(), snapshot.payableTotal()));
+ charts.put("inventoryProfitGaugeOption", buildInventoryProfitGauge(inventoryValue, profitBundle.totalProfit()));
+
+ return jsonResponse(true, "financial_business_cockpit", "宸茬敓鎴怉I缁忚惀椹鹃┒鑸辨暟鎹�", summary,
+ Map.of(
+ "orderProfitTop", profitBundle.orderMetrics().stream()
+ .sorted(Comparator.comparing(OrderProfitMetric::profit).reversed())
+ .limit(10)
+ .map(this::toOrderCostItem)
+ .toList(),
+ "indicators", indicators
+ ),
+ charts
+ );
+ }
+
+ @Tool(name = "鏃ユ姤鍛ㄦ姤鑷姩鐢熸垚", value = "鑷姩杈撳嚭缁忚惀鍒嗘瀽鏃ユ姤/鍛ㄦ姤涓庨闄╁缓璁��")
+ public String generateOperationReport(@ToolMemoryId String memoryId,
+ @P(value = "寮�濮嬫棩鏈� yyyy-MM-dd", required = false) String startDate,
+ @P(value = "缁撴潫鏃ユ湡 yyyy-MM-dd", required = false) String endDate,
+ @P(value = "鏃堕棿鑼冨洿鎻忚堪锛屽浠婂ぉ銆佹湰鍛�", required = false) String timeRange,
+ @P(value = "鎶ュ憡绫诲瀷 daily/weekly", required = false) String reportType) {
+ LoginUser loginUser = currentLoginUser(memoryId);
+ DateRange range = resolveDateRange(startDate, endDate, timeRange,
+ "weekly".equalsIgnoreCase(reportType) ? "鏈懆" : "浠婂ぉ");
+ String type = "weekly".equalsIgnoreCase(reportType) ? "weekly" : "daily";
+
+ AnalysisBundle bundle = buildOrderProfitBundle(loginUser, range, null, 30);
+ StatementSnapshot snapshot = buildStatementSnapshot(loginUser);
+ BigDecimal inventoryValue = estimateInventoryValue(loginUser, queryStockInventory(loginUser));
+ long lossCount = bundle.orderMetrics().stream().filter(item -> item.profit().compareTo(BigDecimal.ZERO) < 0).count();
+
+ List<String> conclusions = new ArrayList<>();
+ conclusions.add("钀ユ敹" + bundle.totalRevenue() + "锛屽埄娑�" + bundle.totalProfit() + "锛屽埄娑︾巼" + toPercent(rate(bundle.totalProfit(), bundle.totalRevenue())) + "銆�");
+ conclusions.add("搴旀敹浣欓" + snapshot.receivableTotal() + "锛屽簲浠樹綑棰�" + snapshot.payableTotal() + "锛屽簱瀛樿祫閲戝崰鐢�" + inventoryValue + "銆�");
+ if (lossCount > 0) {
+ conclusions.add("鍙戠幇浜忔崯璁㈠崟" + lossCount + "涓紝寤鸿浼樺厛澶嶆牳鏉愭枡鎹熻�楀拰宸ュ簭浜哄伐鏁堢巼銆�");
+ } else {
+ conclusions.add("褰撳墠鏈彂鐜颁簭鎹熻鍗曪紝寤鸿鎸佺画璺熻釜浣庝簬8%鍒╂鼎鐜囪鍗曘��");
+ }
+ if (snapshot.receivableTotal().compareTo(snapshot.payableTotal()) > 0) {
+ conclusions.add("鍥炴鍘嬪姏鍋忛珮锛屽缓璁拡瀵归珮搴旀敹瀹㈡埛鎵ц鍒嗗眰鍌敹涓庤处鏈熶紭鍖栥��");
+ } else {
+ conclusions.add("璧勯噾鍘嬪姏鍙帶锛屽缓璁繚鎸佷粯娆捐鍒掍笌閲囪喘鑺傚鑱斿姩銆�");
+ }
+
+ List<Map<String, Object>> riskSuggestions = new ArrayList<>();
+ if (lossCount > 0) {
+ riskSuggestions.add(riskSuggestion("鍒╂鼎椋庨櫓", "楂�", "澶嶆牳浜忔崯璁㈠崟BOM鍜屽伐搴忓伐璧勫畾棰濓紝蹇呰鏃惰皟鏁存姤浠蜂笌浜や粯鑺傚銆�"));
+ }
+ if (snapshot.receivableTotal().compareTo(new BigDecimal("1000000")) > 0) {
+ riskSuggestions.add(riskSuggestion("鍥炴椋庨櫓", "涓�", "瀵瑰簲鏀禩OP瀹㈡埛寤虹珛鍛ㄥ害鍥炴璁″垝锛屽苟璁剧疆棰勮闃堝�笺��"));
+ }
+ if (inventoryValue.compareTo(new BigDecimal("3000000")) > 0) {
+ riskSuggestions.add(riskSuggestion("搴撳瓨椋庨櫓", "涓�", "瀵归珮閲戦鍛嗘粸搴撳瓨鎵ц闄嶄环銆佹浛浠e拰鐢熶骇娑堣�楃瓥鐣ャ��"));
+ }
+
+ Map<String, Object> summary = new LinkedHashMap<>();
+ summary.put("reportType", type);
+ summary.put("timeRange", range.label());
+ summary.put("startDate", range.start().toString());
+ summary.put("endDate", range.end().toString());
+ summary.put("orderCount", bundle.orderMetrics().size());
+ summary.put("lossOrderCount", lossCount);
+ summary.put("riskSuggestionCount", riskSuggestions.size());
+
+ Map<String, Object> data = new LinkedHashMap<>();
+ data.put("headline", "weekly".equals(type) ? "缁忚惀鍛ㄦ姤" : "缁忚惀鏃ユ姤");
+ data.put("conclusions", conclusions);
+ data.put("riskSuggestions", riskSuggestions);
+ data.put("orderProfitTop", bundle.orderMetrics().stream()
+ .sorted(Comparator.comparing(OrderProfitMetric::profitRate))
+ .limit(10)
+ .map(this::toRiskOrderItem)
+ .toList());
+
+ Map<String, Object> charts = new LinkedHashMap<>();
+ charts.put("reportProfitBarOption", buildOrderProfitBar(bundle.orderMetrics()));
+ charts.put("reportReceivablePayableOption", buildReceivablePayableBar(snapshot.receivableTotal(), snapshot.payableTotal()));
+ return jsonResponse(true, "financial_operation_report", "宸茶嚜鍔ㄧ敓鎴愮粡钀ュ垎鏋愭姤鍛�", summary, data, charts);
+ }
+
+ private AnalysisBundle buildOrderProfitBundle(LoginUser loginUser, DateRange range, String keyword, Integer limit) {
+ List<SalesLedger> ledgers = querySalesLedgers(loginUser, range, keyword, limit);
+ if (ledgers.isEmpty()) {
+ return AnalysisBundle.empty();
+ }
+
+ List<Long> ledgerIds = ledgers.stream().map(SalesLedger::getId).filter(Objects::nonNull).toList();
+ List<SalesLedgerProduct> ledgerProducts = queryLedgerProducts(loginUser, ledgerIds);
+ Map<Long, List<SalesLedgerProduct>> productsByLedgerId = ledgerProducts.stream()
+ .collect(Collectors.groupingBy(SalesLedgerProduct::getSalesLedgerId));
+
+ MaterialCostResult materialCostResult = calculateMaterialCost(loginUser, range, ledgerProducts);
+ ProductionCostContext productionCostContext = calculateProductionCost(loginUser, range, ledgers, ledgerProducts, materialCostResult.avgUnitCostByModelId());
+ BigDecimal totalDepreciation = calculateTotalDepreciation(loginUser);
+
+ BigDecimal totalRevenue = ledgers.stream()
+ .map(SalesLedger::getContractAmount)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ Map<Long, BigDecimal> depreciationCostByLedger = allocateDepreciation(ledgers, totalDepreciation, totalRevenue);
+
+ List<OrderProfitMetric> metrics = new ArrayList<>();
+ for (SalesLedger ledger : ledgers) {
+ BigDecimal revenue = defaultDecimal(ledger.getContractAmount());
+ BigDecimal materialCost = materialCostResult.materialCostByLedgerId().getOrDefault(ledger.getId(), fallbackMaterialCost(productsByLedgerId.get(ledger.getId()), revenue));
+ BigDecimal laborCost = productionCostContext.laborCostByLedgerId().getOrDefault(ledger.getId(), BigDecimal.ZERO);
+ BigDecimal scrapCost = productionCostContext.scrapCostByLedgerId().getOrDefault(ledger.getId(), BigDecimal.ZERO);
+ BigDecimal depreciationCost = depreciationCostByLedger.getOrDefault(ledger.getId(), BigDecimal.ZERO);
+ BigDecimal totalCost = materialCost.add(laborCost).add(scrapCost).add(depreciationCost);
+ BigDecimal profit = revenue.subtract(totalCost);
+ BigDecimal profitRate = rate(profit, revenue);
+ String riskLevel = profit.compareTo(BigDecimal.ZERO) < 0
+ ? "high"
+ : (profitRate.compareTo(new BigDecimal("0.08")) < 0 ? "medium" : "low");
+ List<String> reasons = buildProfitReasons(revenue, materialCost, laborCost, scrapCost, profit, profitRate);
+ String suggestion = buildProfitSuggestion(riskLevel, reasons);
+
+ metrics.add(new OrderProfitMetric(
+ ledger.getId(),
+ safe(ledger.getSalesContractNo()),
+ safe(ledger.getCustomerName()),
+ safe(ledger.getProjectName()),
+ toLocalDate(ledger.getEntryDate()),
+ ledger.getDeliveryDate(),
+ revenue,
+ materialCost,
+ laborCost,
+ depreciationCost,
+ scrapCost,
+ totalCost,
+ profit,
+ profitRate,
+ riskLevel,
+ reasons,
+ suggestion
+ ));
+ }
+
+ metrics.sort(Comparator.comparing(OrderProfitMetric::entryDate, Comparator.nullsLast(Comparator.reverseOrder()))
+ .thenComparing(OrderProfitMetric::ledgerId, Comparator.nullsLast(Comparator.reverseOrder())));
+ BigDecimal totalMaterialCost = metrics.stream().map(OrderProfitMetric::materialCost).reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal totalLaborCost = metrics.stream().map(OrderProfitMetric::laborCost).reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal totalScrapCost = metrics.stream().map(OrderProfitMetric::scrapCost).reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal totalDepreciationCost = metrics.stream().map(OrderProfitMetric::depreciationCost).reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal totalCost = metrics.stream().map(OrderProfitMetric::totalCost).reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal totalProfit = metrics.stream().map(OrderProfitMetric::profit).reduce(BigDecimal.ZERO, BigDecimal::add);
+
+ return new AnalysisBundle(
+ metrics,
+ productionCostContext.processCostRanking(),
+ totalRevenue,
+ totalMaterialCost,
+ totalLaborCost,
+ totalDepreciationCost,
+ totalScrapCost,
+ totalCost,
+ totalProfit
+ );
+ }
+
+ private MaterialCostResult calculateMaterialCost(LoginUser loginUser, DateRange range, List<SalesLedgerProduct> ledgerProducts) {
+ if (ledgerProducts.isEmpty()) {
+ return new MaterialCostResult(Map.of(), Map.of());
+ }
+ List<Long> ledgerProductIds = ledgerProducts.stream().map(SalesLedgerProduct::getId).filter(Objects::nonNull).toList();
+ Set<Long> productModelIds = ledgerProducts.stream().map(SalesLedgerProduct::getProductModelId).filter(Objects::nonNull).collect(Collectors.toSet());
+ Map<Long, Long> productIdToLedgerId = ledgerProducts.stream()
+ .filter(item -> item.getId() != null && item.getSalesLedgerId() != null)
+ .collect(Collectors.toMap(SalesLedgerProduct::getId, SalesLedgerProduct::getSalesLedgerId, (a, b) -> a));
+
+ Map<Long, BigDecimal> avgUnitCostByModelId = queryAverageUnitCostByModel(loginUser, productModelIds);
+ LambdaQueryWrapper<ProcurementRecordOut> outWrapper = new LambdaQueryWrapper<>();
+ applyTenantFilter(outWrapper, loginUser.getTenantId(), ProcurementRecordOut::getTenantId);
+ applyDeptFilter(outWrapper, loginUser.getCurrentDeptId(), ProcurementRecordOut::getDeptId);
+ outWrapper.eq(ProcurementRecordOut::getType, 2)
+ .in(ProcurementRecordOut::getSalesLedgerProductId, ledgerProductIds)
+ .ge(ProcurementRecordOut::getCreateTime, range.start().atStartOfDay())
+ .lt(ProcurementRecordOut::getCreateTime, range.end().plusDays(1).atStartOfDay());
+ List<ProcurementRecordOut> outList = defaultList(procurementRecordOutMapper.selectList(outWrapper));
+
+ Set<Integer> storageIds = outList.stream()
+ .map(ProcurementRecordOut::getProcurementRecordStorageId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+ Map<Integer, ProcurementRecordStorage> storageMap = storageIds.isEmpty()
+ ? Map.of()
+ : defaultList(procurementRecordMapper.selectBatchIds(storageIds)).stream()
+ .collect(Collectors.toMap(ProcurementRecordStorage::getId, item -> item, (a, b) -> a));
+
+ Map<Long, BigDecimal> materialCostByLedgerId = new HashMap<>();
+ for (ProcurementRecordOut out : outList) {
+ Long ledgerId = productIdToLedgerId.get(out.getSalesLedgerProductId());
+ if (ledgerId == null) {
+ continue;
+ }
+ ProcurementRecordStorage storage = storageMap.get(out.getProcurementRecordStorageId());
+ BigDecimal unitPrice = storage == null ? BigDecimal.ZERO : defaultDecimal(storage.getUnitPrice());
+ BigDecimal quantity = defaultDecimal(out.getInboundNum());
+ BigDecimal cost = quantity.multiply(unitPrice);
+ materialCostByLedgerId.merge(ledgerId, cost, BigDecimal::add);
+ }
+ return new MaterialCostResult(materialCostByLedgerId, avgUnitCostByModelId);
+ }
+
+ private ProductionCostContext calculateProductionCost(LoginUser loginUser,
+ DateRange range,
+ List<SalesLedger> ledgers,
+ List<SalesLedgerProduct> ledgerProducts,
+ Map<Long, BigDecimal> avgUnitCostByModelId) {
+ if (ledgers.isEmpty()) {
+ return ProductionCostContext.empty();
+ }
+
+ Set<Long> ledgerIds = ledgers.stream().map(SalesLedger::getId).filter(Objects::nonNull).collect(Collectors.toSet());
+ Map<Long, Set<Long>> productModelToLedgerIds = new HashMap<>();
+ for (SalesLedgerProduct product : ledgerProducts) {
+ if (product.getProductModelId() == null || product.getSalesLedgerId() == null) {
+ continue;
+ }
+ productModelToLedgerIds.computeIfAbsent(product.getProductModelId(), key -> new HashSet<>()).add(product.getSalesLedgerId());
+ }
+
+ LambdaQueryWrapper<ProductionPlan> planWrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(planWrapper, loginUser.getCurrentDeptId(), ProductionPlan::getDeptId);
+ planWrapper.in(ProductionPlan::getSalesLedgerId, ledgerIds);
+ List<ProductionPlan> plans = defaultList(productionPlanMapper.selectList(planWrapper));
+ Map<Long, Long> planIdToLedgerId = plans.stream()
+ .filter(item -> item.getId() != null && item.getSalesLedgerId() != null)
+ .collect(Collectors.toMap(ProductionPlan::getId, ProductionPlan::getSalesLedgerId, (a, b) -> a));
+
+ LambdaQueryWrapper<ProductionOrder> orderWrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(orderWrapper, loginUser.getCurrentDeptId(), ProductionOrder::getDeptId);
+ orderWrapper.ge(ProductionOrder::getCreateTime, range.start().atStartOfDay().minusMonths(2))
+ .lt(ProductionOrder::getCreateTime, range.end().plusDays(1).atStartOfDay().plusMonths(1));
+ List<ProductionOrder> orders = defaultList(productionOrderMapper.selectList(orderWrapper));
+
+ Map<Long, Set<Long>> orderIdToLedgerIds = new HashMap<>();
+ for (ProductionOrder order : orders) {
+ Set<Long> orderLedgers = new HashSet<>();
+ for (Long planId : parseIdList(order.getProductionPlanIds())) {
+ Long ledgerId = planIdToLedgerId.get(planId);
+ if (ledgerId != null) {
+ orderLedgers.add(ledgerId);
+ }
+ }
+ if (orderLedgers.isEmpty() && order.getProductModelId() != null) {
+ orderLedgers.addAll(productModelToLedgerIds.getOrDefault(order.getProductModelId(), Set.of()));
+ }
+ if (!orderLedgers.isEmpty()) {
+ orderIdToLedgerIds.put(order.getId(), orderLedgers);
+ }
+ }
+ if (orderIdToLedgerIds.isEmpty()) {
+ return ProductionCostContext.empty();
+ }
+
+ LambdaQueryWrapper<ProductionOperationTask> taskWrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(taskWrapper, loginUser.getCurrentDeptId(), ProductionOperationTask::getDeptId);
+ taskWrapper.in(ProductionOperationTask::getProductionOrderId, orderIdToLedgerIds.keySet());
+ List<ProductionOperationTask> tasks = defaultList(productionOperationTaskMapper.selectList(taskWrapper));
+ Map<Long, Long> taskIdToOrderId = tasks.stream()
+ .filter(item -> item.getId() != null && item.getProductionOrderId() != null)
+ .collect(Collectors.toMap(ProductionOperationTask::getId, ProductionOperationTask::getProductionOrderId, (a, b) -> a));
+ if (taskIdToOrderId.isEmpty()) {
+ return ProductionCostContext.empty();
+ }
+
+ LambdaQueryWrapper<ProductionProductMain> mainWrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(mainWrapper, loginUser.getCurrentDeptId(), ProductionProductMain::getDeptId);
+ mainWrapper.in(ProductionProductMain::getProductionOperationTaskId, taskIdToOrderId.keySet())
+ .ge(ProductionProductMain::getCreateTime, range.start().atStartOfDay().minusMonths(2))
+ .lt(ProductionProductMain::getCreateTime, range.end().plusDays(1).atStartOfDay().plusMonths(1));
+ List<ProductionProductMain> mainList = defaultList(productionProductMainMapper.selectList(mainWrapper));
+ Map<Long, Set<Long>> mainIdToLedgers = new HashMap<>();
+ for (ProductionProductMain main : mainList) {
+ Long orderId = taskIdToOrderId.get(main.getProductionOperationTaskId());
+ if (orderId == null) {
+ continue;
+ }
+ Set<Long> ledgerSet = orderIdToLedgerIds.get(orderId);
+ if (ledgerSet == null || ledgerSet.isEmpty()) {
+ continue;
+ }
+ mainIdToLedgers.put(main.getId(), ledgerSet);
+ }
+ if (mainIdToLedgers.isEmpty()) {
+ return ProductionCostContext.empty();
+ }
+
+ LambdaQueryWrapper<ProductionAccount> accountWrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(accountWrapper, loginUser.getCurrentDeptId(), ProductionAccount::getDeptId);
+ accountWrapper.in(ProductionAccount::getProductionProductMainId, mainIdToLedgers.keySet())
+ .ge(ProductionAccount::getSchedulingDate, range.start().atStartOfDay())
+ .lt(ProductionAccount::getSchedulingDate, range.end().plusDays(1).atStartOfDay());
+ List<ProductionAccount> accountList = defaultList(productionAccountMapper.selectList(accountWrapper));
+
+ Map<String, BigDecimal> salaryQuotaByOperation = defaultList(technologyOperationMapper.selectList(new LambdaQueryWrapper<TechnologyOperation>()
+ .select(TechnologyOperation::getName, TechnologyOperation::getSalaryQuota)))
+ .stream()
+ .filter(item -> StringUtils.hasText(item.getName()))
+ .collect(Collectors.toMap(TechnologyOperation::getName, item -> defaultDecimal(item.getSalaryQuota()), (a, b) -> a));
+
+ Map<Long, BigDecimal> laborCostByLedger = new HashMap<>();
+ Map<String, BigDecimal> processCostMap = new HashMap<>();
+ for (ProductionAccount account : accountList) {
+ Set<Long> ledgerSet = mainIdToLedgers.get(account.getProductionProductMainId());
+ if (ledgerSet == null || ledgerSet.isEmpty()) {
+ continue;
+ }
+ BigDecimal cost = estimateLaborCost(account, salaryQuotaByOperation);
+ if (cost.compareTo(BigDecimal.ZERO) <= 0) {
+ continue;
+ }
+ BigDecimal split = cost.divide(new BigDecimal(ledgerSet.size()), 4, RoundingMode.HALF_UP);
+ for (Long ledgerId : ledgerSet) {
+ laborCostByLedger.merge(ledgerId, split, BigDecimal::add);
+ }
+ processCostMap.merge(safe(account.getTechnologyOperationName()), cost, BigDecimal::add);
+ }
+
+ LambdaQueryWrapper<ProductionProductOutput> outputWrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(outputWrapper, loginUser.getCurrentDeptId(), ProductionProductOutput::getDeptId);
+ outputWrapper.in(ProductionProductOutput::getProductionProductMainId, mainIdToLedgers.keySet())
+ .ge(ProductionProductOutput::getCreateTime, range.start().atStartOfDay())
+ .lt(ProductionProductOutput::getCreateTime, range.end().plusDays(1).atStartOfDay());
+ List<ProductionProductOutput> outputList = defaultList(productionProductOutputMapper.selectList(outputWrapper));
+ Map<Long, BigDecimal> scrapCostByLedger = new HashMap<>();
+ for (ProductionProductOutput output : outputList) {
+ Set<Long> ledgerSet = mainIdToLedgers.get(output.getProductionProductMainId());
+ if (ledgerSet == null || ledgerSet.isEmpty()) {
+ continue;
+ }
+ BigDecimal scrapQty = defaultDecimal(output.getScrapQty());
+ if (scrapQty.compareTo(BigDecimal.ZERO) <= 0) {
+ continue;
+ }
+ BigDecimal unitCost = avgUnitCostByModelId.getOrDefault(output.getProductModelId(), BigDecimal.ZERO);
+ BigDecimal scrapCost = scrapQty.multiply(unitCost);
+ BigDecimal split = scrapCost.divide(new BigDecimal(ledgerSet.size()), 4, RoundingMode.HALF_UP);
+ for (Long ledgerId : ledgerSet) {
+ scrapCostByLedger.merge(ledgerId, split, BigDecimal::add);
+ }
+ }
+
+ Map<String, BigDecimal> processCostRanking = processCostMap.entrySet().stream()
+ .sorted(Map.Entry.<String, BigDecimal>comparingByValue().reversed())
+ .limit(10)
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new));
+
+ return new ProductionCostContext(laborCostByLedger, scrapCostByLedger, processCostRanking);
+ }
+
+ private List<SalesLedger> querySalesLedgers(LoginUser loginUser, DateRange range, String keyword, Integer limit) {
+ LambdaQueryWrapper<SalesLedger> wrapper = new LambdaQueryWrapper<>();
+ applyTenantFilter(wrapper, loginUser.getTenantId(), SalesLedger::getTenantId);
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), SalesLedger::getDeptId);
+ if (StringUtils.hasText(keyword)) {
+ wrapper.and(w -> w.like(SalesLedger::getSalesContractNo, keyword)
+ .or().like(SalesLedger::getCustomerContractNo, keyword)
+ .or().like(SalesLedger::getCustomerName, keyword)
+ .or().like(SalesLedger::getProjectName, keyword)
+ .or().like(SalesLedger::getSalesman, keyword));
+ }
+ wrapper.ge(SalesLedger::getEntryDate, toDate(range.start()))
+ .lt(SalesLedger::getEntryDate, toExclusiveEndDate(range.end()))
+ .orderByDesc(SalesLedger::getEntryDate, SalesLedger::getId)
+ .last("limit " + normalizeLimit(limit));
+ return defaultList(salesLedgerMapper.selectList(wrapper));
+ }
+
+ private List<SalesLedgerProduct> queryLedgerProducts(LoginUser loginUser, List<Long> ledgerIds) {
+ if (ledgerIds == null || ledgerIds.isEmpty()) {
+ return List.of();
+ }
+ LambdaQueryWrapper<SalesLedgerProduct> wrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), SalesLedgerProduct::getDeptId);
+ wrapper.in(SalesLedgerProduct::getSalesLedgerId, ledgerIds)
+ .eq(SalesLedgerProduct::getType, 1);
+ return defaultList(salesLedgerProductMapper.selectList(wrapper));
+ }
+
+ private List<StockInventory> queryStockInventory(LoginUser loginUser) {
+ LambdaQueryWrapper<StockInventory> wrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), StockInventory::getDeptId);
+ return defaultList(stockInventoryMapper.selectList(wrapper));
+ }
+
+ private Map<Long, ProductModel> queryProductModels(Set<Long> modelIds) {
+ if (modelIds == null || modelIds.isEmpty()) {
+ return defaultList(productModelMapper.selectList(null)).stream()
+ .filter(item -> item.getId() != null)
+ .collect(Collectors.toMap(ProductModel::getId, item -> item, (a, b) -> a));
+ }
+ LambdaQueryWrapper<ProductModel> wrapper = new LambdaQueryWrapper<>();
+ wrapper.in(ProductModel::getId, modelIds);
+ return defaultList(productModelMapper.selectList(wrapper)).stream()
+ .filter(item -> item.getId() != null)
+ .collect(Collectors.toMap(ProductModel::getId, item -> item, (a, b) -> a));
+ }
+
+ private Map<Long, Product> queryProducts(Collection<ProductModel> models) {
+ Set<Long> productIds = models == null ? Set.of() : models.stream()
+ .map(ProductModel::getProductId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+ if (productIds.isEmpty()) {
+ return Map.of();
+ }
+ LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();
+ wrapper.in(Product::getId, productIds);
+ return defaultList(productMapper.selectList(wrapper)).stream()
+ .filter(item -> item.getId() != null)
+ .collect(Collectors.toMap(Product::getId, item -> item, (a, b) -> a));
+ }
+
+ private Map<Long, BigDecimal> queryAverageUnitCostByModel(LoginUser loginUser, Set<Long> productModelIds) {
+ LambdaQueryWrapper<ProcurementRecordStorage> wrapper = new LambdaQueryWrapper<>();
+ applyTenantFilter(wrapper, loginUser.getTenantId(), ProcurementRecordStorage::getTenantId);
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ProcurementRecordStorage::getDeptId);
+ wrapper.in(ProcurementRecordStorage::getType, List.of(1, 2));
+ if (productModelIds != null && !productModelIds.isEmpty()) {
+ wrapper.in(ProcurementRecordStorage::getProductModelId, productModelIds);
+ }
+ List<ProcurementRecordStorage> rows = defaultList(procurementRecordMapper.selectList(wrapper));
+ Map<Long, BigDecimal> amountByModel = new HashMap<>();
+ Map<Long, BigDecimal> qtyByModel = new HashMap<>();
+ for (ProcurementRecordStorage row : rows) {
+ if (row.getProductModelId() == null) {
+ continue;
+ }
+ BigDecimal qty = defaultDecimal(row.getInboundNum());
+ if (qty.compareTo(BigDecimal.ZERO) <= 0) {
+ continue;
+ }
+ BigDecimal amount = defaultDecimal(row.getUnitPrice()).multiply(qty);
+ amountByModel.merge(row.getProductModelId(), amount, BigDecimal::add);
+ qtyByModel.merge(row.getProductModelId(), qty, BigDecimal::add);
+ }
+ Map<Long, BigDecimal> result = new HashMap<>();
+ for (Map.Entry<Long, BigDecimal> entry : amountByModel.entrySet()) {
+ BigDecimal qty = qtyByModel.get(entry.getKey());
+ if (qty == null || qty.compareTo(BigDecimal.ZERO) <= 0) {
+ continue;
+ }
+ result.put(entry.getKey(), entry.getValue().divide(qty, 6, RoundingMode.HALF_UP));
+ }
+ return result;
+ }
+
+ private OutboundStats queryOutboundStats(LoginUser loginUser, Set<Long> productModelIds, DateRange range) {
+ LambdaQueryWrapper<ProcurementRecordOut> wrapper = new LambdaQueryWrapper<>();
+ applyTenantFilter(wrapper, loginUser.getTenantId(), ProcurementRecordOut::getTenantId);
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ProcurementRecordOut::getDeptId);
+ if (productModelIds != null && !productModelIds.isEmpty()) {
+ wrapper.in(ProcurementRecordOut::getProductModelId, productModelIds);
+ }
+ wrapper.ge(ProcurementRecordOut::getCreateTime, range.start().atStartOfDay())
+ .lt(ProcurementRecordOut::getCreateTime, range.end().plusDays(1).atStartOfDay());
+ List<ProcurementRecordOut> outList = defaultList(procurementRecordOutMapper.selectList(wrapper));
+ if (outList.isEmpty()) {
+ return OutboundStats.empty();
+ }
+ Set<Integer> storageIds = outList.stream()
+ .map(ProcurementRecordOut::getProcurementRecordStorageId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+ Map<Integer, ProcurementRecordStorage> storageMap = storageIds.isEmpty()
+ ? Map.of()
+ : defaultList(procurementRecordMapper.selectBatchIds(storageIds)).stream()
+ .collect(Collectors.toMap(ProcurementRecordStorage::getId, item -> item, (a, b) -> a));
+
+ Map<Long, BigDecimal> outboundQtyByModel = new HashMap<>();
+ Map<Long, LocalDateTime> lastOutboundTimeByModel = new HashMap<>();
+ BigDecimal totalOutboundCost = BigDecimal.ZERO;
+ for (ProcurementRecordOut out : outList) {
+ Long modelId = out.getProductModelId();
+ if (modelId == null) {
+ continue;
+ }
+ BigDecimal qty = defaultDecimal(out.getInboundNum());
+ outboundQtyByModel.merge(modelId, qty, BigDecimal::add);
+ if (out.getCreateTime() != null) {
+ LocalDateTime existing = lastOutboundTimeByModel.get(modelId);
+ if (existing == null || out.getCreateTime().isAfter(existing)) {
+ lastOutboundTimeByModel.put(modelId, out.getCreateTime());
+ }
+ }
+ ProcurementRecordStorage storage = storageMap.get(out.getProcurementRecordStorageId());
+ BigDecimal unitPrice = storage == null ? BigDecimal.ZERO : defaultDecimal(storage.getUnitPrice());
+ totalOutboundCost = totalOutboundCost.add(unitPrice.multiply(qty));
+ }
+ return new OutboundStats(outboundQtyByModel, lastOutboundTimeByModel, totalOutboundCost);
+ }
+
+ private List<InventoryMetric> buildInventoryMetrics(List<StockInventory> inventoryRows,
+ Map<Long, ProductModel> productModelMap,
+ Map<Long, Product> productMap,
+ Map<Long, BigDecimal> avgUnitCostByModelId,
+ OutboundStats outboundStats) {
+ Map<Long, InventoryMetricBuilder> metricBuilderByModel = new HashMap<>();
+ for (StockInventory row : inventoryRows) {
+ if (row.getProductModelId() == null) {
+ continue;
+ }
+ InventoryMetricBuilder builder = metricBuilderByModel.computeIfAbsent(row.getProductModelId(), InventoryMetricBuilder::new);
+ builder.addQuantity(maxZero(defaultDecimal(row.getQualitity()).subtract(defaultDecimal(row.getLockedQuantity()))));
+ builder.addLockedQuantity(defaultDecimal(row.getLockedQuantity()));
+ builder.addWarnNum(defaultDecimal(row.getWarnNum()));
+ if (row.getCreateTime() != null) {
+ builder.updateFirstInTime(row.getCreateTime());
+ }
+ }
+
+ List<InventoryMetric> result = new ArrayList<>();
+ LocalDate today = LocalDate.now();
+ for (InventoryMetricBuilder builder : metricBuilderByModel.values()) {
+ Long modelId = builder.modelId();
+ ProductModel model = productModelMap.get(modelId);
+ Product product = model == null ? null : productMap.get(model.getProductId());
+ BigDecimal unitCost = avgUnitCostByModelId.getOrDefault(modelId, BigDecimal.ZERO);
+ BigDecimal value = builder.quantity().multiply(unitCost);
+ LocalDateTime lastOutTime = outboundStats.lastOutboundTimeByModel().get(modelId);
+ long stagnantDays;
+ if (lastOutTime != null) {
+ stagnantDays = daysBetween(lastOutTime.toLocalDate(), today);
+ } else if (builder.firstInTime() != null) {
+ stagnantDays = daysBetween(builder.firstInTime().toLocalDate(), today);
+ } else {
+ stagnantDays = 0;
+ }
+ BigDecimal outQty = outboundStats.outboundQtyByModel().getOrDefault(modelId, BigDecimal.ZERO);
+ boolean overstock = builder.warnNum().compareTo(BigDecimal.ZERO) > 0
+ && builder.quantity().compareTo(builder.warnNum().multiply(new BigDecimal("3"))) > 0;
+ result.add(new InventoryMetric(
+ modelId,
+ product == null ? "鏈煡浜у搧" : safe(product.getProductName()),
+ model == null ? "鏈煡鍨嬪彿" : safe(model.getModel()),
+ builder.quantity(),
+ builder.lockedQuantity(),
+ unitCost,
+ value,
+ outQty,
+ stagnantDays,
+ overstock
+ ));
+ }
+ return result;
+ }
+
+ private List<AccountSalesCollection> queryCollections(LoginUser loginUser, DateRange range) {
+ LambdaQueryWrapper<AccountSalesCollection> wrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), AccountSalesCollection::getDeptId);
+ wrapper.ge(AccountSalesCollection::getCollectionDate, range.start())
+ .le(AccountSalesCollection::getCollectionDate, range.end())
+ .orderByAsc(AccountSalesCollection::getCollectionDate);
+ return defaultList(accountSalesCollectionMapper.selectList(wrapper));
+ }
+
+ private List<AccountPurchasePayment> queryPayments(LoginUser loginUser, DateRange range) {
+ LambdaQueryWrapper<AccountPurchasePayment> wrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), AccountPurchasePayment::getDeptId);
+ wrapper.ge(AccountPurchasePayment::getPaymentDate, range.start())
+ .le(AccountPurchasePayment::getPaymentDate, range.end())
+ .orderByAsc(AccountPurchasePayment::getPaymentDate);
+ return defaultList(accountPurchasePaymentMapper.selectList(wrapper));
+ }
+
+ private List<MonthlyCashFlow> buildMonthlyCashFlow(DateRange range,
+ List<AccountSalesCollection> collections,
+ List<AccountPurchasePayment> payments) {
+ Map<YearMonth, BigDecimal> incomeByMonth = new LinkedHashMap<>();
+ Map<YearMonth, BigDecimal> expenseByMonth = new LinkedHashMap<>();
+ YearMonth startMonth = YearMonth.from(range.start());
+ YearMonth endMonth = YearMonth.from(range.end());
+ for (YearMonth month = startMonth; !month.isAfter(endMonth); month = month.plusMonths(1)) {
+ incomeByMonth.put(month, BigDecimal.ZERO);
+ expenseByMonth.put(month, BigDecimal.ZERO);
+ }
+
+ for (AccountSalesCollection row : collections) {
+ if (row.getCollectionDate() == null) {
+ continue;
+ }
+ YearMonth month = YearMonth.from(row.getCollectionDate());
+ if (incomeByMonth.containsKey(month)) {
+ incomeByMonth.put(month, incomeByMonth.get(month).add(defaultDecimal(row.getCollectionAmount())));
+ }
+ }
+ for (AccountPurchasePayment row : payments) {
+ if (row.getPaymentDate() == null) {
+ continue;
+ }
+ YearMonth month = YearMonth.from(row.getPaymentDate());
+ if (expenseByMonth.containsKey(month)) {
+ expenseByMonth.put(month, expenseByMonth.get(month).add(defaultDecimal(row.getPaymentAmount())));
+ }
+ }
+
+ List<MonthlyCashFlow> result = new ArrayList<>();
+ for (YearMonth month : incomeByMonth.keySet()) {
+ BigDecimal income = incomeByMonth.get(month);
+ BigDecimal expense = expenseByMonth.getOrDefault(month, BigDecimal.ZERO);
+ result.add(new MonthlyCashFlow(month.toString(), income, expense, income.subtract(expense)));
+ }
+ return result;
+ }
+
+ private List<MonthlyCashFlow> forecastMonthlyCashFlow(List<MonthlyCashFlow> actual, int forecastMonths) {
+ if (actual.isEmpty()) {
+ List<MonthlyCashFlow> defaults = new ArrayList<>();
+ YearMonth now = YearMonth.now();
+ for (int i = 1; i <= forecastMonths; i++) {
+ YearMonth month = now.plusMonths(i);
+ defaults.add(new MonthlyCashFlow(month.toString(), BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO));
+ }
+ return defaults;
+ }
+ List<BigDecimal> series = actual.stream().map(MonthlyCashFlow::netFlow).toList();
+ BigDecimal avg = series.stream().reduce(BigDecimal.ZERO, BigDecimal::add)
+ .divide(new BigDecimal(series.size()), 4, RoundingMode.HALF_UP);
+ BigDecimal slope = BigDecimal.ZERO;
+ if (series.size() > 1) {
+ slope = series.get(series.size() - 1).subtract(series.get(0))
+ .divide(new BigDecimal(series.size() - 1), 4, RoundingMode.HALF_UP);
+ }
+ YearMonth lastMonth = YearMonth.parse(actual.get(actual.size() - 1).month());
+ List<MonthlyCashFlow> forecast = new ArrayList<>();
+ for (int i = 1; i <= forecastMonths; i++) {
+ YearMonth month = lastMonth.plusMonths(i);
+ BigDecimal net = avg.add(slope.multiply(new BigDecimal(i))).setScale(2, RoundingMode.HALF_UP);
+ BigDecimal income = net.compareTo(BigDecimal.ZERO) >= 0 ? net : BigDecimal.ZERO;
+ BigDecimal expense = net.compareTo(BigDecimal.ZERO) >= 0 ? BigDecimal.ZERO : net.abs();
+ forecast.add(new MonthlyCashFlow(month.toString(), income, expense, net));
+ }
+ return forecast;
+ }
+
+ private StatementSnapshot buildStatementSnapshot(LoginUser loginUser) {
+ LambdaQueryWrapper<AccountStatement> wrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), AccountStatement::getDeptId);
+ wrapper.orderByDesc(AccountStatement::getStatementMonth);
+ List<AccountStatement> rows = defaultList(accountStatementMapper.selectList(wrapper));
+ if (rows.isEmpty()) {
+ return StatementSnapshot.empty();
+ }
+
+ Map<String, AccountStatement> latestByEntity = new HashMap<>();
+ for (AccountStatement row : rows) {
+ if (row.getAccountType() == null || row.getCustomerId() == null || !StringUtils.hasText(row.getStatementMonth())) {
+ continue;
+ }
+ String key = row.getAccountType() + "::" + row.getCustomerId();
+ AccountStatement existing = latestByEntity.get(key);
+ if (existing == null || row.getStatementMonth().compareTo(existing.getStatementMonth()) > 0) {
+ latestByEntity.put(key, row);
+ }
+ }
+
+ BigDecimal receivableTotal = BigDecimal.ZERO;
+ BigDecimal payableTotal = BigDecimal.ZERO;
+ List<StatementMetric> receivableMetrics = new ArrayList<>();
+ List<StatementMetric> payableMetrics = new ArrayList<>();
+ for (AccountStatement row : latestByEntity.values()) {
+ BigDecimal closing = defaultDecimal(row.getClosingBalance());
+ if (Objects.equals(row.getAccountType(), 1)) {
+ receivableTotal = receivableTotal.add(closing);
+ receivableMetrics.add(new StatementMetric(String.valueOf(row.getCustomerId()), closing,
+ defaultDecimal(row.getCurrentPlan()), defaultDecimal(row.getCurrentActually()), safe(row.getStatementMonth())));
+ } else if (Objects.equals(row.getAccountType(), 2)) {
+ payableTotal = payableTotal.add(closing);
+ payableMetrics.add(new StatementMetric(String.valueOf(row.getCustomerId()), closing,
+ defaultDecimal(row.getCurrentPlan()), defaultDecimal(row.getCurrentActually()), safe(row.getStatementMonth())));
+ }
+ }
+ receivableMetrics.sort(Comparator.comparing(StatementMetric::closingBalance).reversed());
+ payableMetrics.sort(Comparator.comparing(StatementMetric::closingBalance).reversed());
+
+ return new StatementSnapshot(
+ receivableTotal,
+ payableTotal,
+ receivableMetrics.stream().limit(10).toList(),
+ payableMetrics.stream().limit(10).toList()
+ );
+ }
+
+ private BigDecimal calculateTotalDepreciation(LoginUser loginUser) {
+ LambdaQueryWrapper<DeviceLedger> wrapper = new LambdaQueryWrapper<>();
+ applyTenantFilter(wrapper, loginUser.getTenantId(), DeviceLedger::getTenantId);
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), DeviceLedger::getDeptId);
+ wrapper.eq(DeviceLedger::getIsDepr, 1);
+ List<DeviceLedger> devices = defaultList(deviceLedgerMapper.selectList(wrapper));
+ BigDecimal total = BigDecimal.ZERO;
+ for (DeviceLedger device : devices) {
+ total = total.add(defaultDecimal(AccountingServiceImpl.calculatePreciseDepreciation(device)));
+ }
+ return total;
+ }
+
+ private Map<Long, BigDecimal> allocateDepreciation(List<SalesLedger> ledgers, BigDecimal totalDepreciation, BigDecimal totalRevenue) {
+ if (ledgers.isEmpty() || totalDepreciation.compareTo(BigDecimal.ZERO) <= 0) {
+ return Map.of();
+ }
+ Map<Long, BigDecimal> result = new HashMap<>();
+ if (totalRevenue.compareTo(BigDecimal.ZERO) <= 0) {
+ BigDecimal avg = totalDepreciation.divide(new BigDecimal(ledgers.size()), 4, RoundingMode.HALF_UP);
+ for (SalesLedger ledger : ledgers) {
+ result.put(ledger.getId(), avg);
+ }
+ return result;
+ }
+ for (SalesLedger ledger : ledgers) {
+ BigDecimal revenue = defaultDecimal(ledger.getContractAmount());
+ BigDecimal ratio = revenue.divide(totalRevenue, 6, RoundingMode.HALF_UP);
+ result.put(ledger.getId(), totalDepreciation.multiply(ratio));
+ }
+ return result;
+ }
+
+ private BigDecimal fallbackMaterialCost(List<SalesLedgerProduct> products, BigDecimal revenue) {
+ if (products != null && !products.isEmpty()) {
+ BigDecimal productAmount = products.stream()
+ .map(SalesLedgerProduct::getTaxExclusiveTotalPrice)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ if (productAmount.compareTo(BigDecimal.ZERO) > 0) {
+ return productAmount;
+ }
+ }
+ return revenue.multiply(DEFAULT_FALLBACK_MATERIAL_COST_RATE);
+ }
+
+ private Map<String, String> queryCustomerNameMap(Set<String> idSet) {
+ if (idSet == null || idSet.isEmpty()) {
+ return Map.of();
+ }
+ Set<Long> ids = idSet.stream()
+ .map(this::toLongOrNull)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+ if (ids.isEmpty()) {
+ return Map.of();
+ }
+ LambdaQueryWrapper<Customer> wrapper = new LambdaQueryWrapper<>();
+ wrapper.in(Customer::getId, ids);
+ return defaultList(customerMapper.selectList(wrapper)).stream()
+ .collect(Collectors.toMap(item -> String.valueOf(item.getId()), Customer::getCustomerName, (a, b) -> a));
+ }
+
+ private Map<String, String> querySupplierNameMap(Set<String> idSet) {
+ if (idSet == null || idSet.isEmpty()) {
+ return Map.of();
+ }
+ Set<Long> ids = idSet.stream()
+ .map(this::toLongOrNull)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+ if (ids.isEmpty()) {
+ return Map.of();
+ }
+ LambdaQueryWrapper<SupplierManage> wrapper = new LambdaQueryWrapper<>();
+ wrapper.in(SupplierManage::getId, ids);
+ return defaultList(supplierManageMapper.selectList(wrapper)).stream()
+ .collect(Collectors.toMap(item -> String.valueOf(item.getId()), SupplierManage::getSupplierName, (a, b) -> a));
+ }
+
+ private String riskLevelByAmount(BigDecimal amount) {
+ if (amount.compareTo(new BigDecimal("5000000")) >= 0) {
+ return "high";
+ }
+ if (amount.compareTo(new BigDecimal("1000000")) >= 0) {
+ return "medium";
+ }
+ return "low";
+ }
+
+ private long countDevices(LoginUser loginUser) {
+ LambdaQueryWrapper<DeviceLedger> wrapper = new LambdaQueryWrapper<>();
+ applyTenantFilter(wrapper, loginUser.getTenantId(), DeviceLedger::getTenantId);
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), DeviceLedger::getDeptId);
+ return deviceLedgerMapper.selectCount(wrapper);
+ }
+
+ private long countRepairingDevices(LoginUser loginUser) {
+ LambdaQueryWrapper<DeviceRepair> wrapper = new LambdaQueryWrapper<>();
+ applyTenantFilter(wrapper, loginUser.getTenantId(), DeviceRepair::getTenantId);
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), DeviceRepair::getDeptId);
+ wrapper.in(DeviceRepair::getStatus, List.of(0, 3));
+ return deviceRepairMapper.selectCount(wrapper);
+ }
+
+ private BigDecimal estimateInventoryValue(LoginUser loginUser, List<StockInventory> inventories) {
+ if (inventories == null || inventories.isEmpty()) {
+ return BigDecimal.ZERO;
+ }
+ Set<Long> modelIds = inventories.stream().map(StockInventory::getProductModelId).filter(Objects::nonNull).collect(Collectors.toSet());
+ Map<Long, BigDecimal> costMap = queryAverageUnitCostByModel(loginUser, modelIds);
+ BigDecimal total = BigDecimal.ZERO;
+ for (StockInventory inventory : inventories) {
+ BigDecimal qty = maxZero(defaultDecimal(inventory.getQualitity()).subtract(defaultDecimal(inventory.getLockedQuantity())));
+ BigDecimal unit = costMap.getOrDefault(inventory.getProductModelId(), BigDecimal.ZERO);
+ total = total.add(qty.multiply(unit));
+ }
+ return total;
+ }
+
+ private DateRange previousSameLengthRange(DateRange range) {
+ long days = daysBetween(range.start(), range.end()) + 1L;
+ LocalDate prevEnd = range.start().minusDays(1);
+ LocalDate prevStart = prevEnd.minusDays(days - 1L);
+ return new DateRange(prevStart, prevEnd, prevStart + "鑷�" + prevEnd);
+ }
+
+ private List<String> buildProfitReasons(BigDecimal revenue,
+ BigDecimal materialCost,
+ BigDecimal laborCost,
+ BigDecimal scrapCost,
+ BigDecimal profit,
+ BigDecimal profitRate) {
+ List<String> reasons = new ArrayList<>();
+ BigDecimal materialRate = rate(materialCost, revenue);
+ if (materialRate.compareTo(new BigDecimal("0.70")) >= 0) {
+ reasons.add("鏉愭枡鎴愭湰鍗犳瘮瓒呰繃70%");
+ } else if (materialRate.compareTo(new BigDecimal("0.55")) >= 0) {
+ reasons.add("鏉愭枡鎴愭湰鍗犳瘮鍋忛珮");
+ }
+ BigDecimal laborRate = rate(laborCost, revenue);
+ if (laborRate.compareTo(new BigDecimal("0.20")) >= 0) {
+ reasons.add("浜哄伐鎴愭湰鍗犳瘮瓒呰繃20%");
+ } else if (laborRate.compareTo(new BigDecimal("0.12")) >= 0) {
+ reasons.add("浜哄伐鎴愭湰澧為暱鍋忓揩");
+ }
+ BigDecimal scrapRate = rate(scrapCost, revenue);
+ if (scrapRate.compareTo(new BigDecimal("0.05")) >= 0) {
+ reasons.add("鎶ュ簾鎹熻�楀崰姣斿亸楂�");
+ }
+ if (profit.compareTo(BigDecimal.ZERO) < 0) {
+ reasons.add("璁㈠崟澶勪簬浜忔崯鐘舵��");
+ } else if (profitRate.compareTo(new BigDecimal("0.08")) < 0) {
+ reasons.add("鍒╂鼎鐜囦綆浜�8%");
+ }
+ if (reasons.isEmpty()) {
+ reasons.add("鎴愭湰缁撴瀯澶勪簬鍚堢悊鍖洪棿");
+ }
+ return reasons;
+ }
+
+ private String buildProfitSuggestion(String riskLevel, List<String> reasons) {
+ if ("high".equals(riskLevel)) {
+ return "浼樺厛澶嶆牳BOM鐢ㄩ噺涓庡伐搴忓畾棰濓紝蹇呰鏃惰皟鏁存姤浠峰拰浠樻鏉℃锛屽苟闄愬埗瓒呰处鏈熶氦浠樸��";
+ }
+ if ("medium".equals(riskLevel)) {
+ return "寤鸿浼樺寲閲囪喘鎵规鍜屽伐搴忔帓浜э紝鎻愬崌涓�娆″悎鏍肩巼骞跺悓姝ユ墽琛屾瘺鍒╅璀︺��";
+ }
+ if (reasons.stream().anyMatch(item -> item.contains("鏉愭枡"))) {
+ return "淇濇寔鏉愭枡閲囪喘鎴愭湰鐪嬫澘锛屾寜鍛ㄨ窡韪富瑕佹潗鏂欏崟浠锋尝鍔ㄣ��";
+ }
+ return "缁存寔褰撳墠缁忚惀鑺傚锛岀户缁窡韪鍗曞埄娑︾巼鍜屽洖娆炬晥鐜囥��";
+ }
+
+ private Map<String, Object> toOrderCostItem(OrderProfitMetric metric) {
+ Map<String, Object> item = new LinkedHashMap<>();
+ item.put("ledgerId", metric.ledgerId());
+ item.put("salesContractNo", metric.salesContractNo());
+ item.put("customerName", metric.customerName());
+ item.put("projectName", metric.projectName());
+ item.put("entryDate", formatDate(metric.entryDate()));
+ item.put("deliveryDate", formatDate(metric.deliveryDate()));
+ item.put("revenue", metric.revenue());
+ item.put("materialCost", metric.materialCost());
+ item.put("laborCost", metric.laborCost());
+ item.put("depreciationCost", metric.depreciationCost());
+ item.put("scrapCost", metric.scrapCost());
+ item.put("totalCost", metric.totalCost());
+ item.put("profit", metric.profit());
+ item.put("profitRate", toPercent(metric.profitRate()));
+ item.put("riskLevel", metric.riskLevel());
+ item.put("reasons", metric.reasons());
+ item.put("suggestion", metric.suggestion());
+ return item;
+ }
+
+ private Map<String, Object> toRiskOrderItem(OrderProfitMetric metric) {
+ Map<String, Object> map = toOrderCostItem(metric);
+ map.put("priority", "high".equals(metric.riskLevel()) ? "high" : ("medium".equals(metric.riskLevel()) ? "medium" : "low"));
+ return map;
+ }
+
+ private List<Map<String, Object>> buildCustomerProfitTop(List<OrderProfitMetric> metrics, int topN) {
+ Map<String, BigDecimal> customerProfitMap = new HashMap<>();
+ Map<String, BigDecimal> customerRevenueMap = new HashMap<>();
+ for (OrderProfitMetric metric : metrics) {
+ customerProfitMap.merge(metric.customerName(), metric.profit(), BigDecimal::add);
+ customerRevenueMap.merge(metric.customerName(), metric.revenue(), BigDecimal::add);
+ }
+ return customerProfitMap.entrySet().stream()
+ .sorted(Map.Entry.<String, BigDecimal>comparingByValue().reversed())
+ .limit(topN)
+ .map(entry -> {
+ Map<String, Object> map = new LinkedHashMap<>();
+ BigDecimal revenue = customerRevenueMap.getOrDefault(entry.getKey(), BigDecimal.ZERO);
+ map.put("customerName", entry.getKey());
+ map.put("profit", entry.getValue());
+ map.put("revenue", revenue);
+ map.put("profitRate", toPercent(rate(entry.getValue(), revenue)));
+ return map;
+ })
+ .toList();
+ }
+
+ private Map<String, Object> toInventoryItem(InventoryMetric metric) {
+ Map<String, Object> map = new LinkedHashMap<>();
+ map.put("productModelId", metric.modelId());
+ map.put("productName", metric.productName());
+ map.put("model", metric.modelName());
+ map.put("quantity", metric.quantity());
+ map.put("lockedQuantity", metric.lockedQuantity());
+ map.put("avgUnitCost", metric.avgUnitCost());
+ map.put("inventoryValue", metric.inventoryValue());
+ map.put("outboundQuantity", metric.outboundQuantity());
+ map.put("stagnantDays", metric.stagnantDays());
+ map.put("overstock", metric.overstock());
+ map.put("riskLevel", metric.stagnantDays() >= 90 ? "high" : (metric.stagnantDays() >= 30 ? "medium" : "low"));
+ return map;
+ }
+
+ private boolean matchInventoryKeyword(InventoryMetric metric, String keyword) {
+ if (!StringUtils.hasText(keyword)) {
+ return true;
+ }
+ return metric.productName().contains(keyword.trim()) || metric.modelName().contains(keyword.trim());
+ }
+
+ private Map<String, Object> toMonthlyCashFlowItem(MonthlyCashFlow flow) {
+ Map<String, Object> map = new LinkedHashMap<>();
+ map.put("month", flow.month());
+ map.put("income", flow.income());
+ map.put("expense", flow.expense());
+ map.put("netFlow", flow.netFlow());
+ return map;
+ }
+
+ private Map<String, Object> toStatementRiskItem(StatementMetric metric, Map<String, String> nameMap, String type) {
+ BigDecimal actualRate = rate(metric.actualAmount(), metric.planAmount());
+ Map<String, Object> map = new LinkedHashMap<>();
+ map.put(type + "Id", metric.entityId());
+ map.put(type + "Name", safe(nameMap.get(metric.entityId())));
+ map.put("statementMonth", metric.statementMonth());
+ map.put("closingBalance", metric.closingBalance());
+ map.put("planAmount", metric.planAmount());
+ map.put("actualAmount", metric.actualAmount());
+ map.put("actualRate", toPercent(actualRate));
+ map.put("riskLevel", metric.closingBalance().compareTo(new BigDecimal("1000000")) > 0 || actualRate.compareTo(new BigDecimal("0.50")) < 0 ? "high" : "medium");
+ return map;
+ }
+
+ private Map<String, Object> anomalyItem(String level, String type, String message, Map<String, Object> detail) {
+ Map<String, Object> map = new LinkedHashMap<>();
+ map.put("riskLevel", level);
+ map.put("type", type);
+ map.put("message", message);
+ map.put("detail", detail);
+ return map;
+ }
+
+ private Map<String, Object> riskSuggestion(String type, String level, String suggestion) {
+ Map<String, Object> map = new LinkedHashMap<>();
+ map.put("type", type);
+ map.put("level", level);
+ map.put("suggestion", suggestion);
+ return map;
+ }
+
+ private Map<String, Object> buildCostCompositionPie(BigDecimal material, BigDecimal labor, BigDecimal depreciation, BigDecimal scrap) {
+ List<Map<String, Object>> data = List.of(
+ Map.of("name", "鏉愭枡鎴愭湰", "value", material),
+ Map.of("name", "浜哄伐鎴愭湰", "value", labor),
+ Map.of("name", "鎶樻棫鎴愭湰", "value", depreciation),
+ Map.of("name", "鎹熻�楁垚鏈�", "value", scrap)
+ );
+ Map<String, Object> option = new LinkedHashMap<>();
+ option.put("title", Map.of("text", "鎴愭湰鏋勬垚", "left", "center"));
+ option.put("tooltip", Map.of("trigger", "item"));
+ option.put("series", List.of(Map.of("name", "鎴愭湰鏋勬垚", "type", "pie", "radius", "60%", "data", data)));
+ return option;
+ }
+
+ private Map<String, Object> buildOrderProfitBar(List<OrderProfitMetric> metrics) {
+ List<OrderProfitMetric> top = metrics.stream()
+ .sorted(Comparator.comparing(OrderProfitMetric::profit))
+ .limit(10)
+ .toList();
+ List<String> xData = top.stream().map(OrderProfitMetric::salesContractNo).toList();
+ List<BigDecimal> yData = top.stream().map(OrderProfitMetric::profit).toList();
+ Map<String, Object> option = new LinkedHashMap<>();
+ option.put("title", Map.of("text", "璁㈠崟鍒╂鼎鍒嗗竷", "left", "center"));
+ option.put("tooltip", Map.of("trigger", "axis"));
+ option.put("xAxis", Map.of("type", "category", "data", xData));
+ option.put("yAxis", Map.of("type", "value"));
+ option.put("series", List.of(Map.of("name", "鍒╂鼎", "type", "bar", "data", yData)));
+ return option;
+ }
+
+ private Map<String, Object> buildProcessCostBar(Map<String, BigDecimal> processCosts) {
+ List<String> xData = new ArrayList<>(processCosts.keySet());
+ List<BigDecimal> yData = new ArrayList<>(processCosts.values());
+ Map<String, Object> option = new LinkedHashMap<>();
+ option.put("title", Map.of("text", "宸ュ簭鎴愭湰鎺掑悕", "left", "center"));
+ option.put("tooltip", Map.of("trigger", "axis"));
+ option.put("xAxis", Map.of("type", "category", "data", xData));
+ option.put("yAxis", Map.of("type", "value"));
+ option.put("series", List.of(Map.of("name", "鎴愭湰", "type", "bar", "data", yData)));
+ return option;
+ }
+
+ private Map<String, Object> buildProfitDistributionBar(List<OrderProfitMetric> metrics) {
+ List<OrderProfitMetric> sorted = metrics.stream()
+ .sorted(Comparator.comparing(OrderProfitMetric::profitRate))
+ .limit(15)
+ .toList();
+ List<String> xData = sorted.stream().map(OrderProfitMetric::salesContractNo).toList();
+ List<BigDecimal> yData = sorted.stream().map(metric -> metric.profitRate().multiply(ONE_HUNDRED).setScale(2, RoundingMode.HALF_UP)).toList();
+ Map<String, Object> option = new LinkedHashMap<>();
+ option.put("title", Map.of("text", "璁㈠崟鍒╂鼎鐜囧垎甯�", "left", "center"));
+ option.put("tooltip", Map.of("trigger", "axis"));
+ option.put("xAxis", Map.of("type", "category", "data", xData));
+ option.put("yAxis", Map.of("type", "value", "name", "%"));
+ option.put("series", List.of(Map.of("name", "鍒╂鼎鐜�", "type", "bar", "data", yData)));
+ return option;
+ }
+
+ private Map<String, Object> buildLossOrderTrendLine(List<OrderProfitMetric> metrics) {
+ Map<String, Long> lossByDate = new LinkedHashMap<>();
+ List<OrderProfitMetric> sorted = metrics.stream()
+ .filter(metric -> metric.entryDate() != null)
+ .sorted(Comparator.comparing(OrderProfitMetric::entryDate))
+ .toList();
+ for (OrderProfitMetric metric : sorted) {
+ String day = formatDate(metric.entryDate());
+ long inc = metric.profit().compareTo(BigDecimal.ZERO) < 0 ? 1L : 0L;
+ lossByDate.merge(day, inc, Long::sum);
+ }
+ Map<String, Object> option = new LinkedHashMap<>();
+ option.put("title", Map.of("text", "浜忔崯璁㈠崟瓒嬪娍", "left", "center"));
+ option.put("tooltip", Map.of("trigger", "axis"));
+ option.put("xAxis", Map.of("type", "category", "data", new ArrayList<>(lossByDate.keySet())));
+ option.put("yAxis", Map.of("type", "value"));
+ option.put("series", List.of(Map.of("name", "浜忔崯璁㈠崟鏁�", "type", "line", "smooth", true, "data", new ArrayList<>(lossByDate.values()))));
+ return option;
+ }
+
+ private Map<String, Object> buildCustomerProfitBar(Map<String, BigDecimal> customerProfitMap) {
+ List<Map.Entry<String, BigDecimal>> top = customerProfitMap.entrySet().stream()
+ .sorted(Map.Entry.<String, BigDecimal>comparingByValue().reversed())
+ .limit(10)
+ .toList();
+ Map<String, Object> option = new LinkedHashMap<>();
+ option.put("title", Map.of("text", "瀹㈡埛鍒╂鼎璐$尞TOP10", "left", "center"));
+ option.put("tooltip", Map.of("trigger", "axis"));
+ option.put("xAxis", Map.of("type", "category", "data", top.stream().map(Map.Entry::getKey).toList()));
+ option.put("yAxis", Map.of("type", "value"));
+ option.put("series", List.of(Map.of("name", "鍒╂鼎", "type", "bar", "data", top.stream().map(Map.Entry::getValue).toList())));
+ return option;
+ }
+
+ private Map<String, Object> buildInventoryTopBar(List<InventoryMetric> metrics) {
+ List<InventoryMetric> top = metrics.stream()
+ .sorted(Comparator.comparing(InventoryMetric::inventoryValue).reversed())
+ .limit(10)
+ .toList();
+ Map<String, Object> option = new LinkedHashMap<>();
+ option.put("title", Map.of("text", "搴撳瓨璧勯噾鍗犵敤TOP10", "left", "center"));
+ option.put("tooltip", Map.of("trigger", "axis"));
+ option.put("xAxis", Map.of("type", "category", "data", top.stream().map(item -> item.productName() + "/" + item.modelName()).toList()));
+ option.put("yAxis", Map.of("type", "value"));
+ option.put("series", List.of(Map.of("name", "璧勯噾鍗犵敤", "type", "bar", "data", top.stream().map(InventoryMetric::inventoryValue).toList())));
+ return option;
+ }
+
+ private Map<String, Object> buildInventoryAgingPie(List<InventoryMetric> metrics) {
+ long normal = metrics.stream().filter(item -> item.stagnantDays() < 30).count();
+ long slow = metrics.stream().filter(item -> item.stagnantDays() >= 30 && item.stagnantDays() < 90).count();
+ long stagnant = metrics.stream().filter(item -> item.stagnantDays() >= 90).count();
+ List<Map<String, Object>> data = List.of(
+ Map.of("name", "姝e父", "value", normal),
+ Map.of("name", "缂撴參", "value", slow),
+ Map.of("name", "鍛嗘粸", "value", stagnant)
+ );
+ Map<String, Object> option = new LinkedHashMap<>();
+ option.put("title", Map.of("text", "搴撳瓨搴撻緞鍒嗗竷", "left", "center"));
+ option.put("tooltip", Map.of("trigger", "item"));
+ option.put("series", List.of(Map.of("type", "pie", "radius", "60%", "data", data)));
+ return option;
+ }
+
+ private Map<String, Object> buildTurnoverGauge(BigDecimal turnoverDays) {
+ Map<String, Object> option = new LinkedHashMap<>();
+ option.put("title", Map.of("text", "搴撳瓨鍛ㄨ浆澶╂暟", "left", "center"));
+ option.put("series", List.of(Map.of(
+ "type", "gauge",
+ "min", 0,
+ "max", 180,
+ "detail", Map.of("formatter", "{value}澶�"),
+ "data", List.of(Map.of("value", turnoverDays, "name", "鍛ㄨ浆澶╂暟"))
+ )));
+ return option;
+ }
+
+ private Map<String, Object> buildCashflowTrend(List<MonthlyCashFlow> actual, List<MonthlyCashFlow> forecast) {
+ List<String> labels = new ArrayList<>();
+ List<BigDecimal> netActual = new ArrayList<>();
+ List<BigDecimal> netForecast = new ArrayList<>();
+ for (MonthlyCashFlow point : actual) {
+ labels.add(point.month());
+ netActual.add(point.netFlow());
+ netForecast.add(null);
+ }
+ for (MonthlyCashFlow point : forecast) {
+ labels.add(point.month());
+ netActual.add(null);
+ netForecast.add(point.netFlow());
+ }
+ Map<String, Object> option = new LinkedHashMap<>();
+ option.put("title", Map.of("text", "鐜伴噾娴佽秼鍔匡紙瀹為檯+棰勬祴锛�", "left", "center"));
+ option.put("tooltip", Map.of("trigger", "axis"));
+ option.put("xAxis", Map.of("type", "category", "data", labels));
+ option.put("yAxis", Map.of("type", "value"));
+ option.put("series", List.of(
+ Map.of("name", "瀹為檯鍑�鐜伴噾娴�", "type", "line", "smooth", true, "data", netActual),
+ Map.of("name", "棰勬祴鍑�鐜伴噾娴�", "type", "line", "smooth", true, "data", netForecast)
+ ));
+ return option;
+ }
+
+ private Map<String, Object> buildReceivablePayableBar(BigDecimal receivable, BigDecimal payable) {
+ Map<String, Object> option = new LinkedHashMap<>();
+ option.put("title", Map.of("text", "搴旀敹搴斾粯浣欓瀵规瘮", "left", "center"));
+ option.put("tooltip", Map.of("trigger", "axis"));
+ option.put("xAxis", Map.of("type", "category", "data", List.of("搴旀敹", "搴斾粯")));
+ option.put("yAxis", Map.of("type", "value"));
+ option.put("series", List.of(Map.of("name", "浣欓", "type", "bar", "data", List.of(receivable, payable))));
+ return option;
+ }
+
+ private Map<String, Object> buildFundGapGauge(BigDecimal fundGap) {
+ Map<String, Object> option = new LinkedHashMap<>();
+ option.put("title", Map.of("text", "璧勯噾缂哄彛", "left", "center"));
+ option.put("series", List.of(Map.of(
+ "type", "gauge",
+ "min", 0,
+ "max", 10000000,
+ "detail", Map.of("formatter", "{value}"),
+ "data", List.of(Map.of("value", fundGap, "name", "璧勯噾缂哄彛"))
+ )));
+ return option;
+ }
+
+ private Map<String, Object> buildAnomalyLevelPie(List<Map<String, Object>> anomalies) {
+ long high = anomalies.stream().filter(item -> "high".equals(item.get("riskLevel"))).count();
+ long medium = anomalies.stream().filter(item -> "medium".equals(item.get("riskLevel"))).count();
+ long low = anomalies.stream().filter(item -> "low".equals(item.get("riskLevel"))).count();
+ Map<String, Object> option = new LinkedHashMap<>();
+ option.put("title", Map.of("text", "寮傚父绛夌骇鍒嗗竷", "left", "center"));
+ option.put("tooltip", Map.of("trigger", "item"));
+ option.put("series", List.of(Map.of("type", "pie", "radius", "60%", "data", List.of(
+ Map.of("name", "楂橀闄�", "value", high),
+ Map.of("name", "涓闄�", "value", medium),
+ Map.of("name", "浣庨闄�", "value", low)
+ ))));
+ return option;
+ }
+
+ private Map<String, Object> buildAnomalyTypeBar(List<Map<String, Object>> anomalies) {
+ Map<String, Long> countByType = new LinkedHashMap<>();
+ for (Map<String, Object> anomaly : anomalies) {
+ countByType.merge(String.valueOf(anomaly.get("type")), 1L, Long::sum);
+ }
+ Map<String, Object> option = new LinkedHashMap<>();
+ option.put("title", Map.of("text", "寮傚父绫诲瀷鍒嗗竷", "left", "center"));
+ option.put("tooltip", Map.of("trigger", "axis"));
+ option.put("xAxis", Map.of("type", "category", "data", new ArrayList<>(countByType.keySet())));
+ option.put("yAxis", Map.of("type", "value"));
+ option.put("series", List.of(Map.of("name", "寮傚父鏁�", "type", "bar", "data", new ArrayList<>(countByType.values()))));
+ return option;
+ }
+
+ private Map<String, Object> buildInventoryProfitGauge(BigDecimal inventoryValue, BigDecimal profit) {
+ BigDecimal ratio = inventoryValue.compareTo(BigDecimal.ZERO) <= 0
+ ? BigDecimal.ZERO
+ : profit.divide(inventoryValue, 4, RoundingMode.HALF_UP).multiply(ONE_HUNDRED);
+ Map<String, Object> option = new LinkedHashMap<>();
+ option.put("title", Map.of("text", "鍒╂鼎/搴撳瓨璧勯噾姣�", "left", "center"));
+ option.put("series", List.of(Map.of(
+ "type", "gauge",
+ "min", -100,
+ "max", 100,
+ "detail", Map.of("formatter", "{value}%"),
+ "data", List.of(Map.of("value", ratio.setScale(2, RoundingMode.HALF_UP), "name", "鍒╂鼎璧勯噾姣�"))
+ )));
+ return option;
+ }
+
+ private int normalizeLimit(Integer limit) {
+ if (limit == null || limit <= 0) {
+ return DEFAULT_LIMIT;
+ }
+ return Math.min(limit, MAX_LIMIT);
+ }
+
+ private DateRange resolveDateRange(String startDate, String endDate, String timeRange, String defaultLabel) {
+ LocalDate today = LocalDate.now();
+ LocalDate explicitStart = parseLocalDate(startDate);
+ LocalDate explicitEnd = parseLocalDate(endDate);
+ if (explicitStart != null || explicitEnd != null) {
+ LocalDate start = explicitStart != null ? explicitStart : explicitEnd;
+ LocalDate end = explicitEnd != null ? explicitEnd : explicitStart;
+ if (start.isAfter(end)) {
+ LocalDate temp = start;
+ start = end;
+ end = temp;
+ }
+ return new DateRange(start, end, start + "鑷�" + end);
+ }
+
+ if (!StringUtils.hasText(timeRange)) {
+ if ("浠婂ぉ".equals(defaultLabel)) {
+ return new DateRange(today, today, "浠婂ぉ");
+ }
+ if ("鏈懆".equals(defaultLabel)) {
+ LocalDate start = today.minusDays(today.getDayOfWeek().getValue() - 1L);
+ return new DateRange(start, today, "鏈懆");
+ }
+ if ("鏈湀".equals(defaultLabel)) {
+ return new DateRange(today.withDayOfMonth(1), today, "鏈湀");
+ }
+ if ("杩�90澶�".equals(defaultLabel)) {
+ return new DateRange(today.minusDays(89), today, "杩�90澶�");
+ }
+ return new DateRange(today.minusDays(29), today, defaultLabel);
+ }
+
+ String text = timeRange.trim();
+ if (text.contains("浠婂ぉ")) {
+ return new DateRange(today, today, "浠婂ぉ");
+ }
+ if (text.contains("鏄ㄥぉ") || text.contains("鏄ㄦ棩")) {
+ LocalDate day = today.minusDays(1);
+ return new DateRange(day, day, "鏄ㄥぉ");
+ }
+ if (text.contains("鏈懆")) {
+ LocalDate start = today.minusDays(today.getDayOfWeek().getValue() - 1L);
+ return new DateRange(start, today, "鏈懆");
+ }
+ if (text.contains("涓婂懆")) {
+ LocalDate thisWeekStart = today.minusDays(today.getDayOfWeek().getValue() - 1L);
+ LocalDate start = thisWeekStart.minusWeeks(1);
+ LocalDate end = thisWeekStart.minusDays(1);
+ return new DateRange(start, end, "涓婂懆");
+ }
+ if (text.contains("鏈湀")) {
+ return new DateRange(today.withDayOfMonth(1), today, "鏈湀");
+ }
+ if (text.contains("涓婃湀")) {
+ YearMonth lastMonth = YearMonth.from(today).minusMonths(1);
+ return new DateRange(lastMonth.atDay(1), lastMonth.atEndOfMonth(), "涓婃湀");
+ }
+ if (text.contains("浠婂勾") || text.contains("鏈勾")) {
+ return new DateRange(today.withDayOfYear(1), today, "浠婂勾");
+ }
+ Matcher relativeMatcher = RELATIVE_PATTERN.matcher(text);
+ if (relativeMatcher.find()) {
+ int amount = Integer.parseInt(relativeMatcher.group(2));
+ String unit = relativeMatcher.group(3);
+ LocalDate start = switch (unit) {
+ case "澶�" -> today.minusDays(Math.max(amount - 1L, 0));
+ case "鍛�" -> today.minusWeeks(Math.max(amount, 1)).plusDays(1);
+ case "涓湀", "鏈�" -> today.minusMonths(Math.max(amount, 1)).plusDays(1);
+ case "骞�" -> today.minusYears(Math.max(amount, 1)).plusDays(1);
+ default -> today.minusDays(29);
+ };
+ return new DateRange(start, today, "杩�" + amount + unit);
+ }
+ Matcher dateMatcher = DATE_PATTERN.matcher(text);
+ if (dateMatcher.find()) {
+ LocalDate start = parseLocalDate(dateMatcher.group(1));
+ LocalDate end = dateMatcher.find() ? parseLocalDate(dateMatcher.group(1)) : start;
+ if (start != null && end != null) {
+ if (start.isAfter(end)) {
+ LocalDate temp = start;
+ start = end;
+ end = temp;
+ }
+ return new DateRange(start, end, start + "鑷�" + end);
+ }
+ }
+ return new DateRange(today.minusDays(29), today, "杩�30澶�");
+ }
+
+ private LocalDate parseLocalDate(String text) {
+ if (!StringUtils.hasText(text)) {
+ return null;
+ }
+ try {
+ return LocalDate.parse(text.trim(), DATE_FMT);
+ } catch (Exception ignored) {
+ return null;
+ }
+ }
+
+ private Date toDate(LocalDate localDate) {
+ return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
+ }
+
+ private Date toExclusiveEndDate(LocalDate localDate) {
+ return Date.from(localDate.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
+ }
+
+ private LocalDate toLocalDate(Date date) {
+ if (date == null) {
+ return null;
+ }
+ return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+ }
+
+ private String formatDate(LocalDate date) {
+ return date == null ? "" : date.format(DATE_FMT);
+ }
+
+ private long daysBetween(LocalDate start, LocalDate end) {
+ if (start == null || end == null || start.isAfter(end)) {
+ return 0;
+ }
+ return end.toEpochDay() - start.toEpochDay();
+ }
+
+ private BigDecimal defaultDecimal(BigDecimal value) {
+ return value == null ? BigDecimal.ZERO : value;
+ }
+
+ private BigDecimal maxZero(BigDecimal value) {
+ return value == null || value.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : value;
+ }
+
+ private BigDecimal rate(BigDecimal numerator, BigDecimal denominator) {
+ if (denominator == null || denominator.compareTo(BigDecimal.ZERO) <= 0) {
+ return BigDecimal.ZERO;
+ }
+ return defaultDecimal(numerator).divide(denominator, 6, RoundingMode.HALF_UP);
+ }
+
+ private String toPercent(BigDecimal decimal) {
+ if (decimal == null) {
+ return "0.00%";
+ }
+ BigDecimal rate = decimal.multiply(ONE_HUNDRED).setScale(2, RoundingMode.HALF_UP);
+ return rate.toPlainString() + "%";
+ }
+
+ private BigDecimal avgRate(List<OrderProfitMetric> metrics) {
+ if (metrics == null || metrics.isEmpty()) {
+ return BigDecimal.ZERO;
+ }
+ BigDecimal sum = metrics.stream().map(OrderProfitMetric::profitRate).reduce(BigDecimal.ZERO, BigDecimal::add);
+ return sum.divide(new BigDecimal(metrics.size()), 6, RoundingMode.HALF_UP);
+ }
+
+ private BigDecimal estimateLaborCost(ProductionAccount account, Map<String, BigDecimal> salaryQuotaByOperation) {
+ BigDecimal salaryQuota = salaryQuotaByOperation.getOrDefault(safe(account.getTechnologyOperationName()), BigDecimal.ZERO);
+ BigDecimal finishedNum = defaultDecimal(account.getFinishedNum());
+ BigDecimal workHours = defaultDecimal(account.getWorkHours());
+ if (salaryQuota.compareTo(BigDecimal.ZERO) > 0 && finishedNum.compareTo(BigDecimal.ZERO) > 0) {
+ return finishedNum.multiply(salaryQuota);
+ }
+ if (salaryQuota.compareTo(BigDecimal.ZERO) > 0 && workHours.compareTo(BigDecimal.ZERO) > 0) {
+ return workHours.multiply(salaryQuota);
+ }
+ if (workHours.compareTo(BigDecimal.ZERO) > 0) {
+ return workHours;
+ }
+ return finishedNum;
+ }
+
+ private List<Long> parseIdList(String raw) {
+ if (!StringUtils.hasText(raw)) {
+ return List.of();
+ }
+ String text = raw.replace("[", "").replace("]", "").replace(" ", "");
+ if (!StringUtils.hasText(text)) {
+ return List.of();
+ }
+ List<Long> result = new ArrayList<>();
+ for (String part : text.split(",")) {
+ if (!StringUtils.hasText(part)) {
+ continue;
+ }
+ try {
+ result.add(Long.parseLong(part.trim()));
+ } catch (Exception ignored) {
+ }
+ }
+ return result;
+ }
+
+ private int keywordHitCount(List<String> keywords, String question) {
+ if (!StringUtils.hasText(question) || keywords == null) {
+ return 0;
+ }
+ int count = 0;
+ for (String keyword : keywords) {
+ if (question.contains(keyword)) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ private String normalizeForMatch(String text) {
+ if (!StringUtils.hasText(text)) {
+ return "";
+ }
+ return text.replace("锛�", "")
+ .replace(",", "")
+ .replace("銆�", "")
+ .replace(".", "")
+ .replace("锛�", "")
+ .replace("!", "")
+ .replace("锛�", "")
+ .replace("?", "")
+ .replace("锛�", "")
+ .replace(":", "")
+ .replace("锛�", "")
+ .replace(";", "")
+ .replace(" ", "")
+ .trim();
+ }
+
+ private String safe(Object value) {
+ return value == null ? "" : String.valueOf(value).replace('\n', ' ').replace('\r', ' ').trim();
+ }
+
+ private LoginUser currentLoginUser(String memoryId) {
+ LoginUser loginUser = aiSessionUserContext.get(memoryId);
+ if (loginUser != null) {
+ return loginUser;
+ }
+ return SecurityUtils.getLoginUser();
+ }
+
+ private Map<String, Object> rangeSummary(DateRange range, int count, String keyword) {
+ Map<String, Object> summary = new LinkedHashMap<>();
+ summary.put("timeRange", range.label());
+ summary.put("startDate", range.start().toString());
+ summary.put("endDate", range.end().toString());
+ summary.put("count", count);
+ summary.put("keyword", safe(keyword));
+ return summary;
+ }
+
+ private Long toLongOrNull(String value) {
+ if (!StringUtils.hasText(value)) {
+ return null;
+ }
+ try {
+ return Long.valueOf(value.trim());
+ } catch (Exception ignored) {
+ return null;
+ }
+ }
+
+ private <T> List<T> defaultList(List<T> list) {
+ return list == null ? List.of() : list;
+ }
+
+ private <T> void applyTenantFilter(LambdaQueryWrapper<T> wrapper, Long tenantId, SFunction<T, Long> field) {
+ if (tenantId != null) {
+ wrapper.eq(field, tenantId);
+ }
+ }
+
+ private <T> void applyDeptFilter(LambdaQueryWrapper<T> wrapper, Long deptId, SFunction<T, Long> field) {
+ if (deptId != null) {
+ wrapper.eq(field, deptId);
+ }
+ }
+
+ private List<KnowledgeDoc> financeKnowledgeBase() {
+ return List.of(
+ new KnowledgeDoc(
+ "鍒╂鼎涓嬮檷鍒嗘瀽妗嗘灦",
+ List.of("鍒╂鼎涓嬮檷", "浜忔崯璁㈠崟", "姣涘埄鐜�", "鍑�鍒╃巼"),
+ "鍏堢湅鏀跺叆绔紙璁㈠崟缁撴瀯銆佸崟浠枫�佷氦浠樺欢杩燂級锛屽啀鐪嬫垚鏈锛堟潗鏂欍�佷汉宸ャ�佹姌鏃с�佹崯鑰楋級锛屾渶鍚庣湅鐜伴噾绔紙鍥炴銆佽处鏈熴�佸潖璐﹂闄╋級銆�",
+ List.of("sales_ledger", "sales_ledger_product", "production_account", "device_ledger", "account_statement"),
+ List.of("涓轰粈涔堟湰鏈堝埄娑︿笅闄嶏紵", "鍝簺璁㈠崟浜忔崯鏈�涓ラ噸锛�", "鎴愭湰涓婂崌鏉ヨ嚜鍝釜宸ュ簭锛�")
+ ),
+ new KnowledgeDoc(
+ "搴撳瓨璧勯噾鍗犵敤璇婃柇",
+ List.of("搴撳瓨绉帇", "鍛嗘粸搴撳瓨", "鍛ㄨ浆鐜�", "璧勯噾鍗犵敤"),
+ "搴撳瓨璧勯噾璇婃柇閲嶇偣鐪嬶細搴撳瓨浠峰�笺�佽繎30澶╁嚭搴撴垚鏈�佸憜婊炲ぉ鏁般�佽秴鍌ㄦ瘮渚嬶紝褰㈡垚鍘诲簱瀛樹笌閲囪喘鑺傚鑱斿姩绛栫暐銆�",
+ List.of("stock_inventory", "procurement_record_storage", "procurement_record_out"),
+ List.of("鍝簺鐗╂枡璧勯噾鍗犵敤鏈�楂橈紵", "鍝簺搴撳瓨瓒呰繃90澶╂湭鍛ㄨ浆锛�", "搴撳瓨鍛ㄨ浆澶╂暟鏄惁寮傚父锛�")
+ ),
+ new KnowledgeDoc(
+ "鐜伴噾娴佷笌璐︽椋庨櫓",
+ List.of("鐜伴噾娴�", "搴旀敹", "搴斾粯", "鍥炴", "璧勯噾缂哄彛"),
+ "鐜伴噾娴佸垽鏂缁撳悎鏀舵銆佷粯娆俱�佸簲鏀跺簲浠樹綑棰濅笌棰勬祴鍑�娴侀噺锛岄噸鐐瑰叧娉ㄩ珮浣欓瀹㈡埛鍜岄珮闆嗕腑浠樻渚涘簲鍟嗐��",
+ List.of("account_sales_collection", "account_purchase_payment", "account_statement"),
+ List.of("鏈潵涓変釜鏈堟槸鍚︽湁璧勯噾缂哄彛锛�", "鍝釜瀹㈡埛鍥炴椋庨櫓鏈�楂橈紵", "浠樻鍘嬪姏鏈�澶х殑鏄摢浜涗緵搴斿晢锛�")
+ ),
+ new KnowledgeDoc(
+ "涓氳储涓�浣撳寲鍙e緞",
+ List.of("涓氳储铻嶅悎", "涓氳储鑱斿姩", "鍙e緞", "椹鹃┒鑸�"),
+ "璁㈠崟鍒╂鼎鍙e緞=閿�鍞敹鍏�-鏉愭枡鎴愭湰-浜哄伐鎴愭湰-璁惧鎶樻棫-鎹熻�楁垚鏈紱缁忚惀椹鹃┒鑸辫仈鍔ㄨ鍗曘�佺敓浜с�佸簱瀛樸�佽澶囥�佽处娆炬暟鎹��",
+ List.of("sales_ledger", "production_operation_task", "production_product_main", "device_ledger", "stock_inventory", "account_statement"),
+ List.of("璁㈠崟鍒╂鼎鐜囧浣曡绠楋紵", "缁忚惀椹鹃┒鑸辨牳蹇冩寚鏍囨湁鍝簺锛�")
+ )
+ );
+ }
+
+ private String jsonResponse(boolean success,
+ String type,
+ String description,
+ Map<String, Object> summary,
+ Map<String, Object> data,
+ Map<String, Object> charts) {
+ Map<String, Object> result = new LinkedHashMap<>();
+ result.put("success", success);
+ result.put("type", type);
+ result.put("description", description);
+ result.put("summary", summary == null ? Map.of() : summary);
+ result.put("data", data == null ? Map.of() : data);
+ result.put("charts", charts == null ? Map.of() : charts);
+ return JSON.toJSONString(result);
+ }
+
+ private record DateRange(LocalDate start, LocalDate end, String label) {
+ }
+
+ private record OrderProfitMetric(Long ledgerId,
+ String salesContractNo,
+ String customerName,
+ String projectName,
+ LocalDate entryDate,
+ LocalDate deliveryDate,
+ BigDecimal revenue,
+ BigDecimal materialCost,
+ BigDecimal laborCost,
+ BigDecimal depreciationCost,
+ BigDecimal scrapCost,
+ BigDecimal totalCost,
+ BigDecimal profit,
+ BigDecimal profitRate,
+ String riskLevel,
+ List<String> reasons,
+ String suggestion) {
+ }
+
+ private record AnalysisBundle(List<OrderProfitMetric> orderMetrics,
+ Map<String, BigDecimal> processCostRanking,
+ BigDecimal totalRevenue,
+ BigDecimal totalMaterialCost,
+ BigDecimal totalLaborCost,
+ BigDecimal totalDepreciationCost,
+ BigDecimal totalScrapCost,
+ BigDecimal totalCost,
+ BigDecimal totalProfit) {
+ private static AnalysisBundle empty() {
+ return new AnalysisBundle(List.of(), Map.of(), BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO,
+ BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO);
+ }
+ }
+
+ private record MaterialCostResult(Map<Long, BigDecimal> materialCostByLedgerId,
+ Map<Long, BigDecimal> avgUnitCostByModelId) {
+ }
+
+ private record ProductionCostContext(Map<Long, BigDecimal> laborCostByLedgerId,
+ Map<Long, BigDecimal> scrapCostByLedgerId,
+ Map<String, BigDecimal> processCostRanking) {
+ private static ProductionCostContext empty() {
+ return new ProductionCostContext(Map.of(), Map.of(), Map.of());
+ }
+ }
+
+ private record InventoryMetric(Long modelId,
+ String productName,
+ String modelName,
+ BigDecimal quantity,
+ BigDecimal lockedQuantity,
+ BigDecimal avgUnitCost,
+ BigDecimal inventoryValue,
+ BigDecimal outboundQuantity,
+ long stagnantDays,
+ boolean overstock) {
+ }
+
+ private static class InventoryMetricBuilder {
+ private final Long modelId;
+ private BigDecimal quantity = BigDecimal.ZERO;
+ private BigDecimal lockedQuantity = BigDecimal.ZERO;
+ private BigDecimal warnNum = BigDecimal.ZERO;
+ private LocalDateTime firstInTime;
+
+ private InventoryMetricBuilder(Long modelId) {
+ this.modelId = modelId;
+ }
+
+ private void addQuantity(BigDecimal quantity) {
+ this.quantity = this.quantity.add(quantity);
+ }
+
+ private void addLockedQuantity(BigDecimal lockedQuantity) {
+ this.lockedQuantity = this.lockedQuantity.add(lockedQuantity);
+ }
+
+ private void addWarnNum(BigDecimal warnNum) {
+ this.warnNum = this.warnNum.max(warnNum);
+ }
+
+ private void updateFirstInTime(LocalDateTime createTime) {
+ if (this.firstInTime == null || createTime.isBefore(this.firstInTime)) {
+ this.firstInTime = createTime;
+ }
+ }
+
+ private Long modelId() {
+ return modelId;
+ }
+
+ private BigDecimal quantity() {
+ return quantity;
+ }
+
+ private BigDecimal lockedQuantity() {
+ return lockedQuantity;
+ }
+
+ private BigDecimal warnNum() {
+ return warnNum;
+ }
+
+ private LocalDateTime firstInTime() {
+ return firstInTime;
+ }
+ }
+
+ private record OutboundStats(Map<Long, BigDecimal> outboundQtyByModel,
+ Map<Long, LocalDateTime> lastOutboundTimeByModel,
+ BigDecimal totalOutboundCost) {
+ private static OutboundStats empty() {
+ return new OutboundStats(Map.of(), Map.of(), BigDecimal.ZERO);
+ }
+ }
+
+ private record MonthlyCashFlow(String month, BigDecimal income, BigDecimal expense, BigDecimal netFlow) {
+ }
+
+ private record StatementMetric(String entityId,
+ BigDecimal closingBalance,
+ BigDecimal planAmount,
+ BigDecimal actualAmount,
+ String statementMonth) {
+ }
+
+ private record StatementSnapshot(BigDecimal receivableTotal,
+ BigDecimal payableTotal,
+ List<StatementMetric> receivableTop,
+ List<StatementMetric> payableTop) {
+ private static StatementSnapshot empty() {
+ return new StatementSnapshot(BigDecimal.ZERO, BigDecimal.ZERO, List.of(), List.of());
+ }
+ }
+
+ private record KnowledgeDoc(String topic,
+ List<String> keywords,
+ String knowledge,
+ List<String> relatedTables,
+ List<String> suggestedQuestions) {
+ }
+}
diff --git a/src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java b/src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java
index 17b6868..bdd1f1f 100644
--- a/src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java
+++ b/src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java
@@ -2,23 +2,29 @@
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.account.mapper.purchase.AccountPaymentApplicationMapper;
+import com.ruoyi.account.mapper.purchase.AccountPurchaseInvoiceMapper;
+import com.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper;
+import com.ruoyi.account.pojo.purchase.AccountPaymentApplication;
+import com.ruoyi.account.pojo.purchase.AccountPurchaseInvoice;
+import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
import com.ruoyi.ai.context.AiSessionUserContext;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.security.LoginUser;
-import com.ruoyi.purchase.mapper.InvoicePurchaseMapper;
-import com.ruoyi.purchase.mapper.PaymentRegistrationMapper;
-import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
-import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
-import com.ruoyi.purchase.pojo.InvoicePurchase;
-import com.ruoyi.purchase.pojo.PaymentRegistration;
-import com.ruoyi.purchase.pojo.PurchaseLedger;
-import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
import com.ruoyi.procurementrecord.mapper.InboundManagementMapper;
import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper;
import com.ruoyi.procurementrecord.pojo.InboundManagement;
import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
+import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
+import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
+import com.ruoyi.purchase.pojo.PurchaseLedger;
+import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
+import com.ruoyi.quality.mapper.QualityInspectMapper;
+import com.ruoyi.quality.pojo.QualityInspect;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.stock.mapper.StockInRecordMapper;
+import com.ruoyi.stock.pojo.StockInRecord;
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.agent.tool.ToolMemoryId;
@@ -27,48 +33,52 @@
import java.math.BigDecimal;
import java.time.LocalDate;
-import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
-import java.util.Date;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Comparator;
+import java.util.*;
import java.util.stream.Collectors;
@Component
public class PurchaseAgentTools {
private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ private static final ZoneId CHINA_ZONE_ID = ZoneId.of("Asia/Shanghai");
private static final int DEFAULT_LIMIT = 10;
private static final int MAX_LIMIT = 30;
private final PurchaseLedgerMapper purchaseLedgerMapper;
- private final PaymentRegistrationMapper paymentRegistrationMapper;
- private final InvoicePurchaseMapper invoicePurchaseMapper;
private final PurchaseReturnOrdersMapper purchaseReturnOrdersMapper;
private final SalesLedgerProductMapper salesLedgerProductMapper;
private final ProcurementRecordMapper procurementRecordMapper;
private final InboundManagementMapper inboundManagementMapper;
+ private final AccountPurchasePaymentMapper accountPurchasePaymentMapper;
+ private final AccountPaymentApplicationMapper accountPaymentApplicationMapper;
+ private final AccountPurchaseInvoiceMapper accountPurchaseInvoiceMapper;
+ private final StockInRecordMapper stockInRecordMapper;
+ private final QualityInspectMapper qualityInspectMapper;
private final AiSessionUserContext aiSessionUserContext;
public PurchaseAgentTools(PurchaseLedgerMapper purchaseLedgerMapper,
- PaymentRegistrationMapper paymentRegistrationMapper,
- InvoicePurchaseMapper invoicePurchaseMapper,
PurchaseReturnOrdersMapper purchaseReturnOrdersMapper,
SalesLedgerProductMapper salesLedgerProductMapper,
ProcurementRecordMapper procurementRecordMapper,
InboundManagementMapper inboundManagementMapper,
+ AccountPurchasePaymentMapper accountPurchasePaymentMapper,
+ AccountPaymentApplicationMapper accountPaymentApplicationMapper,
+ AccountPurchaseInvoiceMapper accountPurchaseInvoiceMapper,
+ StockInRecordMapper stockInRecordMapper,
+ QualityInspectMapper qualityInspectMapper,
AiSessionUserContext aiSessionUserContext) {
this.purchaseLedgerMapper = purchaseLedgerMapper;
- this.paymentRegistrationMapper = paymentRegistrationMapper;
- this.invoicePurchaseMapper = invoicePurchaseMapper;
this.purchaseReturnOrdersMapper = purchaseReturnOrdersMapper;
this.salesLedgerProductMapper = salesLedgerProductMapper;
this.procurementRecordMapper = procurementRecordMapper;
this.inboundManagementMapper = inboundManagementMapper;
+ this.accountPurchasePaymentMapper = accountPurchasePaymentMapper;
+ this.accountPaymentApplicationMapper = accountPaymentApplicationMapper;
+ this.accountPurchaseInvoiceMapper = accountPurchaseInvoiceMapper;
+ this.stockInRecordMapper = stockInRecordMapper;
+ this.qualityInspectMapper = qualityInspectMapper;
this.aiSessionUserContext = aiSessionUserContext;
}
@@ -130,8 +140,8 @@
DateRange range = resolveDateRange(startDate, endDate, timeRange);
List<PurchaseLedger> ledgers = queryLedgers(loginUser, range);
- List<PaymentRegistration> payments = queryPayments(loginUser, range);
- List<InvoicePurchase> invoices = queryInvoices(loginUser, range);
+ List<AccountPurchasePayment> payments = queryPayments(loginUser, range);
+ List<AccountPurchaseInvoice> invoices = queryInvoices(loginUser, range);
List<PurchaseReturnOrders> returns = queryReturns(loginUser, range);
BigDecimal contractAmount = ledgers.stream()
@@ -139,11 +149,11 @@
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal paymentAmount = payments.stream()
- .map(PaymentRegistration::getCurrentPaymentAmount)
+ .map(AccountPurchasePayment::getPaymentAmount)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal invoiceAmount = invoices.stream()
- .map(InvoicePurchase::getInvoiceAmount)
+ .map(this::invoiceAmountOf)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal returnAmount = returns.stream()
@@ -279,15 +289,37 @@
@P(value = "杩斿洖鏉℃暟锛岄粯璁�10锛屾渶澶�30", required = false) Integer limit) {
LoginUser loginUser = currentLoginUser(memoryId);
DateRange range = resolveDateRange(startDate, endDate, null);
- List<Map<String, Object>> items = queryLedgers(loginUser, range).stream()
+ List<PurchaseLedger> matchedLedgers = queryLedgers(loginUser, range).stream()
.filter(ledger -> matchLedgerKeyword(ledger, keyword))
- .map(ledger -> toPendingPaymentItem(loginUser, ledger))
+ .collect(Collectors.toList());
+ Map<Long, BigDecimal> paidAmountByLedgerId = sumPaymentAmountByLedgerId(loginUser, matchedLedgers.stream()
+ .map(PurchaseLedger::getId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList()));
+ List<Map<String, Object>> items = matchedLedgers.stream()
+ .map(ledger -> toPendingPaymentItem(ledger, paidAmountByLedgerId.getOrDefault(ledger.getId(), BigDecimal.ZERO)))
.filter(Objects::nonNull)
.sorted(Comparator.comparing(item -> (BigDecimal) item.get("pendingAmount"), Comparator.reverseOrder()))
.limit(normalizeLimit(limit))
.collect(Collectors.toList());
+
+ BigDecimal totalContractAmount = items.stream()
+ .map(item -> asBigDecimal(item.get("contractAmount")))
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal totalPaidAmount = items.stream()
+ .map(item -> asBigDecimal(item.get("paidAmount")))
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal totalPendingAmount = items.stream()
+ .map(item -> asBigDecimal(item.get("pendingAmount")))
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ Map<String, Object> summary = rangeSummary(range, items.size());
+ summary.put("pendingOrderCount", items.size());
+ summary.put("totalContractAmount", totalContractAmount);
+ summary.put("totalPaidAmount", totalPaidAmount);
+ summary.put("totalPendingAmount", totalPendingAmount);
+
return jsonResponse(true, "purchase_pending_payment_list", "宸茶繑鍥炲緟浠樻閲囪喘鍗曘��",
- rangeSummary(range, items.size()), Map.of("items", items), Map.of());
+ summary, Map.of("items", items), Map.of());
}
@Tool(name = "鏌ヨ閲囪喘閫�璐ф儏鍐�", value = "鎸夋椂闂磋寖鍥存煡璇㈤噰璐��璐у崟鍒楄〃鍜岄��璐ч噾棰濄��")
@@ -406,27 +438,58 @@
return map;
}
- private Map<String, Object> toPendingPaymentItem(LoginUser loginUser, PurchaseLedger ledger) {
+ private Map<String, Object> toPendingPaymentItem(PurchaseLedger ledger, BigDecimal paidAmount) {
BigDecimal contractAmount = defaultDecimal(ledger.getContractAmount());
- BigDecimal paidAmount = sumPaymentAmount(loginUser, ledger.getId());
- BigDecimal pendingAmount = contractAmount.subtract(paidAmount);
+ BigDecimal safePaidAmount = defaultDecimal(paidAmount);
+ BigDecimal pendingAmount = contractAmount.subtract(safePaidAmount);
if (pendingAmount.compareTo(BigDecimal.ZERO) <= 0) {
return null;
}
Map<String, Object> item = toLedgerItem(ledger);
- item.put("paidAmount", paidAmount);
+ item.put("paidAmount", safePaidAmount);
item.put("pendingAmount", pendingAmount);
return item;
}
- private BigDecimal sumPaymentAmount(LoginUser loginUser, Long purchaseLedgerId) {
- LambdaQueryWrapper<PaymentRegistration> wrapper = new LambdaQueryWrapper<>();
- applyTenantFilter(wrapper, loginUser.getTenantId(), PaymentRegistration::getTenantId);
- wrapper.eq(PaymentRegistration::getPurchaseLedgerId, purchaseLedgerId);
- return defaultList(paymentRegistrationMapper.selectList(wrapper)).stream()
- .map(PaymentRegistration::getCurrentPaymentAmount)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
+ private Map<Long, BigDecimal> sumPaymentAmountByLedgerId(LoginUser loginUser, List<Long> purchaseLedgerIds) {
+ if (purchaseLedgerIds == null || purchaseLedgerIds.isEmpty()) {
+ return Map.of();
+ }
+ List<AccountPurchasePayment> payments = queryPayments(loginUser);
+ if (payments.isEmpty()) {
+ return Map.of();
+ }
+
+ Map<Integer, AccountPaymentApplication> applicationById = queryPaymentApplications(payments);
+ if (applicationById.isEmpty()) {
+ return Map.of();
+ }
+
+ Map<Long, StockInRecord> stockInRecordById = queryStockInRecords(applicationById.values());
+ Map<Long, Long> purchaseLedgerIdByQualityInspectId = queryPurchaseLedgerIdByQualityInspectId(stockInRecordById.values());
+ Set<Long> targetLedgerIdSet = new HashSet<>(purchaseLedgerIds);
+ Map<Long, BigDecimal> result = new HashMap<>();
+
+ for (AccountPurchasePayment payment : payments) {
+ if (payment.getAccountPaymentApplicationId() == null) {
+ continue;
+ }
+ AccountPaymentApplication application = applicationById.get(payment.getAccountPaymentApplicationId());
+ if (application == null) {
+ continue;
+ }
+ Set<Long> ledgerIds = resolvePurchaseLedgerIds(application, stockInRecordById, purchaseLedgerIdByQualityInspectId);
+ if (ledgerIds.isEmpty()) {
+ continue;
+ }
+ BigDecimal amount = defaultDecimal(payment.getPaymentAmount());
+ for (Long ledgerId : ledgerIds) {
+ if (targetLedgerIdSet.contains(ledgerId)) {
+ result.merge(ledgerId, amount, BigDecimal::add);
+ }
+ }
+ }
+ return result;
}
private Map<String, Object> toReturnItem(PurchaseReturnOrders item) {
@@ -446,21 +509,141 @@
return value == null ? BigDecimal.ZERO : value;
}
- private List<PaymentRegistration> queryPayments(LoginUser loginUser, DateRange range) {
- LambdaQueryWrapper<PaymentRegistration> wrapper = new LambdaQueryWrapper<>();
- applyTenantFilter(wrapper, loginUser.getTenantId(), PaymentRegistration::getTenantId);
- wrapper.ge(PaymentRegistration::getPaymentDate, toDate(range.start()))
- .lt(PaymentRegistration::getPaymentDate, toExclusiveEndDate(range.end()));
- return defaultList(paymentRegistrationMapper.selectList(wrapper));
+ private BigDecimal asBigDecimal(Object value) {
+ if (value == null) {
+ return BigDecimal.ZERO;
+ }
+ if (value instanceof BigDecimal decimal) {
+ return decimal;
+ }
+ if (value instanceof Number number) {
+ return new BigDecimal(String.valueOf(number));
+ }
+ try {
+ return new BigDecimal(String.valueOf(value));
+ } catch (Exception ignored) {
+ return BigDecimal.ZERO;
+ }
}
- private List<InvoicePurchase> queryInvoices(LoginUser loginUser, DateRange range) {
- LambdaQueryWrapper<InvoicePurchase> wrapper = new LambdaQueryWrapper<>();
- applyTenantFilter(wrapper, loginUser.getTenantId(), InvoicePurchase::getTenantId);
- wrapper.ge(InvoicePurchase::getIssueDate, range.start())
- .le(InvoicePurchase::getIssueDate, range.end());
- return defaultList(invoicePurchaseMapper.selectList(wrapper));
+ private BigDecimal invoiceAmountOf(AccountPurchaseInvoice invoice) {
+ if (invoice == null) {
+ return BigDecimal.ZERO;
+ }
+ BigDecimal amount = defaultDecimal(invoice.getTaxInclusivePrice());
+ if (amount.compareTo(BigDecimal.ZERO) > 0) {
+ return amount;
+ }
+ return defaultDecimal(invoice.getTaxExclusivelPrice()).add(defaultDecimal(invoice.getTaxPrice()));
}
+
+ private List<AccountPurchasePayment> queryPayments(LoginUser loginUser, DateRange range) {
+ LambdaQueryWrapper<AccountPurchasePayment> wrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), AccountPurchasePayment::getDeptId);
+ wrapper.ge(AccountPurchasePayment::getPaymentDate, range.start())
+ .le(AccountPurchasePayment::getPaymentDate, range.end())
+ .orderByDesc(AccountPurchasePayment::getPaymentDate, AccountPurchasePayment::getId);
+ return defaultList(accountPurchasePaymentMapper.selectList(wrapper));
+ }
+
+ private List<AccountPurchasePayment> queryPayments(LoginUser loginUser) {
+ LambdaQueryWrapper<AccountPurchasePayment> wrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), AccountPurchasePayment::getDeptId);
+ return defaultList(accountPurchasePaymentMapper.selectList(wrapper));
+ }
+
+ private List<AccountPurchaseInvoice> queryInvoices(LoginUser loginUser, DateRange range) {
+ LambdaQueryWrapper<AccountPurchaseInvoice> wrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), AccountPurchaseInvoice::getDeptId);
+ wrapper.ge(AccountPurchaseInvoice::getIssueDate, range.start())
+ .le(AccountPurchaseInvoice::getIssueDate, range.end())
+ .orderByDesc(AccountPurchaseInvoice::getIssueDate, AccountPurchaseInvoice::getId);
+ return defaultList(accountPurchaseInvoiceMapper.selectList(wrapper));
+ }
+
+ private Map<Integer, AccountPaymentApplication> queryPaymentApplications(List<AccountPurchasePayment> payments) {
+ List<Integer> ids = payments.stream()
+ .map(AccountPurchasePayment::getAccountPaymentApplicationId)
+ .filter(Objects::nonNull)
+ .distinct()
+ .collect(Collectors.toList());
+ if (ids.isEmpty()) {
+ return Map.of();
+ }
+ return defaultList(accountPaymentApplicationMapper.selectBatchIds(ids)).stream()
+ .filter(item -> item.getId() != null)
+ .collect(Collectors.toMap(AccountPaymentApplication::getId, item -> item, (a, b) -> a));
+ }
+
+ private Map<Long, StockInRecord> queryStockInRecords(Collection<AccountPaymentApplication> applications) {
+ Set<Long> stockInRecordIds = new HashSet<>();
+ for (AccountPaymentApplication application : applications) {
+ stockInRecordIds.addAll(parseLongIds(application.getStockInRecordIds()));
+ }
+ if (stockInRecordIds.isEmpty()) {
+ return Map.of();
+ }
+ return defaultList(stockInRecordMapper.selectBatchIds(stockInRecordIds)).stream()
+ .filter(item -> item.getId() != null)
+ .collect(Collectors.toMap(StockInRecord::getId, item -> item, (a, b) -> a));
+ }
+
+ private Map<Long, Long> queryPurchaseLedgerIdByQualityInspectId(Collection<StockInRecord> stockInRecords) {
+ Set<Long> qualityInspectIds = stockInRecords.stream()
+ .filter(Objects::nonNull)
+ .filter(item -> item.getRecordId() != null && "10".equals(safe(item.getRecordType()).trim()))
+ .map(StockInRecord::getRecordId)
+ .collect(Collectors.toSet());
+ if (qualityInspectIds.isEmpty()) {
+ return Map.of();
+ }
+ return defaultList(qualityInspectMapper.selectBatchIds(qualityInspectIds)).stream()
+ .filter(item -> item.getId() != null && item.getPurchaseLedgerId() != null)
+ .collect(Collectors.toMap(QualityInspect::getId, QualityInspect::getPurchaseLedgerId, (a, b) -> a));
+ }
+
+ private Set<Long> resolvePurchaseLedgerIds(AccountPaymentApplication application,
+ Map<Long, StockInRecord> stockInRecordById,
+ Map<Long, Long> purchaseLedgerIdByQualityInspectId) {
+ Set<Long> result = new LinkedHashSet<>();
+ for (Long stockInRecordId : parseLongIds(application.getStockInRecordIds())) {
+ StockInRecord stockInRecord = stockInRecordById.get(stockInRecordId);
+ if (stockInRecord == null || stockInRecord.getRecordId() == null) {
+ continue;
+ }
+ if (stockInRecord.getApprovalStatus() != null && stockInRecord.getApprovalStatus() != 1) {
+ continue;
+ }
+ String recordType = safe(stockInRecord.getRecordType()).trim();
+ if ("7".equals(recordType)) {
+ result.add(stockInRecord.getRecordId());
+ } else if ("10".equals(recordType)) {
+ Long purchaseLedgerId = purchaseLedgerIdByQualityInspectId.get(stockInRecord.getRecordId());
+ if (purchaseLedgerId != null) {
+ result.add(purchaseLedgerId);
+ }
+ }
+ }
+ return result;
+ }
+
+ private List<Long> parseLongIds(String raw) {
+ if (!StringUtils.hasText(raw)) {
+ return List.of();
+ }
+ List<Long> result = new ArrayList<>();
+ for (String part : raw.split(",")) {
+ if (!StringUtils.hasText(part)) {
+ continue;
+ }
+ try {
+ result.add(Long.parseLong(part.trim()));
+ } catch (Exception ignored) {
+ }
+ }
+ return result;
+ }
+
private List<PurchaseReturnOrders> queryReturns(LoginUser loginUser, DateRange range) {
LambdaQueryWrapper<PurchaseReturnOrders> wrapper = new LambdaQueryWrapper<>();
@@ -484,7 +667,7 @@
}
private DateRange resolveDateRange(String startDate, String endDate, String timeRange) {
- LocalDate today = LocalDate.now();
+ LocalDate today = LocalDate.now(CHINA_ZONE_ID);
LocalDate start = parseLocalDate(startDate);
LocalDate end = parseLocalDate(endDate);
if (start != null || end != null) {
@@ -501,6 +684,22 @@
return new DateRange(today.minusDays(29), today, "杩�30澶�");
}
String text = timeRange.trim();
+ if (text.contains("浠婂ぉ")) {
+ return new DateRange(today, today, "浠婂ぉ");
+ }
+ if (text.contains("鏄ㄥぉ")) {
+ LocalDate yesterday = today.minusDays(1);
+ return new DateRange(yesterday, yesterday, "鏄ㄥぉ");
+ }
+ if (text.contains("鏈懆")) {
+ LocalDate startOfWeek = today.minusDays(today.getDayOfWeek().getValue() - 1L);
+ return new DateRange(startOfWeek, today, "鏈懆");
+ }
+ if (text.contains("涓婂懆")) {
+ LocalDate thisWeekStart = today.minusDays(today.getDayOfWeek().getValue() - 1L);
+ LocalDate startOfLastWeek = thisWeekStart.minusWeeks(1);
+ return new DateRange(startOfLastWeek, startOfLastWeek.plusDays(6), "涓婂懆");
+ }
if (text.contains("浠婂勾") || text.contains("鏈勾")) {
return new DateRange(today.withDayOfYear(1), today, "浠婂勾");
}
@@ -538,7 +737,11 @@
if (!StringUtils.hasText(text)) {
return null;
}
- return LocalDate.parse(text.trim(), DATE_FMT);
+ try {
+ return LocalDate.parse(text.trim(), DATE_FMT);
+ } catch (Exception ignored) {
+ return null;
+ }
}
private Date toDate(LocalDate localDate) {
diff --git a/src/main/java/com/ruoyi/ai/tools/SalesAgentTools.java b/src/main/java/com/ruoyi/ai/tools/SalesAgentTools.java
index b56144b..0f7e586 100644
--- a/src/main/java/com/ruoyi/ai/tools/SalesAgentTools.java
+++ b/src/main/java/com/ruoyi/ai/tools/SalesAgentTools.java
@@ -3,24 +3,22 @@
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
-import com.ruoyi.account.mapper.SalesReceiptReturnMapper;
-import com.ruoyi.account.pojo.SalesReceiptReturn;
+import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper;
+import com.ruoyi.account.pojo.sales.AccountSalesCollection;
import com.ruoyi.ai.context.AiSessionUserContext;
import com.ruoyi.basic.dto.CustomerDto;
import com.ruoyi.basic.mapper.CustomerMapper;
import com.ruoyi.basic.vo.CustomerVo;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.security.LoginUser;
-import com.ruoyi.sales.dto.InvoiceLedgerDto;
-import com.ruoyi.sales.mapper.InvoiceLedgerMapper;
-import com.ruoyi.sales.mapper.ReceiptPaymentMapper;
import com.ruoyi.sales.mapper.SalesLedgerMapper;
import com.ruoyi.sales.mapper.SalesQuotationMapper;
import com.ruoyi.sales.mapper.ShippingInfoMapper;
-import com.ruoyi.sales.pojo.ReceiptPayment;
import com.ruoyi.sales.pojo.SalesLedger;
import com.ruoyi.sales.pojo.SalesQuotation;
import com.ruoyi.sales.pojo.ShippingInfo;
+import com.ruoyi.stock.mapper.StockOutRecordMapper;
+import com.ruoyi.stock.pojo.StockOutRecord;
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.agent.tool.ToolMemoryId;
@@ -34,16 +32,7 @@
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -62,26 +51,23 @@
private final SalesLedgerMapper salesLedgerMapper;
private final SalesQuotationMapper salesQuotationMapper;
private final ShippingInfoMapper shippingInfoMapper;
- private final ReceiptPaymentMapper receiptPaymentMapper;
- private final InvoiceLedgerMapper invoiceLedgerMapper;
- private final SalesReceiptReturnMapper salesReceiptReturnMapper;
+ private final AccountSalesCollectionMapper accountSalesCollectionMapper;
+ private final StockOutRecordMapper stockOutRecordMapper;
private final AiSessionUserContext aiSessionUserContext;
public SalesAgentTools(CustomerMapper customerMapper,
SalesLedgerMapper salesLedgerMapper,
SalesQuotationMapper salesQuotationMapper,
ShippingInfoMapper shippingInfoMapper,
- ReceiptPaymentMapper receiptPaymentMapper,
- InvoiceLedgerMapper invoiceLedgerMapper,
- SalesReceiptReturnMapper salesReceiptReturnMapper,
+ AccountSalesCollectionMapper accountSalesCollectionMapper,
+ StockOutRecordMapper stockOutRecordMapper,
AiSessionUserContext aiSessionUserContext) {
this.customerMapper = customerMapper;
this.salesLedgerMapper = salesLedgerMapper;
this.salesQuotationMapper = salesQuotationMapper;
this.shippingInfoMapper = shippingInfoMapper;
- this.receiptPaymentMapper = receiptPaymentMapper;
- this.invoiceLedgerMapper = invoiceLedgerMapper;
- this.salesReceiptReturnMapper = salesReceiptReturnMapper;
+ this.accountSalesCollectionMapper = accountSalesCollectionMapper;
+ this.stockOutRecordMapper = stockOutRecordMapper;
this.aiSessionUserContext = aiSessionUserContext;
}
@@ -261,36 +247,35 @@
@P(value = "杩斿洖鏉℃暟锛岄粯璁�10锛屾渶澶�30", required = false) Integer limit) {
LoginUser loginUser = currentLoginUser(memoryId);
DateRange range = resolveDateRange(startDate, endDate, null);
- LambdaQueryWrapper<SalesReceiptReturn> wrapper = new LambdaQueryWrapper<>();
- applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), SalesReceiptReturn::getDeptId);
+ LambdaQueryWrapper<AccountSalesCollection> wrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), AccountSalesCollection::getDeptId);
if (StringUtils.hasText(keyword)) {
- wrapper.and(w -> w.like(SalesReceiptReturn::getRefundId, keyword)
- .or().like(SalesReceiptReturn::getTransactionNo, keyword)
- .or().like(SalesReceiptReturn::getPaymentAccountName, keyword));
+ wrapper.and(w -> w.like(AccountSalesCollection::getCollectionNumber, keyword)
+ .or().like(AccountSalesCollection::getCollectionMethod, keyword)
+ .or().like(AccountSalesCollection::getRemark, keyword));
}
- wrapper.ge(SalesReceiptReturn::getCreateTime, range.start().atStartOfDay())
- .le(SalesReceiptReturn::getCreateTime, range.end().atTime(23, 59, 59))
- .orderByDesc(SalesReceiptReturn::getCreateTime, SalesReceiptReturn::getId)
+ wrapper.ge(AccountSalesCollection::getCollectionDate, range.start())
+ .le(AccountSalesCollection::getCollectionDate, range.end())
+ .orderByDesc(AccountSalesCollection::getCollectionDate, AccountSalesCollection::getId)
.last("limit " + normalizeLimit(limit));
- List<SalesReceiptReturn> rows = defaultList(salesReceiptReturnMapper.selectList(wrapper));
+ List<AccountSalesCollection> rows = defaultList(accountSalesCollectionMapper.selectList(wrapper));
BigDecimal returnAmount = rows.stream()
- .map(SalesReceiptReturn::getActualAmount)
+ .map(AccountSalesCollection::getCollectionAmount)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
List<Map<String, Object>> items = rows.stream().map(item -> {
Map<String, Object> map = new LinkedHashMap<>();
map.put("id", item.getId());
- map.put("refundId", safe(item.getRefundId()));
- map.put("paymentAccount", safe(item.getPaymentAccount()));
- map.put("paymentAccountName", safe(item.getPaymentAccountName()));
- map.put("paymentMethod", item.getPaymentMethod());
- map.put("actualAmount", item.getActualAmount());
- map.put("fee", item.getFee());
- map.put("discountAmount", item.getDiscountAmount());
- map.put("transactionNo", safe(item.getTransactionNo()));
- map.put("createTime", formatDateTime(item.getCreateTime()));
+ map.put("refundId", safe(item.getCollectionNumber()));
+ map.put("collectionNumber", safe(item.getCollectionNumber()));
+ map.put("paymentMethod", safe(item.getCollectionMethod()));
+ map.put("actualAmount", item.getCollectionAmount());
+ map.put("collectionAmount", item.getCollectionAmount());
+ map.put("customerId", item.getCustomerId());
+ map.put("remark", safe(item.getRemark()));
+ map.put("createTime", formatDate(item.getCollectionDate()));
return map;
}).collect(Collectors.toList());
@@ -307,55 +292,59 @@
@P(value = "杩斿洖鏉℃暟锛岄粯璁�10锛屾渶澶�30", required = false) Integer limit) {
LoginUser loginUser = currentLoginUser(memoryId);
DateRange range = resolveDateRange(startDate, endDate, null);
- LambdaQueryWrapper<ReceiptPayment> wrapper = new LambdaQueryWrapper<>();
- applyTenantFilter(wrapper, loginUser.getTenantId(), ReceiptPayment::getTenantId);
- applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ReceiptPayment::getDeptId);
- wrapper.ge(ReceiptPayment::getReceiptPaymentDate, range.start())
- .le(ReceiptPayment::getReceiptPaymentDate, range.end())
- .orderByDesc(ReceiptPayment::getReceiptPaymentDate, ReceiptPayment::getId);
- List<ReceiptPayment> payments = defaultList(receiptPaymentMapper.selectList(wrapper));
- if (payments.isEmpty()) {
- return jsonResponse(true, "sales_customer_interaction_list", "鏈煡璇㈠埌瀹㈡埛寰�鏉ヨ褰�", rangeSummary(range, 0, keyword), Map.of("items", List.of()), Map.of());
+ List<AccountSalesCollection> collections = queryCollections(loginUser, range);
+ if (collections.isEmpty()) {
+ return jsonResponse(true, "sales_customer_interaction_list", "no_customer_interactions", rangeSummary(range, 0, keyword), Map.of("items", List.of()), Map.of());
}
- List<Long> ledgerIds = payments.stream()
- .map(ReceiptPayment::getSalesLedgerId)
- .filter(Objects::nonNull)
- .distinct()
- .collect(Collectors.toList());
+ Map<Integer, Set<Long>> ledgerIdsByCollectionId = mapCollectionLedgerIds(loginUser, collections);
+ Set<Long> ledgerIds = ledgerIdsByCollectionId.values().stream()
+ .flatMap(Collection::stream)
+ .collect(Collectors.toSet());
Map<Long, SalesLedger> ledgerMap = defaultList(salesLedgerMapper.selectBatchIds(ledgerIds)).stream()
.filter(ledger -> tenantMatched(ledger.getTenantId(), loginUser.getTenantId()))
.collect(Collectors.toMap(SalesLedger::getId, item -> item, (a, b) -> a, LinkedHashMap::new));
- List<ReceiptPayment> filtered = payments.stream()
- .filter(item -> matchInteractionKeyword(item, ledgerMap.get(item.getSalesLedgerId()), keyword))
- .limit(normalizeLimit(limit))
- .collect(Collectors.toList());
+ int finalLimit = normalizeLimit(limit);
+ List<Map<String, Object>> items = new ArrayList<>();
+ for (AccountSalesCollection collection : collections) {
+ Set<Long> relatedLedgerIds = ledgerIdsByCollectionId.get(collection.getId());
+ if (relatedLedgerIds == null || relatedLedgerIds.isEmpty()) {
+ if (!matchInteractionKeyword(collection, null, keyword)) {
+ continue;
+ }
+ items.add(toInteractionItem(collection, null));
+ if (items.size() >= finalLimit) {
+ break;
+ }
+ continue;
+ }
+ for (Long ledgerId : relatedLedgerIds) {
+ SalesLedger ledger = ledgerMap.get(ledgerId);
+ if (ledger == null || !matchInteractionKeyword(collection, ledger, keyword)) {
+ continue;
+ }
+ items.add(toInteractionItem(collection, ledger));
+ if (items.size() >= finalLimit) {
+ break;
+ }
+ }
+ if (items.size() >= finalLimit) {
+ break;
+ }
+ }
- BigDecimal totalReceiptAmount = filtered.stream()
- .map(ReceiptPayment::getReceiptPaymentAmount)
- .filter(Objects::nonNull)
+ BigDecimal totalReceiptAmount = items.stream()
+ .map(item -> asBigDecimal(item.get("receiptPaymentAmount")))
.reduce(BigDecimal.ZERO, BigDecimal::add);
-
- List<Map<String, Object>> items = filtered.stream().map(item -> {
- SalesLedger ledger = ledgerMap.get(item.getSalesLedgerId());
- Map<String, Object> map = new LinkedHashMap<>();
- map.put("id", item.getId());
- map.put("salesLedgerId", item.getSalesLedgerId());
- map.put("salesContractNo", ledger == null ? "" : safe(ledger.getSalesContractNo()));
- map.put("customerName", ledger == null ? "" : safe(ledger.getCustomerName()));
- map.put("projectName", ledger == null ? "" : safe(ledger.getProjectName()));
- map.put("receiptPaymentDate", formatDate(item.getReceiptPaymentDate()));
- map.put("receiptPaymentAmount", item.getReceiptPaymentAmount());
- map.put("receiptPaymentType", safe(item.getReceiptPaymentType()));
- map.put("registrant", safe(item.getRegistrant()));
- return map;
- }).collect(Collectors.toList());
-
Map<String, Object> summary = rangeSummary(range, items.size(), keyword);
summary.put("totalReceiptAmount", totalReceiptAmount);
- summary.put("customerCount", items.stream().map(item -> String.valueOf(item.get("customerName"))).filter(StringUtils::hasText).distinct().count());
- return jsonResponse(true, "sales_customer_interaction_list", "宸茶繑鍥炲鎴峰線鏉ユ槑缁�", summary, Map.of("items", items), Map.of());
+ summary.put("customerCount", items.stream()
+ .map(item -> String.valueOf(item.get("customerName")))
+ .filter(StringUtils::hasText)
+ .distinct()
+ .count());
+ return jsonResponse(true, "sales_customer_interaction_list", "ok", summary, Map.of("items", items), Map.of());
}
@Tool(name = "鏌ヨ鍙戣揣鍙拌处", value = "鎸夊叧閿瘝鍜屾椂闂磋寖鍥存煡璇㈠彂璐у彴璐�")
@@ -426,7 +415,7 @@
List<SalesLedger> ledgers = querySalesLedgers(loginUser, range);
List<SalesQuotation> quotations = querySalesQuotations(loginUser, range);
List<ShippingInfo> shippings = queryShippings(loginUser, range);
- List<ReceiptPayment> receipts = queryReceipts(loginUser, range);
+
BigDecimal contractAmountTotal = ledgers.stream()
.map(SalesLedger::getContractAmount)
@@ -436,11 +425,6 @@
.map(SalesQuotation::getTotalAmount)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
- BigDecimal receivedAmountTotal = receipts.stream()
- .map(ReceiptPayment::getReceiptPaymentAmount)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- BigDecimal pendingAmountTotal = maxZero(contractAmountTotal.subtract(receivedAmountTotal));
long shippingCount = shippings.size();
long shippedCount = shippings.stream().filter(item -> isShippedStatus(item.getStatus())).count();
@@ -460,11 +444,12 @@
summary.put("shipRate", shipRate);
summary.put("contractAmountTotal", contractAmountTotal);
summary.put("quotationAmountTotal", quotationAmountTotal);
- summary.put("receivedAmountTotal", receivedAmountTotal);
- summary.put("pendingAmountTotal", pendingAmountTotal);
+ summary.put("receivedAmountTotal", BigDecimal.ZERO);
+ summary.put("pendingAmountTotal", BigDecimal.ZERO);
Map<String, Object> charts = new LinkedHashMap<>();
- charts.put("amountBarOption", buildAmountBarOption(contractAmountTotal, quotationAmountTotal, receivedAmountTotal, pendingAmountTotal));
+// charts.put("amountBarOption", buildAmountBarOption(contractAmountTotal, quotationAmountTotal, receivedAmountTotal, pendingAmountTotal));
+ charts.put("amountBarOption", buildAmountBarOption(contractAmountTotal, quotationAmountTotal, BigDecimal.ONE, BigDecimal.ONE));
charts.put("shippingPieOption", buildShippingPieOption(shippedCount, Math.max(shippingCount - shippedCount, 0)));
charts.put("customerTopBarOption", buildCustomerTopBarOption(topCustomers));
charts.put("contractTrendLineOption", buildContractTrendLineOption(trendData.labels(), trendData.values()));
@@ -858,28 +843,6 @@
return defaultList(shippingInfoMapper.selectList(wrapper));
}
- private List<ReceiptPayment> queryReceipts(LoginUser loginUser, DateRange range) {
- LambdaQueryWrapper<ReceiptPayment> wrapper = new LambdaQueryWrapper<>();
- applyTenantFilter(wrapper, loginUser.getTenantId(), ReceiptPayment::getTenantId);
- applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ReceiptPayment::getDeptId);
- if (range != null) {
- wrapper.ge(ReceiptPayment::getReceiptPaymentDate, range.start())
- .le(ReceiptPayment::getReceiptPaymentDate, range.end());
- }
- return defaultList(receiptPaymentMapper.selectList(wrapper));
- }
-
- private List<ReceiptPayment> queryReceiptsByLedgerIds(LoginUser loginUser, List<Long> ledgerIds) {
- if (ledgerIds == null || ledgerIds.isEmpty()) {
- return List.of();
- }
- LambdaQueryWrapper<ReceiptPayment> wrapper = new LambdaQueryWrapper<>();
- applyTenantFilter(wrapper, loginUser.getTenantId(), ReceiptPayment::getTenantId);
- applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ReceiptPayment::getDeptId);
- wrapper.in(ReceiptPayment::getSalesLedgerId, ledgerIds);
- return defaultList(receiptPaymentMapper.selectList(wrapper));
- }
-
private List<ShippingInfo> queryShippingsByLedgerIds(LoginUser loginUser, List<Long> ledgerIds) {
if (ledgerIds == null || ledgerIds.isEmpty()) {
return List.of();
@@ -896,24 +859,213 @@
return Map.of();
}
Map<Long, BigDecimal> result = new HashMap<>();
- for (InvoiceLedgerDto item : defaultList(invoiceLedgerMapper.invoicedTotal(ledgerIds))) {
- if (item.getSalesLedgerId() == null) {
- continue;
- }
- result.merge(item.getSalesLedgerId().longValue(), defaultDecimal(item.getInvoiceTotal()), BigDecimal::add);
- }
return result;
}
private Map<Long, BigDecimal> sumReceiptAmounts(LoginUser loginUser, List<Long> ledgerIds) {
+ if (ledgerIds == null || ledgerIds.isEmpty()) {
+ return Map.of();
+ }
+ List<SalesLedger> ledgers = defaultList(salesLedgerMapper.selectBatchIds(ledgerIds)).stream()
+ .filter(ledger -> tenantMatched(ledger.getTenantId(), loginUser.getTenantId()))
+ .collect(Collectors.toList());
+ if (ledgers.isEmpty()) {
+ return Map.of();
+ }
+
+ Set<Integer> customerIds = ledgers.stream()
+ .map(SalesLedger::getCustomerId)
+ .filter(Objects::nonNull)
+ .map(Long::intValue)
+ .collect(Collectors.toSet());
+ if (customerIds.isEmpty()) {
+ return Map.of();
+ }
+
+ LambdaQueryWrapper<AccountSalesCollection> wrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), AccountSalesCollection::getDeptId);
+ wrapper.in(AccountSalesCollection::getCustomerId, customerIds);
+ List<AccountSalesCollection> collections = defaultList(accountSalesCollectionMapper.selectList(wrapper));
+ if (collections.isEmpty()) {
+ return Map.of();
+ }
+
+ Map<Integer, Set<Long>> ledgerIdsByCollectionId = mapCollectionLedgerIds(loginUser, collections);
+ Map<Long, List<Long>> ledgerIdsByCustomerId = ledgers.stream()
+ .filter(item -> item.getId() != null && item.getCustomerId() != null)
+ .collect(Collectors.groupingBy(item -> item.getCustomerId().longValue(),
+ Collectors.mapping(SalesLedger::getId, Collectors.toList())));
+ Set<Long> targetLedgerIdSet = new HashSet<>(ledgerIds);
+
Map<Long, BigDecimal> result = new HashMap<>();
- for (ReceiptPayment item : queryReceiptsByLedgerIds(loginUser, ledgerIds)) {
- if (item.getSalesLedgerId() == null) {
+ for (AccountSalesCollection collection : collections) {
+ BigDecimal amount = defaultDecimal(collection.getCollectionAmount());
+ if (amount.compareTo(BigDecimal.ZERO) == 0) {
continue;
}
- result.merge(item.getSalesLedgerId(), defaultDecimal(item.getReceiptPaymentAmount()), BigDecimal::add);
+ Set<Long> relatedLedgerIds = ledgerIdsByCollectionId.getOrDefault(collection.getId(), Set.of());
+ if (!relatedLedgerIds.isEmpty()) {
+ for (Long ledgerId : relatedLedgerIds) {
+ if (targetLedgerIdSet.contains(ledgerId)) {
+ result.merge(ledgerId, amount, BigDecimal::add);
+ }
+ }
+ continue;
+ }
+ if (collection.getCustomerId() == null) {
+ continue;
+ }
+ List<Long> customerLedgerIds = ledgerIdsByCustomerId.get(collection.getCustomerId().longValue());
+ if (customerLedgerIds == null || customerLedgerIds.isEmpty()) {
+ continue;
+ }
+ for (Long ledgerId : customerLedgerIds) {
+ if (targetLedgerIdSet.contains(ledgerId)) {
+ result.merge(ledgerId, amount, BigDecimal::add);
+ }
+ }
}
return result;
+ }
+
+ private List<AccountSalesCollection> queryCollections(LoginUser loginUser, DateRange range) {
+ LambdaQueryWrapper<AccountSalesCollection> wrapper = new LambdaQueryWrapper<>();
+ applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), AccountSalesCollection::getDeptId);
+ if (range != null) {
+ wrapper.ge(AccountSalesCollection::getCollectionDate, range.start())
+ .le(AccountSalesCollection::getCollectionDate, range.end());
+ }
+ wrapper.orderByDesc(AccountSalesCollection::getCollectionDate, AccountSalesCollection::getId);
+ return defaultList(accountSalesCollectionMapper.selectList(wrapper));
+ }
+
+ private Map<Integer, Set<Long>> mapCollectionLedgerIds(LoginUser loginUser, List<AccountSalesCollection> collections) {
+ Map<Integer, Set<Long>> result = new HashMap<>();
+ if (collections == null || collections.isEmpty()) {
+ return result;
+ }
+
+ Map<Integer, List<Long>> stockOutRecordIdsByCollection = new HashMap<>();
+ Set<Long> allStockOutRecordIds = new HashSet<>();
+ for (AccountSalesCollection collection : collections) {
+ if (collection.getId() == null) {
+ continue;
+ }
+ List<Long> stockOutRecordIds = parseLongIds(collection.getStockOutRecordIds());
+ if (stockOutRecordIds.isEmpty()) {
+ continue;
+ }
+ stockOutRecordIdsByCollection.put(collection.getId(), stockOutRecordIds);
+ allStockOutRecordIds.addAll(stockOutRecordIds);
+ }
+ if (allStockOutRecordIds.isEmpty()) {
+ return result;
+ }
+
+ List<StockOutRecord> stockOutRecords = defaultList(stockOutRecordMapper.selectList(new LambdaQueryWrapper<StockOutRecord>()
+ .in(StockOutRecord::getId, allStockOutRecordIds)));
+ if (stockOutRecords.isEmpty()) {
+ return result;
+ }
+ Map<Long, StockOutRecord> stockOutRecordMap = stockOutRecords.stream()
+ .filter(item -> item.getId() != null)
+ .collect(Collectors.toMap(StockOutRecord::getId, item -> item, (a, b) -> a));
+
+ Set<Long> shippingIds = stockOutRecords.stream()
+ .filter(this::isSalesOutboundRecord)
+ .map(StockOutRecord::getRecordId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+ if (shippingIds.isEmpty()) {
+ return result;
+ }
+
+ LambdaQueryWrapper<ShippingInfo> shippingWrapper = new LambdaQueryWrapper<>();
+ applyTenantFilter(shippingWrapper, loginUser.getTenantId(), ShippingInfo::getTenantId);
+ applyDeptFilter(shippingWrapper, loginUser.getCurrentDeptId(), ShippingInfo::getDeptId);
+ shippingWrapper.in(ShippingInfo::getId, shippingIds);
+ Map<Long, Long> ledgerIdByShippingId = defaultList(shippingInfoMapper.selectList(shippingWrapper)).stream()
+ .filter(item -> item.getId() != null && item.getSalesLedgerId() != null)
+ .collect(Collectors.toMap(ShippingInfo::getId, ShippingInfo::getSalesLedgerId, (a, b) -> a));
+
+ for (Map.Entry<Integer, List<Long>> entry : stockOutRecordIdsByCollection.entrySet()) {
+ Set<Long> ledgerIds = new LinkedHashSet<>();
+ for (Long stockOutRecordId : entry.getValue()) {
+ StockOutRecord stockOutRecord = stockOutRecordMap.get(stockOutRecordId);
+ if (!isSalesOutboundRecord(stockOutRecord)) {
+ continue;
+ }
+ Long ledgerId = ledgerIdByShippingId.get(stockOutRecord.getRecordId());
+ if (ledgerId != null) {
+ ledgerIds.add(ledgerId);
+ }
+ }
+ if (!ledgerIds.isEmpty()) {
+ result.put(entry.getKey(), ledgerIds);
+ }
+ }
+ return result;
+ }
+
+ private boolean isSalesOutboundRecord(StockOutRecord stockOutRecord) {
+ if (stockOutRecord == null || !StringUtils.hasText(stockOutRecord.getRecordType())) {
+ return false;
+ }
+ if (stockOutRecord.getApprovalStatus() != null && stockOutRecord.getApprovalStatus() != 1) {
+ return false;
+ }
+ return "13".equals(stockOutRecord.getRecordType().trim());
+ }
+
+ private List<Long> parseLongIds(String raw) {
+ if (!StringUtils.hasText(raw)) {
+ return List.of();
+ }
+ List<Long> result = new ArrayList<>();
+ for (String part : raw.split(",")) {
+ if (!StringUtils.hasText(part)) {
+ continue;
+ }
+ try {
+ result.add(Long.parseLong(part.trim()));
+ } catch (Exception ignored) {
+ }
+ }
+ return result;
+ }
+
+ private boolean matchInteractionKeyword(AccountSalesCollection collection, SalesLedger ledger, String keyword) {
+ if (!StringUtils.hasText(keyword)) {
+ return true;
+ }
+ String text = keyword.trim();
+ if (safe(collection.getCollectionNumber()).contains(text)
+ || safe(collection.getCollectionMethod()).contains(text)
+ || safe(collection.getRemark()).contains(text)) {
+ return true;
+ }
+ if (ledger == null) {
+ return false;
+ }
+ return safe(ledger.getSalesContractNo()).contains(text)
+ || safe(ledger.getCustomerName()).contains(text)
+ || safe(ledger.getProjectName()).contains(text);
+ }
+
+ private Map<String, Object> toInteractionItem(AccountSalesCollection collection, SalesLedger ledger) {
+ Map<String, Object> map = new LinkedHashMap<>();
+ map.put("id", collection.getId());
+ map.put("salesLedgerId", ledger == null ? null : ledger.getId());
+ map.put("salesContractNo", ledger == null ? "" : safe(ledger.getSalesContractNo()));
+ map.put("customerName", ledger == null ? "" : safe(ledger.getCustomerName()));
+ map.put("projectName", ledger == null ? "" : safe(ledger.getProjectName()));
+ map.put("receiptPaymentDate", formatDate(collection.getCollectionDate()));
+ map.put("receiptPaymentAmount", collection.getCollectionAmount());
+ map.put("receiptPaymentType", safe(collection.getCollectionMethod()));
+ map.put("collectionNumber", safe(collection.getCollectionNumber()));
+ map.put("registrant", collection.getCreateUser());
+ map.put("remark", safe(collection.getRemark()));
+ return map;
}
private boolean isLedgerFullyShipped(Long ledgerId, Map<Long, List<ShippingInfo>> shippingByLedgerId) {
@@ -952,17 +1104,6 @@
|| safe(customer.getContactPhone()).contains(text)
|| safe(customer.getCompanyPhone()).contains(text)
|| safe(customer.getUsageUserName()).contains(text);
- }
-
- private boolean matchInteractionKeyword(ReceiptPayment payment, SalesLedger ledger, String keyword) {
- if (!StringUtils.hasText(keyword)) {
- return true;
- }
- String text = keyword.trim();
- return safe(payment.getRegistrant()).contains(text)
- || (ledger != null && (safe(ledger.getCustomerName()).contains(text)
- || safe(ledger.getSalesContractNo()).contains(text)
- || safe(ledger.getProjectName()).contains(text)));
}
private boolean matchLedgerCustomerKeyword(SalesLedger ledger, String keyword) {
@@ -1150,6 +1291,23 @@
return value == null ? BigDecimal.ZERO : value;
}
+ private BigDecimal asBigDecimal(Object value) {
+ if (value == null) {
+ return BigDecimal.ZERO;
+ }
+ if (value instanceof BigDecimal decimal) {
+ return decimal;
+ }
+ if (value instanceof Number number) {
+ return new BigDecimal(String.valueOf(number));
+ }
+ try {
+ return new BigDecimal(String.valueOf(value));
+ } catch (Exception ignored) {
+ return BigDecimal.ZERO;
+ }
+ }
+
private BigDecimal maxZero(BigDecimal value) {
return value == null || value.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : value;
}
diff --git a/src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java b/src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java
new file mode 100644
index 0000000..a2df482
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java
@@ -0,0 +1,21 @@
+package com.ruoyi.approve.bean.dto;
+
+import com.ruoyi.approve.pojo.ApprovalInstance;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ApprovalInstanceDto extends ApprovalInstance {
+
+ private String approveAction;
+
+ private String approveComment;
+
+ private String createTimeEnd;
+
+ private String createTimeStart;
+
+ private List<StorageBlobDTO> storageBlobDTOs;
+}
diff --git a/src/main/java/com/ruoyi/approve/bean/dto/ApprovalTemplateDto.java b/src/main/java/com/ruoyi/approve/bean/dto/ApprovalTemplateDto.java
new file mode 100644
index 0000000..35952a5
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/dto/ApprovalTemplateDto.java
@@ -0,0 +1,12 @@
+package com.ruoyi.approve.bean.dto;
+
+import com.ruoyi.approve.pojo.ApprovalTemplate;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ApprovalTemplateDto extends ApprovalTemplate {
+
+ private List<ApprovalTemplateNodeDto> nodes;
+}
diff --git a/src/main/java/com/ruoyi/approve/bean/dto/ApprovalTemplateNodeApproverDto.java b/src/main/java/com/ruoyi/approve/bean/dto/ApprovalTemplateNodeApproverDto.java
new file mode 100644
index 0000000..8382619
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/dto/ApprovalTemplateNodeApproverDto.java
@@ -0,0 +1,8 @@
+package com.ruoyi.approve.bean.dto;
+
+import com.ruoyi.approve.pojo.ApprovalTemplateNodeApprover;
+import lombok.Data;
+
+@Data
+public class ApprovalTemplateNodeApproverDto extends ApprovalTemplateNodeApprover {
+}
diff --git a/src/main/java/com/ruoyi/approve/bean/dto/ApprovalTemplateNodeDto.java b/src/main/java/com/ruoyi/approve/bean/dto/ApprovalTemplateNodeDto.java
new file mode 100644
index 0000000..e85aee9
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/dto/ApprovalTemplateNodeDto.java
@@ -0,0 +1,12 @@
+package com.ruoyi.approve.bean.dto;
+
+import com.ruoyi.approve.pojo.ApprovalTemplateNode;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ApprovalTemplateNodeDto extends ApprovalTemplateNode {
+
+ private List<ApprovalTemplateNodeApproverDto> approvers;
+}
diff --git a/src/main/java/com/ruoyi/approve/bean/dto/FinReimbursementDto.java b/src/main/java/com/ruoyi/approve/bean/dto/FinReimbursementDto.java
new file mode 100644
index 0000000..2f14376
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/dto/FinReimbursementDto.java
@@ -0,0 +1,21 @@
+package com.ruoyi.approve.bean.dto;
+
+import com.ruoyi.approve.pojo.FinReimbursement;
+import com.ruoyi.approve.pojo.FinReimbursementDetail;
+import com.ruoyi.approve.pojo.FinReimbursementTravel;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class FinReimbursementDto extends FinReimbursement {
+
+ private String createTimeStart;
+ private String createTimeEnd;
+
+ private FinReimbursementTravel travel;
+ private List<FinReimbursementDetail> details;
+ private List<ApprovalTemplateNodeDto> nodes;
+ private List<StorageBlobDTO> storageBlobDTOs;
+}
diff --git a/src/main/java/com/ruoyi/approve/bean/vo/ApprovalInstanceVo.java b/src/main/java/com/ruoyi/approve/bean/vo/ApprovalInstanceVo.java
new file mode 100644
index 0000000..552ed0a
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/vo/ApprovalInstanceVo.java
@@ -0,0 +1,28 @@
+package com.ruoyi.approve.bean.vo;
+
+import com.ruoyi.approve.pojo.ApprovalInstance;
+import com.ruoyi.approve.pojo.ApprovalRecord;
+import com.ruoyi.approve.pojo.ApprovalTask;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ApprovalInstanceVo extends ApprovalInstance {
+ //褰撳墠鐢ㄦ埛鏄惁鍙互瀹℃壒
+ @Schema(description = "褰撳墠鐢ㄦ埛鏄惁鍙互瀹℃壒")
+ private Boolean isApprove;
+
+ //瀹℃壒娴佺▼
+ private List<ApprovalTask> tasks;
+
+ //瀹℃壒璁板綍
+ private List<ApprovalRecord> records;
+
+ @Schema(description = "涓氬姟鍚嶇О")
+ private String businessName;
+
+ private List<StorageBlobVO> storageBlobVOList;
+}
diff --git a/src/main/java/com/ruoyi/approve/bean/vo/ApprovalTemplateNodeApproverVo.java b/src/main/java/com/ruoyi/approve/bean/vo/ApprovalTemplateNodeApproverVo.java
new file mode 100644
index 0000000..4c0ce0f
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/vo/ApprovalTemplateNodeApproverVo.java
@@ -0,0 +1,9 @@
+package com.ruoyi.approve.bean.vo;
+
+
+import com.ruoyi.approve.pojo.ApprovalTemplateNodeApprover;
+import lombok.Data;
+
+@Data
+public class ApprovalTemplateNodeApproverVo extends ApprovalTemplateNodeApprover {
+}
diff --git a/src/main/java/com/ruoyi/approve/bean/vo/ApprovalTemplateNodeVo.java b/src/main/java/com/ruoyi/approve/bean/vo/ApprovalTemplateNodeVo.java
new file mode 100644
index 0000000..9acd0af
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/vo/ApprovalTemplateNodeVo.java
@@ -0,0 +1,13 @@
+package com.ruoyi.approve.bean.vo;
+
+
+import com.ruoyi.approve.pojo.ApprovalTemplateNode;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ApprovalTemplateNodeVo extends ApprovalTemplateNode {
+
+ private List<ApprovalTemplateNodeApproverVo> approvers;
+}
diff --git a/src/main/java/com/ruoyi/approve/bean/vo/ApprovalTemplateVo.java b/src/main/java/com/ruoyi/approve/bean/vo/ApprovalTemplateVo.java
new file mode 100644
index 0000000..2793293
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/vo/ApprovalTemplateVo.java
@@ -0,0 +1,14 @@
+package com.ruoyi.approve.bean.vo;
+
+import com.ruoyi.approve.pojo.ApprovalTemplate;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ApprovalTemplateVo extends ApprovalTemplate {
+
+ private List<ApprovalTemplateNodeVo> nodes;
+
+ private String createdUserName;
+}
diff --git a/src/main/java/com/ruoyi/approve/bean/vo/ApproveGetAndUpdateVo.java b/src/main/java/com/ruoyi/approve/bean/vo/ApproveGetAndUpdateVo.java
index f43ecac..4bf8d2f 100644
--- a/src/main/java/com/ruoyi/approve/bean/vo/ApproveGetAndUpdateVo.java
+++ b/src/main/java/com/ruoyi/approve/bean/vo/ApproveGetAndUpdateVo.java
@@ -9,6 +9,7 @@
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
+import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
@@ -45,6 +46,14 @@
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date endDate;
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
+ @Schema(description = "鍑哄樊寮�濮嬫椂闂�")
+ private LocalDateTime startDateTime;
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
+ @Schema(description = "鍑哄樊缁撴潫鏃堕棿")
+ private LocalDateTime endDateTime;
+
private BigDecimal price;
private String location;
diff --git a/src/main/java/com/ruoyi/approve/bean/vo/ApproveProcessVO.java b/src/main/java/com/ruoyi/approve/bean/vo/ApproveProcessVO.java
index 8c5db04..8e730ff 100644
--- a/src/main/java/com/ruoyi/approve/bean/vo/ApproveProcessVO.java
+++ b/src/main/java/com/ruoyi/approve/bean/vo/ApproveProcessVO.java
@@ -8,6 +8,7 @@
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
+import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
@@ -58,6 +59,14 @@
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date endDate;
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
+ @Schema(description = "鍑哄樊寮�濮嬫椂闂�")
+ private LocalDateTime startDateTime;
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
+ @Schema(description = "鍑哄樊缁撴潫鏃堕棿")
+ private LocalDateTime endDateTime;
+
private BigDecimal price;
private String location;
diff --git a/src/main/java/com/ruoyi/approve/bean/vo/FinReimbursementVo.java b/src/main/java/com/ruoyi/approve/bean/vo/FinReimbursementVo.java
new file mode 100644
index 0000000..5706ff3
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/vo/FinReimbursementVo.java
@@ -0,0 +1,34 @@
+package com.ruoyi.approve.bean.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.approve.pojo.*;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Data
+public class FinReimbursementVo extends FinReimbursement {
+
+
+ private String createTimeStart;
+ private String createTimeEnd;
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime startTime;
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime endTime;
+
+ private FinReimbursementTravel travel;
+ private List<FinReimbursementDetail> details;
+ //瀹℃壒娴佺▼
+ private List<ApprovalTask> tasks;
+
+ //瀹℃壒璁板綍
+ private List<ApprovalRecord> records;
+ private List<StorageBlobVO> storageBlobVOList;
+}
diff --git a/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java b/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java
new file mode 100644
index 0000000..36dcfc3
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java
@@ -0,0 +1,67 @@
+package com.ruoyi.approve.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.approve.bean.dto.ApprovalInstanceDto;
+import com.ruoyi.approve.bean.vo.ApprovalInstanceVo;
+import com.ruoyi.approve.service.ApprovalInstanceService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹℃壒瀹炰緥琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:27:46
+ */
+@RestController
+@RequestMapping("/approvalInstance")
+@Tag(name = "瀹℃壒瀹炰緥琛�")
+@AllArgsConstructor
+public class ApprovalInstanceController extends BaseController {
+
+ private final ApprovalInstanceService approvalInstanceService;
+ @GetMapping("/listPage")
+ @Operation(summary = "鍒嗛〉鏌ヨ")
+ @Log(title = "瀹℃壒鍒楄〃鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
+ public R listPage(Page<ApprovalInstanceVo> page, ApprovalInstanceDto approvalInstanceDto) {
+ return approvalInstanceService.listPage(page, approvalInstanceDto);
+ }
+
+ @PostMapping("/save")
+ @Operation(summary = "淇濆瓨")
+ @Log(title = "瀹℃壒鍒楄〃淇濆瓨", businessType = BusinessType.INSERT)
+ public R save(@RequestBody ApprovalInstanceDto approvalInstanceDto) {
+ return approvalInstanceService.add(approvalInstanceDto) ? R.ok() : R.fail();
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "鏇存柊")
+ @Log(title = "瀹℃壒鍒楄〃鏇存柊", businessType = BusinessType.UPDATE)
+ public R update(@RequestBody ApprovalInstanceDto approvalInstanceDto) {
+ return approvalInstanceService.update(approvalInstanceDto) ? R.ok() : R.fail();
+ }
+
+ @DeleteMapping("/delete")
+ @Log(title = "瀹℃壒鍒楄〃鍒犻櫎", businessType = BusinessType.DELETE)
+ @Operation(summary = "鍒犻櫎")
+ public R delete(@RequestBody List<Long> ids) {
+ return approvalInstanceService.delete(ids) ? R.ok() : R.fail();
+ }
+
+ @Operation(summary = "瀹℃壒")
+ @PostMapping("/approve")
+ @Log(title = "瀹℃壒鍒楄〃瀹℃壒", businessType = BusinessType.UPDATE)
+ public R approve(@RequestBody ApprovalInstanceDto approvalInstanceDto) {
+ return approvalInstanceService.approve(approvalInstanceDto);
+ }
+}
diff --git a/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceNodeController.java b/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceNodeController.java
new file mode 100644
index 0000000..e42af42
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceNodeController.java
@@ -0,0 +1,19 @@
+package com.ruoyi.approve.controller;
+
+import com.ruoyi.framework.web.controller.BaseController;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 瀹℃壒鑺傜偣瀹炰緥琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:27:54
+ */
+@RestController
+@RequestMapping("/approvalInstanceNode")
+public class ApprovalInstanceNodeController extends BaseController {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/controller/ApprovalRecordController.java b/src/main/java/com/ruoyi/approve/controller/ApprovalRecordController.java
new file mode 100644
index 0000000..2d6f9dd
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/controller/ApprovalRecordController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 瀹℃壒璁板綍琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:28:21
+ */
+@RestController
+@RequestMapping("/approvalRecord")
+public class ApprovalRecordController {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/controller/ApprovalTaskController.java b/src/main/java/com/ruoyi/approve/controller/ApprovalTaskController.java
new file mode 100644
index 0000000..8682caa
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/controller/ApprovalTaskController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 瀹℃壒浠诲姟琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:32:37
+ */
+@RestController
+@RequestMapping("/approvalTask")
+public class ApprovalTaskController {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/controller/ApprovalTemplateController.java b/src/main/java/com/ruoyi/approve/controller/ApprovalTemplateController.java
new file mode 100644
index 0000000..674d278
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/controller/ApprovalTemplateController.java
@@ -0,0 +1,74 @@
+package com.ruoyi.approve.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.approve.bean.dto.ApprovalTemplateDto;
+import com.ruoyi.approve.bean.vo.ApprovalTemplateVo;
+import com.ruoyi.approve.service.ApprovalTemplateService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹℃壒妯℃澘琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺嬮亾杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 11:20:08
+ */
+@RestController
+@RequestMapping("/approvalTemplate")
+@Tag(name = "瀹℃壒妯℃澘琛�")
+@AllArgsConstructor
+public class ApprovalTemplateController extends BaseController {
+
+ private final ApprovalTemplateService approvalTemplateService;
+
+ @GetMapping("/listPage")
+ @Operation(summary = "鍒嗛〉鏌ヨ")
+ @Log(title = "瀹℃壒妯℃澘鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
+ public R listPage(Page<ApprovalTemplateVo> page, ApprovalTemplateDto approvalTemplateDto) {
+ return R.ok(approvalTemplateService.listPage(page, approvalTemplateDto));
+ }
+
+ @PostMapping("/add")
+ @Operation(summary = "娣诲姞")
+ @Log(title = "娣诲姞瀹℃壒妯℃澘", businessType = BusinessType.INSERT)
+ public R add(@RequestBody ApprovalTemplateDto approvalTemplateDto) {
+ return R.ok(approvalTemplateService.saveApprovalTemplateDto(approvalTemplateDto));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "淇敼")
+ @Log(title = "淇敼瀹℃壒妯℃澘", businessType = BusinessType.UPDATE)
+ public R update(@RequestBody ApprovalTemplateDto approvalTemplateDto) {
+ return R.ok(approvalTemplateService.updateApprovalTemplateDto(approvalTemplateDto));
+ }
+
+ @PostMapping("/delete")
+ @Operation(summary = "鍒犻櫎")
+ @Log(title = "鍒犻櫎瀹℃壒妯℃澘", businessType = BusinessType.DELETE)
+ public R delete(@RequestBody List<Long> ids) {
+ return R.ok(approvalTemplateService.delete(ids));
+ }
+
+ @GetMapping("/list/{type}")
+ @Operation(summary = "鏌ヨ鎵�鏈夊鎵规ā鏉�")
+ public R list(@PathVariable("type") Integer type) {
+ return R.ok(approvalTemplateService.listApprovalTemplateVo(type));
+ }
+
+ @GetMapping("/detail/{id}")
+ @Operation(summary = "鏌ヨ瀹℃壒妯℃澘璇︽儏")
+ @Log(title = "鏌ヨ瀹℃壒妯℃澘璇︽儏", businessType = BusinessType.OTHER)
+ public R detail(@PathVariable("id") Long id) {
+ return R.ok(approvalTemplateService.getApprovalTemplateVoById(id));
+ }
+}
diff --git a/src/main/java/com/ruoyi/approve/controller/ApprovalTemplateNodeApproverController.java b/src/main/java/com/ruoyi/approve/controller/ApprovalTemplateNodeApproverController.java
new file mode 100644
index 0000000..b0e2bff
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/controller/ApprovalTemplateNodeApproverController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 瀹℃壒妯℃澘鑺傜偣瀹℃壒浜鸿〃 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 11:20:30
+ */
+@RestController
+@RequestMapping("/approvalTemplateNodeApprover")
+public class ApprovalTemplateNodeApproverController {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/controller/ApprovalTemplateNodeController.java b/src/main/java/com/ruoyi/approve/controller/ApprovalTemplateNodeController.java
new file mode 100644
index 0000000..5a1ed88
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/controller/ApprovalTemplateNodeController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 瀹℃壒妯℃澘鑺傜偣琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 11:20:19
+ */
+@RestController
+@RequestMapping("/approvalTemplateNode")
+public class ApprovalTemplateNodeController {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/controller/FinReimbursementController.java b/src/main/java/com/ruoyi/approve/controller/FinReimbursementController.java
new file mode 100644
index 0000000..a2eecdb
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/controller/FinReimbursementController.java
@@ -0,0 +1,60 @@
+package com.ruoyi.approve.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.approve.bean.dto.FinReimbursementDto;
+import com.ruoyi.approve.bean.vo.FinReimbursementVo;
+import com.ruoyi.approve.service.FinReimbursementService;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曚富琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:15
+ */
+@RestController
+@RequestMapping("/finReimbursement")
+@Tag(name = "鎶ラ攢鍗曚富琛�", description = "鎶ラ攢鍗曚富琛�")
+@AllArgsConstructor
+public class FinReimbursementController {
+
+ private final FinReimbursementService finReimbursementService;
+
+ @GetMapping("/listPage")
+ @Operation(summary = "鍒嗛〉鏌ヨ")
+ public R listPage(Page<FinReimbursementVo> page, FinReimbursementDto finReimbursementDto) {
+ return R.ok(finReimbursementService.listPage(finReimbursementDto, page));
+ }
+
+ @PostMapping("/save")
+ @Operation(summary = "淇濆瓨")
+ public R save(@RequestBody FinReimbursementDto finReimbursementDto) {
+ return R.ok(finReimbursementService.add(finReimbursementDto));
+ }
+
+ @GetMapping("/detail")
+ @Operation(summary = "璇︽儏")
+ public R detail(Long id) {
+ return R.ok(finReimbursementService.detail(id));
+ }
+
+ @PostMapping("/update")
+ @Operation(summary = "淇敼")
+ public R update(@RequestBody FinReimbursementDto finReimbursementDto) {
+ return R.ok(finReimbursementService.update(finReimbursementDto));
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "鍒犻櫎")
+ public R delete(@RequestBody List<Long> ids) {
+ return R.ok(finReimbursementService.delete(ids));
+ }
+}
diff --git a/src/main/java/com/ruoyi/approve/controller/FinReimbursementDetailController.java b/src/main/java/com/ruoyi/approve/controller/FinReimbursementDetailController.java
new file mode 100644
index 0000000..18e4f73
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/controller/FinReimbursementDetailController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曟槑缁嗚〃 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:38
+ */
+@RestController
+@RequestMapping("/finReimbursementDetail")
+public class FinReimbursementDetailController {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/controller/FinReimbursementTravelController.java b/src/main/java/com/ruoyi/approve/controller/FinReimbursementTravelController.java
new file mode 100644
index 0000000..0e67feb
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/controller/FinReimbursementTravelController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 宸梾鎶ラ攢鎵╁睍琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:47
+ */
+@RestController
+@RequestMapping("/finReimbursementTravel")
+public class FinReimbursementTravelController {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/mapper/ApprovalInstanceMapper.java b/src/main/java/com/ruoyi/approve/mapper/ApprovalInstanceMapper.java
new file mode 100644
index 0000000..a541b90
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/mapper/ApprovalInstanceMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.approve.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.approve.bean.dto.ApprovalInstanceDto;
+import com.ruoyi.approve.bean.vo.ApprovalInstanceVo;
+import com.ruoyi.approve.pojo.ApprovalInstance;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * 瀹℃壒瀹炰緥琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:27:46
+ */
+@Mapper
+public interface ApprovalInstanceMapper extends BaseMapper<ApprovalInstance> {
+
+ IPage<ApprovalInstanceVo> listPage(Page<ApprovalInstanceVo> page,@Param("ew") ApprovalInstanceDto approvalInstanceDto);
+}
diff --git a/src/main/java/com/ruoyi/approve/mapper/ApprovalInstanceNodeMapper.java b/src/main/java/com/ruoyi/approve/mapper/ApprovalInstanceNodeMapper.java
new file mode 100644
index 0000000..8787e55
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/mapper/ApprovalInstanceNodeMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.approve.pojo.ApprovalInstanceNode;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 瀹℃壒鑺傜偣瀹炰緥琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:27:54
+ */
+@Mapper
+public interface ApprovalInstanceNodeMapper extends BaseMapper<ApprovalInstanceNode> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/mapper/ApprovalRecordMapper.java b/src/main/java/com/ruoyi/approve/mapper/ApprovalRecordMapper.java
new file mode 100644
index 0000000..fcf5ec6
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/mapper/ApprovalRecordMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.approve.pojo.ApprovalRecord;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 瀹℃壒璁板綍琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:28:21
+ */
+@Mapper
+public interface ApprovalRecordMapper extends BaseMapper<ApprovalRecord> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/mapper/ApprovalTaskMapper.java b/src/main/java/com/ruoyi/approve/mapper/ApprovalTaskMapper.java
new file mode 100644
index 0000000..2531d8e
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/mapper/ApprovalTaskMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.approve.pojo.ApprovalTask;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 瀹℃壒浠诲姟琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:32:37
+ */
+@Mapper
+public interface ApprovalTaskMapper extends BaseMapper<ApprovalTask> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/mapper/ApprovalTemplateMapper.java b/src/main/java/com/ruoyi/approve/mapper/ApprovalTemplateMapper.java
new file mode 100644
index 0000000..693f4b2
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/mapper/ApprovalTemplateMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.approve.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.approve.bean.dto.ApprovalTemplateDto;
+import com.ruoyi.approve.bean.vo.ApprovalTemplateVo;
+import com.ruoyi.approve.pojo.ApprovalTemplate;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * 瀹℃壒妯℃澘琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 11:20:08
+ */
+@Mapper
+public interface ApprovalTemplateMapper extends BaseMapper<ApprovalTemplate> {
+
+ IPage<ApprovalTemplateVo> listPage(Page<ApprovalTemplateVo> page,@Param("ew") ApprovalTemplateDto approvalTemplateDto);
+}
diff --git a/src/main/java/com/ruoyi/approve/mapper/ApprovalTemplateNodeApproverMapper.java b/src/main/java/com/ruoyi/approve/mapper/ApprovalTemplateNodeApproverMapper.java
new file mode 100644
index 0000000..d96f1e3
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/mapper/ApprovalTemplateNodeApproverMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.approve.pojo.ApprovalTemplateNodeApprover;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 瀹℃壒妯℃澘鑺傜偣瀹℃壒浜鸿〃 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 11:20:30
+ */
+@Mapper
+public interface ApprovalTemplateNodeApproverMapper extends BaseMapper<ApprovalTemplateNodeApprover> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/mapper/ApprovalTemplateNodeMapper.java b/src/main/java/com/ruoyi/approve/mapper/ApprovalTemplateNodeMapper.java
new file mode 100644
index 0000000..dc4a67f
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/mapper/ApprovalTemplateNodeMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.approve.pojo.ApprovalTemplateNode;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 瀹℃壒妯℃澘鑺傜偣琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 11:20:19
+ */
+@Mapper
+public interface ApprovalTemplateNodeMapper extends BaseMapper<ApprovalTemplateNode> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/mapper/FinReimbursementDetailMapper.java b/src/main/java/com/ruoyi/approve/mapper/FinReimbursementDetailMapper.java
new file mode 100644
index 0000000..edc039a
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/mapper/FinReimbursementDetailMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.approve.pojo.FinReimbursementDetail;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曟槑缁嗚〃 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:38
+ */
+@Mapper
+public interface FinReimbursementDetailMapper extends BaseMapper<FinReimbursementDetail> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/mapper/FinReimbursementMapper.java b/src/main/java/com/ruoyi/approve/mapper/FinReimbursementMapper.java
new file mode 100644
index 0000000..19ac354
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/mapper/FinReimbursementMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.approve.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.approve.bean.dto.FinReimbursementDto;
+import com.ruoyi.approve.bean.vo.FinReimbursementVo;
+import com.ruoyi.approve.pojo.FinReimbursement;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曚富琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:15
+ */
+@Mapper
+public interface FinReimbursementMapper extends BaseMapper<FinReimbursement> {
+
+ IPage<FinReimbursementVo> listPage(@Param("ew") FinReimbursementDto finReimbursementDto, Page<FinReimbursementVo> page);
+}
diff --git a/src/main/java/com/ruoyi/approve/mapper/FinReimbursementTravelMapper.java b/src/main/java/com/ruoyi/approve/mapper/FinReimbursementTravelMapper.java
new file mode 100644
index 0000000..bc5e1b8
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/mapper/FinReimbursementTravelMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.approve.pojo.FinReimbursementTravel;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 宸梾鎶ラ攢鎵╁睍琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:47
+ */
+@Mapper
+public interface FinReimbursementTravelMapper extends BaseMapper<FinReimbursementTravel> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/ApprovalInstance.java b/src/main/java/com/ruoyi/approve/pojo/ApprovalInstance.java
new file mode 100644
index 0000000..77d8d58
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/pojo/ApprovalInstance.java
@@ -0,0 +1,152 @@
+package com.ruoyi.approve.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 瀹℃壒瀹炰緥琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:27:46
+ */
+@Getter
+@Setter
+@ToString
+@TableName("approval_instance")
+@ApiModel(value = "ApprovalInstance瀵硅薄", description = "瀹℃壒瀹炰緥琛�")
+public class ApprovalInstance implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 瀹℃壒瀹炰緥ID
+ */
+ @Schema(description ="瀹℃壒瀹炰緥ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 瀹℃壒缂栧彿
+ */
+ @Schema(description ="瀹℃壒缂栧彿")
+ private String instanceNo;
+
+ /**
+ * 妯℃澘ID
+ */
+ @Schema(description ="妯℃澘ID")
+ private Long templateId;
+
+ /**
+ * 妯℃澘鍚嶇О
+ */
+ @Schema(description ="妯℃澘鍚嶇О")
+ private String templateName;
+
+ /**
+ * 涓氬姟ID
+ */
+ @Schema(description ="涓氬姟ID")
+ private Long businessId;
+
+ /**
+ * 涓氬姟绫诲瀷
+ */
+ @Schema(description ="涓氬姟绫诲瀷")
+ private Long businessType;
+
+ /**
+ * 瀹℃壒鏍囬
+ */
+ @Schema(description ="瀹℃壒鏍囬")
+ private String title;
+
+ /**
+ * 瀹℃壒鐘舵��
+ */
+ @Schema(description ="瀹℃壒鐘舵�� PENDING - 寰呭鎵�/杩涜涓� APPROVED - 宸查�氳繃/宸插畬鎴� REJECTED - 宸查┏鍥�")
+ private String status;
+
+ /**
+ * 褰撳墠瀹℃壒绾у埆
+ */
+ @Schema(description ="褰撳墠瀹℃壒绾у埆")
+ private Integer currentLevel;
+
+ /**
+ * 鐢宠浜篒D
+ */
+ @Schema(description ="鐢宠浜篒D")
+ private Long applicantId;
+
+ /**
+ * 鐢宠浜哄悕绉�
+ */
+ @Schema(description ="鐢宠浜哄悕绉�")
+ private String applicantName;
+
+ /**
+ * 鐢宠鏃堕棿
+ */
+ @Schema(description ="鐢宠鏃堕棿")
+ private LocalDateTime applyTime;
+
+ /**
+ * 瀹屾垚鏃堕棿
+ */
+ @Schema(description ="瀹屾垚鏃堕棿")
+ private LocalDateTime finishTime;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @Schema(description ="鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Long createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @Schema(description ="鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ @Schema(description ="鏇存柊浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Long updateUser;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ @Schema(description ="鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+ /**
+ * 閫昏緫鍒犻櫎
+ */
+ @Schema(description ="閫昏緫鍒犻櫎")
+ private Byte deleted;
+
+ @Schema(description = "琛ㄥ崟鏁版嵁")
+ private String formConfig;
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/ApprovalInstanceNode.java b/src/main/java/com/ruoyi/approve/pojo/ApprovalInstanceNode.java
new file mode 100644
index 0000000..621ce1f
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/pojo/ApprovalInstanceNode.java
@@ -0,0 +1,106 @@
+package com.ruoyi.approve.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 瀹℃壒鑺傜偣瀹炰緥琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:27:54
+ */
+@Getter
+@Setter
+@ToString
+@TableName("approval_instance_node")
+@ApiModel(value = "ApprovalInstanceNode瀵硅薄", description = "瀹℃壒鑺傜偣瀹炰緥琛�")
+public class ApprovalInstanceNode implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 鑺傜偣瀹炰緥ID
+ */
+ @Schema(description ="鑺傜偣瀹炰緥ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 瀹℃壒瀹炰緥ID
+ */
+ @Schema(description ="瀹℃壒瀹炰緥ID")
+ private Long instanceId;
+
+ /**
+ * 瀹℃壒绾у埆
+ */
+ @Schema(description ="瀹℃壒绾у埆")
+ private Integer levelNo;
+
+ /**
+ * 瀹℃壒绫诲瀷
+ */
+ @Schema(description ="瀹℃壒绫诲瀷")
+ private String approveType;
+
+ /**
+ * 鑺傜偣鐘舵��
+ */
+ @Schema(description ="鑺傜偣鐘舵�� PENDING - 寰呭鐞� APPROVED - 宸查�氳繃 REJECTED - 宸查┏鍥�")
+ private String status;
+
+ /**
+ * 寮�濮嬫椂闂�
+ */
+ @Schema(description ="寮�濮嬫椂闂�")
+ private LocalDateTime startTime;
+
+ /**
+ * 瀹屾垚鏃堕棿
+ */
+ @Schema(description ="瀹屾垚鏃堕棿")
+ private LocalDateTime finishTime;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @Schema(description ="鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Long createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @Schema(description ="鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ @Schema(description ="鏇存柊浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Long updateUser;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ @Schema(description ="鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+ /**
+ * 閫昏緫鍒犻櫎
+ */
+ @Schema(description ="閫昏緫鍒犻櫎")
+ private Byte deleted;
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/ApprovalRecord.java b/src/main/java/com/ruoyi/approve/pojo/ApprovalRecord.java
new file mode 100644
index 0000000..21bc52b
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/pojo/ApprovalRecord.java
@@ -0,0 +1,98 @@
+package com.ruoyi.approve.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 瀹℃壒璁板綍琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:28:21
+ */
+@Getter
+@Setter
+@ToString
+@TableName("approval_record")
+@ApiModel(value = "ApprovalRecord瀵硅薄", description = "瀹℃壒璁板綍琛�")
+public class ApprovalRecord implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 瀹℃壒璁板綍ID
+ */
+ @Schema(description ="瀹℃壒璁板綍ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 瀹℃壒瀹炰緥ID
+ */
+ @Schema(description ="瀹℃壒瀹炰緥ID")
+ private Long instanceId;
+
+ /**
+ * 鑺傜偣瀹炰緥ID
+ */
+ @Schema(description ="鑺傜偣瀹炰緥ID")
+ private Long nodeId;
+
+ /**
+ * 瀹℃壒浠诲姟ID
+ */
+ @Schema(description ="瀹℃壒浠诲姟ID")
+ private Long taskId;
+
+ /**
+ * 鎿嶄綔浜篒D
+ */
+ @Schema(description ="鎿嶄綔浜篒D")
+ private Long operatorId;
+
+ /**
+ * 鎿嶄綔浜哄悕绉�
+ */
+ @Schema(description ="鎿嶄綔浜哄悕绉�")
+ private String operatorName;
+
+ /**
+ * 鎿嶄綔绫诲瀷
+ */
+ @Schema(description ="鎿嶄綔绫诲瀷")
+ private String action;
+
+ /**
+ * 瀹℃壒鎰忚
+ */
+ @Schema(description ="瀹℃壒鎰忚")
+ private String comment;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @Schema(description ="鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Long createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @Schema(description ="鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ /**
+ * 閫昏緫鍒犻櫎
+ */
+ @Schema(description ="閫昏緫鍒犻櫎")
+ private Byte deleted;
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/ApprovalTask.java b/src/main/java/com/ruoyi/approve/pojo/ApprovalTask.java
new file mode 100644
index 0000000..d78c964
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/pojo/ApprovalTask.java
@@ -0,0 +1,128 @@
+package com.ruoyi.approve.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 瀹℃壒浠诲姟琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:32:37
+ */
+@Getter
+@Setter
+@ToString
+@TableName("approval_task")
+@ApiModel(value = "ApprovalTask瀵硅薄", description = "瀹℃壒浠诲姟琛�")
+public class ApprovalTask implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 瀹℃壒浠诲姟ID
+ */
+ @Schema(description ="瀹℃壒浠诲姟ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 瀹℃壒瀹炰緥ID
+ */
+ @Schema(description ="瀹℃壒瀹炰緥ID")
+ private Long instanceId;
+
+ /**
+ * 鑺傜偣瀹炰緥ID
+ */
+ @Schema(description ="鑺傜偣瀹炰緥ID")
+ private Long nodeId;
+
+ /**
+ * 瀹℃壒绾у埆
+ */
+ @Schema(description ="瀹℃壒绾у埆")
+ private Integer levelNo;
+
+ /**
+ * 瀹℃壒浜篒D
+ */
+ @Schema(description ="瀹℃壒浜篒D")
+ private Long approverId;
+
+ /**
+ * 瀹℃壒浜哄悕绉�
+ */
+ @Schema(description ="瀹℃壒浜哄悕绉�")
+ private String approverName;
+
+ /**
+ * 浠诲姟鐘舵��
+ */
+ @Schema(description ="浠诲姟鐘舵�� PENDING - 寰呭鎵� APPROVED - 宸插悓鎰� REJECTED - 宸叉嫆缁�")
+ private String taskStatus;
+
+ /**
+ * 瀹℃壒鏃堕棿
+ */
+ @Schema(description ="瀹℃壒鏃堕棿")
+ private LocalDateTime approveTime;
+
+ /**
+ * 瀹℃壒鎰忚
+ */
+ @Schema(description ="瀹℃壒鎰忚")
+ private String comment;
+
+ /**
+ * 鏄惁宸茶
+ */
+ @Schema(description ="鏄惁宸茶")
+ private Byte isRead;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @Schema(description ="鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Long createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @Schema(description ="鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ @Schema(description ="鏇存柊浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Long updateUser;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ @Schema(description ="鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+ /**
+ * 閫昏緫鍒犻櫎
+ */
+ @Schema(description ="閫昏緫鍒犻櫎")
+ private Byte deleted;
+
+ @Schema(description ="閮ㄩ棬ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/ApprovalTemplate.java b/src/main/java/com/ruoyi/approve/pojo/ApprovalTemplate.java
new file mode 100644
index 0000000..272b945
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/pojo/ApprovalTemplate.java
@@ -0,0 +1,107 @@
+package com.ruoyi.approve.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 瀹℃壒妯℃澘琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 11:20:08
+ */
+@Getter
+@Setter
+@ToString
+@TableName("approval_template")
+@ApiModel(value = "ApprovalTemplate瀵硅薄", description = "瀹℃壒妯℃澘琛�")
+public class ApprovalTemplate implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 妯℃澘ID
+ */
+ @Schema(description ="妯℃澘ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 妯℃澘鍚嶇О
+ */
+ @Schema(description ="妯℃澘鍚嶇О")
+ private String templateName;
+
+ /**
+ * 鍚敤鐘舵�侊細1鍚敤锛�0鍋滅敤
+ */
+ @Schema(description ="鍚敤鐘舵�侊細1鍚敤锛�0鍋滅敤")
+ private Byte enabled;
+
+ /**
+ * 妯℃澘璇存槑
+ */
+ @Schema(description ="妯℃澘璇存槑")
+ private String description;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @Schema(description ="鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Long createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @Schema(description ="鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ @Schema(description ="鏇存柊浜�")
+ @TableField(fill = FieldFill.UPDATE)
+ private Long updateUser;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ @Schema(description ="鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+ /**
+ * 閫昏緫鍒犻櫎锛�0鍚︼紝1鏄�
+ */
+ @Schema(description ="閫昏緫鍒犻櫎锛�0鍚︼紝1鏄�")
+ private Integer deleted;
+
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+
+ @Schema(description = "琛ㄥ崟閰嶇疆")
+ private String formConfig;
+
+ @Schema(description = "妯℃澘绫诲瀷锛�0绯荤粺鍐呯疆锛�1鑷畾涔�")
+ private Integer templateType;
+
+ @Schema(description = "涓氬姟绫诲瀷")
+ private Long businessType;
+
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/ApprovalTemplateNode.java b/src/main/java/com/ruoyi/approve/pojo/ApprovalTemplateNode.java
new file mode 100644
index 0000000..cd77198
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/pojo/ApprovalTemplateNode.java
@@ -0,0 +1,66 @@
+package com.ruoyi.approve.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 瀹℃壒妯℃澘鑺傜偣琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 11:20:19
+ */
+@Getter
+@Setter
+@ToString
+@TableName("approval_template_node")
+@ApiModel(value = "ApprovalTemplateNode瀵硅薄", description = "瀹℃壒妯℃澘鑺傜偣琛�")
+public class ApprovalTemplateNode implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 鑺傜偣ID
+ */
+ @Schema(description ="鑺傜偣ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 瀹℃壒妯℃澘ID
+ */
+ @Schema(description ="瀹℃壒妯℃澘ID")
+ private Long templateId;
+
+ /**
+ * 瀹℃壒绾у埆锛屼粠1寮�濮�
+ */
+ @Schema(description ="瀹℃壒绾у埆锛屼粠1寮�濮�")
+ private Integer levelNo;
+
+ /**
+ * 瀹℃壒鏂瑰紡锛欰ND浼氱锛孫R鎴栫
+ */
+ @Schema(description ="瀹℃壒鏂瑰紡锛欰ND浼氱锛孫R鎴栫")
+ private String approveType;
+
+ @TableField(fill = FieldFill.INSERT)
+ private Long createUser;
+
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ @TableField(fill = FieldFill.UPDATE)
+ private LocalDateTime updateTime;
+
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/ApprovalTemplateNodeApprover.java b/src/main/java/com/ruoyi/approve/pojo/ApprovalTemplateNodeApprover.java
new file mode 100644
index 0000000..4113bff
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/pojo/ApprovalTemplateNodeApprover.java
@@ -0,0 +1,76 @@
+package com.ruoyi.approve.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 瀹℃壒妯℃澘鑺傜偣瀹℃壒浜鸿〃
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 11:20:30
+ */
+@Getter
+@Setter
+@ToString
+@TableName("approval_template_node_approver")
+@ApiModel(value = "ApprovalTemplateNodeApprover瀵硅薄", description = "瀹℃壒妯℃澘鑺傜偣瀹℃壒浜鸿〃")
+public class ApprovalTemplateNodeApprover implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 涓婚敭ID
+ */
+ @Schema(description = "涓婚敭ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 瀹℃壒鑺傜偣ID
+ */
+ @Schema(description ="瀹℃壒鑺傜偣ID")
+ private Long nodeId;
+
+ /**
+ * 瀹℃壒妯℃澘ID
+ */
+ @Schema(description ="瀹℃壒妯℃澘ID")
+ private Long templateId;
+
+ /**
+ * 瀹℃壒浜篒D
+ */
+ @Schema(description ="瀹℃壒浜篒D")
+ private Long approverId;
+
+ /**
+ * 瀹℃壒浜哄悕绉板啑浣�
+ */
+ @Schema(description ="瀹℃壒浜哄悕绉板啑浣�")
+ private String approverName;
+
+ /**
+ * 瀹℃壒浜烘帓搴�
+ */
+ @Schema(description ="瀹℃壒浜烘帓搴�")
+ private Integer sortNo;
+
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+ @TableField(fill = FieldFill.INSERT)
+ private Long createUser;
+ @TableField(fill = FieldFill.INSERT)
+ private Long deleted ;
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java b/src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java
index bd56b0f..728878b 100644
--- a/src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java
+++ b/src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java
@@ -151,6 +151,16 @@
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date endDate;
+ @Excel(name = "鍑哄樊寮�濮嬫椂闂�", dateFormat = "yyyy-MM-dd HH:mm", width = 30)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
+ @Schema(description = "鍑哄樊寮�濮嬫椂闂�")
+ private LocalDateTime startDateTime;
+
+ @Excel(name = "鍑哄樊缁撴潫鏃堕棿", dateFormat = "yyyy-MM-dd HH:mm", width = 30)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
+ @Schema(description = "鍑哄樊缁撴潫鏃堕棿")
+ private LocalDateTime endDateTime;
+
private BigDecimal price;
private String location;
diff --git a/src/main/java/com/ruoyi/approve/pojo/FinReimbursement.java b/src/main/java/com/ruoyi/approve/pojo/FinReimbursement.java
new file mode 100644
index 0000000..7d5ad9c
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/pojo/FinReimbursement.java
@@ -0,0 +1,210 @@
+package com.ruoyi.approve.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曚富琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:15
+ */
+@Getter
+@Setter
+@ToString
+@TableName("fin_reimbursement")
+@ApiModel(value = "FinReimbursement瀵硅薄", description = "鎶ラ攢鍗曚富琛�")
+public class FinReimbursement implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 涓婚敭ID
+ */
+ @Schema(description = "涓婚敭ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 鎶ラ攢鍗曞彿
+ */
+ @Schema(description = "鎶ラ攢鍗曞彿")
+ private String billNo;
+
+ /**
+ * 鎶ラ攢绫诲瀷锛�1-宸梾鎶ラ攢锛�2-璐圭敤鎶ラ攢
+ */
+ @Schema(description = "鎶ラ攢绫诲瀷锛�1-宸梾鎶ラ攢锛�2-璐圭敤鎶ラ攢")
+ private Byte reimbursementType;
+
+ /**
+ * 璐圭敤绫诲瀷锛氬樊鏃呰垂/鍔炲叕閲囪喘/涓氬姟鎷涘緟/浜ら�氳垂/閫氳璐�/鍏朵粬
+ */
+ @Schema(description = "璐圭敤绫诲瀷锛氬樊鏃呰垂/鍔炲叕閲囪喘/涓氬姟鎷涘緟/浜ら�氳垂/閫氳璐�/鍏朵粬")
+ private String expenseType;
+
+ /**
+ * 鐢宠浜篒D
+ */
+ @Schema(description = "鐢宠浜篒D")
+ private Long applicantId;
+
+ /**
+ * 鍛樺伐缂栧彿
+ */
+ @Schema(description = "鍛樺伐缂栧彿")
+ private String applicantCode;
+
+ /**
+ * 鍛樺伐濮撳悕
+ */
+ @Schema(description = "鍛樺伐濮撳悕")
+ private String applicantName;
+
+ /**
+ * 鐢宠閮ㄩ棬ID
+ */
+ @Schema(description = "鐢宠閮ㄩ棬ID")
+ private Long applicantDeptId;
+
+ /**
+ * 鐢宠閮ㄩ棬鍚嶇О
+ */
+ @Schema(description = "鐢宠閮ㄩ棬鍚嶇О")
+ private String applicantDeptName;
+
+ /**
+ * 鎶ラ攢鍘熷洜
+ */
+ @Schema(description = "鎶ラ攢鍘熷洜")
+ private String reason;
+
+ /**
+ * 鐢宠閲戦
+ */
+ @Schema(description = "鐢宠閲戦")
+ private BigDecimal applyAmount;
+
+ /**
+ * 鏄庣粏姹囨�婚噾棰�
+ */
+ @Schema(description = "鏄庣粏姹囨�婚噾棰�")
+ private BigDecimal detailTotalAmount;
+
+ /**
+ * 鏀舵浜�
+ */
+ @Schema(description = "鏀舵浜�")
+ private String payeeName;
+
+ /**
+ * 鏀舵璐﹀彿
+ */
+ @Schema(description = "鏀舵璐﹀彿")
+ private String payeeAccount;
+
+ /**
+ * 寮�鎴锋敮琛�
+ */
+ @Schema(description = "寮�鎴锋敮琛�")
+ private String payeeBank;
+
+ /**
+ * 瀹℃壒瀹炰緥ID锛屽搴� approval_instance.id
+ */
+ @Schema(description = "瀹℃壒瀹炰緥ID锛屽搴� approval_instance.id")
+ private Long approvalInstanceId;
+
+ /**
+ * 瀹℃壒娴佺▼ID锛屽搴� approve_process.id
+ */
+ @Schema(description = "瀹℃壒娴佺▼ID锛屽搴� approve_process.id")
+ private Long approveProcessId;
+
+ /**
+ * 鍗曟嵁鐘舵�侊細DRAFT-鑽夌锛孖N_APPROVAL-瀹℃壒涓紝APPROVED-瀹℃壒閫氳繃锛孯EJECTED-瀹℃壒椹冲洖锛學ITHDRAWN-宸叉挙鍥烇紝PAID-宸蹭粯娆�
+ */
+ @Schema(description = "鍗曟嵁鐘舵�侊細DRAFT-鑽夌锛孖N_APPROVAL-瀹℃壒涓紝APPROVED-瀹℃壒閫氳繃锛孯EJECTED-瀹℃壒椹冲洖锛學ITHDRAWN-宸叉挙鍥烇紝PAID-宸蹭粯娆�")
+ private String billStatus;
+
+ /**
+ * 瀹℃壒閫氳繃鏃堕棿
+ */
+ @Schema(description = "瀹℃壒閫氳繃鏃堕棿")
+ private LocalDateTime approvedTime;
+
+ /**
+ * 浠樻鏃堕棿
+ */
+ @Schema(description = "浠樻鏃堕棿")
+ private LocalDateTime paidTime;
+
+ /**
+ * 鐢熸垚鐨勮储鍔℃敮鍑鸿褰旾D锛屽搴� account_expense.id
+ */
+ @Schema(description = "鐢熸垚鐨勮储鍔℃敮鍑鸿褰旾D锛屽搴� account_expense.id")
+ private Long accountExpenseId;
+
+ /**
+ * 澶囨敞
+ */
+ @Schema(description = "澶囨敞")
+ private String remark;
+
+ /**
+ * 绉熸埛ID
+ */
+ @Schema(description = "绉熸埛ID")
+ private Long tenantId;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @Schema(description = "鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Long createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @Schema(description = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ @Schema(description = "鏇存柊浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Long updateUser;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ @Schema(description = "鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+ /**
+ * 褰掑睘閮ㄩ棬ID
+ */
+ @Schema(description = "褰掑睘閮ㄩ棬ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+
+ /**
+ * 閫昏緫鍒犻櫎锛�0-鍚︼紝1-鏄�
+ */
+ @Schema(description = "閫昏緫鍒犻櫎锛�0-鍚︼紝1-鏄�")
+ private Byte deleted;
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/FinReimbursementDetail.java b/src/main/java/com/ruoyi/approve/pojo/FinReimbursementDetail.java
new file mode 100644
index 0000000..5d0220e
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/pojo/FinReimbursementDetail.java
@@ -0,0 +1,157 @@
+package com.ruoyi.approve.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曟槑缁嗚〃
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:38
+ */
+@Getter
+@Setter
+@ToString
+@TableName("fin_reimbursement_detail")
+@ApiModel(value = "FinReimbursementDetail瀵硅薄", description = "鎶ラ攢鍗曟槑缁嗚〃")
+public class FinReimbursementDetail implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 涓婚敭ID
+ */
+ @Schema(description = "涓婚敭ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 鎶ラ攢鍗旾D锛屽搴� fin_reimbursement.id
+ */
+ @Schema(description = "鎶ラ攢鍗旾D锛屽搴� fin_reimbursement.id")
+ private Long reimbursementId;
+
+ /**
+ * 鏄庣粏琛屽彿
+ */
+ @Schema(description = "鏄庣粏琛屽彿")
+ private Integer rowNo;
+
+ /**
+ * 鍙戠エ鏃ユ湡
+ */
+ @Schema(description = "鍙戠エ鏃ユ湡")
+ private LocalDate invoiceDate;
+
+ /**
+ * 璐圭敤绉戠洰
+ */
+ @Schema(description = "璐圭敤绉戠洰")
+ private String expenseCategory;
+
+ /**
+ * 閲戦
+ */
+ @Schema(description = "閲戦")
+ private BigDecimal amount;
+
+ /**
+ * 鎻忚堪
+ */
+ @Schema(description = "鎻忚堪")
+ private String description;
+
+ /**
+ * 鍙戠エ鍙风爜
+ */
+ @Schema(description = "鍙戠エ鍙风爜")
+ private String invoiceNo;
+
+ /**
+ * 鍙戠エ绫诲瀷
+ */
+ @Schema(description = "鍙戠エ绫诲瀷")
+ private String invoiceType;
+
+ /**
+ * 绁ㄩ潰閲戦
+ */
+ @Schema(description = "绁ㄩ潰閲戦")
+ private BigDecimal invoiceAmount;
+
+ /**
+ * 绋庣巼
+ */
+ @Schema(description = "绋庣巼")
+ private BigDecimal taxRate;
+
+ /**
+ * 绋庨
+ */
+ @Schema(description = "绋庨")
+ private BigDecimal taxAmount;
+
+ /**
+ * 澶囨敞
+ */
+ @Schema(description = "澶囨敞")
+ private String remark;
+
+ /**
+ * 绉熸埛ID
+ */
+ @Schema(description = "绉熸埛ID")
+ private Long tenantId;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @Schema(description = "鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Long createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @Schema(description = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ @Schema(description = "鏇存柊浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Long updateUser;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ @Schema(description = "鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+ /**
+ * 褰掑睘閮ㄩ棬ID
+ */
+ @Schema(description = "褰掑睘閮ㄩ棬ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+
+ /**
+ * 閫昏緫鍒犻櫎锛�0-鍚︼紝1-鏄�
+ */
+ @Schema(description = "閫昏緫鍒犻櫎锛�0-鍚︼紝1-鏄�")
+ private Byte deleted;
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/FinReimbursementTravel.java b/src/main/java/com/ruoyi/approve/pojo/FinReimbursementTravel.java
new file mode 100644
index 0000000..10c607c
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/pojo/FinReimbursementTravel.java
@@ -0,0 +1,162 @@
+package com.ruoyi.approve.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 宸梾鎶ラ攢鎵╁睍琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:47
+ */
+@Getter
+@Setter
+@ToString
+@TableName("fin_reimbursement_travel")
+@ApiModel(value = "FinReimbursementTravel瀵硅薄", description = "宸梾鎶ラ攢鎵╁睍琛�")
+public class FinReimbursementTravel implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 涓婚敭ID
+ */
+ @Schema(description = "涓婚敭ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 鎶ラ攢鍗旾D锛屽搴� fin_reimbursement.id
+ */
+ @Schema(description = "鎶ラ攢鍗旾D锛屽搴� fin_reimbursement.id")
+ private Long reimbursementId;
+
+ /**
+ * 鍑哄樊寮�濮嬫椂闂�
+ */
+ @Schema(description = "鍑哄樊寮�濮嬫椂闂�")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime startTime;
+
+ /**
+ * 鍑哄樊缁撴潫鏃堕棿
+ */
+ @Schema(description = "鍑哄樊缁撴潫鏃堕棿")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime endTime;
+
+ /**
+ * 鍑哄樊澶╂暟
+ */
+ @Schema(description = "鍑哄樊澶╂暟")
+ private BigDecimal travelDays;
+
+ /**
+ * 鍑哄樊鍦�/鍑哄彂鍩庡競
+ */
+ @Schema(description = "鍑哄樊鍦�/鍑哄彂鍩庡競")
+ private String departureCity;
+
+ /**
+ * 鐩殑鍦�/鐩殑鍩庡競
+ */
+ @Schema(description = "鐩殑鍦�/鐩殑鍩庡競")
+ private String destinationCity;
+
+ /**
+ * 閰掑簵鏍囧噯
+ */
+ @Schema(description = "閰掑簵鏍囧噯")
+ private BigDecimal hotelStandard;
+
+ /**
+ * 浣忓澶╂暟
+ */
+ @Schema(description = "浣忓澶╂暟")
+ private BigDecimal lodgingDays;
+
+ /**
+ * 鐢熸椿琛ヨ创
+ */
+ @Schema(description = "鐢熸椿琛ヨ创")
+ private BigDecimal mealAllowance;
+
+ /**
+ * 浜ら�氳ˉ璐�
+ */
+ @Schema(description = "浜ら�氳ˉ璐�")
+ private BigDecimal transportAllowance;
+
+ /**
+ * 浣忓闄愰
+ */
+ @Schema(description = "浣忓闄愰")
+ private BigDecimal lodgingLimit;
+
+ /**
+ * 鐗规壒鏍囪鏂囨湰锛屽鍦ㄦ爣鍑嗚寖鍥村唴/瓒呮爣鐗规壒
+ */
+ @Schema(description = "鐗规壒鏍囪鏂囨湰锛屽鍦ㄦ爣鍑嗚寖鍥村唴/瓒呮爣鐗规壒")
+ private String standardTag;
+
+ /**
+ * 鏄惁鍦ㄦ爣鍑嗗唴锛�1-鏄紝0-鍚�
+ */
+ @Schema(description = "鏄惁鍦ㄦ爣鍑嗗唴锛�1-鏄紝0-鍚�")
+ private Byte withinStandard;
+
+ /**
+ * 绉熸埛ID
+ */
+ @Schema(description = "绉熸埛ID")
+ private Long tenantId;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @Schema(description = "鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Long createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @Schema(description = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ @Schema(description = "鏇存柊浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Long updateUser;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ @Schema(description = "鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+ /**
+ * 褰掑睘閮ㄩ棬ID
+ */
+ @Schema(description = "褰掑睘閮ㄩ棬ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/approve/service/ApprovalInstanceNodeService.java b/src/main/java/com/ruoyi/approve/service/ApprovalInstanceNodeService.java
new file mode 100644
index 0000000..8fa7c60
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/ApprovalInstanceNodeService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.approve.service;
+
+import com.ruoyi.approve.pojo.ApprovalInstanceNode;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 瀹℃壒鑺傜偣瀹炰緥琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:27:54
+ */
+public interface ApprovalInstanceNodeService extends IService<ApprovalInstanceNode> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/ApprovalInstanceService.java b/src/main/java/com/ruoyi/approve/service/ApprovalInstanceService.java
new file mode 100644
index 0000000..dfb9517
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/ApprovalInstanceService.java
@@ -0,0 +1,31 @@
+package com.ruoyi.approve.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.approve.bean.dto.ApprovalInstanceDto;
+import com.ruoyi.approve.bean.vo.ApprovalInstanceVo;
+import com.ruoyi.approve.pojo.ApprovalInstance;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.framework.web.domain.R;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹℃壒瀹炰緥琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:27:46
+ */
+public interface ApprovalInstanceService extends IService<ApprovalInstance> {
+
+ R listPage(Page<ApprovalInstanceVo> page, ApprovalInstanceDto approvalInstanceDto);
+
+ Boolean add(ApprovalInstanceDto approvalInstanceDto);
+
+ Boolean update(ApprovalInstanceDto approvalInstanceDto);
+
+ Boolean delete(List<Long> ids);
+
+ R approve(ApprovalInstanceDto approvalInstanceDto);
+}
diff --git a/src/main/java/com/ruoyi/approve/service/ApprovalRecordService.java b/src/main/java/com/ruoyi/approve/service/ApprovalRecordService.java
new file mode 100644
index 0000000..041571c
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/ApprovalRecordService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.approve.service;
+
+import com.ruoyi.approve.pojo.ApprovalRecord;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 瀹℃壒璁板綍琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:28:21
+ */
+public interface ApprovalRecordService extends IService<ApprovalRecord> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/ApprovalTaskService.java b/src/main/java/com/ruoyi/approve/service/ApprovalTaskService.java
new file mode 100644
index 0000000..491e57d
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/ApprovalTaskService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.approve.service;
+
+import com.ruoyi.approve.pojo.ApprovalTask;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 瀹℃壒浠诲姟琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:32:37
+ */
+public interface ApprovalTaskService extends IService<ApprovalTask> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/ApprovalTemplateNodeApproverService.java b/src/main/java/com/ruoyi/approve/service/ApprovalTemplateNodeApproverService.java
new file mode 100644
index 0000000..e335276
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/ApprovalTemplateNodeApproverService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.approve.service;
+
+import com.ruoyi.approve.pojo.ApprovalTemplateNodeApprover;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 瀹℃壒妯℃澘鑺傜偣瀹℃壒浜鸿〃 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 11:20:30
+ */
+public interface ApprovalTemplateNodeApproverService extends IService<ApprovalTemplateNodeApprover> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/ApprovalTemplateNodeService.java b/src/main/java/com/ruoyi/approve/service/ApprovalTemplateNodeService.java
new file mode 100644
index 0000000..4a8d6a8
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/ApprovalTemplateNodeService.java
@@ -0,0 +1,20 @@
+package com.ruoyi.approve.service;
+
+import com.ruoyi.approve.bean.dto.ApprovalTemplateNodeDto;
+import com.ruoyi.approve.pojo.ApprovalTemplateNode;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹℃壒妯℃澘鑺傜偣琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 11:20:19
+ */
+public interface ApprovalTemplateNodeService extends IService<ApprovalTemplateNode> {
+
+ Boolean saveApprovalTemplateNode(Long id, List<ApprovalTemplateNodeDto> nodes);
+}
diff --git a/src/main/java/com/ruoyi/approve/service/ApprovalTemplateService.java b/src/main/java/com/ruoyi/approve/service/ApprovalTemplateService.java
new file mode 100644
index 0000000..38bbabc
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/ApprovalTemplateService.java
@@ -0,0 +1,34 @@
+package com.ruoyi.approve.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.approve.bean.dto.ApprovalTemplateDto;
+import com.ruoyi.approve.bean.vo.ApprovalTemplateVo;
+import com.ruoyi.approve.pojo.ApprovalTemplate;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹℃壒妯℃澘琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 11:20:08
+ */
+public interface ApprovalTemplateService extends IService<ApprovalTemplate> {
+
+ IPage<ApprovalTemplateVo> listPage(Page<ApprovalTemplateVo> page, ApprovalTemplateDto approvalTemplateDto);
+
+ Boolean saveApprovalTemplateDto(ApprovalTemplateDto approvalTemplateDto);
+
+ Boolean updateApprovalTemplateDto(ApprovalTemplateDto approvalTemplateDto);
+
+ Boolean delete(List<Long> ids);
+
+ List<ApprovalTemplateVo> listApprovalTemplateVo(Integer type);
+
+ ApprovalTemplateVo getApprovalTemplateVoById(Long id);
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/FinReimbursementDetailService.java b/src/main/java/com/ruoyi/approve/service/FinReimbursementDetailService.java
new file mode 100644
index 0000000..0279c25
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/FinReimbursementDetailService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.approve.service;
+
+import com.ruoyi.approve.pojo.FinReimbursementDetail;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曟槑缁嗚〃 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:38
+ */
+public interface FinReimbursementDetailService extends IService<FinReimbursementDetail> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/FinReimbursementService.java b/src/main/java/com/ruoyi/approve/service/FinReimbursementService.java
new file mode 100644
index 0000000..c14b943
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/FinReimbursementService.java
@@ -0,0 +1,31 @@
+package com.ruoyi.approve.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.approve.bean.dto.FinReimbursementDto;
+import com.ruoyi.approve.bean.vo.FinReimbursementVo;
+import com.ruoyi.approve.pojo.FinReimbursement;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曚富琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:15
+ */
+public interface FinReimbursementService extends IService<FinReimbursement> {
+
+ IPage<FinReimbursementVo> listPage(FinReimbursementDto finReimbursementDto, Page<FinReimbursementVo> page);
+
+ Boolean add(FinReimbursementDto finReimbursementDto);
+
+ FinReimbursementVo detail(Long id);
+
+ Boolean update(FinReimbursementDto finReimbursementDto);
+
+ Boolean delete(List<Long> ids);
+}
diff --git a/src/main/java/com/ruoyi/approve/service/FinReimbursementTravelService.java b/src/main/java/com/ruoyi/approve/service/FinReimbursementTravelService.java
new file mode 100644
index 0000000..0733d1b
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/FinReimbursementTravelService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.approve.service;
+
+import com.ruoyi.approve.pojo.FinReimbursementTravel;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 宸梾鎶ラ攢鎵╁睍琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:47
+ */
+public interface FinReimbursementTravelService extends IService<FinReimbursementTravel> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceNodeServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceNodeServiceImpl.java
new file mode 100644
index 0000000..9ea1963
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceNodeServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.approve.service.impl;
+
+import com.ruoyi.approve.pojo.ApprovalInstanceNode;
+import com.ruoyi.approve.mapper.ApprovalInstanceNodeMapper;
+import com.ruoyi.approve.service.ApprovalInstanceNodeService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 瀹℃壒鑺傜偣瀹炰緥琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:27:54
+ */
+@Service
+public class ApprovalInstanceNodeServiceImpl extends ServiceImpl<ApprovalInstanceNodeMapper, ApprovalInstanceNode> implements ApprovalInstanceNodeService {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
new file mode 100644
index 0000000..1fb2333
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
@@ -0,0 +1,753 @@
+package com.ruoyi.approve.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.approve.bean.dto.ApprovalInstanceDto;
+import com.ruoyi.approve.bean.vo.ApprovalInstanceVo;
+import com.ruoyi.approve.mapper.ApprovalInstanceMapper;
+import com.ruoyi.approve.mapper.ApprovalTemplateNodeApproverMapper;
+import com.ruoyi.approve.mapper.FinReimbursementMapper;
+import com.ruoyi.approve.pojo.*;
+import com.ruoyi.approve.service.*;
+import com.ruoyi.approve.utils.ApproveProcessConfigNodeUtils;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
+import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsMapper;
+import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeDeptMapper;
+import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeUserMapper;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser;
+import com.ruoyi.common.enums.*;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.OrderUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.procurementrecord.utils.StockUtils;
+import com.ruoyi.project.system.domain.SysDept;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysDeptMapper;
+import com.ruoyi.project.system.mapper.SysUserDeptMapper;
+import com.ruoyi.project.system.mapper.SysUserMapper;
+import com.ruoyi.project.system.service.ISysNoticeService;
+import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
+import com.ruoyi.purchase.pojo.PurchaseLedger;
+import com.ruoyi.quality.utils.QualityInspectHelper;
+import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
+import com.ruoyi.sales.mapper.SalesQuotationMapper;
+import com.ruoyi.sales.mapper.ShippingInfoMapper;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.sales.pojo.SalesQuotation;
+import com.ruoyi.sales.pojo.ShippingInfo;
+import com.ruoyi.staff.mapper.HolidayApplicationMapper;
+import com.ruoyi.staff.pojo.HolidayApplication;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 瀹℃壒瀹炰緥鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @since 2026-05-18 03:27:46
+ */
+@Service
+@RequiredArgsConstructor
+public class ApprovalInstanceServiceImpl extends ServiceImpl<ApprovalInstanceMapper, ApprovalInstance> implements ApprovalInstanceService {
+
+ private static final String ENTERPRISE_NEWS_STATUS_PUBLISHED = "PUBLISHED";
+ private static final String ENTERPRISE_NEWS_STATUS_REJECTED = "REJECTED";
+
+ private final ApprovalInstanceMapper approvalInstanceMapper;
+ private final ApproveProcessConfigNodeUtils approveProcessConfigNodeUtils;
+ private final ApprovalInstanceNodeService approvalInstanceNodeService;
+ private final ApprovalTaskService approvalTaskService;
+ private final ApprovalRecordService approvalRecordService;
+ private final ApprovalTemplateNodeService approvalTemplateNodeService;
+ private final FinReimbursementMapper finReimbursementMapper;
+ private final FileUtil fileUtil;
+ private final ISysNoticeService sysNoticeService;
+ private final PurchaseLedgerMapper purchaseLedgerMapper;
+ private final SalesLedgerProductMapper salesLedgerProductMapper;
+ private final StockUtils stockUtils;
+ private final SalesQuotationMapper salesQuotationMapper;
+ private final ShippingInfoMapper shippingInfoMapper;
+ private final QualityInspectHelper qualityInspectHelper;
+ private final EnterpriseNewsScopeUserMapper enterpriseNewsScopeUserMapper;
+ private final SysUserMapper sysUserMapper;
+ private final SysUserDeptMapper sysUserDeptMapper;
+ private final SysDeptMapper sysDeptMapper;
+ private final HolidayApplicationMapper holidayApplicationMapper;
+ private final EnterpriseNewsMapper enterpriseNewsMapper;
+ private final EnterpriseNewsScopeDeptMapper enterpriseNewsScopeDeptMapper;
+ private final ApprovalTemplateNodeApproverMapper approvalTemplateNodeApproverMapper;
+
+ @Override
+ public R listPage(Page<ApprovalInstanceVo> page, ApprovalInstanceDto approvalInstanceDto) {
+ IPage<ApprovalInstanceVo> approvalInstanceVoIPage = approvalInstanceMapper.listPage(page, approvalInstanceDto);
+
+ List<ApprovalInstanceVo> records = approvalInstanceVoIPage.getRecords();
+ if (records == null || records.isEmpty()) {
+ return R.ok(approvalInstanceVoIPage);
+ }
+ records.forEach(vo -> {
+ vo.setBusinessName(TypeEnums.getLabelByValue(vo.getBusinessType()));
+ });
+ Long currentUserId = SecurityUtils.getUserId();
+
+ List<Long> instanceIds = records.stream()
+ .map(ApprovalInstanceVo::getId)
+ .filter(id -> id != null)
+ .distinct()
+ .collect(Collectors.toList());
+
+ if (!instanceIds.isEmpty()) {
+ Map<Long, List<ApprovalRecord>> recordMap = approvalRecordService.list(
+ Wrappers.<ApprovalRecord>lambdaQuery()
+ .in(ApprovalRecord::getInstanceId, instanceIds)
+ .eq(ApprovalRecord::getDeleted, 0)
+ ).stream().collect(Collectors.groupingBy(ApprovalRecord::getInstanceId));
+ Map<Long, List<ApprovalTask>> taskMap = approvalTaskService.list(
+ Wrappers.<ApprovalTask>lambdaQuery()
+ .in(ApprovalTask::getInstanceId, instanceIds)
+ .eq(ApprovalTask::getDeleted, 0)
+ ).stream().collect(Collectors.groupingBy(ApprovalTask::getInstanceId));
+
+ for (ApprovalInstanceVo vo : records) {
+ vo.setIsApprove(approveProcessConfigNodeUtils.isCurrentApprover(vo.getId(), currentUserId));
+ vo.setRecords(recordMap.getOrDefault(vo.getId(), new ArrayList<>()));
+ vo.setTasks(taskMap.getOrDefault(vo.getId(), new ArrayList<>()));
+ vo.setStorageBlobVOList(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.APPROVAL_INSTANCE, vo.getId()));
+ }
+
+ }
+ return R.ok(approvalInstanceVoIPage);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean add(ApprovalInstanceDto approvalInstanceDto) {
+ String instanceNo = OrderUtils.countTodayByCreateTime(approvalInstanceMapper, "SP", "instance_no");
+ approvalInstanceDto.setInstanceNo(instanceNo);
+ approvalInstanceDto.setStatus("PENDING");
+ approvalInstanceDto.setCurrentLevel(1);
+ boolean saved = this.save(approvalInstanceDto);
+ if (!saved) {
+ return false;
+ }
+ approveProcessConfigNodeUtils.createCurrentNodeAndTasks(approvalInstanceDto);
+ fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVAL_INSTANCE, approvalInstanceDto.getId(), approvalInstanceDto.getStorageBlobDTOs());
+ sendApproveNotice(approvalInstanceDto, approveProcessConfigNodeUtils.getCurrentPendingTasks(approvalInstanceDto.getId()));
+ return true;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean update(ApprovalInstanceDto approvalInstanceDto) {
+ if (approvalInstanceDto == null || approvalInstanceDto.getId() == null) {
+ return false;
+ }
+ // 鍒ゆ柇鏄惁鏈夋鍦ㄨ繘琛岀殑瀹℃壒浠诲姟锛屾湁鍒欎笉鍏佽淇敼
+ long pendingTaskCount = approvalTaskService.count(
+ Wrappers.<ApprovalTask>lambdaQuery()
+ .eq(ApprovalTask::getInstanceId, approvalInstanceDto.getId())
+ .eq(ApprovalTask::getTaskStatus, "PENDING")
+ .eq(ApprovalTask::getDeleted, 0)
+ );
+ if (pendingTaskCount > 0) {
+ throw new ServiceException("璇ュ鎵瑰崟鏈夋鍦ㄨ繘琛岀殑瀹℃壒浠诲姟锛屼笉鍏佽淇敼");
+ }
+ boolean updated = this.updateById(approvalInstanceDto);
+ if (!updated) {
+ return false;
+ }
+ fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVAL_INSTANCE, approvalInstanceDto.getId(), approvalInstanceDto.getStorageBlobDTOs());
+ return true;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean delete(List<Long> ids) {
+ if (ids == null || ids.isEmpty()) {
+ return false;
+ }
+ fileUtil.deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordIds(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVAL_INSTANCE, ids);
+
+ int instanceRows = approvalInstanceMapper.update(
+ null,
+ Wrappers.<ApprovalInstance>lambdaUpdate()
+ .in(ApprovalInstance::getId, ids)
+ .eq(ApprovalInstance::getDeleted, 0)
+ .set(ApprovalInstance::getDeleted, (byte) 1)
+ );
+
+ LambdaUpdateWrapper<ApprovalInstanceNode> nodeUpdateWrapper = Wrappers.lambdaUpdate();
+ nodeUpdateWrapper.in(ApprovalInstanceNode::getInstanceId, ids)
+ .eq(ApprovalInstanceNode::getDeleted, 0)
+ .set(ApprovalInstanceNode::getDeleted, (byte) 1);
+ approvalInstanceNodeService.update(nodeUpdateWrapper);
+
+ LambdaUpdateWrapper<ApprovalTask> taskUpdateWrapper = Wrappers.lambdaUpdate();
+ taskUpdateWrapper.in(ApprovalTask::getInstanceId, ids)
+ .eq(ApprovalTask::getDeleted, 0)
+ .set(ApprovalTask::getDeleted, (byte) 1);
+ approvalTaskService.update(taskUpdateWrapper);
+
+ LambdaUpdateWrapper<ApprovalRecord> recordUpdateWrapper = Wrappers.lambdaUpdate();
+ recordUpdateWrapper.in(ApprovalRecord::getInstanceId, ids)
+ .eq(ApprovalRecord::getDeleted, 0)
+ .set(ApprovalRecord::getDeleted, (byte) 1);
+ approvalRecordService.update(recordUpdateWrapper);
+
+ return instanceRows > 0;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public R approve(ApprovalInstanceDto approvalInstanceDto) {
+ if (approvalInstanceDto == null || approvalInstanceDto.getId() == null) {
+ return R.fail("瀹℃壒瀹炰緥 ID 涓嶈兘涓虹┖");
+ }
+ String approveAction = normalizeApproveAction(approvalInstanceDto.getApproveAction());
+ if (approveAction == null) {
+ return R.fail("瀹℃壒鍔ㄤ綔鍙敮鎸� APPROVED 鎴� REJECTED");
+ }
+
+ ApprovalInstance instance = getPendingApprovalInstance(approvalInstanceDto.getId());
+ if (instance == null) {
+ return R.fail("瀹℃壒瀹炰緥涓嶅瓨鍦�");
+ }
+
+ ApprovalInstanceNode currentNode = approveProcessConfigNodeUtils.getCurrentNode(instance.getId());
+ if (currentNode == null) {
+ return R.fail("褰撳墠娌℃湁寰呭鐞嗙殑瀹℃壒鑺傜偣");
+ }
+
+ Long currentUserId = SecurityUtils.getUserId();
+ ApprovalTask currentTask = approveProcessConfigNodeUtils.getCurrentUserTask(instance.getId(), currentUserId);
+ if (currentTask == null) {
+ return R.fail("褰撳墠鐢ㄦ埛娌℃湁鍙鎵逛换鍔�");
+ }
+
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ String operatorName = loginUser.getUser() != null ? loginUser.getUser().getNickName() : SecurityUtils.getUsername();
+ LocalDateTime now = LocalDateTime.now();
+
+ if (!updateCurrentTask(approvalInstanceDto, approveAction, currentTask, now)) {
+ return R.fail("褰撳墠浠诲姟宸茶澶勭悊锛岃鍒锋柊鍚庨噸璇�");
+ }
+
+ saveApprovalRecord(
+ instance.getId(),
+ currentNode.getId(),
+ currentTask.getId(),
+ currentUserId,
+ operatorName,
+ approveAction,
+ approvalInstanceDto.getApproveComment()
+ );
+ //瀹℃壒鎷掔粷鐨勫鐞�
+ if ("REJECTED".equals(approveAction)) {
+ return rejectCurrentNode(instance, currentNode, now);
+ }
+ if (!approveProcessConfigNodeUtils.canProceedToNextLevel(instance.getId(), currentNode.getApproveType())) {
+ return R.ok("瀹℃壒鎴愬姛锛岀瓑寰呭叾浠栧鎵逛汉澶勭悊");
+ }
+
+ return approveAndMoveNext(instance, currentNode, approvalInstanceDto, now);
+ }
+
+ private String normalizeApproveAction(String approveAction) {
+ if (!StringUtils.hasText(approveAction)) {
+ return null;
+ }
+ String normalizedAction = approveAction.trim().toUpperCase(Locale.ROOT);
+ return "APPROVED".equals(normalizedAction) || "REJECTED".equals(normalizedAction)
+ ? normalizedAction
+ : null;
+ }
+
+ private ApprovalInstance getPendingApprovalInstance(Long instanceId) {
+ return this.getOne(
+ new LambdaQueryWrapper<ApprovalInstance>()
+ .eq(ApprovalInstance::getId, instanceId)
+ .eq(ApprovalInstance::getDeleted, 0)
+ .last("LIMIT 1")
+ );
+ }
+
+ private boolean updateCurrentTask(ApprovalInstanceDto approvalInstanceDto,
+ String approveAction,
+ ApprovalTask currentTask,
+ LocalDateTime now) {
+ // 浠呭厑璁稿緟瀹℃壒浠诲姟琚垚鍔熷鐞嗕竴娆★紝閬垮厤骞跺彂涓嬮噸澶嶅鎵规垚鍔熴��
+ return approvalTaskService.update(
+ Wrappers.<ApprovalTask>lambdaUpdate()
+ .eq(ApprovalTask::getId, currentTask.getId())
+ .eq(ApprovalTask::getTaskStatus, "PENDING")
+ .eq(ApprovalTask::getDeleted, 0)
+ .set(ApprovalTask::getTaskStatus, approveAction)
+ .set(ApprovalTask::getComment, approvalInstanceDto.getApproveComment())
+ .set(ApprovalTask::getApproveTime, now)
+ .set(ApprovalTask::getIsRead, (byte) 1)
+ );
+ }
+
+ private R rejectCurrentNode(ApprovalInstance instance, ApprovalInstanceNode currentNode, LocalDateTime now) {
+ if (!updateCurrentNodeStatus(currentNode.getId(), "REJECTED", now)) {
+ return R.ok("褰撳墠鑺傜偣宸插鐞嗗畬鎴�");
+ }
+
+ closePendingTasks(instance.getId(), currentNode.getId());
+ instance.setStatus("REJECTED");
+ instance.setFinishTime(now);
+ this.updateById(instance);
+ // 椹冲洖瀵瑰簲鐨勪紒涓氭柊闂伙紝 宸梾鎶ラ攢
+ if (instance.getBusinessType().equals(TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode())) {
+ enterpriseNewsMapper.update(
+ new LambdaUpdateWrapper<EnterpriseNews>()
+ .eq(EnterpriseNews::getId, instance.getBusinessId())
+ .set(EnterpriseNews::getStatus, "REJECTED")
+ );
+ }else if (instance.getBusinessType().equals(TypeEnums.TRAVEL_REIMBURSEMENT_APPROVAL.getCode())||instance.getBusinessType().equals(TypeEnums.EXPENSE_APPROVAL.getCode())) {
+ finReimbursementMapper.update(
+ new LambdaUpdateWrapper<FinReimbursement>()
+ .eq(FinReimbursement::getId, instance.getBusinessId())
+ .set(FinReimbursement::getBillStatus, "REJECTED")
+ );
+ }
+ return R.ok("瀹℃壒宸查┏鍥�");
+ }
+
+ private R approveAndMoveNext(ApprovalInstance instance,
+ ApprovalInstanceNode currentNode,
+ ApprovalInstanceDto approvalInstanceDto,
+ LocalDateTime now) {
+ if (!updateCurrentNodeStatus(currentNode.getId(), "APPROVED", now)) {
+ return R.ok("褰撳墠鑺傜偣宸插鐞嗗畬鎴�");
+ }
+
+ closePendingTasks(instance.getId(), currentNode.getId());
+
+ int nextLevel = currentNode.getLevelNo() + 1;
+ ApprovalInstanceNode nextInstanceNode = approvalInstanceNodeService.getOne(
+ new LambdaQueryWrapper<ApprovalInstanceNode>()
+ .eq(ApprovalInstanceNode::getInstanceId, instance.getId())
+ .eq(ApprovalInstanceNode::getLevelNo, nextLevel)
+ .eq(ApprovalInstanceNode::getDeleted, 0)
+ .orderByAsc(ApprovalInstanceNode::getId)
+ .last("LIMIT 1")
+ );
+
+ if (nextInstanceNode != null) {
+ if (!activateNextInstanceNode(nextInstanceNode.getId(), now)) {
+ return R.ok("涓嬩竴瀹℃壒鑺傜偣宸茶婵�娲伙紝璇峰埛鏂板悗閲嶈瘯");
+ }
+ instance.setCurrentLevel(nextLevel);
+ instance.setStatus("PENDING");
+ this.updateById(instance);
+ List<ApprovalTask> nextTasks = approvalTaskService.list(
+ Wrappers.<ApprovalTask>lambdaQuery()
+ .eq(ApprovalTask::getInstanceId, instance.getId())
+ .eq(ApprovalTask::getNodeId, nextInstanceNode.getId())
+ .eq(ApprovalTask::getTaskStatus, "PENDING")
+ .eq(ApprovalTask::getDeleted, 0)
+ );
+ sendApproveNotice(instance, nextTasks);
+ return R.ok("瀹℃壒鎴愬姛锛屽凡娴佽浆鍒颁笅涓�鑺傜偣");
+ }
+
+ ApprovalTemplateNode nextTemplateNode = approvalTemplateNodeService.getOne(
+ new LambdaQueryWrapper<ApprovalTemplateNode>()
+ .eq(ApprovalTemplateNode::getTemplateId, instance.getTemplateId())
+ .eq(ApprovalTemplateNode::getLevelNo, nextLevel)
+ .orderByAsc(ApprovalTemplateNode::getId)
+ .last("LIMIT 1")
+ );
+
+ if (nextTemplateNode == null) {
+ instance.setStatus("APPROVED");
+ instance.setFinishTime(now);
+ this.updateById(instance);
+ handleBusinessAfterApprovalFinished(instance);
+ return R.ok("瀹℃壒宸插畬鎴�");
+ }
+
+ instance.setCurrentLevel(nextLevel);
+ instance.setStatus("PENDING");
+ this.updateById(instance);
+ approveProcessConfigNodeUtils.createCurrentNodeAndTasks(instance, false);
+ sendApproveNotice(instance, approveProcessConfigNodeUtils.getCurrentPendingTasks(approvalInstanceDto.getId()));
+ return R.ok("瀹℃壒鎴愬姛锛屽凡娴佽浆鍒颁笅涓�鑺傜偣");
+ }
+
+ private boolean activateNextInstanceNode(Long nodeId, LocalDateTime now) {
+ return approvalInstanceNodeService.update(
+ Wrappers.<ApprovalInstanceNode>lambdaUpdate()
+ .eq(ApprovalInstanceNode::getId, nodeId)
+ .eq(ApprovalInstanceNode::getStatus, "WAITING")
+ .eq(ApprovalInstanceNode::getDeleted, 0)
+ .set(ApprovalInstanceNode::getStatus, "PENDING")
+ .set(ApprovalInstanceNode::getStartTime, now)
+ );
+ }
+
+ private boolean updateCurrentNodeStatus(Long nodeId, String targetStatus, LocalDateTime now) {
+ // 浠呭厑璁镐竴涓姹傚皢褰撳墠鑺傜偣浠庡緟澶勭悊鎺ㄨ繘鍒扮洰鏍囩姸鎬侊紝閬垮厤閲嶅娴佽浆銆�
+ return approvalInstanceNodeService.update(
+ Wrappers.<ApprovalInstanceNode>lambdaUpdate()
+ .eq(ApprovalInstanceNode::getId, nodeId)
+ .eq(ApprovalInstanceNode::getStatus, "PENDING")
+ .eq(ApprovalInstanceNode::getDeleted, 0)
+ .set(ApprovalInstanceNode::getStatus, targetStatus)
+ .set(ApprovalInstanceNode::getFinishTime, now)
+ );
+ }
+
+ private void handleBusinessAfterApprovalFinished(ApprovalInstance instance) {
+ String status = instance.getStatus();
+ Long businessType = instance.getBusinessType();
+ if (TypeEnums.PURCHASE_APPROVAL.getCode().equals(businessType)) {
+ handlePurchaseApprovalFinished(instance, status);
+ return;
+ }
+ if (TypeEnums.QUOTATION_APPROVAL.getCode().equals(businessType)) {
+ handleSalesQuotationApprovalFinished(instance, status);
+ return;
+ }
+ if (TypeEnums.SHIPPING_APPROVAL.getCode().equals(businessType)) {
+ handleShippingApprovalFinished(instance, status);
+ return;
+ }
+ if (TypeEnums.TRAVEL_REIMBURSEMENT_APPROVAL.getCode().equals(businessType)
+ || TypeEnums.EXPENSE_APPROVAL.getCode().equals(businessType)) {
+ handleReimbursementApprovalFinished(instance, status);
+ return;
+ }
+ // 椹冲洖瀵瑰簲鐨勪紒涓氭柊闂汇�佸姞鐝敵璇枫�佽鍋囩敵璇峰彲浠ラ噸鏂板啀鎻愪氦
+ if (TypeEnums.LEAVE_APPROVAL.getCode().equals(businessType)
+ || TypeEnums.OVERTIME_APPROVAL.getCode().equals(businessType)) {
+ handleHolidayApplicationApprovalFinished(instance, status);
+ return;
+ }
+ if (TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode().equals(businessType)) {
+ handleNewsApprovalFinished(instance, status);
+ }
+ }
+
+ private void handleReimbursementApprovalFinished(ApprovalInstance instance, String status) {
+ if (instance == null || instance.getBusinessId() == null) {
+ return;
+ }
+
+ FinReimbursement reimbursement = new FinReimbursement();
+ reimbursement.setId(instance.getBusinessId());
+ if ("APPROVED".equals(status)) {
+ reimbursement.setBillStatus("APPROVED");
+ reimbursement.setApprovedTime(instance.getFinishTime());
+ } else if ("REJECTED".equals(status)) {
+ reimbursement.setBillStatus("REJECTED");
+ } else if ("PENDING".equals(status)) {
+ reimbursement.setBillStatus("IN_APPROVAL");
+ } else {
+ return;
+ }
+ finReimbursementMapper.updateById(reimbursement);
+ }
+
+ private void handleNewsApprovalFinished(ApprovalInstance instance, String status) {
+ if (instance == null || instance.getBusinessId() == null) {
+ return;
+ }
+ EnterpriseNews enterpriseNews = new EnterpriseNews();
+ enterpriseNews.setId(instance.getBusinessId());
+ if ("APPROVED".equals(status)) {
+ enterpriseNews.setStatus(ENTERPRISE_NEWS_STATUS_PUBLISHED);
+ enterpriseNewsMapper.updateById(enterpriseNews);
+ sendEnterpriseNewsNotice(instance.getBusinessId());
+ return;
+ }
+ if ("REJECTED".equals(status)) {
+ enterpriseNews.setStatus(ENTERPRISE_NEWS_STATUS_REJECTED);
+ enterpriseNewsMapper.updateById(enterpriseNews);
+ }
+ }
+
+ private void handleHolidayApplicationApprovalFinished(ApprovalInstance instance, String status) {
+ if (instance == null || instance.getBusinessId() == null) {
+ return;
+ }
+ HolidayApplication holidayApplication = new HolidayApplication();
+ holidayApplication.setId(instance.getBusinessId());
+ if ("APPROVED".equals(status)) {
+ holidayApplication.setStatus("APPROVED");
+ } else if ("REJECTED".equals(status)) {
+ holidayApplication.setStatus("REJECTED");
+ } else if ("PENDING".equals(status)) {
+ holidayApplication.setStatus("PENDING");
+ } else {
+ return;
+ }
+ holidayApplicationMapper.updateById(holidayApplication);
+ }
+
+ private void handlePurchaseApprovalFinished(ApprovalInstance instance, String status) {
+ PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectOne(
+ new LambdaQueryWrapper<PurchaseLedger>()
+ .eq(PurchaseLedger::getPurchaseContractNumber, instance.getTitle())
+ .last("limit 1")
+ );
+ if (purchaseLedger == null) {
+ return;
+ }
+
+ if ("APPROVED".equals(status)) {
+ purchaseLedger.setApprovalStatus(ApprovalStatusEnum.APPROVED.getCode());
+ List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(
+ new QueryWrapper<SalesLedgerProduct>().lambda()
+ .eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId())
+ .eq(SalesLedgerProduct::getType, 2)
+ );
+ for (SalesLedgerProduct salesLedgerProduct : salesLedgerProducts) {
+ if (salesLedgerProduct.getIsChecked()) {
+ qualityInspectHelper.addQualityInspect(purchaseLedger, salesLedgerProduct);
+ } else {
+ stockUtils.addStockWithBatchNo(
+ salesLedgerProduct.getProductModelId(),
+ salesLedgerProduct.getQuantity(),
+ StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(),
+ purchaseLedger.getId(),
+ purchaseLedger.getPurchaseContractNumber() + "-" + salesLedgerProduct.getId()
+ );
+ }
+ }
+ } else if ("REJECTED".equals(status)) {
+ purchaseLedger.setApprovalStatus(ApprovalStatusEnum.REJECTED.getCode());
+ } else if ("PENDING".equals(status)) {
+ purchaseLedger.setApprovalStatus(ApprovalStatusEnum.IN_PROGRESS.getCode());
+ }
+ purchaseLedgerMapper.updateById(purchaseLedger);
+ }
+
+ private void handleSalesQuotationApprovalFinished(ApprovalInstance instance, String status) {
+ SalesQuotation salesQuote = salesQuotationMapper.selectOne(
+ new LambdaQueryWrapper<SalesQuotation>()
+ .eq(SalesQuotation::getQuotationNo, instance.getTitle())
+ .last("limit 1")
+ );
+ if (salesQuote == null) {
+ return;
+ }
+
+ if ("APPROVED".equals(status)) {
+ salesQuote.setStatus(SalesQuotationStatusEnum.APPROVED.getCode());
+ } else if ("REJECTED".equals(status)) {
+ salesQuote.setStatus(SalesQuotationStatusEnum.REJECTED.getCode());
+ } else if ("PENDING".equals(status)) {
+ salesQuote.setStatus(SalesQuotationStatusEnum.IN_PROGRESS.getCode());
+ }
+ salesQuotationMapper.updateById(salesQuote);
+ }
+
+ private void handleShippingApprovalFinished(ApprovalInstance instance, String status) {
+ ShippingInfo shippingInfo = shippingInfoMapper.selectOne(
+ new LambdaQueryWrapper<ShippingInfo>()
+ .eq(ShippingInfo::getShippingNo, instance.getTitle())
+ .orderByDesc(ShippingInfo::getCreateTime)
+ .last("limit 1")
+ );
+ if (shippingInfo == null) {
+ return;
+ }
+
+ if ("APPROVED".equals(status)) {
+ shippingInfo.setStatus(ShippingStatusEnum.APPROVED.getCode());
+ shippingInfo.setShippingDate(new Date());
+ stockUtils.shipmentStatus(StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), shippingInfo.getId());
+ } else if ("REJECTED".equals(status)) {
+ stockUtils.deleteStockOutRecord(shippingInfo.getId(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode());
+ shippingInfo.setStatus(ShippingStatusEnum.REJECTED.getCode());
+ } else if ("PENDING".equals(status)) {
+ shippingInfo.setStatus(ShippingStatusEnum.IN_PROGRESS.getCode());
+ }
+ shippingInfoMapper.updateById(shippingInfo);
+ }
+
+ private List<ApprovalTask> createNodeAndTasks(ApprovalInstance instance, ApprovalTemplateNode templateNode) {
+ List<ApprovalTemplateNodeApprover> approvers = approvalTemplateNodeApproverMapper.selectList(
+ new LambdaQueryWrapper<ApprovalTemplateNodeApprover>()
+ .eq(ApprovalTemplateNodeApprover::getTemplateId, instance.getTemplateId())
+ .eq(ApprovalTemplateNodeApprover::getNodeId, templateNode.getId())
+ .eq(ApprovalTemplateNodeApprover::getDeleted, 0L)
+ .orderByAsc(ApprovalTemplateNodeApprover::getSortNo)
+ );
+ if (approvers == null || approvers.isEmpty()) {
+ throw new RuntimeException("涓嬩竴瀹℃壒鑺傜偣鏈厤缃鎵逛汉");
+ }
+
+ ApprovalInstanceNode instanceNode = new ApprovalInstanceNode();
+ instanceNode.setInstanceId(instance.getId());
+ instanceNode.setLevelNo(templateNode.getLevelNo());
+ instanceNode.setApproveType(templateNode.getApproveType());
+ instanceNode.setStatus("PENDING");
+ instanceNode.setStartTime(LocalDateTime.now());
+ instanceNode.setDeleted((byte) 0);
+ approvalInstanceNodeService.save(instanceNode);
+
+ List<ApprovalTask> taskList = new ArrayList<>(approvers.size());
+ for (ApprovalTemplateNodeApprover approver : approvers) {
+ ApprovalTask task = new ApprovalTask();
+ task.setInstanceId(instance.getId());
+ task.setNodeId(instanceNode.getId());
+ task.setLevelNo(instanceNode.getLevelNo());
+ task.setApproverId(approver.getApproverId());
+ task.setApproverName(approver.getApproverName());
+ task.setTaskStatus("PENDING");
+ task.setIsRead((byte) 0);
+ task.setDeleted((byte) 0);
+ taskList.add(task);
+ }
+ approvalTaskService.saveBatch(taskList);
+ return taskList;
+ }
+
+ private void sendApproveNotice(ApprovalInstance instance, List<ApprovalTask> tasks) {
+ if (instance == null || tasks == null || tasks.isEmpty()) {
+ return;
+ }
+
+ List<Long> approverIds = tasks.stream()
+ .map(ApprovalTask::getApproverId)
+ .filter(id -> id != null && id > 0)
+ .distinct()
+ .collect(Collectors.toList());
+ if (approverIds.isEmpty()) {
+ return;
+ }
+
+ String title = StringUtils.hasText(instance.getTemplateName()) ? instance.getTemplateName() : "瀹℃壒鎻愰啋";
+ String message = "瀹℃壒鍗曞彿 " + instance.getInstanceNo() + " 闇�瑕佹偍瀹℃壒";
+ String jumpPath = "/officeProcessAutomation/ApproveManage/approve-list?id=" + instance.getId();
+ sysNoticeService.simpleNoticeByUser(title, message, approverIds, jumpPath);
+ }
+
+ private void sendEnterpriseNewsNotice(Long newsId) {
+ EnterpriseNews enterpriseNews = enterpriseNewsMapper.selectById(newsId);
+ if (enterpriseNews == null) {
+ return;
+ }
+ List<Long> userIds = getEnterpriseNewsNoticeUserIds(enterpriseNews);
+ if (userIds == null || userIds.isEmpty()) {
+ return;
+ }
+ String title = "浼佷笟鏂伴椈";
+ String message = "鎮ㄦ湁鏂扮殑浼佷笟鏂伴椈銆�" + enterpriseNews.getTitle() + "銆嬭鍙婃椂鏌ラ槄";
+ String jumpPath = "/officeProcessAutomation/EnterpriseNews?id=" + newsId;
+ sysNoticeService.simpleNoticeByUser(title, message, userIds, jumpPath);
+ }
+
+ private List<Long> getEnterpriseNewsNoticeUserIds(EnterpriseNews enterpriseNews) {
+ if (enterpriseNews == null || !org.springframework.util.StringUtils.hasText(enterpriseNews.getReadScope())) {
+ return Collections.emptyList();
+ }
+ String readScope = enterpriseNews.getReadScope().trim();
+ if ("all".equals(readScope)) {
+ return sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>()
+ .select(SysUser::getUserId)
+ .eq(SysUser::getDelFlag, "0"))
+ .stream()
+ .map(SysUser::getUserId)
+ .filter(id -> id != null && id > 0)
+ .distinct()
+ .collect(Collectors.toList());
+ }
+ if ("dept".equals(readScope)) {
+ List<Long> deptIds = enterpriseNewsScopeDeptMapper.selectList(
+ new LambdaQueryWrapper<EnterpriseNewsScopeDept>()
+ .eq(EnterpriseNewsScopeDept::getNewsId, enterpriseNews.getId()))
+ .stream()
+ .map(EnterpriseNewsScopeDept::getDeptId)
+ .filter(id -> id != null && id > 0)
+ .distinct()
+ .collect(Collectors.toList());
+ if (deptIds.isEmpty()) {
+ return Collections.emptyList();
+ }
+ return sysUserDeptMapper.selectDistinctUserIdsByDeptIds(collectDeptIdsWithChildren(deptIds));
+ }
+ if ("custom".equals(readScope)) {
+ return enterpriseNewsScopeUserMapper.selectList(
+ new LambdaQueryWrapper<EnterpriseNewsScopeUser>()
+ .eq(EnterpriseNewsScopeUser::getNewsId, enterpriseNews.getId()))
+ .stream()
+ .map(EnterpriseNewsScopeUser::getUserId)
+ .filter(id -> id != null && id > 0)
+ .distinct()
+ .collect(Collectors.toList());
+ }
+ return Collections.emptyList();
+ }
+
+ private List<Long> collectDeptIdsWithChildren(List<Long> deptIds) {
+ Set<Long> allDeptIds = new LinkedHashSet<>();
+ for (Long deptId : deptIds) {
+ if (deptId == null) {
+ continue;
+ }
+ allDeptIds.add(deptId);
+ List<SysDept> children = sysDeptMapper.selectChildrenDeptById(deptId);
+ if (children != null && !children.isEmpty()) {
+ for (SysDept child : children) {
+ if (child != null && child.getDeptId() != null) {
+ allDeptIds.add(child.getDeptId());
+ }
+ }
+ }
+ }
+ return new ArrayList<>(allDeptIds);
+ }
+
+ private void closePendingTasks(Long instanceId, Long nodeId) {
+ LambdaUpdateWrapper<ApprovalTask> updateWrapper = Wrappers.lambdaUpdate();
+ updateWrapper.eq(ApprovalTask::getInstanceId, instanceId)
+ .eq(ApprovalTask::getNodeId, nodeId)
+ .eq(ApprovalTask::getTaskStatus, "PENDING")
+ .eq(ApprovalTask::getDeleted, 0)
+ .set(ApprovalTask::getDeleted, (byte) 1);
+ approvalTaskService.update(updateWrapper);
+ }
+
+ private void saveApprovalRecord(Long instanceId,
+ Long nodeId,
+ Long taskId,
+ Long operatorId,
+ String operatorName,
+ String action,
+ String comment) {
+ ApprovalRecord record = new ApprovalRecord();
+ record.setInstanceId(instanceId);
+ record.setNodeId(nodeId);
+ record.setTaskId(taskId);
+ record.setOperatorId(operatorId);
+ record.setOperatorName(operatorName);
+ record.setAction(action);
+ record.setComment(comment);
+ record.setDeleted((byte) 0);
+ approvalRecordService.save(record);
+ }
+
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApprovalRecordServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApprovalRecordServiceImpl.java
new file mode 100644
index 0000000..50911e4
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApprovalRecordServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.approve.service.impl;
+
+import com.ruoyi.approve.pojo.ApprovalRecord;
+import com.ruoyi.approve.mapper.ApprovalRecordMapper;
+import com.ruoyi.approve.service.ApprovalRecordService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 瀹℃壒璁板綍琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:28:21
+ */
+@Service
+public class ApprovalRecordServiceImpl extends ServiceImpl<ApprovalRecordMapper, ApprovalRecord> implements ApprovalRecordService {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApprovalTaskServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApprovalTaskServiceImpl.java
new file mode 100644
index 0000000..14e10ca
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApprovalTaskServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.approve.service.impl;
+
+import com.ruoyi.approve.pojo.ApprovalTask;
+import com.ruoyi.approve.mapper.ApprovalTaskMapper;
+import com.ruoyi.approve.service.ApprovalTaskService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 瀹℃壒浠诲姟琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 03:32:37
+ */
+@Service
+public class ApprovalTaskServiceImpl extends ServiceImpl<ApprovalTaskMapper, ApprovalTask> implements ApprovalTaskService {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateNodeApproverServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateNodeApproverServiceImpl.java
new file mode 100644
index 0000000..0921c35
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateNodeApproverServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.approve.service.impl;
+
+import com.ruoyi.approve.pojo.ApprovalTemplateNodeApprover;
+import com.ruoyi.approve.mapper.ApprovalTemplateNodeApproverMapper;
+import com.ruoyi.approve.service.ApprovalTemplateNodeApproverService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 瀹℃壒妯℃澘鑺傜偣瀹℃壒浜鸿〃 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 11:20:30
+ */
+@Service
+public class ApprovalTemplateNodeApproverServiceImpl extends ServiceImpl<ApprovalTemplateNodeApproverMapper, ApprovalTemplateNodeApprover> implements ApprovalTemplateNodeApproverService {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateNodeServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateNodeServiceImpl.java
new file mode 100644
index 0000000..ca65a5f
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateNodeServiceImpl.java
@@ -0,0 +1,62 @@
+package com.ruoyi.approve.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.approve.bean.dto.ApprovalTemplateNodeApproverDto;
+import com.ruoyi.approve.bean.dto.ApprovalTemplateNodeDto;
+import com.ruoyi.approve.mapper.ApprovalTemplateNodeMapper;
+import com.ruoyi.approve.pojo.ApprovalTemplateNode;
+import com.ruoyi.approve.pojo.ApprovalTemplateNodeApprover;
+import com.ruoyi.approve.service.ApprovalTemplateNodeApproverService;
+import com.ruoyi.approve.service.ApprovalTemplateNodeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹℃壒妯℃澘鑺傜偣琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-18 11:20:19
+ */
+@Service
+@RequiredArgsConstructor
+public class ApprovalTemplateNodeServiceImpl extends ServiceImpl<ApprovalTemplateNodeMapper, ApprovalTemplateNode> implements ApprovalTemplateNodeService {
+
+ private final ApprovalTemplateNodeMapper approvalTemplateNodeMapper;
+ private final ApprovalTemplateNodeApproverService approvalTemplateNodeApproverService;
+ @Override
+ public Boolean saveApprovalTemplateNode(Long templateId, List<ApprovalTemplateNodeDto> nodes) {
+ if (nodes == null || nodes.isEmpty()) {
+ throw new RuntimeException("鑺傜偣鍒楄〃涓嶈兘涓虹┖");
+ }
+
+ List<ApprovalTemplateNodeApprover> approverList = new ArrayList<>();
+
+ for (ApprovalTemplateNodeDto nodeDto : nodes) {
+ ApprovalTemplateNode node = new ApprovalTemplateNode();
+ BeanUtils.copyProperties(nodeDto, node);
+ node.setTemplateId(templateId);
+ approvalTemplateNodeMapper.insert(node);
+
+ List<ApprovalTemplateNodeApproverDto> approvers = nodeDto.getApprovers();
+ if (approvers == null || approvers.isEmpty()) {
+ throw new RuntimeException("鑺傜偣瀹℃壒浜轰笉鑳戒负绌�");
+ }
+ for (ApprovalTemplateNodeApproverDto approverDto : approvers) {
+ ApprovalTemplateNodeApprover approver = new ApprovalTemplateNodeApprover();
+ BeanUtils.copyProperties(approverDto, approver);
+ approver.setNodeId(node.getId());
+ approver.setTemplateId(templateId);
+ approver.setDeleted(0L);
+ approverList.add(approver);
+ }
+ }
+ approvalTemplateNodeApproverService.saveBatch(approverList);
+ return true;
+ }
+}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateServiceImpl.java
new file mode 100644
index 0000000..af5a774
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateServiceImpl.java
@@ -0,0 +1,250 @@
+package com.ruoyi.approve.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.approve.bean.dto.ApprovalTemplateDto;
+import com.ruoyi.approve.bean.vo.ApprovalTemplateNodeApproverVo;
+import com.ruoyi.approve.bean.vo.ApprovalTemplateNodeVo;
+import com.ruoyi.approve.bean.vo.ApprovalTemplateVo;
+import com.ruoyi.approve.mapper.ApprovalTemplateMapper;
+import com.ruoyi.approve.mapper.ApprovalTemplateNodeApproverMapper;
+import com.ruoyi.approve.pojo.ApprovalTemplate;
+import com.ruoyi.approve.pojo.ApprovalTemplateNode;
+import com.ruoyi.approve.pojo.ApprovalTemplateNodeApprover;
+import com.ruoyi.approve.service.ApprovalTemplateNodeService;
+import com.ruoyi.approve.service.ApprovalTemplateService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 瀹℃壒妯℃澘鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @since 2026-05-18 11:20:08
+ */
+@Service
+@RequiredArgsConstructor
+public class ApprovalTemplateServiceImpl extends ServiceImpl<ApprovalTemplateMapper, ApprovalTemplate> implements ApprovalTemplateService {
+
+ private final ApprovalTemplateMapper approvalTemplateMapper;
+ private final ApprovalTemplateNodeService approvalTemplateNodeService;
+ private final ApprovalTemplateNodeApproverMapper approvalTemplateNodeApproverMapper;
+
+ @Override
+ public IPage<ApprovalTemplateVo> listPage(Page<ApprovalTemplateVo> page, ApprovalTemplateDto approvalTemplateDto) {
+ IPage<ApprovalTemplateVo> approvalTemplateVoIPage = approvalTemplateMapper.listPage(page, approvalTemplateDto);
+ fillTemplateVoNodes(approvalTemplateVoIPage.getRecords());
+ return approvalTemplateVoIPage;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean saveApprovalTemplateDto(ApprovalTemplateDto approvalTemplateDto) {
+ approvalTemplateMapper.insert(approvalTemplateDto);
+ approvalTemplateNodeService.remove(
+ new LambdaQueryWrapper<ApprovalTemplateNode>()
+ .eq(ApprovalTemplateNode::getTemplateId, approvalTemplateDto.getId())
+ );
+ approvalTemplateNodeApproverMapper.delete(
+ new LambdaQueryWrapper<ApprovalTemplateNodeApprover>()
+ .eq(ApprovalTemplateNodeApprover::getTemplateId, approvalTemplateDto.getId())
+ );
+ return approvalTemplateNodeService.saveApprovalTemplateNode(
+ approvalTemplateDto.getId(),
+ approvalTemplateDto.getNodes()
+ );
+ }
+
+ @Override
+ public Boolean updateApprovalTemplateDto(ApprovalTemplateDto approvalTemplateDto) {
+ approvalTemplateMapper.updateById(approvalTemplateDto);
+ approvalTemplateNodeService.remove(
+ new LambdaQueryWrapper<ApprovalTemplateNode>()
+ .eq(ApprovalTemplateNode::getTemplateId, approvalTemplateDto.getId())
+ );
+ approvalTemplateNodeApproverMapper.delete(
+ new LambdaQueryWrapper<ApprovalTemplateNodeApprover>()
+ .eq(ApprovalTemplateNodeApprover::getTemplateId, approvalTemplateDto.getId())
+ );
+ return approvalTemplateNodeService.saveApprovalTemplateNode(
+ approvalTemplateDto.getId(),
+ approvalTemplateDto.getNodes()
+ );
+ }
+
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean delete(List<Long> ids) {
+ if (ids == null || ids.isEmpty()) {
+ return false;
+ }
+ ApprovalTemplate updateEntity = new ApprovalTemplate();
+ updateEntity.setDeleted(1);
+ LambdaUpdateWrapper<ApprovalTemplate> updateWrapper = Wrappers.lambdaUpdate();
+ updateWrapper.in(ApprovalTemplate::getId, ids)
+ .eq(ApprovalTemplate::getDeleted, 0);
+
+ int rows = approvalTemplateMapper.update(updateEntity, updateWrapper);
+ return rows == ids.size();
+ }
+
+ @Override
+ public List<ApprovalTemplateVo> listApprovalTemplateVo(Integer type) {
+ List<ApprovalTemplate> templateList = this.list(
+ new LambdaQueryWrapper<ApprovalTemplate>()
+ .eq(ApprovalTemplate::getDeleted, 0)
+ .eq(ApprovalTemplate::getEnabled, 1)
+ .orderByDesc(ApprovalTemplate::getTemplateType)
+ .orderByDesc(ApprovalTemplate::getId)
+ );
+ if (CollUtil.isEmpty(templateList)) {
+ return Collections.emptyList();
+ }
+
+ List<ApprovalTemplateVo> templateVos = templateList.stream()
+ .map(template -> {
+ ApprovalTemplateVo templateVo = new ApprovalTemplateVo();
+ BeanUtils.copyProperties(template, templateVo);
+ return templateVo;
+ })
+ .collect(Collectors.toList());
+ fillTemplateVoNodes(templateVos);
+ return templateVos;
+ }
+
+ @Override
+ public ApprovalTemplateVo getApprovalTemplateVoById(Long id) {
+ if (id == null) {
+ throw new IllegalArgumentException("鍙傛暟 id 涓嶈兘涓虹┖");
+ }
+
+ ApprovalTemplate template = this.getOne(
+ new LambdaQueryWrapper<ApprovalTemplate>()
+ .eq(ApprovalTemplate::getId, id)
+ .eq(ApprovalTemplate::getDeleted, 0)
+ );
+ if (template == null) {
+ throw new IllegalArgumentException("妯℃澘涓嶅瓨鍦�");
+ }
+
+ List<ApprovalTemplateNode> nodeList = approvalTemplateNodeService.list(
+ new LambdaQueryWrapper<ApprovalTemplateNode>()
+ .eq(ApprovalTemplateNode::getTemplateId, id)
+ .orderByAsc(ApprovalTemplateNode::getLevelNo)
+ );
+
+ List<ApprovalTemplateNodeApprover> approverList = approvalTemplateNodeApproverMapper.selectList(
+ new LambdaQueryWrapper<ApprovalTemplateNodeApprover>()
+ .eq(ApprovalTemplateNodeApprover::getTemplateId, id)
+ .eq(ApprovalTemplateNodeApprover::getDeleted, 0L)
+ );
+
+ Map<Long, List<ApprovalTemplateNode>> nodeMap = nodeList.stream()
+ .collect(Collectors.groupingBy(ApprovalTemplateNode::getTemplateId));
+
+ Map<Long, List<ApprovalTemplateNodeApprover>> approverMap = approverList.stream()
+ .collect(Collectors.groupingBy(ApprovalTemplateNodeApprover::getNodeId));
+
+ return buildTemplateVo(template, nodeMap, approverMap);
+ }
+
+ /**
+ * 鎵归噺濉厖妯℃澘鑺傜偣鍙婅妭鐐瑰鎵逛汉锛岄伩鍏嶅惊鐜煡搴撱��
+ */
+ private void fillTemplateVoNodes(List<ApprovalTemplateVo> templateVos) {
+ if (CollUtil.isEmpty(templateVos)) {
+ return;
+ }
+
+ List<Long> templateIds = templateVos.stream()
+ .map(ApprovalTemplateVo::getId)
+ .collect(Collectors.toList());
+
+ List<ApprovalTemplateNode> nodeList = approvalTemplateNodeService.list(
+ new LambdaQueryWrapper<ApprovalTemplateNode>()
+ .in(ApprovalTemplateNode::getTemplateId, templateIds)
+ .orderByAsc(ApprovalTemplateNode::getLevelNo)
+ );
+
+ List<ApprovalTemplateNodeApprover> approverList = approvalTemplateNodeApproverMapper.selectList(
+ new LambdaQueryWrapper<ApprovalTemplateNodeApprover>()
+ .in(ApprovalTemplateNodeApprover::getTemplateId, templateIds)
+ .eq(ApprovalTemplateNodeApprover::getDeleted, 0L)
+ );
+
+ Map<Long, List<ApprovalTemplateNode>> nodeMap = nodeList.stream()
+ .collect(Collectors.groupingBy(ApprovalTemplateNode::getTemplateId));
+
+ Map<Long, List<ApprovalTemplateNodeApprover>> approverMap = approverList.stream()
+ .collect(Collectors.groupingBy(ApprovalTemplateNodeApprover::getNodeId));
+
+ templateVos.forEach(templateVo -> templateVo.setNodes(
+ nodeMap.getOrDefault(templateVo.getId(), Collections.emptyList())
+ .stream()
+ .sorted(Comparator.comparing(
+ ApprovalTemplateNode::getLevelNo,
+ Comparator.nullsLast(Integer::compareTo)
+ ))
+ .map(node -> buildNodeVo(node, approverMap))
+ .collect(Collectors.toList())
+ ));
+ }
+
+ private ApprovalTemplateVo buildTemplateVo(ApprovalTemplate template,
+ Map<Long, List<ApprovalTemplateNode>> nodeMap,
+ Map<Long, List<ApprovalTemplateNodeApprover>> approverMap) {
+ ApprovalTemplateVo templateVo = new ApprovalTemplateVo();
+ BeanUtils.copyProperties(template, templateVo);
+
+ List<ApprovalTemplateNodeVo> nodeVos = nodeMap
+ .getOrDefault(template.getId(), Collections.emptyList())
+ .stream()
+ .sorted(Comparator.comparing(
+ ApprovalTemplateNode::getLevelNo,
+ Comparator.nullsLast(Integer::compareTo)
+ ))
+ .map(node -> buildNodeVo(node, approverMap))
+ .collect(Collectors.toList());
+
+ templateVo.setNodes(nodeVos);
+ return templateVo;
+ }
+
+ private ApprovalTemplateNodeVo buildNodeVo(ApprovalTemplateNode node,
+ Map<Long, List<ApprovalTemplateNodeApprover>> approverMap) {
+ ApprovalTemplateNodeVo nodeVo = new ApprovalTemplateNodeVo();
+ BeanUtils.copyProperties(node, nodeVo);
+
+ List<ApprovalTemplateNodeApproverVo> approverVos = approverMap
+ .getOrDefault(node.getId(), Collections.emptyList())
+ .stream()
+ .sorted(Comparator.comparing(
+ ApprovalTemplateNodeApprover::getSortNo,
+ Comparator.nullsLast(Integer::compareTo)
+ ))
+ .map(this::buildApproverVo)
+ .collect(Collectors.toList());
+
+ nodeVo.setApprovers(approverVos);
+ return nodeVo;
+ }
+
+ private ApprovalTemplateNodeApproverVo buildApproverVo(ApprovalTemplateNodeApprover approver) {
+ ApprovalTemplateNodeApproverVo approverVo = new ApprovalTemplateNodeApproverVo();
+ BeanUtils.copyProperties(approver, approverVo);
+ return approverVo;
+ }
+}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApproveBusinessStatusService.java b/src/main/java/com/ruoyi/approve/service/impl/ApproveBusinessStatusService.java
new file mode 100644
index 0000000..8135c3a
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveBusinessStatusService.java
@@ -0,0 +1,175 @@
+package com.ruoyi.approve.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
+import com.ruoyi.procurementrecord.utils.StockUtils;
+import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
+import com.ruoyi.purchase.pojo.PurchaseLedger;
+import com.ruoyi.quality.mapper.QualityInspectMapper;
+import com.ruoyi.quality.mapper.QualityInspectParamMapper;
+import com.ruoyi.quality.mapper.QualityTestStandardMapper;
+import com.ruoyi.quality.mapper.QualityTestStandardParamMapper;
+import com.ruoyi.quality.pojo.QualityInspect;
+import com.ruoyi.quality.pojo.QualityInspectParam;
+import com.ruoyi.quality.pojo.QualityTestStandard;
+import com.ruoyi.quality.pojo.QualityTestStandardParam;
+import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
+import com.ruoyi.sales.mapper.SalesQuotationMapper;
+import com.ruoyi.sales.mapper.ShippingInfoMapper;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.sales.pojo.SalesQuotation;
+import com.ruoyi.sales.pojo.ShippingInfo;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.util.Date;
+import java.util.List;
+
+@Service
+@RequiredArgsConstructor
+public class ApproveBusinessStatusService {
+
+ private final PurchaseLedgerMapper purchaseLedgerMapper;
+ private final SalesQuotationMapper salesQuotationMapper;
+ private final ShippingInfoMapper shippingInfoMapper;
+ private final SalesLedgerProductMapper salesLedgerProductMapper;
+ private final StockUtils stockUtils;
+ private final QualityInspectMapper qualityInspectMapper;
+ private final QualityTestStandardMapper qualityTestStandardMapper;
+ private final QualityTestStandardParamMapper qualityTestStandardParamMapper;
+ private final QualityInspectParamMapper qualityInspectParamMapper;
+
+ /**
+ * 缁熶竴鍚屾瀹℃壒缁撴灉瀵瑰簲鐨勪笟鍔″崟鎹姸鎬併��
+ * status锛�1-瀹℃牳涓紝2-瀹℃牳瀹屾垚锛�3-瀹℃牳鏈�氳繃銆�
+ */
+ public void syncBusinessStatus(Integer approveType, String approveReason, Integer status) {
+ if (approveType == null || status == null || !StringUtils.hasText(approveReason)) {
+ return;
+ }
+ switch (approveType) {
+ case 5:
+ syncPurchaseStatus(approveReason, status);
+ break;
+ case 6:
+ syncSalesQuotationStatus(approveReason, status);
+ break;
+ case 7:
+ syncShippingStatus(approveReason, status);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // 閲囪喘瀹℃壒閫氳繃鏃讹紝鎸変骇鍝佽川妫�閰嶇疆鍐冲畾鐢熸垚璐ㄦ鍗曟垨鐩存帴鍏ュ簱銆�
+ private void syncPurchaseStatus(String approveReason, Integer status) {
+ PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectOne(new LambdaQueryWrapper<PurchaseLedger>()
+ .eq(PurchaseLedger::getPurchaseContractNumber, approveReason)
+ .last("limit 1"));
+ if (purchaseLedger == null) {
+ return;
+ }
+ if (status.equals(2)) {
+ purchaseLedger.setApprovalStatus(3);
+ List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(new QueryWrapper<SalesLedgerProduct>()
+ .lambda().eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId()).eq(SalesLedgerProduct::getType, 2));
+ for (SalesLedgerProduct salesLedgerProduct : salesLedgerProducts) {
+ if (Boolean.TRUE.equals(salesLedgerProduct.getIsChecked())) {
+ addQualityInspect(purchaseLedger, salesLedgerProduct);
+ } else {
+ stockUtils.addStockWithBatchNo(
+ salesLedgerProduct.getProductModelId(),
+ salesLedgerProduct.getQuantity(),
+ StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(),
+ purchaseLedger.getId(),
+ purchaseLedger.getPurchaseContractNumber() + "-" + salesLedgerProduct.getId());
+ }
+ }
+ } else if (status.equals(3)) {
+ purchaseLedger.setApprovalStatus(4);
+ } else if (status.equals(1)) {
+ purchaseLedger.setApprovalStatus(2);
+ } else {
+ return;
+ }
+ purchaseLedgerMapper.updateById(purchaseLedger);
+ }
+
+ // 鎶ヤ环瀹℃壒鐘舵�佸洖鍐欏埌閿�鍞姤浠峰崟鐘舵�併��
+ private void syncSalesQuotationStatus(String approveReason, Integer status) {
+ SalesQuotation salesQuote = salesQuotationMapper.selectOne(new LambdaQueryWrapper<SalesQuotation>()
+ .eq(SalesQuotation::getQuotationNo, approveReason)
+ .last("limit 1"));
+ if (salesQuote == null) {
+ return;
+ }
+ if (status.equals(2)) {
+ salesQuote.setStatus("閫氳繃");
+ } else if (status.equals(3)) {
+ salesQuote.setStatus("鎷掔粷");
+ } else if (status.equals(1)) {
+ salesQuote.setStatus("瀹℃牳涓�");
+ } else {
+ return;
+ }
+ salesQuotationMapper.updateById(salesQuote);
+ }
+
+ // 鍙戣揣瀹℃壒閫氳繃鏃跺悓姝ュ彂璐х姸鎬佸拰鍑哄簱瀹℃壒鐘舵�侊紱鎷掔粷鏃跺垹闄ゅ緟纭鍑哄簱璁板綍銆�
+ private void syncShippingStatus(String approveReason, Integer status) {
+ ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
+ .eq(ShippingInfo::getShippingNo, approveReason)
+ .orderByDesc(ShippingInfo::getCreateTime)
+ .last("limit 1"));
+ if (shippingInfo == null) {
+ return;
+ }
+ if (status.equals(2)) {
+ shippingInfo.setStatus("瀹℃牳閫氳繃");
+ shippingInfo.setShippingDate(new Date());
+ stockUtils.shipmentStatus(StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), shippingInfo.getId());
+ } else if (status.equals(3)) {
+ stockUtils.deleteStockOutRecord(shippingInfo.getId(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode());
+ shippingInfo.setStatus("瀹℃牳鎷掔粷");
+ } else if (status.equals(1)) {
+ shippingInfo.setStatus("瀹℃牳涓�");
+ } else {
+ return;
+ }
+ shippingInfoMapper.updateById(shippingInfo);
+ }
+
+ // 鐢熸垚閲囪喘璐ㄦ鍗曪紝骞舵寜浜у搧璐ㄦ鏍囧噯鍒濆鍖栬川妫�鍙傛暟銆�
+ private void addQualityInspect(PurchaseLedger purchaseLedger, SalesLedgerProduct saleProduct) {
+ QualityInspect qualityInspect = new QualityInspect();
+ qualityInspect.setInspectType(0);
+ qualityInspect.setSupplier(purchaseLedger.getSupplierName());
+ qualityInspect.setPurchaseLedgerId(purchaseLedger.getId());
+ qualityInspect.setProductId(saleProduct.getProductId());
+ qualityInspect.setProductName(saleProduct.getProductCategory());
+ qualityInspect.setModel(saleProduct.getSpecificationModel());
+ qualityInspect.setProductModelId(saleProduct.getProductModelId());
+ qualityInspect.setUnit(saleProduct.getUnit());
+ qualityInspect.setQuantity(saleProduct.getQuantity());
+ qualityInspectMapper.insert(qualityInspect);
+ List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(saleProduct.getProductId(), 0, null);
+ if (qualityTestStandard.size() > 0) {
+ qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId());
+ qualityInspectMapper.updateById(qualityInspect);
+ qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery()
+ .eq(QualityTestStandardParam::getTestStandardId, qualityTestStandard.get(0).getId()))
+ .forEach(qualityTestStandardParam -> {
+ QualityInspectParam param = new QualityInspectParam();
+ com.ruoyi.common.utils.bean.BeanUtils.copyProperties(qualityTestStandardParam, param);
+ param.setId(null);
+ param.setInspectId(qualityInspect.getId());
+ qualityInspectParamMapper.insert(param);
+ });
+ }
+ }
+}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
index 0b1a854..964be23 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
@@ -1,7 +1,6 @@
package com.ruoyi.approve.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -14,26 +13,12 @@
import com.ruoyi.basic.enums.RecordTypeEnum;
import com.ruoyi.basic.utils.FileUtil;
import com.ruoyi.common.enums.FileNameType;
-import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.device.mapper.DeviceRepairMapper;
-import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.project.system.service.ISysNoticeService;
-import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
-import com.ruoyi.purchase.pojo.PurchaseLedger;
-import com.ruoyi.quality.mapper.QualityInspectMapper;
-import com.ruoyi.quality.mapper.QualityInspectParamMapper;
-import com.ruoyi.quality.mapper.QualityTestStandardMapper;
-import com.ruoyi.quality.mapper.QualityTestStandardParamMapper;
-import com.ruoyi.quality.pojo.QualityInspect;
-import com.ruoyi.quality.pojo.QualityInspectParam;
-import com.ruoyi.quality.pojo.QualityTestStandard;
-import com.ruoyi.quality.pojo.QualityTestStandardParam;
-import com.ruoyi.sales.mapper.*;
-import com.ruoyi.sales.pojo.*;
+import com.ruoyi.sales.mapper.CommonFileMapper;
+import com.ruoyi.sales.pojo.CommonFile;
import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -55,18 +40,8 @@
private final SysUserMapper sysUserMapper;
private final ISysNoticeService sysNoticeService;
private final CommonFileMapper fileMapper;
- private final DeviceRepairMapper deviceRepairMapper;
- private final PurchaseLedgerMapper purchaseLedgerMapper;
- private final SalesQuotationMapper salesQuotationMapper;
- private final ShippingInfoMapper shippingInfoMapper;
- private final ShippingProductDetailMapper shippingProductDetailMapper;
private final CommonFileServiceImpl commonFileService;
- private final StockUtils stockUtils;
- private final SalesLedgerProductMapper salesLedgerProductMapper;
- private final QualityInspectMapper qualityInspectMapper;
- private final QualityTestStandardMapper qualityTestStandardMapper;
- private final QualityTestStandardParamMapper qualityTestStandardParamMapper;
- private final QualityInspectParamMapper qualityInspectParamMapper;
+ private final ApproveBusinessStatusService approveBusinessStatusService;
private final FileUtil fileUtil;
@@ -162,74 +137,7 @@
}
approveProcessMapper.updateById(approveProcess);
- //閲囪喘瀹℃牳
- if (approveProcess.getApproveType().equals(5)) {
- PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectOne(new LambdaQueryWrapper<PurchaseLedger>()
- .eq(PurchaseLedger::getPurchaseContractNumber, approveProcess.getApproveReason())
- .last("limit 1"));
- if (purchaseLedger != null) {
- if (status.equals(2)) {
- // 鍚屾剰
- purchaseLedger.setApprovalStatus(3);
- List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(new QueryWrapper<SalesLedgerProduct>()
- .lambda().eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId()).eq(SalesLedgerProduct::getType, 2));
- for (SalesLedgerProduct salesLedgerProduct : salesLedgerProducts) {
- // 璐ㄦ
- if (salesLedgerProduct.getIsChecked()) {
- addQualityInspect(purchaseLedger, salesLedgerProduct);
- } else {
- //鐩存帴鍏ュ簱
- stockUtils.addStockWithBatchNo(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(), purchaseLedger.getId(), purchaseLedger.getPurchaseContractNumber() + "-" + salesLedgerProduct.getId());
- }
- }
- } else if (status.equals(3)) {
- // 鎷掔粷
- purchaseLedger.setApprovalStatus(4);
- } else if (status.equals(1)) {
- // 瀹℃牳涓�
- purchaseLedger.setApprovalStatus(2);
- }
- purchaseLedgerMapper.updateById(purchaseLedger);
- }
- }
- // 閿�鍞姤浠风姸鎬佷慨鏀�
- if (approveProcess.getApproveType().equals(6)) {
- SalesQuotation salesQuote = salesQuotationMapper.selectOne(new LambdaQueryWrapper<SalesQuotation>()
- .eq(SalesQuotation::getQuotationNo, approveProcess.getApproveReason())
- .last("limit 1"));
- // 鍚屾剰
- if (status.equals(2) && salesQuote != null) {
- salesQuote.setStatus("閫氳繃");
- } else if (status.equals(3) && salesQuote != null) {
- salesQuote.setStatus("鎷掔粷");
- } else if (status.equals(1) && salesQuote != null) {
- salesQuote.setStatus("瀹℃牳涓�");
- }
- salesQuotationMapper.updateById(salesQuote);
- }
- // 鍑哄簱瀹℃壒淇敼=鍙戣揣瀹℃壒
- if (approveProcess.getApproveType().equals(7)) {
- ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
- .eq(ShippingInfo::getShippingNo, approveProcess.getApproveReason())
- .orderByDesc(ShippingInfo::getCreateTime)
- .last("limit 1"));
- if (shippingInfo != null) {
- if (status.equals(2)) {
- shippingInfo.setStatus("瀹℃牳閫氳繃");
- shippingInfo.setShippingDate(new Date());
- //鏇存敼鍑哄簱瀹℃牳鐘舵�侊紙寰呯‘璁ゆ敼鎴愬緟瀹℃牳锛�
- stockUtils.shipmentStatus(StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), shippingInfo.getId());
- } else if (status.equals(3)) {
- //鍒犻櫎鍘熸湰锛堝緟纭锛夌殑鍑哄簱瀹℃牳鐘舵��
- stockUtils.deleteStockOutRecord(shippingInfo.getId(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode());
- shippingInfo.setStatus("瀹℃牳鎷掔粷");
- } else if (status.equals(1)) {
- shippingInfo.setStatus("瀹℃牳涓�");
- }
- shippingInfoMapper.updateById(shippingInfo);
- }
-
- }
+ approveBusinessStatusService.syncBusinessStatus(approveProcess.getApproveType(), approveProcess.getApproveReason(), status);
fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVE_NODE, approveNode.getId(), approveNode.getStorageBlobDTOS());
}
@@ -305,34 +213,6 @@
return "鍔炲叕鐢ㄥ搧瀹℃壒";
}
return null;
- }
-
- private void addQualityInspect(PurchaseLedger purchaseLedger, SalesLedgerProduct saleProduct) {
- QualityInspect qualityInspect = new QualityInspect();
- qualityInspect.setInspectType(0);
- qualityInspect.setSupplier(purchaseLedger.getSupplierName());
- qualityInspect.setPurchaseLedgerId(purchaseLedger.getId());
- qualityInspect.setProductId(saleProduct.getProductId());
- qualityInspect.setProductName(saleProduct.getProductCategory());
- qualityInspect.setModel(saleProduct.getSpecificationModel());
- qualityInspect.setProductModelId(saleProduct.getProductModelId());
- qualityInspect.setUnit(saleProduct.getUnit());
- qualityInspect.setQuantity(saleProduct.getQuantity());
- qualityInspectMapper.insert(qualityInspect);
- List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(saleProduct.getProductId(), 0, null);
- if (qualityTestStandard.size() > 0) {
- qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId());
- qualityInspectMapper.updateById(qualityInspect);
- qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery()
- .eq(QualityTestStandardParam::getTestStandardId, qualityTestStandard.get(0).getId()))
- .forEach(qualityTestStandardParam -> {
- QualityInspectParam param = new QualityInspectParam();
- com.ruoyi.common.utils.bean.BeanUtils.copyProperties(qualityTestStandardParam, param);
- param.setId(null);
- param.setInspectId(qualityInspect.getId());
- qualityInspectParamMapper.insert(param);
- });
- }
}
}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
index c9d7aae..c356708 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
@@ -1,8 +1,6 @@
package com.ruoyi.approve.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -25,10 +23,8 @@
import com.ruoyi.basic.enums.RecordTypeEnum;
import com.ruoyi.basic.utils.FileUtil;
import com.ruoyi.common.enums.FileNameType;
-import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysNotice;
import com.ruoyi.project.system.domain.SysUser;
@@ -38,10 +34,8 @@
import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
import com.ruoyi.purchase.pojo.PurchaseLedger;
import com.ruoyi.sales.mapper.CommonFileMapper;
-import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
import com.ruoyi.sales.mapper.ShippingInfoMapper;
import com.ruoyi.sales.pojo.CommonFile;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.sales.pojo.ShippingInfo;
import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
import lombok.RequiredArgsConstructor;
@@ -53,15 +47,12 @@
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class ApproveProcessServiceImpl extends ServiceImpl<ApproveProcessMapper, ApproveProcess> implements IApproveProcessService {
- private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd");
-
private final SysDeptMapper sysDeptMapper;
private final IApproveNodeService approveNodeService;
private final SysUserMapper sysUserMapper;
@@ -70,11 +61,10 @@
private final CommonFileServiceImpl commonFileService;
private final ISysNoticeService sysNoticeService;
private final PurchaseLedgerMapper purchaseLedgerMapper;
- private final SalesLedgerProductMapper salesLedgerProductMapper;
- private final StockUtils stockUtils;
private final ShippingInfoMapper shippingInfoMapper;
private final ApproveNodeMapper approveNodeMapper;
private final ApproveProcessConfigNodeService approveProcessConfigNodeService;
+ private final ApproveBusinessStatusService approveBusinessStatusService;
private final FileUtil fileUtil;
private final ApproveProcessConfigNodeMapper approveProcessConfigNodeMapper;
@@ -82,61 +72,34 @@
public void addApprove(ApproveProcessVO approveProcessVO) throws Exception {
SysUser sysUser = SecurityUtils.getLoginUser().getUser();
SysDept sysDept = sysDeptMapper.selectDeptById(SecurityUtils.getLoginUser().getCurrentDeptId());
- List<ApproveProcessConfigNodeVo> list = approveProcessConfigNodeService.listNode(approveProcessVO.getApproveType());
+ if (sysDept == null) throw new RuntimeException("閮ㄩ棬涓嶅瓨鍦�");
+ if (sysUser == null) throw new RuntimeException("鐢宠浜轰笉瀛樺湪");
+
+ List<ApproveProcessConfigNodeVo> list = Optional.ofNullable(approveProcessConfigNodeService.listNode(approveProcessVO.getApproveType()))
+ .orElse(Collections.emptyList());
List<Long> nodeIds = list.stream()
.map(ApproveProcessConfigNodeVo::getApproverId)
.filter(Objects::nonNull)
.collect(Collectors.toList());
- // 鏃犲鏍镐汉閫昏緫娣诲姞
+
+ // 瀹℃壒閰嶇疆娌℃湁鏈夋晥瀹℃牳浜烘椂锛屼笉鏂板鍗忓悓瀹℃壒娴佺▼锛岀洿鎺ユ墽琛屼笟鍔″鏍搁�氳繃閫昏緫銆�
if (CollectionUtils.isEmpty(nodeIds)) {
- autoPassPurchaseApproveIfNoApprover(approveProcessVO); // 閲囪喘鍗曟棤瀹℃牳浜洪�昏緫
+ approveBusinessStatusService.syncBusinessStatus(approveProcessVO.getApproveType(), approveProcessVO.getApproveReason(), 2);
return;
}
+
List<SysUser> sysUsers = sysUserMapper.selectUserByIds(nodeIds);
if (CollectionUtils.isEmpty(sysUsers)) throw new RuntimeException("瀹℃牳鐢ㄦ埛涓嶅瓨鍦�");
- if (sysDept == null) throw new RuntimeException("閮ㄩ棬涓嶅瓨鍦�");
- if (sysUser == null) throw new RuntimeException("鐢宠浜轰笉瀛樺湪");
- SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
- ApproveProcess approveProcess = new ApproveProcess();
- String no = OrderUtils.countTodayByCreateTime(approveProcessMapper, "", "approve_id");
- approveProcess.setApproveId(no);
- approveProcess.setApproveUser(sysUser.getUserId());
- approveProcess.setApproveUserName(sysUser.getNickName());
- approveProcess.setApproveDeptId(sysDept.getDeptId());
- approveProcess.setApproveUserIds(nodeIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
- approveProcess.setApproveDeptName(sysDept.getDeptName());
- approveProcess.setApproveUserNames(sysUsers.stream().map(SysUser::getNickName).collect(Collectors.joining(",")));
- approveProcess.setApproveTime(StringUtils.isEmpty(approveProcessVO.getApproveTime()) ? new Date() : dateFormat.parse(approveProcessVO.getApproveTime()));
- approveProcess.setApproveReason(approveProcessVO.getApproveReason());
- approveProcess.setDeviceRepairId(approveProcessVO.getDeviceRepairId());
- approveProcess.setMaintenancePrice(approveProcessVO.getMaintenancePrice());
- approveProcess.setPrice(approveProcessVO.getPrice());
- approveProcess.setStartDate(approveProcessVO.getStartDate());
- approveProcess.setEndDate(approveProcessVO.getEndDate());
- approveProcess.setApproveStatus(0);
- approveProcess.setApproveDelete(0);
- approveProcess.setApproveType(approveProcessVO.getApproveType());
- approveProcess.setCreateTime(LocalDateTime.now());
- approveProcess.setTenantId(approveProcessVO.getApproveDeptId());
- approveProcess.setApproveUserCurrentId(nodeIds.get(0));
- approveProcess.setApproveUserCurrentName(sysUsers
- .stream()
- .filter(SysUser -> SysUser.getUserId().equals(nodeIds.get(0)))
- .collect(Collectors.toList())
- .get(0)
- .getNickName());
- // 璁剧疆鐘舵�佷负閲嶆柊鎻愪氦
- if (approveProcessVO.getId() != null) {
- ApproveProcess approveProcess1 = approveProcessMapper.selectById(approveProcessVO.getId());
- approveProcess1.setApproveStatus(4);
- approveProcessMapper.updateById(approveProcess1);
- }
+
+ // 鏈夊鏍镐汉鏃讹紝鎸夋甯稿崗鍚屽鎵规祦绋嬪垱寤哄鎵逛富琛ㄣ�佸鎵硅妭鐐瑰苟閫氱煡棣栦釜瀹℃牳浜恒��
+ ApproveProcess approveProcess = buildApproveProcess(approveProcessVO, sysUser, sysDept, nodeIds, sysUsers, 0);
+ markResubmitted(approveProcessVO);
save(approveProcess);
//鍒濆鍖栧鎵硅妭鐐�
String nodeIdStr = nodeIds.stream()
.map(String::valueOf)
.collect(Collectors.joining(","));
- approveNodeService.initApproveNodes(nodeIdStr, no, approveProcessVO.getApproveDeptId());
+ approveNodeService.initApproveNodes(nodeIdStr, approveProcess.getApproveId(), approveProcessVO.getApproveDeptId());
// 闄勪欢缁戝畾
fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVE_PROCESS, approveProcess.getId(), approveProcessVO.getStorageBlobDTOS());
/*娑堟伅閫氱煡*/
@@ -154,24 +117,56 @@
}
}
- private void autoPassPurchaseApproveIfNoApprover(ApproveProcessVO approveProcessVO) {
- if (!Objects.equals(approveProcessVO.getApproveType(), 5)
- || !StringUtils.hasText(approveProcessVO.getApproveReason())) {
- throw new RuntimeException("瀹℃牳鐢ㄦ埛涓嶅瓨鍦�");
+ private ApproveProcess buildApproveProcess(ApproveProcessVO approveProcessVO, SysUser sysUser, SysDept sysDept,
+ List<Long> nodeIds, List<SysUser> sysUsers, Integer approveStatus) throws Exception {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ ApproveProcess approveProcess = new ApproveProcess();
+ String no = OrderUtils.countTodayByCreateTime(approveProcessMapper, "", "approve_id");
+ approveProcess.setApproveId(no);
+ approveProcess.setApproveUser(sysUser.getUserId());
+ approveProcess.setApproveUserName(sysUser.getNickName());
+ approveProcess.setApproveDeptId(sysDept.getDeptId());
+ approveProcess.setApproveDeptName(sysDept.getDeptName());
+ approveProcess.setApproveUserIds(nodeIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
+ approveProcess.setApproveUserNames(sysUsers.stream().map(SysUser::getNickName).collect(Collectors.joining(",")));
+ approveProcess.setApproveTime(StringUtils.isEmpty(approveProcessVO.getApproveTime()) ? new Date() : dateFormat.parse(approveProcessVO.getApproveTime()));
+ approveProcess.setApproveReason(approveProcessVO.getApproveReason());
+ approveProcess.setDeviceRepairId(approveProcessVO.getDeviceRepairId());
+ approveProcess.setMaintenancePrice(approveProcessVO.getMaintenancePrice());
+ approveProcess.setPrice(approveProcessVO.getPrice());
+ approveProcess.setStartDate(approveProcessVO.getStartDate());
+ approveProcess.setEndDate(approveProcessVO.getEndDate());
+ approveProcess.setStartDateTime(approveProcessVO.getStartDateTime());
+ approveProcess.setEndDateTime(approveProcessVO.getEndDateTime());
+ approveProcess.setApproveStatus(approveStatus);
+ approveProcess.setApproveDelete(0);
+ approveProcess.setApproveType(approveProcessVO.getApproveType());
+ approveProcess.setCreateTime(LocalDateTime.now());
+ approveProcess.setTenantId(approveProcessVO.getApproveDeptId());
+ if (!CollectionUtils.isEmpty(nodeIds)) {
+ SysUser currentUser = sysUsers.stream()
+ .filter(user -> user.getUserId().equals(nodeIds.get(0)))
+ .findFirst()
+ .orElseThrow(() -> new RuntimeException("瀹℃牳鐢ㄦ埛涓嶅瓨鍦�"));
+ approveProcess.setApproveUserCurrentId(currentUser.getUserId());
+ approveProcess.setApproveUserCurrentName(currentUser.getNickName());
}
+ if (approveStatus.equals(2) || approveStatus.equals(3) || approveStatus.equals(4)) {
+ approveProcess.setApproveOverTime(new Date());
+ }
+ return approveProcess;
+ }
- purchaseLedgerMapper.update(null, new LambdaUpdateWrapper<PurchaseLedger>()
- .eq(PurchaseLedger::getPurchaseContractNumber, approveProcessVO.getApproveReason())
- .set(PurchaseLedger::getApprovalStatus, 3));
- //閲囪喘鍏ュ簱
- PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectOne(new LambdaQueryWrapper<PurchaseLedger>()
- .eq(PurchaseLedger::getPurchaseContractNumber, approveProcessVO.getApproveReason())
- .last("limit 1"));
- List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(new QueryWrapper<SalesLedgerProduct>()
- .lambda().eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId()).eq(SalesLedgerProduct::getType, 2));
- for (SalesLedgerProduct salesLedgerProduct : salesLedgerProducts) {
- stockUtils.addStockWithBatchNo(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(), purchaseLedger.getId(),purchaseLedger.getPurchaseContractNumber()+"-"+salesLedgerProduct.getId());
+ private void markResubmitted(ApproveProcessVO approveProcessVO) {
+ if (approveProcessVO.getId() == null) {
+ return;
}
+ ApproveProcess approveProcess = approveProcessMapper.selectById(approveProcessVO.getId());
+ if (approveProcess == null) {
+ return;
+ }
+ approveProcess.setApproveStatus(4);
+ approveProcessMapper.updateById(approveProcess);
}
@Override
diff --git a/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementDetailServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementDetailServiceImpl.java
new file mode 100644
index 0000000..1897440
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementDetailServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.approve.service.impl;
+
+import com.ruoyi.approve.pojo.FinReimbursementDetail;
+import com.ruoyi.approve.mapper.FinReimbursementDetailMapper;
+import com.ruoyi.approve.service.FinReimbursementDetailService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曟槑缁嗚〃 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:38
+ */
+@Service
+public class FinReimbursementDetailServiceImpl extends ServiceImpl<FinReimbursementDetailMapper, FinReimbursementDetail> implements FinReimbursementDetailService {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementServiceImpl.java
new file mode 100644
index 0000000..1861d83
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementServiceImpl.java
@@ -0,0 +1,544 @@
+package com.ruoyi.approve.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.approve.bean.dto.ApprovalInstanceDto;
+import com.ruoyi.approve.bean.dto.ApprovalTemplateNodeApproverDto;
+import com.ruoyi.approve.bean.dto.ApprovalTemplateNodeDto;
+import com.ruoyi.approve.bean.dto.FinReimbursementDto;
+import com.ruoyi.approve.bean.vo.FinReimbursementVo;
+import com.ruoyi.approve.mapper.ApprovalInstanceMapper;
+import com.ruoyi.approve.mapper.FinReimbursementDetailMapper;
+import com.ruoyi.approve.mapper.FinReimbursementMapper;
+import com.ruoyi.approve.mapper.FinReimbursementTravelMapper;
+import com.ruoyi.approve.pojo.*;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
+import com.ruoyi.approve.service.*;
+import com.ruoyi.common.enums.TypeEnums;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.OrderUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.project.system.service.ISysNoticeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曚富琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:15
+ */
+@Service
+@RequiredArgsConstructor
+public class FinReimbursementServiceImpl extends ServiceImpl<FinReimbursementMapper, FinReimbursement> implements FinReimbursementService {
+
+ private static final String BILL_STATUS_DRAFT = "DRAFT";
+ private static final String BILL_STATUS_IN_APPROVAL = "IN_APPROVAL";
+ private static final String NODE_STATUS_WAITING = "WAITING";
+
+ private final ApprovalInstanceMapper approvalInstanceMapper;
+ private final ApprovalInstanceService approvalInstanceService;
+ private final ApprovalInstanceNodeService approvalInstanceNodeService;
+ private final ApprovalTaskService approvalTaskService;
+ private final ApprovalRecordService approvalRecordService;
+ private final FinReimbursementMapper finReimbursementMapper;
+ private final FinReimbursementTravelMapper finReimbursementTravelMapper;
+ private final FinReimbursementDetailMapper finReimbursementDetailMapper;
+ private final FileUtil fileUtil;
+ private final ISysNoticeService sysNoticeService;
+ @Override
+ public IPage<FinReimbursementVo> listPage(FinReimbursementDto finReimbursementDto, Page<FinReimbursementVo> page) {
+ IPage<FinReimbursementVo> finReimbursementVoIPage = finReimbursementMapper.listPage(finReimbursementDto, page);
+ finReimbursementVoIPage.getRecords().forEach(vo -> {
+ vo.setStorageBlobVOList(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.FIN_REIMBURSEMENT, vo.getId()));
+ });
+
+ return finReimbursementVoIPage;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean add(FinReimbursementDto finReimbursementDto) {
+ String billStatus = validateAddParam(finReimbursementDto);
+
+ // 鐢熸垚鎶ラ攢鍗曞彿
+ String billNo = OrderUtils.countTodayByCreateTime(finReimbursementMapper, "BXD", "bill_no");
+ List<FinReimbursementDetail> details = finReimbursementDto.getDetails();
+ BigDecimal totalAmount = details.stream()
+ .map(FinReimbursementDetail::getAmount)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+ FinReimbursement reimbursement = buildReimbursement(finReimbursementDto, billNo, totalAmount, billStatus);
+ // 淇濆瓨鎶ラ攢鍗曚富琛�
+ boolean saved = this.save(reimbursement);
+ if (!saved || reimbursement.getId() == null) {
+ throw new ServiceException("鏂板鎶ラ攢鍗曞け璐�");
+ }
+ Long reimbursementId = reimbursement.getId();
+
+ // 淇濆瓨宸梾鎶ラ攢鎵╁睍淇℃伅锛堟姤閿�绫诲瀷涓哄樊鏃呮姤閿�鏃讹級
+ FinReimbursementTravel travel = finReimbursementDto.getTravel();
+ if (isTravelReimbursement(finReimbursementDto.getReimbursementType())) {
+ travel.setReimbursementId(reimbursementId);
+ int travelRows = finReimbursementTravelMapper.insert(travel);
+ if (travelRows != 1) {
+ throw new ServiceException("鏂板宸梾鎶ラ攢鎵╁睍淇℃伅澶辫触");
+ }
+ }
+
+ // 淇濆瓨鎶ラ攢鍗曟槑缁�
+ for (int i = 0; i < details.size(); i++) {
+ FinReimbursementDetail detail = details.get(i);
+ detail.setId(null);
+ detail.setReimbursementId(reimbursementId);
+ detail.setRowNo(i + 1);
+ int detailRows = finReimbursementDetailMapper.insert(detail);
+ if (detailRows != 1) {
+ throw new ServiceException("鏂板鎶ラ攢鍗曟槑缁嗗け璐�");
+ }
+ }
+
+ if (BILL_STATUS_IN_APPROVAL.equals(billStatus)) {
+ startApproval(reimbursement, finReimbursementDto);
+ }
+ fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.FIN_REIMBURSEMENT, reimbursementId, finReimbursementDto.getStorageBlobDTOs());
+ return true;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean update(FinReimbursementDto finReimbursementDto) {
+ String billStatus = validateUpdateParam(finReimbursementDto);
+
+ Long reimbursementId = finReimbursementDto.getId();
+ FinReimbursement existing = finReimbursementMapper.selectById(reimbursementId);
+ if (existing == null) {
+ throw new ServiceException("鎶ラ攢鍗曚笉瀛樺湪");
+ }
+
+ // 璁$畻鏄庣粏姹囨�婚噾棰�
+ List<FinReimbursementDetail> details = finReimbursementDto.getDetails();
+ BigDecimal totalAmount = details.stream()
+ .map(FinReimbursementDetail::getAmount)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+ // 鏇存柊涓昏〃
+ FinReimbursement reimbursement = buildReimbursement(
+ finReimbursementDto,
+ existing.getBillNo(),
+ totalAmount,
+ billStatus
+ );
+ reimbursement.setId(reimbursementId);
+ int mainRows = finReimbursementMapper.updateById(reimbursement);
+ if (mainRows != 1) {
+ throw new ServiceException("鏇存柊鎶ラ攢鍗曚富琛ㄥけ璐�");
+ }
+
+ // 鏌ヨ鏁版嵁搴撲腑宸叉湁鐨勬槑缁�
+ List<FinReimbursementDetail> existingDetails = finReimbursementDetailMapper.selectList(
+ new LambdaQueryWrapper<FinReimbursementDetail>()
+ .eq(FinReimbursementDetail::getReimbursementId, reimbursementId));
+ Set<Long> existingDetailIds = existingDetails.stream()
+ .map(FinReimbursementDetail::getId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+
+ // 鏂版槑缁嗕腑鏈塈D鐨� 鈫� 鏇存柊锛涙棤ID鐨� 鈫� 鏂板
+ Set<Long> submittedDetailIds = new HashSet<>();
+ for (int i = 0; i < details.size(); i++) {
+ FinReimbursementDetail detail = details.get(i);
+ detail.setReimbursementId(reimbursementId);
+ detail.setRowNo(i + 1);
+ if (detail.getId() != null && existingDetailIds.contains(detail.getId())) {
+ finReimbursementDetailMapper.updateById(detail);
+ submittedDetailIds.add(detail.getId());
+ } else {
+ detail.setId(null);
+ finReimbursementDetailMapper.insert(detail);
+ }
+ }
+
+ // 鏁版嵁搴撲腑宸叉湁浣嗘柊鏄庣粏涓病鏈夌殑 鈫� 鍒犻櫎
+ for (Long existingId : existingDetailIds) {
+ if (!submittedDetailIds.contains(existingId)) {
+ finReimbursementDetailMapper.deleteById(existingId);
+ }
+ }
+
+ // 宸梾鎵╁睍锛氭湁鍒欐洿鏂帮紝鏃犲垯鏂板
+ FinReimbursementTravel existingTravel = finReimbursementTravelMapper.selectOne(
+ new LambdaQueryWrapper<FinReimbursementTravel>()
+ .eq(FinReimbursementTravel::getReimbursementId, reimbursementId)
+ .last("LIMIT 1"));
+ FinReimbursementTravel travel = finReimbursementDto.getTravel();
+ if (isTravelReimbursement(finReimbursementDto.getReimbursementType()) && travel != null) {
+ travel.setReimbursementId(reimbursementId);
+ if (existingTravel != null) {
+ travel.setId(existingTravel.getId());
+ finReimbursementTravelMapper.updateById(travel);
+ } else {
+ travel.setId(null);
+ finReimbursementTravelMapper.insert(travel);
+ }
+ }
+
+ resetApprovalFlow(existing, reimbursementId);
+ if (BILL_STATUS_IN_APPROVAL.equals(billStatus)) {
+ reimbursement.setApprovalInstanceId(null);
+ startApproval(reimbursement, finReimbursementDto);
+ }
+ fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.FIN_REIMBURSEMENT, reimbursementId, finReimbursementDto.getStorageBlobDTOs());
+
+ return true;
+ }
+
+ @Override
+ public FinReimbursementVo detail(Long id) {
+ if (id == null ) {
+ throw new ServiceException("鎶ラ攢鍗旾D涓嶈兘涓虹┖");
+ }
+
+ FinReimbursement reimbursement = finReimbursementMapper.selectById(id);
+ if (reimbursement == null) {
+ throw new ServiceException("鎶ラ攢鍗曚笉瀛樺湪");
+ }
+
+ FinReimbursementVo vo = new FinReimbursementVo();
+ vo.setId(reimbursement.getId());
+ vo.setBillNo(reimbursement.getBillNo());
+ vo.setReimbursementType(reimbursement.getReimbursementType());
+ vo.setExpenseType(reimbursement.getExpenseType());
+ vo.setApplicantId(reimbursement.getApplicantId());
+ vo.setApplicantCode(reimbursement.getApplicantCode());
+ vo.setApplicantName(reimbursement.getApplicantName());
+ vo.setApplicantDeptId(reimbursement.getApplicantDeptId());
+ vo.setApplicantDeptName(reimbursement.getApplicantDeptName());
+ vo.setReason(reimbursement.getReason());
+ vo.setApplyAmount(reimbursement.getApplyAmount());
+ vo.setDetailTotalAmount(reimbursement.getDetailTotalAmount());
+ vo.setPayeeName(reimbursement.getPayeeName());
+ vo.setPayeeAccount(reimbursement.getPayeeAccount());
+ vo.setPayeeBank(reimbursement.getPayeeBank());
+ vo.setApprovalInstanceId(reimbursement.getApprovalInstanceId());
+ vo.setApproveProcessId(reimbursement.getApproveProcessId());
+ vo.setBillStatus(reimbursement.getBillStatus());
+ vo.setApprovedTime(reimbursement.getApprovedTime());
+ vo.setPaidTime(reimbursement.getPaidTime());
+ vo.setAccountExpenseId(reimbursement.getAccountExpenseId());
+ vo.setRemark(reimbursement.getRemark());
+ vo.setTenantId(reimbursement.getTenantId());
+ vo.setCreateUser(reimbursement.getCreateUser());
+ vo.setCreateTime(reimbursement.getCreateTime());
+ vo.setUpdateUser(reimbursement.getUpdateUser());
+ vo.setUpdateTime(reimbursement.getUpdateTime());
+ vo.setDeptId(reimbursement.getDeptId());
+ vo.setDeleted(reimbursement.getDeleted());
+
+ vo.setDetails(finReimbursementDetailMapper.selectList(
+ new LambdaQueryWrapper<FinReimbursementDetail>()
+ .eq(FinReimbursementDetail::getReimbursementId, reimbursement.getId())
+ .orderByAsc(FinReimbursementDetail::getRowNo)
+ ));
+
+ if (isTravelReimbursement(reimbursement.getReimbursementType())) {
+ vo.setTravel(finReimbursementTravelMapper.selectOne(
+ new LambdaQueryWrapper<FinReimbursementTravel>()
+ .eq(FinReimbursementTravel::getReimbursementId, reimbursement.getId())
+ .last("LIMIT 1")
+ ));
+ }
+ vo.setStorageBlobVOList(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.FIN_REIMBURSEMENT, reimbursement.getId()));
+ //瀹℃壒璁板綍杩斿洖
+ vo.setTasks(approvalTaskService.list(new LambdaQueryWrapper<ApprovalTask>().eq(ApprovalTask::getInstanceId, reimbursement.getApprovalInstanceId())));
+ vo.setRecords(approvalRecordService.list(new LambdaQueryWrapper<ApprovalRecord>().eq(ApprovalRecord::getInstanceId, reimbursement.getApprovalInstanceId())));
+ return vo;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean delete(List<Long> ids) {
+ fileUtil.deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordIds(ApplicationTypeEnum.FILE, RecordTypeEnum.FIN_REIMBURSEMENT, ids);
+ //鍏堝垹闄ゆ槑缁�
+ finReimbursementDetailMapper.delete(new LambdaQueryWrapper<FinReimbursementDetail>().in(FinReimbursementDetail::getReimbursementId, ids));
+ //鍒犻櫎宸梾
+ finReimbursementTravelMapper.delete(new LambdaQueryWrapper<FinReimbursementTravel>().in(FinReimbursementTravel::getReimbursementId, ids));
+ //鍒犻櫎涓昏〃
+ int rows = finReimbursementMapper.delete(new LambdaQueryWrapper<FinReimbursement>().in(FinReimbursement::getId, ids));
+ return rows == ids.size();
+ }
+
+ private String validateUpdateParam(FinReimbursementDto finReimbursementDto) {
+ if (finReimbursementDto == null || finReimbursementDto.getId() == null) {
+ throw new ServiceException("鎶ラ攢鍗旾D涓嶈兘涓虹┖");
+ }
+ if (finReimbursementDto.getReimbursementType() == null) {
+ throw new ServiceException("鎶ラ攢绫诲瀷涓嶈兘涓虹┖");
+ }
+ String billStatus = normalizeBillStatus(finReimbursementDto.getBillStatus());
+ if (billStatus == null) {
+ throw new ServiceException("鍗曟嵁鐘舵�佸彧鏀寔 DRAFT 鎴� IN_APPROVAL");
+ }
+ if (BILL_STATUS_IN_APPROVAL.equals(billStatus)) {
+ validateApprovalNodes(finReimbursementDto.getNodes());
+ }
+ List<FinReimbursementDetail> details = finReimbursementDto.getDetails();
+ if (details == null || details.isEmpty()) {
+ throw new ServiceException("鎶ラ攢鍗曟槑缁嗕笉鑳戒负绌�");
+ }
+ for (FinReimbursementDetail detail : details) {
+ if (detail == null) {
+ throw new ServiceException("鎶ラ攢鍗曟槑缁嗕笉鑳戒负绌�");
+ }
+ if (detail.getAmount() == null || detail.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
+ throw new ServiceException("鎶ラ攢鍗曟槑缁嗛噾棰濆繀椤诲ぇ浜�0");
+ }
+ }
+ if (isTravelReimbursement(finReimbursementDto.getReimbursementType()) && finReimbursementDto.getTravel() == null) {
+ throw new ServiceException("宸梾鎶ラ攢蹇呴』濉啓宸梾鎵╁睍淇℃伅");
+ }
+ if (!isTravelReimbursement(finReimbursementDto.getReimbursementType()) && finReimbursementDto.getTravel() != null) {
+ throw new ServiceException("闈炲樊鏃呮姤閿�涓嶅厑璁稿~鍐欏樊鏃呮墿灞曚俊鎭�");
+ }
+ return billStatus;
+ }
+
+ private String validateAddParam(FinReimbursementDto finReimbursementDto) {
+ if (finReimbursementDto == null) {
+ throw new ServiceException("鎶ラ攢鍗曟暟鎹笉鑳戒负绌�");
+ }
+ if (finReimbursementDto.getReimbursementType() == null) {
+ throw new ServiceException("鎶ラ攢绫诲瀷涓嶈兘涓虹┖");
+ }
+ String billStatus = normalizeBillStatus(finReimbursementDto.getBillStatus());
+ if (billStatus == null) {
+ throw new ServiceException("鍗曟嵁鐘舵�佸彧鏀寔 DRAFT 鎴� IN_APPROVAL");
+ }
+ if (BILL_STATUS_IN_APPROVAL.equals(billStatus)) {
+ validateApprovalNodes(finReimbursementDto.getNodes());
+ }
+ List<FinReimbursementDetail> details = finReimbursementDto.getDetails();
+ if (details == null || details.isEmpty()) {
+ throw new ServiceException("鎶ラ攢鍗曟槑缁嗕笉鑳戒负绌�");
+ }
+ for (FinReimbursementDetail detail : details) {
+ if (detail == null) {
+ throw new ServiceException("鎶ラ攢鍗曟槑缁嗕笉鑳戒负绌�");
+ }
+ if (detail.getAmount() == null || detail.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
+ throw new ServiceException("鎶ラ攢鍗曟槑缁嗛噾棰濆繀椤诲ぇ浜�0");
+ }
+ }
+ if (isTravelReimbursement(finReimbursementDto.getReimbursementType()) && finReimbursementDto.getTravel() == null) {
+ throw new ServiceException("宸梾鎶ラ攢蹇呴』濉啓宸梾鎵╁睍淇℃伅");
+ }
+ if (!isTravelReimbursement(finReimbursementDto.getReimbursementType()) && finReimbursementDto.getTravel() != null) {
+ throw new ServiceException("闈炲樊鏃呮姤閿�涓嶅厑璁稿~鍐欏樊鏃呮墿灞曚俊鎭�");
+ }
+ return billStatus;
+ }
+
+ private FinReimbursement buildReimbursement(FinReimbursementDto finReimbursementDto, String billNo, BigDecimal totalAmount, String billStatus) {
+ FinReimbursement reimbursement = new FinReimbursement();
+ reimbursement.setId(null);
+ reimbursement.setBillNo(billNo);
+ reimbursement.setReimbursementType(finReimbursementDto.getReimbursementType());
+ reimbursement.setExpenseType(finReimbursementDto.getExpenseType());
+ reimbursement.setApplicantId(finReimbursementDto.getApplicantId());
+ reimbursement.setApplicantCode(finReimbursementDto.getApplicantCode());
+ reimbursement.setApplicantName(finReimbursementDto.getApplicantName());
+ reimbursement.setApplicantDeptId(finReimbursementDto.getApplicantDeptId());
+ reimbursement.setApplicantDeptName(finReimbursementDto.getApplicantDeptName());
+ reimbursement.setReason(finReimbursementDto.getReason());
+ reimbursement.setApplyAmount(finReimbursementDto.getApplyAmount());
+ reimbursement.setDetailTotalAmount(totalAmount);
+ reimbursement.setPayeeName(finReimbursementDto.getPayeeName());
+ reimbursement.setPayeeAccount(finReimbursementDto.getPayeeAccount());
+ reimbursement.setPayeeBank(finReimbursementDto.getPayeeBank());
+ reimbursement.setRemark(finReimbursementDto.getRemark());
+ reimbursement.setTenantId(finReimbursementDto.getTenantId());
+ reimbursement.setApproveProcessId(null);
+ reimbursement.setBillStatus(billStatus);
+ return reimbursement;
+ }
+
+ private void startApproval(FinReimbursement reimbursement, FinReimbursementDto finReimbursementDto) {
+ Long businessType = resolveBusinessType(finReimbursementDto.getReimbursementType());
+ ApprovalInstanceDto approvalInstanceDto = new ApprovalInstanceDto();
+ approvalInstanceDto.setInstanceNo(OrderUtils.countTodayByCreateTime(approvalInstanceMapper, "SP", "instance_no"));
+ approvalInstanceDto.setBusinessId(reimbursement.getId());
+ approvalInstanceDto.setTemplateId(null);
+ approvalInstanceDto.setTemplateName(TypeEnums.getLabelByValue(businessType) + "瀹℃壒");
+ approvalInstanceDto.setBusinessType(businessType);
+ approvalInstanceDto.setTitle("鎶ラ攢鍗曞彿锛�" + reimbursement.getBillNo());
+ approvalInstanceDto.setApplicantId(reimbursement.getApplicantId() != null ? reimbursement.getApplicantId() : SecurityUtils.getUserId());
+ approvalInstanceDto.setApplicantName(reimbursement.getApplicantName() != null ? reimbursement.getApplicantName() : SecurityUtils.getLoginUser().getNickName());
+ approvalInstanceDto.setApplyTime(LocalDateTime.now());
+ approvalInstanceDto.setStatus("PENDING");
+ approvalInstanceDto.setCurrentLevel(1);
+
+ boolean approvalSaved = approvalInstanceService.save(approvalInstanceDto);
+ if (!approvalSaved || approvalInstanceDto.getId() == null) {
+ throw new ServiceException("鍙戣捣瀹℃壒澶辫触");
+ }
+ List<ApprovalTask> firstTasks = createApprovalNodes(approvalInstanceDto, finReimbursementDto.getNodes());
+ sendApproveNotice(approvalInstanceDto, firstTasks);
+
+ FinReimbursement update = new FinReimbursement();
+ update.setId(reimbursement.getId());
+ update.setApprovalInstanceId(approvalInstanceDto.getId());
+ update.setBillStatus(BILL_STATUS_IN_APPROVAL);
+ int rows = finReimbursementMapper.updateById(update);
+ if (rows != 1) {
+ throw new ServiceException("鍥炲~瀹℃壒瀹炰緥澶辫触");
+ }
+ }
+
+ private List<ApprovalTask> createApprovalNodes(ApprovalInstanceDto approvalInstanceDto, List<ApprovalTemplateNodeDto> nodes) {
+ List<ApprovalTask> firstTasks = Collections.emptyList();
+ for (int i = 0; i < nodes.size(); i++) {
+ ApprovalTemplateNodeDto nodeDto = nodes.get(i);
+ ApprovalInstanceNode instanceNode = new ApprovalInstanceNode();
+ instanceNode.setInstanceId(approvalInstanceDto.getId());
+ instanceNode.setLevelNo(nodeDto.getLevelNo());
+ instanceNode.setApproveType(nodeDto.getApproveType());
+ instanceNode.setStatus(i == 0 ? "PENDING" : NODE_STATUS_WAITING);
+ instanceNode.setStartTime(i == 0 ? LocalDateTime.now() : null);
+ instanceNode.setDeleted((byte) 0);
+ approvalInstanceNodeService.save(instanceNode);
+
+ List<ApprovalTask> tasks = nodeDto.getApprovers().stream().map(approver -> {
+ ApprovalTask task = new ApprovalTask();
+ task.setInstanceId(approvalInstanceDto.getId());
+ task.setNodeId(instanceNode.getId());
+ task.setLevelNo(instanceNode.getLevelNo());
+ task.setApproverId(approver.getApproverId());
+ task.setApproverName(approver.getApproverName());
+ task.setTaskStatus("PENDING");
+ task.setIsRead((byte) 0);
+ task.setDeleted((byte) 0);
+ return task;
+ }).collect(Collectors.toList());
+ approvalTaskService.saveBatch(tasks);
+
+ if (i == 0) {
+ firstTasks = tasks;
+ ApprovalRecord record = new ApprovalRecord();
+ record.setInstanceId(approvalInstanceDto.getId());
+ record.setNodeId(instanceNode.getId());
+ record.setOperatorId(approvalInstanceDto.getApplicantId());
+ record.setOperatorName(approvalInstanceDto.getApplicantName());
+ record.setAction("SUBMIT");
+ record.setComment("鍙戣捣瀹℃壒");
+ record.setDeleted((byte) 0);
+ approvalRecordService.save(record);
+ }
+ }
+ return firstTasks;
+ }
+
+ private void validateApprovalNodes(List<ApprovalTemplateNodeDto> nodes) {
+ if (nodes == null || nodes.isEmpty()) {
+ throw new ServiceException("鎻愪氦瀹℃壒鏃跺鎵硅妭鐐逛笉鑳戒负绌�");
+ }
+ for (int i = 0; i < nodes.size(); i++) {
+ ApprovalTemplateNodeDto node = nodes.get(i);
+ if (node == null) {
+ throw new ServiceException("瀹℃壒鑺傜偣涓嶈兘涓虹┖");
+ }
+ if (node.getLevelNo() == null) {
+ node.setLevelNo(i + 1);
+ }
+ if (!StringUtils.hasText(node.getApproveType())) {
+ throw new ServiceException("瀹℃壒鑺傜偣瀹℃壒鏂瑰紡涓嶈兘涓虹┖");
+ }
+ List<ApprovalTemplateNodeApproverDto> approvers = node.getApprovers();
+ if (approvers == null || approvers.isEmpty()) {
+ throw new ServiceException("瀹℃壒鑺傜偣瀹℃壒浜轰笉鑳戒负绌�");
+ }
+ for (ApprovalTemplateNodeApproverDto approver : approvers) {
+ if (approver == null || approver.getApproverId() == null) {
+ throw new ServiceException("瀹℃壒浜轰笉鑳戒负绌�");
+ }
+ }
+ }
+ }
+
+ private void sendApproveNotice(ApprovalInstanceDto instance, List<ApprovalTask> tasks) {
+ if (instance == null || tasks == null || tasks.isEmpty()) {
+ return;
+ }
+ List<Long> approverIds = tasks.stream()
+ .map(ApprovalTask::getApproverId)
+ .filter(id -> id != null && id > 0)
+ .distinct()
+ .collect(Collectors.toList());
+ if (approverIds.isEmpty()) {
+ return;
+ }
+ String title = "鎶ラ攢瀹℃壒";
+ String message = "瀹℃壒鍗曞彿 " + instance.getInstanceNo() + " 闇�瑕佹偍瀹℃壒";
+ String jumpPath = "/approvalInstance?id=" + instance.getId();
+ sysNoticeService.simpleNoticeByUser(title, message, approverIds, jumpPath);
+ }
+
+ private void resetApprovalFlow(FinReimbursement existing, Long reimbursementId) {
+ if (existing == null || existing.getApprovalInstanceId() == null) {
+ return;
+ }
+ Long approvalInstanceId = existing.getApprovalInstanceId();
+ if (!"REJECTED".equals(existing.getBillStatus())) {
+ approvalInstanceService.delete(Collections.singletonList(approvalInstanceId));
+ }
+ clearApprovalBinding(reimbursementId);
+ }
+
+ private void clearApprovalBinding(Long reimbursementId) {
+ int rows = finReimbursementMapper.update(
+ null,
+ Wrappers.<FinReimbursement>lambdaUpdate()
+ .eq(FinReimbursement::getId, reimbursementId)
+ .set(FinReimbursement::getApprovalInstanceId, null)
+ );
+ if (rows != 1) {
+ throw new ServiceException("閲嶇疆瀹℃壒娴佺▼澶辫触");
+ }
+ }
+
+ private Long resolveBusinessType(Byte reimbursementType) {
+ return isTravelReimbursement(reimbursementType)
+ ? TypeEnums.TRAVEL_REIMBURSEMENT_APPROVAL.getCode()
+ : TypeEnums.EXPENSE_APPROVAL.getCode();
+ }
+
+ private String normalizeBillStatus(String billStatus) {
+ if (billStatus == null) {
+ return BILL_STATUS_DRAFT;
+ }
+ String normalized = billStatus.trim().toUpperCase();
+ if (BILL_STATUS_DRAFT.equals(normalized) || BILL_STATUS_IN_APPROVAL.equals(normalized)) {
+ return normalized;
+ }
+ return null;
+ }
+
+ private boolean isTravelReimbursement(Byte reimbursementType) {
+ return Byte.valueOf((byte) 1).equals(reimbursementType);
+ }
+}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementTravelServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementTravelServiceImpl.java
new file mode 100644
index 0000000..3329f9a
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementTravelServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.approve.service.impl;
+
+import com.ruoyi.approve.pojo.FinReimbursementTravel;
+import com.ruoyi.approve.mapper.FinReimbursementTravelMapper;
+import com.ruoyi.approve.service.FinReimbursementTravelService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 宸梾鎶ラ攢鎵╁睍琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:47
+ */
+@Service
+public class FinReimbursementTravelServiceImpl extends ServiceImpl<FinReimbursementTravelMapper, FinReimbursementTravel> implements FinReimbursementTravelService {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/utils/ApproveProcessConfigNodeUtils.java b/src/main/java/com/ruoyi/approve/utils/ApproveProcessConfigNodeUtils.java
index 4ae03e6..239726a 100644
--- a/src/main/java/com/ruoyi/approve/utils/ApproveProcessConfigNodeUtils.java
+++ b/src/main/java/com/ruoyi/approve/utils/ApproveProcessConfigNodeUtils.java
@@ -1,9 +1,370 @@
package com.ruoyi.approve.utils;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.approve.pojo.ApprovalInstance;
+import com.ruoyi.approve.pojo.ApprovalInstanceNode;
+import com.ruoyi.approve.pojo.ApprovalRecord;
+import com.ruoyi.approve.pojo.ApprovalTask;
+import com.ruoyi.approve.pojo.ApprovalTemplateNode;
+import com.ruoyi.approve.pojo.ApprovalTemplateNodeApprover;
+import com.ruoyi.approve.service.ApprovalInstanceNodeService;
+import com.ruoyi.approve.service.ApprovalRecordService;
+import com.ruoyi.approve.service.ApprovalTaskService;
+import com.ruoyi.approve.service.ApprovalTemplateNodeApproverService;
+import com.ruoyi.approve.service.ApprovalTemplateNodeService;
import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 瀹℃壒娴佺▼鑺傜偣宸ュ叿绫�
+ */
+@Component
@RequiredArgsConstructor
public class ApproveProcessConfigNodeUtils {
+ private final ApprovalInstanceNodeService instanceNodeService;
+ private final ApprovalTaskService approvalTaskService;
+ private final ApprovalRecordService approvalRecordService;
+ private final ApprovalTemplateNodeService approvalTemplateNodeService;
+ private final ApprovalTemplateNodeApproverService approvalTemplateNodeApproverService;
-}
+ /**
+ * 鎸夊綋鍓嶅眰绾у垱寤哄鎵硅妭鐐瑰拰瀹℃壒浠诲姟銆�
+ * 璇ラ噸杞戒細鍚屾椂鍐欏叆涓�鏉″彂璧峰鎵硅褰曘��
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public ApprovalInstanceNode createCurrentNodeAndTasks(ApprovalInstance instance) {
+ return createCurrentNodeAndTasks(instance, true);
+ }
+
+ /**
+ * 鎸夊綋鍓嶅眰绾у垱寤哄鎵硅妭鐐瑰拰瀹℃壒浠诲姟銆�
+ *
+ * @param instance 瀹℃壒瀹炰緥
+ * @param createSubmitRecord 鏄惁鍒涘缓鍙戣捣瀹℃壒璁板綍
+ * @return 鍒涘缓鍑虹殑褰撳墠鑺傜偣瀹炰緥
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public ApprovalInstanceNode createCurrentNodeAndTasks(ApprovalInstance instance, boolean createSubmitRecord) {
+ if (instance == null || instance.getId() == null) {
+ throw new RuntimeException("瀹℃壒瀹炰緥涓嶈兘涓虹┖");
+ }
+ if (instance.getTemplateId() == null) {
+ throw new RuntimeException("瀹℃壒妯℃澘涓嶈兘涓虹┖");
+ }
+
+ Integer currentLevel = instance.getCurrentLevel() == null ? 1 : instance.getCurrentLevel();
+
+ ApprovalInstanceNode existsNode = instanceNodeService.getOne(
+ new LambdaQueryWrapper<ApprovalInstanceNode>()
+ .eq(ApprovalInstanceNode::getInstanceId, instance.getId())
+ .eq(ApprovalInstanceNode::getLevelNo, currentLevel)
+ .eq(ApprovalInstanceNode::getDeleted, 0)
+ .last("LIMIT 1")
+ );
+ if (existsNode != null) {
+ return existsNode;
+ }
+
+ ApprovalTemplateNode templateNode = approvalTemplateNodeService.getOne(
+ new LambdaQueryWrapper<ApprovalTemplateNode>()
+ .eq(ApprovalTemplateNode::getTemplateId, instance.getTemplateId())
+ .eq(ApprovalTemplateNode::getLevelNo, currentLevel)
+ .orderByAsc(ApprovalTemplateNode::getId)
+ .last("LIMIT 1")
+ );
+ if (templateNode == null) {
+ throw new RuntimeException("鏈壘鍒板綋鍓嶅眰绾у搴旂殑瀹℃壒妯℃澘鑺傜偣");
+ }
+
+ List<ApprovalTemplateNodeApprover> approvers = approvalTemplateNodeApproverService.list(
+ new LambdaQueryWrapper<ApprovalTemplateNodeApprover>()
+ .eq(ApprovalTemplateNodeApprover::getTemplateId, instance.getTemplateId())
+ .eq(ApprovalTemplateNodeApprover::getNodeId, templateNode.getId())
+ .eq(ApprovalTemplateNodeApprover::getDeleted, 0L)
+ .orderByAsc(ApprovalTemplateNodeApprover::getSortNo)
+ );
+ if (approvers == null || approvers.isEmpty()) {
+ throw new RuntimeException("褰撳墠瀹℃壒鑺傜偣鏈厤缃鎵逛汉");
+ }
+
+ ApprovalInstanceNode instanceNode = new ApprovalInstanceNode();
+ instanceNode.setInstanceId(instance.getId());
+ instanceNode.setLevelNo(templateNode.getLevelNo());
+ instanceNode.setApproveType(templateNode.getApproveType());
+ instanceNode.setStatus("PENDING");
+ instanceNode.setStartTime(LocalDateTime.now());
+ instanceNode.setDeleted((byte) 0);
+ instanceNodeService.save(instanceNode);
+
+ List<ApprovalTask> taskList = new ArrayList<>(approvers.size());
+ for (ApprovalTemplateNodeApprover approver : approvers) {
+ ApprovalTask task = new ApprovalTask();
+ task.setInstanceId(instance.getId());
+ task.setNodeId(instanceNode.getId());
+ task.setLevelNo(instanceNode.getLevelNo());
+ task.setApproverId(approver.getApproverId());
+ task.setApproverName(approver.getApproverName());
+ task.setTaskStatus("PENDING");
+ task.setIsRead((byte) 0);
+ task.setDeleted((byte) 0);
+ taskList.add(task);
+ }
+ approvalTaskService.saveBatch(taskList);
+
+ if (createSubmitRecord) {
+ ApprovalRecord record = new ApprovalRecord();
+ record.setInstanceId(instance.getId());
+ record.setNodeId(instanceNode.getId());
+ record.setOperatorId(instance.getApplicantId());
+ record.setOperatorName(instance.getApplicantName());
+ record.setAction("SUBMIT");
+ record.setComment("鍙戣捣瀹℃壒");
+ record.setDeleted((byte) 0);
+ approvalRecordService.save(record);
+ }
+
+ return instanceNode;
+ }
+
+ /**
+ * 鏌ヨ褰撳墠寰呭鐞嗚妭鐐广��
+ */
+ public ApprovalInstanceNode getCurrentNode(Long instanceId) {
+ if (instanceId == null) {
+ return null;
+ }
+
+ return instanceNodeService.getOne(
+ new LambdaQueryWrapper<ApprovalInstanceNode>()
+ .eq(ApprovalInstanceNode::getInstanceId, instanceId)
+ .eq(ApprovalInstanceNode::getStatus, "PENDING")
+ .eq(ApprovalInstanceNode::getDeleted, 0)
+ .orderByAsc(ApprovalInstanceNode::getLevelNo)
+ .last("LIMIT 1")
+ );
+ }
+
+ /**
+ * 鏌ヨ褰撳墠瀹℃壒灞傜骇銆�
+ */
+ public Integer getCurrentLevel(Long instanceId) {
+ ApprovalInstanceNode currentNode = getCurrentNode(instanceId);
+ return currentNode != null ? currentNode.getLevelNo() : null;
+ }
+
+ /**
+ * 鏌ヨ褰撳墠鑺傜偣涓嬬殑寰呭鎵逛换鍔°��
+ */
+ public List<ApprovalTask> getCurrentPendingTasks(Long instanceId) {
+ if (instanceId == null) {
+ return List.of();
+ }
+
+ ApprovalInstanceNode currentNode = getCurrentNode(instanceId);
+ if (currentNode == null) {
+ return List.of();
+ }
+
+ return approvalTaskService.list(
+ new LambdaQueryWrapper<ApprovalTask>()
+ .eq(ApprovalTask::getInstanceId, instanceId)
+ .eq(ApprovalTask::getNodeId, currentNode.getId())
+ .eq(ApprovalTask::getTaskStatus, "PENDING")
+ .eq(ApprovalTask::getDeleted, 0)
+ .orderByAsc(ApprovalTask::getLevelNo)
+ );
+ }
+
+ /**
+ * 鏌ヨ褰撳墠鐢ㄦ埛鍦ㄥ綋鍓嶈妭鐐逛笂鐨勫緟瀹℃壒浠诲姟銆�
+ */
+ public ApprovalTask getCurrentUserTask(Long instanceId, Long userId) {
+ if (instanceId == null || userId == null) {
+ return null;
+ }
+
+ ApprovalInstanceNode currentNode = getCurrentNode(instanceId);
+ if (currentNode == null) {
+ return null;
+ }
+
+ return approvalTaskService.getOne(
+ new LambdaQueryWrapper<ApprovalTask>()
+ .eq(ApprovalTask::getInstanceId, instanceId)
+ .eq(ApprovalTask::getNodeId, currentNode.getId())
+ .eq(ApprovalTask::getApproverId, userId)
+ .eq(ApprovalTask::getTaskStatus, "PENDING")
+ .eq(ApprovalTask::getDeleted, 0)
+ .last("LIMIT 1")
+ );
+ }
+
+ /**
+ * 鍒ゆ柇褰撳墠鐢ㄦ埛鏄惁鏄綋鍓嶅鎵逛汉銆�
+ */
+ public boolean isCurrentApprover(Long instanceId, Long userId) {
+ return getCurrentUserTask(instanceId, userId) != null;
+ }
+
+ /**
+ * 鏌ヨ褰撳墠鑺傜偣鐨勫鎵逛汉 ID 鍒楄〃銆�
+ */
+ public List<Long> getCurrentNodeApproverIds(Long instanceId) {
+ return getCurrentPendingTasks(instanceId).stream()
+ .map(ApprovalTask::getApproverId)
+ .distinct()
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * 鏌ヨ褰撳墠鑺傜偣鍓╀綑寰呭鎵逛汉鏁般��
+ */
+ public int getRemainingApproverCount(Long instanceId) {
+ return getCurrentPendingTasks(instanceId).size();
+ }
+
+ /**
+ * 鏌ヨ褰撳墠鑺傜偣宸插悓鎰忎汉鏁般��
+ */
+ public int getApprovedCount(Long instanceId) {
+ if (instanceId == null) {
+ return 0;
+ }
+
+ ApprovalInstanceNode currentNode = getCurrentNode(instanceId);
+ if (currentNode == null) {
+ return 0;
+ }
+
+ return Math.toIntExact(approvalTaskService.count(
+ new LambdaQueryWrapper<ApprovalTask>()
+ .eq(ApprovalTask::getInstanceId, instanceId)
+ .eq(ApprovalTask::getNodeId, currentNode.getId())
+ .eq(ApprovalTask::getTaskStatus, "APPROVED")
+ .eq(ApprovalTask::getDeleted, 0)
+ ));
+ }
+
+ /**
+ * 鏌ヨ褰撳墠鑺傜偣宸叉嫆缁濅汉鏁般��
+ */
+ public int getRejectedCount(Long instanceId) {
+ if (instanceId == null) {
+ return 0;
+ }
+
+ ApprovalInstanceNode currentNode = getCurrentNode(instanceId);
+ if (currentNode == null) {
+ return 0;
+ }
+
+ return Math.toIntExact(approvalTaskService.count(
+ new LambdaQueryWrapper<ApprovalTask>()
+ .eq(ApprovalTask::getInstanceId, instanceId)
+ .eq(ApprovalTask::getNodeId, currentNode.getId())
+ .eq(ApprovalTask::getTaskStatus, "REJECTED")
+ .eq(ApprovalTask::getDeleted, 0)
+ ));
+ }
+
+ /**
+ * 鍒ゆ柇褰撳墠鑺傜偣鏄惁鍙互娴佽浆鍒颁笅涓�灞傘��
+ */
+ public boolean canProceedToNextLevel(Long instanceId, String approveType) {
+ if (instanceId == null || approveType == null) {
+ return false;
+ }
+
+ if (getRejectedCount(instanceId) > 0) {
+ return false;
+ }
+
+ int totalApproverCount = getCurrentPendingTasks(instanceId).size() + getApprovedCount(instanceId);
+ int approvedCount = getApprovedCount(instanceId);
+
+ if ("AND".equalsIgnoreCase(approveType)) {
+ return approvedCount > 0 && approvedCount == totalApproverCount;
+ }
+ if ("OR".equalsIgnoreCase(approveType)) {
+ return approvedCount > 0;
+ }
+ return false;
+ }
+
+ /**
+ * 鏌ヨ褰撳墠鐢ㄦ埛鍦ㄥ綋鍓嶈妭鐐逛笂鐨勪换鍔$姸鎬併��
+ */
+ public String getUserTaskStatus(Long instanceId, Long userId) {
+ if (instanceId == null || userId == null) {
+ return null;
+ }
+
+ ApprovalInstanceNode currentNode = getCurrentNode(instanceId);
+ if (currentNode == null) {
+ return null;
+ }
+
+ ApprovalTask task = approvalTaskService.getOne(
+ new LambdaQueryWrapper<ApprovalTask>()
+ .eq(ApprovalTask::getInstanceId, instanceId)
+ .eq(ApprovalTask::getNodeId, currentNode.getId())
+ .eq(ApprovalTask::getApproverId, userId)
+ .eq(ApprovalTask::getDeleted, 0)
+ .last("LIMIT 1")
+ );
+
+ return task != null ? task.getTaskStatus() : null;
+ }
+
+ /**
+ * 鏌ヨ鎸囧畾鐢ㄦ埛鐨勫叏閮ㄥ緟瀹℃壒浠诲姟銆�
+ */
+ public List<ApprovalTask> getUserAllPendingTasks(Long userId) {
+ if (userId == null) {
+ return List.of();
+ }
+
+ return approvalTaskService.list(
+ new LambdaQueryWrapper<ApprovalTask>()
+ .eq(ApprovalTask::getApproverId, userId)
+ .eq(ApprovalTask::getTaskStatus, "PENDING")
+ .eq(ApprovalTask::getDeleted, 0)
+ .orderByDesc(ApprovalTask::getCreateTime)
+ );
+ }
+
+ /**
+ * 鏌ヨ瀹℃壒瀹炰緥鐨勮繘搴︽憳瑕併��
+ */
+ public String getApprovalProgress(Long instanceId) {
+ if (instanceId == null) {
+ return "鏃犳晥鐨勫鎵瑰疄渚�";
+ }
+
+ ApprovalInstanceNode currentNode = getCurrentNode(instanceId);
+ if (currentNode == null) {
+ return "瀹℃壒宸插畬鎴愭垨灏氭湭寮�濮�";
+ }
+
+ int approvedCount = getApprovedCount(instanceId);
+ int rejectedCount = getRejectedCount(instanceId);
+ int pendingCount = getRemainingApproverCount(instanceId);
+ int totalCount = approvedCount + rejectedCount + pendingCount;
+
+ return String.format(
+ "绗�%d绾у鎵癸細鎬讳汉鏁�=%d锛屽凡鍚屾剰=%d锛屽凡鎷掔粷=%d锛屽緟瀹℃壒=%d",
+ currentNode.getLevelNo(),
+ totalCount,
+ approvedCount,
+ rejectedCount,
+ pendingCount
+ );
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java b/src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java
index ef7e57c..506a9d8 100644
--- a/src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java
+++ b/src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java
@@ -57,11 +57,8 @@
SALES_QUOTATION("sales_quotation"),
SALES_LEDGER_PRODUCT("sales_ledger_product"),
PURCHASE_LEDGER_FILE("purchase_ledger_file"),
- RECEIPT_PAYMENT("receipt_payment"),
PAYMENT_SHIPPING("payment_shipping"),
- INVOICE_REGISTRATION_PRODUCT("invoice_registration_product"),
LOSS("loss"),
- INVOICE_REGISTRATION("invoice_registration"),
INVOICE_LEDGER_FILE("invoice_ledger_file"),
INVOICE_LEDGER("invoice_ledger"),
COMMON_FILE("common_file"),
@@ -86,15 +83,11 @@
QUALITY_INSPECT_PARAM("quality_inspect_param"),
QUALITY_INSPECT("quality_inspect"),
// Purchase
- TICKET_REGISTRATION("ticket_registration"),
PURCHASE_RETURN_ORDER_PRODUCTS("purchase_return_order_products"),
PURCHASE_RETURN_ORDERS("purchase_return_orders"),
SALES_LEDGER_PRODUCT_TEMPLATE("sales_ledger_product_template"),
PURCHASE_LEDGER("purchase_ledger"),
PURCHASE_LEDGER_TEMPLATE("purchase_ledger_template"),
- PRODUCT_RECORD("product_record"),
- PAYMENT_REGISTRATION("payment_registration"),
- INVOICE_PURCHASE("invoice_purchase"),
// Project Management
SHIPPING_ADDRESS("shipping_address"),
ROLES("roles"),
@@ -199,13 +192,16 @@
AFTER_SALES_SERVICE_FILE("after_sales_service_file"),
AFTER_SALES_NEAR_EXPIRY("after_sales_near_expiry"),
// Account
- ACCOUNT_INCOME("account_income"),
- BORROW_INFO("borrow_info"),
SALES_REFUND_AMOUNT_ORDER("sales_refund_amount_order"),
SALES_RECEIPT_RETURN("sales_receipt_return"),
ACCOUNT_EXPENSE("account_expense"),
+ FIN_REIMBURSEMENT("fin_reimbursement"),
FIN_VOUCHER("fin_voucher"),
- ACCOUNT_FILE("account_file");
+ ACCOUNT_FILE("account_file"),
+ ENTERPRISE_NEWS("enterprise_news"),
+ APPROVAL_INSTANCE("approval_instance"),
+ ACCOUNT_INVOICE_APPLICATION("account_invoice_application"),
+ ACCOUNT_PURCHASE_INVOICE("account_purchase_invoice");
private final String type;
RecordTypeEnum(String type) { this.type = type; }
diff --git a/src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java b/src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java
index 2605737..f871b91 100644
--- a/src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java
+++ b/src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java
@@ -6,6 +6,8 @@
import com.ruoyi.basic.dto.CustomerDto;
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.basic.vo.CustomerVo;
+import com.ruoyi.sales.vo.CustomerTransactionsDetailsVo;
+import com.ruoyi.sales.vo.CustomerTransactionsVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -13,7 +15,7 @@
/**
* 瀹㈡埛妗fMapper鎺ュ彛
- *
+ *
* @author ruoyi
* @date 2025-05-07
*/
@@ -22,7 +24,7 @@
{
/**
* 鏌ヨ瀹㈡埛妗f
- *
+ *
* @param id 瀹㈡埛妗f涓婚敭
* @return 瀹㈡埛妗f
*/
@@ -30,7 +32,7 @@
/**
* 鏌ヨ瀹㈡埛妗f鍒楄〃
- *
+ *
* @param customer 瀹㈡埛妗f
* @return 瀹㈡埛妗f闆嗗悎
*/
@@ -38,7 +40,7 @@
/**
* 鏂板瀹㈡埛妗f
- *
+ *
* @param customer 瀹㈡埛妗f
* @return 缁撴灉
*/
@@ -46,7 +48,7 @@
/**
* 淇敼瀹㈡埛妗f
- *
+ *
* @param customer 瀹㈡埛妗f
* @return 缁撴灉
*/
@@ -54,7 +56,7 @@
/**
* 鍒犻櫎瀹㈡埛妗f
- *
+ *
* @param id 瀹㈡埛妗f涓婚敭
* @return 缁撴灉
*/
@@ -62,7 +64,7 @@
/**
* 鎵归噺鍒犻櫎瀹㈡埛妗f
- *
+ *
* @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
* @return 缁撴灉
*/
@@ -71,4 +73,8 @@
IPage<CustomerVo> listPage(Page<CustomerDto> page, @Param("c") CustomerDto customer, @Param("loginUserId") Long loginUserId);
List<CustomerVo> list(@Param("c") CustomerDto customer, @Param("loginUserId") Long loginUserId);
-}
\ No newline at end of file
+
+ IPage<CustomerTransactionsVo> customewTransactions(Page page, @Param("customerName") String customerName);
+
+ IPage<CustomerTransactionsDetailsVo> customewTransactionsDetails(Page page, @Param("customerId") Long customerId);
+}
diff --git a/src/main/java/com/ruoyi/basic/mapper/SupplierManageMapper.java b/src/main/java/com/ruoyi/basic/mapper/SupplierManageMapper.java
index 1ba05a6..beea9c3 100644
--- a/src/main/java/com/ruoyi/basic/mapper/SupplierManageMapper.java
+++ b/src/main/java/com/ruoyi/basic/mapper/SupplierManageMapper.java
@@ -6,6 +6,8 @@
import com.ruoyi.basic.dto.SupplierManageDto;
import com.ruoyi.basic.excel.SupplierManageExcelDto;
import com.ruoyi.basic.pojo.SupplierManage;
+import com.ruoyi.purchase.vo.SupplierTransactionsDetailsVo;
+import com.ruoyi.purchase.vo.SupplierTransactionsVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -17,4 +19,8 @@
IPage<SupplierManage> supplierListPage(Page page, @Param("supplierManageDto") SupplierManageDto supplierManageDto);
List<SupplierManageExcelDto> supplierExportList(@Param("supplierManageDto") SupplierManageDto supplierManageDto);
+
+ IPage<SupplierTransactionsVo> supplierTransactions(Page page, @Param("supplierName") String supplierName);
+
+ IPage<SupplierTransactionsDetailsVo> supplierTransactionsDetails(Page page, @Param("supplierId") Long supplierId);
}
diff --git a/src/main/java/com/ruoyi/basic/pojo/ProductModel.java b/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
index 8c0dc07..dc7201c 100644
--- a/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
+++ b/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
@@ -46,12 +46,6 @@
@Excel(name = "鍗曚綅")
private String unit;
- /**
- * 鐢熶骇鐐掓満
- */
- @Excel(name = "鐢熶骇鐐掓満")
- private String speculativeTradingName;
-
@Schema(description = "绉熸埛ID")
@TableField(fill = FieldFill.INSERT)
private Long tenantId;
diff --git a/src/main/java/com/ruoyi/basic/service/ICustomerService.java b/src/main/java/com/ruoyi/basic/service/ICustomerService.java
index b725216..27e4739 100644
--- a/src/main/java/com/ruoyi/basic/service/ICustomerService.java
+++ b/src/main/java/com/ruoyi/basic/service/ICustomerService.java
@@ -7,6 +7,8 @@
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.basic.vo.CustomerVo;
import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.sales.vo.CustomerTransactionsDetailsVo;
+import com.ruoyi.sales.vo.CustomerTransactionsVo;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
@@ -93,4 +95,20 @@
void together(CustomerDto customerDto);
Boolean back(Long id);
+
+ /**
+ * 鏌ヨ瀹㈡埛寰�鏉ュ垪琛�
+ * @param page
+ * @param customerName
+ * @return
+ */
+ IPage<CustomerTransactionsVo> customewTransactions(Page page, String customerName);
+
+ /**
+ * 鏌ヨ瀹㈡埛寰�鏉ユ槑缁嗗垪琛�
+ * @param page
+ * @param customerId
+ * @return
+ */
+ IPage<CustomerTransactionsDetailsVo> customewTransactionsDetails(Page page, Long customerId);
}
diff --git a/src/main/java/com/ruoyi/basic/service/ISupplierService.java b/src/main/java/com/ruoyi/basic/service/ISupplierService.java
index b54c2ad..ce6d832 100644
--- a/src/main/java/com/ruoyi/basic/service/ISupplierService.java
+++ b/src/main/java/com/ruoyi/basic/service/ISupplierService.java
@@ -5,10 +5,11 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.basic.dto.SupplierManageDto;
import com.ruoyi.basic.pojo.SupplierManage;
-import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.purchase.vo.SupplierTransactionsDetailsVo;
+import com.ruoyi.purchase.vo.SupplierTransactionsVo;
+import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.multipart.MultipartFile;
-import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
public interface ISupplierService extends IService<SupplierManage> {
@@ -57,4 +58,20 @@
void supplierExport(HttpServletResponse response, SupplierManageDto supplierManageDto);
Boolean importData(MultipartFile file);
+
+ /**
+ * 渚涘簲鍟嗗線鏉�
+ * @param page
+ * @param supplierName
+ * @return
+ */
+ IPage<SupplierTransactionsVo> supplierTransactions(Page page, String supplierName);
+
+ /**
+ * 渚涘簲鍟嗗線鏉ヨ鎯�
+ * @param page
+ * @param supplierId
+ * @return
+ */
+ IPage<SupplierTransactionsDetailsVo> supplierTransactionsDetails(Page page, Long supplierId);
}
diff --git a/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
index 09c2a46..eef85aa 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
@@ -23,6 +23,8 @@
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.sales.mapper.SalesLedgerMapper;
import com.ruoyi.sales.pojo.SalesLedger;
+import com.ruoyi.sales.vo.CustomerTransactionsDetailsVo;
+import com.ruoyi.sales.vo.CustomerTransactionsVo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
@@ -379,6 +381,16 @@
return this.updateById(customer);
}
+ @Override
+ public IPage<CustomerTransactionsVo> customewTransactions(Page page, String customerName) {
+ return customerMapper.customewTransactions(page, customerName);
+ }
+
+ @Override
+ public IPage<CustomerTransactionsDetailsVo> customewTransactionsDetails(Page page, Long customerId) {
+ return customerMapper.customewTransactionsDetails(page, customerId);
+ }
+
/**
* 涓嬪垝绾垮懡鍚嶈浆椹煎嘲鍛藉悕
*/
diff --git a/src/main/java/com/ruoyi/basic/service/impl/SupplierServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/SupplierServiceImpl.java
index 6adaf2a..613bde2 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/SupplierServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/SupplierServiceImpl.java
@@ -14,6 +14,8 @@
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
import com.ruoyi.purchase.pojo.PurchaseLedger;
+import com.ruoyi.purchase.vo.SupplierTransactionsDetailsVo;
+import com.ruoyi.purchase.vo.SupplierTransactionsVo;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
@@ -130,4 +132,14 @@
}
return false;
}
+
+ @Override
+ public IPage<SupplierTransactionsVo> supplierTransactions(Page page, String supplierName) {
+ return supplierMapper.supplierTransactions(page,supplierName);
+ }
+
+ @Override
+ public IPage<SupplierTransactionsDetailsVo> supplierTransactionsDetails(Page page, Long supplierId) {
+ return supplierMapper.supplierTransactionsDetails(page,supplierId);
+ }
}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsController.java b/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsController.java
new file mode 100644
index 0000000..36f1e21
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsController.java
@@ -0,0 +1,61 @@
+package com.ruoyi.collaborativeApproval.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.collaborativeApproval.dto.EnterpriseNewsDto;
+import com.ruoyi.collaborativeApproval.service.EnterpriseNewsService;
+import com.ruoyi.collaborativeApproval.vo.EnterpriseNewsVo;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:50:59
+ */
+@RestController
+@RequestMapping("/enterpriseNews")
+@Tag(name = "浼佷笟鏂伴椈琛�")
+@AllArgsConstructor
+public class EnterpriseNewsController {
+
+ private final EnterpriseNewsService enterpriseNewsService;
+
+ @Operation(summary = "鍒嗛〉鏌ヨ")
+ @GetMapping("/listPage")
+ @Log(title = "浼佷笟鏂伴椈鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
+ public R listPage(Page<EnterpriseNewsVo> page , EnterpriseNewsDto enterpriseNewsDto) {
+ return R.ok(enterpriseNewsService.listPage(page, enterpriseNewsDto));
+ }
+
+ @PostMapping("/save")
+ @Operation(summary = "淇濆瓨")
+ @Log(title = "淇濆瓨浼佷笟鏂伴椈", businessType = BusinessType.INSERT)
+ public R save(@RequestBody EnterpriseNewsDto enterpriseNewsDto) {
+ return R.ok(enterpriseNewsService.add(enterpriseNewsDto));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "鏇存柊")
+ @Log(title = "鏇存柊浼佷笟鏂伴椈", businessType = BusinessType.UPDATE)
+ public R update(@RequestBody EnterpriseNewsDto enterpriseNewsDto) {
+ return R.ok(enterpriseNewsService.updateEnterpriseNewsDto(enterpriseNewsDto));
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "鍒犻櫎")
+ @Log(title = "鍒犻櫎浼佷笟鏂伴椈", businessType = BusinessType.DELETE)
+ public R delete(@RequestBody List<Long> ids) {
+ return R.ok(enterpriseNewsService.delete(ids));
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeDeptController.java b/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeDeptController.java
new file mode 100644
index 0000000..8c68d1a
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeDeptController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.collaborativeApproval.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿閮ㄩ棬琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:12
+ */
+@RestController
+@RequestMapping("/enterpriseNewsScopeDept")
+public class EnterpriseNewsScopeDeptController {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeUserController.java b/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeUserController.java
new file mode 100644
index 0000000..7ceba13
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeUserController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.collaborativeApproval.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿鐢ㄦ埛琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:23
+ */
+@RestController
+@RequestMapping("/enterpriseNewsScopeUser")
+public class EnterpriseNewsScopeUserController {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/dto/EnterpriseNewsDto.java b/src/main/java/com/ruoyi/collaborativeApproval/dto/EnterpriseNewsDto.java
new file mode 100644
index 0000000..108cf66
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/dto/EnterpriseNewsDto.java
@@ -0,0 +1,26 @@
+package com.ruoyi.collaborativeApproval.dto;
+
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class EnterpriseNewsDto extends EnterpriseNews {
+
+ private String createUserName;
+
+ private List<Long> deptIds;
+
+ private List<Long> userIds;
+
+ private Long templateId;
+ private String templateName;
+
+ private String createTimeStart;
+ private String createTimeEnd;
+
+ private List<StorageBlobDTO> storageBlobDTOs;
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsMapper.java b/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsMapper.java
new file mode 100644
index 0000000..799ae82
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.collaborativeApproval.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.collaborativeApproval.dto.EnterpriseNewsDto;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
+import com.ruoyi.collaborativeApproval.vo.EnterpriseNewsVo;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:50:59
+ */
+@Mapper
+public interface EnterpriseNewsMapper extends BaseMapper<EnterpriseNews> {
+
+ IPage<EnterpriseNewsVo> listPage(Page<EnterpriseNewsVo> page,@Param("enterpriseNewsDto") EnterpriseNewsDto enterpriseNewsDto);
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeDeptMapper.java b/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeDeptMapper.java
new file mode 100644
index 0000000..5b4639f
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeDeptMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.collaborativeApproval.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿閮ㄩ棬琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:12
+ */
+@Mapper
+public interface EnterpriseNewsScopeDeptMapper extends BaseMapper<EnterpriseNewsScopeDept> {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeUserMapper.java b/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeUserMapper.java
new file mode 100644
index 0000000..ab9a64f
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeUserMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.collaborativeApproval.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿鐢ㄦ埛琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:23
+ */
+@Mapper
+public interface EnterpriseNewsScopeUserMapper extends BaseMapper<EnterpriseNewsScopeUser> {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNews.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNews.java
new file mode 100644
index 0000000..f5e001b
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNews.java
@@ -0,0 +1,88 @@
+package com.ruoyi.collaborativeApproval.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 浼佷笟鏂伴椈琛�
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:50:59
+ */
+@Getter
+@Setter
+@ToString
+@TableName("enterprise_news")
+@ApiModel(value = "EnterpriseNews瀵硅薄", description = "浼佷笟鏂伴椈琛�")
+public class EnterpriseNews implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Schema(description = "缂栧彿 ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ @Schema(description = "鏍囬 Title")
+ private String title;
+
+ @Schema(description = "鎽樿 Summary")
+ private String summary;
+
+ @Schema(description = "姝f枃 Content")
+ private String content;
+
+ @Schema(description = "鍒嗙被 Category")
+ private String category;
+
+ @Schema(description = "闃呰鑼冨洿 Read scope: all 鍏ㄥ憳, dept 閮ㄩ棬, custom 鑷畾涔�")
+ private String readScope;
+
+ @Schema(description = "鏄惁蹇呰 Required flag: 0 鍚�, 1 鏄�")
+ private Byte isRequired;
+
+ @Schema(description = "鐘舵�� Status: DRAFT 鑽夌, PENDING 寰呭鎵�, PUBLISHED 宸插彂甯�, REJECTED 椹冲洖, OFFLINE 宸蹭笅绾�")
+ private String status;
+
+ @Schema(description = "搴旇浜烘暟 Required read count")
+ private Integer requiredReadCount;
+
+ @Schema(description = "宸茶浜烘暟 Read count")
+ private Integer readCount;
+
+ @Schema(description = "鍒涘缓浜� Create user")
+ @TableField(fill = FieldFill.INSERT)
+ private Long createUser;
+
+ @Schema(description = "鍒涘缓鏃堕棿 Create time")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss", iso = DateTimeFormat.ISO.DATE_TIME)
+ private LocalDateTime createTime;
+
+ @Schema(description = "鏇存柊浜� Update user")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Long updateUser;
+
+ @Schema(description = "鏇存柊鏃堕棿 Update time")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss", iso = DateTimeFormat.ISO.DATE_TIME)
+ private LocalDateTime updateTime;
+
+ @Schema(description = "閮ㄩ棬ID Dept ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeDept.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeDept.java
new file mode 100644
index 0000000..97ff9de
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeDept.java
@@ -0,0 +1,59 @@
+package com.ruoyi.collaborativeApproval.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿閮ㄩ棬琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:12
+ */
+@Getter
+@Setter
+@ToString
+@TableName("enterprise_news_scope_dept")
+@ApiModel(value = "EnterpriseNewsScopeDept瀵硅薄", description = "浼佷笟鏂伴椈闃呰鑼冨洿閮ㄩ棬琛�")
+public class EnterpriseNewsScopeDept implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 缂栧彿
+ */
+ @ApiModelProperty("缂栧彿")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 浼佷笟鏂伴椈ID
+ */
+ @ApiModelProperty("浼佷笟鏂伴椈ID")
+ private Long newsId;
+
+ /**
+ * 閮ㄩ棬ID
+ */
+ @ApiModelProperty("閮ㄩ棬ID")
+ private Long deptId;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeUser.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeUser.java
new file mode 100644
index 0000000..9d43df2
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeUser.java
@@ -0,0 +1,59 @@
+package com.ruoyi.collaborativeApproval.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿鐢ㄦ埛琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:23
+ */
+@Getter
+@Setter
+@ToString
+@TableName("enterprise_news_scope_user")
+@ApiModel(value = "EnterpriseNewsScopeUser瀵硅薄", description = "浼佷笟鏂伴椈闃呰鑼冨洿鐢ㄦ埛琛�")
+public class EnterpriseNewsScopeUser implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 缂栧彿
+ */
+ @ApiModelProperty("缂栧彿")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 浼佷笟鏂伴椈ID
+ */
+ @ApiModelProperty("浼佷笟鏂伴椈ID")
+ private Long newsId;
+
+ /**
+ * 鐢ㄦ埛ID
+ */
+ @ApiModelProperty("鐢ㄦ埛ID")
+ private Long userId;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeDeptService.java b/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeDeptService.java
new file mode 100644
index 0000000..b41a7d8
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeDeptService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.collaborativeApproval.service;
+
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿閮ㄩ棬琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:12
+ */
+public interface EnterpriseNewsScopeDeptService extends IService<EnterpriseNewsScopeDept> {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeUserService.java b/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeUserService.java
new file mode 100644
index 0000000..28ac6c7
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeUserService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.collaborativeApproval.service;
+
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿鐢ㄦ埛琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:23
+ */
+public interface EnterpriseNewsScopeUserService extends IService<EnterpriseNewsScopeUser> {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsService.java b/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsService.java
new file mode 100644
index 0000000..21e7e6c
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsService.java
@@ -0,0 +1,29 @@
+package com.ruoyi.collaborativeApproval.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.collaborativeApproval.dto.EnterpriseNewsDto;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.collaborativeApproval.vo.EnterpriseNewsVo;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:50:59
+ */
+public interface EnterpriseNewsService extends IService<EnterpriseNews> {
+
+ IPage<EnterpriseNewsVo> listPage(Page<EnterpriseNewsVo> page, EnterpriseNewsDto enterpriseNewsDto);
+
+ Boolean add(EnterpriseNewsDto enterpriseNewsDto);
+
+ Boolean updateEnterpriseNewsDto(EnterpriseNewsDto enterpriseNewsDto);
+
+ Boolean delete(List<Long> ids);
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeDeptServiceImpl.java b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeDeptServiceImpl.java
new file mode 100644
index 0000000..22283c7
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeDeptServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.collaborativeApproval.service.impl;
+
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept;
+import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeDeptMapper;
+import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeDeptService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿閮ㄩ棬琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:12
+ */
+@Service
+public class EnterpriseNewsScopeDeptServiceImpl extends ServiceImpl<EnterpriseNewsScopeDeptMapper, EnterpriseNewsScopeDept> implements EnterpriseNewsScopeDeptService {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeUserServiceImpl.java b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeUserServiceImpl.java
new file mode 100644
index 0000000..db1521e
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeUserServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.collaborativeApproval.service.impl;
+
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser;
+import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeUserMapper;
+import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeUserService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿鐢ㄦ埛琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:23
+ */
+@Service
+public class EnterpriseNewsScopeUserServiceImpl extends ServiceImpl<EnterpriseNewsScopeUserMapper, EnterpriseNewsScopeUser> implements EnterpriseNewsScopeUserService {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsServiceImpl.java b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsServiceImpl.java
new file mode 100644
index 0000000..2d89e2c
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsServiceImpl.java
@@ -0,0 +1,409 @@
+package com.ruoyi.collaborativeApproval.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.approve.mapper.ApprovalInstanceMapper;
+import com.ruoyi.approve.mapper.ApprovalTemplateMapper;
+import com.ruoyi.approve.pojo.ApprovalInstance;
+import com.ruoyi.approve.pojo.ApprovalTask;
+import com.ruoyi.approve.pojo.ApprovalTemplate;
+import com.ruoyi.approve.service.ApprovalInstanceService;
+import com.ruoyi.approve.utils.ApproveProcessConfigNodeUtils;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
+import com.ruoyi.collaborativeApproval.dto.EnterpriseNewsDto;
+import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsMapper;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser;
+import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeDeptService;
+import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeUserService;
+import com.ruoyi.collaborativeApproval.service.EnterpriseNewsService;
+import com.ruoyi.collaborativeApproval.vo.EnterpriseNewsVo;
+import com.ruoyi.common.enums.TypeEnums;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.OrderUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.project.system.domain.SysDept;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysDeptMapper;
+import com.ruoyi.project.system.mapper.SysUserDeptMapper;
+import com.ruoyi.project.system.mapper.SysUserMapper;
+import com.ruoyi.project.system.service.ISysNoticeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * 浼佷笟鏂伴椈琛ㄦ湇鍔″疄鐜扮被
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:50:59
+ */
+@Service
+@RequiredArgsConstructor
+public class EnterpriseNewsServiceImpl extends ServiceImpl<EnterpriseNewsMapper, EnterpriseNews> implements EnterpriseNewsService {
+
+ private static final String READ_SCOPE_ALL = "all";
+ private static final String READ_SCOPE_DEPT = "dept";
+ private static final String READ_SCOPE_CUSTOM = "custom";
+
+ private static final String STATUS_DRAFT = "DRAFT";
+ private static final String STATUS_PENDING = "PENDING";
+ private static final String STATUS_PUBLISHED = "PUBLISHED";
+ private static final String STATUS_REJECTED = "REJECTED";
+ private static final String STATUS_OFFLINE = "OFFLINE";
+
+ private final EnterpriseNewsMapper enterpriseNewsMapper;
+ private final EnterpriseNewsScopeDeptService enterpriseNewsScopeDeptService;
+ private final EnterpriseNewsScopeUserService enterpriseNewsScopeUserService;
+ private final SysUserMapper sysUserMapper;
+ private final SysDeptMapper sysDeptMapper;
+ private final SysUserDeptMapper sysUserDeptMapper;
+ private final ApprovalInstanceMapper approvalInstanceMapper;
+ private final ApprovalInstanceService approvalInstanceService;
+ private final ApprovalTemplateMapper approvalTemplateMapper;
+ private final ApproveProcessConfigNodeUtils approveProcessConfigNodeUtils;
+ private final ISysNoticeService sysNoticeService;
+ private final FileUtil fileUtil;
+
+ @Override
+ public IPage<EnterpriseNewsVo> listPage(Page<EnterpriseNewsVo> page, EnterpriseNewsDto enterpriseNewsDto) {
+ IPage<EnterpriseNewsVo> enterpriseNewsVoIPage = enterpriseNewsMapper.listPage(page, enterpriseNewsDto);
+ enterpriseNewsVoIPage.getRecords().forEach(enterpriseNewsVo -> {
+ enterpriseNewsVo.setStorageBlobDTOs(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.ENTERPRISE_NEWS, enterpriseNewsVo.getId()));
+ });
+ return enterpriseNewsVoIPage;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean add(EnterpriseNewsDto enterpriseNewsDto) {
+ validateForSave(enterpriseNewsDto);
+ String readScope = normalizeReadScope(enterpriseNewsDto.getReadScope());
+ List<Long> deptIds = distinctIds(enterpriseNewsDto.getDeptIds());
+ List<Long> userIds = distinctIds(enterpriseNewsDto.getUserIds());
+
+ EnterpriseNews enterpriseNews = new EnterpriseNews();
+ BeanUtils.copyProperties(enterpriseNewsDto, enterpriseNews);
+ enterpriseNews.setReadScope(readScope);
+ enterpriseNews.setIsRequired(enterpriseNewsDto.getIsRequired() == null ? (byte) 0 : enterpriseNewsDto.getIsRequired());
+ enterpriseNews.setStatus(normalizeStatus(enterpriseNewsDto.getStatus(), STATUS_DRAFT));
+ enterpriseNews.setReadCount(0);
+ enterpriseNews.setRequiredReadCount(calculateRequiredReadCount(readScope, deptIds, userIds));
+
+ Long[] loginDeptIds = SecurityUtils.getDeptId();
+ if (StringUtils.isNotEmpty(loginDeptIds)) {
+ enterpriseNews.setDeptId(loginDeptIds[0]);
+ }
+
+ if (!save(enterpriseNews) || enterpriseNews.getId() == null) {
+ throw new ServiceException("鏂板浼佷笟鏂伴椈澶辫触");
+ }
+
+ saveReadScopeRelations(enterpriseNews.getId(), readScope, deptIds, userIds);
+ if (STATUS_PENDING.equals(enterpriseNews.getStatus())) {
+ startEnterpriseNewsApproval(enterpriseNews, enterpriseNewsDto);
+ }
+ //娣诲姞闄勪欢
+ fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.ENTERPRISE_NEWS, enterpriseNews.getId(), enterpriseNewsDto.getStorageBlobDTOs());
+ return true;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean updateEnterpriseNewsDto(EnterpriseNewsDto enterpriseNewsDto) {
+ if (enterpriseNewsDto == null || enterpriseNewsDto.getId() == null) {
+ throw new ServiceException("浼佷笟鏂伴椈ID涓嶈兘涓虹┖");
+ }
+
+ EnterpriseNews oldEnterpriseNews = getById(enterpriseNewsDto.getId());
+ if (oldEnterpriseNews == null) {
+ throw new ServiceException("浼佷笟鏂伴椈涓嶅瓨鍦�");
+ }
+ if (!STATUS_DRAFT.equals(oldEnterpriseNews.getStatus())
+ && !STATUS_REJECTED.equals(oldEnterpriseNews.getStatus())) {
+ throw new ServiceException("寰呭鎵规垨宸插彂甯冪殑浼佷笟鏂伴椈涓嶅厑璁镐慨鏀�");
+ }
+
+ validateForSave(enterpriseNewsDto);
+ String readScope = normalizeReadScope(enterpriseNewsDto.getReadScope());
+ List<Long> deptIds = distinctIds(enterpriseNewsDto.getDeptIds());
+ List<Long> userIds = distinctIds(enterpriseNewsDto.getUserIds());
+
+ EnterpriseNews enterpriseNews = new EnterpriseNews();
+ BeanUtils.copyProperties(enterpriseNewsDto, enterpriseNews);
+ enterpriseNews.setReadScope(readScope);
+ enterpriseNews.setIsRequired(enterpriseNewsDto.getIsRequired() == null ? oldEnterpriseNews.getIsRequired() : enterpriseNewsDto.getIsRequired());
+ enterpriseNews.setStatus(normalizeStatus(enterpriseNewsDto.getStatus(), oldEnterpriseNews.getStatus()));
+ enterpriseNews.setReadCount(oldEnterpriseNews.getReadCount());
+ enterpriseNews.setRequiredReadCount(calculateRequiredReadCount(readScope, deptIds, userIds));
+ enterpriseNews.setCreateUser(oldEnterpriseNews.getCreateUser());
+ enterpriseNews.setCreateTime(oldEnterpriseNews.getCreateTime());
+ enterpriseNews.setDeptId(oldEnterpriseNews.getDeptId());
+
+ if (!updateById(enterpriseNews)) {
+ throw new ServiceException("淇敼浼佷笟鏂伴椈澶辫触");
+ }
+
+ clearReadScopeRelations(enterpriseNews.getId());
+ saveReadScopeRelations(enterpriseNews.getId(), readScope, deptIds, userIds);
+ fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.ENTERPRISE_NEWS, enterpriseNews.getId(), enterpriseNewsDto.getStorageBlobDTOs());
+ if (STATUS_PENDING.equals(enterpriseNews.getStatus())) {
+ resetEnterpriseNewsApprovalFlow(oldEnterpriseNews);
+ startEnterpriseNewsApproval(enterpriseNews, enterpriseNewsDto);
+ }
+ return true;
+ }
+
+ @Override
+ public Boolean delete(List<Long> ids) {
+ if (ids == null || ids.isEmpty()) {
+ return false;
+ }
+ if (!removeByIds(ids)) {
+ throw new ServiceException("鍒犻櫎浼佷笟鏂伴椈澶辫触");
+ }
+ ids.forEach(this::clearReadScopeRelations);
+ return true;
+ }
+
+ private void validateForSave(EnterpriseNewsDto enterpriseNewsDto) {
+ if (enterpriseNewsDto == null) {
+ throw new ServiceException("浼佷笟鏂伴椈鏁版嵁涓嶈兘涓虹┖");
+ }
+ if (StringUtils.isEmpty(enterpriseNewsDto.getTitle())) {
+ throw new ServiceException("鏍囬涓嶈兘涓虹┖");
+ }
+ if (StringUtils.isEmpty(enterpriseNewsDto.getContent())) {
+ throw new ServiceException("姝f枃涓嶈兘涓虹┖");
+ }
+
+ normalizeStatus(enterpriseNewsDto.getStatus(), STATUS_DRAFT);
+ String readScope = normalizeReadScope(enterpriseNewsDto.getReadScope());
+ List<Long> deptIds = distinctIds(enterpriseNewsDto.getDeptIds());
+ List<Long> userIds = distinctIds(enterpriseNewsDto.getUserIds());
+
+ if (READ_SCOPE_DEPT.equals(readScope) && StringUtils.isEmpty(deptIds)) {
+ throw new ServiceException("璇烽�夋嫨闃呰鑼冨洿閮ㄩ棬");
+ }
+ if (READ_SCOPE_CUSTOM.equals(readScope) && StringUtils.isEmpty(userIds)) {
+ throw new ServiceException("璇烽�夋嫨鑷畾涔夐槄璇讳汉鍛�");
+ }
+
+ validateDeptIds(deptIds);
+ validateUserIds(userIds);
+ }
+
+ private String normalizeReadScope(String readScope) {
+ String normalized = StringUtils.isEmpty(readScope) ? READ_SCOPE_ALL : readScope.trim();
+ if (!READ_SCOPE_ALL.equals(normalized)
+ && !READ_SCOPE_DEPT.equals(normalized)
+ && !READ_SCOPE_CUSTOM.equals(normalized)) {
+ throw new ServiceException("闃呰鑼冨洿涓嶅悎娉�");
+ }
+ return normalized;
+ }
+
+ private String normalizeStatus(String status, String defaultStatus) {
+ String normalized = StringUtils.isEmpty(status) ? defaultStatus : status.trim().toUpperCase();
+ if (!STATUS_DRAFT.equals(normalized)
+ && !STATUS_PENDING.equals(normalized)
+ && !STATUS_PUBLISHED.equals(normalized)
+ && !STATUS_REJECTED.equals(normalized)
+ && !STATUS_OFFLINE.equals(normalized)) {
+ throw new ServiceException("浼佷笟鏂伴椈鐘舵�佷笉鍚堟硶");
+ }
+ return normalized;
+ }
+
+ private void validateDeptIds(List<Long> deptIds) {
+ if (StringUtils.isEmpty(deptIds)) {
+ return;
+ }
+ for (Long deptId : deptIds) {
+ SysDept sysDept = sysDeptMapper.selectDeptById(deptId);
+ if (deptId == null || sysDept == null) {
+ throw new ServiceException("闃呰鑼冨洿閮ㄩ棬涓嶅瓨鍦�");
+ }
+ }
+ }
+
+ private void validateUserIds(List<Long> userIds) {
+ if (StringUtils.isEmpty(userIds)) {
+ return;
+ }
+ List<SysUser> users = sysUserMapper.selectUsersByIds(userIds);
+ if (users.size() != userIds.size()) {
+ throw new ServiceException("鑷畾涔夐槄璇讳汉鍛樺寘鍚棤鏁堢敤鎴�");
+ }
+ }
+
+ private Integer calculateRequiredReadCount(String readScope, List<Long> deptIds, List<Long> userIds) {
+ if (READ_SCOPE_ALL.equals(readScope)) {
+ Long count = sysUserMapper.selectCount(new LambdaQueryWrapper<SysUser>()
+ .eq(SysUser::getDelFlag, "0"));
+ return count == null ? 0 : count.intValue();
+ }
+ if (READ_SCOPE_DEPT.equals(readScope)) {
+ List<Long> allDeptIds = collectDeptIdsWithChildren(deptIds);
+ if (StringUtils.isEmpty(allDeptIds)) {
+ return 0;
+ }
+ Long count = sysUserDeptMapper.countDistinctUserIdsByDeptIds(allDeptIds);
+ return count == null ? 0 : count.intValue();
+ }
+ return userIds.size();
+ }
+
+ private List<Long> collectDeptIdsWithChildren(List<Long> deptIds) {
+ Set<Long> allDeptIds = new LinkedHashSet<>();
+ for (Long deptId : deptIds) {
+ if (deptId == null) {
+ continue;
+ }
+ allDeptIds.add(deptId);
+ List<SysDept> children = sysDeptMapper.selectChildrenDeptById(deptId);
+ if (StringUtils.isNotEmpty(children)) {
+ for (SysDept child : children) {
+ allDeptIds.add(child.getDeptId());
+ }
+ }
+ }
+ return new ArrayList<>(allDeptIds);
+ }
+
+ private void saveReadScopeRelations(Long newsId, String readScope, List<Long> deptIds, List<Long> userIds) {
+ if (READ_SCOPE_DEPT.equals(readScope)) {
+ List<EnterpriseNewsScopeDept> scopeDeptList = new ArrayList<>();
+ for (Long deptId : deptIds) {
+ EnterpriseNewsScopeDept scopeDept = new EnterpriseNewsScopeDept();
+ scopeDept.setNewsId(newsId);
+ scopeDept.setDeptId(deptId);
+ scopeDeptList.add(scopeDept);
+ }
+ if (StringUtils.isNotEmpty(scopeDeptList)) {
+ enterpriseNewsScopeDeptService.saveBatch(scopeDeptList);
+ }
+ return;
+ }
+
+ if (READ_SCOPE_CUSTOM.equals(readScope)) {
+ List<EnterpriseNewsScopeUser> scopeUserList = new ArrayList<>();
+ for (Long userId : userIds) {
+ EnterpriseNewsScopeUser scopeUser = new EnterpriseNewsScopeUser();
+ scopeUser.setNewsId(newsId);
+ scopeUser.setUserId(userId);
+ scopeUserList.add(scopeUser);
+ }
+ if (StringUtils.isNotEmpty(scopeUserList)) {
+ enterpriseNewsScopeUserService.saveBatch(scopeUserList);
+ }
+ }
+ }
+
+ private void clearReadScopeRelations(Long newsId) {
+ enterpriseNewsScopeDeptService.remove(new LambdaQueryWrapper<EnterpriseNewsScopeDept>()
+ .eq(EnterpriseNewsScopeDept::getNewsId, newsId));
+ enterpriseNewsScopeUserService.remove(new LambdaQueryWrapper<EnterpriseNewsScopeUser>()
+ .eq(EnterpriseNewsScopeUser::getNewsId, newsId));
+ }
+
+ private void resetEnterpriseNewsApprovalFlow(EnterpriseNews oldEnterpriseNews) {
+ if (oldEnterpriseNews == null || !STATUS_DRAFT.equals(oldEnterpriseNews.getStatus())) {
+ return;
+ }
+ List<Long> approvalInstanceIds = approvalInstanceMapper.selectList(new LambdaQueryWrapper<ApprovalInstance>()
+ .eq(ApprovalInstance::getBusinessId, oldEnterpriseNews.getId())
+ .eq(ApprovalInstance::getBusinessType, TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode())
+ .eq(ApprovalInstance::getDeleted, (byte) 0))
+ .stream()
+ .map(ApprovalInstance::getId)
+ .filter(id -> id != null && id > 0)
+ .collect(Collectors.toList());
+ if (StringUtils.isEmpty(approvalInstanceIds)) {
+ return;
+ }
+ approvalInstanceService.delete(approvalInstanceIds);
+ }
+
+ private List<Long> distinctIds(List<Long> ids) {
+ if (StringUtils.isEmpty(ids)) {
+ return new ArrayList<>();
+ }
+ Set<Long> distinctSet = new LinkedHashSet<>();
+ for (Long id : ids) {
+ if (id != null) {
+ distinctSet.add(id);
+ }
+ }
+ return new ArrayList<>(distinctSet);
+ }
+
+ private void startEnterpriseNewsApproval(EnterpriseNews enterpriseNews, EnterpriseNewsDto enterpriseNewsDto) {
+ if (enterpriseNewsDto.getTemplateId() == null) {
+ throw new ServiceException("瀹℃壒妯℃澘涓嶈兘涓虹┖");
+ }
+
+ String templateName = enterpriseNewsDto.getTemplateName();
+ if (StringUtils.isEmpty(templateName)) {
+ ApprovalTemplate approvalTemplate = approvalTemplateMapper.selectById(enterpriseNewsDto.getTemplateId());
+ if (approvalTemplate == null) {
+ throw new ServiceException("瀹℃壒妯℃澘涓嶅瓨鍦�");
+ }
+ templateName = approvalTemplate.getTemplateName();
+ }
+
+ ApprovalInstance approvalInstance = new ApprovalInstance();
+ approvalInstance.setInstanceNo(OrderUtils.countTodayByCreateTime(approvalInstanceMapper, "SP", "instance_no"));
+ approvalInstance.setTemplateId(enterpriseNewsDto.getTemplateId());
+ approvalInstance.setTemplateName(templateName);
+ approvalInstance.setBusinessId(enterpriseNews.getId());
+ approvalInstance.setBusinessType(TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode());
+ approvalInstance.setTitle(enterpriseNews.getTitle());
+ approvalInstance.setStatus("PENDING");
+ approvalInstance.setCurrentLevel(1);
+ approvalInstance.setApplicantId(SecurityUtils.getUserId());
+ approvalInstance.setApplicantName(SecurityUtils.getLoginUser().getNickName());
+ approvalInstance.setApplyTime(LocalDateTime.now());
+ approvalInstance.setDeleted((byte) 0);
+ approvalInstance.setCreateUser(SecurityUtils.getUserId());
+ approvalInstance.setUpdateUser(SecurityUtils.getUserId());
+ approvalInstance.setDeptId(enterpriseNews.getDeptId());
+ approvalInstanceMapper.insert(approvalInstance);
+
+ approveProcessConfigNodeUtils.createCurrentNodeAndTasks(approvalInstance);
+ sendApproveNotice(approvalInstance, approveProcessConfigNodeUtils.getCurrentPendingTasks(approvalInstance.getId()));
+ }
+
+ private void sendApproveNotice(ApprovalInstance instance, List<ApprovalTask> tasks) {
+ if (instance == null || tasks == null || tasks.isEmpty()) {
+ return;
+ }
+ List<Long> approverIds = tasks.stream()
+ .map(ApprovalTask::getApproverId)
+ .filter(id -> id != null && id > 0)
+ .distinct()
+ .collect(Collectors.toList());
+ if (approverIds.isEmpty()) {
+ return;
+ }
+
+ String title = StringUtils.isNotEmpty(instance.getTemplateName()) ? instance.getTemplateName() : "瀹℃壒鎻愰啋";
+ String message = "瀹℃壒鍗曞彿 " + instance.getInstanceNo() + " 闇�瑕佹偍瀹℃壒";
+ String jumpPath = "/officeProcessAutomation/ApproveManage/approve-list/?id=" + instance.getId();
+ sysNoticeService.simpleNoticeByUser(title, message, approverIds, jumpPath);
+ }
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/vo/EnterpriseNewsVo.java b/src/main/java/com/ruoyi/collaborativeApproval/vo/EnterpriseNewsVo.java
new file mode 100644
index 0000000..66123b9
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/vo/EnterpriseNewsVo.java
@@ -0,0 +1,15 @@
+package com.ruoyi.collaborativeApproval.vo;
+
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class EnterpriseNewsVo extends EnterpriseNews {
+
+ private String createUserName;
+
+ private List<StorageBlobVO> storageBlobDTOs;
+}
diff --git a/src/main/java/com/ruoyi/common/enums/ApprovalStatusEnum.java b/src/main/java/com/ruoyi/common/enums/ApprovalStatusEnum.java
new file mode 100644
index 0000000..8913ebd
--- /dev/null
+++ b/src/main/java/com/ruoyi/common/enums/ApprovalStatusEnum.java
@@ -0,0 +1,49 @@
+package com.ruoyi.common.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 瀹℃壒鐘舵�佹灇涓�
+ */
+@Getter
+@AllArgsConstructor
+public enum ApprovalStatusEnum implements BaseEnum<Integer> {
+
+ DRAFT(0, "鑽夌"),
+ PENDING(1, "寰呭鎵�"),
+ IN_PROGRESS(2, "瀹℃壒涓�"),
+ APPROVED(3, "宸查�氳繃"),
+ REJECTED(4, "宸查┏鍥�");
+
+
+ private final Integer value;
+ private final String label;
+
+ @Override
+ public Integer getCode() {
+ return value;
+ }
+
+ @Override
+ public String getValue() {
+ return label;
+ }
+
+ public static ApprovalStatusEnum fromValue(Integer value) {
+ if (value == null) {
+ return null;
+ }
+ for (ApprovalStatusEnum status : values()) {
+ if (status.getCode().equals(value)) {
+ return status;
+ }
+ }
+ return null;
+ }
+
+ public static String getLabelByValue(Integer value) {
+ ApprovalStatusEnum statusEnum = fromValue(value);
+ return statusEnum != null ? statusEnum.getValue() : "鏈煡鐘舵��";
+ }
+}
diff --git a/src/main/java/com/ruoyi/common/enums/EnterpriseNewsStatusEnum.java b/src/main/java/com/ruoyi/common/enums/EnterpriseNewsStatusEnum.java
new file mode 100644
index 0000000..8e6e480
--- /dev/null
+++ b/src/main/java/com/ruoyi/common/enums/EnterpriseNewsStatusEnum.java
@@ -0,0 +1,143 @@
+package com.ruoyi.common.enums;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+
+/**
+ * 浼佷笟鏂伴椈鐘舵�佹灇涓剧被
+ *
+ * @author ruoyi
+ * @date 2026-05-20
+ */
+@Schema(description = "浼佷笟鏂伴椈鐘舵�佹灇涓�")
+public enum EnterpriseNewsStatusEnum implements BaseEnum<String> {
+
+ /**
+ * 鑽夌
+ */
+ @Schema(description = "鑽夌")
+ DRAFT("DRAFT", "鑽夌"),
+
+ /**
+ * 寰呭鎵�
+ */
+ @Schema(description = "寰呭鎵�")
+ PENDING("PENDING", "寰呭鎵�"),
+
+ /**
+ * 宸插彂甯�
+ */
+ @Schema(description = "宸插彂甯�")
+ PUBLISHED("PUBLISHED", "宸插彂甯�"),
+
+ /**
+ * 椹冲洖
+ */
+ @Schema(description = "椹冲洖")
+ REJECTED("REJECTED", "椹冲洖"),
+
+ /**
+ * 宸蹭笅绾�
+ */
+ @Schema(description = "宸蹭笅绾�")
+ OFFLINE("OFFLINE", "宸蹭笅绾�");
+
+ /**
+ * 鐘舵�佺爜
+ */
+ private final String code;
+
+ /**
+ * 鐘舵�佹弿杩�
+ * -- GETTER --
+ * 鑾峰彇鐘舵�佹弿杩�
+ *
+ * @return 鐘舵�佹弿杩�
+
+ */
+ @Getter
+ private final String description;
+
+ EnterpriseNewsStatusEnum(String code, String description) {
+ this.code = code;
+ this.description = description;
+ }
+
+ /**
+ * 鑾峰彇鐘舵�佺爜
+ *
+ * @return 鐘舵�佺爜
+ */
+ @JsonValue
+ public String getCode() {
+ return code;
+ }
+
+ @Override
+ public String getValue() {
+ return "";
+ }
+
+ /**
+ * 鏍规嵁鐘舵�佺爜鑾峰彇鏋氫妇
+ *
+ * @param code 鐘舵�佺爜
+ * @return 鏋氫妇鍊�
+ */
+ @JsonCreator
+ public static EnterpriseNewsStatusEnum getByCode(String code) {
+ for (EnterpriseNewsStatusEnum status : values()) {
+ if (status.code.equals(code)) {
+ return status;
+ }
+ }
+ throw new IllegalArgumentException("Invalid enterprise news status code: " + code);
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁涓鸿崏绋跨姸鎬�
+ *
+ * @return 鏄惁涓鸿崏绋跨姸鎬�
+ */
+ public boolean isDraft() {
+ return DRAFT.equals(this);
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁涓哄緟瀹℃壒鐘舵��
+ *
+ * @return 鏄惁涓哄緟瀹℃壒鐘舵��
+ */
+ public boolean isPending() {
+ return PENDING.equals(this);
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁涓哄凡鍙戝竷鐘舵��
+ *
+ * @return 鏄惁涓哄凡鍙戝竷鐘舵��
+ */
+ public boolean isPublished() {
+ return PUBLISHED.equals(this);
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁涓洪┏鍥炵姸鎬�
+ *
+ * @return 鏄惁涓洪┏鍥炵姸鎬�
+ */
+ public boolean isRejected() {
+ return REJECTED.equals(this);
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁涓哄凡涓嬬嚎鐘舵��
+ *
+ * @return 鏄惁涓哄凡涓嬬嚎鐘舵��
+ */
+ public boolean isOffline() {
+ return OFFLINE.equals(this);
+ }
+}
diff --git a/src/main/java/com/ruoyi/common/enums/SalesQuotationStatusEnum.java b/src/main/java/com/ruoyi/common/enums/SalesQuotationStatusEnum.java
new file mode 100644
index 0000000..0789c26
--- /dev/null
+++ b/src/main/java/com/ruoyi/common/enums/SalesQuotationStatusEnum.java
@@ -0,0 +1,43 @@
+package com.ruoyi.common.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 閿�鍞姤浠风姸鎬佹灇涓�
+ */
+@Getter
+@AllArgsConstructor
+public enum SalesQuotationStatusEnum implements BaseEnum<String> {
+
+ DRAFT("鑽夌", "鑽夌"),
+ PENDING("寰呭鎵�", "寰呭鎵�"),
+ IN_PROGRESS("瀹℃牳涓�", "瀹℃牳涓�"),
+ APPROVED("閫氳繃", "閫氳繃"),
+ REJECTED("鎷掔粷", "鎷掔粷");
+
+ private final String value;
+ private final String label;
+
+ @Override
+ public String getCode() {
+ return value;
+ }
+
+ @Override
+ public String getValue() {
+ return label;
+ }
+
+ public static SalesQuotationStatusEnum fromValue(String value) {
+ if (value == null) {
+ return null;
+ }
+ for (SalesQuotationStatusEnum status : values()) {
+ if (status.getCode().equals(value)) {
+ return status;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/ruoyi/common/enums/ShippingStatusEnum.java b/src/main/java/com/ruoyi/common/enums/ShippingStatusEnum.java
new file mode 100644
index 0000000..e8155f2
--- /dev/null
+++ b/src/main/java/com/ruoyi/common/enums/ShippingStatusEnum.java
@@ -0,0 +1,42 @@
+package com.ruoyi.common.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 鍙戣揣瀹℃壒鐘舵�佹灇涓�
+ */
+@Getter
+@AllArgsConstructor
+public enum ShippingStatusEnum implements BaseEnum<String> {
+
+ PENDING("寰呯‘璁�", "寰呯‘璁�"),
+ IN_PROGRESS("瀹℃牳涓�", "瀹℃牳涓�"),
+ APPROVED("瀹℃牳閫氳繃", "瀹℃牳閫氳繃"),
+ REJECTED("瀹℃牳鎷掔粷", "瀹℃牳鎷掔粷");
+
+ private final String value;
+ private final String label;
+
+ @Override
+ public String getCode() {
+ return value;
+ }
+
+ @Override
+ public String getValue() {
+ return label;
+ }
+
+ public static ShippingStatusEnum fromValue(String value) {
+ if (value == null) {
+ return null;
+ }
+ for (ShippingStatusEnum status : values()) {
+ if (status.getCode().equals(value)) {
+ return status;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/ruoyi/common/enums/TypeEnums.java b/src/main/java/com/ruoyi/common/enums/TypeEnums.java
new file mode 100644
index 0000000..ba1c1f3
--- /dev/null
+++ b/src/main/java/com/ruoyi/common/enums/TypeEnums.java
@@ -0,0 +1,70 @@
+package com.ruoyi.common.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum TypeEnums implements BaseEnum<Long> {
+
+ PUBLIC_OUT(1L, "鍏嚭绠$悊"),
+ LEAVE(2L, "璇峰亣绠$悊"),
+ BUSINESS_TRIP(3L, "鍑哄樊绠$悊"),
+ REIMBURSEMENT(4L, "鎶ラ攢绠$悊"),
+ PURCHASE_APPROVAL(5L, "閲囪喘瀹℃壒"),
+ QUOTATION_APPROVAL(6L, "鎶ヤ环瀹℃壒"),
+ SHIPPING_APPROVAL(7L, "鍙戣揣瀹℃壒"),
+ DANGEROUS_OPERATION(8L, "鍗遍櫓浣滀笟瀹℃壒"),
+ OFFICE_SUPPLIES(9L, "鍔炲叕鐢ㄥ搧瀹℃壒"),
+ REGULARIZATION_APPROVAL(10L, "杞瀹℃壒"),
+ TRANSFER_APPROVAL(11L, "璋冨姩瀹℃壒"),
+ RESIGNATION_APPROVAL(12L, "绂昏亴瀹℃壒"),
+ WORK_HANDOVER_APPROVAL(13L, "宸ヤ綔浜ゆ帴瀹℃壒"),
+ LEAVE_APPROVAL(14L, "璇峰亣瀹℃壒"),
+ OVERTIME_APPROVAL(15L, "鍔犵彮瀹℃壒"),
+ TRAVEL_REIMBURSEMENT_APPROVAL(16L, "鍑哄樊鎶ラ攢瀹℃壒"),
+ EXPENSE_APPROVAL(17L, "璐圭敤瀹℃壒"),
+ ENTERPRISE_NEWS_APPROVAL(18L, "浼佷笟鏂伴椈瀹℃壒");
+
+
+
+ private final Long value;
+ private final String label;
+
+ @Override
+ public Long getCode() {
+ return value;
+ }
+
+ @Override
+ public String getValue() {
+ return label;
+ }
+
+ /**
+ * 鏍规嵁鍊艰幏鍙栧搴旂殑鏋氫妇
+ * @param value 涓氬姟绫诲瀷鍊�
+ * @return 瀵瑰簲鐨勬灇涓撅紝鏈尮閰嶈繑鍥瀗ull
+ */
+ public static TypeEnums fromValue(Long value) {
+ if (value == null) {
+ return null;
+ }
+ for (TypeEnums type : values()) {
+ if (type.getCode().equals(value)) {
+ return type;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 鏍规嵁鍊艰幏鍙栨弿杩�
+ * @param value 涓氬姟绫诲瀷鍊�
+ * @return 涓氬姟绫诲瀷鎻忚堪锛屾湭鍖归厤杩斿洖"鑷畾涔夊鎵�"
+ */
+ public static String getLabelByValue(Long value) {
+ TypeEnums typeEnum = fromValue(value);
+ return typeEnum != null ? typeEnum.getValue() : "鑷畾涔夊鎵�";
+ }
+}
diff --git a/src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java b/src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java
index f4b807d..298980e 100644
--- a/src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java
+++ b/src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java
@@ -35,30 +35,29 @@
private DeviceMaintenanceMapper deviceMaintenanceMapper;
-
@Operation(summary = "璁惧鍙拌处鍒楄〃")
@GetMapping("/page")
- public AjaxResult page(Page page , DeviceLedgerDto deviceLedger) {
- return AjaxResult.success(deviceLedgerService.queryPage(page,deviceLedger));
+ public AjaxResult page(Page page, DeviceLedgerDto deviceLedger) {
+ return AjaxResult.success(deviceLedgerService.queryPage(page, deviceLedger));
}
@PostMapping()
@Operation(summary = "娣诲姞璁惧鍙拌处")
- public AjaxResult add(@RequestBody DeviceLedger deviceLedger) {
-
- return deviceLedgerService.saveDeviceLedger(deviceLedger);
+ public AjaxResult add(@RequestBody DeviceLedgerDto deviceLedgerDto) {
+ return deviceLedgerService.saveDeviceLedger(deviceLedgerDto);
}
@Operation(summary = "鏍规嵁id鏌ヨ璁惧鍙拌处")
@GetMapping("/{id}")
public AjaxResult detail(@PathVariable Long id) {
- return AjaxResult.success(deviceLedgerService.getById(id));
+ DeviceLedgerDto deviceLedgerDto = deviceLedgerService.getDeviceLedgerDetail(id);
+ return AjaxResult.success(deviceLedgerDto);
}
- @PutMapping ()
+ @PutMapping()
@Operation(summary = "淇敼璁惧鍙拌处")
- public AjaxResult update(@RequestBody DeviceLedger deviceLedger) {
- return deviceLedgerService.updateDeviceLedger(deviceLedger);
+ public AjaxResult update(@RequestBody DeviceLedgerDto deviceLedgerDto) {
+ return deviceLedgerService.updateDeviceLedger(deviceLedgerDto);
}
@DeleteMapping("/{ids}")
@@ -74,7 +73,7 @@
@PostMapping("export")
@Operation(summary = "瀵煎嚭璁惧鍙拌处")
public void export(HttpServletResponse response, Long[] ids) {
- deviceLedgerService.export(response, ids);
+ deviceLedgerService.export(response, ids);
}
@Operation(summary = "涓嬭浇妯℃澘")
@@ -97,9 +96,9 @@
@GetMapping("getDeviceLedger")
@Operation(summary = "鑾峰彇璁惧鍙拌处")
- public AjaxResult getDeviceLedger( ) {
+ public AjaxResult getDeviceLedger() {
return AjaxResult.success(deviceLedgerService.list(new QueryWrapper<DeviceLedger>().lambda()
- .select(DeviceLedger::getId, DeviceLedger::getDeviceName,DeviceLedger::getDeviceModel)));
+ .select(DeviceLedger::getId, DeviceLedger::getDeviceName, DeviceLedger::getDeviceModel)));
}
@GetMapping("scanDevice")
@@ -108,8 +107,8 @@
public AjaxResult scanDevice(Long id) {
List<DeviceMaintenance> list = deviceMaintenanceMapper.list1(id);
DeviceLedger deviceLedger = deviceLedgerMapper.selectById1(id);
- if (list.size()>0){
- deviceLedger.setUpdateTime(list.get(0).getMaintenanceActuallyTime());//鏈�鍚庣淮鎶ゆ椂闂�
+ if (!list.isEmpty()) {
+ deviceLedger.setUpdateTime(list.getFirst().getMaintenanceActuallyTime());//鏈�鍚庣淮鎶ゆ椂闂�
}
deviceLedger.setCreateTime(deviceLedger.getUpdateTime().plusMonths(1));//涓嬫缁存姢鏃堕棿
return AjaxResult.success(deviceLedger);
diff --git a/src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java b/src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java
index 79e0aff..8ceb915 100644
--- a/src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java
+++ b/src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java
@@ -12,6 +12,9 @@
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
+import java.util.List;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
/**
* 璁惧鍙拌处瀹炰綋绫�
@@ -55,6 +58,20 @@
private String supplierName;
/**
+ * 璁惧闄勪欢(鐢ㄤ簬鎺ユ敹)
+ */
+ @TableField(exist = false)
+ @Schema(description = "璁惧闄勪欢鎺ユ敹鍒楄〃")
+ private List<StorageBlobDTO> storageBlobDTOs;
+
+ /**
+ * 璁惧闄勪欢(鐢ㄤ簬杩斿洖)
+ */
+ @TableField(exist = false)
+ @Schema(description = "璁惧闄勪欢灞曠ず鍒楄〃")
+ private List<StorageBlobVO> storageBlobVOs;
+
+ /**
* 鍗曚綅
*/
private String unit;
diff --git a/src/main/java/com/ruoyi/device/service/IDeviceLedgerService.java b/src/main/java/com/ruoyi/device/service/IDeviceLedgerService.java
index d34ea65..78dfcac 100644
--- a/src/main/java/com/ruoyi/device/service/IDeviceLedgerService.java
+++ b/src/main/java/com/ruoyi/device/service/IDeviceLedgerService.java
@@ -14,9 +14,11 @@
public interface IDeviceLedgerService extends IService<DeviceLedger> {
IPage<DeviceLedgerDto> queryPage(Page page, DeviceLedgerDto deviceLedger);
- AjaxResult saveDeviceLedger(DeviceLedger deviceLedger);
+ AjaxResult saveDeviceLedger(DeviceLedgerDto deviceLedgerDto);
- AjaxResult updateDeviceLedger(DeviceLedger deviceLedger);
+ AjaxResult updateDeviceLedger(DeviceLedgerDto deviceLedgerDto);
+
+ DeviceLedgerDto getDeviceLedgerDetail(Long id);
void export(HttpServletResponse response, Long[] ids);
diff --git a/src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java b/src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java
index b4c5d65..154923d 100644
--- a/src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java
@@ -12,6 +12,9 @@
import com.ruoyi.device.execl.DeviceLedgerExeclDto;
import com.ruoyi.device.mapper.DeviceLedgerMapper;
import com.ruoyi.device.pojo.DeviceLedger;
+import com.ruoyi.basic.dto.StorageAttachmentDTO;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.service.StorageAttachmentService;
import com.ruoyi.device.service.IDeviceLedgerService;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.system.domain.SysUser;
@@ -36,6 +39,7 @@
private final DeviceLedgerMapper deviceLedgerMapper;
private final SysUserMapper sysUserMapper;
+ private final StorageAttachmentService storageAttachmentService;
@Override
public IPage<DeviceLedgerDto> queryPage(Page page, DeviceLedgerDto deviceLedger) {
@@ -44,25 +48,61 @@
}
@Override
- public AjaxResult saveDeviceLedger(DeviceLedger deviceLedger) {
+ public AjaxResult saveDeviceLedger(DeviceLedgerDto deviceLedgerDto) {
LambdaQueryWrapper<DeviceLedger> deviceLedgerLambdaQueryWrapper = new LambdaQueryWrapper<>();
- deviceLedgerLambdaQueryWrapper.eq(DeviceLedger::getDeviceName,deviceLedger.getDeviceName());
+ deviceLedgerLambdaQueryWrapper.eq(DeviceLedger::getDeviceName,deviceLedgerDto.getDeviceName());
if (this.count(deviceLedgerLambdaQueryWrapper) > 0) {
return AjaxResult.error("璁惧鍚嶇О宸插瓨鍦�");
}
+ DeviceLedger deviceLedger = new DeviceLedger();
+ BeanUtils.copyProperties(deviceLedgerDto, deviceLedger);
boolean save = this.save(deviceLedger);
if (save){
+ if (deviceLedgerDto.getStorageBlobDTOs() != null) {
+ StorageAttachmentDTO attachmentDTO = new StorageAttachmentDTO();
+ attachmentDTO.setApplication("image");
+ attachmentDTO.setRecordType(RecordTypeEnum.DEVICE_LEDGER.getType());
+ attachmentDTO.setRecordId(deviceLedger.getId());
+ attachmentDTO.setStorageBlobDTOs(deviceLedgerDto.getStorageBlobDTOs());
+ storageAttachmentService.saveStorageAttachment(attachmentDTO);
+ }
return AjaxResult.success();
}
return AjaxResult.error();
}
@Override
- public AjaxResult updateDeviceLedger(DeviceLedger deviceLedger) {
+ public AjaxResult updateDeviceLedger(DeviceLedgerDto deviceLedgerDto) {
+ DeviceLedger deviceLedger = new DeviceLedger();
+ BeanUtils.copyProperties(deviceLedgerDto, deviceLedger);
if (this.updateById(deviceLedger)) {
+ if (deviceLedgerDto.getStorageBlobDTOs() != null) {
+ StorageAttachmentDTO attachmentDTO = new StorageAttachmentDTO();
+ attachmentDTO.setApplication("image");
+ attachmentDTO.setRecordType(RecordTypeEnum.DEVICE_LEDGER.getType());
+ attachmentDTO.setRecordId(deviceLedger.getId());
+ attachmentDTO.setStorageBlobDTOs(deviceLedgerDto.getStorageBlobDTOs());
+ storageAttachmentService.saveStorageAttachment(attachmentDTO);
+ }
return AjaxResult.success();
}
return AjaxResult.error();
+ }
+
+ @Override
+ public DeviceLedgerDto getDeviceLedgerDetail(Long id) {
+ DeviceLedger deviceLedger = this.getById(id);
+ if (deviceLedger != null) {
+ DeviceLedgerDto deviceLedgerDto = new DeviceLedgerDto();
+ BeanUtils.copyProperties(deviceLedger, deviceLedgerDto);
+ StorageAttachmentDTO dto = new StorageAttachmentDTO();
+ dto.setRecordType(RecordTypeEnum.DEVICE_LEDGER.getType());
+ dto.setRecordId(id);
+ dto.setApplication("image");
+ deviceLedgerDto.setStorageBlobVOs(storageAttachmentService.list(dto));
+ return deviceLedgerDto;
+ }
+ return null;
}
@Override
@@ -82,9 +122,7 @@
util.exportExcel(response, deviceLedgerExeclDtos, "璁惧鍙拌处瀵煎嚭");
}else {
ArrayList<Long> arrayList = new ArrayList<>();
- Arrays.stream(ids).map(id -> {
- return arrayList.add( id);
- });
+ Arrays.stream(ids).map(arrayList::add);
List<DeviceLedger> supplierManageList = deviceLedgerMapper.selectBatchIds(arrayList);
ArrayList<DeviceLedgerExeclDto> deviceLedgerExeclDtos = new ArrayList<>();
supplierManageList.stream().forEach(deviceLedger -> {
@@ -116,7 +154,10 @@
deviceLedger.setTaxIncludingPriceTotal(c.getTaxIncludingPriceUnit());
deviceLedger.setNumber(BigDecimal.ONE);
deviceLedger.setPlanRuntimeTime(DateUtils.toLocalDate(c.getPlanRuntimeTime()));
- deviceLedger.setUnTaxIncludingPriceTotal(deviceLedger.getTaxIncludingPriceTotal().divide(BigDecimal.ONE.add(c.getTaxRate()),2, RoundingMode.HALF_UP));
+ // 璁$畻涓嶅惈绋庢�讳环锛屽鐞嗙┖鍊兼儏鍐�
+ if (deviceLedger.getTaxIncludingPriceTotal() != null && c.getTaxRate() != null) {
+ deviceLedger.setUnTaxIncludingPriceTotal(deviceLedger.getTaxIncludingPriceTotal().divide(BigDecimal.ONE.add(c.getTaxRate()), 2, RoundingMode.HALF_UP));
+ }
deviceLedgerMapper.insert(deviceLedger);
});
diff --git a/src/main/java/com/ruoyi/home/controller/HomeController.java b/src/main/java/com/ruoyi/home/controller/HomeController.java
index 41ae224..7878d28 100644
--- a/src/main/java/com/ruoyi/home/controller/HomeController.java
+++ b/src/main/java/com/ruoyi/home/controller/HomeController.java
@@ -1,14 +1,21 @@
package com.ruoyi.home.controller;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.approve.pojo.ApproveProcess;
+import com.ruoyi.device.mapper.DeviceLedgerMapper;
+import com.ruoyi.device.mapper.DeviceRepairMapper;
+import com.ruoyi.device.pojo.DeviceRepair;
import com.ruoyi.dto.MapDto;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.domain.R;
import com.ruoyi.home.annotation.DefaultType;
import com.ruoyi.home.dto.*;
import com.ruoyi.home.service.HomeService;
+import com.ruoyi.production.mapper.ProductionOrderMapper;
+import com.ruoyi.production.mapper.ProductionProductOutputMapper;
+import com.ruoyi.production.pojo.ProductionOrder;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.AllArgsConstructor;
@@ -17,9 +24,21 @@
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.text.ParseException;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.*;
/**
* @author :yys
@@ -32,293 +51,698 @@
public class HomeController extends BaseController {
private final HomeService homeService;
+ private final ProductionOrderMapper productionOrderMapper;
+ private final ProductionProductOutputMapper productionProductOutputMapper;
+ private final DeviceLedgerMapper deviceLedgerMapper;
+ private final DeviceRepairMapper deviceRepairMapper;
+
+ private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+ private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ private static final Integer ORDER_STATUS_WAIT = 1;
+ private static final Integer ORDER_STATUS_RUNNING = 2;
+ private static final Integer ORDER_STATUS_COMPLETED = 3;
+ private static final Integer ORDER_STATUS_PAUSED = 4;
/********************************************************鍩虹绫�*****************************************************/
@GetMapping("/todos")
@Log(title = "寰呭姙浜嬮」", businessType = BusinessType.OTHER)
@Operation(summary = "寰呭姙浜嬮」")
- public AjaxResult todos(ApproveProcess req) throws ParseException {
+ public R todos() throws ParseException {
List<ApproveProcess> approveProcessList = homeService.todos();
- return AjaxResult.success(approveProcessList);
+ return R.ok(approveProcessList);
}
@GetMapping("/approveAndDeviceTodos")
@Operation(summary = "瀹℃壒鍗忓悓锛岃澶囨姤淇緟鍔炰簨椤�")
- public AjaxResult approveAndDeviceTodos(){
+ public R approveAndDeviceTodos(){
Map<String, Object> map = homeService.approveAndDeviceTodos();
- return AjaxResult.success(map);
+ return R.ok(map);
}
@GetMapping("/noticesCount")
@Operation(summary = "鏈繃鏈熺殑鍏憡鏁伴噺")
- public AjaxResult noticesCount(){
+ public R noticesCount(){
Long count = homeService.noticesCount();
- return AjaxResult.success(count);
+ return R.ok(count);
}
@GetMapping("/deptStaffDistribution")
@Operation(summary = "鍚勯儴闂ㄤ汉鍛樺垎甯�")
- public AjaxResult deptStaffDistribution() {
+ public R deptStaffDistribution() {
DeptStaffDistributionDto dto = homeService.deptStaffDistribution();
- return AjaxResult.success(dto);
+ return R.ok(dto);
}
@GetMapping("/summaryStatistics")
@Operation(summary = "鍛樺伐-瀹㈡埛-渚涘簲鍟嗘�绘暟")
- public AjaxResult summaryStatistics() {
+ public R summaryStatistics() {
HomeSummaryDto homeSummaryDto = homeService.summaryStatistics();
- return AjaxResult.success(homeSummaryDto);
+ return R.ok(homeSummaryDto);
}
/********************************************************钀ラ攢閲囪喘绫�**************************************************/
@GetMapping("/supplierPurchaseRanking")
@Operation(summary = "渚涘簲鍟嗛噰璐帓鍚�")
- public AjaxResult supplierPurchaseRanking(@DefaultType Integer type) {
+ public R supplierPurchaseRanking(@DefaultType Integer type) {
List<SupplierPurchaseRankingDto> list = homeService.supplierPurchaseRanking(type);
- return AjaxResult.success(list);
+ return R.ok(list);
}
@GetMapping("/customerRevenueAnalysis")
@Operation(summary = "瀹㈡埛钀ユ敹璐$尞鏁板�煎垎鏋�")
- public AjaxResult customerRevenueAnalysis(Long customerId, @DefaultType Integer type) {
+ public R customerRevenueAnalysis(Long customerId, @DefaultType Integer type) {
CustomerRevenueAnalysisDto dto = homeService.customerRevenueAnalysis(customerId, type);
- return AjaxResult.success(dto);
+ return R.ok(dto);
}
@GetMapping("/customerContributionRanking")
@Operation(summary = "瀹㈡埛閲戦璐$尞鎺掑悕")
- public AjaxResult customerContributionRanking(@DefaultType Integer type) {
+ public R customerContributionRanking(@DefaultType Integer type) {
List<CustomerContributionRankingDto> list = homeService.customerContributionRanking(type);
- return AjaxResult.success(list);
+ return R.ok(list);
}
@GetMapping("/productSalesAnalysis")
@Operation(summary = "鍚勪骇鍝侀攢鍞噾棰濆垎鏋�")
- public AjaxResult productSalesAnalysis() {
+ public R productSalesAnalysis() {
List<MapDto> list = homeService.productSalesAnalysis();
- return AjaxResult.success(list);
+ return R.ok(list);
}
@GetMapping("/rawMaterialPurchaseAmountRatio")
@Operation(summary = "鍘熸潗鏂欓噰璐噾棰濆崰姣�")
- public AjaxResult rawMaterialPurchaseAmountRatio(){
+ public R rawMaterialPurchaseAmountRatio(){
List<MapDto> list = homeService.rawMaterialPurchaseAmountRatio();
- return AjaxResult.success(list);
+ return R.ok(list);
}
@GetMapping("/business")
@Log(title = "閿�鍞�-閲囪喘-搴撳瓨鏁版嵁", businessType = BusinessType.OTHER)
@Operation(summary = "閿�鍞�-閲囪喘-搴撳瓨鏁版嵁")
- public AjaxResult business(HomeBusinessDto req) {
+ public R business() {
HomeBusinessDto homeBusinessDto = homeService.business();
- return AjaxResult.success(homeBusinessDto);
+ return R.ok(homeBusinessDto);
}
@GetMapping("/analysisCustomerContractAmounts")
@Log(title = "瀹㈡埛鍚堝悓閲戦鍒嗘瀽", businessType = BusinessType.OTHER)
@Operation(summary = "瀹㈡埛鍚堝悓閲戦鍒嗘瀽")
- public AjaxResult analysisCustomerContractAmounts(AnalysisCustomerContractAmountsDto req) {
+ public R analysisCustomerContractAmounts() {
AnalysisCustomerContractAmountsDto analysisCustomerContractAmounts = homeService.analysisCustomerContractAmounts();
- return AjaxResult.success(analysisCustomerContractAmounts);
+ return R.ok(analysisCustomerContractAmounts);
}
/********************************************************鐢熶骇绫�*****************************************************/
@GetMapping("/inputOutputAnalysis")
@Operation(summary = "鎶曞叆浜у嚭鍒嗘瀽")
- public AjaxResult inputOutputAnalysis(@DefaultType Integer type){
+ public R inputOutputAnalysis(@DefaultType Integer type){
List<InputOutputAnalysisDto> list = homeService.inputOutputAnalysis(type);
- return AjaxResult.success(list);
+ return R.ok(list);
}
@GetMapping("/processOutputAnalysis")
@Operation(summary = "宸ュ簭浜у嚭鍒嗘瀽")
- public AjaxResult processOutputAnalysis(@DefaultType Integer type){
+ public R processOutputAnalysis(@DefaultType Integer type){
List<MapDto> list = homeService.processOutputAnalysis(type);
- return AjaxResult.success(list);
+ return R.ok(list);
}
@GetMapping("/workOrderEfficiencyAnalysis")
@Operation(summary = "宸ュ崟鎵ц鏁堢巼鍒嗘瀽")
- public AjaxResult workOrderEfficiencyAnalysis(@DefaultType Integer type){
+ public R workOrderEfficiencyAnalysis(@DefaultType Integer type){
List<WorkOrderEfficiencyDto> list = homeService.workOrderEfficiencyAnalysis(type);
- return AjaxResult.success(list);
+ return R.ok(list);
}
@GetMapping("/productionAccountingAnalysis")
@Operation(summary = "鐢熶骇鏍哥畻鍒嗘瀽")
- public AjaxResult productionAccountingAnalysis(@DefaultType Integer type){
+ public R productionAccountingAnalysis(@DefaultType Integer type){
List<ProductionAccountingDto> list = homeService.productionAccountingAnalysis(type);
- return AjaxResult.success(list);
+ return R.ok(list);
}
@GetMapping("/orderCount")
@Operation(summary = "璁㈠崟鏁�")
- public AjaxResult orderCount(){
- return AjaxResult.success(homeService.orderCount());
+ public R orderCount(){
+ return R.ok(homeService.orderCount());
}
@GetMapping("/progressStatistics")
@Operation(summary = "鍚勭敓浜ц鍗曠殑瀹屾垚杩涘害缁熻")
- public AjaxResult progressStatistics(){
+ public R progressStatistics(){
ProductionProgressDto productionProgressDto = homeService.productionProgress();
- return AjaxResult.success(productionProgressDto);
+ return R.ok(productionProgressDto);
}
@GetMapping("/workInProcessTurnover")
@Operation(summary = "鍦ㄥ埗鍝佸懆杞儏鍐�")
- public AjaxResult workInProcessTurnover(){
+ public R workInProcessTurnover(){
ProductionTurnoverDto productionTurnoverDto = homeService.workInProcessTurnover();
- return AjaxResult.success(productionTurnoverDto);
+ return R.ok(productionTurnoverDto);
}
@GetMapping("/processDataProductionStatistics")
@Operation(summary = "宸ュ簭鏁版嵁鐢熶骇缁熻鏁版嵁")
- public AjaxResult processDataProductionStatistics(@DefaultType Integer type,@RequestParam(required = false) List<Long> processIds) {
+ public R processDataProductionStatistics(@DefaultType Integer type,@RequestParam(required = false) List<Long> processIds) {
List<processDataProductionStatisticsDto> list = homeService.processDataProductionStatistics(type, processIds);
- return AjaxResult.success(list);
+ return R.ok(list);
}
/********************************************************璐ㄩ噺绫�*****************************************************/
+ @GetMapping("/productionOverview")
+ @Operation(summary = "Production Overview")
+ public R productionOverview() {
+ LocalDate today = LocalDate.now();
+ Map<String, BigDecimal> totalStats = loadOutputStats(LocalDate.of(2000, 1, 1), today.plusDays(1));
+ BigDecimal totalOutput = totalStats.get("quantity");
+ BigDecimal totalScrap = totalStats.get("scrapQty");
+ BigDecimal yieldRate = calcRate(totalOutput, totalOutput.add(totalScrap));
+
+ Map<String, Object> result = new LinkedHashMap<>();
+ result.put("totalOutput", scale(totalOutput));
+ result.put("totalScrap", scale(totalScrap));
+ result.put("yieldRate", scale(yieldRate));
+ return R.ok(result);
+ }
+
+ @GetMapping("/productionRealtimeBoard")
+ @Operation(summary = "Production Realtime Board")
+ public R productionRealtimeBoard() {
+ LocalDate today = LocalDate.now();
+ LocalDate yesterday = today.minusDays(1);
+
+ BigDecimal todayDeviceOee = calcDeviceOee(today);
+ BigDecimal yesterdayDeviceOee = calcDeviceOee(yesterday);
+
+ BigDecimal todayOrderAchievementRate = calcOrderAchievementRate(today);
+ BigDecimal yesterdayOrderAchievementRate = calcOrderAchievementRate(yesterday);
+
+ BigDecimal todayDefectRate = calcDefectRate(today);
+ BigDecimal yesterdayDefectRate = calcDefectRate(yesterday);
+
+ Map<String, Object> result = new LinkedHashMap<>();
+ result.put("deviceOee", buildRealtimeMetric(todayDeviceOee, todayDeviceOee.subtract(yesterdayDeviceOee)));
+ result.put("orderAchievementRate", buildRealtimeMetric(todayOrderAchievementRate, todayOrderAchievementRate.subtract(yesterdayOrderAchievementRate)));
+ result.put("defectRate", buildRealtimeMetric(todayDefectRate, todayDefectRate.subtract(yesterdayDefectRate)));
+ return R.ok(result);
+ }
+
+ @GetMapping("/productionOrderProgress")
+ @Operation(summary = "Production Order Progress")
+ public R productionOrderProgress(@RequestParam(defaultValue = "all") String tab,
+ @RequestParam(required = false) String status,
+ @RequestParam(required = false) String bizDate,
+ @RequestParam(defaultValue = "1") Long pageNum,
+ @RequestParam(defaultValue = "10") Long pageSize) {
+ LocalDate queryDate = parseDateOrNull(bizDate);
+ if (!isBlank(bizDate) && queryDate == null) {
+ return R.fail("bizDate鏍煎紡閿欒锛岃浣跨敤yyyy-MM-dd");
+ }
+ Integer statusFromParam = parseOrderStatus(status);
+ if (!isBlank(status) && statusFromParam == null && !"all".equalsIgnoreCase(status.trim())) {
+ return R.fail("status鍙傛暟涓嶅悎娉曪紝鍙�夊�硷細all/waiting/inProgress/completed/paused 鎴� 1/2/3/4");
+ }
+ Integer queryStatus = resolveOrderStatus(status, tab);
+
+ long safePageNum = pageNum == null || pageNum < 1 ? 1 : pageNum;
+ long safePageSize = pageSize == null || pageSize < 1 ? 10 : Math.min(pageSize, 50);
+ long offset = (safePageNum - 1) * safePageSize;
+ LocalDateTime startTime = queryDate == null ? null : queryDate.atStartOfDay();
+ LocalDateTime endTime = queryDate == null ? null : queryDate.plusDays(1).atStartOfDay();
+
+ List<Map<String, Object>> rawRows = productionOrderMapper.selectHomeOrderProgressPage(queryStatus, offset, safePageSize, startTime, endTime);
+ List<Map<String, Object>> records = new ArrayList<>();
+ if (rawRows != null) {
+ for (Map<String, Object> rawRow : rawRows) {
+ records.add(buildOrderProgressRow(rawRow));
+ }
+ }
+
+ long waitingCount = 0L;
+ long inProgressCount = 0L;
+ long completedCount = 0L;
+ long pausedCount = 0L;
+ List<Map<String, Object>> statusCountRows = productionOrderMapper.countHomeOrderProgressByStatus(startTime, endTime);
+ if (statusCountRows != null) {
+ for (Map<String, Object> countRow : statusCountRows) {
+ Integer statusKey = toInteger(countRow.get("status"));
+ long cnt = toLong(countRow.get("cnt"));
+ if (Objects.equals(statusKey, ORDER_STATUS_WAIT)) {
+ waitingCount = cnt;
+ } else if (Objects.equals(statusKey, ORDER_STATUS_RUNNING)) {
+ inProgressCount = cnt;
+ } else if (Objects.equals(statusKey, ORDER_STATUS_COMPLETED)) {
+ completedCount = cnt;
+ } else if (Objects.equals(statusKey, ORDER_STATUS_PAUSED)) {
+ pausedCount = cnt;
+ }
+ }
+ }
+
+ Map<String, Object> result = new LinkedHashMap<>();
+ result.put("tab", mapOrderTab(queryStatus));
+ result.put("status", mapOrderStatus(queryStatus));
+ result.put("bizDate", queryDate == null ? null : queryDate.format(DATE_FORMATTER));
+ result.put("total", toLong(productionOrderMapper.countHomeOrderProgress(queryStatus, startTime, endTime)));
+ result.put("pageNum", safePageNum);
+ result.put("pageSize", safePageSize);
+ result.put("waitingCount", waitingCount);
+ result.put("inProgressCount", inProgressCount);
+ result.put("completedCount", completedCount);
+ result.put("pausedCount", pausedCount);
+ result.put("records", records);
+ return R.ok(result);
+ }
+
+ @GetMapping("/todayProductionPlan")
+ @Operation(summary = "Today Production Plan")
+ public R todayProductionPlan(@RequestParam(defaultValue = "4") Long limit,
+ @RequestParam(required = false) String planDate) {
+ LocalDate queryDate = parseDateOrNull(planDate);
+ if (!isBlank(planDate) && queryDate == null) {
+ return R.fail("planDate鏍煎紡閿欒锛岃浣跨敤yyyy-MM-dd");
+ }
+
+ long safeLimit = limit == null || limit < 1 ? 4 : Math.min(limit, 20);
+ LocalDateTime planStart = queryDate == null ? null : queryDate.atStartOfDay();
+ LocalDateTime planEnd = queryDate == null ? null : queryDate.plusDays(1).atStartOfDay();
+ List<Map<String, Object>> records = new ArrayList<>();
+ List<Map<String, Object>> rawRows = productionOrderMapper.selectHomeTodayProductionPlan(safeLimit, planStart, planEnd);
+ if (rawRows != null) {
+ for (Map<String, Object> rawRow : rawRows) {
+ Map<String, Object> row = new LinkedHashMap<>();
+ Integer rowStatus = toInteger(rawRow.get("status"));
+ row.put("orderNo", rawRow.get("orderNo"));
+ row.put("productName", rawRow.get("productName"));
+ row.put("plannedQuantity", scale(toBigDecimal(rawRow.get("plannedQuantity"))));
+ row.put("dueDate", rawRow.get("dueDate"));
+ row.put("status", rowStatus);
+ row.put("statusLabel", mapOrderStatusLabel(rowStatus));
+ records.add(row);
+ }
+ }
+
+ Map<String, Object> result = new LinkedHashMap<>();
+ result.put("planDate", queryDate == null ? null : queryDate.format(DATE_FORMATTER));
+ result.put("total", toLong(productionOrderMapper.countHomeTodayProductionPlan(planStart, planEnd)));
+ result.put("records", records);
+ return R.ok(result);
+ }
+
@GetMapping("/rawMaterialDetection")
@Operation(summary = "鍘熸潗鏂欐娴�")
- public AjaxResult rawMaterialDetection(@DefaultType Integer type){
- return AjaxResult.success(homeService.rawMaterialDetection(type));
+ public R rawMaterialDetection(@DefaultType Integer type){
+ return R.ok(homeService.rawMaterialDetection(type));
}
@GetMapping("/processDetection")
@Operation(summary = "杩囩▼妫�娴�")
- public AjaxResult processDetection(@DefaultType Integer type){
- return AjaxResult.success(homeService.processDetection(type));
+ public R processDetection(@DefaultType Integer type){
+ return R.ok(homeService.processDetection(type));
}
@GetMapping("/factoryDetection")
@Operation(summary = "鎴愬搧鍑哄巶妫�娴�")
- public AjaxResult factoryDetection(@DefaultType Integer type){
- return AjaxResult.success(homeService.factoryDetection(type));
+ public R factoryDetection(@DefaultType Integer type){
+ return R.ok(homeService.factoryDetection(type));
}
@GetMapping("/qualityInspectionCount")
@Operation(summary = "璐ㄩ噺妫�楠屾暟閲�")
- public AjaxResult qualityInspectionCount(){
+ public R qualityInspectionCount(){
QualityInspectionCountDto qualityInspectionCountDto = homeService.qualityInspectionCount();
- return AjaxResult.success(qualityInspectionCountDto);
+ return R.ok(qualityInspectionCountDto);
}
@GetMapping("/nonComplianceWarning")
@Operation(summary = "涓嶅悎鏍奸璀�")
- public AjaxResult nonComplianceWarning(){
+ public R nonComplianceWarning(){
NonComplianceWarningDto nonComplianceWarningDto = homeService.nonComplianceWarning();
- return AjaxResult.success(nonComplianceWarningDto);
+ return R.ok(nonComplianceWarningDto);
}
@GetMapping("/completedInspectionCount")
@Operation(summary = "瀹屾垚妫�楠屾暟")
- public AjaxResult completedInspectionCount(){
+ public R completedInspectionCount(){
List<CompletedInspectionCountDto> list = homeService.completedInspectionCount();
- return AjaxResult.success(list);
+ return R.ok(list);
}
@GetMapping("/unqualifiedProductRanking")
@Operation(summary = "涓嶅悎鏍间骇鍝佹帓鍚�")
- public AjaxResult unqualifiedProductRanking(){
+ public R unqualifiedProductRanking(){
List<UnqualifiedProductRankDto> list = homeService.unqualifiedProductRanking();
- return AjaxResult.success(list);
+ return R.ok(list);
}
@GetMapping("/unqualifiedProductProcessingAnalysis")
@Operation(summary = "涓嶅悎鏍兼鍝佸鐞嗗垎鏋�")
- public AjaxResult unqualifiedProductProcessingAnalysis(){
+ public R unqualifiedProductProcessingAnalysis(){
List<MapDto> list = homeService.unqualifiedProductProcessingAnalysis();
- return AjaxResult.success(list);
+ return R.ok(list);
}
@GetMapping("/qualityStatistics")
@Log(title = "璐ㄩ噺鍒嗘瀽", businessType = BusinessType.OTHER)
@Operation(summary = "璐ㄩ噺鍒嗘瀽")
- public AjaxResult qualityStatistics(QualityStatisticsDto req) {
+ public R qualityStatistics() {
QualityStatisticsDto qualityStatisticsDto = homeService.qualityStatistics();
- return AjaxResult.success(qualityStatisticsDto);
+ return R.ok(qualityStatisticsDto);
}
@GetMapping("/qualityInspectionStatistics")
@Operation(summary = "璐ㄩ噺缁熻")
- public AjaxResult qualityInspectionStatistics(@DefaultType Integer type) {
+ public R qualityInspectionStatistics(@DefaultType Integer type) {
QualityStatisticsDto dto = homeService.qualityInspectionStatistics(type);
- return AjaxResult.success(dto);
+ return R.ok(dto);
}
/********************************************************璐㈠姟绫�*****************************************************/
@GetMapping("/incomeExpenseAnalysis")
@Operation(summary = "鏀敹瀵规瘮鍒嗘瀽")
- public AjaxResult incomeExpenseAnalysis(@DefaultType Integer type) {
+ public R incomeExpenseAnalysis(@DefaultType Integer type) {
List<Map<String, Object>> result = homeService.incomeExpenseAnalysis(type);
- return AjaxResult.success(result);
+ return R.ok(result);
}
@GetMapping("/profitTrendAnalysis")
@Operation(summary = "鍒╂鼎瓒嬪娍鍒嗘瀽")
- public AjaxResult profitTrendAnalysis(){
+ public R profitTrendAnalysis(){
List<MapDto> list = homeService.profitTrendAnalysis();
- return AjaxResult.success(list);
+ return R.ok(list);
}
@GetMapping("/expenseCompositionAnalysis")
@Operation(summary = "鏋勬垚鍒嗘瀽")
- public AjaxResult expenseCompositionAnalysis(@DefaultType Integer type) {
+ public R expenseCompositionAnalysis(@DefaultType Integer type) {
List<MapDto> list = homeService.expenseCompositionAnalysis(type);
- return AjaxResult.success(list);
+ return R.ok(list);
}
@GetMapping("/monthlyIncome")
@Operation(summary = "鏈堝害鏀跺叆")
- public AjaxResult monthlyIncome(){
+ public R monthlyIncome(){
MonthlyIncomeDto dto = homeService.monthlyIncome();
- return AjaxResult.success(dto);
+ return R.ok(dto);
}
@GetMapping("/monthlyExpenditure")
@Operation(summary = "鏈堝害鏀嚭")
- public AjaxResult monthlyExpenditure(){
+ public R monthlyExpenditure(){
MonthlyExpenditureDto dto = homeService.monthlyExpenditure();
- return AjaxResult.success(dto);
+ return R.ok(dto);
}
@GetMapping("/statisticsReceivablePayable")
@Log(title = "搴旀敹搴斾粯缁熻", businessType = BusinessType.OTHER)
@Operation(summary = "搴旀敹搴斾粯缁熻")
- public AjaxResult statisticsReceivablePayable(StatisticsReceivablePayableDto req, @DefaultType Integer type ) {
+ public R statisticsReceivablePayable(@DefaultType Integer type ) {
StatisticsReceivablePayableDto statisticsReceivablePayable = homeService.statisticsReceivablePayable(type);
- return AjaxResult.success(statisticsReceivablePayable);
+ return R.ok(statisticsReceivablePayable);
}
/********************************************************浠撳偍绫�*****************************************************/
@GetMapping("/productCategoryDistribution")
@Operation(summary = "浜у搧澶х被鍒嗗竷")
- public AjaxResult productCategoryDistribution() {
+ public R productCategoryDistribution() {
ProductCategoryDistributionDto dto = homeService.productCategoryDistribution();
- return AjaxResult.success(dto);
+ return R.ok(dto);
}
@GetMapping("/salesPurchaseStorageProductCount")
@Operation(summary = "閿�鍞�-閲囪喘-鍌ㄥ瓨浜у搧鏁�")
- public AjaxResult salesPurchaseStorageProductCount(){
+ public R salesPurchaseStorageProductCount(){
List<MapDto> list = homeService.salesPurchaseStorageProductCount();
- return AjaxResult.success(list);
+ return R.ok(list);
}
@GetMapping("/productInOutAnalysis")
@Operation(summary = "浜у搧鍑哄叆搴撳垎鏋�")
- public AjaxResult productInOutAnalysis(@DefaultType Integer type){
+ public R productInOutAnalysis(@DefaultType Integer type){
List<Map<String, Object>> result = homeService.productInOutAnalysis(type);
- return AjaxResult.success(result);
+ return R.ok(result);
}
@GetMapping("/productTurnoverDays")
@Operation(summary = "浜у搧鍛ㄨ浆澶╂暟")
- public AjaxResult productTurnoverDays(){
+ public R productTurnoverDays(){
List<MapDto> list = homeService.productTurnoverDays();
- return AjaxResult.success(list);
+ return R.ok(list);
+ }
+
+ private Map<String, Object> buildOrderProgressRow(Map<String, Object> rawRow) {
+ Map<String, Object> row = new LinkedHashMap<>();
+ Integer rowStatus = toInteger(rawRow.get("status"));
+ row.put("orderNo", rawRow.get("orderNo"));
+ row.put("productName", rawRow.get("productName"));
+ row.put("plannedQuantity", scale(toBigDecimal(rawRow.get("plannedQuantity"))));
+ row.put("completedQuantity", scale(toBigDecimal(rawRow.get("completedQuantity"))));
+ row.put("completionRate", scale(toBigDecimal(rawRow.get("completionRate"))));
+ row.put("dueDate", rawRow.get("dueDate"));
+ row.put("status", rowStatus);
+ row.put("statusLabel", mapOrderStatusLabel(rowStatus));
+ return row;
+ }
+
+ private Integer resolveOrderStatus(String status, String tab) {
+ if (!isBlank(status)) {
+ return parseOrderStatus(status);
+ }
+ return parseOrderStatus(tab);
+ }
+
+ private Integer parseOrderStatus(String rawStatus) {
+ if (isBlank(rawStatus)) {
+ return null;
+ }
+ String normalized = rawStatus.trim().toLowerCase();
+ if ("all".equals(normalized)) {
+ return null;
+ }
+ if ("1".equals(normalized) || "waiting".equals(normalized) || "wait".equals(normalized)) {
+ return ORDER_STATUS_WAIT;
+ }
+ if ("2".equals(normalized) || "inprogress".equals(normalized) || "running".equals(normalized)) {
+ return ORDER_STATUS_RUNNING;
+ }
+ if ("3".equals(normalized) || "completed".equals(normalized)) {
+ return ORDER_STATUS_COMPLETED;
+ }
+ if ("4".equals(normalized) || "paused".equals(normalized)) {
+ return ORDER_STATUS_PAUSED;
+ }
+ return null;
+ }
+
+ private String mapOrderTab(Integer status) {
+ if (Objects.equals(status, ORDER_STATUS_RUNNING)) {
+ return "inProgress";
+ }
+ if (Objects.equals(status, ORDER_STATUS_COMPLETED)) {
+ return "completed";
+ }
+ if (Objects.equals(status, ORDER_STATUS_PAUSED)) {
+ return "paused";
+ }
+ if (Objects.equals(status, ORDER_STATUS_WAIT)) {
+ return "waiting";
+ }
+ return "all";
+ }
+
+ private String mapOrderStatus(Integer status) {
+ if (Objects.equals(status, ORDER_STATUS_WAIT)) {
+ return "waiting";
+ }
+ if (Objects.equals(status, ORDER_STATUS_RUNNING)) {
+ return "inProgress";
+ }
+ if (Objects.equals(status, ORDER_STATUS_COMPLETED)) {
+ return "completed";
+ }
+ if (Objects.equals(status, ORDER_STATUS_PAUSED)) {
+ return "paused";
+ }
+ return "all";
+ }
+
+ private String mapOrderStatusLabel(Integer status) {
+ if (Objects.equals(status, ORDER_STATUS_WAIT)) {
+ return "寰呭紑濮�";
+ }
+ if (Objects.equals(status, ORDER_STATUS_RUNNING)) {
+ return "杩涜涓�";
+ }
+ if (Objects.equals(status, ORDER_STATUS_COMPLETED)) {
+ return "宸插畬鎴�";
+ }
+ if (Objects.equals(status, ORDER_STATUS_PAUSED)) {
+ return "宸叉殏鍋�";
+ }
+ return "鏈煡";
+ }
+
+ private Map<String, BigDecimal> loadOutputStats(LocalDate startDate, LocalDate endDateExclusive) {
+ String start = startDate.atStartOfDay().format(DATE_TIME_FORMATTER);
+ String end = endDateExclusive.atStartOfDay().format(DATE_TIME_FORMATTER);
+
+ BigDecimal quantity = BigDecimal.ZERO;
+ BigDecimal scrapQty = BigDecimal.ZERO;
+ List<Map<String, Object>> rows = productionProductOutputMapper.selectDailyOutputStats(start, end);
+ if (rows != null) {
+ for (Map<String, Object> row : rows) {
+ quantity = quantity.add(toBigDecimal(row.get("quantity")));
+ scrapQty = scrapQty.add(toBigDecimal(row.get("scrapQty")));
+ }
+ }
+
+ Map<String, BigDecimal> stats = new LinkedHashMap<>();
+ stats.put("quantity", quantity);
+ stats.put("scrapQty", scrapQty);
+ return stats;
+ }
+
+ private BigDecimal calcDeviceOee(LocalDate day) {
+ long totalDeviceCount = deviceLedgerMapper.selectCount(new LambdaQueryWrapper<>());
+ if (totalDeviceCount <= 0) {
+ return BigDecimal.ZERO;
+ }
+
+ Date start = Date.from(day.atStartOfDay(ZoneId.systemDefault()).toInstant());
+ Date end = Date.from(day.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
+
+ List<DeviceRepair> repairList = deviceRepairMapper.selectList(new LambdaQueryWrapper<DeviceRepair>()
+ .select(DeviceRepair::getDeviceLedgerId)
+ .ge(DeviceRepair::getRepairTime, start)
+ .lt(DeviceRepair::getRepairTime, end)
+ .in(DeviceRepair::getStatus, 0, 3));
+
+ long repairingDeviceCount = repairList == null ? 0 : repairList.stream()
+ .map(DeviceRepair::getDeviceLedgerId)
+ .filter(Objects::nonNull)
+ .distinct()
+ .count();
+
+ long availableDeviceCount = Math.max(totalDeviceCount - repairingDeviceCount, 0);
+ return new BigDecimal(availableDeviceCount)
+ .multiply(new BigDecimal("100"))
+ .divide(new BigDecimal(totalDeviceCount), 2, RoundingMode.HALF_UP);
+ }
+
+ private BigDecimal calcOrderAchievementRate(LocalDate day) {
+ List<ProductionOrder> orderList = productionOrderMapper.selectList(new LambdaQueryWrapper<ProductionOrder>()
+ .select(ProductionOrder::getQuantity, ProductionOrder::getCompleteQuantity)
+ .ge(ProductionOrder::getCreateTime, day.atStartOfDay())
+ .lt(ProductionOrder::getCreateTime, day.plusDays(1).atStartOfDay())
+ .ne(ProductionOrder::getStatus, ORDER_STATUS_PAUSED));
+
+ BigDecimal totalQuantity = BigDecimal.ZERO;
+ BigDecimal totalCompleteQuantity = BigDecimal.ZERO;
+ if (orderList != null) {
+ for (ProductionOrder order : orderList) {
+ totalQuantity = totalQuantity.add(zeroIfNull(order.getQuantity()));
+ totalCompleteQuantity = totalCompleteQuantity.add(zeroIfNull(order.getCompleteQuantity()));
+ }
+ }
+ return calcRate(totalCompleteQuantity, totalQuantity);
+ }
+
+ private BigDecimal calcDefectRate(LocalDate day) {
+ Map<String, BigDecimal> stats = loadOutputStats(day, day.plusDays(1));
+ BigDecimal quantity = stats.get("quantity");
+ BigDecimal scrapQty = stats.get("scrapQty");
+ return calcRate(scrapQty, quantity.add(scrapQty));
+ }
+
+ private Map<String, Object> buildRealtimeMetric(BigDecimal value, BigDecimal change) {
+ Map<String, Object> metric = new LinkedHashMap<>();
+ metric.put("value", scale(value));
+ metric.put("compareYesterday", scale(change));
+ return metric;
+ }
+
+ private BigDecimal calcRate(BigDecimal numerator, BigDecimal denominator) {
+ if (denominator == null || denominator.compareTo(BigDecimal.ZERO) <= 0) {
+ return BigDecimal.ZERO;
+ }
+ return zeroIfNull(numerator)
+ .multiply(new BigDecimal("100"))
+ .divide(denominator, 2, RoundingMode.HALF_UP);
+ }
+
+ private BigDecimal toBigDecimal(Object value) {
+ if (value == null) {
+ return BigDecimal.ZERO;
+ }
+ if (value instanceof BigDecimal) {
+ return (BigDecimal) value;
+ }
+ if (value instanceof Number) {
+ return BigDecimal.valueOf(((Number) value).doubleValue());
+ }
+ try {
+ return new BigDecimal(String.valueOf(value));
+ } catch (Exception ex) {
+ return BigDecimal.ZERO;
+ }
+ }
+
+ private Integer toInteger(Object value) {
+ if (value == null) {
+ return null;
+ }
+ if (value instanceof Integer) {
+ return (Integer) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).intValue();
+ }
+ try {
+ return Integer.valueOf(String.valueOf(value));
+ } catch (Exception ex) {
+ return null;
+ }
+ }
+
+ private long toLong(Object value) {
+ if (value == null) {
+ return 0L;
+ }
+ if (value instanceof Long) {
+ return (Long) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).longValue();
+ }
+ try {
+ return Long.parseLong(String.valueOf(value));
+ } catch (Exception ex) {
+ return 0L;
+ }
+ }
+
+ private LocalDate parseDateOrNull(String rawDate) {
+ if (isBlank(rawDate)) {
+ return null;
+ }
+ try {
+ return LocalDate.parse(rawDate.trim(), DATE_FORMATTER);
+ } catch (DateTimeParseException ex) {
+ return null;
+ }
+ }
+
+ private boolean isBlank(String value) {
+ return value == null || value.trim().isEmpty();
+ }
+
+ private BigDecimal zeroIfNull(BigDecimal value) {
+ return value == null ? BigDecimal.ZERO : value;
+ }
+
+ private BigDecimal scale(BigDecimal value) {
+ return zeroIfNull(value).setScale(2, RoundingMode.HALF_UP);
}
}
diff --git a/src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java b/src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java
index a16390c..4f1509b 100644
--- a/src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java
+++ b/src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java
@@ -19,10 +19,10 @@
@Schema(description = "搴斾粯閲戦")
private BigDecimal payableMoney;
- @Schema(description = "棰勬敹閲戦")
+ @Schema(description = "鏀舵閲戦")
private BigDecimal advanceMoney;
- @Schema(description = "棰勪粯閲戦")
+ @Schema(description = "浠樻閲戦")
private BigDecimal prepayMoney;
}
diff --git a/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java b/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
index e01927c..d3c21a2 100644
--- a/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
+++ b/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -3,9 +3,20 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
-import com.ruoyi.account.mapper.AccountExpenseMapper;
-import com.ruoyi.account.mapper.AccountIncomeMapper;
-import com.ruoyi.account.pojo.AccountExpense;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.purchase.PurchaseInboundDto;
+import com.ruoyi.account.bean.dto.purchase.PurchaseReturnDto;
+import com.ruoyi.account.bean.dto.sales.SalesOutboundDto;
+import com.ruoyi.account.bean.dto.sales.SalesReturnDto;
+import com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo;
+import com.ruoyi.account.bean.vo.purchase.PurchaseReturnVo;
+import com.ruoyi.account.bean.vo.sales.SalesOutboundVo;
+import com.ruoyi.account.bean.vo.sales.SalesReturnVo;
+import com.ruoyi.account.mapper.AccountStatementMapper;
+import com.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper;
+import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper;
+import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
+import com.ruoyi.account.pojo.sales.AccountSalesCollection;
import com.ruoyi.approve.mapper.ApproveProcessMapper;
import com.ruoyi.approve.pojo.ApproveProcess;
import com.ruoyi.basic.mapper.CustomerMapper;
@@ -26,27 +37,27 @@
import com.ruoyi.home.dto.*;
import com.ruoyi.home.mapper.HomeMapper;
import com.ruoyi.home.service.HomeService;
+import com.ruoyi.procurementrecord.mapper.ReturnManagementMapper;
import com.ruoyi.production.bean.dto.ProductionProductOutputDto;
import com.ruoyi.production.mapper.*;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.mapper.SysDeptMapper;
-import com.ruoyi.purchase.mapper.PaymentRegistrationMapper;
import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
-import com.ruoyi.purchase.pojo.PaymentRegistration;
+import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
import com.ruoyi.purchase.pojo.PurchaseLedger;
import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.quality.mapper.QualityUnqualifiedMapper;
import com.ruoyi.quality.pojo.QualityInspect;
import com.ruoyi.quality.pojo.QualityUnqualified;
-import com.ruoyi.sales.mapper.ReceiptPaymentMapper;
import com.ruoyi.sales.mapper.SalesLedgerMapper;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
-import com.ruoyi.sales.pojo.ReceiptPayment;
import com.ruoyi.sales.pojo.SalesLedger;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.staff.mapper.StaffOnJobMapper;
import com.ruoyi.staff.pojo.StaffOnJob;
+import com.ruoyi.stock.mapper.StockInRecordMapper;
import com.ruoyi.stock.mapper.StockInventoryMapper;
+import com.ruoyi.stock.mapper.StockOutRecordMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -72,6 +83,10 @@
public class HomeServiceImpl implements HomeService {
private final SalesLedgerMapper salesLedgerMapper;
+ private final StockOutRecordMapper stockOutRecordMapper;
+ private final ReturnManagementMapper returnManagementMapper;
+ private final StockInRecordMapper stockInRecordMapper;
+ private final PurchaseReturnOrdersMapper purchaseReturnOrdersMapper;
private final PurchaseLedgerMapper purchaseLedgerMapper;
@@ -82,10 +97,6 @@
private final QualityInspectMapper qualityStatisticsMapper;
private final ApproveProcessMapper approveProcessMapper;
-
- private final ReceiptPaymentMapper receiptPaymentMapper;
-
- private final PaymentRegistrationMapper paymentRegistrationMapper;
private final SysDeptMapper sysDeptMapper;
@@ -111,9 +122,9 @@
private final ProductionOperationTaskMapper productionOperationTaskMapper;
- private final AccountExpenseMapper accountExpenseMapper;
-
- private final AccountIncomeMapper accountIncomeMapper;
+ private final AccountPurchasePaymentMapper accountPurchasePaymentMapper;
+ private final AccountSalesCollectionMapper accountSalesCollectionMapper;
+ private final AccountStatementMapper accountStatementMapper;
private final ProductionAccountMapper productionAccountMapper;
@@ -141,12 +152,8 @@
salesLedgers.stream().map(SalesLedger::getId).collect(Collectors.toList()));
List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper
.selectList(salesLedgerProductMapperLambdaQueryWrapper);
- // 鏈紑绁ㄩ噾棰�
- BigDecimal noInvoiceAmountTotal = salesLedgerProducts.stream().map(SalesLedgerProduct::getNoInvoiceAmount)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
homeBusinessDto.setMonthSaleMoney(contractAmount.setScale(2, RoundingMode.HALF_UP).toString());
- homeBusinessDto.setMonthSaleHaveMoney(noInvoiceAmountTotal.setScale(2, RoundingMode.HALF_UP).toString());
+ homeBusinessDto.setMonthSaleHaveMoney(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP).toString());
}
// 鍒涘缓LambdaQueryWrapper
LambdaQueryWrapper<PurchaseLedger> queryWrapper = new LambdaQueryWrapper<>();
@@ -169,14 +176,8 @@
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
- // 寰呬粯娆炬�婚噾棰�
- BigDecimal unReceiptPaymentAmount = salesLedgerProductsCopy.stream()
- .map(SalesLedgerProduct::getPendingTicketsTotal)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
-
homeBusinessDto.setMonthPurchaseMoney(receiveAmount.setScale(2, RoundingMode.HALF_UP).toString());
- homeBusinessDto.setMonthPurchaseHaveMoney(unReceiptPaymentAmount.setScale(2, RoundingMode.HALF_UP).toString());
+ homeBusinessDto.setMonthPurchaseHaveMoney(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP).toString());
}
// 缁熻搴撳瓨
BigDecimal stockQuantityTotal = stockInventoryMapper.selectTotal();
@@ -312,19 +313,35 @@
queryWrapper.ge(QualityInspect::getCheckTime, monthStart.toString())
.le(QualityInspect::getCheckTime, monthEnd.toString());
List<QualityInspect> monthInspects = qualityStatisticsMapper.selectList(queryWrapper);
+
+ // 缁熻鎬绘暟閲忥紙鍚堟牸鏁伴噺 + 涓嶅悎鏍兼暟閲忥級
BigDecimal reduce = monthInspects.stream()
.filter(inspect -> inspect.getInspectType().equals(0))
- .map(QualityInspect::getQuantity)
+ .map(inspect -> {
+ BigDecimal qualified = inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO;
+ BigDecimal unqualified = inspect.getUnqualifiedQuantity() != null ? inspect.getUnqualifiedQuantity() : BigDecimal.ZERO;
+ return qualified.add(unqualified);
+ })
.reduce(BigDecimal.ZERO, BigDecimal::add);
supplierNum = supplierNum.add(reduce);
+
BigDecimal reduce1 = monthInspects.stream()
.filter(inspect -> inspect.getInspectType().equals(1))
- .map(QualityInspect::getQuantity)
+ .map(inspect -> {
+ BigDecimal qualified = inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO;
+ BigDecimal unqualified = inspect.getUnqualifiedQuantity() != null ? inspect.getUnqualifiedQuantity() : BigDecimal.ZERO;
+ return qualified.add(unqualified);
+ })
.reduce(BigDecimal.ZERO, BigDecimal::add);
processNum = processNum.add(reduce1);
+
BigDecimal reduce2 = monthInspects.stream()
.filter(inspect -> inspect.getInspectType().equals(2))
- .map(QualityInspect::getQuantity)
+ .map(inspect -> {
+ BigDecimal qualified = inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO;
+ BigDecimal unqualified = inspect.getUnqualifiedQuantity() != null ? inspect.getUnqualifiedQuantity() : BigDecimal.ZERO;
+ return qualified.add(unqualified);
+ })
.reduce(BigDecimal.ZERO, BigDecimal::add);
factoryNum = factoryNum.add(reduce2);
@@ -334,25 +351,22 @@
// 1. 渚涘簲鍟嗘楠岋紙绫诲瀷0锛�- 鍚堟牸鏁伴噺
BigDecimal supplierQualified = monthInspects.stream()
- .filter(inspect -> inspect.getInspectType().equals(0)
- && "鍚堟牸".equals(inspect.getCheckResult()))
- .map(QualityInspect::getQuantity)
+ .filter(inspect -> inspect.getInspectType().equals(0))
+ .map(inspect -> inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO)
.reduce(BigDecimal.ZERO, BigDecimal::add);
item.setSupplierNum(supplierQualified);
// 2. 宸ュ簭妫�楠岋紙绫诲瀷1锛�- 鍚堟牸鏁伴噺
BigDecimal processQualified = monthInspects.stream()
- .filter(inspect -> inspect.getInspectType().equals(1)
- && "鍚堟牸".equals(inspect.getCheckResult()))
- .map(QualityInspect::getQuantity)
+ .filter(inspect -> inspect.getInspectType().equals(1))
+ .map(inspect -> inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO)
.reduce(BigDecimal.ZERO, BigDecimal::add);
item.setProcessNum(processQualified);
// 3. 宸ュ巶妫�楠岋紙绫诲瀷2锛�- 鍚堟牸鏁伴噺
BigDecimal factoryQualified = monthInspects.stream()
- .filter(inspect -> inspect.getInspectType().equals(2)
- && "鍚堟牸".equals(inspect.getCheckResult()))
- .map(QualityInspect::getQuantity)
+ .filter(inspect -> inspect.getInspectType().equals(2))
+ .map(inspect -> inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO)
.reduce(BigDecimal.ZERO, BigDecimal::add);
item.setFactoryNum(factoryQualified);
@@ -414,76 +428,33 @@
*/
@Override
public StatisticsReceivablePayableDto statisticsReceivablePayable(Integer type) {
- LocalDate today = LocalDate.now();
- LocalDate startDate = null;
- LocalDate endDate = null;
- switch (type) {
- case 1:
- // 鑾峰彇鏈懆鍛ㄤ竴
- startDate = today.with(DayOfWeek.MONDAY);
- // 鑾峰彇鏈懆鍛ㄦ棩
- endDate = today.with(DayOfWeek.SUNDAY);
- break;
- case 2:
- startDate = today.with(TemporalAdjusters.firstDayOfMonth());
- endDate = today.with(TemporalAdjusters.lastDayOfMonth());
- break;
- case 3:
- Month currentMonth = today.getMonth();
- Month firstMonthOfQuarter = currentMonth.firstMonthOfQuarter();
- Month lastMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2);
+ StatisticsReceivablePayableDto dto = new StatisticsReceivablePayableDto();
+ LocalDate[] range = resolveFinanceRange(type);
+ LocalDate startDate = range[0];
+ LocalDate endDate = range[1];
- startDate = today.withMonth(firstMonthOfQuarter.getValue())
- .with(TemporalAdjusters.firstDayOfMonth());
- endDate = today.withMonth(lastMonthOfQuarter.getValue())
- .with(TemporalAdjusters.lastDayOfMonth());
- break;
- }
- // 搴旀敹
- List<SalesLedger> salesLedgers = salesLedgerMapper.selectList(new LambdaQueryWrapper<SalesLedger>()
- // .ge(SalesLedger::getEntryDate, startDate)
- // .lt(SalesLedger::getEntryDate, endDate)
- );
- // BigDecimal receivableMoney =
- // salesLedgers.stream().map(SalesLedger::getContractAmount).reduce(BigDecimal.ZERO,
- // BigDecimal::add);
- BigDecimal receivableMoney = sumAmount(salesLedgers, SalesLedger::getContractAmount);
- // 搴斾粯
- List<PurchaseLedger> procurementRecords = purchaseLedgerMapper
- .selectList(new LambdaQueryWrapper<PurchaseLedger>()
- // .ge(PurchaseLedger::getEntryDate, startDate)
- // .lt(PurchaseLedger::getEntryDate, endDate)
- );
- // BigDecimal payableMoney =
- // procurementRecords.stream().map(PurchaseLedger::getContractAmount).reduce(BigDecimal.ZERO,
- // BigDecimal::add);
- BigDecimal payableMoney = sumAmount(procurementRecords, PurchaseLedger::getContractAmount);
- // 棰勬敹
- List<ReceiptPayment> receiptPayments = receiptPaymentMapper.selectList(new LambdaQueryWrapper<ReceiptPayment>()
- // .ge(ReceiptPayment::getReceiptPaymentDate, startDate)
- // .lt(ReceiptPayment::getReceiptPaymentDate, endDate)
- );
- // BigDecimal advanceMoney =
- // receiptPayments.stream().map(ReceiptPayment::getReceiptPaymentAmount).reduce(BigDecimal.ZERO,
- // BigDecimal::add);
- BigDecimal advanceMoney = sumAmount(receiptPayments, ReceiptPayment::getReceiptPaymentAmount);
- // 棰勪粯
- List<PaymentRegistration> paymentRegistrations = paymentRegistrationMapper
- .selectList(new LambdaQueryWrapper<PaymentRegistration>()
- // .ge(PaymentRegistration::getPaymentDate, startDate)
- // .lt(PaymentRegistration::getPaymentDate, endDate)
- );
- // BigDecimal prepayMoney =
- // paymentRegistrations.stream().map(PaymentRegistration::getCurrentPaymentAmount).reduce(BigDecimal.ZERO,
- // BigDecimal::add);
- BigDecimal prepayMoney = sumAmount(paymentRegistrations, PaymentRegistration::getCurrentPaymentAmount);
- StatisticsReceivablePayableDto statisticsReceivablePayableDto = new StatisticsReceivablePayableDto();
- statisticsReceivablePayableDto.setPayableMoney(payableMoney.subtract(prepayMoney));
- statisticsReceivablePayableDto.setReceivableMoney(receivableMoney.subtract(advanceMoney));
- statisticsReceivablePayableDto.setAdvanceMoney(advanceMoney);
- statisticsReceivablePayableDto.setPrepayMoney(prepayMoney);
+ //閿�鍞嚭搴�
+ BigDecimal receivableBase = sumSalesContractAmount(startDate, endDate);
+ //閿�鍞��璐�
+ BigDecimal salesReturnAmount = sumSalesReturnAmount(startDate, endDate);
+ //閲囪喘鍏ュ簱
+ BigDecimal payableBase = sumPurchaseContractAmount(startDate, endDate);
+ //閲囪喘閫�璐�
+ BigDecimal purchaseReturnAmount = sumPurchaseReturnAmount(startDate, endDate);
+ //鏀舵
+ BigDecimal advanceMoney = sumCollectionAmount(startDate, endDate);
+ //浠樻
+ BigDecimal prepayMoney = sumPaymentAmount(startDate, endDate);
- return statisticsReceivablePayableDto;
+ //搴旀敹閲戦=閿�鍞嚭搴�-閿�鍞��璐�
+ dto.setReceivableMoney(scaleMoney(maxZero(receivableBase.subtract(salesReturnAmount))));
+ //搴斾粯閲戦=閲囪喘鍏ュ簱-閲囪喘閫�璐�
+ dto.setPayableMoney(scaleMoney(maxZero(payableBase.subtract(purchaseReturnAmount))));
+ //鏀舵閲戦=鏀舵鍗�
+ dto.setAdvanceMoney(scaleMoney(advanceMoney));
+ //浠樻閲戦=浠樻鍗�
+ dto.setPrepayMoney(scaleMoney(prepayMoney));
+ return dto;
}
public static <T> BigDecimal sumAmount(List<T> list, java.util.function.Function<T, BigDecimal> amountExtractor) {
@@ -1164,13 +1135,9 @@
String endStr = endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
// 2. 鏌ヨ鏁版嵁
- List<IncomeExpenseAnalysisDto> incomeList = accountIncomeMapper.selectIncomeStats(startStr, endStr, dateFormat);
+ List<IncomeExpenseAnalysisDto> incomeList = accountSalesCollectionMapper.selectIncomeStats(startStr, endStr, dateFormat);
+ List<IncomeExpenseAnalysisDto> expenseList = accountPurchasePaymentMapper.selectPayment(startStr, endStr, dateFormat);
- // List<IncomeExpenseAnalysisDto> purchaseList =
- // purchaseLedgerMapper.selectPurchaseStats(startStr, endStr, dateFormat);
-
- List<IncomeExpenseAnalysisDto> expenseList = accountExpenseMapper.selectAccountExpenseStats(startStr, endStr,
- dateFormat);
// 3. 杞� Map锛堣嚜鍔ㄥ悎骞讹級
Map<String, BigDecimal> incomeMap = incomeList.stream()
@@ -1179,11 +1146,7 @@
IncomeExpenseAnalysisDto::getAmount,
BigDecimal::add));
- // Map<String, BigDecimal> purchaseMap = purchaseList.stream()
- // .collect(Collectors.toMap(
- // IncomeExpenseAnalysisDto::getDateStr,
- // IncomeExpenseAnalysisDto::getAmount,
- // BigDecimal::add));
+
Map<String, BigDecimal> expenseMap = expenseList.stream()
.collect(Collectors.toMap(
@@ -1197,18 +1160,12 @@
for (String dateStr : xAxis) {
Map<String, Object> item = new HashMap<>();
item.put("date", dateStr);
-
// 鏀跺叆
BigDecimal income = incomeMap.getOrDefault(dateStr, BigDecimal.ZERO);
item.put("income", income.setScale(2, RoundingMode.HALF_UP));
-
- // 鏀嚭 = 閲囪喘 + 璐㈠姟鏀嚭
- // BigDecimal purchase = purchaseMap.getOrDefault(dateStr, BigDecimal.ZERO);
+ // 鏀嚭
BigDecimal expense = expenseMap.getOrDefault(dateStr, BigDecimal.ZERO);
- // BigDecimal totalExpense = purchase.add(expense);
- BigDecimal totalExpense = expense;
-
- item.put("expense", totalExpense.setScale(2, RoundingMode.HALF_UP));
+ item.put("expense", expense.setScale(2, RoundingMode.HALF_UP));
result.add(item);
}
@@ -1235,8 +1192,8 @@
String startStr = startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
String endStr = endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
- List<IncomeExpenseAnalysisDto> incomeList = accountIncomeMapper.selectIncomeStats(startStr, endStr, dateFormat);
- List<IncomeExpenseAnalysisDto> expenseList = accountExpenseMapper.selectAccountExpenseStats(startStr, endStr, dateFormat);
+ List<IncomeExpenseAnalysisDto> incomeList = accountSalesCollectionMapper.selectIncomeStats(startStr, endStr, dateFormat);
+ List<IncomeExpenseAnalysisDto> expenseList = accountPurchasePaymentMapper.selectPayment(startStr, endStr, dateFormat);
Map<String, BigDecimal> incomeMap = incomeList.stream().collect(Collectors
.toMap(IncomeExpenseAnalysisDto::getDateStr, IncomeExpenseAnalysisDto::getAmount, BigDecimal::add));
@@ -1272,11 +1229,6 @@
rawMaterialDto.setName("鍘熸潗鏂�");
rawMaterialDto.setValue(rawMaterialAmount != null ? rawMaterialAmount.toString() : "0");
result.add(rawMaterialDto);
-
- List<MapDto> expenseList = accountExpenseMapper.selectExpenseComposition(null, null);
- if (expenseList != null) {
- result.addAll(expenseList);
- }
}
BigDecimal total = BigDecimal.ZERO;
@@ -1311,161 +1263,55 @@
@Override
public MonthlyIncomeDto monthlyIncome() {
MonthlyIncomeDto dto = new MonthlyIncomeDto();
- LocalDate now = LocalDate.now();
- YearMonth currentMonth = YearMonth.from(now);
- LocalDateTime startOfMonth = currentMonth.atDay(1).atStartOfDay();
- LocalDateTime endOfMonth = currentMonth.atEndOfMonth().atTime(23, 59, 59);
-
- LambdaQueryWrapper<SalesLedgerProduct> wrapper = new LambdaQueryWrapper<>();
- wrapper.eq(SalesLedgerProduct::getType, 1);
- wrapper.ge(SalesLedgerProduct::getRegisterDate, startOfMonth);
- wrapper.le(SalesLedgerProduct::getRegisterDate, endOfMonth);
-
- List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(wrapper);
-
- if (CollectionUtils.isEmpty(products)) {
- return dto;
- }
-
- BigDecimal collected = products.stream()
- .map(SalesLedgerProduct::getInvoiceTotal)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- dto.setMonthlyIncome(collected);
-
- BigDecimal overdue = products.stream()
- .map(SalesLedgerProduct::getPendingInvoiceTotal)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- dto.setOverdueNum(overdue);
-
- BigDecimal total = collected.add(overdue);
-
- if (total.compareTo(BigDecimal.ZERO) > 0) {
- String collectionRate = collected.divide(total, 4, RoundingMode.HALF_UP)
- .multiply(new BigDecimal("100"))
- .setScale(2, RoundingMode.HALF_UP)
- .toString();
- dto.setCollectionRate(collectionRate);
-
- String overdueRate = overdue.divide(total, 4, RoundingMode.HALF_UP)
- .multiply(new BigDecimal("100"))
- .setScale(2, RoundingMode.HALF_UP)
- .toString();
- dto.setOverdueRate(overdueRate);
- }
-
+ LocalDate today = LocalDate.now();
+ YearMonth currentMonth = YearMonth.from(today);
+ LocalDate startDate = currentMonth.atDay(1);
+ LocalDate endDate = currentMonth.atEndOfMonth();
+ //鏀舵
+ BigDecimal monthlyIncome = sumCollectionAmount(startDate, endDate);
+ //閿�鍞嚭搴�
+ BigDecimal receivableBase = sumSalesContractAmount(startDate, endDate);
+ //閿�鍞��璐�
+ BigDecimal salesReturnAmount = sumSalesReturnAmount(startDate, endDate);
+ //鍥炴鐜�=鏀舵/(閿�鍞嚭搴�-閿�鍞��璐�)搴旀敹
+ String collectionRate = toRateString(monthlyIncome, receivableBase.subtract(salesReturnAmount));
+ //閫炬湡鏁�=(閿�鍞嚭搴撻噾棰�-閿�鍞��璐ч噾棰�)搴旀敹閲戦-鏀舵閲戦
+ BigDecimal overdueAmount = receivableBase.subtract(salesReturnAmount).subtract(monthlyIncome);
+ //閫炬湡鐜�=閫炬湡鏁�/搴旀敹閲戦
+ String overdueRate = toRateString(overdueAmount, receivableBase);
+ dto.setMonthlyIncome(scaleMoney(monthlyIncome));
+ dto.setCollectionRate(collectionRate);
+ dto.setOverdueNum(overdueAmount);
+ dto.setOverdueRate(overdueRate);
return dto;
}
+ @Override
public MonthlyExpenditureDto monthlyExpenditure() {
-
MonthlyExpenditureDto dto = new MonthlyExpenditureDto();
+ LocalDate today = LocalDate.now();
+ YearMonth currentMonth = YearMonth.from(today);
+ LocalDate startDate = currentMonth.atDay(1);
+ LocalDate endDate = currentMonth.atEndOfMonth();
+ //鏀嚭
+ BigDecimal monthlyExpenditure = sumPaymentAmount(startDate, endDate);
+ //閲囪喘鍏ュ簱
+ BigDecimal payableBase = sumPurchaseContractAmount(startDate, endDate);
+ //閲囪喘閫�璐�
+ BigDecimal purchaseReturnAmount = sumPurchaseReturnAmount(startDate, endDate);
+ //浠樻鐜�=浠樻/(閲囪喘鍏ュ簱-閲囪喘閫�璐�)搴斾粯
+ String paymentRate = toRateString(monthlyExpenditure, payableBase.subtract(purchaseReturnAmount));
+ //鏀舵
+ BigDecimal monthlyIncome = sumCollectionAmount(startDate, endDate);
+ //姣涘埄娑�= 鏀舵-鏀嚭
+ BigDecimal grossProfit = monthlyIncome.subtract(monthlyExpenditure);
+ //鍒╂鼎鐜�=姣涘埄娑�/鏀舵
+ String profitMarginRate = toRateString(grossProfit, monthlyIncome);
- // 褰撴湀鏃堕棿鑼冨洿
- LocalDate now = LocalDate.now();
- YearMonth currentMonth = YearMonth.from(now);
- LocalDateTime startOfMonth = currentMonth.atDay(1).atStartOfDay();
- LocalDateTime endOfMonth = currentMonth.atEndOfMonth().atTime(23, 59, 59);
-
- // 閲囪喘鍙拌处锛坱ype = 2锛�
- LambdaQueryWrapper<SalesLedgerProduct> purchaseWrapper = new LambdaQueryWrapper<>();
- purchaseWrapper.eq(SalesLedgerProduct::getType, 2);
- purchaseWrapper.ge(SalesLedgerProduct::getRegisterDate, startOfMonth);
- purchaseWrapper.le(SalesLedgerProduct::getRegisterDate, endOfMonth);
-
- List<SalesLedgerProduct> purchaseProducts = salesLedgerProductMapper.selectList(purchaseWrapper);
-
- BigDecimal rawMaterialCost = BigDecimal.ZERO; // 鍘熸潗鏂欐垚鏈�
- BigDecimal paidAmount = BigDecimal.ZERO; // 宸蹭粯娆鹃噾棰�
- BigDecimal pendingAmount = BigDecimal.ZERO; // 寰呬粯娆鹃噾棰�
-
- if (!CollectionUtils.isEmpty(purchaseProducts)) {
- for (SalesLedgerProduct p : purchaseProducts) {
-
- if (p.getTaxInclusiveTotalPrice() != null) {
- rawMaterialCost = rawMaterialCost.add(p.getTaxInclusiveTotalPrice());
- }
-
- if (p.getTicketsTotal() != null) {
- paidAmount = paidAmount.add(p.getTicketsTotal());
- }
-
- if (p.getPendingTicketsTotal() != null) {
- pendingAmount = pendingAmount.add(p.getPendingTicketsTotal());
- }
- }
- }
-
- // 鍏朵粬璐圭敤
- LambdaQueryWrapper<AccountExpense> expenseWrapper = new LambdaQueryWrapper<>();
- expenseWrapper.ge(AccountExpense::getExpenseDate,
- java.sql.Date.valueOf(currentMonth.atDay(1)));
- expenseWrapper.le(AccountExpense::getExpenseDate,
- java.sql.Date.valueOf(currentMonth.atEndOfMonth()));
-
- List<AccountExpense> expenses = accountExpenseMapper.selectList(expenseWrapper);
-
- BigDecimal otherExpense = BigDecimal.ZERO;
- if (!CollectionUtils.isEmpty(expenses)) {
- for (AccountExpense e : expenses) {
- if (e.getExpenseMoney() != null) {
- otherExpense = otherExpense.add(e.getExpenseMoney());
- }
- }
- }
-
- // 鏈堝害鎬绘敮鍑�
- // BigDecimal monthlyExpenditure = rawMaterialCost.add(otherExpense);
- BigDecimal monthlyExpenditure = otherExpense;
- dto.setMonthlyExpenditure(monthlyExpenditure);
-
- // 宸蹭粯娆� 梅锛堝凡浠樻 + 寰呬粯娆撅級
- BigDecimal totalPayable = paidAmount.add(pendingAmount);
- if (totalPayable.compareTo(BigDecimal.ZERO) > 0) {
- String paymentRate = paidAmount
- .divide(totalPayable, 4, RoundingMode.HALF_UP)
- .multiply(BigDecimal.valueOf(100))
- .setScale(2, RoundingMode.HALF_UP)
- .toString();
- dto.setPaymentRate(paymentRate);
- }
-
- // 鍞彴璐︼紙type = 1锛�
- LambdaQueryWrapper<SalesLedgerProduct> salesWrapper = new LambdaQueryWrapper<>();
- salesWrapper.eq(SalesLedgerProduct::getType, 1);
- salesWrapper.ge(SalesLedgerProduct::getRegisterDate, startOfMonth);
- salesWrapper.le(SalesLedgerProduct::getRegisterDate, endOfMonth);
-
- List<SalesLedgerProduct> salesProducts = salesLedgerProductMapper.selectList(salesWrapper);
-
- BigDecimal revenue = BigDecimal.ZERO;
- if (!CollectionUtils.isEmpty(salesProducts)) {
- for (SalesLedgerProduct s : salesProducts) {
- if (s.getInvoiceAmount() != null) {
- revenue = revenue.add(s.getInvoiceAmount());
- }
- }
- }
-
- // 姣涘埄娑� & 鍒╂鼎鐜�
- if (revenue.compareTo(BigDecimal.ZERO) > 0) {
-
- // 姣涘埄娑� = 閿�鍞敹鍏� - 鍘熸潗鏂欐垚鏈�
- BigDecimal grossProfit = revenue.subtract(rawMaterialCost);
- dto.setGrossProfit(grossProfit);
-
- // 鍒╂鼎鐜� = (閿�鍞敹鍏� - 鏈堝害鎬绘敮鍑�) / 閿�鍞敹鍏�
- BigDecimal profit = revenue.subtract(monthlyExpenditure);
- String profitMarginRate = profit
- .divide(revenue, 4, RoundingMode.HALF_UP)
- .multiply(BigDecimal.valueOf(100))
- .setScale(2, RoundingMode.HALF_UP)
- .toString();
-
- dto.setProfitMarginRate(profitMarginRate);
- }
-
+ dto.setMonthlyExpenditure(scaleMoney(monthlyExpenditure));
+ dto.setPaymentRate(paymentRate);
+ dto.setGrossProfit(scaleMoney(grossProfit));
+ dto.setProfitMarginRate(profitMarginRate);
return dto;
}
@@ -1904,11 +1750,8 @@
BigDecimal unqualifiedCount = BigDecimal.ZERO;
for (QualityInspect item : list) {
- if ("鍚堟牸".equals(item.getCheckResult())) {
- qualifiedCount = qualifiedCount.add(item.getQuantity());
- } else {
- unqualifiedCount = unqualifiedCount.add(item.getQuantity());
- }
+ qualifiedCount = qualifiedCount.add(item.getQualifiedQuantity() != null ? item.getQualifiedQuantity() : BigDecimal.ZERO);
+ unqualifiedCount = unqualifiedCount.add(item.getUnqualifiedQuantity() != null ? item.getUnqualifiedQuantity() : BigDecimal.ZERO);
}
BigDecimal totalCount = qualifiedCount.add(unqualifiedCount);
@@ -2177,13 +2020,11 @@
continue;
}
- BigDecimal quantity = item.getQuantity();
+ BigDecimal qualifiedQty = item.getQualifiedQuantity() != null ? item.getQualifiedQuantity() : BigDecimal.ZERO;
+ BigDecimal unqualifiedQty = item.getUnqualifiedQuantity() != null ? item.getUnqualifiedQuantity() : BigDecimal.ZERO;
- if ("鍚堟牸".equals(item.getCheckResult())) {
- dto.setQualifiedCount(dto.getQualifiedCount().add(quantity));
- } else {
- dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(quantity));
- }
+ dto.setQualifiedCount(dto.getQualifiedCount().add(qualifiedQty));
+ dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(unqualifiedQty));
}
// 璁$畻鍚堟牸鐜�
@@ -2224,14 +2065,12 @@
BigDecimal unqualifiedCount = BigDecimal.ZERO;
for (QualityInspect item : items) {
- BigDecimal qty = item.getQuantity();
- totalCount = totalCount.add(qty);
+ BigDecimal qualifiedQty = item.getQualifiedQuantity() != null ? item.getQualifiedQuantity() : BigDecimal.ZERO;
+ BigDecimal unqualifiedQty = item.getUnqualifiedQuantity() != null ? item.getUnqualifiedQuantity() : BigDecimal.ZERO;
- if ("鍚堟牸".equals(item.getCheckResult())) {
- qualifiedCount = qualifiedCount.add(qty);
- } else {
- unqualifiedCount = unqualifiedCount.add(qty);
- }
+ totalCount = totalCount.add(qualifiedQty.add(unqualifiedQty));
+ qualifiedCount = qualifiedCount.add(qualifiedQty);
+ unqualifiedCount = unqualifiedCount.add(unqualifiedQty);
}
if (totalCount.compareTo(BigDecimal.ZERO) == 0) {
@@ -2360,13 +2199,17 @@
dto.setProcessNum(sumQuantity(qualityInspectList, 1)); // 杩囩▼
dto.setFactoryNum(sumQuantity(qualityInspectList, 2)); // 鍑哄巶
- // 鍋囪 qualityInspectList 鏄竴涓� List<QualityInspect> 绫诲瀷鐨勯泦鍚�
- Map<String, List<QualityInspect>> groupedByCheckResult = qualityInspectList.stream()
- .collect(Collectors.groupingBy(QualityInspect::getCheckResult));
- List<QualityInspect> qualityInspects = groupedByCheckResult.get("涓嶅悎鏍�");
- if (ObjectUtils.isNull(qualityInspects) || qualityInspects.size() == 0) {
- return null;
+ // 鏍规嵁 unqualifiedQuantity > 0 绛涢�変笉鍚堟牸璁板綍
+ List<QualityInspect> qualityInspects = qualityInspectList.stream()
+ .filter(i -> i.getUnqualifiedQuantity() != null && i.getUnqualifiedQuantity().compareTo(BigDecimal.ZERO) > 0)
+ .collect(Collectors.toList());
+
+ if (ObjectUtils.isEmpty(qualityInspects)) {
+ // 鍗充娇娌℃湁涓嶅悎鏍艰褰曪紝涔熷簲璇ヨ繑鍥炵粺璁℃暟鎹紝鍙槸鍥捐〃椤逛负绌�
+ dto.setItem(new ArrayList<>());
+ return dto;
}
+
// 4. 澶勭悊鍥捐〃椤� (Item)
List<QualityStatisticsItem> itemList = new ArrayList<>();
@@ -2409,8 +2252,11 @@
private BigDecimal sumQuantity(List<QualityInspect> list, Integer type) {
return list.stream()
.filter(i -> i.getInspectType().equals(type))
- .map(QualityInspect::getQuantity)
- .filter(Objects::nonNull)
+ .map(i -> {
+ BigDecimal qualified = i.getQualifiedQuantity() != null ? i.getQualifiedQuantity() : BigDecimal.ZERO;
+ BigDecimal unqualified = i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO;
+ return qualified.add(unqualified);
+ })
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
@@ -2418,11 +2264,18 @@
QualityStatisticsItem item = new QualityStatisticsItem();
item.setDate(dateLabel);
- item.setSupplierNum(list.stream().filter(i -> i.getInspectType() == 0).map(QualityInspect::getQuantity)
+ // 缁熻姣忕妫�楠岀被鍨嬬殑涓嶅悎鏍兼暟閲�
+ item.setSupplierNum(list.stream()
+ .filter(i -> i.getInspectType() == 0)
+ .map(i -> i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO)
.reduce(BigDecimal.ZERO, BigDecimal::add));
- item.setProcessNum(list.stream().filter(i -> i.getInspectType() == 1).map(QualityInspect::getQuantity)
+ item.setProcessNum(list.stream()
+ .filter(i -> i.getInspectType() == 1)
+ .map(i -> i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO)
.reduce(BigDecimal.ZERO, BigDecimal::add));
- item.setFactoryNum(list.stream().filter(i -> i.getInspectType() == 2).map(QualityInspect::getQuantity)
+ item.setFactoryNum(list.stream()
+ .filter(i -> i.getInspectType() == 2)
+ .map(i -> i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO)
.reduce(BigDecimal.ZERO, BigDecimal::add));
return item;
@@ -2462,6 +2315,121 @@
return productionOperationTaskMapper.calculateProductionStatistics(startDateTime, endDateTime, userId, processIds);
}
+ private LocalDate[] resolveFinanceRange(Integer type) {
+ LocalDate today = LocalDate.now();
+ int safeType = type == null ? 1 : type;
+ LocalDate startDate;
+ LocalDate endDate;
+ switch (safeType) {
+ case 1:
+ startDate = today.with(DayOfWeek.MONDAY);
+ endDate = today.with(DayOfWeek.SUNDAY);
+ break;
+ case 2:
+ startDate = today.with(TemporalAdjusters.firstDayOfMonth());
+ endDate = today.with(TemporalAdjusters.lastDayOfMonth());
+ break;
+ case 3:
+ Month firstMonthOfQuarter = today.getMonth().firstMonthOfQuarter();
+ startDate = LocalDate.of(today.getYear(), firstMonthOfQuarter, 1);
+ endDate = startDate.plusMonths(2).with(TemporalAdjusters.lastDayOfMonth());
+ break;
+ default:
+ startDate = today.with(DayOfWeek.MONDAY);
+ endDate = today.with(DayOfWeek.SUNDAY);
+ break;
+ }
+ return new LocalDate[]{startDate, endDate};
+ }
+
+ //璁$畻鏃ユ湡鍐呯殑閿�鍞嚭搴撻噾棰�
+ private BigDecimal sumSalesContractAmount(LocalDate startDate, LocalDate endDate) {
+ SalesOutboundDto salesOutboundDto = new SalesOutboundDto();
+ salesOutboundDto.setStartDate(startDate);
+ salesOutboundDto.setEndDate(endDate);
+ List<SalesOutboundVo> salesOutboundVos = stockOutRecordMapper.listPageAccountSales(new Page(1, -1), salesOutboundDto).getRecords();
+ return sumAmount(salesOutboundVos, SalesOutboundVo::getOutboundAmount);
+ }
+
+ //璁$畻鏃ユ湡鍐呯殑閿�鍞��璐ч噾棰�
+ private BigDecimal sumSalesReturnAmount(LocalDate startDate, LocalDate endDate) {
+ SalesReturnDto salesReturnDto = new SalesReturnDto();
+ salesReturnDto.setStartDate(startDate);
+ salesReturnDto.setEndDate(endDate);
+ List<SalesReturnVo> salesReturnVos = returnManagementMapper.listPageAccountSalesReturn(new Page(1, -1), salesReturnDto).getRecords();
+ return sumAmount(salesReturnVos, SalesReturnVo::getRefundAmount);
+ }
+
+ //璁$畻鏃ユ湡鍐呯殑閲囪喘鍏ュ簱閲戦
+ private BigDecimal sumPurchaseContractAmount(LocalDate startDate, LocalDate endDate) {
+ PurchaseInboundDto purchaseInboundDto = new PurchaseInboundDto();
+ purchaseInboundDto.setStartDate(startDate);
+ purchaseInboundDto.setEndDate(endDate);
+ List<PurchaseInboundVo> purchaseInboundVos = stockInRecordMapper.listPageAccountPurchase(new Page(1, -1), purchaseInboundDto).getRecords();
+ return sumAmount(purchaseInboundVos, PurchaseInboundVo::getInboundAmount);
+ }
+
+ //璁$畻鏃ユ湡鍐呯殑閲囪喘閫�璐ч噾棰�
+ private BigDecimal sumPurchaseReturnAmount(LocalDate startDate, LocalDate endDate) {
+ PurchaseReturnDto purchaseReturnDto = new PurchaseReturnDto();
+ purchaseReturnDto.setStartDate(startDate);
+ purchaseReturnDto.setEndDate(endDate);
+ List<PurchaseReturnVo> purchaseReturnVos = purchaseReturnOrdersMapper.listPageAccountPurchaseReturn(new Page(1, -1), purchaseReturnDto).getRecords();
+ return sumAmount(purchaseReturnVos, PurchaseReturnVo::getTotalAmount);
+ }
+
+ //璁$畻鏃ユ湡鍐呯殑鎬绘敹娆鹃噾棰�
+ private BigDecimal sumCollectionAmount(LocalDate startDate, LocalDate endDate) {
+ List<AccountSalesCollection> collections = defaultList(accountSalesCollectionMapper.selectList(
+ new LambdaQueryWrapper<AccountSalesCollection>()
+ .ge(AccountSalesCollection::getCollectionDate, startDate)
+ .le(AccountSalesCollection::getCollectionDate, endDate)));
+ return sumAmount(collections, AccountSalesCollection::getCollectionAmount);
+ }
+
+ //璁$畻鏃ユ湡鍐呯殑鎬讳粯娆鹃噾棰�
+ private BigDecimal sumPaymentAmount(LocalDate startDate, LocalDate endDate) {
+ List<AccountPurchasePayment> payments = defaultList(accountPurchasePaymentMapper.selectList(
+ new LambdaQueryWrapper<AccountPurchasePayment>()
+ .ge(AccountPurchasePayment::getPaymentDate, startDate)
+ .le(AccountPurchasePayment::getPaymentDate, endDate)));
+ return sumAmount(payments, AccountPurchasePayment::getPaymentAmount);
+ }
+
+ private Date toDate(LocalDate localDate) {
+ return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
+ }
+
+ private Date toExclusiveEndDate(LocalDate localDate) {
+ return Date.from(localDate.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
+ }
+
+ private String toRateString(BigDecimal numerator, BigDecimal denominator) {
+ if (denominator == null || denominator.compareTo(BigDecimal.ZERO) <= 0) {
+ return "0.00";
+ }
+ return defaultDecimal(numerator)
+ .divide(denominator, 4, RoundingMode.HALF_UP)
+ .multiply(BigDecimal.valueOf(100))
+ .setScale(2, RoundingMode.HALF_UP)
+ .toString();
+ }
+
+ private BigDecimal maxZero(BigDecimal value) {
+ if (value == null) {
+ return BigDecimal.ZERO;
+ }
+ return value.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : value;
+ }
+
+ private BigDecimal scaleMoney(BigDecimal value) {
+ return defaultDecimal(value).setScale(2, RoundingMode.HALF_UP);
+ }
+
+ private <T> List<T> defaultList(List<T> list) {
+ return list == null ? List.of() : list;
+ }
+
private BigDecimal defaultDecimal(BigDecimal value) {
return value == null ? BigDecimal.ZERO : value;
}
diff --git a/src/main/java/com/ruoyi/procurementrecord/controller/ReturnManagementController.java b/src/main/java/com/ruoyi/procurementrecord/controller/ReturnManagementController.java
index b3f31b9..6387006 100644
--- a/src/main/java/com/ruoyi/procurementrecord/controller/ReturnManagementController.java
+++ b/src/main/java/com/ruoyi/procurementrecord/controller/ReturnManagementController.java
@@ -3,11 +3,16 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.pojo.AccountStatementDetails;
+import com.ruoyi.account.service.AccountStatementDetailsService;
+import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.procurementrecord.bean.dto.ReturnManagementDto;
import com.ruoyi.procurementrecord.bean.vo.ShippingInfoVo;
+import com.ruoyi.procurementrecord.pojo.ReturnManagement;
import com.ruoyi.procurementrecord.pojo.ReturnSaleProduct;
import com.ruoyi.procurementrecord.service.ReturnManagementService;
import com.ruoyi.procurementrecord.service.ReturnSaleProductService;
@@ -31,6 +36,7 @@
private ReturnManagementService returnManagementService;
private ReturnSaleProductService returnSaleProductService;
+ private final AccountStatementDetailsService accountStatementDetailsService;
@GetMapping("/listPage")
@Operation(summary = "閿�鍞��璐�-鏌ヨ")
@@ -67,6 +73,14 @@
@Transactional(rollbackFor = Exception.class)
public AjaxResult del(@RequestBody List<Long> ids) {
if (CollectionUtils.isEmpty(ids)) return error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+ //濡傛灉璇ラ攢鍞��璐у凡缁忕敓鎴愬璐﹀崟鍒欐棤娉曞垹闄�
+ List<ReturnManagement> returnManagements = returnManagementService.listByIds(ids);
+ List<String> strings = returnManagements.stream().map(ReturnManagement::getReturnNo).toList();
+ List<AccountStatementDetails> accountStatementDetails = accountStatementDetailsService.list(Wrappers.<AccountStatementDetails>lambdaQuery()
+ .in(AccountStatementDetails::getReceiptNumber, strings));
+ if (CollectionUtils.isNotEmpty(accountStatementDetails)){
+ throw new ServiceException("璇ラ攢鍞��璐у崟宸茬粡鐢熸垚瀵硅处鍗曪紝鏃犳硶鍒犻櫎");
+ }
returnSaleProductService.remove(new QueryWrapper<ReturnSaleProduct>()
.lambda()
.in(ReturnSaleProduct::getReturnManagementId, ids));
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnManagementServiceImpl.java b/src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnManagementServiceImpl.java
index b4701f6..5834e65 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnManagementServiceImpl.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnManagementServiceImpl.java
@@ -4,8 +4,6 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.account.bean.dto.SalesRefundAmountOrderDto;
-import com.ruoyi.account.mapper.AccountExpenseMapper;
-import com.ruoyi.account.pojo.AccountExpense;
import com.ruoyi.account.service.SalesRefundAmountOrderService;
import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
import com.ruoyi.common.utils.OrderUtils;
@@ -31,7 +29,6 @@
import org.springframework.util.ObjectUtils;
import java.math.BigDecimal;
-import java.util.Date;
import java.util.List;
/**
@@ -49,7 +46,6 @@
private final SalesLedgerMapper salesLedgerMapper;
private final SalesRefundAmountOrderService salesRefundAmountOrderService;
private final StockUtils stockUtils;
- private final AccountExpenseMapper accountExpenseMapper;
@Override
public IPage<ReturnManagementDto> listPage(Page page, ReturnManagementDto returnManagement) {
@@ -127,19 +123,6 @@
salesRefundAmountOrder.setNotRefundedAmount(salesRefundAmountOrder.getRefundedAmount());
// 鍒嗘壒閫�娆�
// salesRefundAmountOrderService.addSalesRefundAmountOrderDto(salesRefundAmountOrder);
- // 鍜岃储鍔¤仈鍔紝鏂板鏀嚭
- AccountExpense accountExpense = new AccountExpense();
- accountExpense.setBusinessType(3);
- accountExpense.setExpenseMoney(byId.getRefundAmount());
- accountExpense.setBusinessId(byId.getId());
- accountExpense.setExpenseDate(new Date());
- accountExpense.setExpenseMethod("3");
- accountExpense.setExpenseType("5");
- accountExpense.setExpenseDescribed("閿�鍞��璐ч��娆�");
- accountExpense.setNote(byId.getReturnReason());
- accountExpense.setInputUser(SecurityUtils.getLoginUser().getNickName());
- accountExpense.setInputTime(new Date());
- accountExpenseMapper.insert(accountExpense);
return true;
}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java
index 965cbf3..8a75dcd 100644
--- a/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java
@@ -44,4 +44,7 @@
@Schema(description = "缁撴潫鏃ユ湡")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate endDate;
+
+ @Schema(description = "鏄惁鐢熶骇")
+ private Integer isProduction;
}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingController.java b/src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingController.java
index dda1aa0..833e737 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingController.java
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingController.java
@@ -39,7 +39,7 @@
@PostMapping("/updateRouteItem")
@Operation(summary = "淇敼鐢熶骇璁㈠崟鐨勫伐鑹鸿矾绾胯鎯�")
public R updateRouteItem(@RequestBody ProductionOrderRoutingOperation productionOrderRoutingOperation) {
- return R.ok(productionOrderRoutingOperationService.updateById(productionOrderRoutingOperation));
+ return productionOrderRoutingOperationService.updateRouteItem(productionOrderRoutingOperation);
}
@DeleteMapping("/deleteRouteItem/{id}")
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOrderMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOrderMapper.java
index e52df0c..cec7ca5 100644
--- a/src/main/java/com/ruoyi/production/mapper/ProductionOrderMapper.java
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionOrderMapper.java
@@ -12,6 +12,7 @@
import java.time.LocalDateTime;
import java.util.List;
+import java.util.Map;
/**
* <p>
@@ -39,4 +40,24 @@
Integer countPending(@Param("startDate") String startDate, @Param("endDate") String endDate);
+ List<Map<String, Object>> selectHomeOrderProgressPage(@Param("status") Integer status,
+ @Param("offset") Long offset,
+ @Param("size") Long size,
+ @Param("startTime") LocalDateTime startTime,
+ @Param("endTime") LocalDateTime endTime);
+
+ Long countHomeOrderProgress(@Param("status") Integer status,
+ @Param("startTime") LocalDateTime startTime,
+ @Param("endTime") LocalDateTime endTime);
+
+ List<Map<String, Object>> countHomeOrderProgressByStatus(@Param("startTime") LocalDateTime startTime,
+ @Param("endTime") LocalDateTime endTime);
+
+ List<Map<String, Object>> selectHomeTodayProductionPlan(@Param("size") Long size,
+ @Param("planStart") LocalDateTime planStart,
+ @Param("planEnd") LocalDateTime planEnd);
+
+ Long countHomeTodayProductionPlan(@Param("planStart") LocalDateTime planStart,
+ @Param("planEnd") LocalDateTime planEnd);
+
}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOrderRoutingOperationService.java b/src/main/java/com/ruoyi/production/service/ProductionOrderRoutingOperationService.java
index 2377dc3..e14b36f 100644
--- a/src/main/java/com/ruoyi/production/service/ProductionOrderRoutingOperationService.java
+++ b/src/main/java/com/ruoyi/production/service/ProductionOrderRoutingOperationService.java
@@ -8,7 +8,10 @@
R addRouteItem(ProductionOrderRoutingOperation productionOrderRoutingOperation);
+ R updateRouteItem(ProductionOrderRoutingOperation productionOrderRoutingOperation);
+
R deleteRouteItem(Long id);
int sortRouteItem(ProductionOrderRoutingOperation productionOrderRoutingOperation);
+
}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
index 31cdc79..0513bdc 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
@@ -23,6 +23,7 @@
import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam;
import com.ruoyi.production.pojo.ProductionProductMain;
import com.ruoyi.production.service.ProductionBomStructureService;
+import com.ruoyi.production.util.TaskPlanQuantityUtil;
import com.ruoyi.technology.mapper.TechnologyOperationMapper;
import com.ruoyi.technology.mapper.TechnologyOperationParamMapper;
import com.ruoyi.technology.mapper.TechnologyParamMapper;
@@ -262,7 +263,7 @@
.filter(item -> item != null && item.getId() != null)
.collect(Collectors.toMap(ProductionOrderRoutingOperation::getId, item -> item, (left, right) -> left));
// Keep task plan quantities aligned with the same order BOM snapshot demand used during snapshot creation.
- Map<String, BigDecimal> demandedQuantityMap = buildOperationDemandedQuantityMap(structureList, rootProductModelId);
+ Map<String, BigDecimal> demandedQuantityMap = TaskPlanQuantityUtil.buildOperationDemandedQuantityMap(structureList, rootProductModelId);
for (ProductionOperationTask task : taskList) {
if (task == null || task.getId() == null || task.getProductionOrderRoutingOperationId() == null) {
continue;
@@ -310,7 +311,7 @@
if (matchedOperation == null) {
matchedOperation = insertRoutingOperationSnapshot(orderRouting.getId(), productionOrderId, desiredOperation);
} else {
- updateRoutingOperationSnapshotIfNecessary(desiredOperation, orderRouting.getId(), productionOrderId, matchedOperation);
+ updateRoutingOperationSnapshotIfNecessary(matchedOperation, orderRouting.getId(), productionOrderId, desiredOperation);
}
finalOperationList.add(matchedOperation);
}
@@ -381,17 +382,32 @@
Map<Long, ProductionBomStructure> structureById = structureList.stream()
.filter(item -> item != null && item.getId() != null)
.collect(Collectors.toMap(ProductionBomStructure::getId, item -> item, (left, right) -> left));
- Map<String, ProductionBomStructure> uniqueOperationMap = new LinkedHashMap<>();
- for (ProductionBomStructure bomStructure : structureList) {
- if (bomStructure == null || bomStructure.getTechnologyOperationId() == null) {
- continue;
+
+ // 鏋勫缓鐖�-瀛愭槧灏勫叧绯�
+ Map<Long, List<ProductionBomStructure>> treeMap = buildParentChildMap(structureList);
+
+ // 浣跨敤鍚庡簭閬嶅巻鏋勫缓鎿嶄綔鍒楄〃锛堝厛瀛愬悗鐖讹紝纭繚宸ヨ壓璺嚎椤哄簭姝g‘锛�
+ // 浣跨敤娣卞害浣滀负鎺掑簭渚濇嵁鐨勮緟鍔╃粨鏋�
+ Map<String, ProductionBomStructure> operationMap = new LinkedHashMap<>();
+ Map<String, Integer> depthMap = new HashMap<>();
+ buildOperationListPostOrderWithDepth(null, treeMap, operationMap, depthMap, structureById, rootProductModelId, 1);
+
+ // 鎸夋繁搴︽帓搴忥紝娣卞害澶х殑鎺掑墠闈�
+ List<Map.Entry<String, ProductionBomStructure>> sortedEntries = new ArrayList<>(operationMap.entrySet());
+ sortedEntries.sort((a, b) -> {
+ int depthCompare = Integer.compare(
+ depthMap.getOrDefault(b.getKey(), 0),
+ depthMap.getOrDefault(a.getKey(), 0));
+ if (depthCompare != 0) {
+ return depthCompare;
}
- Long outputProductModelId = resolveOutputProductModelId(resolveOperationOutputNode(bomStructure, structureById), rootProductModelId);
- uniqueOperationMap.putIfAbsent(buildBomOperationDedupKey(bomStructure, outputProductModelId), bomStructure);
- }
+ return 0;
+ });
+
List<ProductionOrderRoutingOperation> desiredOperationList = new ArrayList<>();
int dragSort = 1;
- for (ProductionBomStructure bomStructure : uniqueOperationMap.values()) {
+ for (Map.Entry<String, ProductionBomStructure> entry : sortedEntries) {
+ ProductionBomStructure bomStructure = entry.getValue();
Long outputProductModelId = resolveOutputProductModelId(resolveOperationOutputNode(bomStructure, structureById), rootProductModelId);
TechnologyOperation technologyOperation = getTechnologyOperation(bomStructure.getTechnologyOperationId());
ProductionOrderRoutingOperation routingOperation = new ProductionOrderRoutingOperation();
@@ -405,6 +421,127 @@
desiredOperationList.add(routingOperation);
}
return desiredOperationList;
+ }
+
+ private void buildOperationListPostOrderWithDepth(Long parentId,
+ Map<Long, List<ProductionBomStructure>> treeMap,
+ Map<String, ProductionBomStructure> operationMap,
+ Map<String, Integer> depthMap,
+ Map<Long, ProductionBomStructure> structureById,
+ Long rootProductModelId,
+ int currentDepth) {
+ List<ProductionBomStructure> children = treeMap.get(parentId);
+ if (children == null || children.isEmpty()) {
+ return;
+ }
+ for (ProductionBomStructure child : children) {
+ // 鍏堥�掑綊澶勭悊瀛愯妭鐐�
+ buildOperationListPostOrderWithDepth(child.getId(), treeMap, operationMap, depthMap, structureById, rootProductModelId, currentDepth + 1);
+
+ // 鍐嶅鐞嗗綋鍓嶈妭鐐�
+ if (child.getTechnologyOperationId() != null) {
+ Long outputProductModelId = resolveOutputProductModelId(resolveOperationOutputNode(child, structureById), rootProductModelId);
+ String key = buildBomOperationDedupKey(child, outputProductModelId);
+ // 淇濈暀娣卞害鏈�澶х殑鎿嶄綔
+ Integer existingDepth = depthMap.get(key);
+ if (existingDepth == null || currentDepth > existingDepth) {
+ operationMap.put(key, child);
+ depthMap.put(key, currentDepth);
+ }
+ }
+ }
+ }
+
+ private Map<Long, List<ProductionBomStructure>> buildParentChildMap(List<ProductionBomStructure> structureList) {
+ Map<Long, List<ProductionBomStructure>> treeMap = new LinkedHashMap<>();
+ Map<Long, ProductionBomStructure> structureById = new HashMap<>();
+
+ // 鏋勫缓鐖�-瀛愭槧灏勫拰ID鏄犲皠
+ for (ProductionBomStructure structure : structureList) {
+ if (structure == null) continue;
+ Long parentId = structure.getParentId();
+ treeMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(structure);
+ if (structure.getId() != null) {
+ structureById.put(structure.getId(), structure);
+ }
+ }
+
+ // 璁$畻姣忎釜鑺傜偣鐨勬繁搴︼紙浠庢牴鑺傜偣鍒板綋鍓嶈妭鐐圭殑璺濈锛屾牴鑺傜偣娣卞害涓�1锛�
+ Map<Long, Integer> depthMap = new HashMap<>();
+ for (ProductionBomStructure structure : structureList) {
+ if (structure == null || structure.getId() == null) continue;
+ computeDepthFromRoot(structure.getId(), structureById, depthMap);
+ }
+
+ // 瀵规瘡涓埗鑺傜偣涓嬬殑瀛愯妭鐐规寜娣卞害鍊掑簭鎺掑簭锛堟渶娣卞眰鐨勪紭鍏堬級
+ for (Map.Entry<Long, List<ProductionBomStructure>> entry : treeMap.entrySet()) {
+ List<ProductionBomStructure> children = entry.getValue();
+ children.sort((a, b) -> {
+ // 浼樺厛鎸夋繁搴︽帓搴忥紝娣卞害澶х殑鎺掑墠闈紙鏈�娣卞眰浼樺厛锛�
+ int depthCompare = Integer.compare(
+ depthMap.getOrDefault(b.getId(), 0),
+ depthMap.getOrDefault(a.getId(), 0));
+ if (depthCompare != 0) {
+ return depthCompare;
+ }
+ // 娣卞害鐩稿悓鏃舵寜ID鎺掑簭淇濊瘉绋冲畾鎬�
+ return Long.compare(a.getId(), b.getId());
+ });
+ }
+
+ return treeMap;
+ }
+
+ /**
+ * 璁$畻鑺傜偣娣卞害锛堜粠鏍硅妭鐐瑰埌褰撳墠鑺傜偣鐨勮窛绂伙級
+ * 鏍硅妭鐐规繁搴︿负1锛屾瘡鍚戜笅涓�灞傛繁搴﹀姞1
+ */
+ private int computeDepthFromRoot(Long nodeId, Map<Long, ProductionBomStructure> structureById, Map<Long, Integer> depthMap) {
+ if (depthMap.containsKey(nodeId)) {
+ return depthMap.get(nodeId);
+ }
+
+ ProductionBomStructure structure = structureById.get(nodeId);
+ if (structure == null) {
+ depthMap.put(nodeId, 1);
+ return 1;
+ }
+
+ Long parentId = structure.getParentId();
+ if (parentId == null || parentId == 0L) {
+ // 鏍硅妭鐐规繁搴︿负1
+ depthMap.put(nodeId, 1);
+ return 1;
+ }
+
+ // 瀛愯妭鐐规繁搴� = 鐖惰妭鐐规繁搴� + 1
+ int parentDepth = computeDepthFromRoot(parentId, structureById, depthMap);
+ int depth = parentDepth + 1;
+ depthMap.put(nodeId, depth);
+ return depth;
+ }
+
+ private void buildOperationListPostOrder(Long parentId,
+ Map<Long, List<ProductionBomStructure>> treeMap,
+ Map<String, ProductionBomStructure> uniqueOperationMap,
+ Map<Long, ProductionBomStructure> structureById,
+ Long rootProductModelId) {
+ List<ProductionBomStructure> children = treeMap.get(parentId);
+ if (children == null || children.isEmpty()) {
+ return;
+ }
+ for (ProductionBomStructure child : children) {
+ // 鍏堥�掑綊澶勭悊瀛愯妭鐐�
+ buildOperationListPostOrder(child.getId(), treeMap, uniqueOperationMap, structureById, rootProductModelId);
+
+ // 鍐嶅鐞嗗綋鍓嶈妭鐐�
+ if (child.getTechnologyOperationId() != null) {
+ Long outputProductModelId = resolveOutputProductModelId(resolveOperationOutputNode(child, structureById), rootProductModelId);
+ String key = buildBomOperationDedupKey(child, outputProductModelId);
+ // 鍘婚噸鏃朵繚鐣欐繁搴︽渶澶х殑鎿嶄綔锛堝悗搴忛亶鍘嗗厛閬囧埌娣卞眰鑺傜偣锛屾墍浠ョ洿鎺ヨ鐩栧嵆鍙級
+ uniqueOperationMap.put(key, child);
+ }
+ }
}
private Map<String, Deque<ProductionOrderRoutingOperation>> buildExistingRoutingOperationBucketMap(List<ProductionOrderRoutingOperation> existingOperationList) {
@@ -571,7 +708,7 @@
return;
}
if (defaultDecimal(task.getCompleteQuantity()).compareTo(BigDecimal.ZERO) > 0) {
- throw new ServiceException("宸ュ簭宸蹭骇鐢熸姤宸ヨ褰曪紝鏃犳硶鏍规嵁 BOM 鍙樻洿鍒犻櫎瀵瑰簲宸ュ簭蹇収");
+ throw new ServiceException("宸ュ簭宸蹭骇鐢熸姤宸ヨ褰曪紝鏃犳硶鏍规嵁 BOM 鍙樻洿鍒犻櫎瀵瑰簲宸ュ簭蹇収" + task.getWorkOrderNo());
}
long reportCount = productionProductMainMapper.selectCount(
Wrappers.<ProductionProductMain>lambdaQuery()
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java
index 3d16a07..75d0696 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java
@@ -4,21 +4,15 @@
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.mapper.ProductionOperationTaskMapper;
-import com.ruoyi.production.mapper.ProductionOrderRoutingOperationMapper;
-import com.ruoyi.production.mapper.ProductionOrderRoutingOperationParamMapper;
-import com.ruoyi.production.mapper.ProductionProductMainMapper;
-import com.ruoyi.production.pojo.ProductionOperationTask;
-import com.ruoyi.production.pojo.ProductionOrderRoutingOperation;
-import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam;
-import com.ruoyi.production.pojo.ProductionProductMain;
+import com.ruoyi.production.mapper.*;
+import com.ruoyi.production.util.TaskPlanQuantityUtil;
+import com.ruoyi.technology.mapper.*;
+import com.ruoyi.production.pojo.*;
import com.ruoyi.production.service.ProductionOrderRoutingOperationService;
import com.ruoyi.production.service.ProductionProductMainService;
-import com.ruoyi.technology.mapper.TechnologyOperationParamMapper;
-import com.ruoyi.technology.mapper.TechnologyParamMapper;
-import com.ruoyi.technology.pojo.TechnologyOperationParam;
-import com.ruoyi.technology.pojo.TechnologyParam;
+import com.ruoyi.technology.pojo.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -26,8 +20,7 @@
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
@Service
@Transactional(rollbackFor = Exception.class)
@@ -42,6 +35,11 @@
private final TechnologyOperationParamMapper technologyOperationParamMapper;
private final TechnologyParamMapper technologyParamMapper;
private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper;
+ private final ProductionOrderMapper productionOrderMapper;
+ private final ProductionOrderRoutingMapper productionOrderRoutingMapper;
+ private final ProductionOrderBomMapper productionOrderBomMapper;
+ private final ProductionBomStructureMapper productionBomStructureMapper;
+ private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper;
@Override
public R addRouteItem(ProductionOrderRoutingOperation productionOrderRoutingOperation) {
@@ -102,6 +100,109 @@
productionOperationTaskMapper.insert(productionOperationTask);
}
return R.ok();
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public R updateRouteItem(ProductionOrderRoutingOperation productionOrderRoutingOperation) {
+ Long operationId = productionOrderRoutingOperation.getId();
+
+ // 鏇存柊宸ヨ壓璺嚎宸ュ簭
+ productionOrderRoutingOperationMapper.updateById(productionOrderRoutingOperation);
+
+ // 閲嶆柊鏌ヨ瀹屾暣璁板綍锛堝墠绔彲鑳芥病鏈変紶閫掓墍鏈夊瓧娈碉紝濡� productionOrderId锛�
+ ProductionOrderRoutingOperation updatedOperation = productionOrderRoutingOperationMapper.selectById(operationId);
+ if (updatedOperation == null) {
+ throw new ServiceException("宸ヨ壓璺嚎宸ュ簭涓嶅瓨鍦�");
+ }
+
+ // 鏌ヨ鏄惁瀛樺湪宸ュ崟
+ ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectOne(
+ new LambdaQueryWrapper<ProductionOperationTask>()
+ .eq(ProductionOperationTask::getProductionOrderRoutingOperationId, operationId)
+ .last("limit 1"));
+
+ // 鏍规嵁鏄惁闇�瑕佺敓浜ц繘琛屽鐞�
+ Boolean isProduction = updatedOperation.getIsProduction();
+
+ if (Boolean.TRUE.equals(isProduction)) {
+ // 闇�瑕佺敓浜э細妫�鏌ュ伐鍗曟槸鍚﹀瓨鍦紝涓嶅瓨鍦ㄥ垯鐢熸垚
+ if (productionOperationTask == null) {
+ ProductionOperationTask task = new ProductionOperationTask();
+ task.setProductionOrderRoutingOperationId(updatedOperation.getId());
+ task.setProductionOrderId(updatedOperation.getProductionOrderId());
+ // 鑾峰彇鐢熶骇璁㈠崟
+ ProductionOrder productionOrder = productionOrderMapper.selectById(updatedOperation.getProductionOrderId());
+ if (productionOrder == null) {
+ throw new ServiceException("鐢熶骇璁㈠崟涓嶅瓨鍦�");
+ }
+
+ // 鑾峰彇璁㈠崟BOM
+ ProductionOrderBom orderBom = productionOrderBomMapper.selectOne(
+ Wrappers.<ProductionOrderBom>lambdaQuery()
+ .eq(ProductionOrderBom::getProductionOrderId, productionOrder.getId()));
+
+ // 纭畾鏍逛骇鍝佽鏍糏D
+ Long rootProductModelId = orderBom != null && orderBom.getProductModelId() != null
+ ? orderBom.getProductModelId()
+ : productionOrder.getProductModelId();
+
+ // 鑾峰彇BOM缁撴瀯鍒楄〃
+ List<ProductionBomStructure> orderBomStructureList = orderBom == null || orderBom.getId() == null
+ ? Collections.emptyList()
+ : productionBomStructureMapper.selectList(
+ Wrappers.<ProductionBomStructure>lambdaQuery()
+ .eq(ProductionBomStructure::getProductionOrderBomId, orderBom.getId())
+ .orderByAsc(ProductionBomStructure::getId));
+
+ // 鏋勫缓宸ュ簭闇�姹傞噺鏄犲皠
+ Map<String, BigDecimal> operationDemandedQuantityMap =
+ TaskPlanQuantityUtil.buildOperationDemandedQuantityMap(orderBomStructureList, rootProductModelId);
+
+ // 鑾峰彇宸ヨ壓璺嚎宸ュ簭锛堢敤浜庤绠楄鍒掓暟閲忥級
+ TechnologyRoutingOperation sourceOperation = technologyRoutingOperationMapper.selectById(
+ updatedOperation.getTechnologyRoutingOperationId());
+ // 灏嗗師鏉ョ殑绉佹湁鏂规硶鏇挎崲涓鸿皟鐢ㄥ伐鍏风被
+ BigDecimal planQuantity = TaskPlanQuantityUtil.resolveTaskPlanQuantity(
+ sourceOperation,
+ operationDemandedQuantityMap,
+ productionOrder,
+ rootProductModelId);
+ task.setPlanQuantity(planQuantity);
+ task.setCompleteQuantity(BigDecimal.ZERO);
+ task.setWorkOrderNo(generateNextTaskNo());
+ task.setStatus(2);
+ productionOperationTaskMapper.insert(task);
+ }
+ } else {
+ // 涓嶉渶瑕佺敓浜э細妫�鏌ュ伐鍗曟槸鍚﹀瓨鍦�
+ if (productionOperationTask != null) {
+ validateTaskCanRemove(productionOperationTask);
+ // 娌℃湁鎶ュ伐锛屽垯鍒犻櫎宸ュ崟
+ productionOperationTaskMapper.deleteById(productionOperationTask.getId());
+ }
+ }
+
+ return R.ok();
+ }
+
+ private void validateTaskCanRemove(ProductionOperationTask task) {
+ if (task == null || task.getId() == null) {
+ return;
+ }
+ if (defaultDecimal(task.getCompleteQuantity()).compareTo(BigDecimal.ZERO) > 0) {
+ throw new ServiceException("宸ュ簭宸蹭骇鐢熸姤宸ヨ褰曪紝鏃犳硶鏍规嵁 BOM 鍙樻洿鍒犻櫎瀵瑰簲宸ュ簭蹇収");
+ }
+ long reportCount = productionProductMainMapper.selectCount(
+ Wrappers.<ProductionProductMain>lambdaQuery()
+ .eq(ProductionProductMain::getProductionOperationTaskId, task.getId()));
+ if (reportCount > 0) {
+ throw new ServiceException("宸ュ簭宸蹭骇鐢熸姤宸ヨ褰曪紝鏃犳硶鏍规嵁 BOM 鍙樻洿鍒犻櫎瀵瑰簲宸ュ崟");
+ }
+ }
+
+ private BigDecimal defaultDecimal(BigDecimal value) {
+ return value == null ? BigDecimal.ZERO : value;
}
@Override
@@ -182,4 +283,24 @@
}
return 0;
}
+
+ private String generateNextTaskNo() {
+ // 鐢熸垚涓嬩竴涓敓浜у伐鍗曞彿
+ String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+ String prefix = "GD" + datePrefix;
+ ProductionOperationTask lastTask = productionOperationTaskMapper.selectOne(
+ Wrappers.<ProductionOperationTask>lambdaQuery()
+ .likeRight(ProductionOperationTask::getWorkOrderNo, prefix)
+ .orderByDesc(ProductionOperationTask::getWorkOrderNo)
+ .last("limit 1"));
+ int sequence = 1;
+ if (lastTask != null && lastTask.getWorkOrderNo() != null && lastTask.getWorkOrderNo().startsWith(prefix)) {
+ try {
+ sequence = Integer.parseInt(lastTask.getWorkOrderNo().substring(prefix.length())) + 1;
+ } catch (NumberFormatException ignored) {
+ sequence = 1;
+ }
+ }
+ return prefix + String.format("%03d", sequence);
+ }
}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
index ecdb37c..8562b01 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
@@ -59,6 +59,7 @@
private final ProductionOperationTaskMapper productionOperationTaskMapper;
private final ProductionOrderBomMapper productionOrderBomMapper;
private final ProductionBomStructureMapper productionBomStructureMapper;
+ private final ProductionOrderMapper productionOrderMapper;
private final ProductionProductMainMapper productionProductMainMapper;
private final ProductionProductOutputMapper productionProductOutputMapper;
private final ProductionOrderPickMapper productionOrderPickMapper;
@@ -1029,13 +1030,46 @@
return Collections.emptyList();
}
- List<ProductionBomStructureVo> bomStructureList = productionBomStructureMapper.pickByBomId(orderBom.getId());
+ // 鏌ヨ瀹屾暣鐨凚OM缁撴瀯锛堝寘鎷牴鑺傜偣锛夛紝鐢ㄤ簬璁$畻灞傜骇闇�姹傛暟閲�
+ List<ProductionBomStructureVo> bomStructureList = productionBomStructureMapper.listByBomId(orderBom.getId());
if (bomStructureList == null || bomStructureList.isEmpty()) {
return Collections.emptyList();
}
+ // 鏌ヨ鐢熶骇璁㈠崟鑾峰彇璁㈠崟鏁伴噺
+ ProductionOrder productionOrder = productionOrderMapper.selectById(productionOrderId);
+ BigDecimal orderQuantity = productionOrder != null ? defaultDecimal(productionOrder.getQuantity()) : BigDecimal.ZERO;
+
+ // 鏋勫缓鏍戝舰缁撴瀯骞惰绠楀眰绾ч渶姹傛暟閲�
+ Map<Long, ProductionBomStructureVo> structureByIdMap = bomStructureList.stream()
+ .filter(s -> s != null && s.getId() != null)
+ .collect(Collectors.toMap(ProductionBomStructureVo::getId, s -> s));
+
+ // 鎸夊眰绾ц绠楅渶姹傛暟閲忥細瀛愮骇闇�姹傛暟閲� = 鐖剁骇闇�姹傛暟閲� 脳 瀛愮骇鍗曚綅浜у嚭鎵�闇�鏁伴噺
+ for (ProductionBomStructureVo structure : bomStructureList) {
+ if (structure == null) continue;
+
+ if (structure.getParentId() == null || structure.getParentId() == 0) {
+ // 鏍硅妭鐐癸細闇�姹傛暟閲� = 璁㈠崟鏁伴噺
+ structure.setDemandedQuantity(orderQuantity);
+ } else {
+ // 瀛愯妭鐐癸細闇�姹傛暟閲� = 鐖剁骇闇�姹傛暟閲� 脳 瀛愮骇鍗曚綅浜у嚭鎵�闇�鏁伴噺
+ ProductionBomStructureVo parent = structureByIdMap.get(structure.getParentId());
+ if (parent != null) {
+ BigDecimal parentDemandedQty = defaultDecimal(parent.getDemandedQuantity());
+ BigDecimal unitQuantity = defaultDecimal(structure.getUnitQuantity());
+ structure.setDemandedQuantity(parentDemandedQty.multiply(unitQuantity));
+ }
+ }
+ }
+
+ // 杩囨护鍑洪潪鏍硅妭鐐癸紙瀹為檯棰嗘枡椤癸級
+ List<ProductionBomStructureVo> childStructureList = bomStructureList.stream()
+ .filter(s -> s != null && s.getParentId() != null && s.getParentId() != 0)
+ .collect(Collectors.toList());
+
// 閬嶅巻澶勭悊鏁版嵁骞剁粍瑁呯粨鏋�
- List<Long> productModelIds = bomStructureList.stream()
+ List<Long> productModelIds = childStructureList.stream()
.map(ProductionBomStructureVo::getProductModelId)
.filter(Objects::nonNull)
.distinct()
@@ -1060,7 +1094,7 @@
}
Map<String, ProductionOrderPickVo> mergedPickMap = new LinkedHashMap<>();
- for (ProductionBomStructureVo structure : bomStructureList) {
+ for (ProductionBomStructureVo structure : childStructureList) {
if (structure == null || structure.getProductModelId() == null) {
continue;
}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
index 2e1e578..c52892a 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -401,7 +401,7 @@
productionAccount.setSchedulingUserId(user == null ? null : user.getUserId());
productionAccount.setSchedulingUserName(user == null ? dto.getUserName() : user.getNickName());
productionAccount.setFinishedNum(productQty);
- productionAccount.setWorkHours(workHours);
+ productionAccount.setWorkHours(technologyOperation != null ? technologyOperation.getSalaryQuota() : null);
productionAccount.setTechnologyOperationName(technologyOperation == null ? null : technologyOperation.getName());
productionAccount.setSchedulingDate(LocalDateTime.now());
productionAccountMapper.insert(productionAccount);
diff --git a/src/main/java/com/ruoyi/production/util/TaskPlanQuantityUtil.java b/src/main/java/com/ruoyi/production/util/TaskPlanQuantityUtil.java
new file mode 100644
index 0000000..e82d7e4
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/util/TaskPlanQuantityUtil.java
@@ -0,0 +1,137 @@
+package com.ruoyi.production.util;
+
+import com.ruoyi.production.pojo.ProductionBomStructure;
+import com.ruoyi.production.pojo.ProductionOrder;
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperation;
+import com.ruoyi.technology.pojo.TechnologyRoutingOperation;
+import lombok.experimental.UtilityClass;
+
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 宸ュ崟璁″垝鏁伴噺璁$畻宸ュ叿绫�
+ */
+@UtilityClass
+public class TaskPlanQuantityUtil {
+
+ /**
+ * 璁$畻宸ュ崟璁″垝鏁伴噺锛堜娇鐢� TechnologyRoutingOperation锛�
+ */
+ public BigDecimal resolveTaskPlanQuantity(TechnologyRoutingOperation sourceOperation,
+ Map<String, BigDecimal> operationDemandedQuantityMap,
+ ProductionOrder productionOrder,
+ Long rootProductModelId) {
+ if (sourceOperation == null || operationDemandedQuantityMap == null || operationDemandedQuantityMap.isEmpty()) {
+ return defaultDecimal(productionOrder == null ? null : productionOrder.getQuantity());
+ }
+ Long outputProductModelId = sourceOperation.getProductModelId() != null
+ ? sourceOperation.getProductModelId()
+ : rootProductModelId;
+ String key = buildOperationDemandedQuantityKey(sourceOperation.getTechnologyOperationId(), outputProductModelId);
+ BigDecimal planQuantity = operationDemandedQuantityMap.get(key);
+ return planQuantity != null ? planQuantity : defaultDecimal(productionOrder == null ? null : productionOrder.getQuantity());
+ }
+
+ /**
+ * 璁$畻宸ュ崟璁″垝鏁伴噺锛堜娇鐢� ProductionOrderRoutingOperation锛�
+ */
+ public BigDecimal resolveTaskPlanQuantity(ProductionOrderRoutingOperation routingOperation,
+ Map<String, BigDecimal> demandedQuantityMap,
+ BigDecimal orderQuantity,
+ Long rootProductModelId) {
+ if (routingOperation == null || demandedQuantityMap == null || demandedQuantityMap.isEmpty()) {
+ return orderQuantity;
+ }
+ Long outputProductModelId = routingOperation.getProductModelId() != null
+ ? routingOperation.getProductModelId()
+ : rootProductModelId;
+ String key = buildOperationDemandedQuantityKey(routingOperation.getTechnologyOperationId(), outputProductModelId);
+ BigDecimal planQuantity = demandedQuantityMap.get(key);
+ return planQuantity != null ? planQuantity : orderQuantity;
+ }
+
+ /**
+ * 鏋勫缓宸ュ簭闇�姹傞噺鏄犲皠琛�
+ */
+ public Map<String, BigDecimal> buildOperationDemandedQuantityMap(List<ProductionBomStructure> bomStructures, Long rootProductModelId) {
+ if (bomStructures == null || bomStructures.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ Map<Long, ProductionBomStructure> structureById = new HashMap<>();
+ for (ProductionBomStructure item : bomStructures) {
+ if (item != null && item.getId() != null) {
+ structureById.put(item.getId(), item);
+ }
+ }
+ Map<String, BigDecimal> demandedQuantityMap = new HashMap<>();
+ Set<String> mergedOutputNodeKeySet = new HashSet<>();
+ for (ProductionBomStructure bomStructure : bomStructures) {
+ if (bomStructure == null || bomStructure.getTechnologyOperationId() == null) {
+ continue;
+ }
+ ProductionBomStructure outputNode = resolveOperationOutputNode(bomStructure, structureById);
+ Long outputProductModelId = resolveOutputProductModelId(outputNode, rootProductModelId);
+ if (outputProductModelId == null) {
+ continue;
+ }
+ String mergedOutputNodeKey = buildOperationOutputNodeKey(bomStructure.getTechnologyOperationId(),
+ outputNode == null ? null : outputNode.getId(), outputProductModelId);
+ if (!mergedOutputNodeKeySet.add(mergedOutputNodeKey)) {
+ continue;
+ }
+ BigDecimal demandedQuantity = defaultDecimal(outputNode == null ? null : outputNode.getDemandedQuantity());
+ String key = buildOperationDemandedQuantityKey(bomStructure.getTechnologyOperationId(), outputProductModelId);
+ demandedQuantityMap.merge(key, demandedQuantity, BigDecimal::add);
+ }
+ return demandedQuantityMap;
+ }
+
+ /**
+ * 鏋勫缓宸ュ簭闇�姹傞噺key
+ */
+ public String buildOperationDemandedQuantityKey(Long operationId, Long outputProductModelId) {
+ return String.valueOf(operationId) + "#" + String.valueOf(outputProductModelId);
+ }
+
+ /**
+ * 鏋勫缓杈撳嚭鑺傜偣key
+ */
+ public String buildOperationOutputNodeKey(Long operationId, Long outputNodeId, Long outputProductModelId) {
+ return String.valueOf(operationId) + "#" + String.valueOf(outputNodeId) + "#" + String.valueOf(outputProductModelId);
+ }
+
+ /**
+ * 瑙f瀽宸ュ簭杈撳嚭鑺傜偣
+ */
+ public ProductionBomStructure resolveOperationOutputNode(ProductionBomStructure bomStructure,
+ Map<Long, ProductionBomStructure> structureById) {
+ if (bomStructure == null) {
+ return null;
+ }
+ if (bomStructure.getParentId() == null) {
+ return bomStructure;
+ }
+ ProductionBomStructure parent = structureById.get(bomStructure.getParentId());
+ return parent != null ? parent : bomStructure;
+ }
+
+ /**
+ * 瑙f瀽杈撳嚭浜у搧瑙勬牸ID
+ */
+ public Long resolveOutputProductModelId(ProductionBomStructure outputNode, Long rootProductModelId) {
+ if (outputNode == null) {
+ return rootProductModelId;
+ }
+ return outputNode.getProductModelId() != null ? outputNode.getProductModelId() : rootProductModelId;
+ }
+
+ /**
+ * 榛樿BigDecimal鍊�
+ */
+ public BigDecimal defaultDecimal(BigDecimal value) {
+ return value == null ? BigDecimal.ZERO : value;
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/project/common/CaptchaController.java b/src/main/java/com/ruoyi/project/common/CaptchaController.java
index 40255cb..5966fb5 100644
--- a/src/main/java/com/ruoyi/project/common/CaptchaController.java
+++ b/src/main/java/com/ruoyi/project/common/CaptchaController.java
@@ -1,98 +1,98 @@
-package com.ruoyi.project.common;
-
-import com.google.code.kaptcha.Producer;
-import com.ruoyi.common.constant.CacheConstants;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.utils.sign.Base64;
-import com.ruoyi.common.utils.uuid.IdUtils;
-import com.ruoyi.framework.redis.RedisCache;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.project.system.service.ISysConfigService;
-import jakarta.annotation.Resource;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.RequiredArgsConstructor;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.util.FastByteArrayOutputStream;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.imageio.ImageIO;
-import java.awt.image.BufferedImage;
-import java.io.IOException;
-import java.util.concurrent.TimeUnit;
-
-/**
- * 楠岃瘉鐮佹搷浣滃鐞�
- *
- * @author ruoyi
- */
-@RestController
-@RequiredArgsConstructor
-public class CaptchaController
-{
- @Resource(name = "captchaProducer")
- private Producer captchaProducer;
-
- @Resource(name = "captchaProducerMath")
- private Producer captchaProducerMath;
-
- private final RedisCache redisCache;
-
- // 楠岃瘉鐮佺被鍨�
- @Value("${ruoyi.captchaType}")
- private String captchaType;
-
- private final ISysConfigService configService;
-
- /**
- * 鐢熸垚楠岃瘉鐮�
- */
- @GetMapping("/captchaImage")
- public AjaxResult getCode(HttpServletResponse response) throws IOException
- {
- AjaxResult ajax = AjaxResult.success();
- boolean captchaEnabled = configService.selectCaptchaEnabled();
- ajax.put("captchaEnabled", captchaEnabled);
- if (!captchaEnabled)
- {
- return ajax;
- }
-
- // 淇濆瓨楠岃瘉鐮佷俊鎭�
- String uuid = IdUtils.simpleUUID();
- String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
-
- String capStr = null, code = null;
- BufferedImage image = null;
-
- // 鐢熸垚楠岃瘉鐮�
- if ("math".equals(captchaType))
- {
- String capText = captchaProducerMath.createText();
- capStr = capText.substring(0, capText.lastIndexOf("@"));
- code = capText.substring(capText.lastIndexOf("@") + 1);
- image = captchaProducerMath.createImage(capStr);
- }
- else if ("char".equals(captchaType))
- {
- capStr = code = captchaProducer.createText();
- image = captchaProducer.createImage(capStr);
- }
-
- redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
- // 杞崲娴佷俊鎭啓鍑�
- FastByteArrayOutputStream os = new FastByteArrayOutputStream();
- try
- {
- ImageIO.write(image, "jpg", os);
- }
- catch (IOException e)
- {
- return AjaxResult.error(e.getMessage());
- }
-
- ajax.put("uuid", uuid);
- ajax.put("img", Base64.encode(os.toByteArray()));
- return ajax;
- }
-}
+package com.ruoyi.project.common;
+
+import com.google.code.kaptcha.Producer;
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.sign.Base64;
+import com.ruoyi.common.utils.uuid.IdUtils;
+import com.ruoyi.framework.redis.RedisCache;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.project.system.service.ISysConfigService;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.util.FastByteArrayOutputStream;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 楠岃瘉鐮佹搷浣滃鐞�
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequiredArgsConstructor
+public class CaptchaController
+{
+ @Resource(name = "captchaProducer")
+ private Producer captchaProducer;
+
+ @Resource(name = "captchaProducerMath")
+ private Producer captchaProducerMath;
+
+ private final RedisCache redisCache;
+
+ // 楠岃瘉鐮佺被鍨�
+ @Value("${ruoyi.captchaType}")
+ private String captchaType;
+
+ private final ISysConfigService configService;
+
+ /**
+ * 鐢熸垚楠岃瘉鐮�
+ */
+ @GetMapping("/captchaImage")
+ public AjaxResult getCode(HttpServletResponse response) throws IOException
+ {
+ AjaxResult ajax = AjaxResult.success();
+ boolean captchaEnabled = configService.selectCaptchaEnabled();
+ ajax.put("captchaEnabled", captchaEnabled);
+ if (!captchaEnabled)
+ {
+ return ajax;
+ }
+
+ // 淇濆瓨楠岃瘉鐮佷俊鎭�
+ String uuid = IdUtils.simpleUUID();
+ String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
+
+ String capStr = null, code = null;
+ BufferedImage image = null;
+
+ // 鐢熸垚楠岃瘉鐮�
+ if ("math".equals(captchaType))
+ {
+ String capText = captchaProducerMath.createText();
+ capStr = capText.substring(0, capText.lastIndexOf("@"));
+ code = capText.substring(capText.lastIndexOf("@") + 1);
+ image = captchaProducerMath.createImage(capStr);
+ }
+ else if ("char".equals(captchaType))
+ {
+ capStr = code = captchaProducer.createText();
+ image = captchaProducer.createImage(capStr);
+ }
+
+ redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
+ // 杞崲娴佷俊鎭啓鍑�
+ FastByteArrayOutputStream os = new FastByteArrayOutputStream();
+ try
+ {
+ ImageIO.write(image, "jpg", os);
+ }
+ catch (IOException e)
+ {
+ return AjaxResult.error(e.getMessage());
+ }
+
+ ajax.put("uuid", uuid);
+ ajax.put("img", Base64.encode(os.toByteArray()));
+ return ajax;
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/controller/CacheController.java b/src/main/java/com/ruoyi/project/monitor/controller/CacheController.java
index 63fe76b..ac29662 100644
--- a/src/main/java/com/ruoyi/project/monitor/controller/CacheController.java
+++ b/src/main/java/com/ruoyi/project/monitor/controller/CacheController.java
@@ -1,111 +1,111 @@
-package com.ruoyi.project.monitor.controller;
-
-import com.ruoyi.common.constant.CacheConstants;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.project.monitor.domain.SysCache;
-import lombok.AllArgsConstructor;
-import org.springframework.data.redis.core.RedisCallback;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.*;
-
-/**
- * 缂撳瓨鐩戞帶
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/monitor/cache")
-@AllArgsConstructor
-public class CacheController
-{
- private RedisTemplate<String, String> redisTemplate;
-
- private final static List<SysCache> caches = new ArrayList<SysCache>();
- {
- caches.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "鐢ㄦ埛淇℃伅"));
- caches.add(new SysCache(CacheConstants.SYS_CONFIG_KEY, "閰嶇疆淇℃伅"));
- caches.add(new SysCache(CacheConstants.SYS_DICT_KEY, "鏁版嵁瀛楀吀"));
- caches.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "楠岃瘉鐮�"));
- caches.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "闃查噸鎻愪氦"));
- caches.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "闄愭祦澶勭悊"));
- caches.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "瀵嗙爜閿欒娆℃暟"));
- }
-
- @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
- @GetMapping()
- public AjaxResult getInfo() throws Exception
- {
- Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info());
- Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
- Object dbSize = redisTemplate.execute((RedisCallback<Object>) connection -> connection.dbSize());
-
- Map<String, Object> result = new HashMap<>(3);
- result.put("info", info);
- result.put("dbSize", dbSize);
-
- List<Map<String, String>> pieList = new ArrayList<>();
- commandStats.stringPropertyNames().forEach(key -> {
- Map<String, String> data = new HashMap<>(2);
- String property = commandStats.getProperty(key);
- data.put("name", StringUtils.removeStart(key, "cmdstat_"));
- data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
- pieList.add(data);
- });
- result.put("commandStats", pieList);
- return AjaxResult.success(result);
- }
-
- @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
- @GetMapping("/getNames")
- public AjaxResult cache()
- {
- return AjaxResult.success(caches);
- }
-
- @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
- @GetMapping("/getKeys/{cacheName}")
- public AjaxResult getCacheKeys(@PathVariable String cacheName)
- {
- Set<String> cacheKeys = redisTemplate.keys(cacheName + "*");
- return AjaxResult.success(new TreeSet<>(cacheKeys));
- }
-
- @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
- @GetMapping("/getValue/{cacheName}/{cacheKey}")
- public AjaxResult getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey)
- {
- String cacheValue = redisTemplate.opsForValue().get(cacheKey);
- SysCache sysCache = new SysCache(cacheName, cacheKey, cacheValue);
- return AjaxResult.success(sysCache);
- }
-
- @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
- @DeleteMapping("/clearCacheName/{cacheName}")
- public AjaxResult clearCacheName(@PathVariable String cacheName)
- {
- Collection<String> cacheKeys = redisTemplate.keys(cacheName + "*");
- redisTemplate.delete(cacheKeys);
- return AjaxResult.success();
- }
-
- @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
- @DeleteMapping("/clearCacheKey/{cacheKey}")
- public AjaxResult clearCacheKey(@PathVariable String cacheKey)
- {
- redisTemplate.delete(cacheKey);
- return AjaxResult.success();
- }
-
- @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
- @DeleteMapping("/clearCacheAll")
- public AjaxResult clearCacheAll()
- {
- Collection<String> cacheKeys = redisTemplate.keys("*");
- redisTemplate.delete(cacheKeys);
- return AjaxResult.success();
- }
-}
+package com.ruoyi.project.monitor.controller;
+
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.project.monitor.domain.SysCache;
+import lombok.AllArgsConstructor;
+import org.springframework.data.redis.core.RedisCallback;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+
+/**
+ * 缂撳瓨鐩戞帶
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/cache")
+@AllArgsConstructor
+public class CacheController
+{
+ private RedisTemplate<String, String> redisTemplate;
+
+ private final static List<SysCache> caches = new ArrayList<SysCache>();
+ {
+ caches.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "鐢ㄦ埛淇℃伅"));
+ caches.add(new SysCache(CacheConstants.SYS_CONFIG_KEY, "閰嶇疆淇℃伅"));
+ caches.add(new SysCache(CacheConstants.SYS_DICT_KEY, "鏁版嵁瀛楀吀"));
+ caches.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "楠岃瘉鐮�"));
+ caches.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "闃查噸鎻愪氦"));
+ caches.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "闄愭祦澶勭悊"));
+ caches.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "瀵嗙爜閿欒娆℃暟"));
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+ @GetMapping()
+ public AjaxResult getInfo() throws Exception
+ {
+ Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info());
+ Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
+ Object dbSize = redisTemplate.execute((RedisCallback<Object>) connection -> connection.dbSize());
+
+ Map<String, Object> result = new HashMap<>(3);
+ result.put("info", info);
+ result.put("dbSize", dbSize);
+
+ List<Map<String, String>> pieList = new ArrayList<>();
+ commandStats.stringPropertyNames().forEach(key -> {
+ Map<String, String> data = new HashMap<>(2);
+ String property = commandStats.getProperty(key);
+ data.put("name", StringUtils.removeStart(key, "cmdstat_"));
+ data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
+ pieList.add(data);
+ });
+ result.put("commandStats", pieList);
+ return AjaxResult.success(result);
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+ @GetMapping("/getNames")
+ public AjaxResult cache()
+ {
+ return AjaxResult.success(caches);
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+ @GetMapping("/getKeys/{cacheName}")
+ public AjaxResult getCacheKeys(@PathVariable String cacheName)
+ {
+ Set<String> cacheKeys = redisTemplate.keys(cacheName + "*");
+ return AjaxResult.success(new TreeSet<>(cacheKeys));
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+ @GetMapping("/getValue/{cacheName}/{cacheKey}")
+ public AjaxResult getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey)
+ {
+ String cacheValue = redisTemplate.opsForValue().get(cacheKey);
+ SysCache sysCache = new SysCache(cacheName, cacheKey, cacheValue);
+ return AjaxResult.success(sysCache);
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+ @DeleteMapping("/clearCacheName/{cacheName}")
+ public AjaxResult clearCacheName(@PathVariable String cacheName)
+ {
+ Collection<String> cacheKeys = redisTemplate.keys(cacheName + "*");
+ redisTemplate.delete(cacheKeys);
+ return AjaxResult.success();
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+ @DeleteMapping("/clearCacheKey/{cacheKey}")
+ public AjaxResult clearCacheKey(@PathVariable String cacheKey)
+ {
+ redisTemplate.delete(cacheKey);
+ return AjaxResult.success();
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+ @DeleteMapping("/clearCacheAll")
+ public AjaxResult clearCacheAll()
+ {
+ Collection<String> cacheKeys = redisTemplate.keys("*");
+ redisTemplate.delete(cacheKeys);
+ return AjaxResult.success();
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/controller/ServerController.java b/src/main/java/com/ruoyi/project/monitor/controller/ServerController.java
index 9a50b05..e1f55f1 100644
--- a/src/main/java/com/ruoyi/project/monitor/controller/ServerController.java
+++ b/src/main/java/com/ruoyi/project/monitor/controller/ServerController.java
@@ -1,27 +1,27 @@
-package com.ruoyi.project.monitor.controller;
-
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.domain.Server;
-
-/**
- * 鏈嶅姟鍣ㄧ洃鎺�
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/monitor/server")
-public class ServerController
-{
- @PreAuthorize("@ss.hasPermi('monitor:server:list')")
- @GetMapping()
- public AjaxResult getInfo() throws Exception
- {
- Server server = new Server();
- server.copyTo();
- return AjaxResult.success(server);
- }
-}
+package com.ruoyi.project.monitor.controller;
+
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.domain.Server;
+
+/**
+ * 鏈嶅姟鍣ㄧ洃鎺�
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/server")
+public class ServerController
+{
+ @PreAuthorize("@ss.hasPermi('monitor:server:list')")
+ @GetMapping()
+ public AjaxResult getInfo() throws Exception
+ {
+ Server server = new Server();
+ server.copyTo();
+ return AjaxResult.success(server);
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/controller/SysJobController.java b/src/main/java/com/ruoyi/project/monitor/controller/SysJobController.java
index ee2c058..7abc9bd 100644
--- a/src/main/java/com/ruoyi/project/monitor/controller/SysJobController.java
+++ b/src/main/java/com/ruoyi/project/monitor/controller/SysJobController.java
@@ -1,186 +1,186 @@
-package com.ruoyi.project.monitor.controller;
-
-import java.util.List;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AllArgsConstructor;
-import org.quartz.SchedulerException;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.exception.job.TaskException;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.job.CronUtils;
-import com.ruoyi.common.utils.job.ScheduleUtils;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.project.monitor.domain.SysJob;
-import com.ruoyi.project.monitor.service.ISysJobService;
-
-/**
- * 璋冨害浠诲姟淇℃伅鎿嶄綔澶勭悊
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/monitor/job")
-@AllArgsConstructor
-public class SysJobController extends BaseController
-{
- private ISysJobService jobService;
-
- /**
- * 鏌ヨ瀹氭椂浠诲姟鍒楄〃
- */
- @PreAuthorize("@ss.hasPermi('monitor:job:list')")
- @GetMapping("/list")
- public TableDataInfo list(SysJob sysJob)
- {
- startPage();
- List<SysJob> list = jobService.selectJobList(sysJob);
- return getDataTable(list);
- }
-
- /**
- * 瀵煎嚭瀹氭椂浠诲姟鍒楄〃
- */
- @PreAuthorize("@ss.hasPermi('monitor:job:export')")
- @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.EXPORT)
- @PostMapping("/export")
- public void export(HttpServletResponse response, SysJob sysJob)
- {
- List<SysJob> list = jobService.selectJobList(sysJob);
- ExcelUtil<SysJob> util = new ExcelUtil<SysJob>(SysJob.class);
- util.exportExcel(response, list, "瀹氭椂浠诲姟");
- }
-
- /**
- * 鑾峰彇瀹氭椂浠诲姟璇︾粏淇℃伅
- */
- @PreAuthorize("@ss.hasPermi('monitor:job:query')")
- @GetMapping(value = "/{jobId}")
- public AjaxResult getInfo(@PathVariable("jobId") Long jobId)
- {
- return success(jobService.selectJobById(jobId));
- }
-
- /**
- * 鏂板瀹氭椂浠诲姟
- */
- @PreAuthorize("@ss.hasPermi('monitor:job:add')")
- @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.INSERT)
- @PostMapping
- public AjaxResult add(@RequestBody SysJob job) throws SchedulerException, TaskException
- {
- if (!CronUtils.isValid(job.getCronExpression()))
- {
- return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛孋ron琛ㄨ揪寮忎笉姝g‘");
- }
- else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
- {
- return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'rmi'璋冪敤");
- }
- else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS }))
- {
- return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'ldap(s)'璋冪敤");
- }
- else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
- {
- return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'http(s)'璋冪敤");
- }
- else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
- {
- return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆瀛樺湪杩濊");
- }
- else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
- {
- return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅湪鐧藉悕鍗曞唴");
- }
- job.setCreateBy(getUsername());
- return toAjax(jobService.insertJob(job));
- }
-
- /**
- * 淇敼瀹氭椂浠诲姟
- */
- @PreAuthorize("@ss.hasPermi('monitor:job:edit')")
- @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
- @PutMapping
- public AjaxResult edit(@RequestBody SysJob job) throws SchedulerException, TaskException
- {
- if (!CronUtils.isValid(job.getCronExpression()))
- {
- return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛孋ron琛ㄨ揪寮忎笉姝g‘");
- }
- else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
- {
- return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'rmi'璋冪敤");
- }
- else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS }))
- {
- return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'ldap(s)'璋冪敤");
- }
- else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
- {
- return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'http(s)'璋冪敤");
- }
- else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
- {
- return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆瀛樺湪杩濊");
- }
- else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
- {
- return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅湪鐧藉悕鍗曞唴");
- }
- job.setUpdateBy(getUsername());
- return toAjax(jobService.updateJob(job));
- }
-
- /**
- * 瀹氭椂浠诲姟鐘舵�佷慨鏀�
- */
- @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
- @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
- @PutMapping("/changeStatus")
- public AjaxResult changeStatus(@RequestBody SysJob job) throws SchedulerException
- {
- SysJob newJob = jobService.selectJobById(job.getJobId());
- newJob.setStatus(job.getStatus());
- return toAjax(jobService.changeStatus(newJob));
- }
-
- /**
- * 瀹氭椂浠诲姟绔嬪嵆鎵ц涓�娆�
- */
- @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
- @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
- @PutMapping("/run")
- public AjaxResult run(@RequestBody SysJob job) throws SchedulerException
- {
- boolean result = jobService.run(job);
- return result ? success() : error("浠诲姟涓嶅瓨鍦ㄦ垨宸茶繃鏈燂紒");
- }
-
- /**
- * 鍒犻櫎瀹氭椂浠诲姟
- */
- @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
- @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.DELETE)
- @DeleteMapping("/{jobIds}")
- public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException
- {
- jobService.deleteJobByIds(jobIds);
- return success();
- }
-}
+package com.ruoyi.project.monitor.controller;
+
+import java.util.List;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.exception.job.TaskException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.job.CronUtils;
+import com.ruoyi.common.utils.job.ScheduleUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.monitor.domain.SysJob;
+import com.ruoyi.project.monitor.service.ISysJobService;
+
+/**
+ * 璋冨害浠诲姟淇℃伅鎿嶄綔澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/job")
+@AllArgsConstructor
+public class SysJobController extends BaseController
+{
+ private ISysJobService jobService;
+
+ /**
+ * 鏌ヨ瀹氭椂浠诲姟鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysJob sysJob)
+ {
+ startPage();
+ List<SysJob> list = jobService.selectJobList(sysJob);
+ return getDataTable(list);
+ }
+
+ /**
+ * 瀵煎嚭瀹氭椂浠诲姟鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:export')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysJob sysJob)
+ {
+ List<SysJob> list = jobService.selectJobList(sysJob);
+ ExcelUtil<SysJob> util = new ExcelUtil<SysJob>(SysJob.class);
+ util.exportExcel(response, list, "瀹氭椂浠诲姟");
+ }
+
+ /**
+ * 鑾峰彇瀹氭椂浠诲姟璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:query')")
+ @GetMapping(value = "/{jobId}")
+ public AjaxResult getInfo(@PathVariable("jobId") Long jobId)
+ {
+ return success(jobService.selectJobById(jobId));
+ }
+
+ /**
+ * 鏂板瀹氭椂浠诲姟
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:add')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@RequestBody SysJob job) throws SchedulerException, TaskException
+ {
+ if (!CronUtils.isValid(job.getCronExpression()))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛孋ron琛ㄨ揪寮忎笉姝g‘");
+ }
+ else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'rmi'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS }))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'ldap(s)'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'http(s)'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆瀛樺湪杩濊");
+ }
+ else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅湪鐧藉悕鍗曞唴");
+ }
+ job.setCreateBy(getUsername());
+ return toAjax(jobService.insertJob(job));
+ }
+
+ /**
+ * 淇敼瀹氭椂浠诲姟
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:edit')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@RequestBody SysJob job) throws SchedulerException, TaskException
+ {
+ if (!CronUtils.isValid(job.getCronExpression()))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛孋ron琛ㄨ揪寮忎笉姝g‘");
+ }
+ else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'rmi'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS }))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'ldap(s)'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'http(s)'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆瀛樺湪杩濊");
+ }
+ else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅湪鐧藉悕鍗曞唴");
+ }
+ job.setUpdateBy(getUsername());
+ return toAjax(jobService.updateJob(job));
+ }
+
+ /**
+ * 瀹氭椂浠诲姟鐘舵�佷慨鏀�
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
+ @PutMapping("/changeStatus")
+ public AjaxResult changeStatus(@RequestBody SysJob job) throws SchedulerException
+ {
+ SysJob newJob = jobService.selectJobById(job.getJobId());
+ newJob.setStatus(job.getStatus());
+ return toAjax(jobService.changeStatus(newJob));
+ }
+
+ /**
+ * 瀹氭椂浠诲姟绔嬪嵆鎵ц涓�娆�
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
+ @PutMapping("/run")
+ public AjaxResult run(@RequestBody SysJob job) throws SchedulerException
+ {
+ boolean result = jobService.run(job);
+ return result ? success() : error("浠诲姟涓嶅瓨鍦ㄦ垨宸茶繃鏈燂紒");
+ }
+
+ /**
+ * 鍒犻櫎瀹氭椂浠诲姟
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{jobIds}")
+ public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException
+ {
+ jobService.deleteJobByIds(jobIds);
+ return success();
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/controller/SysJobLogController.java b/src/main/java/com/ruoyi/project/monitor/controller/SysJobLogController.java
index 0c29d22..9ed3059 100644
--- a/src/main/java/com/ruoyi/project/monitor/controller/SysJobLogController.java
+++ b/src/main/java/com/ruoyi/project/monitor/controller/SysJobLogController.java
@@ -1,93 +1,93 @@
-package com.ruoyi.project.monitor.controller;
-
-import java.util.List;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.project.monitor.domain.SysJobLog;
-import com.ruoyi.project.monitor.service.ISysJobLogService;
-
-/**
- * 璋冨害鏃ュ織鎿嶄綔澶勭悊
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/monitor/jobLog")
-@AllArgsConstructor
-public class SysJobLogController extends BaseController
-{
- private ISysJobLogService jobLogService;
-
- /**
- * 鏌ヨ瀹氭椂浠诲姟璋冨害鏃ュ織鍒楄〃
- */
- @PreAuthorize("@ss.hasPermi('monitor:job:list')")
- @GetMapping("/list")
- public TableDataInfo list(SysJobLog sysJobLog)
- {
- startPage();
- List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);
- return getDataTable(list);
- }
-
- /**
- * 瀵煎嚭瀹氭椂浠诲姟璋冨害鏃ュ織鍒楄〃
- */
- @PreAuthorize("@ss.hasPermi('monitor:job:export')")
- @Log(title = "浠诲姟璋冨害鏃ュ織", businessType = BusinessType.EXPORT)
- @PostMapping("/export")
- public void export(HttpServletResponse response, SysJobLog sysJobLog)
- {
- List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);
- ExcelUtil<SysJobLog> util = new ExcelUtil<SysJobLog>(SysJobLog.class);
- util.exportExcel(response, list, "璋冨害鏃ュ織");
- }
-
- /**
- * 鏍规嵁璋冨害缂栧彿鑾峰彇璇︾粏淇℃伅
- */
- @PreAuthorize("@ss.hasPermi('monitor:job:query')")
- @GetMapping(value = "/{jobLogId}")
- public AjaxResult getInfo(@PathVariable Long jobLogId)
- {
- return success(jobLogService.selectJobLogById(jobLogId));
- }
-
-
- /**
- * 鍒犻櫎瀹氭椂浠诲姟璋冨害鏃ュ織
- */
- @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
- @Log(title = "瀹氭椂浠诲姟璋冨害鏃ュ織", businessType = BusinessType.DELETE)
- @DeleteMapping("/{jobLogIds}")
- public AjaxResult remove(@PathVariable Long[] jobLogIds)
- {
- return toAjax(jobLogService.deleteJobLogByIds(jobLogIds));
- }
-
- /**
- * 娓呯┖瀹氭椂浠诲姟璋冨害鏃ュ織
- */
- @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
- @Log(title = "璋冨害鏃ュ織", businessType = BusinessType.CLEAN)
- @DeleteMapping("/clean")
- public AjaxResult clean()
- {
- jobLogService.cleanJobLog();
- return success();
- }
-}
+package com.ruoyi.project.monitor.controller;
+
+import java.util.List;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.monitor.domain.SysJobLog;
+import com.ruoyi.project.monitor.service.ISysJobLogService;
+
+/**
+ * 璋冨害鏃ュ織鎿嶄綔澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/jobLog")
+@AllArgsConstructor
+public class SysJobLogController extends BaseController
+{
+ private ISysJobLogService jobLogService;
+
+ /**
+ * 鏌ヨ瀹氭椂浠诲姟璋冨害鏃ュ織鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysJobLog sysJobLog)
+ {
+ startPage();
+ List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);
+ return getDataTable(list);
+ }
+
+ /**
+ * 瀵煎嚭瀹氭椂浠诲姟璋冨害鏃ュ織鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:export')")
+ @Log(title = "浠诲姟璋冨害鏃ュ織", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysJobLog sysJobLog)
+ {
+ List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);
+ ExcelUtil<SysJobLog> util = new ExcelUtil<SysJobLog>(SysJobLog.class);
+ util.exportExcel(response, list, "璋冨害鏃ュ織");
+ }
+
+ /**
+ * 鏍规嵁璋冨害缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:query')")
+ @GetMapping(value = "/{jobLogId}")
+ public AjaxResult getInfo(@PathVariable Long jobLogId)
+ {
+ return success(jobLogService.selectJobLogById(jobLogId));
+ }
+
+
+ /**
+ * 鍒犻櫎瀹氭椂浠诲姟璋冨害鏃ュ織
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
+ @Log(title = "瀹氭椂浠诲姟璋冨害鏃ュ織", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{jobLogIds}")
+ public AjaxResult remove(@PathVariable Long[] jobLogIds)
+ {
+ return toAjax(jobLogService.deleteJobLogByIds(jobLogIds));
+ }
+
+ /**
+ * 娓呯┖瀹氭椂浠诲姟璋冨害鏃ュ織
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
+ @Log(title = "璋冨害鏃ュ織", businessType = BusinessType.CLEAN)
+ @DeleteMapping("/clean")
+ public AjaxResult clean()
+ {
+ jobLogService.cleanJobLog();
+ return success();
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/controller/SysLogininforController.java b/src/main/java/com/ruoyi/project/monitor/controller/SysLogininforController.java
index 7f5085d..0c96a9d 100644
--- a/src/main/java/com/ruoyi/project/monitor/controller/SysLogininforController.java
+++ b/src/main/java/com/ruoyi/project/monitor/controller/SysLogininforController.java
@@ -1,70 +1,70 @@
-package com.ruoyi.project.monitor.controller;
-
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.security.service.SysPasswordService;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.project.monitor.domain.SysLogininfor;
-import com.ruoyi.project.monitor.service.ISysLogininforService;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AllArgsConstructor;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 绯荤粺璁块棶璁板綍
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/monitor/logininfor")
-@AllArgsConstructor
-public class SysLogininforController extends BaseController {
- private ISysLogininforService logininforService;
- private SysPasswordService passwordService;
-
- @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')")
- @GetMapping("/list")
- public TableDataInfo list(SysLogininfor logininfor) {
- startPage();
- List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
- return getDataTable(list);
- }
-
- @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.EXPORT)
- @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
- @PostMapping("/export")
- public void export(HttpServletResponse response, SysLogininfor logininfor) {
- List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
- ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
- util.exportExcel(response, list, "鐧诲綍鏃ュ織");
- }
-
- @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
- @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.DELETE)
- @DeleteMapping("/{infoIds}")
- public AjaxResult remove(@PathVariable Long[] infoIds) {
- return toAjax(logininforService.deleteLogininforByIds(infoIds));
- }
-
- @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
- @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.CLEAN)
- @DeleteMapping("/clean")
- public AjaxResult clean() {
- logininforService.cleanLogininfor();
- return success();
- }
-
- @PreAuthorize("@ss.hasPermi('monitor:logininfor:unlock')")
- @Log(title = "璐︽埛瑙i攣", businessType = BusinessType.OTHER)
- @GetMapping("/unlock/{userName}")
- public AjaxResult unlock(@PathVariable("userName") String userName) {
- passwordService.clearLoginRecordCache(userName);
- return success();
- }
-}
+package com.ruoyi.project.monitor.controller;
+
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.security.service.SysPasswordService;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.monitor.domain.SysLogininfor;
+import com.ruoyi.project.monitor.service.ISysLogininforService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 绯荤粺璁块棶璁板綍
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/logininfor")
+@AllArgsConstructor
+public class SysLogininforController extends BaseController {
+ private ISysLogininforService logininforService;
+ private SysPasswordService passwordService;
+
+ @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysLogininfor logininfor) {
+ startPage();
+ List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
+ return getDataTable(list);
+ }
+
+ @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysLogininfor logininfor) {
+ List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
+ ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
+ util.exportExcel(response, list, "鐧诲綍鏃ュ織");
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
+ @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{infoIds}")
+ public AjaxResult remove(@PathVariable Long[] infoIds) {
+ return toAjax(logininforService.deleteLogininforByIds(infoIds));
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
+ @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.CLEAN)
+ @DeleteMapping("/clean")
+ public AjaxResult clean() {
+ logininforService.cleanLogininfor();
+ return success();
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:logininfor:unlock')")
+ @Log(title = "璐︽埛瑙i攣", businessType = BusinessType.OTHER)
+ @GetMapping("/unlock/{userName}")
+ public AjaxResult unlock(@PathVariable("userName") String userName) {
+ passwordService.clearLoginRecordCache(userName);
+ return success();
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/controller/SysOperlogController.java b/src/main/java/com/ruoyi/project/monitor/controller/SysOperlogController.java
index 81bab02..091a5a6 100644
--- a/src/main/java/com/ruoyi/project/monitor/controller/SysOperlogController.java
+++ b/src/main/java/com/ruoyi/project/monitor/controller/SysOperlogController.java
@@ -1,70 +1,70 @@
-package com.ruoyi.project.monitor.controller;
-
-import java.util.List;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.project.monitor.domain.SysOperLog;
-import com.ruoyi.project.monitor.service.ISysOperLogService;
-
-/**
- * 鎿嶄綔鏃ュ織璁板綍
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/monitor/operlog")
-@AllArgsConstructor
-public class SysOperlogController extends BaseController
-{
- private ISysOperLogService operLogService;
-
- @PreAuthorize("@ss.hasPermi('monitor:operlog:list')")
- @GetMapping("/list")
- public TableDataInfo list(SysOperLog operLog)
- {
- startPage();
- List<SysOperLog> list = operLogService.selectOperLogList(operLog);
- return getDataTable(list);
- }
-
- @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.EXPORT)
- @PreAuthorize("@ss.hasPermi('monitor:operlog:export')")
- @PostMapping("/export")
- public void export(HttpServletResponse response, SysOperLog operLog)
- {
- List<SysOperLog> list = operLogService.selectOperLogList(operLog);
- ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
- util.exportExcel(response, list, "鎿嶄綔鏃ュ織");
- }
-
- @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.DELETE)
- @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
- @DeleteMapping("/{operIds}")
- public AjaxResult remove(@PathVariable Long[] operIds)
- {
- return toAjax(operLogService.deleteOperLogByIds(operIds));
- }
-
- @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.CLEAN)
- @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
- @DeleteMapping("/clean")
- public AjaxResult clean()
- {
- operLogService.cleanOperLog();
- return success();
- }
-}
+package com.ruoyi.project.monitor.controller;
+
+import java.util.List;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.monitor.domain.SysOperLog;
+import com.ruoyi.project.monitor.service.ISysOperLogService;
+
+/**
+ * 鎿嶄綔鏃ュ織璁板綍
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/operlog")
+@AllArgsConstructor
+public class SysOperlogController extends BaseController
+{
+ private ISysOperLogService operLogService;
+
+ @PreAuthorize("@ss.hasPermi('monitor:operlog:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysOperLog operLog)
+ {
+ startPage();
+ List<SysOperLog> list = operLogService.selectOperLogList(operLog);
+ return getDataTable(list);
+ }
+
+ @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('monitor:operlog:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysOperLog operLog)
+ {
+ List<SysOperLog> list = operLogService.selectOperLogList(operLog);
+ ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
+ util.exportExcel(response, list, "鎿嶄綔鏃ュ織");
+ }
+
+ @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.DELETE)
+ @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
+ @DeleteMapping("/{operIds}")
+ public AjaxResult remove(@PathVariable Long[] operIds)
+ {
+ return toAjax(operLogService.deleteOperLogByIds(operIds));
+ }
+
+ @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.CLEAN)
+ @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
+ @DeleteMapping("/clean")
+ public AjaxResult clean()
+ {
+ operLogService.cleanOperLog();
+ return success();
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/controller/SysUserOnlineController.java b/src/main/java/com/ruoyi/project/monitor/controller/SysUserOnlineController.java
index aa8c824..944656b 100644
--- a/src/main/java/com/ruoyi/project/monitor/controller/SysUserOnlineController.java
+++ b/src/main/java/com/ruoyi/project/monitor/controller/SysUserOnlineController.java
@@ -1,83 +1,83 @@
-package com.ruoyi.project.monitor.controller;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.ruoyi.common.constant.CacheConstants;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.redis.RedisCache;
-import com.ruoyi.framework.security.LoginUser;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.project.monitor.domain.SysUserOnline;
-import com.ruoyi.project.system.service.ISysUserOnlineService;
-
-/**
- * 鍦ㄧ嚎鐢ㄦ埛鐩戞帶
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/monitor/online")
-@AllArgsConstructor
-public class SysUserOnlineController extends BaseController
-{
- private ISysUserOnlineService userOnlineService;
- private RedisCache redisCache;
-
- @PreAuthorize("@ss.hasPermi('monitor:online:list')")
- @GetMapping("/list")
- public TableDataInfo list(String ipaddr, String userName)
- {
- Collection<String> keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
- List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
- for (String key : keys)
- {
- LoginUser user = redisCache.getCacheObject(key);
- if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
- {
- userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
- }
- else if (StringUtils.isNotEmpty(ipaddr))
- {
- userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
- }
- else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser()))
- {
- userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
- }
- else
- {
- userOnlineList.add(userOnlineService.loginUserToUserOnline(user));
- }
- }
- Collections.reverse(userOnlineList);
- userOnlineList.removeAll(Collections.singleton(null));
- return getDataTable(userOnlineList);
- }
-
- /**
- * 寮洪��鐢ㄦ埛
- */
- @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
- @Log(title = "鍦ㄧ嚎鐢ㄦ埛", businessType = BusinessType.FORCE)
- @DeleteMapping("/{tokenId}")
- public AjaxResult forceLogout(@PathVariable String tokenId)
- {
- redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId);
- return success();
- }
-}
+package com.ruoyi.project.monitor.controller;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.redis.RedisCache;
+import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.monitor.domain.SysUserOnline;
+import com.ruoyi.project.system.service.ISysUserOnlineService;
+
+/**
+ * 鍦ㄧ嚎鐢ㄦ埛鐩戞帶
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/online")
+@AllArgsConstructor
+public class SysUserOnlineController extends BaseController
+{
+ private ISysUserOnlineService userOnlineService;
+ private RedisCache redisCache;
+
+ @PreAuthorize("@ss.hasPermi('monitor:online:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(String ipaddr, String userName)
+ {
+ Collection<String> keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
+ List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
+ for (String key : keys)
+ {
+ LoginUser user = redisCache.getCacheObject(key);
+ if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
+ {
+ userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
+ }
+ else if (StringUtils.isNotEmpty(ipaddr))
+ {
+ userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
+ }
+ else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser()))
+ {
+ userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
+ }
+ else
+ {
+ userOnlineList.add(userOnlineService.loginUserToUserOnline(user));
+ }
+ }
+ Collections.reverse(userOnlineList);
+ userOnlineList.removeAll(Collections.singleton(null));
+ return getDataTable(userOnlineList);
+ }
+
+ /**
+ * 寮洪��鐢ㄦ埛
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
+ @Log(title = "鍦ㄧ嚎鐢ㄦ埛", businessType = BusinessType.FORCE)
+ @DeleteMapping("/{tokenId}")
+ public AjaxResult forceLogout(@PathVariable String tokenId)
+ {
+ redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId);
+ return success();
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java b/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java
index a10687b..e73d60e 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java
@@ -1,127 +1,127 @@
-package com.ruoyi.project.system.controller;
-
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.project.system.domain.SysConfig;
-import com.ruoyi.project.system.service.ISysConfigService;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AllArgsConstructor;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 鍙傛暟閰嶇疆 淇℃伅鎿嶄綔澶勭悊
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/system/config")
-@AllArgsConstructor
-public class SysConfigController extends BaseController
-{
- private ISysConfigService configService;
-
- /**
- * 鑾峰彇鍙傛暟閰嶇疆鍒楄〃
- */
- @PreAuthorize("@ss.hasPermi('system:config:list')")
- @GetMapping("/list")
- public TableDataInfo list(SysConfig config)
- {
- startPage();
- List<SysConfig> list = configService.selectConfigList(config);
- return getDataTable(list);
- }
-
- @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.EXPORT)
- @PreAuthorize("@ss.hasPermi('system:config:export')")
- @PostMapping("/export")
- public void export(HttpServletResponse response, SysConfig config)
- {
- List<SysConfig> list = configService.selectConfigList(config);
- ExcelUtil<SysConfig> util = new ExcelUtil<SysConfig>(SysConfig.class);
- util.exportExcel(response, list, "鍙傛暟鏁版嵁");
- }
-
- /**
- * 鏍规嵁鍙傛暟缂栧彿鑾峰彇璇︾粏淇℃伅
- */
- @PreAuthorize("@ss.hasPermi('system:config:query')")
- @GetMapping(value = "/{configId}")
- public AjaxResult getInfo(@PathVariable Long configId)
- {
- return success(configService.selectConfigById(configId));
- }
-
- /**
- * 鏍规嵁鍙傛暟閿悕鏌ヨ鍙傛暟鍊�
- */
- @GetMapping(value = "/configKey/{configKey}")
- public AjaxResult getConfigKey(@PathVariable String configKey)
- {
- return success(configService.selectConfigByKey(configKey));
- }
-
- /**
- * 鏂板鍙傛暟閰嶇疆
- */
- @PreAuthorize("@ss.hasPermi('system:config:add')")
- @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.INSERT)
- @PostMapping
- public AjaxResult add(@Validated @RequestBody SysConfig config)
- {
- if (!configService.checkConfigKeyUnique(config))
- {
- return error("鏂板鍙傛暟'" + config.getConfigName() + "'澶辫触锛屽弬鏁伴敭鍚嶅凡瀛樺湪");
- }
- config.setCreateBy(getUsername());
- return toAjax(configService.insertConfig(config));
- }
-
- /**
- * 淇敼鍙傛暟閰嶇疆
- */
- @PreAuthorize("@ss.hasPermi('system:config:edit')")
- @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.UPDATE)
- @PutMapping
- public AjaxResult edit(@Validated @RequestBody SysConfig config)
- {
- if (!configService.checkConfigKeyUnique(config))
- {
- return error("淇敼鍙傛暟'" + config.getConfigName() + "'澶辫触锛屽弬鏁伴敭鍚嶅凡瀛樺湪");
- }
- config.setUpdateBy(getUsername());
- return toAjax(configService.updateConfig(config));
- }
-
- /**
- * 鍒犻櫎鍙傛暟閰嶇疆
- */
- @PreAuthorize("@ss.hasPermi('system:config:remove')")
- @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.DELETE)
- @DeleteMapping("/{configIds}")
- public AjaxResult remove(@PathVariable Long[] configIds)
- {
- configService.deleteConfigByIds(configIds);
- return success();
- }
-
- /**
- * 鍒锋柊鍙傛暟缂撳瓨
- */
- @PreAuthorize("@ss.hasPermi('system:config:remove')")
- @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.CLEAN)
- @DeleteMapping("/refreshCache")
- public AjaxResult refreshCache()
- {
- configService.resetConfigCache();
- return success();
- }
-}
+package com.ruoyi.project.system.controller;
+
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.system.domain.SysConfig;
+import com.ruoyi.project.system.service.ISysConfigService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 鍙傛暟閰嶇疆 淇℃伅鎿嶄綔澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/config")
+@AllArgsConstructor
+public class SysConfigController extends BaseController
+{
+ private ISysConfigService configService;
+
+ /**
+ * 鑾峰彇鍙傛暟閰嶇疆鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('system:config:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysConfig config)
+ {
+ startPage();
+ List<SysConfig> list = configService.selectConfigList(config);
+ return getDataTable(list);
+ }
+
+ @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('system:config:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysConfig config)
+ {
+ List<SysConfig> list = configService.selectConfigList(config);
+ ExcelUtil<SysConfig> util = new ExcelUtil<SysConfig>(SysConfig.class);
+ util.exportExcel(response, list, "鍙傛暟鏁版嵁");
+ }
+
+ /**
+ * 鏍规嵁鍙傛暟缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('system:config:query')")
+ @GetMapping(value = "/{configId}")
+ public AjaxResult getInfo(@PathVariable Long configId)
+ {
+ return success(configService.selectConfigById(configId));
+ }
+
+ /**
+ * 鏍规嵁鍙傛暟閿悕鏌ヨ鍙傛暟鍊�
+ */
+ @GetMapping(value = "/configKey/{configKey}")
+ public AjaxResult getConfigKey(@PathVariable String configKey)
+ {
+ return success(configService.selectConfigByKey(configKey));
+ }
+
+ /**
+ * 鏂板鍙傛暟閰嶇疆
+ */
+ @PreAuthorize("@ss.hasPermi('system:config:add')")
+ @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysConfig config)
+ {
+ if (!configService.checkConfigKeyUnique(config))
+ {
+ return error("鏂板鍙傛暟'" + config.getConfigName() + "'澶辫触锛屽弬鏁伴敭鍚嶅凡瀛樺湪");
+ }
+ config.setCreateBy(getUsername());
+ return toAjax(configService.insertConfig(config));
+ }
+
+ /**
+ * 淇敼鍙傛暟閰嶇疆
+ */
+ @PreAuthorize("@ss.hasPermi('system:config:edit')")
+ @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysConfig config)
+ {
+ if (!configService.checkConfigKeyUnique(config))
+ {
+ return error("淇敼鍙傛暟'" + config.getConfigName() + "'澶辫触锛屽弬鏁伴敭鍚嶅凡瀛樺湪");
+ }
+ config.setUpdateBy(getUsername());
+ return toAjax(configService.updateConfig(config));
+ }
+
+ /**
+ * 鍒犻櫎鍙傛暟閰嶇疆
+ */
+ @PreAuthorize("@ss.hasPermi('system:config:remove')")
+ @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{configIds}")
+ public AjaxResult remove(@PathVariable Long[] configIds)
+ {
+ configService.deleteConfigByIds(configIds);
+ return success();
+ }
+
+ /**
+ * 鍒锋柊鍙傛暟缂撳瓨
+ */
+ @PreAuthorize("@ss.hasPermi('system:config:remove')")
+ @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.CLEAN)
+ @DeleteMapping("/refreshCache")
+ public AjaxResult refreshCache()
+ {
+ configService.resetConfigCache();
+ return success();
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java b/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java
index f61e42f..24e6c71 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java
@@ -1,134 +1,134 @@
-package com.ruoyi.project.system.controller;
-
-import java.util.List;
-
-import lombok.AllArgsConstructor;
-import org.apache.commons.lang3.ArrayUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.project.system.domain.SysDept;
-import com.ruoyi.project.system.service.ISysDeptService;
-
-/**
- * 閮ㄩ棬淇℃伅
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/system/dept")
-@AllArgsConstructor
-public class SysDeptController extends BaseController
-{
- private ISysDeptService deptService;
-
- /**
- * 鑾峰彇閮ㄩ棬鍒楄〃
- */
- @PreAuthorize("@ss.hasPermi('system:dept:list')")
- @GetMapping("/list")
- public AjaxResult list(SysDept dept)
- {
- List<SysDept> depts = deptService.selectDeptList(dept);
- return success(depts);
- }
-
- /**
- * 鏌ヨ閮ㄩ棬鍒楄〃锛堟帓闄よ妭鐐癸級
- */
- @PreAuthorize("@ss.hasPermi('system:dept:list')")
- @GetMapping("/list/exclude/{deptId}")
- public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId)
- {
- List<SysDept> depts = deptService.selectDeptList(new SysDept());
- depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
- return success(depts);
- }
-
- /**
- * 鏍规嵁閮ㄩ棬缂栧彿鑾峰彇璇︾粏淇℃伅
- */
- @PreAuthorize("@ss.hasPermi('system:dept:query')")
- @GetMapping(value = "/{deptId}")
- public AjaxResult getInfo(@PathVariable Long deptId)
- {
- deptService.checkDeptDataScope(deptId);
- return success(deptService.selectDeptById(deptId));
- }
-
- /**
- * 鏂板閮ㄩ棬
- */
- @PreAuthorize("@ss.hasPermi('system:dept:add')")
- @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.INSERT)
- @PostMapping
- public AjaxResult add(@Validated @RequestBody SysDept dept)
- {
- if (!deptService.checkDeptNameUnique(dept))
- {
- return error("鏂板閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛岄儴闂ㄥ悕绉板凡瀛樺湪");
- }
- dept.setCreateBy(getUsername());
- return toAjax(deptService.insertDept(dept));
- }
-
- /**
- * 淇敼閮ㄩ棬
- */
- @PreAuthorize("@ss.hasPermi('system:dept:edit')")
- @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.UPDATE)
- @PutMapping
- public AjaxResult edit(@Validated @RequestBody SysDept dept)
- {
- Long deptId = dept.getDeptId();
- deptService.checkDeptDataScope(deptId);
- if (!deptService.checkDeptNameUnique(dept))
- {
- return error("淇敼閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛岄儴闂ㄥ悕绉板凡瀛樺湪");
- }
- else if (dept.getParentId().equals(deptId))
- {
- return error("淇敼閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛屼笂绾ч儴闂ㄤ笉鑳芥槸鑷繁");
- }
- else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0)
- {
- return error("璇ラ儴闂ㄥ寘鍚湭鍋滅敤鐨勫瓙閮ㄩ棬锛�");
- }
- dept.setUpdateBy(getUsername());
- return toAjax(deptService.updateDept(dept));
- }
-
- /**
- * 鍒犻櫎閮ㄩ棬
- */
- @PreAuthorize("@ss.hasPermi('system:dept:remove')")
- @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.DELETE)
- @DeleteMapping("/{deptId}")
- public AjaxResult remove(@PathVariable Long deptId)
- {
- if (deptService.hasChildByDeptId(deptId))
- {
- return warn("瀛樺湪涓嬬骇閮ㄩ棬,涓嶅厑璁稿垹闄�");
- }
- if (deptService.checkDeptExistUser(deptId))
- {
- return warn("閮ㄩ棬瀛樺湪鐢ㄦ埛,涓嶅厑璁稿垹闄�");
- }
- deptService.checkDeptDataScope(deptId);
- return toAjax(deptService.deleteDeptById(deptId));
- }
-}
+package com.ruoyi.project.system.controller;
+
+import java.util.List;
+
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.ArrayUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.project.system.domain.SysDept;
+import com.ruoyi.project.system.service.ISysDeptService;
+
+/**
+ * 閮ㄩ棬淇℃伅
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/dept")
+@AllArgsConstructor
+public class SysDeptController extends BaseController
+{
+ private ISysDeptService deptService;
+
+ /**
+ * 鑾峰彇閮ㄩ棬鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('system:dept:list')")
+ @GetMapping("/list")
+ public AjaxResult list(SysDept dept)
+ {
+ List<SysDept> depts = deptService.selectDeptList(dept);
+ return success(depts);
+ }
+
+ /**
+ * 鏌ヨ閮ㄩ棬鍒楄〃锛堟帓闄よ妭鐐癸級
+ */
+ @PreAuthorize("@ss.hasPermi('system:dept:list')")
+ @GetMapping("/list/exclude/{deptId}")
+ public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId)
+ {
+ List<SysDept> depts = deptService.selectDeptList(new SysDept());
+ depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
+ return success(depts);
+ }
+
+ /**
+ * 鏍规嵁閮ㄩ棬缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('system:dept:query')")
+ @GetMapping(value = "/{deptId}")
+ public AjaxResult getInfo(@PathVariable Long deptId)
+ {
+ deptService.checkDeptDataScope(deptId);
+ return success(deptService.selectDeptById(deptId));
+ }
+
+ /**
+ * 鏂板閮ㄩ棬
+ */
+ @PreAuthorize("@ss.hasPermi('system:dept:add')")
+ @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysDept dept)
+ {
+ if (!deptService.checkDeptNameUnique(dept))
+ {
+ return error("鏂板閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛岄儴闂ㄥ悕绉板凡瀛樺湪");
+ }
+ dept.setCreateBy(getUsername());
+ return toAjax(deptService.insertDept(dept));
+ }
+
+ /**
+ * 淇敼閮ㄩ棬
+ */
+ @PreAuthorize("@ss.hasPermi('system:dept:edit')")
+ @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysDept dept)
+ {
+ Long deptId = dept.getDeptId();
+ deptService.checkDeptDataScope(deptId);
+ if (!deptService.checkDeptNameUnique(dept))
+ {
+ return error("淇敼閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛岄儴闂ㄥ悕绉板凡瀛樺湪");
+ }
+ else if (dept.getParentId().equals(deptId))
+ {
+ return error("淇敼閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛屼笂绾ч儴闂ㄤ笉鑳芥槸鑷繁");
+ }
+ else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0)
+ {
+ return error("璇ラ儴闂ㄥ寘鍚湭鍋滅敤鐨勫瓙閮ㄩ棬锛�");
+ }
+ dept.setUpdateBy(getUsername());
+ return toAjax(deptService.updateDept(dept));
+ }
+
+ /**
+ * 鍒犻櫎閮ㄩ棬
+ */
+ @PreAuthorize("@ss.hasPermi('system:dept:remove')")
+ @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{deptId}")
+ public AjaxResult remove(@PathVariable Long deptId)
+ {
+ if (deptService.hasChildByDeptId(deptId))
+ {
+ return warn("瀛樺湪涓嬬骇閮ㄩ棬,涓嶅厑璁稿垹闄�");
+ }
+ if (deptService.checkDeptExistUser(deptId))
+ {
+ return warn("閮ㄩ棬瀛樺湪鐢ㄦ埛,涓嶅厑璁稿垹闄�");
+ }
+ deptService.checkDeptDataScope(deptId);
+ return toAjax(deptService.deleteDeptById(deptId));
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java b/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java
index 58cb4c1..56c44c1 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java
@@ -1,120 +1,120 @@
-package com.ruoyi.project.system.controller;
-
-import java.util.ArrayList;
-import java.util.List;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.project.system.domain.SysDictData;
-import com.ruoyi.project.system.service.ISysDictDataService;
-import com.ruoyi.project.system.service.ISysDictTypeService;
-
-/**
- * 鏁版嵁瀛楀吀淇℃伅
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/system/dict/data")
-@AllArgsConstructor
-public class SysDictDataController extends BaseController
-{
- private ISysDictDataService dictDataService;
- private ISysDictTypeService dictTypeService;
-
- @PreAuthorize("@ss.hasPermi('system:dict:list')")
- @GetMapping("/list")
- public TableDataInfo list(SysDictData dictData)
- {
- startPage();
- List<SysDictData> list = dictDataService.selectDictDataList(dictData);
- return getDataTable(list);
- }
-
- @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.EXPORT)
- @PreAuthorize("@ss.hasPermi('system:dict:export')")
- @PostMapping("/export")
- public void export(HttpServletResponse response, SysDictData dictData)
- {
- List<SysDictData> list = dictDataService.selectDictDataList(dictData);
- ExcelUtil<SysDictData> util = new ExcelUtil<SysDictData>(SysDictData.class);
- util.exportExcel(response, list, "瀛楀吀鏁版嵁");
- }
-
- /**
- * 鏌ヨ瀛楀吀鏁版嵁璇︾粏
- */
- @PreAuthorize("@ss.hasPermi('system:dict:query')")
- @GetMapping(value = "/{dictCode}")
- public AjaxResult getInfo(@PathVariable Long dictCode)
- {
- return success(dictDataService.selectDictDataById(dictCode));
- }
-
- /**
- * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁淇℃伅
- */
- @GetMapping(value = "/type/{dictType}")
- public AjaxResult dictType(@PathVariable String dictType)
- {
- List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
- if (StringUtils.isNull(data))
- {
- data = new ArrayList<SysDictData>();
- }
- return success(data);
- }
-
- /**
- * 鏂板瀛楀吀绫诲瀷
- */
- @PreAuthorize("@ss.hasPermi('system:dict:add')")
- @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.INSERT)
- @PostMapping
- public AjaxResult add(@Validated @RequestBody SysDictData dict)
- {
- dict.setCreateBy(getUsername());
- return toAjax(dictDataService.insertDictData(dict));
- }
-
- /**
- * 淇敼淇濆瓨瀛楀吀绫诲瀷
- */
- @PreAuthorize("@ss.hasPermi('system:dict:edit')")
- @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.UPDATE)
- @PutMapping
- public AjaxResult edit(@Validated @RequestBody SysDictData dict)
- {
- dict.setUpdateBy(getUsername());
- return toAjax(dictDataService.updateDictData(dict));
- }
-
- /**
- * 鍒犻櫎瀛楀吀绫诲瀷
- */
- @PreAuthorize("@ss.hasPermi('system:dict:remove')")
- @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.DELETE)
- @DeleteMapping("/{dictCodes}")
- public AjaxResult remove(@PathVariable Long[] dictCodes)
- {
- dictDataService.deleteDictDataByIds(dictCodes);
- return success();
- }
-}
+package com.ruoyi.project.system.controller;
+
+import java.util.ArrayList;
+import java.util.List;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.system.domain.SysDictData;
+import com.ruoyi.project.system.service.ISysDictDataService;
+import com.ruoyi.project.system.service.ISysDictTypeService;
+
+/**
+ * 鏁版嵁瀛楀吀淇℃伅
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/dict/data")
+@AllArgsConstructor
+public class SysDictDataController extends BaseController
+{
+ private ISysDictDataService dictDataService;
+ private ISysDictTypeService dictTypeService;
+
+ @PreAuthorize("@ss.hasPermi('system:dict:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysDictData dictData)
+ {
+ startPage();
+ List<SysDictData> list = dictDataService.selectDictDataList(dictData);
+ return getDataTable(list);
+ }
+
+ @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('system:dict:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysDictData dictData)
+ {
+ List<SysDictData> list = dictDataService.selectDictDataList(dictData);
+ ExcelUtil<SysDictData> util = new ExcelUtil<SysDictData>(SysDictData.class);
+ util.exportExcel(response, list, "瀛楀吀鏁版嵁");
+ }
+
+ /**
+ * 鏌ヨ瀛楀吀鏁版嵁璇︾粏
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:query')")
+ @GetMapping(value = "/{dictCode}")
+ public AjaxResult getInfo(@PathVariable Long dictCode)
+ {
+ return success(dictDataService.selectDictDataById(dictCode));
+ }
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁淇℃伅
+ */
+ @GetMapping(value = "/type/{dictType}")
+ public AjaxResult dictType(@PathVariable String dictType)
+ {
+ List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
+ if (StringUtils.isNull(data))
+ {
+ data = new ArrayList<SysDictData>();
+ }
+ return success(data);
+ }
+
+ /**
+ * 鏂板瀛楀吀绫诲瀷
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:add')")
+ @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysDictData dict)
+ {
+ dict.setCreateBy(getUsername());
+ return toAjax(dictDataService.insertDictData(dict));
+ }
+
+ /**
+ * 淇敼淇濆瓨瀛楀吀绫诲瀷
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:edit')")
+ @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysDictData dict)
+ {
+ dict.setUpdateBy(getUsername());
+ return toAjax(dictDataService.updateDictData(dict));
+ }
+
+ /**
+ * 鍒犻櫎瀛楀吀绫诲瀷
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:remove')")
+ @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{dictCodes}")
+ public AjaxResult remove(@PathVariable Long[] dictCodes)
+ {
+ dictDataService.deleteDictDataByIds(dictCodes);
+ return success();
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java b/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java
index f1a026f..a385016 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java
@@ -1,132 +1,132 @@
-package com.ruoyi.project.system.controller;
-
-import java.util.List;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.project.system.domain.SysDictType;
-import com.ruoyi.project.system.service.ISysDictTypeService;
-
-/**
- * 鏁版嵁瀛楀吀淇℃伅
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/system/dict/type")
-@AllArgsConstructor
-public class SysDictTypeController extends BaseController
-{
- private ISysDictTypeService dictTypeService;
-
- @PreAuthorize("@ss.hasPermi('system:dict:list')")
- @GetMapping("/list")
- public TableDataInfo list(SysDictType dictType)
- {
- startPage();
- List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
- return getDataTable(list);
- }
-
- @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.EXPORT)
- @PreAuthorize("@ss.hasPermi('system:dict:export')")
- @PostMapping("/export")
- public void export(HttpServletResponse response, SysDictType dictType)
- {
- List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
- ExcelUtil<SysDictType> util = new ExcelUtil<SysDictType>(SysDictType.class);
- util.exportExcel(response, list, "瀛楀吀绫诲瀷");
- }
-
- /**
- * 鏌ヨ瀛楀吀绫诲瀷璇︾粏
- */
- @PreAuthorize("@ss.hasPermi('system:dict:query')")
- @GetMapping(value = "/{dictId}")
- public AjaxResult getInfo(@PathVariable Long dictId)
- {
- return success(dictTypeService.selectDictTypeById(dictId));
- }
-
- /**
- * 鏂板瀛楀吀绫诲瀷
- */
- @PreAuthorize("@ss.hasPermi('system:dict:add')")
- @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.INSERT)
- @PostMapping
- public AjaxResult add(@Validated @RequestBody SysDictType dict)
- {
- if (!dictTypeService.checkDictTypeUnique(dict))
- {
- return error("鏂板瀛楀吀'" + dict.getDictName() + "'澶辫触锛屽瓧鍏哥被鍨嬪凡瀛樺湪");
- }
- dict.setCreateBy(getUsername());
- return toAjax(dictTypeService.insertDictType(dict));
- }
-
- /**
- * 淇敼瀛楀吀绫诲瀷
- */
- @PreAuthorize("@ss.hasPermi('system:dict:edit')")
- @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.UPDATE)
- @PutMapping
- public AjaxResult edit(@Validated @RequestBody SysDictType dict)
- {
- if (!dictTypeService.checkDictTypeUnique(dict))
- {
- return error("淇敼瀛楀吀'" + dict.getDictName() + "'澶辫触锛屽瓧鍏哥被鍨嬪凡瀛樺湪");
- }
- dict.setUpdateBy(getUsername());
- return toAjax(dictTypeService.updateDictType(dict));
- }
-
- /**
- * 鍒犻櫎瀛楀吀绫诲瀷
- */
- @PreAuthorize("@ss.hasPermi('system:dict:remove')")
- @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.DELETE)
- @DeleteMapping("/{dictIds}")
- public AjaxResult remove(@PathVariable Long[] dictIds)
- {
- dictTypeService.deleteDictTypeByIds(dictIds);
- return success();
- }
-
- /**
- * 鍒锋柊瀛楀吀缂撳瓨
- */
- @PreAuthorize("@ss.hasPermi('system:dict:remove')")
- @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.CLEAN)
- @DeleteMapping("/refreshCache")
- public AjaxResult refreshCache()
- {
- dictTypeService.resetDictCache();
- return success();
- }
-
- /**
- * 鑾峰彇瀛楀吀閫夋嫨妗嗗垪琛�
- */
- @GetMapping("/optionselect")
- public AjaxResult optionselect()
- {
- List<SysDictType> dictTypes = dictTypeService.selectDictTypeAll();
- return success(dictTypes);
- }
-}
+package com.ruoyi.project.system.controller;
+
+import java.util.List;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.system.domain.SysDictType;
+import com.ruoyi.project.system.service.ISysDictTypeService;
+
+/**
+ * 鏁版嵁瀛楀吀淇℃伅
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/dict/type")
+@AllArgsConstructor
+public class SysDictTypeController extends BaseController
+{
+ private ISysDictTypeService dictTypeService;
+
+ @PreAuthorize("@ss.hasPermi('system:dict:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysDictType dictType)
+ {
+ startPage();
+ List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
+ return getDataTable(list);
+ }
+
+ @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('system:dict:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysDictType dictType)
+ {
+ List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
+ ExcelUtil<SysDictType> util = new ExcelUtil<SysDictType>(SysDictType.class);
+ util.exportExcel(response, list, "瀛楀吀绫诲瀷");
+ }
+
+ /**
+ * 鏌ヨ瀛楀吀绫诲瀷璇︾粏
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:query')")
+ @GetMapping(value = "/{dictId}")
+ public AjaxResult getInfo(@PathVariable Long dictId)
+ {
+ return success(dictTypeService.selectDictTypeById(dictId));
+ }
+
+ /**
+ * 鏂板瀛楀吀绫诲瀷
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:add')")
+ @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysDictType dict)
+ {
+ if (!dictTypeService.checkDictTypeUnique(dict))
+ {
+ return error("鏂板瀛楀吀'" + dict.getDictName() + "'澶辫触锛屽瓧鍏哥被鍨嬪凡瀛樺湪");
+ }
+ dict.setCreateBy(getUsername());
+ return toAjax(dictTypeService.insertDictType(dict));
+ }
+
+ /**
+ * 淇敼瀛楀吀绫诲瀷
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:edit')")
+ @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysDictType dict)
+ {
+ if (!dictTypeService.checkDictTypeUnique(dict))
+ {
+ return error("淇敼瀛楀吀'" + dict.getDictName() + "'澶辫触锛屽瓧鍏哥被鍨嬪凡瀛樺湪");
+ }
+ dict.setUpdateBy(getUsername());
+ return toAjax(dictTypeService.updateDictType(dict));
+ }
+
+ /**
+ * 鍒犻櫎瀛楀吀绫诲瀷
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:remove')")
+ @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{dictIds}")
+ public AjaxResult remove(@PathVariable Long[] dictIds)
+ {
+ dictTypeService.deleteDictTypeByIds(dictIds);
+ return success();
+ }
+
+ /**
+ * 鍒锋柊瀛楀吀缂撳瓨
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:remove')")
+ @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.CLEAN)
+ @DeleteMapping("/refreshCache")
+ public AjaxResult refreshCache()
+ {
+ dictTypeService.resetDictCache();
+ return success();
+ }
+
+ /**
+ * 鑾峰彇瀛楀吀閫夋嫨妗嗗垪琛�
+ */
+ @GetMapping("/optionselect")
+ public AjaxResult optionselect()
+ {
+ List<SysDictType> dictTypes = dictTypeService.selectDictTypeAll();
+ return success(dictTypes);
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java b/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java
index e5c5bfa..3334a07 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java
@@ -1,155 +1,155 @@
-package com.ruoyi.project.system.controller;
-
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.framework.security.LoginBody;
-import com.ruoyi.framework.security.LoginUser;
-import com.ruoyi.framework.security.service.SysLoginService;
-import com.ruoyi.framework.security.service.SysPermissionService;
-import com.ruoyi.framework.security.service.TokenService;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.project.system.domain.SysDept;
-import com.ruoyi.project.system.domain.SysMenu;
-import com.ruoyi.project.system.domain.SysUser;
-import com.ruoyi.project.system.domain.vo.SysUserDeptVo;
-import com.ruoyi.project.system.mapper.SysDeptMapper;
-import com.ruoyi.project.system.service.ISysMenuService;
-import com.ruoyi.project.system.service.ISysUserDeptService;
-import com.ruoyi.project.system.service.ISysUserService;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.util.ObjectUtils;
-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.RestController;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * 鐧诲綍楠岃瘉
- *
- * @author ruoyi
- */
-@RestController
-@AllArgsConstructor
-public class SysLoginController
-{
- private SysLoginService loginService;
- private ISysMenuService menuService;
- private SysPermissionService permissionService;
- private TokenService tokenService;
- private ISysUserDeptService userDeptService;
- private ISysUserService userService;
- private SysDeptMapper sysDeptMapper;
-
- /**
- * 鐧诲綍鏂规硶
- *
- * @param loginBody 鐧诲綍淇℃伅
- * @return 缁撴灉
- */
- @PostMapping("/login")
- public AjaxResult login(@RequestBody LoginBody loginBody)
- {
- AjaxResult ajax = AjaxResult.success();
- // 鐢熸垚浠ょ墝
- String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
- loginBody.getUuid());
- ajax.put(Constants.TOKEN, token);
- return ajax;
- }
-
- /**
- * 鑾峰彇鐢ㄦ埛淇℃伅
- *
- * @return 鐢ㄦ埛淇℃伅
- */
- @GetMapping("/getInfo")
- public AjaxResult getInfo()
- {
- LoginUser loginUser = SecurityUtils.getLoginUser();
- SysUser user = loginUser.getUser();
- // 鑾峰彇褰撳墠鐧诲綍鍏徃
- Long tenantId = loginUser.getTenantId();
- if(null != tenantId){
- user.setTenantId(tenantId);
- SysDept sysDept = sysDeptMapper.selectDeptById(tenantId.longValue());
- if(!ObjectUtils.isEmpty(sysDept)){
- user.setCurrentFactoryName(sysDept.getDeptName());
- }
- }
- // 瑙掕壊闆嗗悎
- Set<String> roles = permissionService.getRolePermission(user);
- // 鏉冮檺闆嗗悎
- Set<String> permissions = permissionService.getMenuPermission(user);
- if (!loginUser.getPermissions().equals(permissions))
- {
- loginUser.setPermissions(permissions);
- tokenService.refreshToken(loginUser);
- }
- AjaxResult ajax = AjaxResult.success();
- ajax.put("user", user);
- ajax.put("aiEnabled", loginUser.getAiEnabled());
- ajax.put("roles", roles);
- ajax.put("permissions", permissions);
- return ajax;
- }
-
- /**
- * 鑾峰彇璺敱淇℃伅
- *
- * @return 璺敱淇℃伅
- */
- @GetMapping("getRouters")
- public AjaxResult getRouters()
- {
- Long userId = SecurityUtils.getUserId();
- List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
- return AjaxResult.success(menuService.buildMenus(menus));
- }
-
- @PostMapping("/loginCheck")
- public AjaxResult loginCheck(@RequestBody LoginBody loginBody)
- {
- try {
- Long userId = loginService.loginCheck(loginBody.getUsername(), loginBody.getPassword());
- return AjaxResult.success(userId);
- }catch (Exception e) {
- return AjaxResult.error(e.getMessage());
- }
- }
-
- @GetMapping("/userLoginFacotryList")
- public AjaxResult userLoginFacotryList(SysUserDeptVo sysUserDeptVo){
- List<SysUserDeptVo> sysUserDeptVoList = userDeptService.userLoginFacotryList(sysUserDeptVo);
- Map<Long, SysUserDeptVo> map = sysUserDeptVoList.stream()
- .collect(Collectors.toMap(
- SysUserDeptVo::getDeptId,
- item -> item,
- (existing, replacement) -> existing // 濡傛灉閲嶅锛屼繚鐣欑涓�涓�
- ));
- List<SysUserDeptVo> uniqueList = new ArrayList<>(map.values());
- return AjaxResult.success(uniqueList);
- }
-
- /**
- * 閫夋嫨鍏徃鐧诲綍
- *
- * @param loginBody 鐧诲綍淇℃伅
- * @return 缁撴灉
- */
- @PostMapping("/loginCheckFactory")
- public AjaxResult loginCheckFactory(@RequestBody LoginBody loginBody)
- {
- AjaxResult ajax = AjaxResult.success();
- // 鐢熸垚浠ょ墝
- String token = loginService.loginCheckFactory(loginBody.getUsername(), loginBody.getPassword(),loginBody.getFactoryId());
- ajax.put(Constants.TOKEN, token);
- return ajax;
- }
-}
+package com.ruoyi.project.system.controller;
+
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.framework.security.LoginBody;
+import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.framework.security.service.SysLoginService;
+import com.ruoyi.framework.security.service.SysPermissionService;
+import com.ruoyi.framework.security.service.TokenService;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.project.system.domain.SysDept;
+import com.ruoyi.project.system.domain.SysMenu;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.domain.vo.SysUserDeptVo;
+import com.ruoyi.project.system.mapper.SysDeptMapper;
+import com.ruoyi.project.system.service.ISysMenuService;
+import com.ruoyi.project.system.service.ISysUserDeptService;
+import com.ruoyi.project.system.service.ISysUserService;
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.ObjectUtils;
+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.RestController;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * 鐧诲綍楠岃瘉
+ *
+ * @author ruoyi
+ */
+@RestController
+@AllArgsConstructor
+public class SysLoginController
+{
+ private SysLoginService loginService;
+ private ISysMenuService menuService;
+ private SysPermissionService permissionService;
+ private TokenService tokenService;
+ private ISysUserDeptService userDeptService;
+ private ISysUserService userService;
+ private SysDeptMapper sysDeptMapper;
+
+ /**
+ * 鐧诲綍鏂规硶
+ *
+ * @param loginBody 鐧诲綍淇℃伅
+ * @return 缁撴灉
+ */
+ @PostMapping("/login")
+ public AjaxResult login(@RequestBody LoginBody loginBody)
+ {
+ AjaxResult ajax = AjaxResult.success();
+ // 鐢熸垚浠ょ墝
+ String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
+ loginBody.getUuid());
+ ajax.put(Constants.TOKEN, token);
+ return ajax;
+ }
+
+ /**
+ * 鑾峰彇鐢ㄦ埛淇℃伅
+ *
+ * @return 鐢ㄦ埛淇℃伅
+ */
+ @GetMapping("/getInfo")
+ public AjaxResult getInfo()
+ {
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ SysUser user = loginUser.getUser();
+ // 鑾峰彇褰撳墠鐧诲綍鍏徃
+ Long tenantId = loginUser.getTenantId();
+ if(null != tenantId){
+ user.setTenantId(tenantId);
+ SysDept sysDept = sysDeptMapper.selectDeptById(tenantId.longValue());
+ if(!ObjectUtils.isEmpty(sysDept)){
+ user.setCurrentFactoryName(sysDept.getDeptName());
+ }
+ }
+ // 瑙掕壊闆嗗悎
+ Set<String> roles = permissionService.getRolePermission(user);
+ // 鏉冮檺闆嗗悎
+ Set<String> permissions = permissionService.getMenuPermission(user);
+ if (!loginUser.getPermissions().equals(permissions))
+ {
+ loginUser.setPermissions(permissions);
+ tokenService.refreshToken(loginUser);
+ }
+ AjaxResult ajax = AjaxResult.success();
+ ajax.put("user", user);
+ ajax.put("aiEnabled", loginUser.getAiEnabled());
+ ajax.put("roles", roles);
+ ajax.put("permissions", permissions);
+ return ajax;
+ }
+
+ /**
+ * 鑾峰彇璺敱淇℃伅
+ *
+ * @return 璺敱淇℃伅
+ */
+ @GetMapping("getRouters")
+ public AjaxResult getRouters()
+ {
+ Long userId = SecurityUtils.getUserId();
+ List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
+ return AjaxResult.success(menuService.buildMenus(menus));
+ }
+
+ @PostMapping("/loginCheck")
+ public AjaxResult loginCheck(@RequestBody LoginBody loginBody)
+ {
+ try {
+ Long userId = loginService.loginCheck(loginBody.getUsername(), loginBody.getPassword());
+ return AjaxResult.success(userId);
+ }catch (Exception e) {
+ return AjaxResult.error(e.getMessage());
+ }
+ }
+
+ @GetMapping("/userLoginFacotryList")
+ public AjaxResult userLoginFacotryList(SysUserDeptVo sysUserDeptVo){
+ List<SysUserDeptVo> sysUserDeptVoList = userDeptService.userLoginFacotryList(sysUserDeptVo);
+ Map<Long, SysUserDeptVo> map = sysUserDeptVoList.stream()
+ .collect(Collectors.toMap(
+ SysUserDeptVo::getDeptId,
+ item -> item,
+ (existing, replacement) -> existing // 濡傛灉閲嶅锛屼繚鐣欑涓�涓�
+ ));
+ List<SysUserDeptVo> uniqueList = new ArrayList<>(map.values());
+ return AjaxResult.success(uniqueList);
+ }
+
+ /**
+ * 閫夋嫨鍏徃鐧诲綍
+ *
+ * @param loginBody 鐧诲綍淇℃伅
+ * @return 缁撴灉
+ */
+ @PostMapping("/loginCheckFactory")
+ public AjaxResult loginCheckFactory(@RequestBody LoginBody loginBody)
+ {
+ AjaxResult ajax = AjaxResult.success();
+ // 鐢熸垚浠ょ墝
+ String token = loginService.loginCheckFactory(loginBody.getUsername(), loginBody.getPassword(),loginBody.getFactoryId());
+ ajax.put(Constants.TOKEN, token);
+ return ajax;
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysMenuController.java b/src/main/java/com/ruoyi/project/system/controller/SysMenuController.java
index 865e8a4..a59bdb3 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysMenuController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysMenuController.java
@@ -1,136 +1,136 @@
-package com.ruoyi.project.system.controller;
-
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.project.system.domain.SysMenu;
-import com.ruoyi.project.system.service.ISysMenuService;
-import lombok.AllArgsConstructor;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 鑿滃崟淇℃伅
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/system/menu")
-@AllArgsConstructor
-public class SysMenuController extends BaseController
-{
- private ISysMenuService menuService;
-
- /**
- * 鑾峰彇鑿滃崟鍒楄〃
- */
- @PreAuthorize("@ss.hasPermi('system:menu:list')")
- @GetMapping("/list")
- public AjaxResult list(SysMenu menu)
- {
- List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
- return success(menus);
- }
-
- /**
- * 鏍规嵁鑿滃崟缂栧彿鑾峰彇璇︾粏淇℃伅
- */
- @PreAuthorize("@ss.hasPermi('system:menu:query')")
- @GetMapping(value = "/{menuId}")
- public AjaxResult getInfo(@PathVariable Long menuId)
- {
- return success(menuService.selectMenuById(menuId));
- }
-
- /**
- * 鑾峰彇鑿滃崟涓嬫媺鏍戝垪琛�
- */
- @GetMapping("/treeselect")
- public AjaxResult treeselect(SysMenu menu)
- {
- List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
- return success(menuService.buildMenuTreeSelect(menus));
- }
-
- /**
- * 鍔犺浇瀵瑰簲瑙掕壊鑿滃崟鍒楄〃鏍�
- */
- @GetMapping(value = "/roleMenuTreeselect/{roleId}")
- public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId)
- {
- List<SysMenu> menus = menuService.selectMenuList(getUserId());
- AjaxResult ajax = AjaxResult.success();
- ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
- ajax.put("menus", menuService.buildMenuTreeSelect(menus));
- return ajax;
- }
-
- /**
- * 鏂板鑿滃崟
- */
- @PreAuthorize("@ss.hasPermi('system:menu:add')")
- @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.INSERT)
- @PostMapping
- public AjaxResult add(@Validated @RequestBody SysMenu menu)
- {
- if (!menuService.checkMenuNameUnique(menu))
- {
- return error("鏂板鑿滃崟'" + menu.getMenuName() + "'澶辫触锛岃彍鍗曞悕绉板凡瀛樺湪");
- }
- else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
- {
- return error("鏂板鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屽湴鍧�蹇呴』浠ttp(s)://寮�澶�");
- }
- menu.setCreateBy(getUsername());
- return toAjax(menuService.insertMenu(menu));
- }
-
- /**
- * 淇敼鑿滃崟
- */
- @PreAuthorize("@ss.hasPermi('system:menu:edit')")
- @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.UPDATE)
- @PutMapping
- public AjaxResult edit(@Validated @RequestBody SysMenu menu)
- {
- if (!menuService.checkMenuNameUnique(menu))
- {
- return error("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛岃彍鍗曞悕绉板凡瀛樺湪");
- }
- else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
- {
- return error("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屽湴鍧�蹇呴』浠ttp(s)://寮�澶�");
- }
- else if (menu.getMenuId().equals(menu.getParentId()))
- {
- return error("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屼笂绾ц彍鍗曚笉鑳介�夋嫨鑷繁");
- }
- menu.setUpdateBy(getUsername());
- return toAjax(menuService.updateMenu(menu));
- }
-
- /**
- * 鍒犻櫎鑿滃崟
- */
- @PreAuthorize("@ss.hasPermi('system:menu:remove')")
- @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.DELETE)
- @DeleteMapping("/{menuId}")
- public AjaxResult remove(@PathVariable("menuId") Long menuId)
- {
- if (menuService.hasChildByMenuId(menuId))
- {
- return warn("瀛樺湪瀛愯彍鍗�,涓嶅厑璁稿垹闄�");
- }
- if (menuService.checkMenuExistRole(menuId))
- {
- return warn("鑿滃崟宸插垎閰�,涓嶅厑璁稿垹闄�");
- }
- return toAjax(menuService.deleteMenuById(menuId));
- }
+package com.ruoyi.project.system.controller;
+
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.project.system.domain.SysMenu;
+import com.ruoyi.project.system.service.ISysMenuService;
+import lombok.AllArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 鑿滃崟淇℃伅
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/menu")
+@AllArgsConstructor
+public class SysMenuController extends BaseController
+{
+ private ISysMenuService menuService;
+
+ /**
+ * 鑾峰彇鑿滃崟鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('system:menu:list')")
+ @GetMapping("/list")
+ public AjaxResult list(SysMenu menu)
+ {
+ List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
+ return success(menus);
+ }
+
+ /**
+ * 鏍规嵁鑿滃崟缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('system:menu:query')")
+ @GetMapping(value = "/{menuId}")
+ public AjaxResult getInfo(@PathVariable Long menuId)
+ {
+ return success(menuService.selectMenuById(menuId));
+ }
+
+ /**
+ * 鑾峰彇鑿滃崟涓嬫媺鏍戝垪琛�
+ */
+ @GetMapping("/treeselect")
+ public AjaxResult treeselect(SysMenu menu)
+ {
+ List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
+ return success(menuService.buildMenuTreeSelect(menus));
+ }
+
+ /**
+ * 鍔犺浇瀵瑰簲瑙掕壊鑿滃崟鍒楄〃鏍�
+ */
+ @GetMapping(value = "/roleMenuTreeselect/{roleId}")
+ public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId)
+ {
+ List<SysMenu> menus = menuService.selectMenuList(getUserId());
+ AjaxResult ajax = AjaxResult.success();
+ ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
+ ajax.put("menus", menuService.buildMenuTreeSelect(menus));
+ return ajax;
+ }
+
+ /**
+ * 鏂板鑿滃崟
+ */
+ @PreAuthorize("@ss.hasPermi('system:menu:add')")
+ @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysMenu menu)
+ {
+ if (!menuService.checkMenuNameUnique(menu))
+ {
+ return error("鏂板鑿滃崟'" + menu.getMenuName() + "'澶辫触锛岃彍鍗曞悕绉板凡瀛樺湪");
+ }
+ else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
+ {
+ return error("鏂板鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屽湴鍧�蹇呴』浠ttp(s)://寮�澶�");
+ }
+ menu.setCreateBy(getUsername());
+ return toAjax(menuService.insertMenu(menu));
+ }
+
+ /**
+ * 淇敼鑿滃崟
+ */
+ @PreAuthorize("@ss.hasPermi('system:menu:edit')")
+ @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysMenu menu)
+ {
+ if (!menuService.checkMenuNameUnique(menu))
+ {
+ return error("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛岃彍鍗曞悕绉板凡瀛樺湪");
+ }
+ else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
+ {
+ return error("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屽湴鍧�蹇呴』浠ttp(s)://寮�澶�");
+ }
+ else if (menu.getMenuId().equals(menu.getParentId()))
+ {
+ return error("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屼笂绾ц彍鍗曚笉鑳介�夋嫨鑷繁");
+ }
+ menu.setUpdateBy(getUsername());
+ return toAjax(menuService.updateMenu(menu));
+ }
+
+ /**
+ * 鍒犻櫎鑿滃崟
+ */
+ @PreAuthorize("@ss.hasPermi('system:menu:remove')")
+ @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{menuId}")
+ public AjaxResult remove(@PathVariable("menuId") Long menuId)
+ {
+ if (menuService.hasChildByMenuId(menuId))
+ {
+ return warn("瀛樺湪瀛愯彍鍗�,涓嶅厑璁稿垹闄�");
+ }
+ if (menuService.checkMenuExistRole(menuId))
+ {
+ return warn("鑿滃崟宸插垎閰�,涓嶅厑璁稿垹闄�");
+ }
+ return toAjax(menuService.deleteMenuById(menuId));
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java b/src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java
index 5aa3413..eaba7d0 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java
@@ -1,96 +1,96 @@
-package com.ruoyi.project.system.controller;
-
-import java.util.List;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.web.domain.R;
-import io.swagger.v3.oas.annotations.Operation;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.project.system.domain.SysNotice;
-import com.ruoyi.project.system.service.ISysNoticeService;
-
-/**
- * 鍏憡 淇℃伅鎿嶄綔澶勭悊
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/system/notice")
-@AllArgsConstructor
-public class SysNoticeController extends BaseController {
- private ISysNoticeService noticeService;
-
- /**
- * 鑾峰彇閫氱煡鍏憡鍒楄〃
- */
- @GetMapping("/list")
- public R<IPage<SysNotice>> list(SysNotice notice, Page page) {
- IPage<SysNotice> list = noticeService.selectNoticeList(notice, page);
- return R.ok(list);
- }
-
- /**
- * 鑾峰彇鏈鏁伴噺
- */
- @GetMapping("/getCount")
- public R getCount(Long consigneeId) {
- return R.ok(noticeService.getCount(consigneeId));
- }
-
- /**
- * 鏍规嵁閫氱煡鍏憡缂栧彿鑾峰彇璇︾粏淇℃伅
- */
- @GetMapping(value = "/{noticeId}")
- public AjaxResult getInfo(@PathVariable Long noticeId) {
- return success(noticeService.selectNoticeById(noticeId));
- }
-
- /**
- * 鏂板閫氱煡鍏憡
- */
- @PostMapping
- public AjaxResult add(@Validated @RequestBody SysNotice notice) {
- return toAjax(noticeService.insertNotice(notice));
- }
-
- /**
- * 淇敼閫氱煡鍏憡
- */
- @PutMapping
- public AjaxResult edit(@Validated @RequestBody SysNotice notice) {
- return toAjax(noticeService.updateNotice(notice));
- }
-
- /**
- * 鍒犻櫎閫氱煡鍏憡
- */
- @DeleteMapping("/{noticeIds}")
- public AjaxResult remove(@PathVariable Long[] noticeIds) {
- return toAjax(noticeService.deleteNoticeByIds(noticeIds));
- }
-
- /**
- * 涓�閿凡璇�
- */
- @PostMapping("/readAll")
- public AjaxResult readAll() {
- return toAjax(noticeService.readAll());
- }
-
- @PostMapping("appReadNotice")
- @Operation(summary = "绉诲姩绔牴鎹秷鎭疘D杩涜宸茶")
- public AjaxResult appReadNotice(@RequestParam("noticeId") Long noticeId) {
- boolean result = noticeService.appReadNotice(noticeId);
- return toAjax(result);
- }
-}
+package com.ruoyi.project.system.controller;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.system.domain.SysNotice;
+import com.ruoyi.project.system.service.ISysNoticeService;
+
+/**
+ * 鍏憡 淇℃伅鎿嶄綔澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/notice")
+@AllArgsConstructor
+public class SysNoticeController extends BaseController {
+ private ISysNoticeService noticeService;
+
+ /**
+ * 鑾峰彇閫氱煡鍏憡鍒楄〃
+ */
+ @GetMapping("/list")
+ public R<IPage<SysNotice>> list(SysNotice notice, Page page) {
+ IPage<SysNotice> list = noticeService.selectNoticeList(notice, page);
+ return R.ok(list);
+ }
+
+ /**
+ * 鑾峰彇鏈鏁伴噺
+ */
+ @GetMapping("/getCount")
+ public R getCount(Long consigneeId) {
+ return R.ok(noticeService.getCount(consigneeId));
+ }
+
+ /**
+ * 鏍规嵁閫氱煡鍏憡缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @GetMapping(value = "/{noticeId}")
+ public AjaxResult getInfo(@PathVariable Long noticeId) {
+ return success(noticeService.selectNoticeById(noticeId));
+ }
+
+ /**
+ * 鏂板閫氱煡鍏憡
+ */
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysNotice notice) {
+ return toAjax(noticeService.insertNotice(notice));
+ }
+
+ /**
+ * 淇敼閫氱煡鍏憡
+ */
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysNotice notice) {
+ return toAjax(noticeService.updateNotice(notice));
+ }
+
+ /**
+ * 鍒犻櫎閫氱煡鍏憡
+ */
+ @DeleteMapping("/{noticeIds}")
+ public AjaxResult remove(@PathVariable Long[] noticeIds) {
+ return toAjax(noticeService.deleteNoticeByIds(noticeIds));
+ }
+
+ /**
+ * 涓�閿凡璇�
+ */
+ @PostMapping("/readAll")
+ public AjaxResult readAll() {
+ return toAjax(noticeService.readAll());
+ }
+
+ @PostMapping("appReadNotice")
+ @Operation(summary = "绉诲姩绔牴鎹秷鎭疘D杩涜宸茶")
+ public AjaxResult appReadNotice(@RequestParam("noticeId") Long noticeId) {
+ boolean result = noticeService.appReadNotice(noticeId);
+ return toAjax(result);
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysPostController.java b/src/main/java/com/ruoyi/project/system/controller/SysPostController.java
index a4776c4..45c5bcc 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysPostController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysPostController.java
@@ -1,133 +1,133 @@
-package com.ruoyi.project.system.controller;
-
-import java.util.List;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.project.system.domain.SysPost;
-import com.ruoyi.project.system.service.ISysPostService;
-
-/**
- * 宀椾綅淇℃伅鎿嶄綔澶勭悊
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/system/post")
-@AllArgsConstructor
-public class SysPostController extends BaseController
-{
- private ISysPostService postService;
-
- /**
- * 鑾峰彇宀椾綅鍒楄〃
- */
- @PreAuthorize("@ss.hasPermi('system:post:list')")
- @GetMapping("/list")
- public TableDataInfo list(SysPost post)
- {
- startPage();
- List<SysPost> list = postService.selectPostList(post);
- return getDataTable(list);
- }
- /**
- * 瀵煎嚭宀椾綅鍒楄〃
- */
-
- @Log(title = "宀椾綅绠$悊", businessType = BusinessType.EXPORT)
- @PreAuthorize("@ss.hasPermi('system:post:export')")
- @PostMapping("/export")
- public void export(HttpServletResponse response, SysPost post)
- {
- List<SysPost> list = postService.selectPostList(post);
- ExcelUtil<SysPost> util = new ExcelUtil<SysPost>(SysPost.class);
- util.exportExcel(response, list, "宀椾綅鏁版嵁");
- }
-
- /**
- * 鏍规嵁宀椾綅缂栧彿鑾峰彇璇︾粏淇℃伅
- */
- @PreAuthorize("@ss.hasPermi('system:post:query')")
- @GetMapping(value = "/{postId}")
- public AjaxResult getInfo(@PathVariable Long postId)
- {
- return success(postService.selectPostById(postId));
- }
-
- /**
- * 鏂板宀椾綅
- */
- @PreAuthorize("@ss.hasPermi('system:post:add')")
- @Log(title = "宀椾綅绠$悊", businessType = BusinessType.INSERT)
- @PostMapping
- public AjaxResult add(@Validated @RequestBody SysPost post)
- {
- if (!postService.checkPostNameUnique(post))
- {
- return error("鏂板宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶅悕绉板凡瀛樺湪");
- }
- else if (!postService.checkPostCodeUnique(post))
- {
- return error("鏂板宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶇紪鐮佸凡瀛樺湪");
- }
- post.setCreateBy(getUsername());
- return toAjax(postService.insertPost(post));
- }
-
- /**
- * 淇敼宀椾綅
- */
- @PreAuthorize("@ss.hasPermi('system:post:edit')")
- @Log(title = "宀椾綅绠$悊", businessType = BusinessType.UPDATE)
- @PutMapping
- public AjaxResult edit(@Validated @RequestBody SysPost post)
- {
- if (!postService.checkPostNameUnique(post))
- {
- return error("淇敼宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶅悕绉板凡瀛樺湪");
- }
- else if (!postService.checkPostCodeUnique(post))
- {
- return error("淇敼宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶇紪鐮佸凡瀛樺湪");
- }
- post.setUpdateBy(getUsername());
- return toAjax(postService.updatePost(post));
- }
-
- /**
- * 鍒犻櫎宀椾綅
- */
- @PreAuthorize("@ss.hasPermi('system:post:remove')")
- @Log(title = "宀椾綅绠$悊", businessType = BusinessType.DELETE)
- @DeleteMapping("/{postIds}")
- public AjaxResult remove(@PathVariable Long[] postIds)
- {
- return toAjax(postService.deletePostByIds(postIds));
- }
-
- /**
- * 鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
- */
- @GetMapping("/optionselect")
- public AjaxResult optionselect()
- {
- List<SysPost> posts = postService.selectPostAll();
- return success(posts);
- }
-}
+package com.ruoyi.project.system.controller;
+
+import java.util.List;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.system.domain.SysPost;
+import com.ruoyi.project.system.service.ISysPostService;
+
+/**
+ * 宀椾綅淇℃伅鎿嶄綔澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/post")
+@AllArgsConstructor
+public class SysPostController extends BaseController
+{
+ private ISysPostService postService;
+
+ /**
+ * 鑾峰彇宀椾綅鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('system:post:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysPost post)
+ {
+ startPage();
+ List<SysPost> list = postService.selectPostList(post);
+ return getDataTable(list);
+ }
+ /**
+ * 瀵煎嚭宀椾綅鍒楄〃
+ */
+
+ @Log(title = "宀椾綅绠$悊", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('system:post:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysPost post)
+ {
+ List<SysPost> list = postService.selectPostList(post);
+ ExcelUtil<SysPost> util = new ExcelUtil<SysPost>(SysPost.class);
+ util.exportExcel(response, list, "宀椾綅鏁版嵁");
+ }
+
+ /**
+ * 鏍规嵁宀椾綅缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('system:post:query')")
+ @GetMapping(value = "/{postId}")
+ public AjaxResult getInfo(@PathVariable Long postId)
+ {
+ return success(postService.selectPostById(postId));
+ }
+
+ /**
+ * 鏂板宀椾綅
+ */
+ @PreAuthorize("@ss.hasPermi('system:post:add')")
+ @Log(title = "宀椾綅绠$悊", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysPost post)
+ {
+ if (!postService.checkPostNameUnique(post))
+ {
+ return error("鏂板宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶅悕绉板凡瀛樺湪");
+ }
+ else if (!postService.checkPostCodeUnique(post))
+ {
+ return error("鏂板宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶇紪鐮佸凡瀛樺湪");
+ }
+ post.setCreateBy(getUsername());
+ return toAjax(postService.insertPost(post));
+ }
+
+ /**
+ * 淇敼宀椾綅
+ */
+ @PreAuthorize("@ss.hasPermi('system:post:edit')")
+ @Log(title = "宀椾綅绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysPost post)
+ {
+ if (!postService.checkPostNameUnique(post))
+ {
+ return error("淇敼宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶅悕绉板凡瀛樺湪");
+ }
+ else if (!postService.checkPostCodeUnique(post))
+ {
+ return error("淇敼宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶇紪鐮佸凡瀛樺湪");
+ }
+ post.setUpdateBy(getUsername());
+ return toAjax(postService.updatePost(post));
+ }
+
+ /**
+ * 鍒犻櫎宀椾綅
+ */
+ @PreAuthorize("@ss.hasPermi('system:post:remove')")
+ @Log(title = "宀椾綅绠$悊", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{postIds}")
+ public AjaxResult remove(@PathVariable Long[] postIds)
+ {
+ return toAjax(postService.deletePostByIds(postIds));
+ }
+
+ /**
+ * 鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
+ */
+ @GetMapping("/optionselect")
+ public AjaxResult optionselect()
+ {
+ List<SysPost> posts = postService.selectPostAll();
+ return success(posts);
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysProfileController.java b/src/main/java/com/ruoyi/project/system/controller/SysProfileController.java
index 62f6db5..66e89e2 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysProfileController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysProfileController.java
@@ -1,133 +1,133 @@
-package com.ruoyi.project.system.controller;
-
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.file.FileUploadUtils;
-import com.ruoyi.common.utils.file.MimeTypeUtils;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.config.RuoYiConfig;
-import com.ruoyi.framework.security.LoginUser;
-import com.ruoyi.framework.security.service.TokenService;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.project.system.domain.SysUser;
-import com.ruoyi.project.system.service.ISysUserService;
-import lombok.AllArgsConstructor;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.util.Map;
-
-/**
- * 涓汉淇℃伅 涓氬姟澶勭悊
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/system/user/profile")
-@AllArgsConstructor
-public class SysProfileController extends BaseController
-{
- private ISysUserService userService;
- private TokenService tokenService;
-
- /**
- * 涓汉淇℃伅
- */
- @GetMapping
- public AjaxResult profile()
- {
- LoginUser loginUser = getLoginUser();
- SysUser user = loginUser.getUser();
- AjaxResult ajax = AjaxResult.success(user);
- ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
- ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername()));
- return ajax;
- }
-
- /**
- * 淇敼鐢ㄦ埛
- */
- @Log(title = "涓汉淇℃伅", businessType = BusinessType.UPDATE)
- @PutMapping
- public AjaxResult updateProfile(@RequestBody SysUser user)
- {
- LoginUser loginUser = getLoginUser();
- SysUser currentUser = loginUser.getUser();
- currentUser.setNickName(user.getNickName());
- currentUser.setEmail(user.getEmail());
- currentUser.setPhonenumber(user.getPhonenumber());
- currentUser.setSex(user.getSex());
- if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
- {
- return error("淇敼鐢ㄦ埛'" + loginUser.getUsername() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
- }
- if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
- {
- return error("淇敼鐢ㄦ埛'" + loginUser.getUsername() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
- }
- if (userService.updateUserProfile(currentUser) > 0)
- {
- // 鏇存柊缂撳瓨鐢ㄦ埛淇℃伅
- tokenService.setLoginUser(loginUser);
- return success();
- }
- return error("淇敼涓汉淇℃伅寮傚父锛岃鑱旂郴绠$悊鍛�");
- }
-
- /**
- * 閲嶇疆瀵嗙爜
- */
- @Log(title = "涓汉淇℃伅", businessType = BusinessType.UPDATE)
- @PutMapping("/updatePwd")
- public AjaxResult updatePwd(@RequestBody Map<String, String> params)
- {
- String oldPassword = params.get("oldPassword");
- String newPassword = params.get("newPassword");
- LoginUser loginUser = getLoginUser();
- String userName = loginUser.getUsername();
- String password = loginUser.getPassword();
- if (!SecurityUtils.matchesPassword(oldPassword, password))
- {
- return error("淇敼瀵嗙爜澶辫触锛屾棫瀵嗙爜閿欒");
- }
- if (SecurityUtils.matchesPassword(newPassword, password))
- {
- return error("鏂板瘑鐮佷笉鑳戒笌鏃у瘑鐮佺浉鍚�");
- }
- newPassword = SecurityUtils.encryptPassword(newPassword);
- if (userService.resetUserPwd(userName, newPassword) > 0)
- {
- // 鏇存柊缂撳瓨鐢ㄦ埛瀵嗙爜
- loginUser.getUser().setPassword(newPassword);
- tokenService.setLoginUser(loginUser);
- return success();
- }
- return error("淇敼瀵嗙爜寮傚父锛岃鑱旂郴绠$悊鍛�");
- }
-
- /**
- * 澶村儚涓婁紶
- */
- @Log(title = "鐢ㄦ埛澶村儚", businessType = BusinessType.UPDATE)
- @PostMapping("/avatar")
- public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception
- {
- if (!file.isEmpty())
- {
- LoginUser loginUser = getLoginUser();
- String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
- if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
- {
- AjaxResult ajax = AjaxResult.success();
- ajax.put("imgUrl", avatar);
- // 鏇存柊缂撳瓨鐢ㄦ埛澶村儚
- loginUser.getUser().setAvatar(avatar);
- tokenService.setLoginUser(loginUser);
- return ajax;
- }
- }
- return error("涓婁紶鍥剧墖寮傚父锛岃鑱旂郴绠$悊鍛�");
- }
-}
+package com.ruoyi.project.system.controller;
+
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.file.FileUploadUtils;
+import com.ruoyi.common.utils.file.MimeTypeUtils;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.config.RuoYiConfig;
+import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.framework.security.service.TokenService;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.service.ISysUserService;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.Map;
+
+/**
+ * 涓汉淇℃伅 涓氬姟澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/user/profile")
+@AllArgsConstructor
+public class SysProfileController extends BaseController
+{
+ private ISysUserService userService;
+ private TokenService tokenService;
+
+ /**
+ * 涓汉淇℃伅
+ */
+ @GetMapping
+ public AjaxResult profile()
+ {
+ LoginUser loginUser = getLoginUser();
+ SysUser user = loginUser.getUser();
+ AjaxResult ajax = AjaxResult.success(user);
+ ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
+ ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername()));
+ return ajax;
+ }
+
+ /**
+ * 淇敼鐢ㄦ埛
+ */
+ @Log(title = "涓汉淇℃伅", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult updateProfile(@RequestBody SysUser user)
+ {
+ LoginUser loginUser = getLoginUser();
+ SysUser currentUser = loginUser.getUser();
+ currentUser.setNickName(user.getNickName());
+ currentUser.setEmail(user.getEmail());
+ currentUser.setPhonenumber(user.getPhonenumber());
+ currentUser.setSex(user.getSex());
+ if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
+ {
+ return error("淇敼鐢ㄦ埛'" + loginUser.getUsername() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
+ }
+ if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
+ {
+ return error("淇敼鐢ㄦ埛'" + loginUser.getUsername() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
+ }
+ if (userService.updateUserProfile(currentUser) > 0)
+ {
+ // 鏇存柊缂撳瓨鐢ㄦ埛淇℃伅
+ tokenService.setLoginUser(loginUser);
+ return success();
+ }
+ return error("淇敼涓汉淇℃伅寮傚父锛岃鑱旂郴绠$悊鍛�");
+ }
+
+ /**
+ * 閲嶇疆瀵嗙爜
+ */
+ @Log(title = "涓汉淇℃伅", businessType = BusinessType.UPDATE)
+ @PutMapping("/updatePwd")
+ public AjaxResult updatePwd(@RequestBody Map<String, String> params)
+ {
+ String oldPassword = params.get("oldPassword");
+ String newPassword = params.get("newPassword");
+ LoginUser loginUser = getLoginUser();
+ String userName = loginUser.getUsername();
+ String password = loginUser.getPassword();
+ if (!SecurityUtils.matchesPassword(oldPassword, password))
+ {
+ return error("淇敼瀵嗙爜澶辫触锛屾棫瀵嗙爜閿欒");
+ }
+ if (SecurityUtils.matchesPassword(newPassword, password))
+ {
+ return error("鏂板瘑鐮佷笉鑳戒笌鏃у瘑鐮佺浉鍚�");
+ }
+ newPassword = SecurityUtils.encryptPassword(newPassword);
+ if (userService.resetUserPwd(userName, newPassword) > 0)
+ {
+ // 鏇存柊缂撳瓨鐢ㄦ埛瀵嗙爜
+ loginUser.getUser().setPassword(newPassword);
+ tokenService.setLoginUser(loginUser);
+ return success();
+ }
+ return error("淇敼瀵嗙爜寮傚父锛岃鑱旂郴绠$悊鍛�");
+ }
+
+ /**
+ * 澶村儚涓婁紶
+ */
+ @Log(title = "鐢ㄦ埛澶村儚", businessType = BusinessType.UPDATE)
+ @PostMapping("/avatar")
+ public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception
+ {
+ if (!file.isEmpty())
+ {
+ LoginUser loginUser = getLoginUser();
+ String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
+ if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
+ {
+ AjaxResult ajax = AjaxResult.success();
+ ajax.put("imgUrl", avatar);
+ // 鏇存柊缂撳瓨鐢ㄦ埛澶村儚
+ loginUser.getUser().setAvatar(avatar);
+ tokenService.setLoginUser(loginUser);
+ return ajax;
+ }
+ }
+ return error("涓婁紶鍥剧墖寮傚父锛岃鑱旂郴绠$悊鍛�");
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysRegisterController.java b/src/main/java/com/ruoyi/project/system/controller/SysRegisterController.java
index ca7baf5..aa672cf 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysRegisterController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysRegisterController.java
@@ -1,33 +1,33 @@
-package com.ruoyi.project.system.controller;
-
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.framework.security.RegisterBody;
-import com.ruoyi.framework.security.service.SysRegisterService;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.project.system.service.ISysConfigService;
-import lombok.AllArgsConstructor;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * 娉ㄥ唽楠岃瘉
- *
- * @author ruoyi
- */
-@RestController
-@AllArgsConstructor
-public class SysRegisterController extends BaseController {
- private SysRegisterService registerService;
- private ISysConfigService configService;
-
- @PostMapping("/register")
- public AjaxResult register(@RequestBody RegisterBody user) {
- if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) {
- return error("褰撳墠绯荤粺娌℃湁寮�鍚敞鍐屽姛鑳斤紒");
- }
- String msg = registerService.register(user);
- return StringUtils.isEmpty(msg) ? success() : error(msg);
- }
-}
+package com.ruoyi.project.system.controller;
+
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.security.RegisterBody;
+import com.ruoyi.framework.security.service.SysRegisterService;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.project.system.service.ISysConfigService;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 娉ㄥ唽楠岃瘉
+ *
+ * @author ruoyi
+ */
+@RestController
+@AllArgsConstructor
+public class SysRegisterController extends BaseController {
+ private SysRegisterService registerService;
+ private ISysConfigService configService;
+
+ @PostMapping("/register")
+ public AjaxResult register(@RequestBody RegisterBody user) {
+ if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) {
+ return error("褰撳墠绯荤粺娌℃湁寮�鍚敞鍐屽姛鑳斤紒");
+ }
+ String msg = registerService.register(user);
+ return StringUtils.isEmpty(msg) ? success() : error(msg);
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysRoleController.java b/src/main/java/com/ruoyi/project/system/controller/SysRoleController.java
index 3b05811..5f65a8d 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysRoleController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysRoleController.java
@@ -1,255 +1,255 @@
-package com.ruoyi.project.system.controller;
-
-import java.util.List;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.security.LoginUser;
-import com.ruoyi.framework.security.service.SysPermissionService;
-import com.ruoyi.framework.security.service.TokenService;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.project.system.domain.SysDept;
-import com.ruoyi.project.system.domain.SysRole;
-import com.ruoyi.project.system.domain.SysUser;
-import com.ruoyi.project.system.domain.SysUserRole;
-import com.ruoyi.project.system.service.ISysDeptService;
-import com.ruoyi.project.system.service.ISysRoleService;
-import com.ruoyi.project.system.service.ISysUserService;
-
-/**
- * 瑙掕壊淇℃伅
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/system/role")
-@AllArgsConstructor
-public class SysRoleController extends BaseController
-{
- private ISysRoleService roleService;
- private TokenService tokenService;
- private SysPermissionService permissionService;
- private ISysUserService userService;
- private ISysDeptService deptService;
-
- @PreAuthorize("@ss.hasPermi('system:role:list')")
- @GetMapping("/list")
- public TableDataInfo list(SysRole role)
- {
- startPage();
- List<SysRole> list = roleService.selectRoleList(role);
- return getDataTable(list);
- }
-
- @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.EXPORT)
- @PreAuthorize("@ss.hasPermi('system:role:export')")
- @PostMapping("/export")
- public void export(HttpServletResponse response, SysRole role)
- {
- List<SysRole> list = roleService.selectRoleList(role);
- ExcelUtil<SysRole> util = new ExcelUtil<SysRole>(SysRole.class);
- util.exportExcel(response, list, "瑙掕壊鏁版嵁");
- }
-
- /**
- * 鏍规嵁瑙掕壊缂栧彿鑾峰彇璇︾粏淇℃伅
- */
- @PreAuthorize("@ss.hasPermi('system:role:query')")
- @GetMapping(value = "/{roleId}")
- public AjaxResult getInfo(@PathVariable Long roleId)
- {
- roleService.checkRoleDataScope(roleId);
- return success(roleService.selectRoleById(roleId));
- }
-
- /**
- * 鏂板瑙掕壊
- */
- @PreAuthorize("@ss.hasPermi('system:role:add')")
- @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.INSERT)
- @PostMapping
- public AjaxResult add(@Validated @RequestBody SysRole role)
- {
- if (!roleService.checkRoleNameUnique(role))
- {
- return error("鏂板瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹插悕绉板凡瀛樺湪");
- }
- else if (!roleService.checkRoleKeyUnique(role))
- {
- return error("鏂板瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹叉潈闄愬凡瀛樺湪");
- }
- role.setCreateBy(getUsername());
- return toAjax(roleService.insertRole(role));
-
- }
-
- /**
- * 淇敼淇濆瓨瑙掕壊
- */
- @PreAuthorize("@ss.hasPermi('system:role:edit')")
- @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
- @PutMapping
- public AjaxResult edit(@Validated @RequestBody SysRole role)
- {
- roleService.checkRoleAllowed(role);
- roleService.checkRoleDataScope(role.getRoleId());
- if (!roleService.checkRoleNameUnique(role))
- {
- return error("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹插悕绉板凡瀛樺湪");
- }
- else if (!roleService.checkRoleKeyUnique(role))
- {
- return error("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹叉潈闄愬凡瀛樺湪");
- }
- role.setUpdateBy(getUsername());
-
- if (roleService.updateRole(role) > 0)
- {
- // 鏇存柊缂撳瓨鐢ㄦ埛鏉冮檺
- LoginUser loginUser = getLoginUser();
- if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
- {
- loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
- loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
- tokenService.setLoginUser(loginUser);
- }
- return success();
- }
- return error("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑱旂郴绠$悊鍛�");
- }
-
- /**
- * 淇敼淇濆瓨鏁版嵁鏉冮檺
- */
- @PreAuthorize("@ss.hasPermi('system:role:edit')")
- @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
- @PutMapping("/dataScope")
- public AjaxResult dataScope(@RequestBody SysRole role)
- {
- roleService.checkRoleAllowed(role);
- roleService.checkRoleDataScope(role.getRoleId());
- return toAjax(roleService.authDataScope(role));
- }
-
- /**
- * 鐘舵�佷慨鏀�
- */
- @PreAuthorize("@ss.hasPermi('system:role:edit')")
- @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
- @PutMapping("/changeStatus")
- public AjaxResult changeStatus(@RequestBody SysRole role)
- {
- roleService.checkRoleAllowed(role);
- roleService.checkRoleDataScope(role.getRoleId());
- role.setUpdateBy(getUsername());
- return toAjax(roleService.updateRoleStatus(role));
- }
-
- /**
- * 鍒犻櫎瑙掕壊
- */
- @PreAuthorize("@ss.hasPermi('system:role:remove')")
- @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.DELETE)
- @DeleteMapping("/{roleIds}")
- public AjaxResult remove(@PathVariable Long[] roleIds)
- {
- return toAjax(roleService.deleteRoleByIds(roleIds));
- }
-
- /**
- * 鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
- */
- @PreAuthorize("@ss.hasPermi('system:role:query')")
- @GetMapping("/optionselect")
- public AjaxResult optionselect()
- {
- return success(roleService.selectRoleAll());
- }
-
- /**
- * 鏌ヨ宸插垎閰嶇敤鎴疯鑹插垪琛�
- */
- @PreAuthorize("@ss.hasPermi('system:role:list')")
- @GetMapping("/authUser/allocatedList")
- public TableDataInfo allocatedList(SysUser user)
- {
- startPage();
- List<SysUser> list = userService.selectAllocatedList(user);
- return getDataTable(list);
- }
-
- /**
- * 鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
- */
- @PreAuthorize("@ss.hasPermi('system:role:list')")
- @GetMapping("/authUser/unallocatedList")
- public TableDataInfo unallocatedList(SysUser user)
- {
- startPage();
- List<SysUser> list = userService.selectUnallocatedList(user);
- return getDataTable(list);
- }
-
- /**
- * 鍙栨秷鎺堟潈鐢ㄦ埛
- */
- @PreAuthorize("@ss.hasPermi('system:role:edit')")
- @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
- @PutMapping("/authUser/cancel")
- public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
- {
- return toAjax(roleService.deleteAuthUser(userRole));
- }
-
- /**
- * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛
- */
- @PreAuthorize("@ss.hasPermi('system:role:edit')")
- @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
- @PutMapping("/authUser/cancelAll")
- public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds)
- {
- return toAjax(roleService.deleteAuthUsers(roleId, userIds));
- }
-
- /**
- * 鎵归噺閫夋嫨鐢ㄦ埛鎺堟潈
- */
- @PreAuthorize("@ss.hasPermi('system:role:edit')")
- @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
- @PutMapping("/authUser/selectAll")
- public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds)
- {
- roleService.checkRoleDataScope(roleId);
- return toAjax(roleService.insertAuthUsers(roleId, userIds));
- }
-
- /**
- * 鑾峰彇瀵瑰簲瑙掕壊閮ㄩ棬鏍戝垪琛�
- */
- @PreAuthorize("@ss.hasPermi('system:role:query')")
- @GetMapping(value = "/deptTree/{roleId}")
- public AjaxResult deptTree(@PathVariable("roleId") Long roleId)
- {
- AjaxResult ajax = AjaxResult.success();
- ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
- ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
- return ajax;
- }
-}
+package com.ruoyi.project.system.controller;
+
+import java.util.List;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.framework.security.service.SysPermissionService;
+import com.ruoyi.framework.security.service.TokenService;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.system.domain.SysDept;
+import com.ruoyi.project.system.domain.SysRole;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.domain.SysUserRole;
+import com.ruoyi.project.system.service.ISysDeptService;
+import com.ruoyi.project.system.service.ISysRoleService;
+import com.ruoyi.project.system.service.ISysUserService;
+
+/**
+ * 瑙掕壊淇℃伅
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/role")
+@AllArgsConstructor
+public class SysRoleController extends BaseController
+{
+ private ISysRoleService roleService;
+ private TokenService tokenService;
+ private SysPermissionService permissionService;
+ private ISysUserService userService;
+ private ISysDeptService deptService;
+
+ @PreAuthorize("@ss.hasPermi('system:role:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysRole role)
+ {
+ startPage();
+ List<SysRole> list = roleService.selectRoleList(role);
+ return getDataTable(list);
+ }
+
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('system:role:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysRole role)
+ {
+ List<SysRole> list = roleService.selectRoleList(role);
+ ExcelUtil<SysRole> util = new ExcelUtil<SysRole>(SysRole.class);
+ util.exportExcel(response, list, "瑙掕壊鏁版嵁");
+ }
+
+ /**
+ * 鏍规嵁瑙掕壊缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:query')")
+ @GetMapping(value = "/{roleId}")
+ public AjaxResult getInfo(@PathVariable Long roleId)
+ {
+ roleService.checkRoleDataScope(roleId);
+ return success(roleService.selectRoleById(roleId));
+ }
+
+ /**
+ * 鏂板瑙掕壊
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:add')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysRole role)
+ {
+ if (!roleService.checkRoleNameUnique(role))
+ {
+ return error("鏂板瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹插悕绉板凡瀛樺湪");
+ }
+ else if (!roleService.checkRoleKeyUnique(role))
+ {
+ return error("鏂板瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹叉潈闄愬凡瀛樺湪");
+ }
+ role.setCreateBy(getUsername());
+ return toAjax(roleService.insertRole(role));
+
+ }
+
+ /**
+ * 淇敼淇濆瓨瑙掕壊
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:edit')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysRole role)
+ {
+ roleService.checkRoleAllowed(role);
+ roleService.checkRoleDataScope(role.getRoleId());
+ if (!roleService.checkRoleNameUnique(role))
+ {
+ return error("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹插悕绉板凡瀛樺湪");
+ }
+ else if (!roleService.checkRoleKeyUnique(role))
+ {
+ return error("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹叉潈闄愬凡瀛樺湪");
+ }
+ role.setUpdateBy(getUsername());
+
+ if (roleService.updateRole(role) > 0)
+ {
+ // 鏇存柊缂撳瓨鐢ㄦ埛鏉冮檺
+ LoginUser loginUser = getLoginUser();
+ if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
+ {
+ loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
+ loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
+ tokenService.setLoginUser(loginUser);
+ }
+ return success();
+ }
+ return error("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑱旂郴绠$悊鍛�");
+ }
+
+ /**
+ * 淇敼淇濆瓨鏁版嵁鏉冮檺
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:edit')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping("/dataScope")
+ public AjaxResult dataScope(@RequestBody SysRole role)
+ {
+ roleService.checkRoleAllowed(role);
+ roleService.checkRoleDataScope(role.getRoleId());
+ return toAjax(roleService.authDataScope(role));
+ }
+
+ /**
+ * 鐘舵�佷慨鏀�
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:edit')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping("/changeStatus")
+ public AjaxResult changeStatus(@RequestBody SysRole role)
+ {
+ roleService.checkRoleAllowed(role);
+ roleService.checkRoleDataScope(role.getRoleId());
+ role.setUpdateBy(getUsername());
+ return toAjax(roleService.updateRoleStatus(role));
+ }
+
+ /**
+ * 鍒犻櫎瑙掕壊
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:remove')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{roleIds}")
+ public AjaxResult remove(@PathVariable Long[] roleIds)
+ {
+ return toAjax(roleService.deleteRoleByIds(roleIds));
+ }
+
+ /**
+ * 鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:query')")
+ @GetMapping("/optionselect")
+ public AjaxResult optionselect()
+ {
+ return success(roleService.selectRoleAll());
+ }
+
+ /**
+ * 鏌ヨ宸插垎閰嶇敤鎴疯鑹插垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:list')")
+ @GetMapping("/authUser/allocatedList")
+ public TableDataInfo allocatedList(SysUser user)
+ {
+ startPage();
+ List<SysUser> list = userService.selectAllocatedList(user);
+ return getDataTable(list);
+ }
+
+ /**
+ * 鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:list')")
+ @GetMapping("/authUser/unallocatedList")
+ public TableDataInfo unallocatedList(SysUser user)
+ {
+ startPage();
+ List<SysUser> list = userService.selectUnallocatedList(user);
+ return getDataTable(list);
+ }
+
+ /**
+ * 鍙栨秷鎺堟潈鐢ㄦ埛
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:edit')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
+ @PutMapping("/authUser/cancel")
+ public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
+ {
+ return toAjax(roleService.deleteAuthUser(userRole));
+ }
+
+ /**
+ * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:edit')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
+ @PutMapping("/authUser/cancelAll")
+ public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds)
+ {
+ return toAjax(roleService.deleteAuthUsers(roleId, userIds));
+ }
+
+ /**
+ * 鎵归噺閫夋嫨鐢ㄦ埛鎺堟潈
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:edit')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
+ @PutMapping("/authUser/selectAll")
+ public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds)
+ {
+ roleService.checkRoleDataScope(roleId);
+ return toAjax(roleService.insertAuthUsers(roleId, userIds));
+ }
+
+ /**
+ * 鑾峰彇瀵瑰簲瑙掕壊閮ㄩ棬鏍戝垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:query')")
+ @GetMapping(value = "/deptTree/{roleId}")
+ public AjaxResult deptTree(@PathVariable("roleId") Long roleId)
+ {
+ AjaxResult ajax = AjaxResult.success();
+ ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
+ ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
+ return ajax;
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysUserController.java b/src/main/java/com/ruoyi/project/system/controller/SysUserController.java
index 332d6b5..9e15e50 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysUserController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysUserController.java
@@ -1,292 +1,289 @@
-package com.ruoyi.project.system.controller;
-
-import java.util.List;
-import java.util.stream.Collectors;
-import jakarta.servlet.http.HttpServletResponse;
-
-import com.ruoyi.project.system.domain.vo.SysUserDeptVo;
-import com.ruoyi.project.system.mapper.SysUserMapper;
-import com.ruoyi.project.system.service.*;
-import lombok.AllArgsConstructor;
-import org.apache.commons.lang3.ArrayUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.multipart.MultipartFile;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.project.system.domain.SysDept;
-import com.ruoyi.project.system.domain.SysRole;
-import com.ruoyi.project.system.domain.SysUser;
-
-/**
- * 鐢ㄦ埛淇℃伅
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/system/user")
-@AllArgsConstructor
-public class SysUserController extends BaseController
-{
- private ISysUserService userService;
- private ISysRoleService roleService;
- private ISysDeptService deptService;
- private ISysPostService postService;
- private ISysUserDeptService userDeptService;
-
- /**
- * 鑾峰彇鐢ㄦ埛鍒楄〃
- */
- @PreAuthorize("@ss.hasPermi('system:user:list')")
- @GetMapping("/list")
- public TableDataInfo list(SysUser user)
- {
- startPage();
- List<SysUser> list = userService.selectUserList(user);
- return getDataTable(list);
- }
-
- /**
- * 鑾峰彇鐢ㄦ埛鍒楄〃
- */
- @PreAuthorize("@ss.hasPermi('system:user:list')")
- @GetMapping("/listAll")
- public AjaxResult listAll(SysUser user)
- {
- List<SysUser> list = userService.selectUserList(user);
- return AjaxResult.success(list);
- }
-
- @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.EXPORT)
- @PreAuthorize("@ss.hasPermi('system:user:export')")
- @PostMapping("/export")
- public void export(HttpServletResponse response, SysUser user)
- {
- List<SysUser> list = userService.selectUserList(user);
- ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
- util.exportExcel(response, list, "鐢ㄦ埛鏁版嵁");
- }
-
- @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.IMPORT)
- @PreAuthorize("@ss.hasPermi('system:user:import')")
- @PostMapping("/importData")
- public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
- {
- ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
- List<SysUser> userList = util.importExcel(file.getInputStream());
- String operName = getUsername();
- String message = userService.importUser(userList, updateSupport, operName);
- return success(message);
- }
-
- @PostMapping("/importTemplate")
- public void importTemplate(HttpServletResponse response)
- {
- ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
- util.importTemplateExcel(response, "鐢ㄦ埛鏁版嵁");
- }
-
- /**
- * 鏍规嵁鐢ㄦ埛缂栧彿鑾峰彇璇︾粏淇℃伅
- */
- @PreAuthorize("@ss.hasPermi('system:user:query')")
- @GetMapping(value = { "/", "/{userId}" })
- public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
- {
- AjaxResult ajax = AjaxResult.success();
- if (StringUtils.isNotNull(userId))
- {
- userService.checkUserDataScope(userId);
- SysUser sysUser = userService.selectUserById(userId);
- ajax.put(AjaxResult.DATA_TAG, sysUser);
- ajax.put("postIds", postService.selectPostListByUserId(userId));
- ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
- }
- List<SysRole> roles = roleService.selectRoleAll();
- ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
- ajax.put("posts", postService.selectPostAll());
- SysUserDeptVo sysUserDeptVo = new SysUserDeptVo();
- sysUserDeptVo.setUserId(userId);
- List<SysUserDeptVo> sysUserDeptVos = userDeptService.userLoginFacotryList(sysUserDeptVo);
- ajax.put("deptIds",sysUserDeptVos.stream().map(SysUserDeptVo::getDeptId).collect(Collectors.toList()));
- return ajax;
- }
-
- /**
- * 鏂板鐢ㄦ埛
- */
- @PreAuthorize("@ss.hasPermi('system:user:add')")
- @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.INSERT)
- @PostMapping
- public AjaxResult add(@Validated @RequestBody SysUser user)
- {
- roleService.checkRoleDataScope(user.getRoleIds());
- if (!userService.checkUserNameUnique(user))
- {
- return error("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岀櫥褰曡处鍙峰凡瀛樺湪");
- }
- else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
- {
- return error("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
- }
- else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
- {
- return error("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
- }
- user.setCreateBy(getUsername());
- user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
- user.setTenantId(user.getDeptId());
- return toAjax(userService.insertUser(user));
- }
-
- /**
- * 淇敼鐢ㄦ埛
- */
- @PreAuthorize("@ss.hasPermi('system:user:edit')")
- @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
- @PutMapping
- public AjaxResult edit(@Validated @RequestBody SysUser user)
- {
- userService.checkUserAllowed(user);
- userService.checkUserDataScope(user.getUserId());
- roleService.checkRoleDataScope(user.getRoleIds());
- if (!userService.checkUserNameUnique(user))
- {
- return error("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岀櫥褰曡处鍙峰凡瀛樺湪");
- }
- else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
- {
- return error("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
- }
- else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
- {
- return error("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
- }
- user.setUpdateBy(getUsername());
- userService.bindUserDept(user);
- return toAjax(userService.updateUser(user));
- }
-
- /**
- * 鍒犻櫎鐢ㄦ埛
- */
- @PreAuthorize("@ss.hasPermi('system:user:remove')")
- @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.DELETE)
- @DeleteMapping("/{userIds}")
- public AjaxResult remove(@PathVariable Long[] userIds)
- {
- if (ArrayUtils.contains(userIds, getUserId()))
- {
- return error("褰撳墠鐢ㄦ埛涓嶈兘鍒犻櫎");
- }
- return toAjax(userService.deleteUserByIds(userIds));
- }
-
- /**
- * 閲嶇疆瀵嗙爜
- */
- @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
- @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
- @PutMapping("/resetPwd")
- public AjaxResult resetPwd(@RequestBody SysUser user)
- {
- userService.checkUserAllowed(user);
- userService.checkUserDataScope(user.getUserId());
- user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
- user.setUpdateBy(getUsername());
- return toAjax(userService.resetPwd(user));
- }
-
- /**
- * 鐘舵�佷慨鏀�
- */
- @PreAuthorize("@ss.hasPermi('system:user:edit')")
- @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
- @PutMapping("/changeStatus")
- public AjaxResult changeStatus(@RequestBody SysUser user)
- {
- userService.checkUserAllowed(user);
- userService.checkUserDataScope(user.getUserId());
- user.setUpdateBy(getUsername());
- return toAjax(userService.updateUserStatus(user));
- }
-
- /**
- * 鏍规嵁鐢ㄦ埛缂栧彿鑾峰彇鎺堟潈瑙掕壊
- */
- @PreAuthorize("@ss.hasPermi('system:user:query')")
- @GetMapping("/authRole/{userId}")
- public AjaxResult authRole(@PathVariable("userId") Long userId)
- {
- AjaxResult ajax = AjaxResult.success();
- SysUser user = userService.selectUserById(userId);
- List<SysRole> roles = roleService.selectRolesByUserId(userId);
- ajax.put("user", user);
- ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
- return ajax;
- }
-
- /**
- * 鐢ㄦ埛鎺堟潈瑙掕壊
- */
- @PreAuthorize("@ss.hasPermi('system:user:edit')")
- @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.GRANT)
- @PutMapping("/authRole")
- public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
- {
- userService.checkUserDataScope(userId);
- roleService.checkRoleDataScope(roleIds);
- userService.insertUserAuth(userId, roleIds);
- return success();
- }
-
- /**
- * 鑾峰彇閮ㄩ棬鏍戝垪琛�
- */
- @PreAuthorize("@ss.hasPermi('system:user:list')")
- @GetMapping("/deptTree")
- public AjaxResult deptTree(SysDept dept)
- {
- return success(deptService.selectDeptTreeList(dept));
- }
-
- /**
- * 涓嶅垎椤电敤鎴锋煡璇�
- * @param user
- * @return
- */
- @GetMapping("/userListNoPage")
- public AjaxResult userListNoPage(SysUser user){
- List<SysUser> sysUserList = userService.userListNoPage(user);
- return AjaxResult.success(sysUserList);
- }
-
- /**
- * 鏌ヨ褰撳墠鐢ㄦ埛鍏徃涓嬫墍鏈夌敤鎴�
- * @param user
- * @return
- */
- @GetMapping("/userListNoPageByTenantId")
- public AjaxResult userListNoPageByTenantId(SysUser user){
- //鑾峰彇鐧诲綍鐢ㄦ埛淇℃伅
- SysUser loginUser = SecurityUtils.getLoginUser().getUser();
- user.setTenantId(loginUser.getTenantId());
- List<SysUser> sysUserList = userService.userListNoPage(user);
- return AjaxResult.success(sysUserList);
- }
-}
+package com.ruoyi.project.system.controller;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import jakarta.servlet.http.HttpServletResponse;
+
+import com.ruoyi.project.system.domain.vo.SysUserDeptVo;
+import com.ruoyi.project.system.mapper.SysUserMapper;
+import com.ruoyi.project.system.service.*;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.ArrayUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.system.domain.SysDept;
+import com.ruoyi.project.system.domain.SysRole;
+import com.ruoyi.project.system.domain.SysUser;
+
+/**
+ * 鐢ㄦ埛淇℃伅
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/user")
+@AllArgsConstructor
+public class SysUserController extends BaseController
+{
+ private ISysUserService userService;
+ private ISysRoleService roleService;
+ private ISysDeptService deptService;
+ private ISysPostService postService;
+ private ISysUserDeptService userDeptService;
+
+ /**
+ * 鑾峰彇鐢ㄦ埛鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysUser user)
+ {
+ startPage();
+ List<SysUser> list = userService.selectUserList(user);
+ return getDataTable(list);
+ }
+
+ /**
+ * 鑾峰彇鐢ㄦ埛鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:list')")
+ @GetMapping("/listAll")
+ public AjaxResult listAll(SysUser user)
+ {
+ List<SysUser> list = userService.selectUserList(user);
+ return AjaxResult.success(list);
+ }
+
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('system:user:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysUser user)
+ {
+ List<SysUser> list = userService.selectUserList(user);
+ ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
+ util.exportExcel(response, list, "鐢ㄦ埛鏁版嵁");
+ }
+
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.IMPORT)
+ @PreAuthorize("@ss.hasPermi('system:user:import')")
+ @PostMapping("/importData")
+ public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
+ {
+ ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
+ List<SysUser> userList = util.importExcel(file.getInputStream());
+ String operName = getUsername();
+ String message = userService.importUser(userList, updateSupport, operName);
+ return success(message);
+ }
+
+ @PostMapping("/importTemplate")
+ public void importTemplate(HttpServletResponse response)
+ {
+ ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
+ util.importTemplateExcel(response, "鐢ㄦ埛鏁版嵁");
+ }
+
+ /**
+ * 鏍规嵁鐢ㄦ埛缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:query')")
+ @GetMapping(value = { "/", "/{userId}" })
+ public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
+ {
+ AjaxResult ajax = AjaxResult.success();
+ if (StringUtils.isNotNull(userId))
+ {
+ userService.checkUserDataScope(userId);
+ SysUser sysUser = userService.selectUserById(userId);
+ ajax.put(AjaxResult.DATA_TAG, sysUser);
+ ajax.put("postIds", postService.selectPostListByUserId(userId));
+ ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
+ }
+ List<SysRole> roles = roleService.selectRoleAll();
+ ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
+ ajax.put("posts", postService.selectPostAll());
+ ajax.put("deptIds", userService.selectDeptIdsByUserId(userId));
+ return ajax;
+ }
+
+ /**
+ * 鏂板鐢ㄦ埛
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:add')")
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysUser user)
+ {
+ roleService.checkRoleDataScope(user.getRoleIds());
+ if (!userService.checkUserNameUnique(user))
+ {
+ return error("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岀櫥褰曡处鍙峰凡瀛樺湪");
+ }
+ else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
+ {
+ return error("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
+ }
+ else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
+ {
+ return error("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
+ }
+ user.setCreateBy(getUsername());
+ user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
+ user.setTenantId(user.getDeptId());
+ return toAjax(userService.insertUser(user));
+ }
+
+ /**
+ * 淇敼鐢ㄦ埛
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:edit')")
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysUser user)
+ {
+ userService.checkUserAllowed(user);
+ userService.checkUserDataScope(user.getUserId());
+ roleService.checkRoleDataScope(user.getRoleIds());
+ if (!userService.checkUserNameUnique(user))
+ {
+ return error("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岀櫥褰曡处鍙峰凡瀛樺湪");
+ }
+ else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
+ {
+ return error("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
+ }
+ else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
+ {
+ return error("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
+ }
+ user.setUpdateBy(getUsername());
+ userService.bindUserDept(user);
+ return toAjax(userService.updateUser(user));
+ }
+
+ /**
+ * 鍒犻櫎鐢ㄦ埛
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:remove')")
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{userIds}")
+ public AjaxResult remove(@PathVariable Long[] userIds)
+ {
+ if (ArrayUtils.contains(userIds, getUserId()))
+ {
+ return error("褰撳墠鐢ㄦ埛涓嶈兘鍒犻櫎");
+ }
+ return toAjax(userService.deleteUserByIds(userIds));
+ }
+
+ /**
+ * 閲嶇疆瀵嗙爜
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping("/resetPwd")
+ public AjaxResult resetPwd(@RequestBody SysUser user)
+ {
+ userService.checkUserAllowed(user);
+ userService.checkUserDataScope(user.getUserId());
+ user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
+ user.setUpdateBy(getUsername());
+ return toAjax(userService.resetPwd(user));
+ }
+
+ /**
+ * 鐘舵�佷慨鏀�
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:edit')")
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping("/changeStatus")
+ public AjaxResult changeStatus(@RequestBody SysUser user)
+ {
+ userService.checkUserAllowed(user);
+ userService.checkUserDataScope(user.getUserId());
+ user.setUpdateBy(getUsername());
+ return toAjax(userService.updateUserStatus(user));
+ }
+
+ /**
+ * 鏍规嵁鐢ㄦ埛缂栧彿鑾峰彇鎺堟潈瑙掕壊
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:query')")
+ @GetMapping("/authRole/{userId}")
+ public AjaxResult authRole(@PathVariable("userId") Long userId)
+ {
+ AjaxResult ajax = AjaxResult.success();
+ SysUser user = userService.selectUserById(userId);
+ List<SysRole> roles = roleService.selectRolesByUserId(userId);
+ ajax.put("user", user);
+ ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
+ return ajax;
+ }
+
+ /**
+ * 鐢ㄦ埛鎺堟潈瑙掕壊
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:edit')")
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.GRANT)
+ @PutMapping("/authRole")
+ public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
+ {
+ userService.checkUserDataScope(userId);
+ roleService.checkRoleDataScope(roleIds);
+ userService.insertUserAuth(userId, roleIds);
+ return success();
+ }
+
+ /**
+ * 鑾峰彇閮ㄩ棬鏍戝垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:list')")
+ @GetMapping("/deptTree")
+ public AjaxResult deptTree(SysDept dept)
+ {
+ return success(deptService.selectDeptTreeList(dept));
+ }
+
+ /**
+ * 涓嶅垎椤电敤鎴锋煡璇�
+ * @param user
+ * @return
+ */
+ @GetMapping("/userListNoPage")
+ public AjaxResult userListNoPage(SysUser user){
+ List<SysUser> sysUserList = userService.userListNoPage(user);
+ return AjaxResult.success(sysUserList);
+ }
+
+ /**
+ * 鏌ヨ褰撳墠鐢ㄦ埛鍏徃涓嬫墍鏈夌敤鎴�
+ * @param user
+ * @return
+ */
+ @GetMapping("/userListNoPageByTenantId")
+ public AjaxResult userListNoPageByTenantId(SysUser user){
+ //鑾峰彇鐧诲綍鐢ㄦ埛淇℃伅
+ SysUser loginUser = SecurityUtils.getLoginUser().getUser();
+ user.setTenantId(loginUser.getTenantId());
+ List<SysUser> sysUserList = userService.userListNoPage(user);
+ return AjaxResult.success(sysUserList);
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java b/src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java
index 8c0ca53..f5baaec 100644
--- a/src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java
+++ b/src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.project.system.domain.SysUserDept;
import com.ruoyi.project.system.domain.vo.SysUserDeptVo;
+import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -15,4 +16,28 @@
List<SysUserDeptVo> userLoginFacotryList(@Param("userDeptVo") SysUserDeptVo userDeptVo);
List<Map<String, Object>> setSchemeApplicableStaffUserInfo(@Param("ids") List<Long> ids);
+
+ @Select("<script>" +
+ "select count(distinct sud.user_id) " +
+ "from sys_user_dept sud " +
+ "inner join sys_user su on su.user_id = sud.user_id " +
+ "where su.del_flag = '0' " +
+ "and sud.dept_id in " +
+ "<foreach collection='deptIds' item='deptId' open='(' separator=',' close=')'>" +
+ "#{deptId}" +
+ "</foreach>" +
+ "</script>")
+ Long countDistinctUserIdsByDeptIds(@Param("deptIds") List<Long> deptIds);
+
+ @Select("<script>" +
+ "select distinct sud.user_id " +
+ "from sys_user_dept sud " +
+ "inner join sys_user su on su.user_id = sud.user_id " +
+ "where su.del_flag = '0' " +
+ "and sud.dept_id in " +
+ "<foreach collection='deptIds' item='deptId' open='(' separator=',' close=')'>" +
+ "#{deptId}" +
+ "</foreach>" +
+ "</script>")
+ List<Long> selectDistinctUserIdsByDeptIds(@Param("deptIds") List<Long> deptIds);
}
diff --git a/src/main/java/com/ruoyi/project/system/service/ISysUserService.java b/src/main/java/com/ruoyi/project/system/service/ISysUserService.java
index 7d5ba4a..e3be5f4 100644
--- a/src/main/java/com/ruoyi/project/system/service/ISysUserService.java
+++ b/src/main/java/com/ruoyi/project/system/service/ISysUserService.java
@@ -217,4 +217,11 @@
* @return
*/
int bindUserDept(SysUser user);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ鎵�鏈夊叧鑱旂殑閮ㄩ棬ID
+ * @param userId
+ * @return
+ */
+ List<Long> selectDeptIdsByUserId(Long userId);
}
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java
index dcbcded..d04239f 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java
@@ -4,6 +4,8 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsMapper;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysNotice;
@@ -18,8 +20,12 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.stream.Collectors;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* 鍏憡 鏈嶅姟灞傚疄鐜�
@@ -30,11 +36,14 @@
@RequiredArgsConstructor
public class SysNoticeServiceImpl extends ServiceImpl<SysNoticeMapper, SysNotice> implements ISysNoticeService {
+ private static final Pattern ENTERPRISE_NEWS_ID_PATTERN = Pattern.compile("[?&]id=(\\d+)");
+
private final SysNoticeMapper noticeMapper;
private final SysUserMapper userMapper;
private final SysDeptMapper deptMapper;
private final SysUserDeptMapper userDeptMapper;
private final UnipushService unipushService;
+ private final EnterpriseNewsMapper enterpriseNewsMapper;
/**
* 鏌ヨ鍏憡淇℃伅
@@ -78,9 +87,24 @@
* @return 缁撴灉
*/
@Override
+ @Transactional(rollbackFor = Exception.class)
public int updateNotice(SysNotice notice)
{
- return noticeMapper.updateNotice(notice);
+ if (notice == null || notice.getNoticeId() == null) {
+ return 0;
+ }
+ SysNotice dbNotice = noticeMapper.selectNoticeById(notice.getNoticeId());
+ if (dbNotice == null) {
+ return 0;
+ }
+ boolean needSyncNewsReadCount = isEnterpriseNewsNotice(dbNotice)
+ && notice.getStatus() != null
+ && !notice.getStatus().equals(dbNotice.getStatus());
+ int rows = noticeMapper.updateNotice(notice);
+ if (rows > 0 && needSyncNewsReadCount) {
+ syncEnterpriseNewsReadCount(dbNotice.getJumpPath());
+ }
+ return rows;
}
/**
@@ -117,10 +141,17 @@
@Override
public int readAll() {
Long userId = SecurityUtils.getUserId();
- return noticeMapper.update(null, Wrappers.<SysNotice>lambdaUpdate()
+ List<SysNotice> unreadNotices = noticeMapper.selectList(Wrappers.<SysNotice>lambdaQuery()
+ .eq(SysNotice::getConsigneeId, userId)
+ .eq(SysNotice::getStatus, "0"));
+ int rows = noticeMapper.update(null, Wrappers.<SysNotice>lambdaUpdate()
.eq(SysNotice::getConsigneeId, userId)
.eq(SysNotice::getStatus, "0")
.set(SysNotice::getStatus, "1"));
+ if (rows > 0) {
+ syncEnterpriseNewsReadCount(unreadNotices);
+ }
+ return rows;
}
@Override
@@ -220,9 +251,63 @@
return false;
}
sysNotice.setStatus("1");
- return noticeMapper.update(null, Wrappers.<SysNotice>lambdaUpdate()
+ boolean updated = noticeMapper.update(null, Wrappers.<SysNotice>lambdaUpdate()
.eq(SysNotice::getNoticeId, noticeId)
.eq(SysNotice::getStatus, "0")
.set(SysNotice::getStatus, "1")) > 0;
+ if (updated) {
+ syncEnterpriseNewsReadCount(sysNotice.getJumpPath());
+ }
+ return updated;
+ }
+
+ private boolean isEnterpriseNewsNotice(SysNotice sysNotice) {
+ return sysNotice != null
+ && sysNotice.getJumpPath() != null
+ && sysNotice.getJumpPath().contains("/enterpriseNews?id=");
+ }
+
+ private void syncEnterpriseNewsReadCount(List<SysNotice> notices) {
+ if (notices == null || notices.isEmpty()) {
+ return;
+ }
+ Set<String> jumpPaths = new HashSet<>();
+ for (SysNotice notice : notices) {
+ if (isEnterpriseNewsNotice(notice)) {
+ jumpPaths.add(notice.getJumpPath());
+ }
+ }
+ for (String jumpPath : jumpPaths) {
+ syncEnterpriseNewsReadCount(jumpPath);
+ }
+ }
+
+ private void syncEnterpriseNewsReadCount(String jumpPath) {
+ Long newsId = parseEnterpriseNewsId(jumpPath);
+ if (newsId == null) {
+ return;
+ }
+ long readCount = noticeMapper.selectCount(Wrappers.<SysNotice>lambdaQuery()
+ .eq(SysNotice::getStatus, "1")
+ .eq(SysNotice::getJumpPath, jumpPath));
+ EnterpriseNews enterpriseNews = new EnterpriseNews();
+ enterpriseNews.setId(newsId);
+ enterpriseNews.setReadCount((int) readCount);
+ enterpriseNewsMapper.updateById(enterpriseNews);
+ }
+
+ private Long parseEnterpriseNewsId(String jumpPath) {
+ if (jumpPath == null || !jumpPath.startsWith("/enterpriseNews")) {
+ return null;
+ }
+ Matcher matcher = ENTERPRISE_NEWS_ID_PATTERN.matcher(jumpPath);
+ if (!matcher.find()) {
+ return null;
+ }
+ try {
+ return Long.parseLong(matcher.group(1));
+ } catch (NumberFormatException e) {
+ return null;
+ }
}
}
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java
index 39f7234..01addd4 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java
@@ -560,4 +560,11 @@
}
return user.getDeptIds().length;
}
+
+ @Override
+ public List<Long> selectDeptIdsByUserId(Long userId) {
+ LambdaQueryWrapper<SysUserDept> queryWrapper = new LambdaQueryWrapper<>();
+ queryWrapper.eq(SysUserDept::getUserId, userId);
+ return sysUserDeptMapper.selectList(queryWrapper).stream().map(SysUserDept::getDeptId).collect(Collectors.toList());
+ }
}
diff --git a/src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java b/src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java
index ec16cea..a94fe62 100644
--- a/src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java
+++ b/src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java
@@ -1,255 +1,255 @@
-package com.ruoyi.project.tool.gen.controller;
-
-import com.alibaba.druid.DbType;
-import com.alibaba.druid.sql.SQLUtils;
-import com.alibaba.druid.sql.ast.SQLStatement;
-import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
-import com.ruoyi.common.core.text.Convert;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.common.utils.sql.SqlUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.config.GenConfig;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.project.tool.gen.domain.GenTable;
-import com.ruoyi.project.tool.gen.domain.GenTableColumn;
-import com.ruoyi.project.tool.gen.service.IGenTableColumnService;
-import com.ruoyi.project.tool.gen.service.IGenTableService;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AllArgsConstructor;
-import org.apache.commons.io.IOUtils;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 浠g爜鐢熸垚 鎿嶄綔澶勭悊
- *
- * @author ruoyi
- */
-@RestController
-@RequestMapping("/tool/gen")
-@AllArgsConstructor
-public class GenController extends BaseController
-{
- private IGenTableService genTableService;
- private IGenTableColumnService genTableColumnService;
-
- /**
- * 鏌ヨ浠g爜鐢熸垚鍒楄〃
- */
- @PreAuthorize("@ss.hasPermi('tool:gen:list')")
- @GetMapping("/list")
- public TableDataInfo genList(GenTable genTable)
- {
- startPage();
- List<GenTable> list = genTableService.selectGenTableList(genTable);
- return getDataTable(list);
- }
-
- /**
- * 鑾峰彇浠g爜鐢熸垚淇℃伅
- */
- @PreAuthorize("@ss.hasPermi('tool:gen:query')")
- @GetMapping(value = "/{talbleId}")
- public AjaxResult getInfo(@PathVariable Long talbleId)
- {
- GenTable table = genTableService.selectGenTableById(talbleId);
- List<GenTable> tables = genTableService.selectGenTableAll();
- List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(talbleId);
- Map<String, Object> map = new HashMap<String, Object>();
- map.put("info", table);
- map.put("rows", list);
- map.put("tables", tables);
- return success(map);
- }
-
- /**
- * 鏌ヨ鏁版嵁搴撳垪琛�
- */
- @PreAuthorize("@ss.hasPermi('tool:gen:list')")
- @GetMapping("/db/list")
- public TableDataInfo dataList(GenTable genTable)
- {
- startPage();
- List<GenTable> list = genTableService.selectDbTableList(genTable);
- return getDataTable(list);
- }
-
- /**
- * 鏌ヨ鏁版嵁琛ㄥ瓧娈靛垪琛�
- */
- @PreAuthorize("@ss.hasPermi('tool:gen:list')")
- @GetMapping(value = "/column/{tableId}")
- public TableDataInfo columnList(Long tableId)
- {
- TableDataInfo dataInfo = new TableDataInfo();
- List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(tableId);
- dataInfo.setRows(list);
- dataInfo.setTotal(list.size());
- return dataInfo;
- }
-
- /**
- * 瀵煎叆琛ㄧ粨鏋勶紙淇濆瓨锛�
- */
- @PreAuthorize("@ss.hasPermi('tool:gen:import')")
- @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.IMPORT)
- @PostMapping("/importTable")
- public AjaxResult importTableSave(String tables)
- {
- String[] tableNames = Convert.toStrArray(tables);
- // 鏌ヨ琛ㄤ俊鎭�
- List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
- genTableService.importGenTable(tableList, SecurityUtils.getUsername());
- return success();
- }
-
- /**
- * 鍒涘缓琛ㄧ粨鏋勶紙淇濆瓨锛�
- */
- @PreAuthorize("@ss.hasRole('admin')")
- @Log(title = "鍒涘缓琛�", businessType = BusinessType.OTHER)
- @PostMapping("/createTable")
- public AjaxResult createTableSave(String sql)
- {
- try
- {
- SqlUtil.filterKeyword(sql);
- List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, DbType.mysql);
- List<String> tableNames = new ArrayList<>();
- for (SQLStatement sqlStatement : sqlStatements)
- {
- if (sqlStatement instanceof MySqlCreateTableStatement)
- {
- MySqlCreateTableStatement createTableStatement = (MySqlCreateTableStatement) sqlStatement;
- if (genTableService.createTable(createTableStatement.toString()))
- {
- String tableName = createTableStatement.getTableName().replaceAll("`", "");
- tableNames.add(tableName);
- }
- }
- }
- List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames.toArray(new String[tableNames.size()]));
- String operName = SecurityUtils.getUsername();
- genTableService.importGenTable(tableList, operName);
- return AjaxResult.success();
- }
- catch (Exception e)
- {
- logger.error(e.getMessage(), e);
- return AjaxResult.error("鍒涘缓琛ㄧ粨鏋勫紓甯�");
- }
- }
-
- /**
- * 淇敼淇濆瓨浠g爜鐢熸垚涓氬姟
- */
- @PreAuthorize("@ss.hasPermi('tool:gen:edit')")
- @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.UPDATE)
- @PutMapping
- public AjaxResult editSave(@Validated @RequestBody GenTable genTable)
- {
- genTableService.validateEdit(genTable);
- genTableService.updateGenTable(genTable);
- return success();
- }
-
- /**
- * 鍒犻櫎浠g爜鐢熸垚
- */
- @PreAuthorize("@ss.hasPermi('tool:gen:remove')")
- @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.DELETE)
- @DeleteMapping("/{tableIds}")
- public AjaxResult remove(@PathVariable Long[] tableIds)
- {
- genTableService.deleteGenTableByIds(tableIds);
- return success();
- }
-
- /**
- * 棰勮浠g爜
- */
- @PreAuthorize("@ss.hasPermi('tool:gen:preview')")
- @GetMapping("/preview/{tableId}")
- public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException
- {
- Map<String, String> dataMap = genTableService.previewCode(tableId);
- return success(dataMap);
- }
-
- /**
- * 鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
- */
- @PreAuthorize("@ss.hasPermi('tool:gen:code')")
- @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
- @GetMapping("/download/{tableName}")
- public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
- {
- byte[] data = genTableService.downloadCode(tableName);
- genCode(response, data);
- }
-
- /**
- * 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛�
- */
- @PreAuthorize("@ss.hasPermi('tool:gen:code')")
- @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
- @GetMapping("/genCode/{tableName}")
- public AjaxResult genCode(@PathVariable("tableName") String tableName)
- {
- if (!GenConfig.isAllowOverwrite())
- {
- return AjaxResult.error("銆愮郴缁熼璁俱�戜笉鍏佽鐢熸垚鏂囦欢瑕嗙洊鍒版湰鍦�");
- }
- genTableService.generatorCode(tableName);
- return success();
- }
-
- /**
- * 鍚屾鏁版嵁搴�
- */
- @PreAuthorize("@ss.hasPermi('tool:gen:edit')")
- @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.UPDATE)
- @GetMapping("/synchDb/{tableName}")
- public AjaxResult synchDb(@PathVariable("tableName") String tableName)
- {
- genTableService.synchDb(tableName);
- return success();
- }
-
- /**
- * 鎵归噺鐢熸垚浠g爜
- */
- @PreAuthorize("@ss.hasPermi('tool:gen:code')")
- @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
- @GetMapping("/batchGenCode")
- public void batchGenCode(HttpServletResponse response, String tables) throws IOException
- {
- String[] tableNames = Convert.toStrArray(tables);
- byte[] data = genTableService.downloadCode(tableNames);
- genCode(response, data);
- }
-
- /**
- * 鐢熸垚zip鏂囦欢
- */
- private void genCode(HttpServletResponse response, byte[] data) throws IOException
- {
- response.reset();
- response.addHeader("Access-Control-Allow-Origin", "*");
- response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
- response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\"");
- response.addHeader("Content-Length", "" + data.length);
- response.setContentType("application/octet-stream; charset=UTF-8");
- IOUtils.write(data, response.getOutputStream());
- }
+package com.ruoyi.project.tool.gen.controller;
+
+import com.alibaba.druid.DbType;
+import com.alibaba.druid.sql.SQLUtils;
+import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.sql.SqlUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.config.GenConfig;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.tool.gen.domain.GenTable;
+import com.ruoyi.project.tool.gen.domain.GenTableColumn;
+import com.ruoyi.project.tool.gen.service.IGenTableColumnService;
+import com.ruoyi.project.tool.gen.service.IGenTableService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import org.apache.commons.io.IOUtils;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 浠g爜鐢熸垚 鎿嶄綔澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/tool/gen")
+@AllArgsConstructor
+public class GenController extends BaseController
+{
+ private IGenTableService genTableService;
+ private IGenTableColumnService genTableColumnService;
+
+ /**
+ * 鏌ヨ浠g爜鐢熸垚鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:list')")
+ @GetMapping("/list")
+ public TableDataInfo genList(GenTable genTable)
+ {
+ startPage();
+ List<GenTable> list = genTableService.selectGenTableList(genTable);
+ return getDataTable(list);
+ }
+
+ /**
+ * 鑾峰彇浠g爜鐢熸垚淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:query')")
+ @GetMapping(value = "/{talbleId}")
+ public AjaxResult getInfo(@PathVariable Long talbleId)
+ {
+ GenTable table = genTableService.selectGenTableById(talbleId);
+ List<GenTable> tables = genTableService.selectGenTableAll();
+ List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(talbleId);
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put("info", table);
+ map.put("rows", list);
+ map.put("tables", tables);
+ return success(map);
+ }
+
+ /**
+ * 鏌ヨ鏁版嵁搴撳垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:list')")
+ @GetMapping("/db/list")
+ public TableDataInfo dataList(GenTable genTable)
+ {
+ startPage();
+ List<GenTable> list = genTableService.selectDbTableList(genTable);
+ return getDataTable(list);
+ }
+
+ /**
+ * 鏌ヨ鏁版嵁琛ㄥ瓧娈靛垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:list')")
+ @GetMapping(value = "/column/{tableId}")
+ public TableDataInfo columnList(Long tableId)
+ {
+ TableDataInfo dataInfo = new TableDataInfo();
+ List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(tableId);
+ dataInfo.setRows(list);
+ dataInfo.setTotal(list.size());
+ return dataInfo;
+ }
+
+ /**
+ * 瀵煎叆琛ㄧ粨鏋勶紙淇濆瓨锛�
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:import')")
+ @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.IMPORT)
+ @PostMapping("/importTable")
+ public AjaxResult importTableSave(String tables)
+ {
+ String[] tableNames = Convert.toStrArray(tables);
+ // 鏌ヨ琛ㄤ俊鎭�
+ List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
+ genTableService.importGenTable(tableList, SecurityUtils.getUsername());
+ return success();
+ }
+
+ /**
+ * 鍒涘缓琛ㄧ粨鏋勶紙淇濆瓨锛�
+ */
+ @PreAuthorize("@ss.hasRole('admin')")
+ @Log(title = "鍒涘缓琛�", businessType = BusinessType.OTHER)
+ @PostMapping("/createTable")
+ public AjaxResult createTableSave(String sql)
+ {
+ try
+ {
+ SqlUtil.filterKeyword(sql);
+ List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, DbType.mysql);
+ List<String> tableNames = new ArrayList<>();
+ for (SQLStatement sqlStatement : sqlStatements)
+ {
+ if (sqlStatement instanceof MySqlCreateTableStatement)
+ {
+ MySqlCreateTableStatement createTableStatement = (MySqlCreateTableStatement) sqlStatement;
+ if (genTableService.createTable(createTableStatement.toString()))
+ {
+ String tableName = createTableStatement.getTableName().replaceAll("`", "");
+ tableNames.add(tableName);
+ }
+ }
+ }
+ List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames.toArray(new String[tableNames.size()]));
+ String operName = SecurityUtils.getUsername();
+ genTableService.importGenTable(tableList, operName);
+ return AjaxResult.success();
+ }
+ catch (Exception e)
+ {
+ logger.error(e.getMessage(), e);
+ return AjaxResult.error("鍒涘缓琛ㄧ粨鏋勫紓甯�");
+ }
+ }
+
+ /**
+ * 淇敼淇濆瓨浠g爜鐢熸垚涓氬姟
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:edit')")
+ @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult editSave(@Validated @RequestBody GenTable genTable)
+ {
+ genTableService.validateEdit(genTable);
+ genTableService.updateGenTable(genTable);
+ return success();
+ }
+
+ /**
+ * 鍒犻櫎浠g爜鐢熸垚
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:remove')")
+ @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{tableIds}")
+ public AjaxResult remove(@PathVariable Long[] tableIds)
+ {
+ genTableService.deleteGenTableByIds(tableIds);
+ return success();
+ }
+
+ /**
+ * 棰勮浠g爜
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:preview')")
+ @GetMapping("/preview/{tableId}")
+ public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException
+ {
+ Map<String, String> dataMap = genTableService.previewCode(tableId);
+ return success(dataMap);
+ }
+
+ /**
+ * 鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:code')")
+ @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
+ @GetMapping("/download/{tableName}")
+ public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
+ {
+ byte[] data = genTableService.downloadCode(tableName);
+ genCode(response, data);
+ }
+
+ /**
+ * 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛�
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:code')")
+ @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
+ @GetMapping("/genCode/{tableName}")
+ public AjaxResult genCode(@PathVariable("tableName") String tableName)
+ {
+ if (!GenConfig.isAllowOverwrite())
+ {
+ return AjaxResult.error("銆愮郴缁熼璁俱�戜笉鍏佽鐢熸垚鏂囦欢瑕嗙洊鍒版湰鍦�");
+ }
+ genTableService.generatorCode(tableName);
+ return success();
+ }
+
+ /**
+ * 鍚屾鏁版嵁搴�
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:edit')")
+ @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.UPDATE)
+ @GetMapping("/synchDb/{tableName}")
+ public AjaxResult synchDb(@PathVariable("tableName") String tableName)
+ {
+ genTableService.synchDb(tableName);
+ return success();
+ }
+
+ /**
+ * 鎵归噺鐢熸垚浠g爜
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:code')")
+ @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
+ @GetMapping("/batchGenCode")
+ public void batchGenCode(HttpServletResponse response, String tables) throws IOException
+ {
+ String[] tableNames = Convert.toStrArray(tables);
+ byte[] data = genTableService.downloadCode(tableNames);
+ genCode(response, data);
+ }
+
+ /**
+ * 鐢熸垚zip鏂囦欢
+ */
+ private void genCode(HttpServletResponse response, byte[] data) throws IOException
+ {
+ response.reset();
+ response.addHeader("Access-Control-Allow-Origin", "*");
+ response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
+ response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\"");
+ response.addHeader("Content-Length", "" + data.length);
+ response.setContentType("application/octet-stream; charset=UTF-8");
+ IOUtils.write(data, response.getOutputStream());
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java b/src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java
index 813fb44..798112b 100644
--- a/src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java
+++ b/src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java
@@ -1,26 +1,23 @@
package com.ruoyi.purchase.controller;
-import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.service.ISupplierService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.purchase.dto.InvoicePurchaseReportDto;
+import com.ruoyi.framework.web.domain.R;
import com.ruoyi.purchase.dto.VatDto;
-import com.ruoyi.purchase.pojo.InvoicePurchase;
-import com.ruoyi.purchase.service.IInvoicePurchaseService;
-import com.ruoyi.waterrecord.pojo.WaterRecord;
-import io.swagger.v3.oas.annotations.tags.Tag;
+import com.ruoyi.purchase.service.PurchaseReportService;
+import com.ruoyi.purchase.vo.PurchaseReportVo;
import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
@RestController
@@ -29,40 +26,52 @@
@AllArgsConstructor
public class AccountingReportController {
- private IInvoicePurchaseService invoicePurchaseService;
+ private final ISupplierService supplierService;
+ private final PurchaseReportService purchaseReportService;
+
@GetMapping("/list")
@Log(title = "閲囪喘鎶ヨ〃-椤圭洰鍒╂鼎", businessType = BusinessType.OTHER)
- public AjaxResult list(Page page, InvoicePurchaseReportDto invoicePurchaseReportDto) {
- IPage<InvoicePurchaseReportDto> result =invoicePurchaseService.listPurchaseReport(page, invoicePurchaseReportDto);
- return AjaxResult.success(result);
+ public R list(Page page, String customerName) {
+ return R.ok(purchaseReportService.list(page,customerName));
}
@Log(title = "閲囪喘鎶ヨ〃-椤圭洰鍒╂鼎瀵煎嚭", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@Operation(summary = "閲囪喘鎶ヨ〃-椤圭洰鍒╂鼎瀵煎嚭")
- public void export(HttpServletResponse response) {
- Page page = new Page(-1,-1);
- InvoicePurchaseReportDto waterRecord = new InvoicePurchaseReportDto();
- IPage<InvoicePurchaseReportDto> listPage = invoicePurchaseService.listPurchaseReport(page, waterRecord);
- ExcelUtil<InvoicePurchaseReportDto> util = new ExcelUtil<InvoicePurchaseReportDto>(InvoicePurchaseReportDto.class);
- util.exportExcel(response, listPage.getRecords() , "椤圭洰鍒╂鼎瀵煎嚭");
+ public void export(HttpServletResponse response, String customerName) {
+ List<PurchaseReportVo> list = purchaseReportService.list(new Page(1,-1),customerName).getRecords();
+ ExcelUtil<PurchaseReportVo> util = new ExcelUtil<>(PurchaseReportVo.class);
+ util.exportExcel(response, list , "椤圭洰鍒╂鼎");
+
}
@Log(title = "閲囪喘鎶ヨ〃-澧炲�肩◣姣斿", businessType = BusinessType.OTHER)
@GetMapping("/listVat")
- public AjaxResult listVat(Page page,String month) {
- IPage<VatDto> result = invoicePurchaseService.listVat(page, month);
- return AjaxResult.success(result);
+ public R listVat(Page page,String month) {
+ return R.ok(purchaseReportService.listVat(page,month));
}
@Log(title = "閲囪喘鎶ヨ〃-澧炲�肩◣姣斿", businessType = BusinessType.EXPORT)
@PostMapping("/exportTwo")
@Operation(summary = "閲囪喘鎶ヨ〃-澧炲�肩◣姣斿")
- public void exportTwo(HttpServletResponse response) {
- Page page = new Page(-1,-1);
- IPage<VatDto> result = invoicePurchaseService.listVat(page, null);
- ExcelUtil<VatDto> util = new ExcelUtil<VatDto>(VatDto.class);
- util.exportExcel(response, result.getRecords() , "澧炲�肩◣姣斿");
+ public void exportTwo(HttpServletResponse response,String month) {
+ List<VatDto> list = purchaseReportService.listVat(new Page(1,-1),month).getRecords();
+ ExcelUtil<VatDto> util = new ExcelUtil<>(VatDto.class);
+ util.exportExcel(response, list , "澧炲�肩◣姣斿");
+ }
+
+ @GetMapping("/supplierTransactions")
+ @Log(title = "渚涘簲鍟嗗線鏉�", businessType = BusinessType.OTHER)
+ @Operation(summary = "渚涘簲鍟嗗線鏉�")
+ public R supplierTransactions(Page page, String supplierName) {
+ return R.ok(supplierService.supplierTransactions(page,supplierName));
+ }
+
+ @GetMapping("/supplierTransactionsDetails")
+ @Log(title = "渚涘簲鍟嗗線鏉ユ槑缁�", businessType = BusinessType.OTHER)
+ @Operation(summary = "渚涘簲鍟嗗線鏉ユ槑缁�")
+ public R supplierTransactionsDetails(Page page, Long supplierId) {
+ return R.ok(supplierService.supplierTransactionsDetails(page,supplierId));
}
}
diff --git a/src/main/java/com/ruoyi/purchase/controller/InvoicePurchaseController.java b/src/main/java/com/ruoyi/purchase/controller/InvoicePurchaseController.java
deleted file mode 100644
index afd9213..0000000
--- a/src/main/java/com/ruoyi/purchase/controller/InvoicePurchaseController.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.ruoyi.purchase.controller;
-
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.purchase.dto.InvoicePurchaseDto;
-import com.ruoyi.purchase.pojo.InvoicePurchase;
-import com.ruoyi.purchase.service.IInvoicePurchaseService;
-import com.ruoyi.sales.service.ICommonFileService;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AllArgsConstructor;
-import org.springframework.web.bind.annotation.*;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * 鍙戠エ淇℃伅Controller
- *
- * @author ruoyi
- * @date 2025-05-14
- */
-@RestController
-@AllArgsConstructor
-@RequestMapping("/purchase/invoice")
-public class InvoicePurchaseController extends BaseController {
-
- private IInvoicePurchaseService invoicePurchaseService;
-
- private ICommonFileService commonFileService;
-
- /**
- * 鏌ヨ鍙戠エ淇℃伅鍒楄〃
- */
- @GetMapping("/list")
- public TableDataInfo list(InvoicePurchaseDto invoicePurchaseDto) {
- startPage();
- List<InvoicePurchaseDto> list = invoicePurchaseService.selectInvoicePurchaseList(invoicePurchaseDto);
- return getDataTable(list);
- }
-
- /**
- * 瀵煎嚭鍙戠エ淇℃伅鍒楄〃
- */
- @Log(title = "鍙戠エ淇℃伅", businessType = BusinessType.EXPORT)
- @PostMapping("/export")
- public void export(HttpServletResponse response, InvoicePurchase invoicePurchase) {
- List<InvoicePurchase> list = invoicePurchaseService.selectInvoicePurchaseLists(invoicePurchase);
- ExcelUtil<InvoicePurchase> util = new ExcelUtil<InvoicePurchase>(InvoicePurchase.class);
- util.exportExcel(response, list, "鍙戠エ淇℃伅鏁版嵁");
- }
-
- /**
- * 鏌ヨ鍙戠エ淇℃伅
- */
- @GetMapping("/getInvoiceById")
- public InvoicePurchaseDto getInvoiceById(InvoicePurchaseDto invoicePurchaseDto) {
- return invoicePurchaseService.getInvoiceById(invoicePurchaseDto);
- }
-
- /**
- * 鏂板淇敼鍙戠エ淇℃伅
- */
- @Log(title = "鍙戠エ淇℃伅", businessType = BusinessType.INSERT)
- @PostMapping("/addOrUpdateInvoice")
- public AjaxResult addOrUpdateInvoice(@RequestBody InvoicePurchaseDto invoicePurchaseDto) throws IOException {
- return toAjax(invoicePurchaseService.addOrUpdateInvoice(invoicePurchaseDto));
- }
-
- /**
- * 鍒犻櫎鍙戠エ淇℃伅
- */
- @Log(title = "鍙戠エ淇℃伅", businessType = BusinessType.DELETE)
- @DeleteMapping("/delInvoice")
- public AjaxResult remove(@RequestBody Long[] ids) {
- return toAjax(invoicePurchaseService.delInvoice(ids));
- }
-
-}
diff --git a/src/main/java/com/ruoyi/purchase/controller/PaymentRegistrationController.java b/src/main/java/com/ruoyi/purchase/controller/PaymentRegistrationController.java
deleted file mode 100644
index 289110c..0000000
--- a/src/main/java/com/ruoyi/purchase/controller/PaymentRegistrationController.java
+++ /dev/null
@@ -1,184 +0,0 @@
-package com.ruoyi.purchase.controller;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.purchase.dto.PaymentHistoryRecordVo;
-import com.ruoyi.purchase.dto.PaymentLedgerDto;
-import com.ruoyi.purchase.dto.PaymentRegistrationDto;
-import com.ruoyi.purchase.pojo.PaymentRegistration;
-import com.ruoyi.purchase.service.IPaymentRegistrationService;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.*;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 浠樻鐧昏Controller
- *
- * @author ruoyi
- * @date 2025-05-15
- */
-@RestController
-@RequestMapping("/purchase/paymentRegistration")
-@AllArgsConstructor
-public class PaymentRegistrationController extends BaseController {
- private IPaymentRegistrationService paymentRegistrationService;
-
- /**
- * 鏌ヨ浠樻鐧昏鍒楄〃
- */
-// @PreAuthorize("@ss.hasPermi('system:registration:list')")
- @GetMapping("/list")
- public TableDataInfo list(PaymentRegistrationDto paymentRegistrationDto) {
- startPage();
- List<PaymentRegistrationDto> list = paymentRegistrationService.selectPaymentRegistrationList(paymentRegistrationDto);
- return getDataTable(list);
- }
-
- /**
- * 瀵煎嚭浠樻娴佹按鍒楄〃
- */
- @Log(title = "瀵煎嚭浠樻娴佹按鍒楄〃", businessType = BusinessType.EXPORT)
- @PostMapping("/export")
- public void export(HttpServletResponse response, PaymentRegistrationDto paymentRegistrationDto)
- {
- Page page = new Page<>(-1,-1);
- IPage<PaymentRegistrationDto> paymentRegistrationDtoIPage = paymentHistoryListPage(page, paymentRegistrationDto);
- ExcelUtil<PaymentRegistrationDto> util = new ExcelUtil<PaymentRegistrationDto>(PaymentRegistrationDto.class);
- util.exportExcel(response, paymentRegistrationDtoIPage.getRecords(), "瀵煎嚭浠樻娴佹按鍒楄〃");
- }
-
- /**
- * 鑾峰彇浠樻鐧昏璇︾粏淇℃伅
- */
- @GetMapping(value = "/{id}")
- public AjaxResult getInfo(@PathVariable("id") Long id) {
- return success(paymentRegistrationService.selectPaymentRegistrationById(id));
- }
-
- /**
- * 鏂板浠樻鐧昏
- */
- @Log(title = "浠樻鐧昏", businessType = BusinessType.INSERT)
- @PostMapping
- @Transactional(rollbackFor = Exception.class)
- public AjaxResult add(@RequestBody List<PaymentRegistration> paymentRegistration) {
- return toAjax(paymentRegistrationService.insertPaymentRegistration(paymentRegistration));
- }
-
- /**
- * 淇敼浠樻鐧昏
- */
- @Log(title = "浠樻鐧昏", businessType = BusinessType.UPDATE)
- @PutMapping
- @Transactional(rollbackFor = Exception.class)
- public AjaxResult edit(@RequestBody PaymentRegistration paymentRegistration) {
- return toAjax(paymentRegistrationService.updatePaymentRegistration(paymentRegistration));
- }
-
- /**
- * 鍒犻櫎浠樻鐧昏
- */
- @Log(title = "浠樻鐧昏", businessType = BusinessType.DELETE)
- @DeleteMapping("/del")
- public AjaxResult remove(@RequestBody Long[] ids) {
- return toAjax(paymentRegistrationService.deletePaymentRegistrationByIds(ids));
- }
-
- /**
- * 鍒犻櫎浠樻鐧昏
- */
- @Log(title = "浠樻鐧昏", businessType = BusinessType.DELETE)
- @DeleteMapping("/delete")
- public AjaxResult delete(@RequestBody Long[] ids) {
- return toAjax(paymentRegistrationService.delete(ids));
- }
-
- /**
- * 鑾峰彇浠樻鐧昏璇︾粏淇℃伅
- */
- @GetMapping(value = "/byPurchaseId/{id}")
- public AjaxResult getPurchaseInfo(@PathVariable("id") Long id) {
- return success(paymentRegistrationService.selectPaymentRegistrationByPurchaseId(id));
- }
-
- /**
- * 鑾峰彇浠樻鐧昏璇︾粏淇℃伅
- */
- @GetMapping(value = "/paymentLedgerList")
- public AjaxResult paymentLedgerList(PaymentLedgerDto paymentLedgerDto, Page page,
- Integer detailPageNum,
- Integer detailPageSize) {
- IPage<Map<String, Object>> mapIPage = paymentRegistrationService.selectPaymentLedgerList(paymentLedgerDto, page, detailPageNum, detailPageSize);
- return success(mapIPage);
- }
-
- /**
- * 渚涘簲鍟嗗線鏉ュ垎椤垫帴鍙�
- */
- @GetMapping("/supplierNameListPage")
- public AjaxResult supplierNameListPage(PaymentLedgerDto paymentLedgerDto, Page page){
- return success(paymentRegistrationService.supplierNameListPage(page,paymentLedgerDto));
- }
-
- /**
- * 渚涘簲鍟嗗線鏉ュ垎椤垫帴鍙�
- */
- @GetMapping("/supplierNameListPageDetails")
- public AjaxResult supplierNameListPageDetails(PaymentLedgerDto paymentLedgerDto){
- return success(paymentRegistrationService.supplierNameListPageDetails(paymentLedgerDto));
- }
-
- /**
- * 鑾峰彇鏈湀搴斾粯淇℃伅
- */
- @GetMapping(value = "/paymentMonthList")
- public AjaxResult paymentMonthList() {
- return success(paymentRegistrationService.paymentMonthList());
- }
-
- /**
- * 鏌ヨ浠樻鐧昏鍒楄〃
- *
- * @param paymentRegistrationDto 浠樻鐧昏
- * @return 浠樻鐧昏闆嗗悎
- */
- @GetMapping("/paymentHistoryList")
- public TableDataInfo paymentHistoryList(PaymentRegistrationDto paymentRegistrationDto) {
- startPage();
- List<PaymentRegistrationDto> list = paymentRegistrationService.paymentHistoryList(paymentRegistrationDto);
- return getDataTable(list);
- }
-
- /**
- * 鏌ヨ渚涘簲鍟嗗線鏉ヨ褰�
- * @param supplierId
- * @return
- */
- @GetMapping("/getPaymentRecordList/{supplierId}")
- public AjaxResult getPaymentRecordList(@PathVariable Long supplierId) {
- List<PaymentHistoryRecordVo> paymentRecordList = paymentRegistrationService.getPaymentRecordList(supplierId);
- return success(paymentRecordList);
- }
-
- /**
- * 鏌ヨ浠樻鐧昏鍒楄〃
- *
- * @param paymentRegistrationDto 浠樻鐧昏
- * @return 浠樻鐧昏闆嗗悎
- */
- @GetMapping("/paymentHistoryListPage")
- public IPage<PaymentRegistrationDto> paymentHistoryListPage(Page page, PaymentRegistrationDto paymentRegistrationDto) {
- return paymentRegistrationService.paymentHistoryListPage(page,paymentRegistrationDto);
- }
-}
diff --git a/src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java b/src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java
index 3290499..537c903 100644
--- a/src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java
+++ b/src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java
@@ -1,8 +1,6 @@
package com.ruoyi.purchase.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
@@ -17,27 +15,24 @@
import com.ruoyi.purchase.pojo.PurchaseLedgerTemplate;
import com.ruoyi.purchase.pojo.SalesLedgerProductTemplate;
import com.ruoyi.purchase.service.IPurchaseLedgerService;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.sales.service.ISalesLedgerProductService;
import com.ruoyi.sales.service.ISalesLedgerService;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import io.swagger.v3.oas.annotations.Operation;
import io.swagger.annotations.ApiParam;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
-import jakarta.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.math.BigDecimal;
import java.net.URLEncoder;
+import java.util.Date;
import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
/**
* 閲囪喘鍙拌处Controller
@@ -132,19 +127,6 @@
util.exportExcel(response, list, "銆愯濉啓鍔熻兘鍚嶇О銆戞暟鎹�");
}
- /**
- * 瀵煎嚭鏉ョエ鐧昏鍒楄〃
- */
- @Log(title = "瀵煎嚭鏉ョエ鐧昏鍒楄〃", businessType = BusinessType.EXPORT)
- @PostMapping("/exportOne")
- public void exportOne(HttpServletResponse response, PurchaseLedger purchaseLedger) {
- Page page = new Page();
- page.setCurrent(-1);
- page.setSize(-1);
- IPage<PurchaseLedgerDto> purchaseLedgerDtoIPage = purchaseLedgerService.selectPurchaseLedgerListPage(page, new PurchaseLedgerDto());
- ExcelUtil<PurchaseLedgerDto> util = new ExcelUtil<PurchaseLedgerDto>(PurchaseLedgerDto.class);
- util.exportExcel(response, purchaseLedgerDtoIPage.getRecords(), "瀵煎嚭鏉ョエ鐧昏鍒楄〃");
- }
/**
* 鏂板淇敼閲囪喘鍙拌处
@@ -219,7 +201,7 @@
*/
@GetMapping("/getProductBySalesNo")
public AjaxResult getProductBySalesNo(Long id) {
- return AjaxResult.success(purchaseLedgerService.getProductBySalesNo(id));
+ return AjaxResult.success();
}
/**
@@ -265,7 +247,7 @@
@Operation(summary = "鐢熸垚閲囪喘搴忓垪鍙�")
@GetMapping("/createPurchaseNo")
@Log(title = "鐢熸垚閲囪喘搴忓垪鍙�", businessType = BusinessType.OTHER)
- public AjaxResult createPurchaseNo() {
- return AjaxResult.success("鐢熸垚鎴愬姛",purchaseLedgerService.getPurchaseNo());
+ public AjaxResult createPurchaseNo(@RequestParam Date entryDate) {
+ return AjaxResult.success("鐢熸垚鎴愬姛",purchaseLedgerService.getPurchaseNo(entryDate));
}
}
diff --git a/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java b/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java
index bb669b6..e4c7bf7 100644
--- a/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java
+++ b/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java
@@ -1,12 +1,18 @@
package com.ruoyi.purchase.controller;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.pojo.AccountStatementDetails;
+import com.ruoyi.account.service.AccountStatementDetailsService;
+import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.purchase.dto.PurchaseReturnOrderDto;
import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
+import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
import com.ruoyi.purchase.service.PurchaseReturnOrdersService;
import com.ruoyi.purchase.vo.PurchaseStockInProductVo;
import io.swagger.v3.oas.annotations.Operation;
@@ -31,6 +37,7 @@
public class PurchaseReturnOrdersController {
private PurchaseReturnOrdersService purchaseReturnOrdersService;
private PurchaseReturnOrdersMapper purchaseReturnOrdersMapper;
+ private AccountStatementDetailsService accountStatementDetailsService;
@GetMapping("/listPage")
@@ -56,6 +63,13 @@
@PostMapping("/deleteById/{id}")
public AjaxResult deleteById(@PathVariable Long id) {
+ //濡傛灉璇ラ噰璐��璐у凡缁忕敓鎴愬璐﹀崟鍒欐棤娉曞垹闄�
+ PurchaseReturnOrders purchaseReturnOrders = purchaseReturnOrdersService.getById(id);
+ List<AccountStatementDetails> accountStatementDetails = accountStatementDetailsService.list(Wrappers.<AccountStatementDetails>lambdaQuery()
+ .eq(AccountStatementDetails::getReceiptNumber, purchaseReturnOrders.getNo()));
+ if (CollectionUtils.isNotEmpty(accountStatementDetails)){
+ throw new ServiceException("璇ラ噰璐��璐у崟宸茬粡鐢熸垚瀵硅处鍗曪紝鏃犳硶鍒犻櫎");
+ }
purchaseReturnOrdersService.deleteById(id);
return AjaxResult.success();
}
diff --git a/src/main/java/com/ruoyi/purchase/controller/TicketRegistrationController.java b/src/main/java/com/ruoyi/purchase/controller/TicketRegistrationController.java
deleted file mode 100644
index db628af..0000000
--- a/src/main/java/com/ruoyi/purchase/controller/TicketRegistrationController.java
+++ /dev/null
@@ -1,206 +0,0 @@
-package com.ruoyi.purchase.controller;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.purchase.dto.PaymentRegistrationDto;
-import com.ruoyi.purchase.dto.ProductRecordDto;
-import com.ruoyi.purchase.dto.TicketRegistrationDto;
-import com.ruoyi.purchase.pojo.PaymentRegistration;
-import com.ruoyi.purchase.pojo.ProductRecord;
-import com.ruoyi.purchase.pojo.TicketRegistration;
-import com.ruoyi.purchase.service.IPaymentRegistrationService;
-import com.ruoyi.purchase.service.IProductRecordService;
-import com.ruoyi.purchase.service.ITicketRegistrationService;
-import com.ruoyi.purchase.service.impl.PaymentRegistrationServiceImpl;
-import com.ruoyi.sales.service.ICommonFileService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AllArgsConstructor;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.bind.annotation.*;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * 鏉ョエ鐧昏Controller
- *
- * @author ruoyi
- * @date 2025-05-13
- */
-@RestController
-@RequestMapping("/purchase/registration")
-@AllArgsConstructor
-@Tag(name = "鏉ョエ鐧昏")
-public class TicketRegistrationController extends BaseController {
-
- private final PaymentRegistrationServiceImpl paymentRegistrationServiceImpl;
- private ITicketRegistrationService ticketRegistrationService;
-
- private ICommonFileService commonFileService;
-
- private IProductRecordService productRecordService;
-
- private IPaymentRegistrationService paymentRegistrationService;
-
- /**
- * 鏌ヨ鏉ョエ鐧昏鍒楄〃
- */
- @GetMapping("/list")
- public TableDataInfo list(TicketRegistration ticketRegistration) {
- startPage();
- List<TicketRegistration> list = ticketRegistrationService.selectTicketRegistrationList(ticketRegistration);
- return getDataTable(list);
- }
-
- @Operation(summary = "鏍规嵁id鏌ヨ浠樻娴佹按淇℃伅")
- @GetMapping("/getById")
- public List<PaymentRegistrationDto> getById( Long id ) {
- return ticketRegistrationService.getPaymentRegistrationDtoById(id);
- }
-
- @Operation(summary = "鏍规嵁id鏌ヨ浠樻娴佹按")
- @GetMapping("/getPaymentRegistrationById")
- public AjaxResult getPaymentRegistrationById(Long id) {
- PaymentRegistration byId = paymentRegistrationService.getById(id);
- return AjaxResult.success(byId);
- }
-
- @Operation(summary = "淇敼浠樻娴佹按")
- @PutMapping("/updatePaymentRegistration")
- @Log(title = "淇敼浠樻娴佹按", businessType = BusinessType.UPDATE)
- public AjaxResult updatePaymentRegistration(@RequestBody PaymentRegistration paymentRegistratio) {
- return AjaxResult.success(paymentRegistrationService.updatePaymentRegistration(paymentRegistratio));
- }
-
- @Operation(summary = "鍒犻櫎浠樻娴佹按")
- @DeleteMapping("/delPaymentRegistration")
- @Transactional(rollbackFor = Exception.class)
- public AjaxResult delPaymentRegistration(@RequestBody List<Long> id) {
- return toAjax(paymentRegistrationService.delPaymentRegistration(id));
- }
-
- /**
- * 瀵煎嚭鏉ョエ鐧昏鍒楄〃
- */
- @Log(title = "鏉ョエ鐧昏", businessType = BusinessType.EXPORT)
- @PostMapping("/export")
- public void export(HttpServletResponse response, TicketRegistration ticketRegistration) {
- List<TicketRegistration> list = ticketRegistrationService.selectTicketRegistrationList(ticketRegistration);
- ExcelUtil<TicketRegistration> util = new ExcelUtil<TicketRegistration>(TicketRegistration.class);
- util.exportExcel(response, list, "鏉ョエ鐧昏鏁版嵁");
- }
-
- /**
- * 浠樻鐧昏瀵煎嚭
- */
- @Log(title = "浠樻鐧昏瀵煎嚭", businessType = BusinessType.EXPORT)
- @PostMapping("/exportOne")
- public void exportOne(HttpServletResponse response, TicketRegistration ticketRegistration) {
- Page page = new Page<>(-1, -1);
- IPage<TicketRegistration> ticketRegistrationIPage = listPage(page, ticketRegistration);
- ExcelUtil<TicketRegistration> util = new ExcelUtil<TicketRegistration>(TicketRegistration.class);
- util.exportExcel(response, ticketRegistrationIPage.getRecords(), "浠樻鐧昏瀵煎嚭");
- }
-
- /**
- * 鏌ヨ鏉ョエ鐧昏鍜屼骇鍝佺埗瀛愬垪琛�
- */
- @GetMapping("/getRegistrationById")
- public TicketRegistrationDto getRegistrationById(TicketRegistrationDto ticketRegistrationDto) {
- return ticketRegistrationService.getRegistrationById(ticketRegistrationDto);
- }
-
- /**
- * 鏂板淇敼鏉ョエ鐧昏
- */
- @Log(title = "鏉ョエ鐧昏", businessType = BusinessType.INSERT)
- @PostMapping("/addOrUpdateRegistration")
- @Transactional(rollbackFor = Exception.class)
- public AjaxResult addOrUpdateRegistration(@RequestBody List<TicketRegistrationDto> ticketRegistrationDto) throws IOException {
- if(CollectionUtils.isEmpty(ticketRegistrationDto)) return AjaxResult.error("璇烽�夋嫨瑕佷繚瀛樼殑璁板綍");
- for (TicketRegistrationDto ticketRegistrationDto1 : ticketRegistrationDto) {
- ticketRegistrationService.addOrUpdateRegistration(ticketRegistrationDto1);
- }
- return toAjax(1);
- }
-
-
- @PostMapping("/getProductRecordById")
- public AjaxResult getProductRecordById(@RequestBody ProductRecordDto productRecordDto) {
- if (productRecordDto.getId() == null) {
- return AjaxResult.error("鍙傛暟閿欒");
- }
- return AjaxResult.success(productRecordService.getProductRecordById(productRecordDto));
- }
-
- @Schema(description = "淇敼鏉ョエ鐧昏")
- @PostMapping("/updateRegistration")
- public AjaxResult updateRegistration(@RequestBody ProductRecordDto productRecordDto) {
-
- return productRecordService.updateRecord(productRecordDto);
- }
-
- /**
- * 鍒犻櫎鏉ョエ鐧昏(鏉ョエ鍙拌处)
- */
- @Log(title = "鍒犻櫎鏉ョエ鐧昏(鏉ョエ鍙拌处)", businessType = BusinessType.DELETE)
- @DeleteMapping("/delRegistration")
- @Transactional(rollbackFor = Exception.class)
- public AjaxResult delRegistration(@RequestBody Long[] ids) {
- return toAjax(ticketRegistrationService.delRegistration(ids));
- }
-
- /**
- * 鏌ヨ浜у搧淇℃伅寮�绁ㄨ褰曞垪琛�
- */
- @GetMapping("/productRecordList")
- public List<ProductRecord> productRecordList(TicketRegistrationDto ticketRegistrationDto) {
- List<ProductRecord> list = productRecordService.selectProductRecordList(ticketRegistrationDto);
- return list;
- }
-
- /**
- * 鍒嗛〉鏌ヨ浜у搧淇℃伅寮�绁ㄨ褰曞垪琛�
- */
- @GetMapping("/productRecordPage")
- public AjaxResult productRecordPage(Page page, TicketRegistrationDto ticketRegistrationDto) {
-
- IPage<ProductRecordDto> list = productRecordService.productRecordPage(page,ticketRegistrationDto);
- return AjaxResult.success(list);
- }
-
- /**
- * 鏌ヨ鍙戠エ鍙�
- */
- @GetMapping("/getTicketNo")
- public AjaxResult getTicketNo(TicketRegistrationDto ticketRegistrationDto) {
- return AjaxResult.success(ticketRegistrationService.getTicketNo(ticketRegistrationDto));
- }
-
- /**
- * 鏌ヨ鏉ョエ鐧昏鍒楄〃
- */
- @GetMapping("/listPage")
- public IPage<TicketRegistration> listPage(Page page, TicketRegistration ticketRegistration) {
- return ticketRegistrationService.selectTicketRegistrationListPage(page,ticketRegistration);
- }
-
- @Schema(description = "鏍规嵁id鏌ヨ鏉ユ紓鐧昏")
- @GetMapping("/getPuargeById")
- public AjaxResult getPuargeById(Long id) {
- return AjaxResult.success(ticketRegistrationService.getPuargeById( id));
- }
-
-
-
-}
diff --git a/src/main/java/com/ruoyi/purchase/dto/InvoicePurchaseDto.java b/src/main/java/com/ruoyi/purchase/dto/InvoicePurchaseDto.java
deleted file mode 100644
index c8a8671..0000000
--- a/src/main/java/com/ruoyi/purchase/dto/InvoicePurchaseDto.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.ruoyi.purchase.dto;
-
-import com.ruoyi.sales.pojo.CommonFile;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.List;
-
-@Data
-public class InvoicePurchaseDto {
-
- private Long id;
-
- /**
- * 閲囪喘鍙拌处id
- */
- private Long purchaseLedgerId;
-
- /**
- * 閲囪喘鍚堝悓鍙�
- */
- private String purchaseContractNo;
-
- /**
- * 鍏宠仈閿�鍞彴璐︿富琛ㄤ富閿�
- */
- private Long salesLedgerId;
-
- /**
- * 閿�鍞悎鍚屽彿
- */
- private String salesContractNo;
-
- /**
- * 渚涘簲鍟嗗悕绉�
- */
- private String supplierName;
-
- /**
- * 鍙戠エ鍙�
- */
- private String invoiceNumber;
-
- /**
- * 鍙戠エ閲戦锛堝厓锛�
- */
- private BigDecimal invoiceAmount;
-
- /**
- * 绋庣巼
- */
- private BigDecimal taxRate;
-
- /**
- * 寮�绁ㄤ汉ID
- */
- private Long issUerId;
-
- /**
- * 寮�绁ㄤ汉
- */
- private String issUer;
-
- /**
- * 寮�绁ㄦ棩鏈�
- */
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- private LocalDate issueDate;
-
- private List<String> tempFileIds;
- private List<CommonFile> CommonFiles;
-
- private String fileName;
-}
diff --git a/src/main/java/com/ruoyi/purchase/dto/InvoicePurchaseReportDto.java b/src/main/java/com/ruoyi/purchase/dto/InvoicePurchaseReportDto.java
deleted file mode 100644
index 45347ad..0000000
--- a/src/main/java/com/ruoyi/purchase/dto/InvoicePurchaseReportDto.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.ruoyi.purchase.dto;
-
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import lombok.Data;
-
-/**
- * 鎶ヨ〃鍒嗘瀽---椤圭洰鍒╂鼎
- */
-@Data
-public class InvoicePurchaseReportDto {
-
- //閿�鍞悎鍚屽彿
- @Excel(name = "閿�鍞悎鍚屽彿")
- private String customerContractNo;
-// 瀹㈡埛鍚嶇О
- @Excel(name = "瀹㈡埛鍚嶇О")
- private String customerName;
-// 椤圭洰鍚嶇О
- @Excel(name = "椤圭洰鍚嶇О")
- private String projectName;
-// 鍚堝悓閲戦
- @Excel(name = "鍚堝悓閲戦")
- private String contractAmount;
-// 閲囪喘閲戦
- @Excel(name = "閲囪喘閲戦")
- private String purchaseAmount;
-
- private String saleTaxExclusiveTotalPrice;
-
- private String taxExclusiveTotalPrice;
-// 鍒╂鼎
- @Excel(name = "鍒╂鼎")
- private String balance;
- // 鍒╂鼎鐜�
- @Excel(name = "鍒╂鼎鐜�")
- private String balanceRatio;
- // 澧炲�肩◣
- @Excel(name = "澧炲�肩◣")
- private String balanceAmount;
-
-}
diff --git a/src/main/java/com/ruoyi/purchase/dto/PaymentRegistrationDto.java b/src/main/java/com/ruoyi/purchase/dto/PaymentRegistrationDto.java
deleted file mode 100644
index 8d56648..0000000
--- a/src/main/java/com/ruoyi/purchase/dto/PaymentRegistrationDto.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.ruoyi.purchase.dto;
-
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import com.ruoyi.purchase.pojo.PaymentRegistration;
-import lombok.Data;
-
-import java.math.BigDecimal;
-
-@Data
-public class PaymentRegistrationDto extends PaymentRegistration {
-
- // 鏌ヨ鍒楄〃鏌ヨ鐢ㄤ緵搴斿晢鍙峰拰鍚堝悓鍙�
- private String supplierNameOrContractNo;
-
- // 閿�鍞悎鍚屽彿
- private String salesContractNo;
-
- // 閲囪喘鍚堝悓鍙�
- @Excel(name = "閲囪喘鍚堝悓鍙�")
- private String purchaseContractNumber;
-
- // 渚涘簲鍟嗗悕绉�
- @Excel(name = "渚涘簲鍟嗗悕绉�")
- private String supplierName;
-
- // 鍙戠エ鍙�
- private String invoiceNumber;
-
- // 鍙戠エ閲戦
- private BigDecimal invoiceAmount;
-
- // 寰呬粯娆鹃噾棰�
- private BigDecimal unPaymentAmount;
-
- // 浠樻閲戦
- private BigDecimal paymentAmount;
-
- // 搴斾粯閲戦
- private BigDecimal payableAmount;
-
- // 绋庣巼
- private String taxRate;
-
- // 鐧昏浜�
- private String registrant;
-
- private String searchText;
-
- // 宸蹭粯娆炬�婚噾棰�
- private BigDecimal paymentAmountTotal;
-
- private String paymentDateStart;
-
- private String paymentDateEnd;
-}
diff --git a/src/main/java/com/ruoyi/purchase/dto/ProductRecordDto.java b/src/main/java/com/ruoyi/purchase/dto/ProductRecordDto.java
deleted file mode 100644
index 1b3c691..0000000
--- a/src/main/java/com/ruoyi/purchase/dto/ProductRecordDto.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.ruoyi.purchase.dto;
-
-import com.ruoyi.other.pojo.TempFile;
-import com.ruoyi.purchase.pojo.ProductRecord;
-import com.ruoyi.sales.pojo.CommonFile;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.util.List;
-
-@Data
-public class ProductRecordDto extends ProductRecord {
-
- private Long ticketRegistrationId;
-
- //閿�鍞悎鍚屽彿
- private String salesContractNo;
- //瀹㈡埛鍚堝悓鍙�
- private String customerContarctNo;
-
- //瀹㈡埛鍚嶇О
- private String customerName;
- //浜у搧鍚嶇О
- private String productModel;
- //閲囪喘鍚堝悓鍙�
- private String purchaseContractNumber;
- //渚涘簲鍟嗗悕绉�
- private String supplierName;
- private String projectName;
- private Long issUerId;
- private String issUer;
- /**
- * 鍚堝悓閲戦锛堜骇鍝佸惈绋庢�讳环锛�
- */
- private BigDecimal contractAmount = BigDecimal.ZERO;
- //澧炲�肩◣
- /**
- * 宸叉潵绁ㄩ噾棰濓紙鍙戠エ閲戦锛�
- */
- private BigDecimal invoiceTotal = BigDecimal.ZERO;
- private BigDecimal invoiceAmount = BigDecimal.ZERO;
- /**
- * 鍙戠エ鍙�
- */
- private String invoiceNumber;
- private BigDecimal unTicketsPrice = BigDecimal.ZERO;
-
- private List<CommonFile> commonFiles;
-
- private List<String> tempFileIds;
-}
diff --git a/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java b/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java
index 455dc9b..22faea3 100644
--- a/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java
+++ b/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java
@@ -27,6 +27,8 @@
private String entryDateStart;
private String entryDateEnd;
+ @Schema(description = "鍏ュ簱鐘舵��")
+ private String stockInStatus;
private Long id;
@@ -165,26 +167,11 @@
private BigDecimal invoiceAmount;
/**
- * 鏉ョエ鐧昏id
- */
- private Long ticketRegistrationId;
-
- /**
* 鍚堝悓閲戦锛堜骇鍝佸惈绋庢�讳环锛�
*/
@Excel(name = "鍚堝悓閲戦")
private BigDecimal contractAmount = BigDecimal.ZERO;
-
- @TableField(exist = false)
- @Schema(description = "鏉ョエ閲戦")
- @Excel(name = "宸叉潵绁ㄩ噾棰�(鍏�)")
- private BigDecimal receiptPaymentAmount = BigDecimal.ZERO;
-
- @Schema(description = "鏈潵绁ㄩ噾棰�")
- @TableField(exist = false)
- @Excel(name = "鏈潵绁ㄩ噾棰�(鍏�)")
- private BigDecimal unReceiptPaymentAmount =BigDecimal.ZERO;
@Schema(description = "鏂囦欢绫诲瀷 鍙� 4")
@TableField(exist = false)
diff --git a/src/main/java/com/ruoyi/purchase/dto/TicketRegistrationDto.java b/src/main/java/com/ruoyi/purchase/dto/TicketRegistrationDto.java
deleted file mode 100644
index 59f1da3..0000000
--- a/src/main/java/com/ruoyi/purchase/dto/TicketRegistrationDto.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.ruoyi.purchase.dto;
-
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import com.ruoyi.purchase.pojo.TicketRegistration;
-import com.ruoyi.sales.pojo.CommonFile;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.time.LocalDate;
-import java.util.List;
-
-/**
- * 鏉ョエ鐧昏琛�
- */
-
-@Data
-@TableName("ticket_registration")
-public class TicketRegistrationDto extends TicketRegistration {
-
- /**
- * 涓婚敭ID
- */
- private Long id;
-
- /**
- * 閲囪喘鍙拌处id
- */
- private Long purchaseLedgerId;
-
- /**
- * 閲囪喘鍚堝悓鍙�
- */
- private String purchaseContractNumber;
-
- /**
- * 閿�鍞悎鍚屽彿
- */
- private String salesContractNo;
-
- /**
- * 寮�绁ㄦ棩鏈�
- */
-
- @JsonFormat(pattern = "yyyy-MM-dd")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- private LocalDate entryDate;
-
- /**
- * 瀹㈡埛鍚嶇О
- */
- private String customerName;
-
- /**
- * 涓氬姟鍛�
- */
- private String businessPerson;
-
-
-
- @JsonFormat(pattern = "yyyy-MM-dd")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- @TableField(exist = false)
- private LocalDate enterDate;
-
- /**
- * 涓氬姟鍛榠d
- */
- private Long businessPersonId;
-
- /**
- * 椤圭洰鍚嶇О
- */
- private String projectName;
-
- private List<SalesLedgerProduct> productData;
-
- private Long salesContractNoId;
- private String supplierName;
-
- private List<String> tempFileIds;
- private List<CommonFile> CommonFiles;
-
- private String fileName;
-
- @TableField(exist = false)
- private String createdAtStart;
- @TableField(exist = false)
- private String createdAtEnd;
-}
diff --git a/src/main/java/com/ruoyi/purchase/dto/VatDto.java b/src/main/java/com/ruoyi/purchase/dto/VatDto.java
index c70ebeb..3564183 100644
--- a/src/main/java/com/ruoyi/purchase/dto/VatDto.java
+++ b/src/main/java/com/ruoyi/purchase/dto/VatDto.java
@@ -1,27 +1,30 @@
package com.ruoyi.purchase.dto;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
-import java.time.LocalDate;
-
@Data
+@Schema(name = "VatDto", description = "绠$悊椹鹃┒鑸�--澧炲�肩◣姣斿鍙傛暟")
+@ExcelIgnoreUnannotated
public class VatDto {
- //鏈堜唤
@Excel(name = "鏈堜唤")
+ @Schema(description = "鏈堜唤")
private String month ;
- //杩涢」绋�
- @Excel(name = "杩涢」绋庨")
+ @Excel(name = "閿�椤圭◣棰�")
+ @Schema(description = "閿�椤圭◣棰�")
private BigDecimal jTaxAmount;
- //閿�椤圭◣
- @Excel(name = "閿�椤圭◣棰�")
+ @Excel(name = "杩涢」绋庨")
+ @Schema(description = "杩涢」绋庨")
private BigDecimal xTaxAmount;
@Excel(name = "閿�-杩�")
+ @Schema(description = "閿�-杩�")
private BigDecimal taxAmount;
}
diff --git a/src/main/java/com/ruoyi/purchase/mapper/InvoicePurchaseMapper.java b/src/main/java/com/ruoyi/purchase/mapper/InvoicePurchaseMapper.java
deleted file mode 100644
index b1dc03c..0000000
--- a/src/main/java/com/ruoyi/purchase/mapper/InvoicePurchaseMapper.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.ruoyi.purchase.mapper;
-
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.purchase.dto.InvoicePurchaseReportDto;
-import com.ruoyi.purchase.dto.VatDto;
-import com.ruoyi.purchase.pojo.InvoicePurchase;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * 鍙戠エ淇℃伅Mapper鎺ュ彛
- *
- * @author ruoyi
- * @date 2025-05-14
- */
-public interface InvoicePurchaseMapper extends BaseMapper<InvoicePurchase> {
-
-
- IPage<InvoicePurchaseReportDto> selectPurchaseReport(IPage page, @Param("c") InvoicePurchaseReportDto invoicePurchaseReportDto);
-
- IPage<VatDto> listVat(Page page,@Param("month") String month);
-
- List<VatDto> listVat1();
-}
diff --git a/src/main/java/com/ruoyi/purchase/mapper/PaymentRegistrationMapper.java b/src/main/java/com/ruoyi/purchase/mapper/PaymentRegistrationMapper.java
deleted file mode 100644
index 196d531..0000000
--- a/src/main/java/com/ruoyi/purchase/mapper/PaymentRegistrationMapper.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.ruoyi.purchase.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.purchase.dto.PaymentHistoryRecordVo;
-import com.ruoyi.purchase.dto.PaymentLedgerDto;
-import com.ruoyi.purchase.dto.PaymentRegistrationDto;
-import com.ruoyi.purchase.pojo.PaymentRegistration;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * 浠樻鐧昏Mapper鎺ュ彛
- *
- * @author ruoyi
- * @date 2025-05-15
- */
-public interface PaymentRegistrationMapper extends BaseMapper<PaymentRegistration> {
- /**
- * 鏌ヨ浠樻鐧昏
- *
- * @param id 浠樻鐧昏涓婚敭
- * @return 浠樻鐧昏
- */
- public PaymentRegistrationDto selectPaymentRegistrationById(@Param("id") Long id);
-
- /**
- * 鏌ヨ浠樻鐧昏鍒楄〃
- *
- * @param paymentRegistrationDto 浠樻鐧昏
- * @return 浠樻鐧昏闆嗗悎
- */
- public List<PaymentRegistrationDto> selectPaymentRegistrationList(PaymentRegistrationDto paymentRegistrationDto);
-
- /**
- * 鏌ヨ浠樻鐧昏鍒楄〃
- *
- * @param paymentRegistrationDto 浠樻鐧昏
- * @return 浠樻鐧昏闆嗗悎
- */
- public List<PaymentRegistrationDto> paymentHistoryList(@Param("params") PaymentRegistrationDto paymentRegistrationDto);
-
- /**
- * 璁$畻姣忓紶鍙戠エ鐨勫凡寮�绁ㄩ噾棰�
- * @param ticketRegistrationIds
- * @return
- */
- public List<PaymentRegistrationDto> countPaymentTotalByTicketRegId(List<Long> ticketRegistrationIds);
-
- /**
- * 鏌ヨ渚涘簲鍟嗗線鏉ヨ褰�
- * @param supplierId
- * @return
- */
- List<PaymentHistoryRecordVo> getPaymentRecordList(Long supplierId);
-
- /**
- * 鏌ヨ浠樻鐧昏鍒楄〃
- *
- * @param paymentRegistrationDto 浠樻鐧昏
- * @return 浠樻鐧昏闆嗗悎
- */
- IPage<PaymentRegistrationDto> paymentHistoryListPage(Page page, @Param("params") PaymentRegistrationDto paymentRegistrationDto);
-
- IPage<PaymentRegistrationDto> supplierNameListPage(Page page,@Param("req") PaymentLedgerDto paymentLedgerDto);
-
- List<PaymentRegistrationDto> supplierNameListPageDetails(@Param("req") PaymentLedgerDto paymentLedgerDto);
-}
diff --git a/src/main/java/com/ruoyi/purchase/mapper/ProductRecordMapper.java b/src/main/java/com/ruoyi/purchase/mapper/ProductRecordMapper.java
deleted file mode 100644
index b4bdea9..0000000
--- a/src/main/java/com/ruoyi/purchase/mapper/ProductRecordMapper.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.ruoyi.purchase.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.purchase.dto.ProductRecordDto;
-import com.ruoyi.purchase.dto.TicketRegistrationDto;
-import com.ruoyi.purchase.pojo.ProductRecord;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * 閲囪喘鍙拌处浜у搧寮�绁ㄨ褰昅apper鎺ュ彛
- *
- * @author ruoyi
- * @date 2025-05-23
- */
-public interface ProductRecordMapper extends BaseMapper<ProductRecord> {
-
- IPage<ProductRecordDto> productRecordPage(Page page, @Param("c") TicketRegistrationDto ticketRegistrationDto);
-
- List<ProductRecordDto> getProductRecordById(@Param("c") ProductRecordDto productRecordDto);
-}
diff --git a/src/main/java/com/ruoyi/purchase/mapper/PurchaseLedgerMapper.java b/src/main/java/com/ruoyi/purchase/mapper/PurchaseLedgerMapper.java
index c3201e0..8d5ab54 100644
--- a/src/main/java/com/ruoyi/purchase/mapper/PurchaseLedgerMapper.java
+++ b/src/main/java/com/ruoyi/purchase/mapper/PurchaseLedgerMapper.java
@@ -3,7 +3,6 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.ruoyi.purchase.dto.PaymentRegistrationDto;
import com.ruoyi.purchase.dto.PurchaseLedgerDto;
import com.ruoyi.purchase.pojo.PurchaseLedger;
import org.apache.ibatis.annotations.Param;
@@ -23,8 +22,6 @@
int updateContractAmountById(@Param("id") Long id, @Param("totalTaxInclusiveAmount") BigDecimal totalTaxInclusiveAmount);
IPage<PurchaseLedgerDto> selectPurchaseLedgerListPage(IPage ipage, @Param("c") PurchaseLedgerDto purchaseLedger);
-
- List<PaymentRegistrationDto> getPaymentRegistrationDtoById(Long id);
List<IncomeExpenseAnalysisDto> selectPurchaseStats(@Param("startDate") String startDate, @Param("endDate") String endDate, @Param("dateFormat") String dateFormat);
diff --git a/src/main/java/com/ruoyi/purchase/mapper/TicketRegistrationMapper.java b/src/main/java/com/ruoyi/purchase/mapper/TicketRegistrationMapper.java
deleted file mode 100644
index 39633c1..0000000
--- a/src/main/java/com/ruoyi/purchase/mapper/TicketRegistrationMapper.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.ruoyi.purchase.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.ruoyi.purchase.pojo.TicketRegistration;
-
-/**
- * 鏉ョエ鐧昏Mapper鎺ュ彛
- *
- * @author ruoyi
- * @date 2025-05-13
- */
-public interface TicketRegistrationMapper extends BaseMapper<TicketRegistration> {
-}
diff --git a/src/main/java/com/ruoyi/purchase/pojo/InvoicePurchase.java b/src/main/java/com/ruoyi/purchase/pojo/InvoicePurchase.java
deleted file mode 100644
index 0d9eb46..0000000
--- a/src/main/java/com/ruoyi/purchase/pojo/InvoicePurchase.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package com.ruoyi.purchase.pojo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.Date;
-
-/**
- * 鍙戠エ淇℃伅瀵硅薄 invoice_purchase
- *
- * @author ruoyi
- * @date 2025-05-14
- */
-@TableName("invoice_purchase")
-@Data
-public class InvoicePurchase {
- private static final long serialVersionUID = 1L;
-
- /**
- * 涓婚敭ID
- */
- @TableId(value = "id", type = IdType.AUTO)
- private Long id;
-
- /**
- * 閲囪喘鍙拌处id
- */
- private Long purchaseLedgerId;
-
- /**
- * 閲囪喘鍚堝悓鍙�
- */
- @Excel(name = "閲囪喘鍚堝悓鍙�")
- private String purchaseContractNo;
-
- /**
- * 鍏宠仈閿�鍞彴璐︿富琛ㄤ富閿�
- */
- private Long salesLedgerId;
-
- /**
- * 閿�鍞悎鍚屽彿
- */
- @Excel(name = "閿�鍞悎鍚屽彿")
- private String salesContractNo;
-
- /**
- * 渚涘簲鍟嗗悕绉�
- */
- @Excel(name = "渚涘簲鍟嗗悕绉�")
- private String supplierName;
-
- /**
- * 鍙戠エ鍙�
- */
- @Excel(name = "鍙戠エ鍙�")
- private String invoiceNumber;
-
- /**
- * 鍙戠エ閲戦锛堝厓锛�
- */
- @Excel(name = "鍙戠エ閲戦(鍏�)")
- private BigDecimal invoiceAmount;
-
- /**
- * 绋庣巼
- */
- @Excel(name = "绋庣巼(%)")
- private BigDecimal taxRate;
-
- /**
- * 寮�绁ㄤ汉ID
- */
- private Long issUerId;
-
- /**
- * 寮�绁ㄤ汉
- */
- @Excel(name = "寮�绁ㄤ汉")
- private String issUer;
-
- /**
- * 寮�绁ㄦ棩鏈�
- */
- @JsonFormat(pattern = "yyyy-MM-dd" ,timezone = "GMT+8")
- @Excel(name = "寮�绁ㄦ棩鏈�", width = 30, dateFormat = "yyyy-MM-dd")
- private LocalDate issueDate;
-
- /**
- * 鍙戠エ鏂囦欢锛圥DF鏍煎紡锛�
- */
- private String invoiceFile;
-
- /**
- * 鍒涘缓鏃堕棿
- */
- @JsonFormat(pattern = "yyyy-MM-dd")
- private Date createdAt;
-
- /**
- * 鏇存柊鏃堕棿
- */
- @JsonFormat(pattern = "yyyy-MM-dd")
- private Date updatedAt;
-
- @TableField(fill = FieldFill.INSERT)
- private Long tenantId;
-
- @Schema(description = "鍒涘缓鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT)
- private Integer createUser;
-
- @TableField(fill = FieldFill.INSERT)
- private Long deptId;
-
-}
diff --git a/src/main/java/com/ruoyi/purchase/pojo/PaymentRegistration.java b/src/main/java/com/ruoyi/purchase/pojo/PaymentRegistration.java
deleted file mode 100644
index a84cf04..0000000
--- a/src/main/java/com/ruoyi/purchase/pojo/PaymentRegistration.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package com.ruoyi.purchase.pojo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.util.Date;
-
-/**
- * 浠樻鐧昏瀵硅薄 payment_registration
- *
- * @author ruoyi
- * @date 2025-05-15
- */
-
-@Data
-@TableName("payment_registration")
-public class PaymentRegistration {
- private static final long serialVersionUID = 1L;
-
- /**
- * id
- */
- @TableId(value = "id", type = IdType.AUTO)
- private Long id;
-
- /**
- * 閿�鍞彴璐d
- */
- private Long saleLedgerId;
-
- /**
- * 閲囪喘鍙拌处id
- */
- private Long purchaseLedgerId;
-
- /**
- * 閲囪喘璁㈠崟浜у搧id
- */
- private Long salesLedgerProductId;
-
- /**
- * 渚涘簲鍟唅d
- */
- private Long supplierId;
-
- /**
- * 鍙戠エid
- */
- private Long ticketRegistrationId;
-
- /**
- * 鏈浠樻閲戦
- */
- @Excel(name = "浠樻閲戦")
- private BigDecimal currentPaymentAmount;
-
- /**
- * 浠樻褰㈠紡
- */
- @Excel(name = "浠樻褰㈠紡")
- private String paymentMethod;
-
- /**
- * 绋庣巼
- */
- private String taxRate;
-
- /**
- * 鐧昏浜�
- */
- private Long registrantId;
-
- // 绉熸埛id
- @TableField(fill = FieldFill.INSERT)
- private Long tenantId;
-
- /**
- * 浠樻鏃ユ湡
- */
- @JsonFormat(pattern = "yyyy-MM-dd")
- @Excel(name = "浠樻鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
- private Date paymentDate;
-
- /**
- * 鐧昏鏃ユ湡
- */
- @JsonFormat(pattern = "yyyy-MM-dd")
- @Excel(name = "鐧昏鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
- private Date registrationtDate;
-
- /**
- * 鍒涘缓鏃ユ湡
- */
- @TableField(fill = FieldFill.INSERT)
- private Date createTime;
-
- /**
- * 淇敼鏃ユ湡
- */
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private Date updateTime;
- @Schema(description = "鍒涘缓鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT)
- private Integer createUser;
-
- @TableField(fill = FieldFill.INSERT)
- private Long deptId;
-
-}
diff --git a/src/main/java/com/ruoyi/purchase/pojo/ProductRecord.java b/src/main/java/com/ruoyi/purchase/pojo/ProductRecord.java
deleted file mode 100644
index 5003107..0000000
--- a/src/main/java/com/ruoyi/purchase/pojo/ProductRecord.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package com.ruoyi.purchase.pojo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.util.Date;
-
-/**
- * 閲囪喘鍙拌处浜у搧寮�绁ㄨ褰曞璞� product_record
- *
- * @author ruoyi
- * @date 2025-05-23
- */
-@Data
-@TableName("product_record")
-public class ProductRecord implements Serializable {
- private static final long serialVersionUID = 1L;
-
- /**
- * 涓婚敭id
- */
- @TableId(value = "id", type = IdType.AUTO)
- private Long id;
-
- /**
- * 鏉ョエ鐧昏id
- */
- private Long ticketRegistrationId;
-
- /**
- * 閲囪喘鍙拌处id
- */
- private Long purchaseLedgerId;
-
- /**
- * 浜у搧id
- */
- private Long saleLedgerProjectId;
-
- /**
- * 浜у搧澶х被
- */
- private String productCategory;
-
- /**
- * 瑙勬牸鍨嬪彿
- */
- private String specificationModel;
-
- /**
- * 鍗曚綅
- */
- private String unit;
-
- /**
- * 鏁伴噺
- */
- private BigDecimal quantity;
-
- /**
- * 绋庣巼
- */
- private BigDecimal taxRate;
-
- /**
- * 鍚◣鍗曚环
- */
- private BigDecimal taxInclusiveUnitPrice;
-
- /**
- * 鍚◣鎬讳环
- */
- private BigDecimal taxInclusiveTotalPrice;
-
- /**
- * 涓嶅惈绋庢�讳环
- */
- private BigDecimal taxExclusiveTotalPrice;
-
- /**
- * 鍙戠エ绫诲瀷
- */
- private String invoiceType;
-
- /**
- * 1.閿�鍞彴璐︼紝2.閲囪喘鍙拌处
- */
- private String type;
-
- /**
- * 鏈鏉ョエ鏁�
- */
- private BigDecimal ticketsNum;
-
- /**
- * 鏈鏉ョエ閲戦(鍏�)
- */
- private BigDecimal ticketsAmount;
-
- /**
- * 鏈潵绁ㄦ暟
- */
- private BigDecimal futureTickets = BigDecimal.ZERO;
-
- /**
- * 鏈潵绁ㄩ噾棰�(鍏�)
- */
- private BigDecimal futureTicketsAmount = BigDecimal.ZERO;
-
- /**
- * 浜у搧id
- */
- private Long productId;
-
- /**
- * 鍨嬪彿id
- */
- private Long productModelId;
-
- /**
- * 鍒涘缓鏃堕棿
- */
- @JsonFormat(pattern = "yyyy-MM-dd")
- private Date createdAt;
-
- @TableField(fill = FieldFill.INSERT)
- private Long tenantId;
- @Schema(description = "鍒涘缓鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT)
- private Integer createUser;
-
- @TableField(fill = FieldFill.INSERT)
- private Long deptId;
-
-}
diff --git a/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java b/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java
index d937bad..980c6bc 100644
--- a/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java
+++ b/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java
@@ -136,14 +136,6 @@
*/
private String phoneNumber;
- @TableField(exist = false)
- @Schema(description = "鏉ョエ閲戦")
- private String receiptPaymentAmount;
-
- @Schema(description = "鏈潵绁ㄩ噾棰�")
- @TableField(exist = false)
- private String unReceiptPaymentAmount;
-
@Schema(description = "鏂囦欢绫诲瀷 鍙� 4")
@TableField(exist = false)
private Integer type;
@@ -166,4 +158,7 @@
@TableField(fill = FieldFill.INSERT)
private Long deptId;
+ @Schema(description = "妯℃澘id")
+ private Long templateId;
+
}
diff --git a/src/main/java/com/ruoyi/purchase/pojo/TicketRegistration.java b/src/main/java/com/ruoyi/purchase/pojo/TicketRegistration.java
deleted file mode 100644
index 0dcf7c6..0000000
--- a/src/main/java/com/ruoyi/purchase/pojo/TicketRegistration.java
+++ /dev/null
@@ -1,173 +0,0 @@
-package com.ruoyi.purchase.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.Date;
-
-/**
- * 鏉ョエ鐧昏瀵硅薄 ticket_registration
- *
- * @author ruoyi
- * @date 2025-05-13
- */
-@Data
-@TableName("ticket_registration")
-public class TicketRegistration{
- private static final long serialVersionUID = 1L;
-
- /**
- * 涓婚敭ID
- */
- @TableId(value = "id", type = IdType.AUTO)
- private Long id;
-
- /**
- * 鐘舵��
- */
- @Excel(name = "鐘舵��")
- @TableField(exist = false)
- private String statusName;
-
- /**
- * 閲囪喘鍙拌处id
- */
- private Long purchaseLedgerId;
-
- /**
- * 閲囪喘鍚堝悓鍙�
- */
- @Excel(name = "閲囪喘鍚堝悓鍙�")
- private String purchaseContractNumber;
-
- /**
- * 閿�鍞悎鍚屽彿
- */
- @Excel(name = "閿�鍞悎鍚屽彿")
- private String salesContractNo;
-
- /**
- * 渚涘簲鍟嗗悕绉�
- */
- @Excel(name = "渚涘簲鍟嗗悕绉�")
- private String supplierName;
-
- /**
- * 瀹㈡埛鍚嶇О
- */
- private String customerName;
-
-// /**
-// * 涓氬姟鍛�
-// */
-// @Excel(name = "涓氬姟鍛�")
-// private String businessPerson;
-//
-// /**
-// * 涓氬姟鍛榠d
-// */
-// private Long businessPersonId;
-
- /**
- * 鍙戠エ鍙�
- */
- @Excel(name = "鍙戠エ鍙�")
- private String invoiceNumber;
-
- /**
- * 鍙戠エ閲戦锛堝厓锛�
- */
- @Excel(name = "鍙戠エ閲戦(鍏�)")
- private BigDecimal invoiceAmount;
-
- /**
- * 寮�绁ㄤ汉ID
- */
- @Excel(name = "寮�绁ㄤ汉")
- private String issUerId;
-
- /**
- * 寮�绁ㄤ汉
- */
- @Excel(name = "寮�绁ㄤ汉")
- private String issUer;
-
- /**
- * 寮�绁ㄦ棩鏈�
- */
- @JsonFormat(pattern = "yyyy-MM-dd" ,timezone = "GMT+8")
- @Excel(name = "寮�绁ㄦ棩鏈�", width = 30, dateFormat = "yyyy-MM-dd")
- private LocalDate issueDate;
-
- /**
- * 椤圭洰鍚嶇О
- */
- @Excel(name = "椤圭洰鍚嶇О")
- private String projectName;
-
- /**
- * 浜у搧淇℃伅
- */
- private Long productId;
-
- /**
- * 鍒涘缓鏃堕棿
- */
- @JsonFormat(pattern = "yyyy-MM-dd")
- private Date createdAt;
-
- /**
- * 鏇存柊鏃堕棿
- */
- @JsonFormat(pattern = "yyyy-MM-dd")
- private Date updatedAt;
-
- /**
- * 鍏宠仈閿�鍞彴璐︿富琛ㄤ富閿�
- */
- private Long salesLedgerId;
-
- /**
- * 鍚堝悓閲戦锛堜骇鍝佸惈绋庢�讳环锛�
- */
- private BigDecimal contractAmount;
-
- @TableField(fill = FieldFill.INSERT)
- private Long tenantId;
-
- @Schema(description = "宸蹭粯娆炬�婚噾棰�")
- @TableField(exist = false)
- @Excel(name = "宸蹭粯娆炬�婚噾棰�")
- private BigDecimal paymentAmountTotal;
-
- @Schema(description = "鏈粯娆炬�婚噾棰�")
- @TableField(exist = false)
- @Excel(name = "鏈粯娆炬�婚噾棰�")
- private BigDecimal unPaymentAmountTotal;
-
- @TableField(exist = false)
- private Boolean status;
-
- @TableField(exist = false)
- private String issueDateStart;
- @TableField(exist = false)
- private String issueDateEnd;
-
- @TableField(exist = false)
- private String supplierNameOrContractNo;
-
- @Schema(description = "褰曞叆鏃堕棿")
- private LocalDate enterDate;
- @Schema(description = "鍒涘缓鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT)
- private Integer createUser;
-
- @TableField(fill = FieldFill.INSERT)
- private Long deptId;
-
-}
diff --git a/src/main/java/com/ruoyi/purchase/service/IInvoicePurchaseService.java b/src/main/java/com/ruoyi/purchase/service/IInvoicePurchaseService.java
deleted file mode 100644
index cc17fc2..0000000
--- a/src/main/java/com/ruoyi/purchase/service/IInvoicePurchaseService.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.ruoyi.purchase.service;
-
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.purchase.dto.InvoicePurchaseDto;
-import com.ruoyi.purchase.dto.InvoicePurchaseReportDto;
-import com.ruoyi.purchase.dto.VatDto;
-import com.ruoyi.purchase.pojo.InvoicePurchase;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * 鍙戠エ淇℃伅Service鎺ュ彛
- *
- * @author ruoyi
- * @date 2025-05-14
- */
-public interface IInvoicePurchaseService extends IService<InvoicePurchase> {
- List<InvoicePurchaseDto> selectInvoicePurchaseList(InvoicePurchaseDto invoicePurchaseDto);
-
- int delInvoice(Long[] ids);
-
- int addOrUpdateInvoice(InvoicePurchaseDto invoicePurchaseDto) throws IOException;
-
- InvoicePurchaseDto getInvoiceById(InvoicePurchaseDto invoicePurchaseDto);
-
- List<InvoicePurchase> selectInvoicePurchaseLists(InvoicePurchase invoicePurchase);
-
- IPage<InvoicePurchaseReportDto> listPurchaseReport(Page page, InvoicePurchaseReportDto invoicePurchaseReportDto);
-
- IPage<VatDto> listVat(Page page,String month);
-}
diff --git a/src/main/java/com/ruoyi/purchase/service/IPaymentRegistrationService.java b/src/main/java/com/ruoyi/purchase/service/IPaymentRegistrationService.java
deleted file mode 100644
index 88052fa..0000000
--- a/src/main/java/com/ruoyi/purchase/service/IPaymentRegistrationService.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.ruoyi.purchase.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.purchase.dto.PaymentHistoryRecordVo;
-import com.ruoyi.purchase.dto.PaymentLedgerDto;
-import com.ruoyi.purchase.dto.PaymentRegistrationDto;
-import com.ruoyi.purchase.pojo.PaymentRegistration;
-
-import java.math.BigDecimal;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 浠樻鐧昏Service鎺ュ彛
- *
- * @author ruoyi
- * @date 2025-05-15
- */
-public interface IPaymentRegistrationService extends IService<PaymentRegistration> {
- /**
- * 鏌ヨ浠樻鐧昏
- *
- * @param id 浠樻鐧昏涓婚敭
- * @return 浠樻鐧昏
- */
- public PaymentRegistration selectPaymentRegistrationById(Long id);
-
- /**
- * 鏌ヨ浠樻鐧昏鍒楄〃
- *
- * @param paymentRegistrationDto 浠樻鐧昏
- * @return 浠樻鐧昏闆嗗悎
- */
- public List<PaymentRegistrationDto> selectPaymentRegistrationList(PaymentRegistrationDto paymentRegistrationDto);
-
- /**
- * 鏂板浠樻鐧昏
- *
- * @param paymentRegistration 浠樻鐧昏
- * @return 缁撴灉
- */
- public int insertPaymentRegistration(List<PaymentRegistration> paymentRegistration);
-
- /**
- * 淇敼浠樻鐧昏
- *
- * @param paymentRegistration 浠樻鐧昏
- * @return 缁撴灉
- */
- public int updatePaymentRegistration(PaymentRegistration paymentRegistration);
-
- /**
- * 鎵归噺鍒犻櫎浠樻鐧昏
- *
- * @param ids 闇�瑕佸垹闄ょ殑浠樻鐧昏涓婚敭闆嗗悎
- * @return 缁撴灉
- */
- public int deletePaymentRegistrationByIds(Long[] ids);
-
- /**
- * 閫氳繃閲囪喘鍚堝悓鍙锋煡璇㈤攢鍞悎鍚屽彿锛屼緵搴斿晢鍚嶇О锛屽彂绁ㄥ彿锛屽彂绁ㄩ噾棰濓紝绋庣巼
- *
- * @param purchaseId 閲囪喘鍚堝悓id
- * @return 缁撴灉
- */
- PaymentRegistration selectPaymentRegistrationByPurchaseId(Long purchaseId);
-
- IPage<Map<String, Object>> selectPaymentLedgerList(PaymentLedgerDto paymentLedgerDto, Page page,
- Integer detailPageNum,
- Integer detailPageSize);
-
- Map<String, BigDecimal> paymentMonthList();
-
- /**
- * 鏌ヨ浠樻鐧昏鍒楄〃
- *
- * @param paymentRegistrationDto 浠樻鐧昏
- * @return 浠樻鐧昏闆嗗悎
- */
- public List<PaymentRegistrationDto> paymentHistoryList(PaymentRegistrationDto paymentRegistrationDto);
-
- /**
- * 鏌ヨ渚涘簲鍟嗗線鏉ヨ褰�
- * @param supplierId
- * @return
- */
- List<PaymentHistoryRecordVo> getPaymentRecordList(Long supplierId);
-
- /**
- * 鏌ヨ浠樻鐧昏鍒楄〃鍒嗛〉
- *
- * @param paymentRegistrationDto 浠樻鐧昏
- * @return 浠樻鐧昏闆嗗悎
- */
- IPage<PaymentRegistrationDto> paymentHistoryListPage(Page page, PaymentRegistrationDto paymentRegistrationDto);
-
- Boolean delete(Long[] ids);
-
- int delPaymentRegistration(List<Long> ids);
-
- IPage<PaymentRegistrationDto> supplierNameListPage(Page page, PaymentLedgerDto paymentLedgerDto);
-
- List<PaymentRegistrationDto> supplierNameListPageDetails(PaymentLedgerDto paymentLedgerDto);
-}
diff --git a/src/main/java/com/ruoyi/purchase/service/IProductRecordService.java b/src/main/java/com/ruoyi/purchase/service/IProductRecordService.java
deleted file mode 100644
index 3ab3d32..0000000
--- a/src/main/java/com/ruoyi/purchase/service/IProductRecordService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.ruoyi.purchase.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.purchase.dto.ProductRecordDto;
-import com.ruoyi.purchase.dto.TicketRegistrationDto;
-import com.ruoyi.purchase.pojo.ProductRecord;
-
-import java.util.List;
-
-/**
- * 閲囪喘鍙拌处浜у搧寮�绁ㄨ褰昐ervice鎺ュ彛
- *
- * @author ruoyi
- * @date 2025-05-23
- */
-public interface IProductRecordService extends IService<ProductRecord> {
-
- List<ProductRecord> selectProductRecordList(TicketRegistrationDto ticketRegistrationDto);
-
- IPage<ProductRecordDto> productRecordPage(Page page, TicketRegistrationDto ticketRegistrationDto);
-
- AjaxResult updateRecord(ProductRecordDto productRecordDto);
-
- ProductRecordDto getProductRecordById(ProductRecordDto productRecordDto);
-}
diff --git a/src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java b/src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java
index d09050e..a1f135e 100644
--- a/src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java
+++ b/src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java
@@ -6,10 +6,10 @@
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.purchase.dto.PurchaseLedgerDto;
import com.ruoyi.purchase.pojo.PurchaseLedger;
-import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import org.springframework.web.multipart.MultipartFile;
+import java.util.Date;
import java.util.List;
/**
@@ -40,9 +40,7 @@
IPage<PurchaseLedgerDto> selectPurchaseLedgerListPage(IPage ipage, PurchaseLedgerDto purchaseLedger);
- List<InvoiceRegistrationProduct> getProductBySalesNo(Long id);
-
- String getPurchaseNo();
+ String getPurchaseNo(Date entryDate);
AjaxResult importData(MultipartFile file);
diff --git a/src/main/java/com/ruoyi/purchase/service/ITicketRegistrationService.java b/src/main/java/com/ruoyi/purchase/service/ITicketRegistrationService.java
deleted file mode 100644
index 6c1cf5b..0000000
--- a/src/main/java/com/ruoyi/purchase/service/ITicketRegistrationService.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.ruoyi.purchase.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.purchase.dto.PaymentRegistrationDto;
-import com.ruoyi.purchase.dto.PurchaseLedgerDto;
-import com.ruoyi.purchase.dto.TicketRegistrationDto;
-import com.ruoyi.purchase.pojo.TicketRegistration;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * 鏉ョエ鐧昏Service鎺ュ彛
- *
- * @author ruoyi
- * @date 2025-05-13
- */
-public interface ITicketRegistrationService extends IService<TicketRegistration> {
-
- List<TicketRegistration> selectTicketRegistrationList(TicketRegistration ticketRegistration);
-
- int addOrUpdateRegistration(TicketRegistrationDto ticketRegistrationDto) throws IOException;
-
- int delRegistration(Long[] ids);
-
- TicketRegistrationDto getRegistrationById(TicketRegistrationDto ticketRegistrationDto);
-
- List getTicketNo(TicketRegistrationDto ticketRegistrationDto);
-
- IPage<TicketRegistration> selectTicketRegistrationListPage(Page page, TicketRegistration ticketRegistration);
-
- PurchaseLedgerDto getPuargeById(Long id);
-
- List<PaymentRegistrationDto> getPaymentRegistrationDtoById(Long id);
-}
diff --git a/src/main/java/com/ruoyi/purchase/service/PurchaseReportService.java b/src/main/java/com/ruoyi/purchase/service/PurchaseReportService.java
new file mode 100644
index 0000000..4ec6522
--- /dev/null
+++ b/src/main/java/com/ruoyi/purchase/service/PurchaseReportService.java
@@ -0,0 +1,14 @@
+package com.ruoyi.purchase.service;
+
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.purchase.dto.VatDto;
+import com.ruoyi.purchase.vo.PurchaseReportVo;
+
+public interface PurchaseReportService {
+
+ IPage<PurchaseReportVo> list(Page page, String customerName);
+
+ IPage<VatDto> listVat(Page page, String month);
+}
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/InvoicePurchaseServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/InvoicePurchaseServiceImpl.java
deleted file mode 100644
index 8b76b1a..0000000
--- a/src/main/java/com/ruoyi/purchase/service/impl/InvoicePurchaseServiceImpl.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package com.ruoyi.purchase.service.impl;
-
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.enums.FileNameType;
-import com.ruoyi.common.utils.bean.BeanUtils;
-import com.ruoyi.other.mapper.TempFileMapper;
-import com.ruoyi.project.system.domain.SysUser;
-import com.ruoyi.project.system.mapper.SysUserMapper;
-import com.ruoyi.purchase.dto.InvoicePurchaseDto;
-import com.ruoyi.purchase.dto.InvoicePurchaseReportDto;
-import com.ruoyi.purchase.dto.VatDto;
-import com.ruoyi.purchase.mapper.InvoicePurchaseMapper;
-import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
-import com.ruoyi.purchase.pojo.InvoicePurchase;
-import com.ruoyi.purchase.pojo.PurchaseLedger;
-import com.ruoyi.purchase.service.IInvoicePurchaseService;
-import com.ruoyi.sales.mapper.CommonFileMapper;
-import com.ruoyi.sales.pojo.CommonFile;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
-import org.springframework.util.StringUtils;
-
-import java.io.IOException;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * 鍙戠エ淇℃伅Service涓氬姟灞傚鐞�
- *
- * @author ruoyi
- * @date 2025-05-14
- */
-@Service
-@RequiredArgsConstructor
-@Slf4j
-public class InvoicePurchaseServiceImpl extends ServiceImpl<InvoicePurchaseMapper, InvoicePurchase> implements IInvoicePurchaseService {
-
- private final InvoicePurchaseMapper invoicePurchaseMapper;
-
- private final PurchaseLedgerMapper purchaseLedgerMapper;
-
- private final SysUserMapper userMapper;
-
- private final CommonFileMapper commonFileMapper;
-
-
-
- @Override
- public List<InvoicePurchaseDto> selectInvoicePurchaseList(InvoicePurchaseDto invoicePurchaseDto) {
- // 鏋勫缓鍙戠エ鏌ヨ鏉′欢
- LambdaQueryWrapper<InvoicePurchase> queryWrapper = new LambdaQueryWrapper<>();
- Optional.ofNullable(invoicePurchaseDto)
- .ifPresent(dto -> {
- if (StringUtils.hasText(dto.getPurchaseContractNo())) {
- queryWrapper.like(InvoicePurchase::getPurchaseContractNo, dto.getPurchaseContractNo());
- }
- if (StringUtils.hasText(dto.getSupplierName())) {
- queryWrapper.like(InvoicePurchase::getSupplierName, dto.getSupplierName());
- }
- // 澶勭悊鏃ユ湡绫诲瀷瀛楁
- if (dto.getIssueDate() != null) {
- queryWrapper.eq(InvoicePurchase::getIssueDate,invoicePurchaseDto.getIssueDate());
- }
- });
-
- // 鏌ヨ鍙戠エ鍒楄〃
- List<InvoicePurchase> invoiceList = invoicePurchaseMapper.selectList(queryWrapper);
-
- // 濡傛灉娌℃湁鏌ヨ鍒板彂绁紝鐩存帴杩斿洖绌哄垪琛�
- if (CollectionUtils.isEmpty(invoiceList)) {
- return Collections.emptyList();
- }
-
- // 鎻愬彇鎵�鏈夊彂绁↖D
- List<Long> invoiceIds = invoiceList.stream()
- .map(InvoicePurchase::getId)
- .collect(Collectors.toList());
-
- // 鎵归噺鏌ヨ杩欎簺鍙戠エ鍏宠仈鐨勬枃浠朵俊鎭�
- LambdaQueryWrapper<CommonFile> fileQueryWrapper = new LambdaQueryWrapper<>();
- fileQueryWrapper.in(CommonFile::getCommonId, invoiceIds)
- .eq(CommonFile::getType, FileNameType.INVOICE.getValue());
- List<CommonFile> fileList = commonFileMapper.selectList(fileQueryWrapper);
-
- // 灏嗘枃浠朵俊鎭槧灏勫埌瀵瑰簲鐨勫彂绁↖D
- Map<Long, String> fileMap = fileList.stream()
- .collect(Collectors.toMap(
- CommonFile::getCommonId,
- CommonFile::getName,
- (existing, replacement) -> existing // 濡傛灉鏈夊涓枃浠讹紝鍙栫涓�涓�
- ));
-
- // 灏嗘枃浠朵俊鎭缃埌鍙戠エDTO涓�
- List<InvoicePurchaseDto> resultList = new ArrayList<>();
- for (InvoicePurchase invoice : invoiceList) {
- InvoicePurchaseDto dto = new InvoicePurchaseDto();
- // 灏咺nvoicePurchase鐨勫睘鎬у鍒跺埌DTO
- BeanUtils.copyProperties(invoice, dto);
- // 璁剧疆鏂囦欢鍚嶏紝濡傛灉瀛樺湪鐨勮瘽
- dto.setFileName(fileMap.getOrDefault(invoice.getId(), null));
- resultList.add(dto);
- }
-
- return resultList;
- }
-
- @Override
- public int delInvoice(Long[] ids) {
- return invoicePurchaseMapper.deleteBatchIds(Arrays.asList(ids));
- }
-
- @Override
- public int addOrUpdateInvoice(InvoicePurchaseDto invoicePurchaseDto) throws IOException {
- int i;
- PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(invoicePurchaseDto.getPurchaseLedgerId());
- InvoicePurchase invoicePurchase = new InvoicePurchase();
- BeanUtils.copyProperties(invoicePurchaseDto, invoicePurchase);
- invoicePurchase.setPurchaseContractNo(purchaseLedger.getPurchaseContractNumber());
- invoicePurchase.setSalesContractNo(purchaseLedger.getSalesContractNo());
- SysUser sysUser = userMapper.selectUserById(invoicePurchase.getIssUerId());
- invoicePurchase.setIssUer(sysUser.getNickName());
- invoicePurchase.setTenantId(purchaseLedger.getTenantId());
- if (invoicePurchaseDto.getId() == null) {
- i = invoicePurchaseMapper.insert(invoicePurchase);
- } else {
- i = invoicePurchaseMapper.updateById(invoicePurchase);
- }
-
- // 杩佺Щ涓存椂鏂囦欢鍒版寮忕洰褰�
-// if (invoicePurchaseDto.getTempFileIds() != null && !invoicePurchaseDto.getTempFileIds().isEmpty()) {
-// migrateTempFilesToFormal(invoicePurchase.getId(), invoicePurchaseDto.getTempFileIds());
-// }
-
- return i;
- }
-
- @Override
- public InvoicePurchaseDto getInvoiceById(InvoicePurchaseDto invoicePurchaseDto) {
- InvoicePurchase invoicePurchase = invoicePurchaseMapper.selectById(invoicePurchaseDto.getId());
- InvoicePurchaseDto resultDto = new InvoicePurchaseDto();
- BeanUtils.copyProperties(invoicePurchase, resultDto);
-
- // 鏌ヨ涓婁紶鏂囦欢
- LambdaQueryWrapper<CommonFile> commonFileLambdaQueryWrapper = new LambdaQueryWrapper<>();
- commonFileLambdaQueryWrapper.eq(CommonFile::getCommonId, invoicePurchaseDto.getId())
- .eq(CommonFile::getType, FileNameType.INVOICE.getValue());
- List<CommonFile> commonFiles = commonFileMapper.selectList(commonFileLambdaQueryWrapper);
- resultDto.setCommonFiles(commonFiles);
- return resultDto;
- }
-
- @Override
- public List<InvoicePurchase> selectInvoicePurchaseLists(InvoicePurchase invoicePurchase) {
- return invoicePurchaseMapper.selectList(new LambdaQueryWrapper<>());
- }
-
- @Override
- public IPage<InvoicePurchaseReportDto> listPurchaseReport(Page page, InvoicePurchaseReportDto invoicePurchaseReportDto) {
- // 澧炲�肩◣ = 閿�鍞殑锛堝惈绋庢�讳环-涓嶅惈绋庢�讳环锛夊噺鍘婚噰璐殑锛堝惈绋庢�讳环-涓嶅惈绋庢�讳环锛�
- return invoicePurchaseMapper.selectPurchaseReport(page, invoicePurchaseReportDto);
- }
-
- @Override
- public IPage<VatDto> listVat(Page page, String month) {
- IPage<VatDto> vatDtos = invoicePurchaseMapper.listVat(page,month);
- vatDtos.getRecords().forEach(vatDto -> {
- vatDto.setTaxAmount(vatDto.getJTaxAmount().subtract(vatDto.getXTaxAmount()));
- });
- return vatDtos;
- }
-}
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PaymentRegistrationServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PaymentRegistrationServiceImpl.java
deleted file mode 100644
index d5875e3..0000000
--- a/src/main/java/com/ruoyi/purchase/service/impl/PaymentRegistrationServiceImpl.java
+++ /dev/null
@@ -1,564 +0,0 @@
-package com.ruoyi.purchase.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.account.pojo.AccountExpense;
-import com.ruoyi.account.service.AccountExpenseService;
-import com.ruoyi.basic.mapper.SupplierManageMapper;
-import com.ruoyi.basic.pojo.SupplierManage;
-import com.ruoyi.common.utils.DateUtils;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.framework.security.LoginUser;
-import com.ruoyi.purchase.dto.PaymentHistoryRecordVo;
-import com.ruoyi.purchase.dto.PaymentLedgerDto;
-import com.ruoyi.purchase.dto.PaymentRegistrationDto;
-import com.ruoyi.purchase.mapper.PaymentRegistrationMapper;
-import com.ruoyi.purchase.mapper.ProductRecordMapper;
-import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
-import com.ruoyi.purchase.mapper.TicketRegistrationMapper;
-import com.ruoyi.purchase.pojo.PaymentRegistration;
-import com.ruoyi.purchase.pojo.ProductRecord;
-import com.ruoyi.purchase.pojo.PurchaseLedger;
-import com.ruoyi.purchase.pojo.TicketRegistration;
-import com.ruoyi.purchase.service.IPaymentRegistrationService;
-import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-import org.springframework.util.ObjectUtils;
-import org.springframework.util.StringUtils;
-
-import java.math.BigDecimal;
-import java.text.SimpleDateFormat;
-import java.time.LocalDate;
-import java.time.YearMonth;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * 浠樻鐧昏Service涓氬姟灞傚鐞�
- *
- * @author ruoyi
- * @date 2025-05-15
- */
-@Service
-@RequiredArgsConstructor
-public class PaymentRegistrationServiceImpl extends ServiceImpl<PaymentRegistrationMapper, PaymentRegistration> implements IPaymentRegistrationService {
-
- private final PaymentRegistrationMapper paymentRegistrationMapper;
- private final PurchaseLedgerMapper purchaseLedgerMapper;
- private final SupplierManageMapper supplierManageMapper;
- private final SalesLedgerProductMapper salesLedgerProductMapper;
- private final TicketRegistrationMapper ticketRegistrationMapper;
- private final ProductRecordMapper productRecordMapper;
- private final AccountExpenseService accountExpenseService;
-
- /**
- * 鏌ヨ浠樻鐧昏
- *
- * @param id 浠樻鐧昏涓婚敭
- * @return 浠樻鐧昏
- */
- @Override
- public PaymentRegistration selectPaymentRegistrationById(Long id) {
- return paymentRegistrationMapper.selectPaymentRegistrationById(id);
- }
-
- /**
- * 鏌ヨ浠樻鐧昏鍒楄〃
- *
- * @param paymentRegistrationDto 浠樻鐧昏
- * @return 浠樻鐧昏
- */
- @Override
- public List<PaymentRegistrationDto> selectPaymentRegistrationList(PaymentRegistrationDto paymentRegistrationDto) {
- List<PaymentRegistrationDto> list = paymentRegistrationMapper.selectPaymentRegistrationList(paymentRegistrationDto);
- for (PaymentRegistrationDto registrationDto : list) {
- List<PaymentRegistration> paymentRegistrations = paymentRegistrationMapper.selectList(new QueryWrapper<PaymentRegistration>()
- .eq("ticket_registration_id", registrationDto.getTicketRegistrationId()));
- BigDecimal total = paymentRegistrations.stream().map(PaymentRegistration::getCurrentPaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
- BigDecimal invoiceAmount = (null != registrationDto.getInvoiceAmount())? registrationDto.getInvoiceAmount() : BigDecimal.ZERO;
- registrationDto.setUnPaymentAmount(invoiceAmount.subtract(total));
- }
- return list;
- }
-
- /**
- * 鏂板浠樻鐧昏
- *
- * @param paymentRegistrationList 浠樻鐧昏
- * @return 缁撴灉
- */
- @Override
- public int insertPaymentRegistration(List<PaymentRegistration> paymentRegistrationList) {
- LoginUser userId = SecurityUtils.getLoginUser();
- for (PaymentRegistration paymentRegistration : paymentRegistrationList) {
- PaymentRegistration byId = paymentRegistration;
- if (!ObjectUtils.isEmpty(paymentRegistration.getId())){
- paymentRegistration = this.getById(paymentRegistration.getId());
- }
- PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(paymentRegistration.getPurchaseLedgerId());
- if(null==purchaseLedger) throw new RuntimeException("鏈壘鍒伴噰璐崟");
- // 宸插洖娆鹃噾棰�
- SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(paymentRegistration.getSalesLedgerProductId());
- if(null==salesLedgerProduct) throw new RuntimeException("鏈壘鍒伴噰璐崟浜у搧");
- if (salesLedgerProduct.getPendingTicketsTotal().compareTo(paymentRegistration.getCurrentPaymentAmount())<0){
- throw new RuntimeException("鏈鍥炴閲戦涓嶈兘澶т簬寰呭洖娆鹃噾棰�");
- }
- paymentRegistration.setCreateTime(DateUtils.getNowDate());
- paymentRegistration.setUpdateTime(DateUtils.getNowDate());
- paymentRegistration.setRegistrantId(userId.getUserId());
- salesLedgerProduct.setTicketsTotal(salesLedgerProduct.getTicketsTotal().add(paymentRegistration.getCurrentPaymentAmount()));
- salesLedgerProduct.setPendingTicketsTotal(salesLedgerProduct.getTaxInclusiveTotalPrice().subtract(salesLedgerProduct.getTicketsTotal()));
- paymentRegistrationMapper.insert(paymentRegistration);
- salesLedgerProductMapper.updateById(salesLedgerProduct);
- // 2. 澶勭悊璐︽埛鏀嚭
- AccountExpense accountExpense = new AccountExpense();
- accountExpense.setExpenseDate(purchaseLedger.getEntryDate());
- accountExpense.setExpenseType("4");
- accountExpense.setSupplierName(purchaseLedger.getSupplierName());
- accountExpense.setExpenseMoney(paymentRegistration.getCurrentPaymentAmount());
- accountExpense.setExpenseDescribed("浠樻鏀嚭");
-
- accountExpense.setExpenseMethod(paymentRegistration.getPaymentMethod());
- accountExpense.setBusinessId(paymentRegistration.getId());
- accountExpense.setBusinessType(1);
- accountExpense.setInputTime(new Date());
- accountExpense.setInputUser(userId.getNickName());
- accountExpenseService.save(accountExpense);
- }
- return 1;
-
- }
-
- /**
- * 淇敼浠樻鐧昏
- *
- * @param paymentRegistration 浠樻鐧昏
- * @return 缁撴灉
- */
- @Override
- public int updatePaymentRegistration(PaymentRegistration paymentRegistration) {
- PaymentRegistration paymentRegistration1 = paymentRegistrationMapper.selectById(paymentRegistration.getId());
- if(null==paymentRegistration1) throw new RuntimeException("鏈壘鍒颁粯娆剧櫥璁�");
- SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(paymentRegistration1.getSalesLedgerProductId());
- if(null==salesLedgerProduct) throw new RuntimeException("鏈壘鍒伴噰璐崟浜у搧");
- // 鍒ゆ柇浠樻閲戦涓嶅彲澶т簬寰呬粯娆鹃噾棰�
- BigDecimal subtract = paymentRegistration.getCurrentPaymentAmount().subtract(paymentRegistration1.getCurrentPaymentAmount());
- if (subtract.compareTo(salesLedgerProduct.getPendingTicketsTotal()) > 0) {
- throw new RuntimeException("浠樻閲戦瓒呭嚭寰呬粯娆鹃噾棰�");
- }
- paymentRegistration.setUpdateTime(DateUtils.getNowDate());
- // 鍚屾淇敼璐︽埛鏀嚭
- LambdaQueryWrapper<AccountExpense> accountExpenseLambdaQueryWrapper = new LambdaQueryWrapper<>();
- accountExpenseLambdaQueryWrapper.eq(AccountExpense::getBusinessId, paymentRegistration.getId())
- .eq(AccountExpense::getBusinessType, 1)
- .last("limit 1");
- AccountExpense accountExpense = accountExpenseService.getOne(accountExpenseLambdaQueryWrapper);
- if(null!=accountExpense){
- accountExpense.setExpenseMoney(paymentRegistration.getCurrentPaymentAmount());
- accountExpenseService.updateById(accountExpense);
- }
- // 淇敼閲囪喘浜у搧浠樻閲戦
- salesLedgerProduct.setTicketsTotal(salesLedgerProduct.getTicketsTotal().add(subtract));
- salesLedgerProduct.setPendingTicketsTotal(salesLedgerProduct.getTaxInclusiveTotalPrice().subtract(salesLedgerProduct.getTicketsTotal()));
- salesLedgerProductMapper.updateById(salesLedgerProduct);
- return paymentRegistrationMapper.updateById(paymentRegistration);
- }
-
- /**
- * 鎵归噺鍒犻櫎浠樻鐧昏
- *
- * @param ids 闇�瑕佸垹闄ょ殑浠樻鐧昏涓婚敭
- * @return 缁撴灉
- */
- @Override
- public int deletePaymentRegistrationByIds(Long[] ids) {
- return paymentRegistrationMapper.delete(new QueryWrapper<PaymentRegistration>().in("id", ids));
- }
-
- @Override
- public PaymentRegistration selectPaymentRegistrationByPurchaseId(Long id) {
- PaymentRegistrationDto paymentRegistrationDto = new PaymentRegistrationDto();
- PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(id);
- paymentRegistrationDto.setSalesContractNo(purchaseLedger.getSalesContractNo());
- paymentRegistrationDto.setSupplierName(purchaseLedger.getSupplierName());
- paymentRegistrationDto.setSupplierId(purchaseLedger.getSupplierId());
-
- List<TicketRegistration> ticketRegistrations = ticketRegistrationMapper.selectList(new QueryWrapper<TicketRegistration>()
- .eq("purchase_contract_number", purchaseLedger.getPurchaseContractNumber()));
- if (ticketRegistrations != null && ticketRegistrations.size() > 0) {
- paymentRegistrationDto.setInvoiceNumber(ticketRegistrations.get(0).getInvoiceNumber());
- paymentRegistrationDto.setInvoiceAmount(ticketRegistrations.get(0).getInvoiceAmount());
- }
- return paymentRegistrationDto;
- }
-
- @Override
- public IPage<Map<String, Object>> selectPaymentLedgerList(
- PaymentLedgerDto paymentLedgerDto,
- Page page,
- Integer detailPageNum,
- Integer detailPageSize) {
- LambdaQueryWrapper<SupplierManage> queryWrapper = new LambdaQueryWrapper<>();
- Optional.ofNullable(paymentLedgerDto)
- .ifPresent(dto -> {
- if (StringUtils.hasText(dto.getSupplierName())) {
- queryWrapper.like(SupplierManage::getSupplierName, dto.getSupplierName());
- }
- });
-
- IPage<SupplierManage> supplierPage = supplierManageMapper.selectPage(page, queryWrapper);
- List<SupplierManage> supplierManages = supplierPage.getRecords();
-
- IPage<Map<String, Object>> resultPage = new Page<>(page.getCurrent(), page.getSize(), supplierPage.getTotal());
- List<Map<String, Object>> result = new ArrayList<>();
-
- for (SupplierManage supplierManage : supplierManages) {
- Map<String, Object> res = new HashMap<>();
- res.put("supplierName", supplierManage.getSupplierName());
- res.put("supplierId", supplierManage.getId());
-
- // 搴斾粯閲戦璁$畻
- BigDecimal payableAmount = BigDecimal.ZERO;
- List<PurchaseLedger> purchaseLedgers = purchaseLedgerMapper.selectList(
- new QueryWrapper<PurchaseLedger>().eq("supplier_id", supplierManage.getId())
- );
- List<SalesLedgerProduct> salesLedgerProducts = purchaseLedgers.stream()
- .filter(Objects::nonNull)
- .map(PurchaseLedger::getId)
- .filter(Objects::nonNull)
- .flatMap(id -> salesLedgerProductMapper.selectList(
- new QueryWrapper<SalesLedgerProduct>().eq("sales_ledger_id", id).eq("type",2)
- ).stream())
- .collect(Collectors.toList());
- payableAmount = salesLedgerProducts.stream()
- .map(SalesLedgerProduct::getTaxInclusiveTotalPrice)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
-
- // 鏉ョエ閲戦璁$畻
- List<TicketRegistration> ticketRegistrations = purchaseLedgers.stream()
- .map(PurchaseLedger::getId)
- .filter(Objects::nonNull)
- .map(id -> ticketRegistrationMapper.selectList(
- new LambdaQueryWrapper<TicketRegistration>().eq(TicketRegistration::getPurchaseLedgerId, id)
- ))
- .flatMap(Collection::stream)
- .collect(Collectors.toList());
- BigDecimal invoiceAmount = ticketRegistrations.stream()
- .map(TicketRegistration::getInvoiceAmount)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
-
- // 浠樻璁板綍鍙婅鎯呭垎椤�
- List<PaymentRegistration> paymentRegistrations = paymentRegistrationMapper.selectList(
- new QueryWrapper<PaymentRegistration>().eq("supplier_id", supplierManage.getId())
- );
- BigDecimal paymentAmount = paymentRegistrations.stream()
- .map(PaymentRegistration::getCurrentPaymentAmount)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
-
- // 璇︽儏鍒嗛〉澶勭悊
- detailPageNum = detailPageNum != null ? detailPageNum : 1;
- detailPageSize = detailPageSize != null ? detailPageSize : paymentRegistrations.size(); // 榛樿鏄剧ず鍏ㄩ儴
- int totalDetails = paymentRegistrations.size();
- int start = (detailPageNum - 1) * detailPageSize;
- int end = Math.min(start + detailPageSize, totalDetails);
- List<PaymentRegistration> pagedDetails = paymentRegistrations.subList(start, end);
-
- // 鏋勫缓璇︽儏鍒楄〃
- List<Map<String, Object>> details = pagedDetails.stream()
- .filter(Objects::nonNull)
- .map(pr -> {
- Map<String, Object> detail = new HashMap<>();
- detail.put("paymentAmount", pr.getCurrentPaymentAmount());
-
- // 鎵归噺鏌ヨ TicketRegistration锛堥伩鍏� N+1锛�
- TicketRegistration ticketRegistration = ticketRegistrationMapper.selectById(pr.getTicketRegistrationId());
- if (ticketRegistration != null) {
- detail.put("payableAmount", ticketRegistration.getInvoiceAmount());
- BigDecimal voteCount = productRecordMapper.selectList(
- new LambdaQueryWrapper<ProductRecord>().eq(ProductRecord::getTicketRegistrationId, ticketRegistration.getId())
- ).stream()
- .map(ProductRecord::getTicketsNum)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- detail.put("voteCount", voteCount);
- }
-
- // 鏃ユ湡鏍煎紡鍖栵紙寤鸿浣跨敤 LocalDateTime锛�
- if (pr.getPaymentDate() != null) {
- detail.put("paymentDate", new SimpleDateFormat("yyyy-MM-dd").format(pr.getPaymentDate()));
- }
- return detail;
- })
- .collect(Collectors.toList());
-
- // 灏佽璇︽儏鍒嗛〉鍏冩暟鎹�
- Map<String, Object> detailPagination = new HashMap<>();
- detailPagination.put("total", totalDetails);
- detailPagination.put("pageNum", detailPageNum);
- detailPagination.put("pageSize", detailPageSize);
- detailPagination.put("pages", (int) Math.ceil((double) totalDetails / detailPageSize));
-
- // 搴斾粯閲戦閫昏緫涓嶉噰鐢ㄥ悎鍚岄噾棰濇敼鎴� 鍙戠エ閲戦鍑忎粯娆鹃噾棰�
- payableAmount = invoiceAmount.subtract(paymentAmount);
- res.put("invoiceAmount", invoiceAmount);
- res.put("payableAmount", payableAmount);
- res.put("paymentAmount", paymentAmount);
- res.put("details", details);
- res.put("detailPagination", detailPagination); // 娣诲姞璇︽儏鍒嗛〉淇℃伅
- result.add(res);
- }
-
- resultPage.setRecords(result);
- return resultPage;
- }
-
- @Override
- public Map<String, BigDecimal> paymentMonthList() {
-
- // 鏌ヨ渚涘簲鍟嗗垪琛�
- List<SupplierManage> suppliers = supplierManageMapper.selectList(null);
- if (CollectionUtils.isEmpty(suppliers)) {
- Map<String, BigDecimal> result = new HashMap<>();
- result.put("payableAmount", BigDecimal.ZERO);
- result.put("paymentAmount", BigDecimal.ZERO);
- return result;
- }
-
- // 鎻愬彇鎵�鏈変緵搴斿晢ID
- List<Long> supplierIds = suppliers.stream()
- .map(SupplierManage::getId) // 鍏堣幏鍙朓nteger绫诲瀷鐨処D
- .filter(Objects::nonNull) // 杩囨护鎺夊彲鑳界殑null鍊�
- .collect(Collectors.toList());
-
- // 鑾峰彇褰撴湀鐨勫紑濮嬪拰缁撴潫鏃ユ湡
- YearMonth currentMonth = YearMonth.now();
- LocalDate startDate = currentMonth.atDay(1);
- LocalDate endDate = currentMonth.atEndOfMonth();
-
- // 鎵归噺鏌ヨ閲囪喘鍙拌处锛堝綋鏈堬級
- Map<Long, List<PurchaseLedger>> purchaseLedgerMap = batchQueryPurchaseLedgers(supplierIds, startDate, endDate);
-
- // 鎵归噺鏌ヨ閿�鍞彴璐︿骇鍝�
- Map<Long, List<SalesLedgerProduct>> salesLedgerProductMap = batchQuerySalesLedgerProducts(purchaseLedgerMap);
-
- // 鎵归噺鏌ヨ浠樻璁板綍锛堝綋鏈堬級
- Map<Long, List<PaymentRegistration>> paymentRegistrationMap = batchQueryPaymentRegistrations(supplierIds, startDate, endDate);
-
- // 璁$畻搴斾粯閲戦鍜屼粯娆鹃噾棰�
- BigDecimal totalPayableAmount = calculateTotalPayableAmount(purchaseLedgerMap, salesLedgerProductMap);
- BigDecimal totalPaymentAmount = calculateTotalPaymentAmount(paymentRegistrationMap);
-
- // 鏋勫缓缁撴灉
- Map<String, BigDecimal> result = new HashMap<>();
- result.put("payableAmount", totalPayableAmount);
- result.put("paymentAmount", totalPaymentAmount);
- return result;
- }
-
- /**
- * 鏌ヨ浠樻鐧昏鍒楄〃
- *
- * @param paymentRegistrationDto 浠樻鐧昏
- * @return 浠樻鐧昏闆嗗悎
- */
- @Override
- public List<PaymentRegistrationDto> paymentHistoryList(PaymentRegistrationDto paymentRegistrationDto) {
- return paymentRegistrationMapper.paymentHistoryList(paymentRegistrationDto);
- }
-
- /**
- * 鏌ヨ渚涘簲鍟嗗線鏉ヨ褰�
- * @param supplierId
- * @return
- */
- @Override
- public List<PaymentHistoryRecordVo> getPaymentRecordList(Long supplierId) {
- List<PaymentHistoryRecordVo> paymentRecordList = paymentRegistrationMapper.getPaymentRecordList(supplierId);
- List<PaymentHistoryRecordVo> result = new ArrayList<>();
- List<PaymentHistoryRecordVo> newResult = new ArrayList<>();
- // 搴斾粯鎬婚噾棰濋噾棰濊绠�
- BigDecimal amountTotal = BigDecimal.ZERO;
- if(CollectionUtils.isNotEmpty(paymentRecordList)) {
- Map<LocalDate, List<PaymentHistoryRecordVo>> dateListMap = paymentRecordList.stream().collect(
- Collectors.groupingBy(
- PaymentHistoryRecordVo::getHappenTime,
- LinkedHashMap::new,
- Collectors.toList()
- )
- );
- for (LocalDate localDate : dateListMap.keySet()) {
- BigDecimal currentPaymentAmount = BigDecimal.ZERO;
- BigDecimal invoiceAmount = BigDecimal.ZERO;
- BigDecimal currentDateTotal = BigDecimal.ZERO;
- List<PaymentHistoryRecordVo> paymentHistoryRecordVos = dateListMap.get(localDate);
- // 璁$畻褰撳ぉ姹囨鏁�
- currentPaymentAmount = paymentHistoryRecordVos.stream()
- .filter(item ->item.getType() == 0)
- .map(PaymentHistoryRecordVo::getCurrentPaymentAmount)
- .reduce(BigDecimal.ZERO,BigDecimal::add);
- // 璁$畻浠婂ぉ鏉ョエ鏁�
- invoiceAmount = paymentHistoryRecordVos.stream()
- .filter(item ->item.getType() == 1)
- .map(PaymentHistoryRecordVo::getInvoiceAmount)
- .reduce(BigDecimal.ZERO,BigDecimal::add);
- // 璁$畻褰撴棩姹囨��
- currentDateTotal = currentDateTotal.add(invoiceAmount).subtract(currentPaymentAmount);
- PaymentHistoryRecordVo paymentHistoryRecordVo = new PaymentHistoryRecordVo();
- paymentHistoryRecordVo.setHappenTime(localDate);
- paymentHistoryRecordVo.setCurrentPaymentAmount(currentPaymentAmount);
- paymentHistoryRecordVo.setInvoiceAmount(invoiceAmount);
- amountTotal = paymentHistoryRecordVo.getInvoiceAmount().subtract(paymentHistoryRecordVo.getCurrentPaymentAmount());
- paymentHistoryRecordVo.setPayableAmount(amountTotal);
- result.add(paymentHistoryRecordVo);
- }
-
-
- for (int i = 0; i < result.size(); i++) {
- PaymentHistoryRecordVo paymentHistoryRecordVo = result.get(i);
- if (i == 0) {
- paymentHistoryRecordVo.setPayableAmount(paymentHistoryRecordVo.getInvoiceAmount().subtract(paymentHistoryRecordVo.getCurrentPaymentAmount()));
- }else {
- PaymentHistoryRecordVo paymentHistoryRecordVo1 = result.get(i-1);
- paymentHistoryRecordVo.setPayableAmount(paymentHistoryRecordVo1.getPayableAmount()
- .add(paymentHistoryRecordVo.getInvoiceAmount()).subtract(paymentHistoryRecordVo.getCurrentPaymentAmount()));
- }
- newResult.add(paymentHistoryRecordVo);
- }
- }
- return newResult;
- }
-
- /**
- * 鏌ヨ浠樻鐧昏鍒楄〃鍒嗛〉
- *
- * @param paymentRegistrationDto 浠樻鐧昏
- * @return 浠樻鐧昏闆嗗悎
- */
- @Override
- public IPage<PaymentRegistrationDto> paymentHistoryListPage(Page page, PaymentRegistrationDto paymentRegistrationDto) {
- return paymentRegistrationMapper.paymentHistoryListPage(page, paymentRegistrationDto);
- }
-
- @Override
- public Boolean delete(Long[] ids) {
- for (Long id : ids) {
- List<ProductRecord> productRecords = productRecordMapper.selectList(new QueryWrapper<ProductRecord>().lambda().eq(ProductRecord::getTicketRegistrationId, id));
- for (ProductRecord productRecord : productRecords) {
- SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(productRecord.getSaleLedgerProjectId());
- salesLedgerProduct.setTicketsNum(salesLedgerProduct.getTicketsNum().subtract(productRecord.getTicketsNum()));
- salesLedgerProduct.setTicketsAmount(salesLedgerProduct.getTicketsAmount().subtract(productRecord.getTicketsAmount()));
- salesLedgerProduct.setFutureTickets(salesLedgerProduct.getFutureTickets().add(productRecord.getTicketsNum()));
- salesLedgerProduct.setFutureTicketsAmount(salesLedgerProduct.getFutureTicketsAmount().add(productRecord.getTicketsAmount()));
- salesLedgerProductMapper.updateById(salesLedgerProduct);
- }
- ticketRegistrationMapper.delete(new QueryWrapper<TicketRegistration>().lambda().eq(TicketRegistration::getId, id));
- productRecordMapper.delete(new QueryWrapper<ProductRecord>().lambda().eq(ProductRecord::getTicketRegistrationId, id));
- }
- return true;
- }
-
- @Override
- public int delPaymentRegistration(List<Long> ids) {
- LambdaQueryWrapper<AccountExpense> accountExpenseLambdaQueryWrapper = new LambdaQueryWrapper<>();
- accountExpenseLambdaQueryWrapper.in(AccountExpense::getBusinessId, ids)
- .eq(AccountExpense::getBusinessType, 1);
- accountExpenseService.remove(accountExpenseLambdaQueryWrapper);
- // 淇敼閲囪喘浜у搧鐨勫凡浠樻閲戦,寰呬粯娆鹃噾棰�
- List<PaymentRegistration> paymentRegistrations = paymentRegistrationMapper.selectBatchIds(ids);
- for (PaymentRegistration paymentRegistration : paymentRegistrations) {
- SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(paymentRegistration.getSalesLedgerProductId());
- salesLedgerProduct.setTicketsTotal(salesLedgerProduct.getTicketsTotal().subtract(paymentRegistration.getCurrentPaymentAmount()));
- salesLedgerProduct.setPendingTicketsTotal(salesLedgerProduct.getPendingTicketsTotal().add(paymentRegistration.getCurrentPaymentAmount()));
- salesLedgerProductMapper.updateById(salesLedgerProduct);
- }
- return paymentRegistrationMapper.deleteBatchIds(ids);
- }
-
- @Override
- public IPage<PaymentRegistrationDto> supplierNameListPage(Page page, PaymentLedgerDto paymentLedgerDto) {
- return paymentRegistrationMapper.supplierNameListPage(page, paymentLedgerDto);
- }
-
- @Override
- public List<PaymentRegistrationDto> supplierNameListPageDetails(PaymentLedgerDto paymentLedgerDto) {
- return paymentRegistrationMapper.supplierNameListPageDetails(paymentLedgerDto);
- }
-
- // 鎵归噺鏌ヨ閲囪喘鍙拌处锛堝綋鏈堬級
- private Map<Long, List<PurchaseLedger>> batchQueryPurchaseLedgers(List<Long> supplierIds, LocalDate startDate, LocalDate endDate) {
- LambdaQueryWrapper<PurchaseLedger> query = new LambdaQueryWrapper<>();
- query.in(PurchaseLedger::getSupplierId, supplierIds)
- .ge(PurchaseLedger::getCreatedAt, startDate)
- .le(PurchaseLedger::getCreatedAt, endDate);
- List<PurchaseLedger> purchaseLedgers = purchaseLedgerMapper.selectList(query);
-
- return purchaseLedgers.stream()
- .filter(pl -> pl.getSupplierId() != null)
- .collect(Collectors.groupingBy(PurchaseLedger::getSupplierId));
- }
-
- // 鎵归噺鏌ヨ閿�鍞彴璐︿骇鍝�
- private Map<Long, List<SalesLedgerProduct>> batchQuerySalesLedgerProducts(Map<Long, List<PurchaseLedger>> purchaseLedgerMap) {
- // 鎻愬彇鎵�鏈夐噰璐彴璐D
- List<Long> purchaseLedgerIds = purchaseLedgerMap.values().stream()
- .flatMap(Collection::stream)
- .map(PurchaseLedger::getId)
- .filter(Objects::nonNull)
- .collect(Collectors.toList());
-
- if (purchaseLedgerIds.isEmpty()) {
- return Collections.emptyMap();
- }
-
- LambdaQueryWrapper<SalesLedgerProduct> query = new LambdaQueryWrapper<>();
- query.in(SalesLedgerProduct::getSalesLedgerId, purchaseLedgerIds);
- List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(query);
-
- return products.stream()
- .filter(slp -> slp.getSalesLedgerId() != null)
- .collect(Collectors.groupingBy(SalesLedgerProduct::getSalesLedgerId));
- }
-
- // 鎵归噺鏌ヨ浠樻璁板綍锛堝綋鏈堬級
- private Map<Long, List<PaymentRegistration>> batchQueryPaymentRegistrations(List<Long> supplierIds, LocalDate startDate, LocalDate endDate) {
- LambdaQueryWrapper<PaymentRegistration> query = new LambdaQueryWrapper<>();
- query.in(PaymentRegistration::getSupplierId, supplierIds)
- .ge(PaymentRegistration::getPaymentDate, startDate)
- .le(PaymentRegistration::getPaymentDate, endDate);
- List<PaymentRegistration> paymentRegistrations = paymentRegistrationMapper.selectList(query);
-
- return paymentRegistrations.stream()
- .filter(pr -> pr.getSupplierId() != null)
- .collect(Collectors.groupingBy(PaymentRegistration::getSupplierId));
- }
-
- // 璁$畻鎬诲簲浠橀噾棰�
- private BigDecimal calculateTotalPayableAmount(Map<Long, List<PurchaseLedger>> purchaseLedgerMap,
- Map<Long, List<SalesLedgerProduct>> salesLedgerProductMap) {
- return purchaseLedgerMap.values().stream()
- .flatMap(Collection::stream)
- .map(pl -> salesLedgerProductMap.getOrDefault(pl.getId(), Collections.emptyList()))
- .flatMap(Collection::stream)
- .map(SalesLedgerProduct::getTaxInclusiveTotalPrice)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- }
-
- // 璁$畻鎬讳粯娆鹃噾棰�
- private BigDecimal calculateTotalPaymentAmount(Map<Long, List<PaymentRegistration>> paymentRegistrationMap) {
- return paymentRegistrationMap.values().stream()
- .flatMap(Collection::stream)
- .map(PaymentRegistration::getCurrentPaymentAmount)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- }
-}
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/ProductRecordServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/ProductRecordServiceImpl.java
deleted file mode 100644
index 961e759..0000000
--- a/src/main/java/com/ruoyi/purchase/service/impl/ProductRecordServiceImpl.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package com.ruoyi.purchase.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.enums.FileNameType;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.purchase.dto.ProductRecordDto;
-import com.ruoyi.purchase.dto.TicketRegistrationDto;
-import com.ruoyi.purchase.mapper.ProductRecordMapper;
-import com.ruoyi.purchase.mapper.TicketRegistrationMapper;
-import com.ruoyi.purchase.pojo.ProductRecord;
-import com.ruoyi.purchase.pojo.TicketRegistration;
-import com.ruoyi.purchase.service.IProductRecordService;
-import com.ruoyi.sales.mapper.CommonFileMapper;
-import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
-import com.ruoyi.sales.pojo.CommonFile;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import lombok.RequiredArgsConstructor;
-import org.springframework.beans.BeanUtils;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.math.BigDecimal;
-import java.util.List;
-
-/**
- * 閲囪喘鍙拌处浜у搧寮�绁ㄨ褰昐ervice涓氬姟灞傚鐞�
- *
- * @author ruoyi
- * @date 2025-05-23
- */
-@Service
-@RequiredArgsConstructor
-public class ProductRecordServiceImpl extends ServiceImpl<ProductRecordMapper, ProductRecord> implements IProductRecordService {
-
- private final SalesLedgerProductMapper salesLedgerProductMapper;
- private final ProductRecordMapper productRecordMapper;
- private final CommonFileMapper commonFileMapper;
- /**
- * 鏌ヨ閲囪喘鍙拌处浜у搧寮�绁ㄨ褰�
- *
- * @param ticketRegistrationDto 閲囪喘鍙拌处浜у搧寮�绁ㄨ褰曚富閿�
- * @return 閲囪喘鍙拌处浜у搧寮�绁ㄨ褰�
- */
- @Override
- public List<ProductRecord> selectProductRecordList(TicketRegistrationDto ticketRegistrationDto) {
- return productRecordMapper.selectList(new LambdaQueryWrapper<ProductRecord>().eq(ProductRecord::getTicketRegistrationId, ticketRegistrationDto.getId())
- .eq(ProductRecord::getType, "2"));
- }
-
- @Override
- public IPage<ProductRecordDto> productRecordPage(Page page, TicketRegistrationDto ticketRegistrationDto) {
- IPage<ProductRecordDto> productRecordDtoIPage1 = productRecordMapper.productRecordPage(page, ticketRegistrationDto);
- page.setSize(productRecordDtoIPage1.getTotal());
- IPage<ProductRecordDto> productRecordDtoIPage = productRecordMapper.productRecordPage(page, ticketRegistrationDto);
- productRecordDtoIPage.getRecords().forEach(productRecordDto -> {
- productRecordDto.setCommonFiles(commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>().eq(CommonFile::getCommonId, productRecordDto.getId())
- .eq(CommonFile::getType, FileNameType.PURCHASELEDGER.getValue())));
- });
- return productRecordDtoIPage;
- }
-
- private final TicketRegistrationMapper ticketRegistrationMapper;
-
- @Override
- @Transactional(rollbackFor = Exception.class)
- public AjaxResult updateRecord(ProductRecordDto productRecordDto) {
- ProductRecord productRecord = productRecordMapper.selectById(productRecordDto.getId());
- if (productRecord == null) return AjaxResult.error("璁板綍涓嶅瓨鍦�");
-
- // 鏇存柊浜у搧鍙拌处
- SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(productRecord.getSaleLedgerProjectId());
- if (salesLedgerProduct != null) {
- // 鏈潵绁ㄩ噾棰� = 鍘熸湭鏉ョエ閲戦 + 鏃ц閲戦 - 鏂拌閲戦
- BigDecimal futureTicketsAmount = salesLedgerProduct.getFutureTicketsAmount()
- .add(productRecord.getTicketsAmount())
- .subtract(productRecordDto.getTicketsAmount());
- salesLedgerProduct.setFutureTicketsAmount(futureTicketsAmount);
-
- // 鏈潵绁ㄦ暟 = 鍘熸湭鏉ョエ鏁� + 鏃ц鏁伴噺 - 鏂拌鏁伴噺
- BigDecimal futureTickets = salesLedgerProduct.getFutureTickets()
- .add(productRecord.getTicketsNum())
- .subtract(productRecordDto.getTicketsNum());
- salesLedgerProduct.setFutureTickets(futureTickets);
-
- // 鏇存柊浜у搧琛ㄦ湰娆℃暟鍊�
- salesLedgerProduct.setTicketsAmount(productRecordDto.getTicketsAmount());
- salesLedgerProduct.setTicketsNum(productRecordDto.getTicketsNum());
- salesLedgerProductMapper.updateById(salesLedgerProduct);
- }
-
- // 鏇存柊鏉ョエ鐧昏
- TicketRegistration ticketRegistration = ticketRegistrationMapper.selectById(productRecord.getTicketRegistrationId());
- if (ticketRegistration != null) {
- // 閲戦 = 鏂伴噾棰� - 鏃ч噾棰�
- BigDecimal amountDiff = productRecordDto.getTicketsAmount().subtract(productRecord.getTicketsAmount());
- // 鎬婚噾棰� = 鍘熸�婚噾棰� + 宸��
- ticketRegistration.setInvoiceAmount(ticketRegistration.getInvoiceAmount().add(amountDiff));
- // 鏇存柊鍙戠エ鍙�
- ticketRegistration.setInvoiceNumber(productRecordDto.getInvoiceNumber());
-
- ticketRegistrationMapper.updateById(ticketRegistration);
- }
-
- BeanUtils.copyProperties(productRecordDto, productRecord);
- // 閲嶆柊璁$畻鏈潵绁ㄩ噾棰濓紙鏍规嵁鍓╀綑绁ㄦ暟 * 鍗曚环锛�
- productRecord.setFutureTicketsAmount(productRecord.getFutureTickets().multiply(productRecord.getTaxInclusiveUnitPrice()));
- productRecordMapper.updateById(productRecord);
-
- return AjaxResult.success("淇敼鎴愬姛");
- }
-
- @Override
- public ProductRecordDto getProductRecordById(ProductRecordDto productRecordDto) {
- List<ProductRecordDto> productRecordDtoList = productRecordMapper.getProductRecordById(productRecordDto);
- if (CollectionUtils.isNotEmpty(productRecordDtoList)) {
- ProductRecordDto productRecordDto1 = productRecordDtoList.stream()
- .filter(item -> item.getId().equals(productRecordDto.getId()))
- .findFirst()
- .orElse(null);
- // 杩囨护鍑轰笌浼犲叆鐨� productRecordDto 涓婚敭鐩稿悓鐨勮褰�
- BigDecimal reduce = productRecordDtoList
- .stream()
- .filter(item -> item.getProductModelId().equals(productRecordDto.getProductModelId()))
- .map(ProductRecordDto::getTicketsNum)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- if (productRecordDto1 != null) {
- productRecordDto1.setFutureTickets(productRecordDto1.getQuantity().subtract(reduce));
- productRecordDto1.setFutureTicketsAmount(productRecordDto1.getFutureTickets().multiply(productRecordDto1.getTaxInclusiveUnitPrice()));
- }
- return productRecordDto1;
- }
- return null;
- }
-}
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
index cdf80f9..9cf4d5a 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -33,14 +33,8 @@
import com.ruoyi.purchase.dto.PurchaseLedgerDto;
import com.ruoyi.purchase.dto.PurchaseLedgerImportDto;
import com.ruoyi.purchase.dto.PurchaseLedgerProductImportDto;
-import com.ruoyi.purchase.mapper.PaymentRegistrationMapper;
-import com.ruoyi.purchase.mapper.ProductRecordMapper;
import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
-import com.ruoyi.purchase.mapper.TicketRegistrationMapper;
-import com.ruoyi.purchase.pojo.PaymentRegistration;
-import com.ruoyi.purchase.pojo.ProductRecord;
import com.ruoyi.purchase.pojo.PurchaseLedger;
-import com.ruoyi.purchase.pojo.TicketRegistration;
import com.ruoyi.purchase.service.IPurchaseLedgerService;
import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.quality.mapper.QualityInspectParamMapper;
@@ -51,11 +45,9 @@
import com.ruoyi.quality.pojo.QualityTestStandard;
import com.ruoyi.quality.pojo.QualityTestStandardParam;
import com.ruoyi.sales.mapper.CommonFileMapper;
-import com.ruoyi.sales.mapper.InvoiceRegistrationProductMapper;
import com.ruoyi.sales.mapper.SalesLedgerMapper;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
import com.ruoyi.sales.pojo.CommonFile;
-import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
import com.ruoyi.sales.pojo.SalesLedger;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
@@ -99,10 +91,6 @@
private final ProductMapper productMapper;
private final ProductModelMapper productModelMapper;
private final SysUserMapper sysUserMapper;
- private final TicketRegistrationMapper ticketRegistrationMapper;
- private final ProductRecordMapper productRecordMapper;
- private final PaymentRegistrationMapper paymentRegistrationMapper;
- private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
private final StringRedisTemplate redisTemplate;
private final QualityInspectMapper qualityInspectMapper;
private final CommonFileServiceImpl commonFileService;
@@ -283,9 +271,6 @@
LocalDateTime localDateTime = entryDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
salesLedgerProduct.setRegisterDate(localDateTime);
- salesLedgerProduct.setFutureTickets(salesLedgerProduct.getQuantity());
- salesLedgerProduct.setFutureTicketsAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
- salesLedgerProduct.setPendingTicketsTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
salesLedgerProductMapper.insert(salesLedgerProduct);
}
}
@@ -333,18 +318,6 @@
queryWrapper.in(SalesLedgerProduct::getSalesLedgerId, ids)
.eq(SalesLedgerProduct::getType, 2);
salesLedgerProductMapper.delete(queryWrapper);
- // 鎵归噺鍒犻櫎鍏宠仈鐨勯噰璐彴璐︾殑鏉ョエ鐧昏
- LambdaQueryWrapper<TicketRegistration> ticketRegistrationLambdaQueryWrapper = new LambdaQueryWrapper<>();
- ticketRegistrationLambdaQueryWrapper.in(TicketRegistration::getPurchaseLedgerId,ids);
- ticketRegistrationMapper.delete(ticketRegistrationLambdaQueryWrapper);
- // 鎵归噺鍒犻櫎鍏宠仈鐨勯噰璐彴璐︾殑鏉ョエ鐧昏璁板綍
- LambdaQueryWrapper<ProductRecord> productRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
- productRecordLambdaQueryWrapper.in(ProductRecord::getPurchaseLedgerId,ids);
- productRecordMapper.delete(productRecordLambdaQueryWrapper);
- // 鎵归噺鍒犻櫎浠樻鐧昏
- LambdaQueryWrapper<PaymentRegistration> paymentRegistrationLambdaQueryWrapper = new LambdaQueryWrapper<>();
- paymentRegistrationLambdaQueryWrapper.in(PaymentRegistration::getPurchaseLedgerId, ids);
- paymentRegistrationMapper.delete(paymentRegistrationLambdaQueryWrapper);
//鎵归噺鍒犻櫎妫�楠屾爣鍑�
LambdaQueryWrapper<QualityInspect> materialInspectLambdaQueryWrapper = new LambdaQueryWrapper<>();
materialInspectLambdaQueryWrapper.in(QualityInspect::getPurchaseLedgerId, ids);
@@ -447,14 +420,6 @@
queryWrapper.eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId())
.eq(SalesLedgerProduct::getType, 2);
List<SalesLedgerProduct> productList = salesLedgerProductMapper.selectList(queryWrapper);
- productList.forEach(product -> {
- product.setFutureTickets(product.getFutureTickets() != null ? product.getFutureTickets() : product.getQuantity());
- product.setFutureTicketsAmount(product.getFutureTicketsAmount() != null ? product.getFutureTicketsAmount() : product.getTaxInclusiveTotalPrice());
- product.setTicketsNum(null);
- product.setTicketsAmount(null);
- product.setTempFutureTickets(product.getFutureTickets());
- product.setTempFutureTicketsAmount(product.getFutureTicketsAmount());
- });
resultDto.setProductData(productList);
return resultDto;
}
@@ -481,44 +446,22 @@
PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(id);
BeanUtils.copyProperties(purchaseLedger, purchaseLedgerDto);
-// TicketRegistration ticketRegistration = ticketRegistrationMapper.selectOne(new LambdaQueryWrapper<TicketRegistration>().eq(TicketRegistration::getPurchaseLedgerId, id));
-// if (ticketRegistration != null) {
-// purchaseLedgerDto.setInvoiceNumber(ticketRegistration.getInvoiceNumber());
-// purchaseLedgerDto.setInvoiceAmount(ticketRegistration.getInvoiceAmount());
-// purchaseLedgerDto.setTicketRegistrationId(ticketRegistration.getId());
-// }
return purchaseLedgerDto;
}
@Override
public IPage<PurchaseLedgerDto> selectPurchaseLedgerListPage(IPage ipage, PurchaseLedgerDto purchaseLedger) {
- IPage<PurchaseLedgerDto> purchaseLedgerDtoIPage = purchaseLedgerMapper.selectPurchaseLedgerListPage(ipage, purchaseLedger);
- purchaseLedgerDtoIPage.getRecords().forEach(purchaseLedgerDto -> {
- List<CommonFile> commonFiles = commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>().eq(CommonFile::getCommonId, purchaseLedgerDto.getId()).eq(CommonFile::getType, FileNameType.PURCHASE.getValue()));
- purchaseLedgerDto.setSalesLedgerFiles(commonFiles);
- });
- return purchaseLedgerDtoIPage;
+ return purchaseLedgerMapper.selectPurchaseLedgerListPage(ipage, purchaseLedger);
}
@Override
- public List<InvoiceRegistrationProduct> getProductBySalesNo(Long id) {
- List<InvoiceRegistrationProduct> invoiceRegistrationProducts = invoiceRegistrationProductMapper.selectList(new LambdaQueryWrapper<InvoiceRegistrationProduct>()
- .select(InvoiceRegistrationProduct::getId, InvoiceRegistrationProduct::getProductCategory, InvoiceRegistrationProduct::getSpecificationModel,
- InvoiceRegistrationProduct::getUnit, InvoiceRegistrationProduct::getQuantity)
- .eq(InvoiceRegistrationProduct::getSalesLedgerId, id));
- if (invoiceRegistrationProducts.isEmpty()) {
- return new ArrayList<>();
- }
- return invoiceRegistrationProducts;
- }
-
- @Override
- public String getPurchaseNo() {
+ public String getPurchaseNo(Date entryDate) {
+ LocalDate localDate = entryDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
// 鐢熸垚鏃ユ湡鍓嶇紑锛堜緥濡傦細CG20250405锛�
- String purchaseNo = "CG" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+ String purchaseNo = "CG" + localDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
// 鏋勫缓 Redis Key锛堟寜澶╁垎闅旓級
- String redisKey = "purchase_no:" + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
+ String redisKey = "purchase_no:" + localDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
// 鑾峰彇褰撳墠搴忓彿骞堕�掑锛堝師瀛愭搷浣滐級
Long sequence = redisTemplate.opsForValue().increment(redisKey);
@@ -616,8 +559,6 @@
salesLedgerProduct.setType(2);
// 璁$畻涓嶅惈绋庢�讳环
salesLedgerProduct.setTaxExclusiveTotalPrice(salesLedgerProduct.getTaxInclusiveTotalPrice().divide(new BigDecimal(1).add(salesLedgerProduct.getTaxRate().divide(new BigDecimal(100))), 2, RoundingMode.HALF_UP));
- salesLedgerProduct.setFutureTickets(salesLedgerProduct.getQuantity());
- salesLedgerProduct.setFutureTicketsAmount(salesLedgerProduct.getTaxExclusiveTotalPrice());
list.stream()
.filter(map -> map.get("productName").equals(salesLedgerProduct.getProductCategory()) && map.get("model").equals(salesLedgerProduct.getSpecificationModel()))
.findFirst()
@@ -628,7 +569,6 @@
salesLedgerProduct.setRegister(loginUser.getNickName());
salesLedgerProduct.setRegisterDate(LocalDateTime.now());
salesLedgerProduct.setApproveStatus(0);
- salesLedgerProduct.setPendingTicketsTotal(salesLedgerProductImportDto.getTaxInclusiveTotalPrice());
// 鏄惁璐ㄦ鍒ゆ柇
salesLedgerProduct.setIsChecked(salesLedgerProductImportDto.getIsChecked() == 1);
if(salesLedgerProductImportDto.getIsChecked() == 1){
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReportServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReportServiceImpl.java
new file mode 100644
index 0000000..676cf46
--- /dev/null
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReportServiceImpl.java
@@ -0,0 +1,32 @@
+package com.ruoyi.purchase.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.mapper.AccountStatementMapper;
+import com.ruoyi.purchase.dto.VatDto;
+import com.ruoyi.purchase.service.PurchaseReportService;
+import com.ruoyi.purchase.vo.PurchaseReportVo;
+import com.ruoyi.sales.mapper.SalesLedgerMapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class PurchaseReportServiceImpl implements PurchaseReportService {
+
+ private final SalesLedgerMapper salesLedgerMapper;
+ private final AccountStatementMapper accountStatementMapper;
+
+ @Override
+ public IPage<PurchaseReportVo> list(Page page, String customerName) {
+ return salesLedgerMapper.selectPurchaseReportVoPage(page, customerName);
+ }
+
+ @Override
+ public IPage<VatDto> listVat(Page page, String month) {
+ return accountStatementMapper.selectVatDtoPage(page, month);
+ }
+}
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java
index 9da4a11..318c36d 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java
@@ -6,12 +6,7 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.account.pojo.AccountIncome;
-import com.ruoyi.account.service.AccountIncomeService;
import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
-import com.ruoyi.common.utils.DateUtils;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.purchase.dto.PurchaseReturnOrderDto;
import com.ruoyi.purchase.dto.PurchaseReturnOrderHasAllInfoDto;
@@ -50,7 +45,6 @@
private final PurchaseReturnOrdersMapper purchaseReturnOrdersMapper;
private final PurchaseReturnOrderProductsMapper purchaseReturnOrderProductsMapper;
private final ISalesLedgerService salesLedgerService;
- private final AccountIncomeService accountIncomeService;
private final StockUtils stockUtils;
private final SalesLedgerProductMapper salesLedgerProductMapper;
private final PurchaseLedgerMapper purchaseLedgerMapper;
@@ -82,21 +76,6 @@
}else {
throw new RuntimeException("璇烽�夋嫨閫�璐у晢鍝�");
}
-
- // 瀵硅储鍔$鐞嗗彴璐︽坊鍔犱竴绗旇繘璐︽敹鍏�.
- AccountIncome accountIncome = new AccountIncome();
- LoginUser loginUser = SecurityUtils.getLoginUser();
- accountIncome.setInputUser(loginUser.getUsername());
- accountIncome.setIncomeMoney(purchaseReturnOrderDto.getTotalAmount());
- accountIncome.setIncomeDate(DateUtils.toDate(purchaseReturnOrderDto.getPreparedAt()));
- accountIncome.setInputTime(DateUtils.toDate(purchaseReturnOrderDto.getPreparedAt()));
- accountIncome.setBusinessId(purchaseReturnOrderDto.getId());
- accountIncome.setBusinessType(1);
- accountIncome.setIncomeType("4");
- accountIncome.setCustomerName(purchaseReturnOrderDto.getSupplierName());
- accountIncome.setIncomeDescribed(purchaseReturnOrderDto.getRemark());
- accountIncome.setIncomeMethod(String.valueOf(purchaseReturnOrderDto.getIncomeType()));
- accountIncomeService.save(accountIncome);
return true;
}
@@ -123,12 +102,6 @@
purchaseReturnOrderProducts.stream().forEach(purchaseReturnOrderProducts1 -> {
stockUtils.deleteStockOutRecord(purchaseReturnOrderProducts1.getId(),StockOutQualifiedRecordTypeEnum.PURCHASE_RETURN_STOCK_OUT.getCode());
});
- // 璐㈠姟
- LambdaUpdateWrapper<AccountIncome> updateWrapperAccountIncome = new LambdaUpdateWrapper<>();
- updateWrapperAccountIncome.eq(AccountIncome::getBusinessId, id);
- updateWrapperAccountIncome.eq(AccountIncome::getBusinessType, 1);
- updateWrapperAccountIncome.eq(AccountIncome::getIncomeType, 4);
- accountIncomeService.remove(updateWrapperAccountIncome);
}
@Override
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/TicketRegistrationServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/TicketRegistrationServiceImpl.java
deleted file mode 100644
index a98d924..0000000
--- a/src/main/java/com/ruoyi/purchase/service/impl/TicketRegistrationServiceImpl.java
+++ /dev/null
@@ -1,464 +0,0 @@
-package com.ruoyi.purchase.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.enums.FileNameType;
-import com.ruoyi.common.enums.SalesLedgerType;
-import com.ruoyi.common.exception.base.BaseException;
-import com.ruoyi.common.utils.DateUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.bean.BeanUtils;
-import com.ruoyi.other.mapper.TempFileMapper;
-import com.ruoyi.purchase.dto.PaymentRegistrationDto;
-import com.ruoyi.purchase.dto.PurchaseLedgerDto;
-import com.ruoyi.purchase.dto.TicketRegistrationDto;
-import com.ruoyi.purchase.mapper.PaymentRegistrationMapper;
-import com.ruoyi.purchase.mapper.ProductRecordMapper;
-import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
-import com.ruoyi.purchase.mapper.TicketRegistrationMapper;
-import com.ruoyi.purchase.pojo.PaymentRegistration;
-import com.ruoyi.purchase.pojo.ProductRecord;
-import com.ruoyi.purchase.pojo.PurchaseLedger;
-import com.ruoyi.purchase.pojo.TicketRegistration;
-import com.ruoyi.purchase.service.ITicketRegistrationService;
-import com.ruoyi.sales.mapper.CommonFileMapper;
-import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
-import com.ruoyi.sales.pojo.CommonFile;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import com.ruoyi.sales.service.ISalesLedgerProductService;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * 鏉ョエ鐧昏Service涓氬姟灞傚鐞�
- *
- * @author ruoyi
- * @date 2025-05-13
- */
-@Service
-@RequiredArgsConstructor
-@Slf4j
-public class TicketRegistrationServiceImpl extends ServiceImpl<TicketRegistrationMapper, TicketRegistration> implements ITicketRegistrationService {
-
- private final TicketRegistrationMapper ticketRegistrationMapper;
-
- private final PurchaseLedgerMapper purchaseLedgerMapper;
-
- private final SalesLedgerProductMapper salesLedgerProductMapper;
-
- private final CommonFileMapper commonFileMapper;
-
- private final TempFileMapper tempFileMapper;
-
- private final ProductRecordMapper productRecordMapper;
-
- private final ISalesLedgerProductService salesLedgerProductService;
-
- private final PaymentRegistrationMapper paymentRegistrationMapper;
-
-
- @Override
- public List<TicketRegistration> selectTicketRegistrationList(TicketRegistration ticketRegistration) {
- LambdaQueryWrapper<TicketRegistration> queryWrapper = new LambdaQueryWrapper<>();
- if (StringUtils.isNotBlank(ticketRegistration.getPurchaseContractNumber())) {
- queryWrapper.like(TicketRegistration::getPurchaseContractNumber, ticketRegistration.getPurchaseContractNumber())
- .like(TicketRegistration::getSupplierName, ticketRegistration.getSupplierName())
- .eq(TicketRegistration::getIssueDate, ticketRegistration.getIssueDate());
- }
- List<TicketRegistration> ticketRegistrationList = ticketRegistrationMapper.selectList(queryWrapper);
- // 璁$畻宸蹭粯娆鹃噾棰�
- if (CollectionUtils.isNotEmpty(ticketRegistrationList)) {
- List<Long> ids = ticketRegistrationList.stream().map(TicketRegistration::getId).collect(Collectors.toList());
- List<PaymentRegistrationDto> paymentRegistrationDtoList = paymentRegistrationMapper.countPaymentTotalByTicketRegId(ids);
- for (TicketRegistration registration : ticketRegistrationList) {
- BigDecimal paymentAmountTotal = BigDecimal.ZERO;
- for (PaymentRegistrationDto paymentRegistrationDto : paymentRegistrationDtoList) {
- if (registration.getId().equals(paymentRegistrationDto.getTicketRegistrationId())) {
- paymentAmountTotal = paymentRegistrationDto.getPaymentAmountTotal();
- break;
- }
- }
- BigDecimal invoiceAmount = registration.getInvoiceAmount();
- BigDecimal subtractAmount = invoiceAmount.subtract(paymentAmountTotal);
- registration.setPaymentAmountTotal(paymentAmountTotal);
- registration.setUnPaymentAmountTotal(subtractAmount);
- }
- }
-
- return ticketRegistrationList;
- }
-
- @Override
- @Transactional(rollbackFor = Exception.class)
- public int addOrUpdateRegistration(TicketRegistrationDto ticketRegistrationDto) throws IOException {
- // 1. 鏌ヨ閲囪喘鍙拌处璁板綍
- PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(ticketRegistrationDto.getPurchaseLedgerId());
- if (purchaseLedger == null) {
- // 澶勭悊閲囪喘鍙拌处涓嶅瓨鍦ㄧ殑鎯呭喌锛屼緥濡傛姏鍑哄紓甯告垨杩斿洖閿欒
- throw new IllegalArgumentException("閲囪喘鍙拌处璁板綍涓嶅瓨鍦紝ID: " + ticketRegistrationDto.getPurchaseLedgerId());
- }
-
-
-
- // 3. 鍒涘缓鎴栨洿鏂扮エ鎹櫥璁板疄浣�
- TicketRegistration ticketRegistration = new TicketRegistration();
- BeanUtils.copyProperties(ticketRegistrationDto, ticketRegistration);
- ticketRegistration.setPurchaseContractNumber(purchaseLedger.getPurchaseContractNumber());
- ticketRegistration.setTenantId(purchaseLedger.getTenantId());
- ticketRegistration.setIssueDate(ticketRegistrationDto.getEntryDate());
- ticketRegistration.setContractAmount(purchaseLedger.getContractAmount());
- ticketRegistration.setSalesLedgerId(purchaseLedger.getSalesLedgerId());
- ticketRegistration.setEnterDate(ticketRegistrationDto.getEnterDate());
-
- // 4. 澶勭悊瀛愯〃鏁版嵁
- List<SalesLedgerProduct> productData = ticketRegistrationDto.getProductData();
- if (CollectionUtils.isNotEmpty(productData)) {
- handleSalesLedgerProducts(purchaseLedger.getId(), productData, 2);
- }
-
- // 5. 鎵ц鎻掑叆鎴栨洿鏂版搷浣�
- int rowsAffected = ticketRegistrationMapper.insert(ticketRegistration);
-
- // 6. 澧炲姞閲囪喘鍙拌处浜у搧寮�绁ㄨ褰�
- List<SalesLedgerProduct> salesLedgerProducts = ticketRegistrationDto.getProductData();
- if (CollectionUtils.isNotEmpty(salesLedgerProducts)) {
- int insert = 0 ;
- for (SalesLedgerProduct salesLedgerProduct : salesLedgerProducts) {
- //鎺掗櫎鎺夊紑绁ㄤ负0鐨勬暟鎹�
- if (salesLedgerProduct.getTicketsNum() != null && salesLedgerProduct.getTicketsNum().compareTo(BigDecimal.ZERO) > 0) {
- ProductRecord productRecord = new ProductRecord();
-
- productRecord.setTicketRegistrationId(ticketRegistration.getId());
- productRecord.setPurchaseLedgerId(ticketRegistrationDto.getPurchaseLedgerId());
- productRecord.setCreatedAt(DateUtils.getNowDate());
- BeanUtils.copyProperties(salesLedgerProduct, productRecord);
- //鍚屾鏇存柊鍏朵粬鍓╀綑鏁伴噺鍜岄噾棰�
- productRecordMapper.update(
- null,
- new LambdaUpdateWrapper<ProductRecord>()
- .eq(ProductRecord::getPurchaseLedgerId, ticketRegistrationDto.getPurchaseLedgerId())
- .set(ProductRecord::getFutureTickets, salesLedgerProduct.getFutureTickets())
- .set(ProductRecord::getFutureTicketsAmount, salesLedgerProduct.getFutureTicketsAmount())
- );
- productRecord.setSaleLedgerProjectId(salesLedgerProduct.getId());
- productRecord.setId(null);
- productRecord.setType("2");
- insert += productRecordMapper.insert(productRecord);
- }
- }
- if (insert <= 0) {
- throw new RuntimeException("浜у搧寮�绁ㄦ暟閮戒负0锛岃妫�鏌�");
- }
- }
- return rowsAffected;
- }
-
-
- @Override
- @Transactional(rollbackFor = Exception.class)
- public int delRegistration(Long[] ids) {
-
- // 鏌ヨ瑕佸垹闄ょ殑浜у搧鏉ョエ璁板綍
- LambdaQueryWrapper<ProductRecord> productWrapper = new LambdaQueryWrapper<>();
- productWrapper.in(ProductRecord::getId, Arrays.asList(ids));
- List<ProductRecord> productRecords = productRecordMapper.selectList(productWrapper);
-
- if (CollectionUtils.isEmpty(productRecords)) {
- return 0;
- }
-
- // 鏀堕泦鍏宠仈ID
- Set<Long> ticketRegistrationIds = productRecords.stream()
- .map(ProductRecord::getTicketRegistrationId)
- .collect(Collectors.toSet());
-
- Set<Long> salesLedgerProductIds = productRecords.stream()
- .map(ProductRecord::getSaleLedgerProjectId)
- .collect(Collectors.toSet());
-
- // 鏌ヨ鏉ョエ鐧昏
- List<TicketRegistration> ticketRegistrations =
- ticketRegistrationMapper.selectBatchIds(ticketRegistrationIds);
-
- // 澶勭悊鏉ョエ鐧昏閲戦銆佷粯娆炬祦姘�
- for (TicketRegistration ticket : ticketRegistrations) {
-
- // 璇ユ潵绁ㄧ櫥璁颁笅鎵�鏈変骇鍝佽褰�
- List<ProductRecord> recordsOfTicket = productRecords.stream()
- .filter(r -> r.getTicketRegistrationId().equals(ticket.getId()))
- .collect(Collectors.toList());
-
- // 璁$畻瑕佸洖閫�鐨勯噾棰�
- BigDecimal rollbackAmount = recordsOfTicket.stream()
- .map(ProductRecord::getTicketsAmount)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
-
- BigDecimal remain = ticket.getInvoiceAmount().subtract(rollbackAmount);
-
- if (remain.compareTo(BigDecimal.ZERO) <= 0) {
- // 鍒犻櫎鏉ョエ鐧昏
- ticketRegistrationMapper.deleteById(ticket.getId());
- // 鍒犻櫎浠樻娴佹按
- paymentRegistrationMapper.delete(
- new LambdaQueryWrapper<PaymentRegistration>()
- .eq(PaymentRegistration::getTicketRegistrationId, ticket.getId())
- );
- } else {
- ticket.setInvoiceAmount(remain);
- ticketRegistrationMapper.updateById(ticket);
- }
- }
-
- // 鍥為��閿�鍞彴璐︿骇鍝佺殑鏈潵绁�
- for (ProductRecord record : productRecords) {
-
- LambdaQueryWrapper<SalesLedgerProduct> wrapper = new LambdaQueryWrapper<>();
- wrapper.eq(SalesLedgerProduct::getId, record.getSaleLedgerProjectId())
- .eq(SalesLedgerProduct::getType, 2);
-
- SalesLedgerProduct product = salesLedgerProductMapper.selectOne(wrapper);
- if (product != null) {
- product.setFutureTickets(
- product.getFutureTickets().add(record.getTicketsNum())
- );
- product.setFutureTicketsAmount(
- product.getFutureTicketsAmount().add(record.getTicketsAmount())
- );
- salesLedgerProductMapper.updateById(product);
- }
- }
-
- // 鍒犻櫎浜у搧鏉ョエ璁板綍
- productRecordMapper.delete(productWrapper);
-
- // 閲嶆柊璁$畻 currentInvoiceAmount
- for (Long productId : salesLedgerProductIds) {
- refreshCurrentInvoiceAmount(productId);
- }
-
- return 1;
- }
-
- private void refreshCurrentInvoiceAmount(Long salesLedgerProductId) {
-
- // 鏌ヨ璇ヤ骇鍝佹渶鏂颁竴鏉℃潵绁ㄨ褰�
- LambdaQueryWrapper<ProductRecord> wrapper = new LambdaQueryWrapper<>();
- wrapper.eq(ProductRecord::getSaleLedgerProjectId, salesLedgerProductId)
- .orderByDesc(ProductRecord::getCreatedAt)
- .last("limit 1");
-
- ProductRecord latestRecord = productRecordMapper.selectOne(wrapper);
-
- SalesLedgerProduct product =
- salesLedgerProductMapper.selectById(salesLedgerProductId);
-
- if (product == null) {
- return;
- }
-
- if (latestRecord == null) {
- // 娌℃湁浠讳綍鏉ョエ璁板綍
- product.setTicketsAmount(BigDecimal.ZERO);
- } else {
- // 姘歌繙鍙栨渶鏂颁竴鏉�
- product.setTicketsAmount(latestRecord.getTicketsAmount());
- }
-
- salesLedgerProductMapper.updateById(product);
- }
-
-
- @Override
- public TicketRegistrationDto getRegistrationById(TicketRegistrationDto ticketRegistrationDto) {
- TicketRegistration ticketRegistration = ticketRegistrationMapper.selectById(ticketRegistrationDto.getId());
- LambdaQueryWrapper<PurchaseLedger> purchaseQueryWrapper = new LambdaQueryWrapper<>();
- purchaseQueryWrapper.eq(PurchaseLedger::getId, ticketRegistration.getPurchaseLedgerId());
- PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectOne(purchaseQueryWrapper);
- if (ticketRegistration == null) {
- throw new BaseException("閲囪喘鍙拌处涓嶅瓨鍦�");
- }
- // 鍒涘缓骞跺~鍏匘TO
- TicketRegistrationDto resultDto = new TicketRegistrationDto();
- BeanUtils.copyProperties(ticketRegistration, resultDto);
-
- // 鏌ヨ骞惰缃叧鑱斾骇鍝�
- LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId())
- .eq(SalesLedgerProduct::getType, 2);
- List<SalesLedgerProduct> productList = salesLedgerProductMapper.selectList(queryWrapper);
- resultDto.setProductData(productList);
- return resultDto;
- }
-
- @Override
- public List getTicketNo(TicketRegistrationDto ticketRegistrationDto) {
- LambdaQueryWrapper<TicketRegistration> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.select(TicketRegistration::getId, TicketRegistration::getInvoiceNumber, TicketRegistration::getInvoiceAmount)
- .eq(TicketRegistration::getPurchaseLedgerId, ticketRegistrationDto.getId());
- List<Map<String, Object>> result = ticketRegistrationMapper.selectMaps(queryWrapper);
- // 灏嗕笅鍒掔嚎鍛藉悕杞崲涓洪┘宄板懡鍚�
- return result.stream().map(map -> map.entrySet().stream()
- .collect(Collectors.toMap(
- entry -> underlineToCamel(entry.getKey()),
- Map.Entry::getValue))
- ).collect(Collectors.toList());
- }
-
- @Override
- public IPage<TicketRegistration> selectTicketRegistrationListPage(Page page, TicketRegistration ticketRegistration) {
- LambdaQueryWrapper<TicketRegistration> queryWrapper = new LambdaQueryWrapper<>();
- if (StringUtils.isNotBlank(ticketRegistration.getSupplierNameOrContractNo())) {
- queryWrapper.and(wrapper -> wrapper
- .like(TicketRegistration::getPurchaseContractNumber, ticketRegistration.getSupplierNameOrContractNo())
- .or()
- .like(TicketRegistration::getSupplierName, ticketRegistration.getSupplierNameOrContractNo())
- .or()
- .like(TicketRegistration::getSalesContractNo, ticketRegistration.getSupplierNameOrContractNo()));
- }
- if (!ObjectUtils.isEmpty(ticketRegistration.getIssueDateStart()) && !ObjectUtils.isEmpty(ticketRegistration.getIssueDateEnd())) {
- queryWrapper.between(TicketRegistration::getIssueDate, LocalDate.parse(ticketRegistration.getIssueDateStart(), DateTimeFormatter.ofPattern("yyyy-MM-dd")), LocalDate.parse(ticketRegistration.getIssueDateEnd(), DateTimeFormatter.ofPattern("yyyy-MM-dd")));
- }
- IPage<TicketRegistration> ticketRegistrationIPage = ticketRegistrationMapper.selectPage(page, queryWrapper);
- // 璁$畻宸蹭粯娆鹃噾棰�
- if (CollectionUtils.isNotEmpty(ticketRegistrationIPage.getRecords())) {
- List<Long> ids = ticketRegistrationIPage.getRecords().stream().map(TicketRegistration::getId).collect(Collectors.toList());
- List<PaymentRegistrationDto> paymentRegistrationDtoList = paymentRegistrationMapper.countPaymentTotalByTicketRegId(ids);
- for (TicketRegistration registration : ticketRegistrationIPage.getRecords()) {
- BigDecimal paymentAmountTotal = BigDecimal.ZERO;
- for (PaymentRegistrationDto paymentRegistrationDto : paymentRegistrationDtoList) {
- if (registration.getId().equals(paymentRegistrationDto.getTicketRegistrationId())) {
- paymentAmountTotal = paymentRegistrationDto.getPaymentAmountTotal();
- break;
- }
- }
- BigDecimal invoiceAmount = registration.getInvoiceAmount();
- BigDecimal subtractAmount = invoiceAmount.subtract(paymentAmountTotal);
- registration.setPaymentAmountTotal(paymentAmountTotal);
- registration.setUnPaymentAmountTotal(subtractAmount);
- }
- }
- if (!ObjectUtils.isEmpty(ticketRegistration.getStatus())) {
-
- if (ticketRegistration.getStatus()) {
- ticketRegistrationIPage.getRecords().removeIf(receiptPaymentDto1 -> new BigDecimal("0.00").equals(receiptPaymentDto1.getUnPaymentAmountTotal()));
- ticketRegistrationIPage.setTotal(ticketRegistrationIPage.getRecords().size());
- }
- }
- ticketRegistrationIPage.getRecords().forEach(item -> {
- // 宸蹭粯娆鹃噾棰� == 寰呬粯娆鹃噾棰�
- item.setStatusName(item.getPaymentAmountTotal().compareTo(item.getInvoiceAmount()) == 0 ? "宸插畬鎴愪粯娆�" : "鏈畬鎴愪粯娆�");
- });
- return ticketRegistrationIPage;
- }
-
- @Override
- public PurchaseLedgerDto getPuargeById(Long id) {
- PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(id);
- PurchaseLedgerDto purchaseLedgerDto = new PurchaseLedgerDto();
- BeanUtils.copyProperties(purchaseLedger, purchaseLedgerDto);
- SalesLedgerProduct salesLedgerProduct = new SalesLedgerProduct();
- salesLedgerProduct.setSalesLedgerId(id);
- salesLedgerProduct.setType(SalesLedgerType.SALES_LEDGER_TYPE_SALES_LEDGER.getCode());
- List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductService.selectSalesLedgerProductList(salesLedgerProduct);
- purchaseLedgerDto.setProductData(salesLedgerProducts);
- List<CommonFile> commonFiles = commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>()
- .eq(CommonFile::getType, FileNameType.PURCHASELEDGER.getValue())
- .eq(CommonFile::getCommonId, id));
- purchaseLedgerDto.setSalesLedgerFiles(commonFiles);
- return purchaseLedgerDto;
- }
-
- @Override
- public List<PaymentRegistrationDto> getPaymentRegistrationDtoById(Long id) {
- List<PaymentRegistrationDto> paymentRegistrationDtos =purchaseLedgerMapper.getPaymentRegistrationDtoById(id);
- return paymentRegistrationDtos;
- }
-
- private void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, Integer type) {
- if (products == null || products.isEmpty()) {
- return;
- }
-
- // 杩囨护鍑烘湁 ID 鐨勮褰曪紙鍗抽渶瑕佹洿鏂扮殑璁板綍锛�
- List<SalesLedgerProduct> updateList = products.stream()
- .filter(p -> p.getId() != null)
- .peek(p -> {
- p.setSalesLedgerId(salesLedgerId);
- p.setType(type);
- })
- .collect(Collectors.toList());
-
- // 鎵归噺鏇存柊锛堥渶瑕� MyBatis 鎻愪緵鎵归噺鏇存柊鏂规硶锛�
- if (!updateList.isEmpty()) {
- updateList.forEach(product -> {
- // 闈炵┖鏍¢獙锛屼换涓�瀛楁涓虹┖鍒欐姏鍑哄紓甯�
- if (product.getQuantity() == null) {
- throw new BaseException("鏁伴噺涓嶈兘涓虹┖");
- }
- if (product.getTicketsNum() == null) {
- throw new BaseException("宸插紑绁ㄦ暟閲忎笉鑳戒负绌�");
- }
- if (product.getTaxInclusiveTotalPrice() == null) {
- throw new BaseException("鍚◣鎬讳环涓嶈兘涓虹┖");
- }
- if (product.getTicketsAmount() == null) {
- throw new BaseException("鏈鏉ョエ閲戦(鍏�)涓嶈兘涓虹┖");
- }
-
- // 璁$畻 futureTickets锛堢洿鎺ヤ娇鐢� BigDecimal 璁$畻锛岄伩鍏嶇簿搴︿涪澶憋級
-// product.setFutureTickets(
-// product.getQuantity()
-// .subtract(product.getTicketsNum())
-// );
-
-
- // 璁$畻 futureTicketsAmount
-// product.setFutureTicketsAmount(
-// product.getTaxInclusiveTotalPrice()
-// .subtract(product.getTicketsAmount())
-// );
- product.setType(type);
- salesLedgerProductMapper.updateById(product);
- });
- }
- }
-
- /**
- * 涓嬪垝绾垮懡鍚嶈浆椹煎嘲鍛藉悕
- */
- private String underlineToCamel(String param) {
- if (param == null || "".equals(param.trim())) {
- return "";
- }
- int len = param.length();
- StringBuilder sb = new StringBuilder(len);
- for (int i = 0; i < len; i++) {
- char c = param.charAt(i);
- if (c == '_') {
- if (++i < len) {
- sb.append(Character.toUpperCase(param.charAt(i)));
- }
- } else {
- sb.append(Character.toLowerCase(c));
- }
- }
- return sb.toString();
- }
-}
diff --git a/src/main/java/com/ruoyi/purchase/vo/PurchaseReportVo.java b/src/main/java/com/ruoyi/purchase/vo/PurchaseReportVo.java
new file mode 100644
index 0000000..afe7f98
--- /dev/null
+++ b/src/main/java/com/ruoyi/purchase/vo/PurchaseReportVo.java
@@ -0,0 +1,44 @@
+package com.ruoyi.purchase.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+@Schema(name = "PurchaseReportVo", description = "绠$悊椹鹃┒鑸�--椤圭洰鍒╂鼎鍙傛暟")
+@ExcelIgnoreUnannotated
+public class PurchaseReportVo {
+
+ @Schema(description = "閿�鍞悎鍚屽彿")
+ @Excel(name = "閿�鍞悎鍚屽彿")
+ private String customerContractNo;
+
+ @Schema(description = "瀹㈡埛鍚嶇О")
+ @Excel(name = "瀹㈡埛鍚嶇О")
+ private String customerName;
+
+ @Schema(description = "椤圭洰鍚嶇О")
+ @Excel(name = "椤圭洰鍚嶇О")
+ private String projectName;
+
+ @Excel(name = "鍚堝悓閲戦")
+ @Schema(description = "鍚堝悓閲戦")
+ private BigDecimal contractAmount;
+
+ @Excel(name = "閲囪喘閲戦")
+ @Schema(description = "閲囪喘閲戦")
+ private BigDecimal purchaseAmount;
+
+ @Schema(description = "鍒╂鼎")
+ @Excel(name = "鍒╂鼎")
+ private BigDecimal balance;
+
+ @Schema(description = "鍒╂鼎鐜�")
+ @Excel(name = "鍒╂鼎鐜�")
+ private BigDecimal balanceRatio;
+
+
+}
diff --git a/src/main/java/com/ruoyi/purchase/vo/SupplierTransactionsDetailsVo.java b/src/main/java/com/ruoyi/purchase/vo/SupplierTransactionsDetailsVo.java
new file mode 100644
index 0000000..3533e6e
--- /dev/null
+++ b/src/main/java/com/ruoyi/purchase/vo/SupplierTransactionsDetailsVo.java
@@ -0,0 +1,33 @@
+package com.ruoyi.purchase.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@Schema(name = "SupplierTransactionsDetailsVo", description = "閲囪喘绠$悊--渚涘簲鍟嗗線鏉ユ槑缁�(杩斿洖)")
+public class SupplierTransactionsDetailsVo {
+
+ @Schema(description = "閲囪喘鍗旾D")
+ private Long purchaseLedgerId;
+
+ @Schema(description = "閲囪喘鍚堝悓鍙�")
+ private String purchaseContractNumber;
+
+ @Schema(description = "閲囪喘鍚堝悓绛捐鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ private Date executionDate;
+
+ @Schema(description = "鍚堝悓閲戦")
+ private BigDecimal contractAmount;
+
+ @Schema(description = "浠樻閲戦")
+ private BigDecimal paymentAmount;
+
+ @Schema(description = "搴斾粯閲戦")
+ private BigDecimal payableAmount;
+
+}
diff --git a/src/main/java/com/ruoyi/purchase/vo/SupplierTransactionsVo.java b/src/main/java/com/ruoyi/purchase/vo/SupplierTransactionsVo.java
new file mode 100644
index 0000000..35cefc0
--- /dev/null
+++ b/src/main/java/com/ruoyi/purchase/vo/SupplierTransactionsVo.java
@@ -0,0 +1,30 @@
+package com.ruoyi.purchase.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+@Schema(name = "SupplierTransactionsVo", description = "閲囪喘绠$悊--渚涘簲鍟嗗線鏉�(杩斿洖)")
+public class SupplierTransactionsVo {
+
+ @Schema(description = "渚涘簲鍟咺D")
+ private Long supplierId;
+
+ @Schema(description = "渚涘簲鍟嗗悕绉�")
+ private String supplierName;
+
+ @Schema(description = "鍚堝悓鎬婚噾棰�")
+ //璇ヤ緵搴斿晢閲囪喘鍚堝悓绱閲戦
+ private BigDecimal contractAmounts;
+
+ @Schema(description = "浠樻閲戦")
+ //璇ヤ緵搴斿晢閲囪喘浠樻绱閲戦
+ private BigDecimal paymentAmount;
+
+ @Schema(description = "搴斾粯閲戦")
+ //璇ヤ緵搴斿晢閲囪喘搴斾粯绱閲戦=璐㈠姟(鍏ュ簱-閫�璐�)
+ private BigDecimal payableAmount;
+
+}
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java b/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java
index fcaceb6..cc295d5 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java
@@ -2,7 +2,9 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
import com.ruoyi.quality.dto.QualityInspectDto;
import com.ruoyi.quality.pojo.QualityInspect;
import com.ruoyi.quality.pojo.QualityInspectFile;
@@ -10,6 +12,7 @@
import com.ruoyi.quality.service.IQualityInspectFileService;
import com.ruoyi.quality.service.IQualityInspectParamService;
import com.ruoyi.quality.service.IQualityInspectService;
+import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import org.springframework.util.CollectionUtils;
@@ -37,8 +40,10 @@
* @return
*/
@PostMapping("/add")
- public AjaxResult add(@RequestBody QualityInspectDto qualityInspectDto) {
- return AjaxResult.success(qualityInspectService.add(qualityInspectDto));
+ @Operation(summary = "鏂板妫�楠�")
+ @Log(title = "鏂板妫�楠�", businessType = BusinessType.INSERT)
+ public R<?> add(@RequestBody QualityInspectDto qualityInspectDto) {
+ return R.ok(qualityInspectService.add(qualityInspectDto));
}
/**
@@ -48,9 +53,11 @@
* @return
*/
@DeleteMapping("/del")
- public AjaxResult delQualityInspect(@RequestBody List<Integer> ids) {
+ @Operation(summary = "鍒犻櫎妫�楠�")
+ @Log(title = "鍒犻櫎妫�楠�", businessType = BusinessType.DELETE)
+ public R<?> delQualityInspect(@RequestBody List<Integer> ids) {
if (CollectionUtils.isEmpty(ids)) {
- return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+ return R.fail("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
}
//濡傛灉宸茬粡鎻愪氦灏变笉鍏佽鍒犻櫎
List<QualityInspect> qualityInspects = qualityInspectService.listByIds(ids);
@@ -66,7 +73,7 @@
qualityInspectFileService.remove(Wrappers.<QualityInspectFile>lambdaQuery()
.in(QualityInspectFile::getInspectId, ids));
//鍒犻櫎妫�楠屽崟
- return AjaxResult.success(qualityInspectService.removeBatchByIds(ids));
+ return R.ok(qualityInspectService.removeBatchByIds(ids));
}
/**
@@ -76,8 +83,10 @@
* @return
*/
@GetMapping("/{id}")
- public AjaxResult QualityInspectDetail(@PathVariable("id") Integer id) {
- return AjaxResult.success(qualityInspectService.getDetailById(id));
+ @Operation(summary = "妫�楠岃鎯�")
+ @Log(title = "妫�楠岃鎯�", businessType = BusinessType.OTHER)
+ public R<?> QualityInspectDetail(@PathVariable("id") Integer id) {
+ return R.ok(qualityInspectService.getDetailById(id));
}
/**
@@ -87,8 +96,10 @@
* @return
*/
@PostMapping("/update")
- public AjaxResult update(@RequestBody QualityInspectDto qualityInspectDto) {
- return AjaxResult.success(qualityInspectService.updateQualityInspect(qualityInspectDto));
+ @Operation(summary = "淇敼妫�楠�")
+ @Log(title = "淇敼妫�楠�", businessType = BusinessType.UPDATE)
+ public R<?> update(@RequestBody QualityInspectDto qualityInspectDto) {
+ return R.ok(qualityInspectService.updateQualityInspect(qualityInspectDto));
}
/**
@@ -99,8 +110,10 @@
* @return
*/
@GetMapping("/listPage")
- public AjaxResult qualityInspectListPage(Page page, QualityInspectDto qualityInspect) {
- return AjaxResult.success(qualityInspectService.qualityInspectListPage(page, qualityInspect));
+ @Operation(summary = "鍒嗛〉鏌ヨ妫�楠�")
+ @Log(title = "鍒嗛〉鏌ヨ妫�楠�", businessType = BusinessType.OTHER)
+ public R<?> qualityInspectListPage(Page page, QualityInspectDto qualityInspect) {
+ return R.ok(qualityInspectService.qualityInspectListPage(page, qualityInspect));
}
/**
@@ -110,6 +123,8 @@
* @param qualityInspect
*/
@PostMapping("/export")
+ @Operation(summary = "瀵煎嚭妫�楠�")
+ @Log(title = "瀵煎嚭妫�楠�", businessType = BusinessType.EXPORT)
public void qualityInspectExport(HttpServletResponse response, QualityInspect qualityInspect) {
qualityInspectService.qualityInspectExport(response, qualityInspect);
}
@@ -121,8 +136,10 @@
* @return
*/
@PostMapping("/submit")
- public AjaxResult submit(@RequestBody QualityInspect qualityInspect) {
- return AjaxResult.success(qualityInspectService.submit(qualityInspect));
+ @Operation(summary = "鎻愪氦妫�楠�")
+ @Log(title = "鎻愪氦妫�楠�", businessType = BusinessType.OTHER)
+ public R<?> submit(@RequestBody QualityInspect qualityInspect) {
+ return R.ok(qualityInspectService.submit(qualityInspect));
}
/**
@@ -132,6 +149,8 @@
* @param qualityInspect
*/
@PostMapping("/down")
+ @Operation(summary = "涓嬭浇妫�楠�")
+ @Log(title = "涓嬭浇妫�楠�", businessType = BusinessType.OTHER)
public void down(HttpServletResponse response, @RequestBody QualityInspect qualityInspect) {
qualityInspectService.down(response, qualityInspect);
}
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityInspectParamController.java b/src/main/java/com/ruoyi/quality/controller/QualityInspectParamController.java
index 263b201..48fc093 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityInspectParamController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityInspectParamController.java
@@ -2,13 +2,16 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
import com.ruoyi.quality.pojo.QualityInspect;
import com.ruoyi.quality.pojo.QualityInspectFile;
import com.ruoyi.quality.pojo.QualityInspectParam;
import com.ruoyi.quality.service.IQualityInspectFileService;
import com.ruoyi.quality.service.IQualityInspectParamService;
import com.ruoyi.quality.service.IQualityInspectService;
+import io.swagger.v3.oas.annotations.Operation;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
@@ -32,8 +35,10 @@
* @return
*/
@GetMapping("/{inspectId}")
- public AjaxResult QualityInspectParamDetail(@PathVariable("inspectId") Integer inspectId) {
- return AjaxResult.success(qualityInspectParamService.qualityInspectParamDetail(inspectId));
+ @Operation(summary = "妫�楠屽弬鏁伴」璇︽儏")
+ @Log(title = "妫�楠屽弬鏁伴」璇︽儏", businessType = BusinessType.OTHER)
+ public R<?> QualityInspectParamDetail(@PathVariable("inspectId") Integer inspectId) {
+ return R.ok(qualityInspectParamService.qualityInspectParamDetail(inspectId));
}
@@ -43,8 +48,10 @@
* @return
*/
@PostMapping("/update")
- public AjaxResult update(@RequestBody List<QualityInspectParam> qualityInspectParams) {
- return AjaxResult.success(qualityInspectParamService.updateBatchById(qualityInspectParams));
+ @Operation(summary = "淇敼妫�楠屽弬鏁伴」")
+ @Log(title = "淇敼妫�楠屽弬鏁伴」", businessType = BusinessType.UPDATE)
+ public R<?> update(@RequestBody List<QualityInspectParam> qualityInspectParams) {
+ return R.ok(qualityInspectParamService.updateBatchById(qualityInspectParams));
}
/**
@@ -53,11 +60,13 @@
* @return
*/
@DeleteMapping("/del")
- public AjaxResult delQualityUnqualified(@RequestBody List<Integer> ids) {
+ @Operation(summary = "鍒犻櫎妫�楠屽弬鏁伴」")
+ @Log(title = "鍒犻櫎妫�楠屽弬鏁伴」", businessType = BusinessType.DELETE)
+ public R<?> delQualityUnqualified(@RequestBody List<Integer> ids) {
if(CollectionUtils.isEmpty(ids)){
- return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+ return R.fail("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
}
- return AjaxResult.success(qualityInspectParamService.removeBatchByIds(ids));
+ return R.ok(qualityInspectParamService.removeBatchByIds(ids));
}
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityReportController.java b/src/main/java/com/ruoyi/quality/controller/QualityReportController.java
index 4d005b0..370e8f0 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityReportController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityReportController.java
@@ -1,6 +1,8 @@
package com.ruoyi.quality.controller;
-import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
import com.ruoyi.quality.service.QualityReportService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -30,8 +32,9 @@
*/
@Operation(summary = "鑾峰彇妫�楠岀粺璁℃暟鎹�")
@GetMapping("/getInspectStatistics")
- public AjaxResult getInspectStatistics() {
- return AjaxResult.success(qualityReportService.getInspectStatistics());
+ @Log(title = "鑾峰彇妫�楠岀粺璁℃暟鎹�", businessType = BusinessType.OTHER)
+ public R<?> getInspectStatistics() {
+ return R.ok(qualityReportService.getInspectStatistics());
}
/**
@@ -39,8 +42,9 @@
*/
@Operation(summary = "鑾峰彇鍚堟牸鐜囩粺璁℃暟鎹�")
@GetMapping("/getPassRateStatistics")
- public AjaxResult getPassRateStatistics() {
- return AjaxResult.success(qualityReportService.getPassRateStatistics());
+ @Log(title = "鑾峰彇鍚堟牸鐜囩粺璁℃暟鎹�", businessType = BusinessType.OTHER)
+ public R<?> getPassRateStatistics() {
+ return R.ok(qualityReportService.getPassRateStatistics());
}
/**
@@ -48,8 +52,9 @@
*/
@Operation(summary = "鑾峰彇鏈堝害鍚堟牸鐜囩粺璁℃暟鎹�")
@GetMapping("/getMonthlyPassRateStatistics")
- public AjaxResult getMonthlyPassRateStatistics(@RequestParam("year") String year) {
- return AjaxResult.success(qualityReportService.getMonthlyPassRateStatistics(year));
+ @Log(title = "鑾峰彇鏈堝害鍚堟牸鐜囩粺璁℃暟鎹�", businessType = BusinessType.OTHER)
+ public R<?> getMonthlyPassRateStatistics(@RequestParam("year") String year) {
+ return R.ok(qualityReportService.getMonthlyPassRateStatistics(year));
}
/**
@@ -57,8 +62,9 @@
*/
@Operation(summary = "鑾峰彇骞村害鎬诲悎鏍肩巼缁熻鏁版嵁")
@GetMapping("/getYearlyPassRateStatistics")
- public AjaxResult getYearlyPassRateStatistics(@RequestParam("year") String year) {
- return AjaxResult.success(qualityReportService.getYearlyPassRateStatistics(year));
+ @Log(title = "鑾峰彇骞村害鎬诲悎鏍肩巼缁熻鏁版嵁", businessType = BusinessType.OTHER)
+ public R<?> getYearlyPassRateStatistics(@RequestParam("year") String year) {
+ return R.ok(qualityReportService.getYearlyPassRateStatistics(year));
}
/**
@@ -66,8 +72,9 @@
*/
@Operation(summary = "鑾峰彇鏈堝害瀹屾垚鏄庣粏鏁版嵁")
@GetMapping("/getMonthlyCompletionDetails")
- public AjaxResult getMonthlyCompletionDetails(@RequestParam("year") String year) {
- return AjaxResult.success(qualityReportService.getMonthlyCompletionDetails(year));
+ @Log(title = "鑾峰彇鏈堝害瀹屾垚鏄庣粏鏁版嵁", businessType = BusinessType.OTHER)
+ public R<?> getMonthlyCompletionDetails(@RequestParam("year") String year) {
+ return R.ok(qualityReportService.getMonthlyCompletionDetails(year));
}
/**
@@ -75,8 +82,9 @@
*/
@Operation(summary = "鑾峰彇鐑偣妫�娴嬫寚鏍囩粺璁�")
@GetMapping("/getTopParameters")
- public AjaxResult getTopParameters(@RequestParam("modelType") Integer modelType) {
- return AjaxResult.success(qualityReportService.getTopParameters(modelType));
+ @Log(title = "鑾峰彇鐑偣妫�娴嬫寚鏍囩粺璁�", businessType = BusinessType.OTHER)
+ public R<?> getTopParameters(@RequestParam("modelType") Integer modelType) {
+ return R.ok(qualityReportService.getTopParameters(modelType));
}
}
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityTestStandardBindingController.java b/src/main/java/com/ruoyi/quality/controller/QualityTestStandardBindingController.java
index 539f3f7..7f2142e 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityTestStandardBindingController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityTestStandardBindingController.java
@@ -1,8 +1,12 @@
package com.ruoyi.quality.controller;
-import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
import com.ruoyi.quality.pojo.QualityTestStandardBinding;
import com.ruoyi.quality.service.QualityTestStandardBindingService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
@@ -20,6 +24,7 @@
@RestController
@RequestMapping("/qualityTestStandardBinding")
@AllArgsConstructor
+@Tag(name = "妫�娴嬫爣鍑嗕富琛ㄤ笌浜у搧鍏宠仈琛�")
public class QualityTestStandardBindingController {
private QualityTestStandardBindingService qualityTestStandardBindingService;
@@ -31,8 +36,10 @@
* @return
*/
@PostMapping("/add")
- public AjaxResult add(@RequestBody List<QualityTestStandardBinding> qualityTestStandardBindings) {
- return AjaxResult.success(qualityTestStandardBindingService.add(qualityTestStandardBindings));
+ @Operation(summary = "鏂板妫�娴嬫爣鍑嗕富琛ㄤ笌浜у搧鍏宠仈琛�")
+ @Log(title = "鏂板妫�娴嬫爣鍑嗕富琛ㄤ笌浜у搧鍏宠仈琛�", businessType = BusinessType.INSERT)
+ public R<?> add(@RequestBody List<QualityTestStandardBinding> qualityTestStandardBindings) {
+ return R.ok(qualityTestStandardBindingService.add(qualityTestStandardBindings));
}
/**
@@ -42,11 +49,13 @@
* @return
*/
@DeleteMapping("/del")
- public AjaxResult delQualityTestStandard(@RequestBody List<Integer> ids) {
+ @Operation(summary = "鍒犻櫎妫�娴嬫爣鍑嗕富琛ㄤ笌浜у搧鍏宠仈琛�")
+ @Log(title = "鍒犻櫎妫�娴嬫爣鍑嗕富琛ㄤ笌浜у搧鍏宠仈琛�", businessType = BusinessType.DELETE)
+ public R<?> delQualityTestStandard(@RequestBody List<Integer> ids) {
if (CollectionUtils.isEmpty(ids)) {
- return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+ return R.fail("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
}
- return AjaxResult.success(qualityTestStandardBindingService.removeBatchByIds(ids));
+ return R.ok(qualityTestStandardBindingService.removeBatchByIds(ids));
}
/**
@@ -55,8 +64,10 @@
* @return
*/
@GetMapping("/list")
- public AjaxResult listBinding(Long testStandardId) {
- return AjaxResult.success(qualityTestStandardBindingService.listBinding(testStandardId));
+ @Operation(summary = "妫�娴嬫寚鏍囩淮鎶ゆ煡璇�")
+ @Log(title = "妫�娴嬫寚鏍囩淮鎶ゆ煡璇�", businessType = BusinessType.OTHER)
+ public R<?> listBinding(Long testStandardId) {
+ return R.ok(qualityTestStandardBindingService.listBinding(testStandardId));
}
}
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityTestStandardController.java b/src/main/java/com/ruoyi/quality/controller/QualityTestStandardController.java
index a61ffed..ab8fca9 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityTestStandardController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityTestStandardController.java
@@ -2,11 +2,15 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
import com.ruoyi.quality.pojo.QualityTestStandard;
import com.ruoyi.quality.pojo.QualityTestStandardParam;
import com.ruoyi.quality.service.IQualityTestStandardService;
import com.ruoyi.quality.service.QualityTestStandardParamService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
@@ -24,6 +28,7 @@
*/
@RestController
@RequestMapping("/qualityTestStandard")
+@Tag(name = "妫�娴嬫爣鍑嗕富琛�")
public class QualityTestStandardController {
@Resource
@@ -39,8 +44,10 @@
* @return
*/
@PostMapping("/add")
- public AjaxResult add(@RequestBody QualityTestStandard qualityTestStandard) {
- return AjaxResult.success(qualityTestStandardService.save(qualityTestStandard));
+ @Operation(summary = "鏂板妫�娴嬫爣鍑嗕富琛�")
+ @Log(title = "鏂板妫�娴嬫爣鍑嗕富琛�", businessType = BusinessType.INSERT)
+ public R<?> add(@RequestBody QualityTestStandard qualityTestStandard) {
+ return R.ok(qualityTestStandardService.save(qualityTestStandard));
}
/**
@@ -49,11 +56,13 @@
* @return
*/
@DeleteMapping("/del")
- public AjaxResult delQualityTestStandard(@RequestBody List<Integer> ids) {
+ @Operation(summary = "鍒犻櫎妫�娴嬫爣鍑嗕富琛�")
+ @Log(title = "鍒犻櫎妫�娴嬫爣鍑嗕富琛�", businessType = BusinessType.DELETE)
+ public R<?> delQualityTestStandard(@RequestBody List<Integer> ids) {
if(CollectionUtils.isEmpty(ids)){
- return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+ return R.fail("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
}
- return AjaxResult.success(qualityTestStandardService.delQualityTestStandard(ids));
+ return R.ok(qualityTestStandardService.delQualityTestStandard(ids));
}
/**
@@ -62,8 +71,10 @@
* @return
*/
@PostMapping("/update")
- public AjaxResult update(@RequestBody QualityTestStandard qualityTestStandard) {
- return AjaxResult.success(qualityTestStandardService.updateById(qualityTestStandard));
+ @Operation(summary = "妫�娴嬫爣鍑嗕富琛ㄤ慨鏀�")
+ @Log(title = "妫�娴嬫爣鍑嗕富琛ㄤ慨鏀�", businessType = BusinessType.UPDATE)
+ public R<?> update(@RequestBody QualityTestStandard qualityTestStandard) {
+ return R.ok(qualityTestStandardService.updateById(qualityTestStandard));
}
/**
@@ -73,8 +84,10 @@
* @return
*/
@GetMapping("/listPage")
- public AjaxResult qualityTestStandardListPage(Page page, QualityTestStandard qualityTestStandard) {
- return AjaxResult.success(qualityTestStandardService.qualityTestStandardListPage(page, qualityTestStandard));
+ @Operation(summary = "妫�娴嬫爣鍑嗕富琛ㄥ垎椤垫煡璇�")
+ @Log(title = "妫�娴嬫爣鍑嗕富琛ㄥ垎椤垫煡璇�", businessType = BusinessType.OTHER)
+ public R<?> qualityTestStandardListPage(Page page, QualityTestStandard qualityTestStandard) {
+ return R.ok(qualityTestStandardService.qualityTestStandardListPage(page, qualityTestStandard));
}
/**
@@ -83,8 +96,10 @@
* @return
*/
@PostMapping("/copyParam")
- public AjaxResult copyParam(@RequestBody QualityTestStandard qualityTestStandard) {
- return AjaxResult.success(qualityTestStandardService.copyParam(qualityTestStandard));
+ @Operation(summary = "妫�娴嬫爣鍑嗗鍒跺弬鏁�")
+ @Log(title = "妫�娴嬫爣鍑嗗鍒跺弬鏁�", businessType = BusinessType.OTHER)
+ public R<?> copyParam(@RequestBody QualityTestStandard qualityTestStandard) {
+ return R.ok(qualityTestStandardService.copyParam(qualityTestStandard));
}
/**
@@ -93,8 +108,10 @@
* @return
*/
@PostMapping("/qualityTestStandardAudit")
- public AjaxResult qualityTestStandardAudit(@RequestBody List<QualityTestStandard> qualityTestStandards) {
- return AjaxResult.success(qualityTestStandardService.updateBatchById(qualityTestStandards));
+ @Operation(summary = "妫�娴嬫爣鍑嗘壒閲忓鏍�")
+ @Log(title = "妫�娴嬫爣鍑嗘壒閲忓鏍�", businessType = BusinessType.OTHER)
+ public R<?> qualityTestStandardAudit(@RequestBody List<QualityTestStandard> qualityTestStandards) {
+ return R.ok(qualityTestStandardService.updateBatchById(qualityTestStandards));
}
/**
@@ -102,8 +119,10 @@
* @return
*/
@GetMapping("/getQualityTestStandardByProductId")
- public AjaxResult getQualityTestStandardByProductId(@Nonnull Long productId, @Nonnull Integer inspectType, String process) {
- return AjaxResult.success(qualityTestStandardService.getQualityTestStandardByProductId(productId,inspectType,process));
+ @Operation(summary = "鏍规嵁浜у搧id鏌ヨ鐩稿叧鐨勬楠屾爣鍑�")
+ @Log(title = "鏍规嵁浜у搧id鏌ヨ鐩稿叧鐨勬楠屾爣鍑�", businessType = BusinessType.OTHER)
+ public R<?> getQualityTestStandardByProductId(@Nonnull Long productId, @Nonnull Integer inspectType, String process) {
+ return R.ok(qualityTestStandardService.getQualityTestStandardByProductId(productId,inspectType,process));
}
/**
@@ -111,8 +130,10 @@
* @return
*/
@GetMapping("/getQualityTestStandardParamByTestStandardId")
- public AjaxResult getQualityTestStandardParamByTestStandardId(Long testStandardId) {
- return AjaxResult.success(qualityTestStandardParamService.list(Wrappers.<QualityTestStandardParam>lambdaQuery().eq(QualityTestStandardParam::getTestStandardId, testStandardId)));
+ @Operation(summary = "鏍规嵁妫�娴嬫爣鍑唅d鏌ヨ鐩稿叧鐨勬楠屾爣鍑嗗弬鏁�")
+ @Log(title = "鏍规嵁妫�娴嬫爣鍑唅d鏌ヨ鐩稿叧鐨勬楠屾爣鍑嗗弬鏁�", businessType = BusinessType.OTHER)
+ public R<?> getQualityTestStandardParamByTestStandardId(Long testStandardId) {
+ return R.ok(qualityTestStandardParamService.list(Wrappers.<QualityTestStandardParam>lambdaQuery().eq(QualityTestStandardParam::getTestStandardId, testStandardId)));
}
}
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityTestStandardParamController.java b/src/main/java/com/ruoyi/quality/controller/QualityTestStandardParamController.java
index e5c883c..16788c9 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityTestStandardParamController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityTestStandardParamController.java
@@ -2,10 +2,14 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
import com.ruoyi.quality.pojo.QualityTestStandard;
import com.ruoyi.quality.pojo.QualityTestStandardParam;
import com.ruoyi.quality.service.QualityTestStandardParamService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
@@ -24,6 +28,7 @@
@RestController
@RequestMapping("/qualityTestStandardParam")
@AllArgsConstructor
+@Tag(name = "妫�娴嬫爣鍑嗗弬鏁�")
public class QualityTestStandardParamController {
private QualityTestStandardParamService qualityTestStandardParamService;
@@ -34,8 +39,10 @@
* @return
*/
@PostMapping("/add")
- public AjaxResult add(@RequestBody QualityTestStandardParam qualityTestStandardParam) {
- return AjaxResult.success(qualityTestStandardParamService.save(qualityTestStandardParam));
+ @Operation(summary = "鏂板妫�娴嬫爣鍑嗗弬鏁�")
+ @Log(title = "鏂板妫�娴嬫爣鍑嗗弬鏁�", businessType = BusinessType.INSERT)
+ public R<?> add(@RequestBody QualityTestStandardParam qualityTestStandardParam) {
+ return R.ok(qualityTestStandardParamService.save(qualityTestStandardParam));
}
/**
@@ -44,11 +51,13 @@
* @return
*/
@DeleteMapping("/del")
- public AjaxResult delQualityTestStandard(@RequestBody List<Integer> ids) {
+ @Operation(summary = "鍒犻櫎妫�娴嬫寚鏍囩淮鎶�")
+ @Log(title = "鍒犻櫎妫�娴嬫寚鏍囩淮鎶�", businessType = BusinessType.DELETE)
+ public R<?> delQualityTestStandard(@RequestBody List<Integer> ids) {
if(CollectionUtils.isEmpty(ids)){
- return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+ return R.fail("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
}
- return AjaxResult.success(qualityTestStandardParamService.removeBatchByIds(ids));
+ return R.ok(qualityTestStandardParamService.removeBatchByIds(ids));
}
/**
@@ -57,8 +66,10 @@
* @return
*/
@PostMapping("/update")
- public AjaxResult update(@RequestBody QualityTestStandardParam qualityTestStandardParam) {
- return AjaxResult.success(qualityTestStandardParamService.updateById(qualityTestStandardParam));
+ @Operation(summary = "妫�娴嬫寚鏍囩淮鎶や慨鏀�")
+ @Log(title = "妫�娴嬫寚鏍囩淮鎶や慨鏀�", businessType = BusinessType.UPDATE)
+ public R<?> update(@RequestBody QualityTestStandardParam qualityTestStandardParam) {
+ return R.ok(qualityTestStandardParamService.updateById(qualityTestStandardParam));
}
/**
@@ -66,8 +77,10 @@
* @return
*/
@GetMapping("/list")
- public AjaxResult list(Long testStandardId) {
- return AjaxResult.success(qualityTestStandardParamService.list(Wrappers.<QualityTestStandardParam>lambdaQuery().eq(QualityTestStandardParam::getTestStandardId,testStandardId)));
+ @Operation(summary = "妫�娴嬫寚鏍囩淮鎶ゆ煡璇�")
+ @Log(title = "妫�娴嬫寚鏍囩淮鎶ゆ煡璇�", businessType = BusinessType.OTHER)
+ public R<?> list(Long testStandardId) {
+ return R.ok(qualityTestStandardParamService.list(Wrappers.<QualityTestStandardParam>lambdaQuery().eq(QualityTestStandardParam::getTestStandardId,testStandardId)));
}
}
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java b/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
index 3b20f82..a2222c3 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
@@ -1,9 +1,13 @@
package com.ruoyi.quality.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
import com.ruoyi.quality.pojo.QualityUnqualified;
import com.ruoyi.quality.service.IQualityUnqualifiedService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
@@ -16,6 +20,7 @@
*/
@RestController
@RequestMapping("/quality/qualityUnqualified")
+@Tag(name = "涓嶅悎鏍肩鐞�")
public class QualityUnqualifiedController {
@Resource
@@ -28,9 +33,11 @@
* @return
*/
@PostMapping("/add")
- public AjaxResult add(@RequestBody QualityUnqualified qualityUnqualified) {
+ @Operation(summary = "鏂板涓嶅悎鏍肩鐞�")
+ @Log(title = "鏂板涓嶅悎鏍肩鐞�", businessType = BusinessType.INSERT)
+ public R<?> add(@RequestBody QualityUnqualified qualityUnqualified) {
qualityUnqualified.setInspectState(0);
- return AjaxResult.success(qualityUnqualifiedService.save(qualityUnqualified));
+ return R.ok(qualityUnqualifiedService.save(qualityUnqualified));
}
/**
@@ -39,13 +46,15 @@
* @return
*/
@DeleteMapping("/del")
- public AjaxResult delQualityUnqualified(@RequestBody List<Integer> ids) {
+ @Operation(summary = "鍒犻櫎涓嶅悎鏍肩鐞�")
+ @Log(title = "鍒犻櫎涓嶅悎鏍肩鐞�", businessType = BusinessType.DELETE)
+ public R<?> delQualityUnqualified(@RequestBody List<Integer> ids) {
qualityUnqualifiedService.listByIds(ids).stream().forEach(qualityUnqualified -> {
if (qualityUnqualified.getInspectState()==1){
throw new RuntimeException("璇ヤ笉鍚堟牸鏁版嵁宸茬粡澶勭悊鏃犳硶鍒犻櫎!");
}
});
- return AjaxResult.success(qualityUnqualifiedService.removeBatchByIds(ids));
+ return R.ok(qualityUnqualifiedService.removeBatchByIds(ids));
}
/**
@@ -54,8 +63,10 @@
* @return
*/
@GetMapping("/{id}")
- public AjaxResult QualityUnqualifiedDetail(@PathVariable("id") Integer id) {
- return AjaxResult.success(qualityUnqualifiedService.getUnqualified(id));
+ @Operation(summary = "涓嶅悎鏍肩鐞嗚鎯�")
+ @Log(title = "涓嶅悎鏍肩鐞嗚鎯�", businessType = BusinessType.OTHER)
+ public R<?> QualityUnqualifiedDetail(@PathVariable("id") Integer id) {
+ return R.ok(qualityUnqualifiedService.getUnqualified(id));
}
/**
@@ -64,8 +75,10 @@
* @return
*/
@PostMapping("/update")
- public AjaxResult update(@RequestBody QualityUnqualified qualityUnqualified) {
- return AjaxResult.success(qualityUnqualifiedService.updateById(qualityUnqualified));
+ @Operation(summary = "涓嶅悎鏍肩鐞嗕慨鏀�")
+ @Log(title = "涓嶅悎鏍肩鐞嗕慨鏀�", businessType = BusinessType.UPDATE)
+ public R<?> update(@RequestBody QualityUnqualified qualityUnqualified) {
+ return R.ok(qualityUnqualifiedService.updateById(qualityUnqualified));
}
/**
@@ -75,8 +88,10 @@
* @return
*/
@GetMapping("/listPage")
- public AjaxResult qualityUnqualifiedListPage(Page page, QualityUnqualified qualityUnqualified) {
- return AjaxResult.success(qualityUnqualifiedService.qualityUnqualifiedListPage(page, qualityUnqualified));
+ @Operation(summary = "涓嶅悎鏍肩鐞嗗垎椤垫煡璇�")
+ @Log(title = "涓嶅悎鏍肩鐞嗗垎椤垫煡璇�", businessType = BusinessType.OTHER)
+ public R<?> qualityUnqualifiedListPage(Page page, QualityUnqualified qualityUnqualified) {
+ return R.ok(qualityUnqualifiedService.qualityUnqualifiedListPage(page, qualityUnqualified));
}
/**
@@ -85,6 +100,8 @@
* @param qualityUnqualified
*/
@PostMapping("/export")
+ @Operation(summary = "涓嶅悎鏍肩鐞嗗鍑�")
+ @Log(title = "涓嶅悎鏍肩鐞嗗鍑�", businessType = BusinessType.EXPORT)
public void qualityUnqualifiedExport(HttpServletResponse response,QualityUnqualified qualityUnqualified) {
qualityUnqualifiedService.qualityUnqualifiedExport(response, qualityUnqualified);
}
@@ -95,8 +112,10 @@
* @return
*/
@PostMapping("/deal")
- public AjaxResult deal(@RequestBody QualityUnqualified qualityUnqualified) {
- return AjaxResult.success(qualityUnqualifiedService.deal(qualityUnqualified));
+ @Operation(summary = "涓嶅悎鏍肩鐞嗗鐞�")
+ @Log(title = "涓嶅悎鏍肩鐞嗗鐞�", businessType = BusinessType.OTHER)
+ public R<?> deal(@RequestBody QualityUnqualified qualityUnqualified) {
+ return R.ok(qualityUnqualifiedService.deal(qualityUnqualified));
}
diff --git a/src/main/java/com/ruoyi/quality/pojo/QualityInspect.java b/src/main/java/com/ruoyi/quality/pojo/QualityInspect.java
index 62b047a..bc3f60a 100644
--- a/src/main/java/com/ruoyi/quality/pojo/QualityInspect.java
+++ b/src/main/java/com/ruoyi/quality/pojo/QualityInspect.java
@@ -7,7 +7,7 @@
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
-import jakarta.validation.constraints.NotBlank;
+import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@@ -20,6 +20,7 @@
@TableName(value = "quality_inspect")
@Data
public class QualityInspect extends DateQueryDto implements Serializable {
+ @Serial
private static final long serialVersionUID = 1L;
/**
@@ -32,7 +33,6 @@
* 绫诲埆(0:鍘熸潗鏂欐楠�;1:杩囩▼妫�楠�;2:鍑哄巶妫�楠�)
*/
@Excel(name = "绫诲埆",readConverterExp = "0=鍘熸潗鏂欐楠�,1=杩囩▼妫�楠�,2=鍑哄巶妫�楠�")
- @NotBlank(message = "绫诲埆涓嶈兘涓虹┖!!")
private Integer inspectType;
/**
@@ -72,7 +72,6 @@
/**
* 鍏宠仈浜у搧id
*/
- @NotBlank(message = "浜у搧id涓嶈兘涓虹┖")
private Long productId;
/**
diff --git a/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
index 0f410fd..0707375 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
@@ -10,6 +10,7 @@
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
+import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.HackLoopTableRenderPolicy;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.procurementrecord.service.ProcurementRecordService;
@@ -90,16 +91,32 @@
@Override
public int submit(QualityInspect inspect) {
QualityInspect qualityInspect = qualityInspectMapper.selectById(inspect.getId());
+
//鎻愪氦鍓嶅繀椤诲垽鏂槸鍚﹀悎鏍�
if (ObjectUtils.isNull(qualityInspect.getCheckResult())) {
- throw new RuntimeException("璇峰厛鍒ゆ柇鏄惁鍚堟牸");
+ throw new ServiceException("璇峰厛鍒ゆ柇鏄惁鍚堟牸");
}
- // 鍖哄垎鍚堟牸鏁伴噺浠ュ強涓嶅悎鏍煎鐞嗚繘琛屽搴旂殑澶勭悊
- Assert.isTrue(qualityInspect.getQuantity().compareTo(qualityInspect.getQualifiedQuantity().add(qualityInspect.getUnqualifiedQuantity())) == 0,"璇锋鏌ュ悎鏍兼暟閲忓拰涓嶅悎鏍兼暟閲忥紝闇�瑕佸悎鏍兼暟閲�+涓嶅悎鏍兼暟閲忎笌鎬绘暟淇濇寔涓�鑷�");
+ if (ObjectUtils.isNull(qualityInspect.getQualifiedQuantity())) {
+ throw new ServiceException("鍚堟牸鏁伴噺涓嶈兘涓虹┖");
+ }
+
+ if (ObjectUtils.isNull(qualityInspect.getUnqualifiedQuantity())) {
+ throw new ServiceException("涓嶅悎鏍兼暟閲忎笉鑳戒负绌�");
+ }
+
+ // 濡傛灉鍚堟牸鏁伴噺涓虹┖锛岃涓�0
+ if (qualityInspect.getQualifiedQuantity() == null) {
+ qualityInspect.setQualifiedQuantity(BigDecimal.ZERO);
+ }
+
+ // 濡傛灉涓嶅悎鏍兼暟閲忎负绌猴紝璁句负0
+ if (qualityInspect.getUnqualifiedQuantity() == null) {
+ qualityInspect.setUnqualifiedQuantity(BigDecimal.ZERO);
+ }
+
+ // 鍚堟牸鐩存帴鍏ュ簱
if(qualityInspect.getQualifiedQuantity().compareTo(BigDecimal.ZERO) > 0){
- //鍚堟牸鐩存帴鍏ュ簱
- // stockUtils.addStock(qualityInspect.getProductModelId(), qualityInspect.getQuantity(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(), qualityInspect.getId());
//浠呮坊鍔犲叆搴撹褰�
StockInventoryDto stockInventoryDto = new StockInventoryDto();
//濡傛灉鏄噰璐川妫�鍚堟牸鍏ュ簱閫夌敤CUSTOMIZATION_UNSTOCK_OUT,鍏朵綑鍚堟牸鍏ュ簱閫夌敤QUALITYINSPECT_STOCK_IN
@@ -116,6 +133,7 @@
qualityInspect.getProductModelId()));
stockInventoryService.addStockInRecordOnly(stockInventoryDto);
}
+ // 涓嶅悎鏍煎鐞�
if(qualityInspect.getUnqualifiedQuantity().compareTo(BigDecimal.ZERO) > 0){
QualityUnqualified qualityUnqualified = new QualityUnqualified();
BeanUtils.copyProperties(qualityInspect, qualityUnqualified);
diff --git a/src/main/java/com/ruoyi/quality/utils/QualityInspectHelper.java b/src/main/java/com/ruoyi/quality/utils/QualityInspectHelper.java
new file mode 100644
index 0000000..766515a
--- /dev/null
+++ b/src/main/java/com/ruoyi/quality/utils/QualityInspectHelper.java
@@ -0,0 +1,73 @@
+package com.ruoyi.quality.utils;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.purchase.pojo.PurchaseLedger;
+import com.ruoyi.quality.mapper.QualityInspectMapper;
+import com.ruoyi.quality.mapper.QualityInspectParamMapper;
+import com.ruoyi.quality.mapper.QualityTestStandardMapper;
+import com.ruoyi.quality.mapper.QualityTestStandardParamMapper;
+import com.ruoyi.quality.pojo.QualityInspect;
+import com.ruoyi.quality.pojo.QualityInspectParam;
+import com.ruoyi.quality.pojo.QualityTestStandard;
+import com.ruoyi.quality.pojo.QualityTestStandardParam;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * 璐ㄦ鍗曞垱寤哄伐鍏风被
+ */
+@Component
+@RequiredArgsConstructor
+public class QualityInspectHelper {
+
+ private final QualityInspectMapper qualityInspectMapper;
+ private final QualityTestStandardMapper qualityTestStandardMapper;
+ private final QualityTestStandardParamMapper qualityTestStandardParamMapper;
+ private final QualityInspectParamMapper qualityInspectParamMapper;
+
+ /**
+ * 鍒涘缓璐ㄦ鍗�
+ * @param purchaseLedger 閲囪喘鍙拌处
+ * @param saleProduct 閲囪喘浜у搧
+ */
+ public void addQualityInspect(PurchaseLedger purchaseLedger, SalesLedgerProduct saleProduct) {
+ QualityInspect qualityInspect = new QualityInspect();
+ qualityInspect.setInspectType(0);
+ qualityInspect.setSupplier(purchaseLedger.getSupplierName());
+ qualityInspect.setPurchaseLedgerId(purchaseLedger.getId());
+ qualityInspect.setProductId(saleProduct.getProductId());
+ qualityInspect.setProductName(saleProduct.getProductCategory());
+ qualityInspect.setModel(saleProduct.getSpecificationModel());
+ qualityInspect.setProductModelId(saleProduct.getProductModelId());
+ qualityInspect.setUnit(saleProduct.getUnit());
+ qualityInspect.setQuantity(saleProduct.getQuantity());
+ qualityInspectMapper.insert(qualityInspect);
+
+ List<QualityTestStandard> qualityTestStandardList = qualityTestStandardMapper
+ .getQualityTestStandardByProductId(saleProduct.getProductId(), 0, null);
+
+ if (qualityTestStandardList.isEmpty()) {
+ return;
+ }
+
+ QualityTestStandard firstStandard = qualityTestStandardList.get(0);
+ qualityInspect.setTestStandardId(firstStandard.getId());
+ qualityInspectMapper.updateById(qualityInspect);
+
+ List<QualityTestStandardParam> standardParams = qualityTestStandardParamMapper.selectList(
+ Wrappers.<QualityTestStandardParam>lambdaQuery()
+ .eq(QualityTestStandardParam::getTestStandardId, firstStandard.getId()));
+
+ for (QualityTestStandardParam standardParam : standardParams) {
+ QualityInspectParam param = new QualityInspectParam();
+ BeanUtils.copyProperties(standardParam, param);
+ param.setId(null);
+ param.setInspectId(qualityInspect.getId());
+ qualityInspectParamMapper.insert(param);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/sales/controller/InvoiceLedgerController.java b/src/main/java/com/ruoyi/sales/controller/InvoiceLedgerController.java
deleted file mode 100644
index 0559ff8..0000000
--- a/src/main/java/com/ruoyi/sales/controller/InvoiceLedgerController.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package com.ruoyi.sales.controller;
-
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.sales.dto.InvoiceLedgerDto;
-import com.ruoyi.sales.dto.InvoiceRegistrationProductDto;
-import com.ruoyi.sales.mapper.InvoiceLedgerFileMapper;
-import com.ruoyi.sales.service.InvoiceLedgerService;
-import io.jsonwebtoken.lang.Collections;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AllArgsConstructor;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.math.BigDecimal;
-import java.util.List;
-
-@RestController
-@RequestMapping("/invoiceLedger")
-@AllArgsConstructor
-public class InvoiceLedgerController {
-
- private InvoiceLedgerService invoiceLedgerService;
- private InvoiceLedgerFileMapper invoiceLedgerFileMapper;
-
- /**
- * 寮�绁ㄥ彴璐︽柊澧�
- * @param productDto
- * @return
- */
- @PostMapping("/saveOrUpdate")
- public AjaxResult invoiceLedgerSaveOrUpdate(@RequestBody InvoiceRegistrationProductDto productDto) {
- invoiceLedgerService.invoiceLedgerSaveOrUpdate(productDto);
- return AjaxResult.success();
- }
-
- /**
- * 寮�绁ㄥ彴璐﹀垹闄�
- * @param ids
- * @return
- */
- @DeleteMapping("/del")
- public AjaxResult invoiceLedgerDel(@RequestBody List<Integer> ids) {
- invoiceLedgerService.invoiceLedgerDel(ids);
- return AjaxResult.success();
- }
-
- /**
- * 寮�绁ㄥ彴璐﹀垎椤垫煡璇�
- * @param page
- * @param invoiceLedgerDto
- * @return
- */
- @GetMapping("/page")
- public AjaxResult invoiceLedgerPage(Page page, InvoiceLedgerDto invoiceLedgerDto) {
- return AjaxResult.success(invoiceLedgerService.invoiceLedgerPage(page, invoiceLedgerDto));
- }
-
- /**
- * 寮�绁ㄥ彴璐︽枃浠舵煡璇�
- * @param invoiceLedgerId
- * @return
- */
- @GetMapping("/fileList")
- public AjaxResult invoiceLedgerFileList(Integer invoiceLedgerId) {
- return AjaxResult.success(invoiceLedgerService.invoiceLedgerFileList(invoiceLedgerId));
- }
-
- /**
- * 寮�绁ㄥ彴璐︽枃浠跺垹闄�
- */
- @DeleteMapping("/delFile")
- @Log(title = "寮�绁ㄥ彴璐�", businessType = BusinessType.DELETE)
- public AjaxResult invoiceLedgerDelFile(@RequestBody List<Integer> ids) {
- if(Collections.isEmpty(ids)) return AjaxResult.error("璇烽�夋嫨瑕佸垹闄ょ殑鏂囦欢");
- invoiceLedgerFileMapper.deleteBatchIds(ids);
- return AjaxResult.success();
- }
-
-
-
- /**
- * 寮�绁ㄥ彴璐︽枃浠朵笂浼�
- * @param file
- * @return
- */
- @PostMapping("/uploadFile")
- public AjaxResult invoiceLedgerUploadFile(MultipartFile file) {
- try {
- return AjaxResult.success(invoiceLedgerService.invoiceLedgerUploadFile(file));
- }catch (Exception e) {
- return AjaxResult.error(e.getMessage());
- }
- }
-
- /**
- * 寮�绁ㄥ彴璐﹀鍑�
- * @param response
- * @param invoiceRegistrationProductDto
- * @return
- */
- @PostMapping("/export")
- public void invoiceLedgerExport(HttpServletResponse response, InvoiceRegistrationProductDto invoiceRegistrationProductDto) {
- invoiceLedgerService.invoiceLedgerExport(response, invoiceRegistrationProductDto);
- }
-
- /**
- * 寮�绁ㄥ彴璐﹁鎯�
- * @param id
- * @return
- */
- @GetMapping("/info")
- public AjaxResult invoiceLedgerInfo(Integer id) {
- return AjaxResult.success(invoiceLedgerService.invoiceLedgerDetail(id));
- }
-
- /**
- * 鏂囦欢鎻愪氦
- * @param invoiceLedgerDto
- * @return
- */
- @PostMapping("/commitFile")
- public AjaxResult invoiceLedgerCommitFile(@RequestBody InvoiceLedgerDto invoiceLedgerDto) {
- try {
- invoiceLedgerService.invoiceLedgerCommitFile(invoiceLedgerDto);
- return AjaxResult.success();
- }catch (Exception e) {
- return AjaxResult.error(e.getMessage());
- }
- }
-
- /**
- * 寮�绁ㄥ彴璐︽煡璇�
- * @param invoiceLedgerDto
- * @return
- */
- @GetMapping("/list")
- public AjaxResult invoiceLedgerList(InvoiceLedgerDto invoiceLedgerDto) {
- return AjaxResult.success(invoiceLedgerService.invoiceLedgerList(invoiceLedgerDto));
- }
-
- /**
- * 瀹㈡埛閿�鍞褰�
- * @param page
- * @param invoiceLedgerDto
- * @return
- */
- @GetMapping("/salesAccount")
- public AjaxResult invoiceLedgerSalesAccount(Page page, InvoiceLedgerDto invoiceLedgerDto) {
- return AjaxResult.success(invoiceLedgerService.invoiceLedgerSalesAccount(page,invoiceLedgerDto));
- }
-
- /**
- * 鏈湀寮�绁ㄩ噾棰�
- */
- @GetMapping("/getInvoiceAmount")
- public AjaxResult getInvoiceAmount() {
- try {
- BigDecimal amount = invoiceLedgerService.getInvoiceAmount();
- return AjaxResult.success(amount != null ? amount : BigDecimal.ZERO);
- } catch (Exception e) {
- return AjaxResult.error("鑾峰彇寮�绁ㄩ噾棰濆け璐ワ細" + e.getMessage());
- }
- }
-
- /**
- * 浜у搧寮�绁ㄨ褰曟煡璇�
- * @param page
- * @param registrationProductDto
- * @return
- */
- @GetMapping("/registrationProductPage")
- public AjaxResult registrationProductPage(Page page, InvoiceRegistrationProductDto registrationProductDto) {
-
- return AjaxResult.success(invoiceLedgerService.registrationProductPage(page,registrationProductDto));
- }
-
- /**
- * 浜у搧寮�绁ㄨ鎯�
- * @param id
- * @return
- */
- @GetMapping("/invoiceLedgerProductInfo")
- public AjaxResult invoiceLedgerProductDetail(Integer id) {
- return AjaxResult.success(invoiceLedgerService.invoiceLedgerProductDetail(id));
- }
-
- /**
- * 寮�绁ㄥ彴璐﹀垹闄�
- * @param invoiceRegistrationProductId
- * @return
- */
- @DeleteMapping("delInvoiceLedger/{invoiceRegistrationProductId}")
- public AjaxResult delInvoiceLedger(@PathVariable Integer invoiceRegistrationProductId) {
- try {
- invoiceLedgerService.delInvoiceLedger(invoiceRegistrationProductId);
- return AjaxResult.success();
- }catch (Exception e) {
- return AjaxResult.error(e.getMessage());
- }
- }
-
-}
diff --git a/src/main/java/com/ruoyi/sales/controller/InvoiceRegistrationController.java b/src/main/java/com/ruoyi/sales/controller/InvoiceRegistrationController.java
deleted file mode 100644
index 8ea6c11..0000000
--- a/src/main/java/com/ruoyi/sales/controller/InvoiceRegistrationController.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package com.ruoyi.sales.controller;
-
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.sales.dto.InvoiceRegistrationDto;
-import com.ruoyi.sales.dto.InvoiceRegistrationProductDto;
-import com.ruoyi.sales.dto.SalesLedgerDto;
-import com.ruoyi.sales.service.InvoiceRegistrationService;
-import io.jsonwebtoken.lang.Collections;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AllArgsConstructor;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-@RestController
-@RequestMapping("/invoiceRegistration")
-@AllArgsConstructor
-public class InvoiceRegistrationController {
-
- private InvoiceRegistrationService invoiceRegistrationService;
-
- /**
- * 寮�绁ㄧ櫥璁拌褰曟柊澧�
- * @param salesLedgerDto
- * @return
- */
- @PostMapping("/save")
- @Log(title = "寮�绁ㄧ櫥璁�", businessType = com.ruoyi.framework.aspectj.lang.enums.BusinessType.INSERT)
- @Transactional(rollbackFor = Exception.class)
- public AjaxResult invoiceRegistrationSave(@RequestBody List<SalesLedgerDto> salesLedgerDto) {
- if(Collections.isEmpty(salesLedgerDto)) return AjaxResult.error("璇烽�夋嫨瑕佷繚瀛樼殑璁板綍");
- salesLedgerDto.forEach(item ->{
- invoiceRegistrationService.invoiceRegistrationSave(item);
- });
-
- return AjaxResult.success();
- }
-
- /**
- * 寮�绁ㄧ櫥璁板垹闄�
- * @param ids
- * @return
- */
- @DeleteMapping("/del")
- public AjaxResult invoiceRegistrationDel(@RequestBody List<Integer> ids) {
- invoiceRegistrationService.invoiceRegistrationDel(ids);
- return AjaxResult.success();
- }
-
- /**
- * 寮�绁ㄨ褰曚慨鏀�
- * @param invoiceRegistrationDto
- * @return
- */
- @PostMapping("/update")
- public AjaxResult invoiceRegistrationUpdate(@RequestBody InvoiceRegistrationDto invoiceRegistrationDto) {
- invoiceRegistrationService.invoiceRegistrationUpdate(invoiceRegistrationDto);
- return AjaxResult.success();
- }
-
- /**
- * 寮�绁ㄧ櫥璁板垎椤垫煡璇�
- * @param page
- * @param invoiceRegistrationDto
- * @return
- */
- @GetMapping("/listPage")
- public AjaxResult invoiceRegistrationListPage(Page page, InvoiceRegistrationDto invoiceRegistrationDto) {
- return AjaxResult.success(invoiceRegistrationService.invoiceRegistrationListPage(page, invoiceRegistrationDto));
- }
-
- /**
- * 寮�绁ㄧ櫥璁颁骇鍝佹煡璇�
- * @param invoiceRegistrationProductDto
- * @return
- */
- @GetMapping("/productList")
- public AjaxResult invoiceRegistrationProductList(InvoiceRegistrationProductDto invoiceRegistrationProductDto) {
- return AjaxResult.success(invoiceRegistrationService.invoiceRegistrationProductList(invoiceRegistrationProductDto));
- }
-
- /**
- * 寮�绁ㄧ櫥璁颁骇鍝佽鎯�
- * @param id
- * @return
- */
- @GetMapping("/detail")
- public AjaxResult invoiceRegistrationDetail(Integer id) {
- return AjaxResult.success(invoiceRegistrationService.invoiceRegistrationDetail(id));
- }
-
- /**
- * 寮�绁ㄧ櫥璁板鍑�
- * @param response
- * @param invoiceRegistrationDto
- */
- @PostMapping("/export")
- public void invoiceRegistrationExport(HttpServletResponse response, InvoiceRegistrationDto invoiceRegistrationDto) {
- invoiceRegistrationService.invoiceRegistrationExport(response, invoiceRegistrationDto);
- }
-}
diff --git a/src/main/java/com/ruoyi/sales/controller/MetricStatisticsController.java b/src/main/java/com/ruoyi/sales/controller/MetricStatisticsController.java
index 8ad4f02..577508a 100644
--- a/src/main/java/com/ruoyi/sales/controller/MetricStatisticsController.java
+++ b/src/main/java/com/ruoyi/sales/controller/MetricStatisticsController.java
@@ -1,11 +1,16 @@
package com.ruoyi.sales.controller;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.service.ICustomerService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.domain.R;
import com.ruoyi.sales.dto.StatisticsTableDto;
import com.ruoyi.sales.service.impl.MetricStatisticsServiceImpl;
-import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -21,7 +26,8 @@
@AllArgsConstructor
public class MetricStatisticsController extends BaseController {
- private MetricStatisticsServiceImpl metricStatisticsService;
+ private final MetricStatisticsServiceImpl metricStatisticsService;
+ private final ICustomerService customerService;
@Operation(summary = "澶撮儴鎬昏")
@GetMapping("/total")
@@ -35,4 +41,18 @@
return metricStatisticsService.statisticsTable(statisticsTableDto);
}
+ @GetMapping("/customewTransactions")
+ @Log(title = "瀹㈡埛寰�鏉�", businessType = BusinessType.OTHER)
+ @Operation(summary = "瀹㈡埛寰�鏉�")
+ public R customewTransactions(Page page, String customerName) {
+ return R.ok(customerService.customewTransactions(page,customerName));
+ }
+
+ @GetMapping("/customewTransactionsDetails")
+ @Log(title = "瀹㈡埛寰�鏉ユ槑缁�", businessType = BusinessType.OTHER)
+ @Operation(summary = "瀹㈡埛寰�鏉ユ槑缁�")
+ public R customewTransactionsDetails(Page page, Long customerId) {
+ return R.ok(customerService.customewTransactionsDetails(page,customerId));
+ }
+
}
diff --git a/src/main/java/com/ruoyi/sales/controller/ReceiptPaymentController.java b/src/main/java/com/ruoyi/sales/controller/ReceiptPaymentController.java
deleted file mode 100644
index 5512a8d..0000000
--- a/src/main/java/com/ruoyi/sales/controller/ReceiptPaymentController.java
+++ /dev/null
@@ -1,191 +0,0 @@
-package com.ruoyi.sales.controller;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.utils.bean.BeanUtils;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.sales.dto.InvoiceLedgerDto;
-import com.ruoyi.sales.dto.ReceiptPaymentDto;
-import com.ruoyi.sales.dto.ReceiptPaymentRecordDto;
-import com.ruoyi.sales.pojo.ReceiptPayment;
-import com.ruoyi.sales.service.ReceiptPaymentService;
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AllArgsConstructor;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.*;
-
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-@RestController
-@RequestMapping("/receiptPayment")
-@AllArgsConstructor
-public class ReceiptPaymentController extends BaseController {
-
- private ReceiptPaymentService receiptPaymentService;
-
- /**
- * 鍥炴鐧昏鏂板
- * @param receiptPayment
- * @return
- */
- @PostMapping("/saveOrUpdate")
- public AjaxResult receiptPaymentSaveOrUpdate (@RequestBody List<ReceiptPayment> receiptPayment) {
- receiptPaymentService.receiptPaymentSaveOrUpdate(receiptPayment);
- return AjaxResult.success();
- }
-
- /**
- * 鍥炴鐧昏淇敼
- * @param receiptPayment
- * @return
- */
- @PostMapping("/update")
- @Transactional(rollbackFor = Exception.class)
- public AjaxResult receiptPaymentUpdate (@RequestBody ReceiptPayment receiptPayment) {
- return AjaxResult.success(receiptPaymentService.receiptPaymentUpdate(receiptPayment));
- }
-
- /**
- * 鍥炴鐧昏鍒犻櫎
- * @param ids
- * @return
- */
- @DeleteMapping("/del")
- @Transactional(rollbackFor = Exception.class)
- public AjaxResult receiptPaymentDel (@RequestBody List<Integer> ids) {
- return AjaxResult.success(receiptPaymentService.receiptPaymentDel(ids));
- }
-
- /**
- * 瀹㈡埛寰�鏉ヨ褰曟煡璇�
- * @param receiptPaymentDto
- * @return
- */
- @GetMapping("/customerInteractions")
- public AjaxResult customerInteractions (InvoiceLedgerDto receiptPaymentDto) {
- return AjaxResult.success(receiptPaymentService.customerInteractions(receiptPaymentDto));
- }
-
- /**
- * 鍥炴鐧昏璇︽儏
- * @param id
- * @return
- */
- @GetMapping("/info")
- public AjaxResult receiptPaymentInfo (Integer id) {
- return AjaxResult.success(receiptPaymentService.receiptPaymentInfo(id));
- }
-
- /**
- * 鏈湀鍥炴閲戦
- */
- @GetMapping("/getReceiptAmount")
- public AjaxResult getReceiptAmount() {
- try {
- BigDecimal receiptAmount = receiptPaymentService.getReceiptAmount();
- return AjaxResult.success(receiptAmount != null ? receiptAmount : BigDecimal.ZERO);
- } catch (Exception e) {
- return AjaxResult.error("鑾峰彇鍥炴閲戦澶辫触锛�" + e.getMessage());
- }
- }
-
- /**
- * 鏌ヨ宸茬粡缁戝畾鍙戠エ鐨勫紑绁ㄥ彴璐�
- * @param page
- * @param receiptPaymentDto
- * @return
- */
- @GetMapping("/bindInvoiceNoRegPage")
- public AjaxResult bindInvoiceNoRegPage(Page page, ReceiptPaymentDto receiptPaymentDto) {
- return AjaxResult.success(receiptPaymentService.bindInvoiceNoRegPage(page,receiptPaymentDto));
- }
-
- @Schema(description = "瀵煎嚭鍥炴鐧昏")
- @PostMapping("/export")
- public void export(HttpServletResponse response, String ids) {
- if (ids == null || ids.isEmpty()) {
- receiptPaymentService.exportPaymentList(response, null);
- } else {
- ArrayList<Long> idList = (ArrayList<Long>) Arrays.stream(ids.split(","))
- .map(s -> s.replaceAll("[\\[\\]]", "").trim())
- .map(Long::valueOf)
- .collect(Collectors.toList());
- receiptPaymentService.exportPaymentList(response, idList);
- }
- }
-
-
- /**
- * 寮�绁ㄥ彴璐﹁鎯�
- * @param id
- * @return
- */
- @GetMapping("/invoiceInfo")
- public AjaxResult invoiceInfo (Integer id) {
- return AjaxResult.success(receiptPaymentService.invoiceInfo(id));
- }
-
- /**
- * 鏈湀搴旀敹,鍥炴閲戦
- */
- @GetMapping("/getAmountMouth")
- public AjaxResult getAmountMouth() {
- return AjaxResult.success(receiptPaymentService.getAmountMouth());
- }
-
- /**
- * 鏌ヨ鍥炴璁板綍
- */
- @GetMapping("/receiptPaymentHistoryList")
- public TableDataInfo receiptPaymentHistoryList(ReceiptPaymentDto receiptPaymentDto) {
- startPage();
- List<ReceiptPaymentDto> list = receiptPaymentService.receiptPaymentHistoryList(receiptPaymentDto);
- return getDataTable(list);
- }
-
- /**
- * 鏌ヨ鍥炴璁板綍
- */
- @GetMapping("/receiptPaymentHistoryListPage")
- public IPage<ReceiptPaymentDto> receiptPaymentHistoryListPage(Page page, ReceiptPaymentDto receiptPaymentDto) {
- return receiptPaymentService.receiptPaymentHistoryListPage(page,receiptPaymentDto);
- }
-
- /**
- * 瀵煎嚭鍥炴娴佹按鍒楄〃
- */
- @Log(title = "瀵煎嚭鍥炴娴佹按鍒楄〃", businessType = BusinessType.EXPORT)
- @PostMapping("/exportOne")
- public void exportOne(HttpServletResponse response, ReceiptPaymentDto salesLedgerDto) {
- Page page = new Page();
- page.setCurrent(-1);
- page.setSize(-1);
- IPage<ReceiptPaymentDto> salesLedgerIPage = receiptPaymentHistoryListPage(page, salesLedgerDto);
- ExcelUtil<ReceiptPaymentRecordDto> util = new ExcelUtil<ReceiptPaymentRecordDto>(ReceiptPaymentRecordDto.class);
- List<ReceiptPaymentRecordDto> receiptPaymentRecordDtos = new ArrayList<>();
- salesLedgerIPage.getRecords().forEach(receiptPaymentRecordDto -> {
- ReceiptPaymentRecordDto receiptPaymentRecordDto1 = new ReceiptPaymentRecordDto();
- BeanUtils.copyProperties(receiptPaymentRecordDto, receiptPaymentRecordDto1);
- receiptPaymentRecordDtos.add(receiptPaymentRecordDto1);
- });
- util.exportExcel(response, receiptPaymentRecordDtos, "瀵煎嚭寮�绁ㄧ櫥璁板垪琛�");
- }
-
- /**
- * 鏌ヨ鍥炴璁板綍涓嶅垎椤�
- */
- @GetMapping("/receiptPaymentHistoryListNoPage")
- public List<ReceiptPaymentDto> receiptPaymentHistoryListNoPage(ReceiptPaymentDto receiptPaymentDto) {
- return receiptPaymentService.receiptPaymentHistoryListNoPage(receiptPaymentDto);
- }
-}
diff --git a/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java b/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
index ceb3702..44b8563 100644
--- a/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
+++ b/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
@@ -1,11 +1,11 @@
package com.ruoyi.sales.controller;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.basic.enums.ApplicationTypeEnum;
import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
@@ -13,25 +13,20 @@
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.sales.dto.InvoiceLedgerDto;
import com.ruoyi.sales.dto.SalesLedgerDto;
-import com.ruoyi.sales.mapper.InvoiceLedgerMapper;
-import com.ruoyi.sales.mapper.ReceiptPaymentMapper;
-import com.ruoyi.sales.pojo.ReceiptPayment;
import com.ruoyi.sales.pojo.SalesLedger;
import com.ruoyi.sales.service.ICommonFileService;
import com.ruoyi.sales.service.ISalesLedgerService;
import com.ruoyi.sales.vo.SalesLedgerVo;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import io.swagger.v3.oas.annotations.Operation;
import io.swagger.annotations.ApiParam;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
-import com.ruoyi.basic.utils.FileUtil;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -57,8 +52,6 @@
private ISalesLedgerService salesLedgerService;
private ICommonFileService commonFileService;
- private InvoiceLedgerMapper invoiceLedgerMapper;
- private ReceiptPaymentMapper receiptPaymentMapper;
private final FileUtil fileUtil;
/**
@@ -122,20 +115,6 @@
if(CollectionUtils.isEmpty(list)){
return getDataTable(list);
}
- List<Long> salesLedgerIds = list.stream().map(SalesLedger::getId).collect(Collectors.toList());
- List<InvoiceLedgerDto> invoiceLedgerDtoList = invoiceLedgerMapper.invoicedTotal(salesLedgerIds);
- if(CollectionUtils.isEmpty(invoiceLedgerDtoList)){
- return getDataTable(list);
- }
- for (SalesLedger salesLedger : list) {
- for (InvoiceLedgerDto invoiceLedgerDto : invoiceLedgerDtoList) {
- if (salesLedger.getId().intValue() == invoiceLedgerDto.getSalesLedgerId()) {
- BigDecimal noInvoiceAmountTotal = salesLedger.getContractAmount().subtract(invoiceLedgerDto.getInvoiceTotal());
- salesLedger.setNoInvoiceAmountTotal(noInvoiceAmountTotal);
- }
- }
- }
-
return getDataTable(list);
}
@@ -267,77 +246,29 @@
// 鑾峰彇褰撳墠椤垫墍鏈夊彴璐﹁褰曠殑 ID 闆嗗悎
List<Long> salesLedgerIds = iPage.getRecords().stream().map(SalesLedger::getId).collect(Collectors.toList());
- // 鏌ヨ鍙戠エ淇℃伅鐨勫凡寮�绁ㄩ噾棰�
- List<InvoiceLedgerDto> invoiceLedgerDtoList = invoiceLedgerMapper.invoicedTotal(salesLedgerIds);
- if (CollectionUtils.isEmpty(invoiceLedgerDtoList)) {
- invoiceLedgerDtoList = Collections.emptyList();
- }
- // 杞崲鍙戠エ鏁版嵁, key 涓哄彴璐D, value 涓鸿鍙拌处鐨勬�诲紑绁ㄩ噾棰�
- Map<Long, BigDecimal> invoiceTotals = invoiceLedgerDtoList.stream()
- .filter(dto -> dto.getSalesLedgerId() != null && dto.getInvoiceTotal() != null)
- .collect(Collectors.toMap(
- dto -> dto.getSalesLedgerId().longValue(),
- InvoiceLedgerDto::getInvoiceTotal,
- BigDecimal::add // 瀛樺湪閲嶅ID鎵ц绱姞
- ));
- // 鏌ヨ鍥炴/浠樻璁板綍
- List<ReceiptPayment> receiptPayments = Collections.emptyList();
- if (!CollectionUtils.isEmpty(salesLedgerIds)) {
- receiptPayments = receiptPaymentMapper.selectList(new LambdaQueryWrapper<ReceiptPayment>()
- .in(ReceiptPayment::getSalesLedgerId, salesLedgerIds));
- }
// 杞崲鍥炴鏁版嵁, key 涓哄彴璐D, value 涓鸿鍙拌处鐨勬�诲洖娆鹃噾棰�
Map<Long, BigDecimal> receiptTotals = new HashMap<>();
- if (!CollectionUtils.isEmpty(receiptPayments)) {
- for (ReceiptPayment receiptPayment : receiptPayments) {
- if (receiptPayment.getSalesLedgerId() != null && receiptPayment.getReceiptPaymentAmount() != null) {
- // 濡傛灉 key 瀛樺湪鍒欑浉鍔�,涓嶅瓨鍦ㄥ垯鏀惧叆
- receiptTotals.merge(receiptPayment.getSalesLedgerId(), receiptPayment.getReceiptPaymentAmount(), BigDecimal::add);
- }
- }
- }
+
for (SalesLedgerVo salesLedgerVo : iPage.getRecords()) {
Long ledgerId = salesLedgerVo.getId();
// 鍚堝悓鎬婚噾棰�
BigDecimal contractAmount = salesLedgerVo.getContractAmount() == null ? BigDecimal.ZERO : salesLedgerVo.getContractAmount();
// 寮�绁ㄦ�婚鍜屽洖娆炬�婚
- BigDecimal invoiceTotal = invoiceTotals.getOrDefault(ledgerId, BigDecimal.ZERO);
BigDecimal receiptPaymentAmountTotal = receiptTotals.getOrDefault(ledgerId, BigDecimal.ZERO);
- // 鏈紑绁ㄩ噾棰� = 鍚堝悓閲戦 - 宸插紑绁ㄩ噾棰�
- BigDecimal noInvoiceAmountTotal = contractAmount.subtract(invoiceTotal);
- if (noInvoiceAmountTotal.compareTo(BigDecimal.ZERO) < 0) {
- noInvoiceAmountTotal = BigDecimal.ZERO;
- }
-
- // 寰呭洖娆鹃噾棰� = 宸插紑绁ㄩ噾棰� - 宸插洖娆鹃噾棰�
- BigDecimal noReceiptPaymentAmountTotal = invoiceTotal.subtract(receiptPaymentAmountTotal);
- if (noReceiptPaymentAmountTotal.compareTo(BigDecimal.ZERO) < 0) {
- noReceiptPaymentAmountTotal = BigDecimal.ZERO;
- }
-
- salesLedgerVo.setNoInvoiceAmountTotal(noInvoiceAmountTotal);
- salesLedgerVo.setInvoiceTotal(invoiceTotal);
- salesLedgerVo.setReceiptPaymentAmountTotal(receiptPaymentAmountTotal);
- salesLedgerVo.setNoReceiptAmount(noReceiptPaymentAmountTotal);
-
// 濡傛灉宸茬粡鏈夎繃寮�绁ㄦ垨鍥炴鎿嶄綔,鍒欎笉鍏佽缂栬緫
- boolean hasInvoiceOperation = invoiceTotal.compareTo(BigDecimal.ZERO) > 0;
boolean hasReceiptOperation = receiptPaymentAmountTotal.compareTo(BigDecimal.ZERO) > 0;
- salesLedgerVo.setIsEdit(!(hasInvoiceOperation || hasReceiptOperation));
+ salesLedgerVo.setIsEdit(hasReceiptOperation);
salesLedgerVo.setStorageBlobVOs(fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.FILE, RecordTypeEnum.SALES_LEDGER, ledgerId));
}
if (ObjectUtils.isNotEmpty(salesLedgerDto.getStatus())) {
if (salesLedgerDto.getStatus()) {
- // 娓呴櫎鎵�鏈夆�滄湭寮�绁ㄩ噾棰濃�濅负 0 鐨勮褰�
- iPage.getRecords().removeIf(salesLedger ->
- Objects.equals(salesLedger.getNoInvoiceAmountTotal(), new BigDecimal("0.00")));
iPage.setTotal(iPage.getRecords().size());
}
}
diff --git a/src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java b/src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java
index 9485919..6d45432 100644
--- a/src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java
+++ b/src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java
@@ -1,8 +1,6 @@
package com.ruoyi.sales.controller;
import cn.hutool.core.collection.CollUtil;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
@@ -13,7 +11,6 @@
import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.purchase.dto.SimpleReturnOrderGroupDto;
import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper;
-import com.ruoyi.sales.dto.SalesLedgerProductDto;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.sales.service.ISalesLedgerProductService;
import jakarta.servlet.http.HttpServletResponse;
@@ -43,26 +40,6 @@
/**
- * 鍥炴鐧昏鍒嗛〉鏌ヨ
- */
- @GetMapping("/listPageSalesLedger")
- public AjaxResult listPage(Page page, SalesLedgerProductDto salesLedgerProduct) {
- IPage<SalesLedgerProductDto> list = salesLedgerProductService.listPage(page,salesLedgerProduct);
- return AjaxResult.success(list);
- }
-
-
- /**
- * 浠樻鐧昏鍒嗛〉鏌ヨ
- */
- @GetMapping("/listPagePurchaseLedger")
- public AjaxResult listPagePurchaseLedger(Page page, SalesLedgerProductDto salesLedgerProduct) {
- IPage<SalesLedgerProductDto> list = salesLedgerProductService.listPagePurchaseLedger(page,salesLedgerProduct);
- return AjaxResult.success(list);
- }
-
-
- /**
* 鏌ヨ浜у搧淇℃伅鍒楄〃
*/
@GetMapping("/list")
@@ -76,12 +53,6 @@
Map<Long, BigDecimal> returnOrderGroupDtoMap = groupListByProductIds.stream().collect(Collectors.toMap(SimpleReturnOrderGroupDto::getProductModelId, item -> item.getSumReturnQuantity()));
list.forEach(item -> {
- if (item.getFutureTickets().compareTo(BigDecimal.ZERO) == 0) {
- item.setFutureTickets(BigDecimal.ZERO);
- }
- if (item.getFutureTicketsAmount().compareTo(BigDecimal.ZERO) == 0) {
- item.setFutureTicketsAmount(BigDecimal.ZERO);
- }
if (item.getApproveStatus() != 2) {
if (item.getHasSufficientStock() == 0) {
item.setApproveStatus(0);
diff --git a/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java b/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
index f707b5b..1dbfb65 100644
--- a/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
+++ b/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
@@ -65,12 +65,15 @@
approveProcessVO.setApproveUserIds(req.getApproveUserIds());
approveProcessVO.setApproveUser(loginUser.getUserId());
approveProcessVO.setApproveTime(LocalDate.now().toString());
- approveProcessService.addApprove(approveProcessVO);
- // 娣诲姞鍙戣揣娑堟伅
+ // 鍏堜繚瀛樺彂璐у崟锛屽啀鍙戣捣瀹℃壒锛涙棤瀹℃牳浜鸿嚜鍔ㄩ�氳繃鏃堕渶瑕佹寜鍙戣揣缂栧彿鍥炲啓鍙戣揣鐘舵�併��
req.setShippingNo(sh);
req.setStatus("寰呭鏍�");
boolean save = shippingInfoService.add(req);
- return save ? AjaxResult.success() : AjaxResult.error();
+ if (!save) {
+ return AjaxResult.error();
+ }
+ approveProcessService.addApprove(approveProcessVO);
+ return AjaxResult.success();
}
@Operation(summary = "鍙戣揣鎵e簱瀛�")
diff --git a/src/main/java/com/ruoyi/sales/dto/InvoiceLedgerDto.java b/src/main/java/com/ruoyi/sales/dto/InvoiceLedgerDto.java
deleted file mode 100644
index 8f15d3b..0000000
--- a/src/main/java/com/ruoyi/sales/dto/InvoiceLedgerDto.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.ruoyi.sales.dto;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.common.vo.FileVo;
-import com.ruoyi.sales.pojo.InvoiceLedger;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.Date;
-import java.util.List;
-
-@Data
-public class InvoiceLedgerDto extends InvoiceLedger {
-
- private List<FileVo> fileList;
-
- @Schema(description = "鏌ヨ鏂囨湰")
- private String searchText;
-
- @Schema(description = "瀹㈡埛鍚嶇О")
- private String customerName;
-
- @Schema(description = "瀹㈡埛ID")
- private Integer customerId;
-
- @Schema(description = "瀹㈡埛鍚堝悓鍙�")
- private String customerContractNo;
-
- @Schema(description = "涓氬姟鍛�")
- private String salesman;
-
- @Schema(description = "鍙戠エ鏂囦欢鍚�")
- private String invoiceFileName;
-
- @Schema(description = "鍥炴閲戦")
- private BigDecimal receiptPaymentAmount;
-
- @Schema(description = "鍥炴鏃ユ湡")
- @JsonFormat(pattern = "yyyy-MM-dd")
- private Date receiptPaymentDate;
-
- @Schema(description = "鏈洖娆鹃噾棰�")
- private BigDecimal unReceiptPaymentAmount;
-
- @Schema(description = "绋庣巼")
- private BigDecimal taxRate;
-
- @Schema(description = "閿�鍞悎鍚屽彿")
- private String salesContractNo;
-
- @Schema(description = "閿�鍞悎鍚孖D")
- private Integer salesLedgerId;
-
- private String paymentMethod;
-}
diff --git a/src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationDto.java b/src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationDto.java
deleted file mode 100644
index af7dedc..0000000
--- a/src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationDto.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.ruoyi.sales.dto;
-
-import com.ruoyi.sales.pojo.InvoiceRegistration;
-import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.util.List;
-
-@Data
-public class InvoiceRegistrationDto extends InvoiceRegistration {
-
- @Schema(description = "寮�绁ㄧ櫥璁颁骇鍝侀泦鍚�")
- private List<InvoiceRegistrationProductDto> productDtoList;
-
- @Schema(description = "瀹㈡埛鍚堝悓鍙�")
- private String customerContractNo;
-
- @Schema(description = "瀹㈡埛鍚嶇О")
- private String customerName;
-
- @Schema(description = "鍚堝悓閲戦")
- private BigDecimal contractAmount;
-
- @Schema(description = "鏈紑绁ㄩ噾棰�")
- private BigDecimal noInvoiceAmountTotal;
-
-}
diff --git a/src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationProductDto.java b/src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationProductDto.java
deleted file mode 100644
index 4f94afc..0000000
--- a/src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationProductDto.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.ruoyi.sales.dto;
-
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.common.vo.FileVo;
-import com.ruoyi.sales.pojo.CommonFile;
-import com.ruoyi.sales.pojo.InvoiceLedgerFile;
-import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.util.List;
-
-@Data
-public class InvoiceRegistrationProductDto extends InvoiceRegistrationProduct {
-
- @Schema(description = "瀹㈡埛鍚堝悓鍙�")
- private String customerContractNo;
-
- @Schema(description = "瀹㈡埛鍚嶇О")
- private String customerName;
-
- @Schema(description = "閿�鍞悎鍚屽彿")
- private String salesContractNo;
-
- @Schema(description = "闄勪欢")
- private List<FileVo> fileList;
-
- @Schema(description = "鍙戠エ鍙�")
- private String invoiceNo;
-
- @Schema(description = "鍙戠エ閲戦")
- private BigDecimal invoiceTotal;
-
- @Schema(description = "寮�绁ㄤ汉")
- private String invoicePerson;
-
- @Schema(description = "寮�绁ㄦ椂闂�")
- @JsonFormat(pattern = "yyyy-MM-dd")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- private LocalDate invoiceDate;
-
- @TableField(exist = false)
- private String invoiceDateStart;
- @TableField(exist = false)
- private String invoiceDateEnd;
-
- @Schema(description = "寮�绁ㄥ彴璐d")
- private Integer invoiceLedgerId;
-
- @Schema(description = "鍙戠エ鏂囦欢鍚�")
- private String invoiceFileName;
-
- private List<InvoiceLedgerFile> commonFiles;
-
- private String searchText;
-
- private Boolean status;
-
- private String projectName;
-
-
- @TableField(exist = false)
- private String createTimeStart;
- @TableField(exist = false)
- private String createTimeEnd;
-
-
-}
diff --git a/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentDto.java b/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentDto.java
deleted file mode 100644
index fb2004a..0000000
--- a/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentDto.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package com.ruoyi.sales.dto;
-
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import com.ruoyi.sales.pojo.ReceiptPayment;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.Date;
-
-@Data
-public class ReceiptPaymentDto extends ReceiptPayment {
-
- @Schema(description = "瀹㈡埛鍚堝悓鍙�")
- @Excel(name = "瀹㈡埛鍚堝悓鍙�")
- private String customerContractNo;
-
- @Schema(description = "鐘舵��")
- @Excel(name = "鐘舵��")
- private String statusName;
-
-
- @Schema(description = "瀹㈡埛鍚嶇О")
- @Excel(name = "瀹㈡埛鍚嶇О")
- private String customerName;
-
- @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- @Excel(name = "寮�绁ㄦ棩鏈�",width = 30,dateFormat = "yyyy-MM-dd")
- @Schema(description = "寮�绁ㄦ棩鏈�")
- private Date invoiceDate;
-
- @TableField(exist = false)
- private String invoiceDateStart;
- @TableField(exist = false)
- private String invoiceDateEnd;
-
- @Schema(description = "鏌ヨ鏂囨湰")
- private String searchText;
-
- @Schema(description = "閿�鍞彴璐ales_ledger")
- @Excel(isExport = false)
- private Long salesLedgerId;
-
- @Schema(description = "閿�鍞悎鍚屽彿")
- @Excel(name = "閿�鍞悎鍚屽彿")
- private String salesContractNo;
-
- @Schema(description = "瀹㈡埛鍚嶇ОID")
- @Excel(isExport = false)
- private Integer customerId;
-
- @Schema(description = "鍙戠エ鍙�")
- @Excel(name = "鍙戠エ鍙�")
- private String invoiceNo;
-
- @Schema(description = "鍙戠エ閲戦")
- @Excel(name = "鍙戠エ閲戦")
- private BigDecimal invoiceTotal;
-
- @Schema(description = "绋庣巼锛�%锛�")
- @Excel(name = "绋庣巼锛�%锛�")
- private BigDecimal taxRate;
-
- @Schema(description = "浜у搧澶х被")
- @Excel(name = "浜у搧澶х被")
- private String productCategory;
-
- @Schema(description = "鍥炴閲戦")
- @Excel(name = "鍥炴閲戦")
- private BigDecimal receiptPaymentAmountTotal;
-
- @Schema(description = "寰呭洖娆鹃噾棰�")
- @Excel(name = "寰呭洖娆鹃噾棰�")
- private BigDecimal noReceiptAmount;
-
- @TableField(exist = false)
- @Excel(isExport = false)
- private Boolean status;
-
- @TableField(exist = false)
- @Excel(isExport = false)
- private String receiptPaymentDateStart;
- @TableField(exist = false)
- @Excel(isExport = false)
- private String receiptPaymentDateEnd;
-
- @Schema(description = "椤圭洰鍚嶇О")
- @Excel(name = "椤圭洰鍚嶇О")
- private String projectName;
-
-
-}
diff --git a/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentExeclDto.java b/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentExeclDto.java
deleted file mode 100644
index 4212961..0000000
--- a/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentExeclDto.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.ruoyi.sales.dto;
-
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.math.BigDecimal;
-
-@Data
-public class ReceiptPaymentExeclDto {
-
- @Schema(description = "閿�鍞悎鍚屽彿")
- @Excel(name = "閿�鍞悎鍚屽彿",sort = 1)
- private String salesContractNo;
-
- @Schema(description = "瀹㈡埛鍚堝悓鍙�")
- @Excel(name = "瀹㈡埛鍚堝悓鍙�",sort = 2)
-
- private String customerContractNo;
-
- @Schema(description = "瀹㈡埛鍚嶇О")
- @Excel(name = "瀹㈡埛鍚嶇О",sort = 3)
- private String customerName;
-
- @Schema(description = "浜у搧澶х被")
- @Excel(name = "浜у搧澶х被",sort = 4)
- private String productCategory;
-
- @Schema(description = "椤圭洰鍚嶇О")
- @Excel(name = "椤圭洰鍚嶇О",sort = 5)
- private String projectName;
-
- @Schema(description = "鍙戠エ鍙�")
- @Excel(name = "鍙戠エ鍙�",sort = 6)
- private String invoiceNo;
-
- @Schema(description = "鍙戠エ閲戦")
- @Excel(name = "鍙戠エ閲戦",sort = 7)
- private BigDecimal invoiceTotal;
-
- @Schema(description = "绋庣巼锛�%锛�")
- @Excel(name = "绋庣巼锛�%锛�",sort = 8)
- private BigDecimal taxRate;
-
- @Schema(description = "鍥炴閲戦")
- @Excel(name = "鍥炴閲戦",sort = 9)
- private BigDecimal receiptPaymentAmountTotal;
-
- @Schema(description = "寰呭洖娆鹃噾棰�")
- @Excel(name = "寰呭洖娆鹃噾棰�",sort = 10)
- private BigDecimal noReceiptAmount;
-
-
-
-
-}
diff --git a/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentRecordDto.java b/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentRecordDto.java
deleted file mode 100644
index c2410e8..0000000
--- a/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentRecordDto.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.ruoyi.sales.dto;
-
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.util.Date;
-
-/**
- * @author :yys
- * @date : 2025/10/31 10:17
- */
-@Data
-public class ReceiptPaymentRecordDto {
-
- @Schema(description = "瀹㈡埛鍚堝悓鍙�")
- @Excel(name = "瀹㈡埛鍚堝悓鍙�")
- private String customerContractNo;
-
- @Schema(description = "瀹㈡埛鍚嶇О")
- @Excel(name = "瀹㈡埛鍚嶇О")
- private String customerName;
-
- @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- @Excel(name = "鐧昏鏃ユ湡",width = 30,dateFormat = "yyyy-MM-dd")
- @Schema(description = "鐧昏鏃ユ湡")
- private LocalDateTime createTime;
-
- @Schema(description = "閿�鍞悎鍚屽彿")
- @Excel(name = "閿�鍞悎鍚屽彿")
- private String salesContractNo;
-
- @Schema(description = "鍥炴閲戦")
- @Excel(name = "鍥炴閲戦")
- private BigDecimal receiptPaymentAmount;
-
- @Schema(description = "椤圭洰鍚嶇О")
- @Excel(name = "椤圭洰鍚嶇О")
- private String projectName;
-
- @Schema(description = "鍥炴褰㈠紡 0鐢垫眹1鎵垮厬")
- @Excel(name = "鍥炴褰㈠紡",readConverterExp = "0=鐢垫眹,1=鎵垮厬")
- private String receiptPaymentType;
-
- @Schema(description = "鐧昏浜�")
- @Excel(name = "鐧昏浜�")
- private String registrant;
-
- @Schema(description = "鏉ユ鏃ユ湡")
- @JsonFormat(pattern = "yyyy-MM-dd")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- @Excel(name = "鏉ユ鏃ユ湡",width = 30,dateFormat = "yyyy-MM-dd")
- private LocalDate receiptPaymentDate;
-
-}
diff --git a/src/main/java/com/ruoyi/sales/dto/SalesLedgerImportDto.java b/src/main/java/com/ruoyi/sales/dto/SalesLedgerImportDto.java
index 2430d10..0023e17 100644
--- a/src/main/java/com/ruoyi/sales/dto/SalesLedgerImportDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/SalesLedgerImportDto.java
@@ -43,6 +43,10 @@
@Excel(name = "绛捐鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
private Date executionDate;
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @Excel(name = "浜や粯鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
+ private Date deliveryDate;
+
@Schema(description = "浠樻鏂瑰紡")
@Excel(name = "浠樻鏂瑰紡")
private String paymentMethod;
diff --git a/src/main/java/com/ruoyi/sales/dto/SalesLedgerProductImportDto.java b/src/main/java/com/ruoyi/sales/dto/SalesLedgerProductImportDto.java
index 2c95909..9f05b60 100644
--- a/src/main/java/com/ruoyi/sales/dto/SalesLedgerProductImportDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/SalesLedgerProductImportDto.java
@@ -73,6 +73,9 @@
@Excel(name = "鏄惁璐ㄦ", readConverterExp = "0=鍚�,1=鏄�")
private Boolean isChecked;
-
-
+ /**
+ * 鏄惁鐢熶骇
+ */
+ @Excel(name = "鏄惁鐢熶骇", readConverterExp = "0=鍚�,1=鏄�")
+ private Integer isProduction;
}
diff --git a/src/main/java/com/ruoyi/sales/dto/SalesQuotationDto.java b/src/main/java/com/ruoyi/sales/dto/SalesQuotationDto.java
index 4841ffd..4b20ff8 100644
--- a/src/main/java/com/ruoyi/sales/dto/SalesQuotationDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/SalesQuotationDto.java
@@ -17,4 +17,6 @@
*/
// 瀹℃壒浜�
private String approveUserIds;
+
+ private Long templateId;
}
diff --git a/src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java b/src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java
index 43409bc..724473a 100644
--- a/src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java
@@ -47,5 +47,9 @@
//鍙戣揣鏁伴噺
private BigDecimal totalQuantity;
+ private Long templateId;
+
+ private String templateName;
+
}
diff --git a/src/main/java/com/ruoyi/sales/excel/InvoiceLedgerExcelDto.java b/src/main/java/com/ruoyi/sales/excel/InvoiceLedgerExcelDto.java
index b5d09a7..82da2a9 100644
--- a/src/main/java/com/ruoyi/sales/excel/InvoiceLedgerExcelDto.java
+++ b/src/main/java/com/ruoyi/sales/excel/InvoiceLedgerExcelDto.java
@@ -1,19 +1,12 @@
package com.ruoyi.sales.excel;
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.common.vo.FileVo;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import com.ruoyi.sales.pojo.InvoiceLedger;
-import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.util.List;
@Data
public class InvoiceLedgerExcelDto {
diff --git a/src/main/java/com/ruoyi/sales/excel/InvoiceRegisAndProductExcelDto.java b/src/main/java/com/ruoyi/sales/excel/InvoiceRegisAndProductExcelDto.java
deleted file mode 100644
index 8979504..0000000
--- a/src/main/java/com/ruoyi/sales/excel/InvoiceRegisAndProductExcelDto.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.ruoyi.sales.excel;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-@Data
-public class InvoiceRegisAndProductExcelDto {
-
- @Excel(name = "閿�鍞悎鍚屽彿")
- private String salesContractNo;
-
- @Excel(name = "瀹㈡埛鍚堝悓鍙�")
- private String customerContractNo;
-
- @Excel(name = "瀹㈡埛鍚嶇О")
- private String customerName;
-
- @Excel(name = "涓氬姟鍛�")
- private String salesman;
-
- @Excel(name = "椤圭洰鍚嶇О")
- private String projectName;
-
- @Excel(name = "鍚堝悓閲戦")
- private BigDecimal contractAmount;
-
- @Excel(name = "浜у搧澶х被")
- private String productCategory;
-
- @Excel(name = "瑙勬牸鍨嬪彿")
- private String specificationModel;
-
- @Excel(name = "鍗曚綅")
- private String unit;
-
- @Excel(name = "鏁伴噺")
- private BigDecimal quantity;
-
- @Excel(name = "绋庣巼%")
- private BigDecimal taxRate;
-
- @Excel(name = "鍚◣鍗曚环")
- private BigDecimal taxInclusiveUnitPrice;
-
- @Excel(name = "鍚◣鎬讳环")
- private BigDecimal taxInclusiveTotalPrice;
-
- @Excel(name ="涓嶅惈绋庢�讳环")
- private BigDecimal taxExclusiveTotalPrice;
-
- @Excel(name ="鍙戠エ绫诲瀷")
- private String invoiceType;
-
- @Excel(name ="寮�绁ㄦ暟")
- private Integer invoiceNum;
-
- @Excel(name ="鏈紑绁ㄦ暟")
- private Integer noInvoiceNum;
-
- @Excel(name ="寮�绁ㄩ噾棰�")
- private BigDecimal invoiceAmount;
-
- @Excel(name ="鏈紑绁ㄩ噾棰�")
- private BigDecimal noInvoiceAmount;
-
-
-}
diff --git a/src/main/java/com/ruoyi/sales/mapper/InvoiceLedgerFileMapper.java b/src/main/java/com/ruoyi/sales/mapper/InvoiceLedgerFileMapper.java
deleted file mode 100644
index b8c0b4c..0000000
--- a/src/main/java/com/ruoyi/sales/mapper/InvoiceLedgerFileMapper.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.ruoyi.sales.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.ruoyi.sales.pojo.InvoiceLedger;
-import com.ruoyi.sales.pojo.InvoiceLedgerFile;
-
-public interface InvoiceLedgerFileMapper extends BaseMapper<InvoiceLedgerFile> {
-}
diff --git a/src/main/java/com/ruoyi/sales/mapper/InvoiceLedgerMapper.java b/src/main/java/com/ruoyi/sales/mapper/InvoiceLedgerMapper.java
deleted file mode 100644
index a797024..0000000
--- a/src/main/java/com/ruoyi/sales/mapper/InvoiceLedgerMapper.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.ruoyi.sales.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.sales.dto.InvoiceLedgerDto;
-import com.ruoyi.sales.dto.InvoiceRegistrationProductDto;
-import com.ruoyi.sales.pojo.InvoiceLedger;
-import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-public interface InvoiceLedgerMapper extends BaseMapper<InvoiceLedger> {
-
- /**
- * 寮�绁ㄥ彴璐﹀垎椤垫煡璇�
- * @param page
- * @param invoiceLedgerDto
- * @return
- */
- IPage<InvoiceLedgerDto> invoiceLedgerPage(Page page, @Param("invoiceLedgerDto") InvoiceLedgerDto invoiceLedgerDto);
-
- /**
- * 寮�绁ㄥ彴璐︽煡璇�
- * @param invoiceLedgerDto
- * @return
- */
- List<InvoiceLedgerDto> invoiceLedgerList(@Param("invoiceLedgerDto") InvoiceLedgerDto invoiceLedgerDto);
-
- /**
- * 寮�绁ㄥ彴璐﹁鎯�
- * @param id
- * @return
- */
- InvoiceLedgerDto invoiceLedgerInfo(Integer id);
-
- /**
- * 瀹㈡埛閿�鍞褰�
- * @param page
- * @param invoiceLedgerDto
- * @return
- */
- IPage<InvoiceLedgerDto> invoiceLedgerSalesAccount(Page page,@Param("invoiceLedgerDto") InvoiceLedgerDto invoiceLedgerDto);
-
- /**
- * 浜у搧寮�绁ㄥ彴璐﹁鎯�
- * @param id
- * @return
- */
- InvoiceRegistrationProductDto invoiceLedgerProductInfo(Integer id);
-
- /**
- * 鏍规嵁閿�鍞悎鍚岃绠楀凡寮�绁ㄩ噾棰�
- * @param salesLedgerIds
- * @return
- */
- List<InvoiceLedgerDto> invoicedTotal(List<Long> salesLedgerIds);
-
-}
diff --git a/src/main/java/com/ruoyi/sales/mapper/InvoiceRegistrationMapper.java b/src/main/java/com/ruoyi/sales/mapper/InvoiceRegistrationMapper.java
deleted file mode 100644
index 54425c4..0000000
--- a/src/main/java/com/ruoyi/sales/mapper/InvoiceRegistrationMapper.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.ruoyi.sales.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.sales.dto.InvoiceRegistrationDto;
-import com.ruoyi.sales.excel.InvoiceRegisAndProductExcelDto;
-import com.ruoyi.sales.pojo.InvoiceRegistration;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-public interface InvoiceRegistrationMapper extends BaseMapper<InvoiceRegistration> {
-
- /**
- * 寮�绁ㄧ櫥璁板垎椤垫煡璇�
- * @param page
- * @param invoiceRegistrationDto
- * @return
- */
- IPage<InvoiceRegistrationDto> invoiceRegistrationListPage(Page page, @Param("invoiceRegistrationDto") InvoiceRegistrationDto invoiceRegistrationDto);
-
- /**
- * 寮�绁ㄧ櫥璁板鍑烘暟鎹煡璇�
- * @return
- */
- List<InvoiceRegisAndProductExcelDto> invoiceRegisAndProductExcelDtoList();
-}
diff --git a/src/main/java/com/ruoyi/sales/mapper/InvoiceRegistrationProductMapper.java b/src/main/java/com/ruoyi/sales/mapper/InvoiceRegistrationProductMapper.java
deleted file mode 100644
index 1c1ae7a..0000000
--- a/src/main/java/com/ruoyi/sales/mapper/InvoiceRegistrationProductMapper.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.ruoyi.sales.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.sales.dto.InvoiceRegistrationProductDto;
-import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-public interface InvoiceRegistrationProductMapper extends BaseMapper<InvoiceRegistrationProduct> {
-
- /**
- * 寮�绁ㄧ櫥璁颁骇鍝佹煡璇�
- * @param invoiceRegistrationProductDto
- * @return
- */
- List<InvoiceRegistrationProductDto> invoiceRegistrationProductList(@Param("invoiceRegistrationProductDto") InvoiceRegistrationProductDto invoiceRegistrationProductDto);
-
- /**
- * 寮�绁ㄧ櫥璁颁骇鍝佸垎椤垫煡璇�
- * @param page
- * @param invoiceRegistrationProductDto
- * @return
- */
- IPage<InvoiceRegistrationProductDto> invoiceRegistrationProductPage(Page page, @Param("invoiceRegistrationProductDto") InvoiceRegistrationProductDto invoiceRegistrationProductDto);
-}
diff --git a/src/main/java/com/ruoyi/sales/mapper/ReceiptPaymentMapper.java b/src/main/java/com/ruoyi/sales/mapper/ReceiptPaymentMapper.java
deleted file mode 100644
index 576ebd7..0000000
--- a/src/main/java/com/ruoyi/sales/mapper/ReceiptPaymentMapper.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.ruoyi.sales.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.sales.dto.CustomerInteractionDto;
-import com.ruoyi.sales.dto.InvoiceLedgerDto;
-import com.ruoyi.sales.dto.ReceiptPaymentDto;
-import com.ruoyi.sales.dto.ReceiptPaymentExeclDto;
-import com.ruoyi.sales.pojo.ReceiptPayment;
-import org.apache.ibatis.annotations.Param;
-
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.List;
-
-public interface ReceiptPaymentMapper extends BaseMapper<ReceiptPayment> {
-
- IPage<ReceiptPaymentDto> receiptPaymentListPage(Page page, @Param("receiptPaymentDto") ReceiptPaymentDto receiptPaymentDto);
-
- ReceiptPaymentDto receiptPaymentInfo(Integer id);
-
- /**
- * 鏌ヨ宸茬粡缁戝畾鍙戠エ鐨勫紑绁ㄥ彴璐�
- * @param page
- * @param receiptPaymentDto
- * @return
- */
- IPage<ReceiptPaymentDto> bindInvoiceNoRegPage(Page page, @Param("req") ReceiptPaymentDto receiptPaymentDto);
-
- /**
- * 寮�绁ㄥ彴璐﹁鎯�
- * @param id
- * @return
- */
- InvoiceLedgerDto invoiceInfo(Integer id);
-
- /**
- * 璁$畻鍓嶅灏戞潯鏁版嵁鍥炴閲戦缁煎悎
- * @param customerId
- * @param total
- * @return
- */
- BigDecimal getReceiptAmount(@Param("customerId") Integer customerId, @Param("total") long total);
-
- /**
- * 鏌ヨ鍥炴璁板綍
- */
- List<ReceiptPaymentDto> receiptPaymentHistoryList(@Param("params") ReceiptPaymentDto receiptPaymentDto);
-
- /**
- * 鏌ヨ鍥炴璁板綍鍒嗛〉
- */
- IPage<ReceiptPaymentDto> receiptPaymentHistoryListPage(Page page,@Param("params") ReceiptPaymentDto receiptPaymentDto);
-
- /**
- * 瀹㈡埛寰�鏉ヨ褰曟煡璇�
- * @param receiptPaymentDto
- * @return
- */
- List<CustomerInteractionDto> customerInteractions (ReceiptPaymentDto receiptPaymentDto);
-
- /**
- * 瀹㈡埛鍥炴璁板綍鏌ヨ
- * @param invoiceLedgerDto
- * @return
- */
- List<InvoiceLedgerDto> invoiceLedgerSalesAccount(@Param("invoiceLedgerDto") InvoiceLedgerDto invoiceLedgerDto);
-
- /**
- * 鏌ヨ鍥炴璁板綍涓嶅垎椤�
- */
- List<ReceiptPaymentDto> receiptPaymentHistoryListNoPage( @Param("params") ReceiptPaymentDto receiptPaymentDto);
-
- /**
- * 閫氳繃寮�绁ㄧ櫥璁颁骇鍝乮d鏌ヨ鏄惁宸茬粡鏈夊洖娆捐褰�
- * @param invoiceRegistrationProductId
- * @return
- */
- List<ReceiptPayment> receiptPaymentListByProdRegId(Integer invoiceRegistrationProductId);
-
- List<ReceiptPaymentDto> bindInvoiceNoRegListAll();
-
- List<ReceiptPaymentExeclDto> bindInvoiceNoRegListByIds(List<Long> ids,Long tenantId);
-
-
-}
diff --git a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java
index 9f49265..5518290 100644
--- a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java
+++ b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java
@@ -6,6 +6,7 @@
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.home.dto.IncomeExpenseAnalysisDto;
+import com.ruoyi.purchase.vo.PurchaseReportVo;
import com.ruoyi.sales.dto.SalesLedgerDto;
import com.ruoyi.sales.dto.SalesTrendDto;
import com.ruoyi.sales.dto.StatisticsTableDto;
@@ -86,4 +87,7 @@
List<SalesTrendDto> statisticsTable(@Param("statisticsTableDto")StatisticsTableDto statisticsTableDto);
IPage<SalesLedgerDto> listSalesLedgerAndShipped(Page page, @Param("ew") SalesLedgerDto salesLedgerDto);
+
+ IPage<PurchaseReportVo> selectPurchaseReportVoPage(Page page, @Param("customerName") String customerName);
+
}
diff --git a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
index f8e22b9..2615d19 100644
--- a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
+++ b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
@@ -5,7 +5,6 @@
import com.ruoyi.common.config.MyBaseMapper;
import com.ruoyi.purchase.dto.ProcurementBusinessSummaryDto;
import com.ruoyi.sales.dto.LossProductModelDto;
-import com.ruoyi.sales.dto.SalesLedgerProductDto;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import org.apache.ibatis.annotations.Param;
@@ -26,10 +25,6 @@
List<SalesLedgerProduct> selectSalesLedgerProductList(@Param("salesLedgerProduct") SalesLedgerProduct salesLedgerProduct);
SalesLedgerProduct selectSalesLedgerProductByMainId(@Param("productMainId") Long productMainId);
-
- IPage<SalesLedgerProductDto> listPage(Page page, @Param("req") SalesLedgerProductDto salesLedgerProduct);
-
- IPage<SalesLedgerProductDto> listPagePurchaseLedger(Page page, @Param("req") SalesLedgerProductDto salesLedgerProduct);
IPage<ProcurementBusinessSummaryDto> procurementBusinessSummaryListPage(Page page, @Param("req") ProcurementBusinessSummaryDto procurementBusinessSummaryDto);
diff --git a/src/main/java/com/ruoyi/sales/pojo/InvoiceLedger.java b/src/main/java/com/ruoyi/sales/pojo/InvoiceLedger.java
deleted file mode 100644
index ef85b3a..0000000
--- a/src/main/java/com/ruoyi/sales/pojo/InvoiceLedger.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.ruoyi.sales.pojo;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-
-@Data
-public class InvoiceLedger {
-
- /**
- * 搴忓彿
- */
- @TableId(type = IdType.AUTO)
- private Integer id;
-
- @Schema(description = "invoice_registration_product琛ㄤ富閿�")
- private Integer invoiceRegistrationProductId;
-
- @Schema(description = "鍙戠エ鍙�")
- private String invoiceNo;
-
- @Schema(description = "鍙戠エ閲戦")
- private BigDecimal invoiceTotal;
-
- @Schema(description = "寮�绁ㄤ汉")
- private String invoicePerson;
-
- @Schema(description = "寮�绁ㄦ椂闂�")
- @JsonFormat(pattern = "yyyy-MM-dd")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- private LocalDate invoiceDate;
-
- @Schema(description = "鍒涘缓鏃堕棿")
- @TableField(fill = FieldFill.INSERT)
- private LocalDateTime createTime;
-
- @Schema(description = "鍒涘缓鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT)
- private Integer createUser;
-
- @Schema(description = "淇敼鏃堕棿")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private LocalDateTime updateTime;
-
- @Schema(description = "淇敼鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private Integer updateUser;
-
- @Schema(description = "绉熸埛ID")
- @TableField(fill = FieldFill.INSERT)
- private Long tenantId;
-
-
- @TableField(fill = FieldFill.INSERT)
- private Long deptId;
-}
diff --git a/src/main/java/com/ruoyi/sales/pojo/InvoiceLedgerFile.java b/src/main/java/com/ruoyi/sales/pojo/InvoiceLedgerFile.java
deleted file mode 100644
index 0d4a4f5..0000000
--- a/src/main/java/com/ruoyi/sales/pojo/InvoiceLedgerFile.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.ruoyi.sales.pojo;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.TableField;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-@Data
-public class InvoiceLedgerFile {
-
- @Schema(description = "鏂囦欢ID")
- private Long id;
-
- @Schema(description = "鏂囦欢鍚嶇О")
- private String name;
-
- @Schema(description = "鏂囦欢璺緞")
- private String url;
-
- @Schema(description = "鏂囦欢澶у皬")
- private int fileSize;
-
- @Schema(description = "寮�绁ㄥ彴璐D")
- private Integer invoiceLedgerId;
-
- @Schema(description = "鍒涘缓鏃堕棿")
- @TableField(fill = FieldFill.INSERT)
- private LocalDateTime createTime;
-
- @Schema(description = "淇敼鏃堕棿")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private LocalDateTime updateTime;
-
- @Schema(description = "鍒涘缓鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT)
- private Integer createUser;
-
- @Schema(description = "淇敼鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private Integer updateUser;
-
- @Schema(description = "绉熸埛ID")
- @TableField(fill = FieldFill.INSERT)
- private Long tenantId;
-
- @TableField(fill = FieldFill.INSERT)
- private Long deptId;
-}
diff --git a/src/main/java/com/ruoyi/sales/pojo/InvoiceRegistration.java b/src/main/java/com/ruoyi/sales/pojo/InvoiceRegistration.java
deleted file mode 100644
index e7a926b..0000000
--- a/src/main/java/com/ruoyi/sales/pojo/InvoiceRegistration.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.ruoyi.sales.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-@Data
-@TableName("invoice_registration")
-public class InvoiceRegistration {
-
- /**
- * 搴忓彿
- */
- @TableId(type = IdType.AUTO)
- private Integer id;
-
- @Schema(description = "閿�鍞彴璐ales_ledger涓婚敭")
- private Integer salesLedgerId;
-
- @Schema(description = "閿�鍞悎鍚屽彿")
- private String salesContractNo;
-
- @Schema(description = "瀹㈡埛鍚嶇ОID")
- private Integer customerId;
-
- @Schema(description = "涓氬姟鍛�")
- private String salesman;
-
- @Schema(description = "椤圭洰鍚嶇О")
- private String projectName;
-
- @Schema(description = "鍒涘缓鏃堕棿")
- @TableField(fill = FieldFill.INSERT)
- private LocalDateTime createTime;
-
- @Schema(description = "鍒涘缓鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT)
- private Integer createUser;
-
- @Schema(description = "淇敼鏃堕棿")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private LocalDateTime updateTime;
-
- @Schema(description = "淇敼鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private Integer updateUser;
-
- @Schema(description = "绉熸埛ID")
- @TableField(fill = FieldFill.INSERT)
- private Long tenantId;
-
- @TableField(fill = FieldFill.INSERT)
- private Long deptId;
-}
diff --git a/src/main/java/com/ruoyi/sales/pojo/InvoiceRegistrationProduct.java b/src/main/java/com/ruoyi/sales/pojo/InvoiceRegistrationProduct.java
deleted file mode 100644
index 75ef549..0000000
--- a/src/main/java/com/ruoyi/sales/pojo/InvoiceRegistrationProduct.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package com.ruoyi.sales.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-@TableName("invoice_registration_product")
-@Data
-public class InvoiceRegistrationProduct {
-
- /**
- * 搴忓彿
- */
- @TableId(type = IdType.AUTO)
- private Integer id;
-
- @Schema(description = "鍏宠仈閿�鍞彴璐︿富琛ㄤ富閿�")
- private Integer salesLedgerId;
-
- @Schema(description = "sales_ledger_product涓婚敭")
- private Integer salesLedgerProductId;
-
- @Schema(description = "寮�绁ㄧ櫥璁拌〃invoice_registration涓婚敭")
- private Integer invoiceRegistrationId;
-
- @Schema(description = "浜у搧澶х被")
- private String productCategory;
-
- @Schema(description = "瑙勬牸鍨嬪彿")
- private String specificationModel;
-
- @Schema(description = "鍗曚綅")
- private String unit;
-
- @Schema(description = "鏁伴噺")
- private BigDecimal quantity;
-
- @Schema(description = "绋庣巼")
- private BigDecimal taxRate;
-
- @Schema(description = "鍚◣鍗曚环")
- private BigDecimal taxInclusiveUnitPrice;
-
- @Schema(description = "鍚◣鎬讳环")
- private BigDecimal taxInclusiveTotalPrice;
-
- @Schema(description = "涓嶅惈绋庢�讳环")
- private BigDecimal taxExclusiveTotalPrice;
-
- @Schema(description = "鍙戠エ绫诲瀷")
- private String invoiceType;
-
- @Schema(description = "寮�绁ㄦ暟")
- private BigDecimal invoiceNum;
-
- @Schema(description = "鏈紑绁ㄦ暟")
- private BigDecimal noInvoiceNum;
-
- @Schema(description = "寮�绁ㄩ噾棰�")
- private BigDecimal invoiceAmount;
-
- @Schema(description = "鏈紑绁ㄩ噾棰�")
- private BigDecimal noInvoiceAmount;
-
- @Schema(description = "鍒涘缓鏃堕棿")
- @TableField(fill = FieldFill.INSERT)
- private LocalDateTime createTime;
-
- @Schema(description = "鍒涘缓鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT)
- private Integer createUser;
-
- @Schema(description = "淇敼鏃堕棿")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private LocalDateTime updateTime;
-
- @Schema(description = "淇敼鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private Integer updateUser;
-
- @Schema(description = "绉熸埛ID")
- @TableField(fill = FieldFill.INSERT)
- private Long tenantId;
-
- @TableField(fill = FieldFill.INSERT)
- private Long deptId;
-}
diff --git a/src/main/java/com/ruoyi/sales/pojo/ReceiptPayment.java b/src/main/java/com/ruoyi/sales/pojo/ReceiptPayment.java
deleted file mode 100644
index 132bfa2..0000000
--- a/src/main/java/com/ruoyi/sales/pojo/ReceiptPayment.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.ruoyi.sales.pojo;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.util.List;
-
-@Data
-public class ReceiptPayment {
-
- /**
- * 搴忓彿
- */
- @TableId(type = IdType.AUTO)
- private Integer id;
-
- @Schema(description = "鍥炴褰㈠紡 0鐢垫眹1鎵垮厬")
- private String receiptPaymentType;
-
- @Schema(description = "鍥炴閲戦")
- private BigDecimal receiptPaymentAmount;
-
- @Schema(description = "鐧昏浜�")
- private String registrant;
-
- @Schema(description = "invoice_ledger寮�绁ㄥ彴璐︿富閿甀D")
- private Integer invoiceLedgerId;
-
- @Schema(description = "sales_ledger閿�鍞彴璐︿富閿甀D")
- private Long salesLedgerId;
-
- @Schema(description = "sales_ledger_product閿�鍞彴璐︿骇鍝佷富閿甀D")
- private Long salesLedgerProductId;
-
- @Schema(description = "鏉ユ鏃ユ湡")
- @JsonFormat(pattern = "yyyy-MM-dd")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- private LocalDate receiptPaymentDate;
-
- @Schema(description = "鍒涘缓鏃堕棿")
- @TableField(fill = FieldFill.INSERT)
- @JsonFormat(pattern = "yyyy-MM-dd")
- private LocalDateTime createTime;
-
- @Schema(description = "鍒涘缓鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT)
- private Integer createUser;
-
- @Schema(description = "淇敼鏃堕棿")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private LocalDateTime updateTime;
-
- @Schema(description = "淇敼鐢ㄦ埛")
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private Integer updateUser;
-
- @Schema(description = "绉熸埛ID")
- @TableField(fill = FieldFill.INSERT)
- private Long tenantId;
-
-
- @TableField(fill = FieldFill.INSERT)
- private Long deptId;
-}
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
index bc4d02c..00736ba 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
@@ -1,15 +1,15 @@
package com.ruoyi.sales.pojo;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.Date;
-
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.Date;
/**
* 閿�鍞彴璐﹀璞� sales_ledger
@@ -103,26 +103,8 @@
@Excel(name = "鍚堝悓閲戦")
private BigDecimal contractAmount;
- @TableField(exist = false)
- @Schema(description = "鏈紑绁ㄩ噾棰�(鍏�)")
- @Excel(name = "鏈紑绁ㄩ噾棰�")
- private BigDecimal noInvoiceAmountTotal = BigDecimal.ZERO;
-
@Schema(description = "绛捐鏃ユ湡")
private LocalDate executionDate;
-
- @TableField(exist = false)
- @Schema(description = "宸插紑绁ㄩ噾棰�(鍏�)")
- @Excel(name = "宸插紑绁ㄩ噾棰�")
- private BigDecimal invoiceTotal = BigDecimal.ZERO;
-
- @TableField(exist = false)
- @Schema(description = "鍥炴閲戦")
- private BigDecimal receiptPaymentAmountTotal = BigDecimal.ZERO;
-
- @TableField(exist = false)
- @Schema(description = "寰呭洖娆鹃噾棰�")
- private BigDecimal noReceiptAmount = BigDecimal.ZERO;
@Schema(description = "浠樻鏂瑰紡")
private String paymentMethod;
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
index fa528a9..f4a42d6 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
@@ -62,12 +62,6 @@
private String unit;
/**
- * 鐢熶骇鐐掓満
- */
- @Excel(name = "鐢熶骇鐐掓満")
- private String speculativeTradingName;
-
- /**
* 鏁伴噺
*/
@Excel(name = "鏁伴噺")
@@ -110,46 +104,6 @@
private Integer type;
/**
- * 鏈鏉ョエ鏁�
- */
- private BigDecimal ticketsNum=BigDecimal.ZERO;
-
- /**
- * 鏈鏉ョエ閲戦(鍏�)
- */
- private BigDecimal ticketsAmount=BigDecimal.ZERO;
-
- /**
- * 鏈潵绁ㄦ暟
- */
- private BigDecimal futureTickets=BigDecimal.ZERO;
-
- /**
- * 鏈潵绁ㄩ噾棰�(鍏�)
- */
- private BigDecimal futureTicketsAmount=BigDecimal.ZERO;
-
- @Schema(description = "寮�绁ㄦ暟")
- private BigDecimal invoiceNum = BigDecimal.ZERO;
-
- @Schema(description = "鏈紑绁ㄦ暟")
- private BigDecimal noInvoiceNum = BigDecimal.ZERO;
-
- @Schema(description = "寮�绁ㄩ噾棰�")
- private BigDecimal invoiceAmount = BigDecimal.ZERO;
-
- @Schema(description = "鏈紑绁ㄩ噾棰�")
- private BigDecimal noInvoiceAmount = BigDecimal.ZERO;
-
- @Schema(description = "鏈寮�绁ㄦ暟")
- @TableField(exist = false)
- private BigDecimal currentInvoiceNum;
-
- @TableField(exist = false)
- @Schema(description = "鏈寮�绁ㄩ噾棰�")
- private BigDecimal currentInvoiceAmount;
-
- /**
* 浜у搧id
*/
private Long productId;
@@ -158,26 +112,6 @@
* 浜у搧瑙勬牸id
*/
private Long productModelId;
-
- @Schema(description = "鍒濆鏈紑绁ㄦ暟")
- @TableField(exist = false)
- private BigDecimal originalNoInvoiceNum;
-
- @Schema(description = "涓存椂鏈紑绁ㄦ暟")
- @TableField(exist = false)
- private BigDecimal tempNoInvoiceNum;
-
- @Schema(description = "涓存椂鏈紑绁ㄩ噾棰�")
- @TableField(exist = false)
- private BigDecimal tempnoInvoiceAmount;
-
- @Schema(description = "涓存椂鏈潵绁ㄦ暟")
- @TableField(exist = false)
- private BigDecimal tempFutureTickets;
-
- @Schema(description = "涓存椂鏈潵绁ㄩ噾棰�")
- @TableField(exist = false)
- private BigDecimal tempFutureTicketsAmount;
@Schema(description = "鐧昏浜�")
private String register;
@@ -215,21 +149,13 @@
/**
* 浜у搧鐘舵��
*/
+ @TableField(exist = false)
+ @Schema(description = "鍏ュ簱瀹℃牳鐘舵��")
+ private String stockInApprovalStatus;
+
// @TableField(exist = false)
@Schema(description = "浜у搧鐘舵�侊細1-鍏呰冻")
private Integer approveStatus;
-
- @Schema(description = "寰呭洖娆炬�婚噾棰�")
- private BigDecimal pendingInvoiceTotal;
-
- @Schema(description = "鍥炴鎬婚噾棰�")
- private BigDecimal invoiceTotal = BigDecimal.ZERO;
-
- @Schema(description = "寰呬粯娆炬�婚噾棰�")
- private BigDecimal pendingTicketsTotal;
-
- @Schema(description = "浠樻鎬婚噾棰�")
- private BigDecimal ticketsTotal = BigDecimal.ZERO;
@Schema(description = "鏄惁璐ㄦ")
//閽堝閲囪喘鍙拌处锛屾槸鍚﹁川妫�
diff --git a/src/main/java/com/ruoyi/sales/service/ISalesLedgerProductService.java b/src/main/java/com/ruoyi/sales/service/ISalesLedgerProductService.java
index 47e0616..00fc350 100644
--- a/src/main/java/com/ruoyi/sales/service/ISalesLedgerProductService.java
+++ b/src/main/java/com/ruoyi/sales/service/ISalesLedgerProductService.java
@@ -1,10 +1,7 @@
package com.ruoyi.sales.service;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.sales.dto.SalesLedgerProductDto;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import java.util.List;
@@ -24,10 +21,6 @@
int deleteSalesLedgerProductByIds(Long[] ids);
int addOrUpdateSalesLedgerProduct(SalesLedgerProduct salesLedgerProduct);
-
- IPage<SalesLedgerProductDto> listPage(Page page, SalesLedgerProductDto salesLedgerProduct);
-
- IPage<SalesLedgerProductDto> listPagePurchaseLedger(Page page, SalesLedgerProductDto salesLedgerProduct);
R judgmentInventory(SalesLedgerProduct salesLedgerProduct);
diff --git a/src/main/java/com/ruoyi/sales/service/InvoiceLedgerService.java b/src/main/java/com/ruoyi/sales/service/InvoiceLedgerService.java
deleted file mode 100644
index e9335ca..0000000
--- a/src/main/java/com/ruoyi/sales/service/InvoiceLedgerService.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package com.ruoyi.sales.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.vo.FileVo;
-import com.ruoyi.sales.dto.InvoiceLedgerDto;
-import com.ruoyi.sales.dto.InvoiceRegistrationProductDto;
-import com.ruoyi.sales.pojo.InvoiceLedgerFile;
-import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
-import org.springframework.web.multipart.MultipartFile;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.math.BigDecimal;
-import java.util.List;
-
-public interface InvoiceLedgerService {
-
- /**
- * 寮�绁ㄥ彴璐︽柊澧�
- * @param productDto
- * @return
- */
- int invoiceLedgerSaveOrUpdate( InvoiceRegistrationProductDto productDto);
-
- /**
- * 寮�绁ㄥ彴璐﹀垹闄�
- * @param ids
- * @return
- */
- int invoiceLedgerDel(List<Integer> ids);
-
- /**
- * 寮�绁ㄥ彴璐﹀垎椤垫煡璇�
- * @param page
- * @param invoiceLedgerDto
- * @return
- */
- IPage<InvoiceLedgerDto> invoiceLedgerPage(Page page, InvoiceLedgerDto invoiceLedgerDto);
-
- /**
- * 寮�绁ㄥ彴璐︽枃浠舵煡璇�
- * @param invoiceLedgerId
- * @return
- */
- List<InvoiceLedgerFile> invoiceLedgerFileList(Integer invoiceLedgerId);
-
- /**
- * 寮�绁ㄥ彴璐︽枃浠朵笂浼�
- * @param file
- * @return
- */
- FileVo invoiceLedgerUploadFile(MultipartFile file);
-
- /**
- * 闄勪欢涓嬭浇
- * @param response
- * @param invoiceRegistrationProductDto
- * @return
- */
- void invoiceLedgerExport(HttpServletResponse response ,InvoiceRegistrationProductDto invoiceRegistrationProductDto);
-
- /**
- * 寮�绁ㄥ彴璐﹁鎯�
- * @param id
- * @return
- */
- InvoiceLedgerDto invoiceLedgerDetail(Integer id);
-
- /**
- * 闄勪欢鎻愪氦
- * @param invoiceLedgerDto
- * @return
- */
- void invoiceLedgerCommitFile(InvoiceLedgerDto invoiceLedgerDto);
-
- /**
- * 寮�绁ㄥ彴璐︽煡璇�
- * @param invoiceLedgerDto
- * @return
- */
- List<InvoiceLedgerDto> invoiceLedgerList(InvoiceLedgerDto invoiceLedgerDto);
-
- /**
- * 瀹㈡埛閿�鍞褰�
- * @param page
- * @param invoiceLedgerDto
- * @return
- */
- IPage<InvoiceLedgerDto> invoiceLedgerSalesAccount(Page page, InvoiceLedgerDto invoiceLedgerDto);
-
- BigDecimal getInvoiceAmount();
-
- /**
- * 寮�绁ㄧ櫥璁颁骇鍝佸垎椤垫煡璇�
- * @param page
- * @param registrationProductDto
- * @return
- */
- IPage<InvoiceRegistrationProductDto> registrationProductPage(Page page, InvoiceRegistrationProductDto registrationProductDto);
-
- /**
- * 浜у搧寮�绁ㄥ彴璐﹁鎯�
- * @param id
- * @return
- */
- InvoiceRegistrationProductDto invoiceLedgerProductDetail(Integer id);
-
- /**
- * 寮�绁ㄥ彴璐﹀垹闄�
- * @param invoiceRegistrationProductId
- * @return
- */
- void delInvoiceLedger(Integer invoiceRegistrationProductId);
-}
diff --git a/src/main/java/com/ruoyi/sales/service/InvoiceRegistrationService.java b/src/main/java/com/ruoyi/sales/service/InvoiceRegistrationService.java
deleted file mode 100644
index 4044a4e..0000000
--- a/src/main/java/com/ruoyi/sales/service/InvoiceRegistrationService.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.ruoyi.sales.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.sales.dto.InvoiceRegistrationDto;
-import com.ruoyi.sales.dto.InvoiceRegistrationProductDto;
-import com.ruoyi.sales.dto.SalesLedgerDto;
-import org.springframework.web.bind.annotation.RequestBody;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.List;
-
-public interface InvoiceRegistrationService {
-
- /**
- * 寮�绁ㄧ櫥璁拌褰曟柊澧�
- * @param salesLedgerDto
- * @return
- */
- void invoiceRegistrationSave(SalesLedgerDto salesLedgerDto);
-
- /**
- * 寮�绁ㄧ櫥璁板垹闄�
- * @param ids
- * @return
- */
- int invoiceRegistrationDel(List<Integer> ids);
-
-
- /**
- * 寮�绁ㄨ褰曚慨鏀�
- * @param invoiceRegistrationDto
- * @return
- */
- void invoiceRegistrationUpdate(InvoiceRegistrationDto invoiceRegistrationDto);
-
- /**
- * 寮�绁ㄧ櫥璁板垎椤垫煡璇�
- * @param page
- * @param invoiceRegistrationDto
- * @return
- */
- IPage<InvoiceRegistrationDto> invoiceRegistrationListPage(Page page, InvoiceRegistrationDto invoiceRegistrationDto);
-
- /**
- * 寮�绁ㄧ櫥璁颁骇鍝佹煡璇�
- * @param invoiceRegistrationProductDto
- * @return
- */
- List<InvoiceRegistrationProductDto> invoiceRegistrationProductList(InvoiceRegistrationProductDto invoiceRegistrationProductDto);
-
- /**
- * 寮�绁ㄧ櫥璁拌鎯�
- * @param id
- * @return
- */
- InvoiceRegistrationDto invoiceRegistrationDetail(Integer id);
-
- /**
- * 寮�绁ㄧ櫥璁板鍑�
- * @param response
- * @param invoiceRegistrationDto
- */
- void invoiceRegistrationExport(HttpServletResponse response, InvoiceRegistrationDto invoiceRegistrationDto);
-}
diff --git a/src/main/java/com/ruoyi/sales/service/ReceiptPaymentService.java b/src/main/java/com/ruoyi/sales/service/ReceiptPaymentService.java
deleted file mode 100644
index 49378c8..0000000
--- a/src/main/java/com/ruoyi/sales/service/ReceiptPaymentService.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package com.ruoyi.sales.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.sales.dto.CustomerInteractionDto;
-import com.ruoyi.sales.dto.InvoiceLedgerDto;
-import com.ruoyi.sales.dto.ReceiptPaymentDto;
-import com.ruoyi.sales.pojo.ReceiptPayment;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.math.BigDecimal;
-import java.util.List;
-import java.util.Map;
-
-public interface ReceiptPaymentService {
-
- /**
- * 鍥炴鐧昏鏂板
- * @param receiptPayment
- * @return
- */
- int receiptPaymentSaveOrUpdate(List<ReceiptPayment> receiptPayment);
-
- /**
- * 鍥炴鐧昏淇敼
- * @param receiptPayment
- * @return
- */
- int receiptPaymentUpdate(ReceiptPayment receiptPayment);
-
- /**
- * 鍥炴鐧昏鍒犻櫎
- * @param ids
- * @return
- */
- int receiptPaymentDel(List<Integer> ids);
-
- /**
- * 鍥炴鐧昏鍒嗛〉鏌ヨ
- * @param page
- * @param receiptPaymentDto
- * @return
- */
- IPage<ReceiptPaymentDto> receiptPaymentListPage (Page page, ReceiptPaymentDto receiptPaymentDto);
-
- /**
- * 鍥炴鐧昏璇︽儏
- * @param id
- * @return
- */
- ReceiptPaymentDto receiptPaymentInfo(Integer id);
-
- BigDecimal getReceiptAmount();
-
- /**
- * 鏌ヨ宸茬粡缁戝畾鍙戠エ鐨勫紑绁ㄥ彴璐�
- * @param page
- * @param receiptPaymentDto
- * @return
- */
- IPage<ReceiptPaymentDto> bindInvoiceNoRegPage(Page page, ReceiptPaymentDto receiptPaymentDto);
-
- /**
- * 寮�绁ㄥ彴璐﹁鎯�
- * @param id
- * @return
- */
- InvoiceLedgerDto invoiceInfo(Integer id);
-
- Map<String,BigDecimal> getAmountMouth();
-
- /**
- * 鏌ヨ鍥炴璁板綍
- */
- List<ReceiptPaymentDto> receiptPaymentHistoryList(ReceiptPaymentDto receiptPaymentDto);
-
- /**
- * 鏌ヨ鍥炴璁板綍鍒嗛〉
- */
- IPage<ReceiptPaymentDto> receiptPaymentHistoryListPage(Page page, ReceiptPaymentDto receiptPaymentDto);
-
- /**
- * 瀹㈡埛寰�鏉ヨ褰曟煡璇�
- * @param receiptPaymentDto
- * @return
- */
- List<InvoiceLedgerDto> customerInteractions (InvoiceLedgerDto receiptPaymentDto);
-
- /**
- * 鏌ヨ鍥炴璁板綍鍒嗛〉
- */
- List<ReceiptPaymentDto> receiptPaymentHistoryListNoPage(ReceiptPaymentDto receiptPaymentDto);
-
- /**
- * 鍏ㄥ鍑哄洖娆惧垪琛�
- */
- void exportPaymentList(HttpServletResponse response);
-
- /**
- * 閮ㄥ垎瀵煎嚭鍥炴鍒楄〃
- */
- void exportPaymentList(HttpServletResponse response, List<Long> ids);
-}
diff --git a/src/main/java/com/ruoyi/sales/service/impl/InvoiceLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/InvoiceLedgerServiceImpl.java
deleted file mode 100644
index d18a51a..0000000
--- a/src/main/java/com/ruoyi/sales/service/impl/InvoiceLedgerServiceImpl.java
+++ /dev/null
@@ -1,509 +0,0 @@
-package com.ruoyi.sales.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.common.vo.FileVo;
-import com.ruoyi.sales.dto.InvoiceLedgerDto;
-import com.ruoyi.sales.dto.InvoiceRegistrationProductDto;
-import com.ruoyi.sales.excel.InvoiceLedgerExcelDto;
-import com.ruoyi.sales.mapper.*;
-import com.ruoyi.sales.pojo.*;
-import com.ruoyi.sales.service.InvoiceLedgerService;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.RequiredArgsConstructor;
-import org.apache.commons.collections4.CollectionUtils;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.ObjectUtils;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.io.File;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.YearMonth;
-import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
-import java.util.stream.Collectors;
-
-@Service
-@RequiredArgsConstructor
-public class InvoiceLedgerServiceImpl extends ServiceImpl<InvoiceLedgerMapper, InvoiceLedger> implements InvoiceLedgerService {
-
- @Value("${ruoyi.profile}")
- private String uploadFile;
-
- private final InvoiceLedgerMapper invoiceLedgerMapper;
- private final InvoiceLedgerFileMapper invoiceLedgerFileMapper;
- private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
- private final ReceiptPaymentMapper receiptPaymentMapper;
- private final SalesLedgerProductMapper salesLedgerProductMapper;
-
- /**
- * 寮�绁ㄥ彴璐︽柊澧�
- * @param productDto
- * @return
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public int invoiceLedgerSaveOrUpdate(InvoiceRegistrationProductDto productDto) {
- // 鍒ゆ柇鏄惁宸茬粡鏂板寮�绁ㄥ彴璐�
- QueryWrapper<InvoiceLedger> ledgerQueryWrapper = new QueryWrapper<>();
- ledgerQueryWrapper.eq("invoice_registration_product_id", productDto.getId());
- InvoiceLedger invoiceLedger = invoiceLedgerMapper.selectOne(ledgerQueryWrapper);
- int result;
- if(ObjectUtils.isEmpty(invoiceLedger)){
- invoiceLedger = new InvoiceLedger();
- invoiceLedger.setInvoiceRegistrationProductId(productDto.getId());
- invoiceLedger.setInvoiceNo(productDto.getInvoiceNo());
- invoiceLedger.setInvoiceTotal(productDto.getInvoiceTotal());
- invoiceLedger.setInvoiceDate(productDto.getInvoiceDate());
- invoiceLedger.setInvoicePerson(productDto.getInvoicePerson());
- result = invoiceLedgerMapper.insert(invoiceLedger);
- }else {
- // 淇敼sale_leger_product
- InvoiceRegistrationProduct invoiceRegistrationProduct = invoiceRegistrationProductMapper.selectById(productDto.getId());
- SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(invoiceRegistrationProduct.getSalesLedgerProductId());
-
- BigDecimal invoiceNum = productDto.getInvoiceTotal().divide(invoiceRegistrationProduct.getTaxInclusiveUnitPrice(), 2, BigDecimal.ROUND_HALF_UP);
- //璁$畻 鏈紑绁ㄦ暟/鏈紑绁ㄩ噾棰�
- BigDecimal noInvoiceAmount = salesLedgerProduct.getNoInvoiceAmount().add(invoiceRegistrationProduct.getInvoiceAmount()).subtract(productDto.getInvoiceTotal());
- BigDecimal noInvoiceNum = salesLedgerProduct.getNoInvoiceNum().add(invoiceRegistrationProduct.getInvoiceNum()).subtract(invoiceNum);
- salesLedgerProduct.setNoInvoiceAmount(noInvoiceAmount);
- salesLedgerProduct.setNoInvoiceNum(noInvoiceNum);
- salesLedgerProductMapper.updateById(salesLedgerProduct);
-
- // 淇敼褰撳墠浜у搧寮�绁ㄧ櫥璁拌褰曟暟鎹�
- BigDecimal currentNoInvoiceNum = invoiceRegistrationProduct.getNoInvoiceNum().add(invoiceRegistrationProduct.getInvoiceNum()).subtract(invoiceNum);
- BigDecimal currentNoInvoiceAmount = invoiceRegistrationProduct.getNoInvoiceAmount().add(invoiceRegistrationProduct.getInvoiceAmount()).subtract(productDto.getInvoiceTotal());
- invoiceRegistrationProduct.setInvoiceNum(invoiceNum);
- invoiceRegistrationProduct.setInvoiceAmount(productDto.getInvoiceTotal());
- invoiceRegistrationProduct.setNoInvoiceNum(currentNoInvoiceNum);
- invoiceRegistrationProduct.setNoInvoiceAmount(currentNoInvoiceAmount);
- invoiceRegistrationProductMapper.updateById(invoiceRegistrationProduct);
-
- invoiceLedger.setInvoiceNo(productDto.getInvoiceNo());
- invoiceLedger.setInvoiceTotal(productDto.getInvoiceTotal());
- invoiceLedger.setInvoiceDate(productDto.getInvoiceDate());
- invoiceLedger.setInvoicePerson(productDto.getInvoicePerson());
- result = invoiceLedgerMapper.updateById(invoiceLedger);
- //鍒犻櫎鎵�鏈夐檮浠跺叧鑱�
- LambdaQueryWrapper<InvoiceLedgerFile> delWrapper = new LambdaQueryWrapper<>();
- delWrapper.eq(InvoiceLedgerFile::getInvoiceLedgerId, invoiceLedger.getId());
- invoiceLedgerFileMapper.delete(delWrapper);
- }
- List<FileVo> fileList = productDto.getFileList();
- if(CollectionUtils.isNotEmpty(fileList)){
- for (FileVo fileVo : fileList) {
- InvoiceLedgerFile invoiceLedgerFile = new InvoiceLedgerFile();
- BeanUtils.copyProperties(fileVo, invoiceLedgerFile);
- invoiceLedgerFile.setInvoiceLedgerId(invoiceLedger.getId());
- invoiceLedgerFileMapper.insert(invoiceLedgerFile);
- }
- }
- return result;
- }
-
- /**
- * 寮�绁ㄥ彴璐﹀垹闄�
- * @param ids
- * @return
- */
- @Override
- public int invoiceLedgerDel(List<Integer> ids) {
- LambdaQueryWrapper<InvoiceLedger> delWrapper = new LambdaQueryWrapper<>();
- delWrapper.in(InvoiceLedger::getId, ids);
- return invoiceLedgerMapper.delete(delWrapper);
- }
-
- /**
- * 寮�绁ㄥ彴璐﹀垎椤垫煡璇�
- * @param page
- * @param invoiceLedgerDto
- * @return
- */
- @Override
- public IPage<InvoiceLedgerDto> invoiceLedgerPage(Page page, InvoiceLedgerDto invoiceLedgerDto) {
- return invoiceLedgerMapper.invoiceLedgerPage(page, invoiceLedgerDto);
- }
-
- /**
- * 寮�绁ㄥ彴璐︽枃浠舵煡璇�
- * @param invoiceLedgerId
- * @return
- */
- @Override
- public List<InvoiceLedgerFile> invoiceLedgerFileList(Integer invoiceLedgerId) {
- LambdaQueryWrapper<InvoiceLedgerFile> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.eq(InvoiceLedgerFile::getInvoiceLedgerId, invoiceLedgerId);
- return invoiceLedgerFileMapper.selectList(queryWrapper);
- }
-
- /**
- * 寮�绁ㄥ彴璐︽枃浠朵笂浼�
- * @param file
- * @return
- */
- @Override
- public FileVo invoiceLedgerUploadFile(MultipartFile file) {
- FileVo fileVo = new FileVo();
- try {
- String baseDir = uploadFile + File.separatorChar + "invoiceLedger";
- File dirFile = new File(baseDir);
- if(!dirFile.exists()){
- dirFile.mkdirs();
- }
- String filePath = baseDir + File.separatorChar + UUID.randomUUID() + "_" + file.getOriginalFilename();
- file.transferTo(new File(filePath));
- fileVo.setName(file.getOriginalFilename());
- fileVo.setUrl(filePath);
- fileVo.setFileSize((int)file.getSize());
- }catch (Exception e){
- e.printStackTrace();
- throw new RuntimeException("鏂囦欢涓婁紶澶辫触");
- }
- return fileVo;
- }
-
- /**
- * 闄勪欢涓嬭浇
- * @param response
- * @param invoiceRegistrationProductDto
- * @return
- */
- @Override
- public void invoiceLedgerExport(HttpServletResponse response, InvoiceRegistrationProductDto invoiceRegistrationProductDto) {
- List<InvoiceRegistrationProductDto> invoiceRegistrationProductList = invoiceRegistrationProductMapper.invoiceRegistrationProductList(invoiceRegistrationProductDto);
- List<InvoiceLedgerExcelDto> invoiceLedgerExcelDtoList = invoiceRegistrationProductList.stream().map(item -> {
- InvoiceLedgerExcelDto invoiceLedgerExcelDto = new InvoiceLedgerExcelDto();
- BeanUtils.copyProperties(item, invoiceLedgerExcelDto);
- return invoiceLedgerExcelDto;
- }).collect(Collectors.toList());
- ExcelUtil<InvoiceLedgerExcelDto> util = new ExcelUtil<InvoiceLedgerExcelDto>(InvoiceLedgerExcelDto.class);
- util.exportExcel(response, invoiceLedgerExcelDtoList, "渚涘簲鍟嗗鍑�");
- }
-
- /**
- * 寮�绁ㄥ彴璐﹁鎯�
- * @param id
- * @return
- */
- @Override
- public InvoiceLedgerDto invoiceLedgerDetail(Integer id) {
- InvoiceLedgerDto invoiceLedgerDto = invoiceLedgerMapper.invoiceLedgerInfo(id);
- if(ObjectUtils.isEmpty(invoiceLedgerDto)){
- throw new RuntimeException("寮�绁ㄥ彴璐︽煡鎵惧け璐�");
- }
- // 鏌ヨ闄勪欢
- QueryWrapper<InvoiceLedgerFile> queryWrapper = new QueryWrapper<>();
- queryWrapper.eq("invoice_ledger_id", id);
- List<InvoiceLedgerFile> invoiceLedgerFileList = invoiceLedgerFileMapper.selectList(queryWrapper);
- List<FileVo> fileList = invoiceLedgerFileList.stream().map(item -> {
- FileVo fileVo = new FileVo();
- BeanUtils.copyProperties(item, fileVo);
- return fileVo;
- }).collect(Collectors.toList());
- invoiceLedgerDto.setFileList(fileList);
- return invoiceLedgerDto;
- }
-
- /**
- * 闄勪欢鎻愪氦
- * @param invoiceLedgerDto
- * @return
- */
- @Override
- public void invoiceLedgerCommitFile(InvoiceLedgerDto invoiceLedgerDto) {
- if(null == invoiceLedgerDto.getId()){
- throw new RuntimeException("缂哄皯鍙戠エ鍙拌处涓婚敭");
- }
- if(CollectionUtils.isEmpty(invoiceLedgerDto.getFileList())){
- throw new RuntimeException("缂哄皯鏂囦欢淇℃伅");
- }
- QueryWrapper<InvoiceLedger> ledgerQueryWrapper = new QueryWrapper<>();
- ledgerQueryWrapper.eq("invoice_registration_product_id", invoiceLedgerDto.getId());
- InvoiceLedger invoiceLedger = invoiceLedgerMapper.selectOne(ledgerQueryWrapper);
- if(ObjectUtils.isEmpty(invoiceLedger)){
- throw new RuntimeException("寮�绁ㄥ彴璐︽湭鐧昏");
- }
- List<FileVo> fileList = invoiceLedgerDto.getFileList();
- fileList.forEach(fileVo -> {
- InvoiceLedgerFile invoiceLedgerFile = new InvoiceLedgerFile();
- BeanUtils.copyProperties(fileVo, invoiceLedgerFile);
- invoiceLedgerFile.setInvoiceLedgerId(invoiceLedger.getId());
- invoiceLedgerFileMapper.insert(invoiceLedgerFile);
- });
- }
-
- /**
- * 寮�绁ㄥ彴璐︽煡璇�
- * @param invoiceLedgerDto
- * @return
- */
- @Override
- public List<InvoiceLedgerDto> invoiceLedgerList(InvoiceLedgerDto invoiceLedgerDto) {
- return invoiceLedgerMapper.invoiceLedgerList(invoiceLedgerDto);
- }
-
- /**
- * 瀹㈡埛閿�鍞褰�
- * @param page
- * @param invoiceLedgerDto
- * @return
- */
- @Override
- public IPage<InvoiceLedgerDto> invoiceLedgerSalesAccount(Page page, InvoiceLedgerDto invoiceLedgerDto) {
- IPage<InvoiceLedgerDto> invoiceLedgerDtoIPage = invoiceLedgerMapper.invoiceLedgerSalesAccount(page, invoiceLedgerDto);
- return invoiceLedgerDtoIPage;
- }
-
- @Override
- public BigDecimal getInvoiceAmount() {
- LocalDate now = LocalDate.now();
- YearMonth currentMonth = YearMonth.from(now);
-
- // 鍒涘缓LambdaQueryWrapper
- LambdaQueryWrapper<InvoiceLedger> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.ge(InvoiceLedger::getInvoiceDate, currentMonth.atDay(1).atStartOfDay()) // 澶т簬绛変簬鏈湀绗竴澶�
- .lt(InvoiceLedger::getInvoiceDate, currentMonth.plusMonths(1).atDay(1).atStartOfDay()); // 灏忎簬涓嬫湀绗竴澶�
-
- // 鎵ц鏌ヨ骞惰绠楁�诲拰
- List<InvoiceLedger> invoiceLedgers = invoiceLedgerMapper.selectList(queryWrapper);
-
- BigDecimal totalContractAmount = invoiceLedgers.stream()
- .map(InvoiceLedger::getInvoiceTotal)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
-
- return totalContractAmount;
- }
-
- /**
- * 寮�绁ㄧ櫥璁颁骇鍝佸垎椤垫煡璇�
- * @param page
- * @param registrationProductDto
- * @return
- */
- @Override
- public IPage<InvoiceRegistrationProductDto> registrationProductPage(Page page, InvoiceRegistrationProductDto registrationProductDto) {
- IPage<InvoiceRegistrationProductDto> invoiceRegistrationProductDtoIPage = invoiceRegistrationProductMapper.invoiceRegistrationProductPage(page, registrationProductDto);
- if (registrationProductDto.getStatus()) {
- invoiceRegistrationProductDtoIPage.getRecords().removeIf(invoiceRegistrationProduct -> !StringUtils.isEmpty(invoiceRegistrationProduct.getInvoiceNo()));
- }
- invoiceRegistrationProductDtoIPage.getRecords().forEach(invoiceRegistrationProductDto -> {
- invoiceRegistrationProductDto.setCommonFiles(invoiceLedgerFileMapper.selectList(new QueryWrapper<InvoiceLedgerFile>().lambda()
- .eq(InvoiceLedgerFile::getInvoiceLedgerId, invoiceRegistrationProductDto.getInvoiceLedgerId())));
- });
- return invoiceRegistrationProductDtoIPage;
- }
-
- /**
- * 浜у搧寮�绁ㄥ彴璐﹁鎯�
- * @param id
- * @return
- */
- @Override
- public InvoiceRegistrationProductDto invoiceLedgerProductDetail(Integer id) {
- InvoiceRegistrationProductDto invoiceRegistrationProductDto = invoiceLedgerMapper.invoiceLedgerProductInfo(id);
- if(ObjectUtils.isEmpty(invoiceRegistrationProductDto)){
- throw new RuntimeException("浜у搧寮�绁ㄥ彴璐︽煡鎵惧け璐�");
- }
- List<InvoiceRegistrationProduct> invoiceRegistrationProducts = invoiceRegistrationProductMapper.selectList(new LambdaQueryWrapper<InvoiceRegistrationProduct>()
- .eq(InvoiceRegistrationProduct::getSalesLedgerProductId, invoiceRegistrationProductDto.getSalesLedgerProductId()));
- if(CollectionUtils.isNotEmpty(invoiceRegistrationProducts)){
- invoiceRegistrationProductDto.setNoInvoiceNum(invoiceRegistrationProductDto.getQuantity()
- .subtract(invoiceRegistrationProducts.stream().map(InvoiceRegistrationProduct::getInvoiceNum).reduce(BigDecimal.ZERO, BigDecimal::add)));
- invoiceRegistrationProductDto.setNoInvoiceAmount(invoiceRegistrationProductDto.getTaxInclusiveTotalPrice()
- .subtract(invoiceRegistrationProducts.stream().map(InvoiceRegistrationProduct::getInvoiceAmount).reduce(BigDecimal.ZERO, BigDecimal::add)));
- }
- // 鏌ヨ闄勪欢
- QueryWrapper<InvoiceLedgerFile> queryWrapper = new QueryWrapper<>();
- queryWrapper.eq("invoice_ledger_id", invoiceRegistrationProductDto.getInvoiceLedgerId());
- List<InvoiceLedgerFile> invoiceLedgerFileList = invoiceLedgerFileMapper.selectList(queryWrapper);
- List<FileVo> fileList = invoiceLedgerFileList.stream().map(item -> {
- FileVo fileVo = new FileVo();
- BeanUtils.copyProperties(item, fileVo);
- return fileVo;
- }).collect(Collectors.toList());
- invoiceRegistrationProductDto.setFileList(fileList);
- return invoiceRegistrationProductDto;
- }
-
- /**
- * 寮�绁ㄥ彴璐﹀垹闄�
- * @param invoiceRegistrationProductId
- * @return
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public void delInvoiceLedger(Integer invoiceRegistrationProductId) {
- // 鍒ゆ柇鏄惁鏈夊洖娆捐褰�
- List<ReceiptPayment> receiptPaymentList = receiptPaymentMapper.receiptPaymentListByProdRegId(invoiceRegistrationProductId);
- if(!CollectionUtils.isEmpty(receiptPaymentList)){
- throw new RuntimeException("璇峰厛鍒犻櫎鍥炴璁板綍");
- }
- // 鍒ゆ柇鏄惁鏈夊紑绁ㄧ櫥璁拌褰�
- InvoiceRegistrationProduct invoiceRegistrationProduct = invoiceRegistrationProductMapper.selectById(invoiceRegistrationProductId);
- if(ObjectUtils.isEmpty(invoiceRegistrationProduct)){
- throw new RuntimeException("寮�绁ㄧ櫥璁拌褰曟煡鎵惧け璐�");
- }
- // 鍒ゆ柇璇ュ紑绁ㄥ彴璐︽槸鍚︽湭褰撴湀锛屽鏋滀负褰撴湀鐩存帴鍒犻櫎鍚﹀垯鏂板涓�鏉$浉鍙嶈礋鏁版暟鎹�
- QueryWrapper<InvoiceLedger> ledgerQueryWrapper = new QueryWrapper<>();
- ledgerQueryWrapper.eq("invoice_registration_product_id", invoiceRegistrationProductId);
- InvoiceLedger invoiceLedger = invoiceLedgerMapper.selectOne(ledgerQueryWrapper);
- if(ObjectUtils.isEmpty(invoiceLedger)){
- throw new RuntimeException("寮�绁ㄥ彴璐︽煡鎵惧け璐�");
- }
- if( invoiceLedger.getInvoiceDate() == null){
- dealCurrentMonthDel(invoiceRegistrationProductId,invoiceRegistrationProduct);
- return;
- }
- // 鑾峰彇褰撳墠鏃ユ湡
- LocalDate today = LocalDate.now();
- // 浣跨敤YearMonth姣旇緝骞翠唤鍜屾湀浠芥槸鍚︾浉鍚�
- boolean equalsFlag = YearMonth.from(invoiceLedger.getInvoiceDate()).equals(YearMonth.from(today));
- if(equalsFlag){
- dealCurrentMonthDel(invoiceRegistrationProductId,invoiceRegistrationProduct);
- }else {
- dealOtherMonthDel(invoiceRegistrationProduct,invoiceLedger);
- }
- }
-
- /**
- * 澶勭悊褰撴湀寮�绁ㄥ彴璐﹀垹闄�
- *
- * @param invoiceRegistrationProductId
- * @param invoiceRegistrationProduct
- */
-
- private void dealCurrentMonthDel(Integer invoiceRegistrationProductId, InvoiceRegistrationProduct invoiceRegistrationProduct) {
-
- // 鍒犻櫎寮�绁ㄥ彴璐�
- QueryWrapper<InvoiceLedger> delLedgerWrapper = new QueryWrapper<>();
- delLedgerWrapper.eq("invoice_registration_product_id", invoiceRegistrationProductId);
- invoiceLedgerMapper.delete(delLedgerWrapper);
-
- // 鏌ヨ褰撳墠浜у搧涓嬬殑鎵�鏈夊紑绁ㄧ櫥璁�
- QueryWrapper<InvoiceRegistrationProduct> queryWrapper = new QueryWrapper<>();
- queryWrapper.eq("sales_ledger_id", invoiceRegistrationProduct.getSalesLedgerId());
- queryWrapper.eq("sales_ledger_product_id", invoiceRegistrationProduct.getSalesLedgerProductId());
- queryWrapper.orderByAsc("create_time");
- List<InvoiceRegistrationProduct> allList = invoiceRegistrationProductMapper.selectList(queryWrapper);
-
- int index = -1;
- for (int i = 0; i < allList.size(); i++) {
- if (invoiceRegistrationProductId.equals(allList.get(i).getId())) {
- index = i;
- break;
- }
- }
- if (index == -1) {
- return;
- }
-
- for (int i = index + 1; i < allList.size(); i++) {
- InvoiceRegistrationProduct current = allList.get(i);
-
- current.setNoInvoiceNum(current.getNoInvoiceNum().add(invoiceRegistrationProduct.getInvoiceNum()));
- current.setNoInvoiceAmount(current.getNoInvoiceAmount().add(invoiceRegistrationProduct.getInvoiceAmount()));
-
- invoiceRegistrationProductMapper.updateById(current);
- }
-
- // 鍒犻櫎褰撳墠寮�绁ㄧ櫥璁�
- invoiceRegistrationProductMapper.deleteById(invoiceRegistrationProductId);
-
- // 鏌ヨ鍒犻櫎鍚庣殑鍓╀綑寮�绁ㄧ櫥璁�
- QueryWrapper<InvoiceRegistrationProduct> newQueryWrapper = new QueryWrapper<>();
- newQueryWrapper.eq("sales_ledger_id", invoiceRegistrationProduct.getSalesLedgerId());
- newQueryWrapper.eq("sales_ledger_product_id", invoiceRegistrationProduct.getSalesLedgerProductId());
- newQueryWrapper.orderByAsc("create_time");
- List<InvoiceRegistrationProduct> remainList = invoiceRegistrationProductMapper.selectList(newQueryWrapper);
-
- // 鏌ヨ閿�鍞彴璐︿骇鍝�
- SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(invoiceRegistrationProduct.getSalesLedgerProductId());
-
- if (CollectionUtils.isEmpty(remainList)) {
- // 娌℃湁浠讳綍寮�绁ㄨ褰曪紝鎭㈠鍒濆鐘舵��
- salesLedgerProduct.setInvoiceNum(BigDecimal.ZERO);
- salesLedgerProduct.setInvoiceAmount(BigDecimal.ZERO);
- salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
- salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
- } else {
- salesLedgerProduct.setInvoiceNum(salesLedgerProduct.getInvoiceNum().subtract(invoiceRegistrationProduct.getInvoiceNum()));
- salesLedgerProduct.setInvoiceAmount(salesLedgerProduct.getInvoiceAmount().subtract(invoiceRegistrationProduct.getInvoiceAmount()));
- salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getNoInvoiceNum().add(invoiceRegistrationProduct.getInvoiceNum()));
- salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getNoInvoiceAmount().add(invoiceRegistrationProduct.getInvoiceAmount()));
- }
-
- salesLedgerProductMapper.updateById(salesLedgerProduct);
- }
-
- /**
- * 澶勭悊鍏朵粬鏈堜唤寮�绁ㄥ彴璐﹀垹闄�
- * @param invoiceRegistrationProduct
- * @param invoiceLedger
- */
- private void dealOtherMonthDel(InvoiceRegistrationProduct invoiceRegistrationProduct, InvoiceLedger invoiceLedger) {
- //鏌ヨ鍘嗗彶寮�绁ㄧ櫥璁�
- QueryWrapper<InvoiceRegistrationProduct> queryWrapper = new QueryWrapper<>();
- queryWrapper.eq("sales_ledger_id", invoiceRegistrationProduct.getSalesLedgerId());
- queryWrapper.eq("sales_ledger_product_id", invoiceRegistrationProduct.getSalesLedgerProductId());
- queryWrapper.orderByAsc("create_time");
- List<InvoiceRegistrationProduct> list = invoiceRegistrationProductMapper.selectList(queryWrapper);
-
- if (CollectionUtils.isEmpty(list)) {
- return;
- }
-
- InvoiceRegistrationProduct last = list.get(list.size() - 1);
-
- BigDecimal negateInvoiceNum = invoiceRegistrationProduct.getInvoiceNum().negate();
- BigDecimal negateInvoiceAmount = invoiceRegistrationProduct.getInvoiceAmount().negate();
-
- InvoiceRegistrationProduct copy = new InvoiceRegistrationProduct();
- BeanUtils.copyProperties(invoiceRegistrationProduct, copy);
-
- copy.setId(null);
- copy.setInvoiceNum(negateInvoiceNum);
- copy.setInvoiceAmount(negateInvoiceAmount);
-
- // 鏈紑绁� = 涓婁竴鏉� + 鏈鍐插洖鐨勬暟閲�
- copy.setNoInvoiceNum(last.getNoInvoiceNum().add(invoiceRegistrationProduct.getInvoiceNum()));
- copy.setNoInvoiceAmount(last.getNoInvoiceAmount().add(invoiceRegistrationProduct.getInvoiceAmount()));
-
- invoiceRegistrationProductMapper.insert(copy);
-
- // 澶嶅埗寮�绁ㄥ彴璐�
- InvoiceLedger ledgerCopy = new InvoiceLedger();
- BeanUtils.copyProperties(invoiceLedger, ledgerCopy);
-
- ledgerCopy.setId(null);
- ledgerCopy.setInvoiceRegistrationProductId(copy.getId());
- ledgerCopy.setInvoiceTotal(invoiceLedger.getInvoiceTotal().negate());
- ledgerCopy.setInvoiceDate(LocalDate.now());
-
- invoiceLedgerMapper.insert(ledgerCopy);
-
- // 鍥炴粴 sales_ledger_product
- SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(invoiceRegistrationProduct.getSalesLedgerProductId());
-
- // 宸插紑绁�
- salesLedgerProduct.setInvoiceNum(salesLedgerProduct.getInvoiceNum().add(negateInvoiceNum));
- salesLedgerProduct.setInvoiceAmount(salesLedgerProduct.getInvoiceAmount().add(negateInvoiceAmount));
-
- // 鏈紑绁�
- salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getNoInvoiceNum().add(invoiceRegistrationProduct.getInvoiceNum()));
- salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getNoInvoiceAmount().add(invoiceRegistrationProduct.getInvoiceAmount()));
-
- salesLedgerProductMapper.updateById(salesLedgerProduct);
- }
-
-}
diff --git a/src/main/java/com/ruoyi/sales/service/impl/InvoiceRegistrationServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/InvoiceRegistrationServiceImpl.java
deleted file mode 100644
index fefe144..0000000
--- a/src/main/java/com/ruoyi/sales/service/impl/InvoiceRegistrationServiceImpl.java
+++ /dev/null
@@ -1,228 +0,0 @@
-package com.ruoyi.sales.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.sales.dto.InvoiceRegistrationDto;
-import com.ruoyi.sales.dto.InvoiceRegistrationProductDto;
-import com.ruoyi.sales.dto.SalesLedgerDto;
-import com.ruoyi.sales.excel.InvoiceRegisAndProductExcelDto;
-import com.ruoyi.sales.mapper.InvoiceLedgerMapper;
-import com.ruoyi.sales.mapper.InvoiceRegistrationMapper;
-import com.ruoyi.sales.mapper.InvoiceRegistrationProductMapper;
-import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
-import com.ruoyi.sales.pojo.InvoiceLedger;
-import com.ruoyi.sales.pojo.InvoiceRegistration;
-import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import com.ruoyi.sales.service.InvoiceRegistrationService;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.RequiredArgsConstructor;
-import org.apache.commons.collections4.CollectionUtils;
-import org.springframework.beans.BeanUtils;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.ObjectUtils;
-
-import java.math.BigDecimal;
-import java.util.List;
-import java.util.stream.Collectors;
-
-@Service
-@RequiredArgsConstructor
-public class InvoiceRegistrationServiceImpl extends ServiceImpl<InvoiceRegistrationMapper, InvoiceRegistration> implements InvoiceRegistrationService {
-
- private final InvoiceRegistrationMapper invoiceRegistrationMapper;
-
- private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
-
- private final SalesLedgerProductMapper salesLedgerProductMapper;
-
- private final InvoiceLedgerMapper invoiceLedgerMapper;
-
- /**
- * 寮�绁ㄧ櫥璁拌褰曟柊澧�
- * @param salesLedgerDto
- * @return
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public void invoiceRegistrationSave(SalesLedgerDto salesLedgerDto) {
- // 鏂板寮�绁ㄧ櫥璁颁富琛�
- InvoiceRegistration invoiceRegistration = new InvoiceRegistration();
- BeanUtils.copyProperties(salesLedgerDto, invoiceRegistration);
- invoiceRegistration.setId(null);
- invoiceRegistration.setCustomerId(salesLedgerDto.getCustomerId().intValue());
- invoiceRegistration.setSalesLedgerId(salesLedgerDto.getId().intValue());
- invoiceRegistrationMapper.insert(invoiceRegistration);
-
- List<SalesLedgerProduct> productData = salesLedgerDto.getProductData();
- if (CollectionUtils.isEmpty(productData)) {
- return;
- }
-
- for (SalesLedgerProduct productDatum : productData) {
- // 鏈寮�绁ㄦ暟 / 閲戦
- BigDecimal currentInvoiceNum = productDatum.getCurrentInvoiceNum();
- BigDecimal currentInvoiceAmount = productDatum.getCurrentInvoiceAmount();
-
- if (currentInvoiceNum == null || BigDecimal.ZERO.compareTo(currentInvoiceNum) == 0) {
- continue;
- }
-
- LambdaQueryWrapper<SalesLedgerProduct> salesLedgerProductLambdaQueryWrapper = new LambdaQueryWrapper<SalesLedgerProduct>()
- .eq(SalesLedgerProduct::getId, productDatum.getId())
- .eq(SalesLedgerProduct::getSalesLedgerId, productDatum.getSalesLedgerId());
- SalesLedgerProduct dbProduct = salesLedgerProductMapper.selectOne(salesLedgerProductLambdaQueryWrapper);
-
- if (dbProduct == null) {
- throw new RuntimeException("閿�鍞彴璐︿骇鍝佷笉瀛樺湪锛孖D锛�" + productDatum.getId());
- }
-
- // 鏈紑绁�
- BigDecimal noInvoiceAmount = dbProduct.getNoInvoiceAmount();
- BigDecimal noInvoiceNum = dbProduct.getNoInvoiceNum();
-
- // 鍓╀綑鏈紑绁�
- BigDecimal newNoInvoiceNum = noInvoiceNum.subtract(currentInvoiceNum);
- BigDecimal newNoInvoiceAmount = noInvoiceAmount.subtract(currentInvoiceAmount);
-
-
- if (newNoInvoiceAmount.compareTo(BigDecimal.ZERO) < 0) {
- throw new RuntimeException("寮�绁ㄦ暟閲忔垨閲戦瓒呰繃鍚堝悓鎬婚噺");
- }
-
- // 鏇存柊 sales_ledger_product
- salesLedgerProductMapper.update(
- null,
- new LambdaUpdateWrapper<SalesLedgerProduct>()
- .eq(SalesLedgerProduct::getId, dbProduct.getId())
- .set(SalesLedgerProduct::getNoInvoiceNum, newNoInvoiceNum)
- .set(SalesLedgerProduct::getNoInvoiceAmount, newNoInvoiceAmount)
- );
-
- InvoiceRegistrationProduct invoiceRegistrationProduct = new InvoiceRegistrationProduct();
- BeanUtils.copyProperties(dbProduct, invoiceRegistrationProduct);
-
- invoiceRegistrationProduct.setId(null);
- invoiceRegistrationProduct.setSalesLedgerId(salesLedgerDto.getId().intValue());
- invoiceRegistrationProduct.setInvoiceRegistrationId(invoiceRegistration.getId());
- invoiceRegistrationProduct.setSalesLedgerProductId(dbProduct.getId().intValue());
- invoiceRegistrationProduct.setInvoiceNum(currentInvoiceNum);
- invoiceRegistrationProduct.setInvoiceAmount(currentInvoiceAmount);
- invoiceRegistrationProduct.setNoInvoiceAmount(newNoInvoiceAmount);
-
- invoiceRegistrationProductMapper.insert(invoiceRegistrationProduct);
-
- InvoiceLedger invoiceLedger = new InvoiceLedger();
- invoiceLedger.setInvoiceDate(salesLedgerDto.getIssueDate());
- invoiceLedger.setInvoiceRegistrationProductId(invoiceRegistrationProduct.getId());
- invoiceLedger.setInvoiceTotal(currentInvoiceAmount);
- invoiceLedger.setInvoiceNo(salesLedgerDto.getInvoiceNo());
- invoiceLedger.setCreateUser(SecurityUtils.getUserId().intValue());
- invoiceLedger.setInvoicePerson(dbProduct.getRegister());
-
- invoiceLedgerMapper.insert(invoiceLedger);
- }
- }
-
- /**
- * 寮�绁ㄧ櫥璁板垹闄�
- * @param ids
- * @return
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public int invoiceRegistrationDel(List<Integer> ids) {
- int excuteNum = invoiceRegistrationMapper.deleteBatchIds(ids);
- LambdaQueryWrapper<InvoiceRegistrationProduct> delWrapper = new LambdaQueryWrapper<>();
- delWrapper.in(InvoiceRegistrationProduct::getInvoiceRegistrationId, ids);
- invoiceRegistrationProductMapper.delete(delWrapper);
- return excuteNum;
- }
-
- /**
- * 寮�绁ㄨ褰曚慨鏀�
- * @param invoiceRegistrationDto
- * @return
- */
- @Override
- public void invoiceRegistrationUpdate(InvoiceRegistrationDto invoiceRegistrationDto) {
- InvoiceRegistration invoiceRegistration = new InvoiceRegistration();
- BeanUtils.copyProperties(invoiceRegistrationDto, invoiceRegistration);
- // 寮�绁ㄧ櫥璁颁慨鏀�
- invoiceRegistrationMapper.updateById(invoiceRegistration);
- List<InvoiceRegistrationProductDto> productDtoList = invoiceRegistrationDto.getProductDtoList();
- // 寮�绁ㄤ骇鍝佺櫥璁颁慨鏀�
- if(CollectionUtils.isNotEmpty(productDtoList)){
- for (InvoiceRegistrationProductDto invoiceRegistrationProductDto : productDtoList) {
- InvoiceRegistrationProduct invoiceRegistrationProduct = new InvoiceRegistrationProduct();
- BeanUtils.copyProperties(invoiceRegistrationProductDto, invoiceRegistrationProduct);
- invoiceRegistrationProductMapper.updateById(invoiceRegistrationProduct);
- }
- }
- }
-
- /**
- * 寮�绁ㄧ櫥璁板垎椤垫煡璇�
- * @param page
- * @param invoiceRegistrationDto
- * @return
- */
- @Override
- public IPage<InvoiceRegistrationDto> invoiceRegistrationListPage(Page page, InvoiceRegistrationDto invoiceRegistrationDto) {
- return invoiceRegistrationMapper.invoiceRegistrationListPage(page, invoiceRegistrationDto);
- }
-
- /**
- * 寮�绁ㄧ櫥璁颁骇鍝佹煡璇�
- * @param invoiceRegistrationProductDto
- * @return
- */
- @Override
- public List<InvoiceRegistrationProductDto> invoiceRegistrationProductList(InvoiceRegistrationProductDto invoiceRegistrationProductDto) {
- return invoiceRegistrationProductMapper.invoiceRegistrationProductList(invoiceRegistrationProductDto);
- }
-
- /**
- * 寮�绁ㄧ櫥璁拌鎯�
- * @param id
- * @return
- */
- @Override
- public InvoiceRegistrationDto invoiceRegistrationDetail(Integer id) {
- InvoiceRegistration invoiceRegistration = invoiceRegistrationMapper.selectById(id);
- if(ObjectUtils.isEmpty(invoiceRegistration)){
- throw new RuntimeException("寮�绁ㄧ櫥璁颁俊鎭煡鎵惧け璐�");
- }
- InvoiceRegistrationDto invoiceRegistrationDto = new InvoiceRegistrationDto();
- BeanUtils.copyProperties(invoiceRegistration, invoiceRegistrationDto);
- QueryWrapper<InvoiceRegistrationProduct> queryWrapper = new QueryWrapper<>();
- queryWrapper.eq("invoice_registration_id", id);
- List<InvoiceRegistrationProduct> invoiceRegistrationProductList = invoiceRegistrationProductMapper.selectList(queryWrapper);
- List<InvoiceRegistrationProductDto> invoiceRegistrationProductDtoList = invoiceRegistrationProductList.stream().map(item -> {
- InvoiceRegistrationProductDto invoiceRegistrationProductDto = new InvoiceRegistrationProductDto();
- BeanUtils.copyProperties(item, invoiceRegistrationProductDto);
- return invoiceRegistrationProductDto;
- }).collect(Collectors.toList());
- invoiceRegistrationDto.setProductDtoList(invoiceRegistrationProductDtoList);
- return invoiceRegistrationDto;
- }
-
- /**
- * 寮�绁ㄧ櫥璁板鍑�
- * @param response
- * @param invoiceRegistrationDto
- */
- @Override
- public void invoiceRegistrationExport(HttpServletResponse response, InvoiceRegistrationDto invoiceRegistrationDto) {
- List<InvoiceRegisAndProductExcelDto> invoiceRegisAndProductExcelDtoList = invoiceRegistrationMapper.invoiceRegisAndProductExcelDtoList();
- ExcelUtil<InvoiceRegisAndProductExcelDto> util = new ExcelUtil<InvoiceRegisAndProductExcelDto>(InvoiceRegisAndProductExcelDto.class);
- util.exportExcel(response, invoiceRegisAndProductExcelDtoList, "寮�绁ㄧ櫥璁颁俊鎭�");
- }
-}
diff --git a/src/main/java/com/ruoyi/sales/service/impl/ReceiptPaymentServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/ReceiptPaymentServiceImpl.java
deleted file mode 100644
index 677249a..0000000
--- a/src/main/java/com/ruoyi/sales/service/impl/ReceiptPaymentServiceImpl.java
+++ /dev/null
@@ -1,349 +0,0 @@
-package com.ruoyi.sales.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.account.pojo.AccountIncome;
-import com.ruoyi.account.service.AccountIncomeService;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.sales.dto.InvoiceLedgerDto;
-import com.ruoyi.sales.dto.ReceiptPaymentDto;
-import com.ruoyi.sales.dto.ReceiptPaymentExeclDto;
-import com.ruoyi.sales.mapper.ReceiptPaymentMapper;
-import com.ruoyi.sales.mapper.SalesLedgerMapper;
-import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
-import com.ruoyi.sales.pojo.ReceiptPayment;
-import com.ruoyi.sales.pojo.SalesLedger;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import com.ruoyi.sales.service.ReceiptPaymentService;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.RequiredArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.CollectionUtils;
-import org.springframework.util.ObjectUtils;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.YearMonth;
-import java.util.*;
-
-@Service
-@RequiredArgsConstructor
-public class ReceiptPaymentServiceImpl extends ServiceImpl<ReceiptPaymentMapper,ReceiptPayment> implements ReceiptPaymentService {
-
- private final ReceiptPaymentMapper receiptPaymentMapper;
- private final SalesLedgerMapper salesLedgerMapper;
- private final SalesLedgerProductMapper salesLedgerProductMapper;
- private final AccountIncomeService accountIncomeService;
-
- /**
- * 鍥炴鐧昏鏂板
- * @param receiptPaymentList
- * @return
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public int receiptPaymentSaveOrUpdate(List<ReceiptPayment> receiptPaymentList) {
- for (ReceiptPayment receiptPayment : receiptPaymentList) {
- ReceiptPayment byId = receiptPayment;
- if (!ObjectUtils.isEmpty(receiptPayment.getId())){
- receiptPayment = this.getById(receiptPayment.getId());
- }
- SalesLedger salesLedger = salesLedgerMapper.selectById(receiptPayment.getSalesLedgerId());
- if(null==salesLedger) throw new RuntimeException("鏈壘鍒伴攢鍞崟");
- // 宸插洖娆鹃噾棰�
- SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(receiptPayment.getSalesLedgerProductId());
- if(null==salesLedgerProduct) throw new RuntimeException("鏈壘鍒伴攢鍞崟浜у搧");
- if (salesLedgerProduct.getPendingInvoiceTotal().add(receiptPayment.getReceiptPaymentAmount()).compareTo(byId.getReceiptPaymentAmount())<0){
- throw new RuntimeException("鏈鍥炴閲戦涓嶈兘澶т簬寰呭洖娆鹃噾棰�+鍥炴閲戦");
- }
- if(null==receiptPayment.getId()){
- salesLedgerProduct.setInvoiceTotal(salesLedgerProduct.getInvoiceTotal().add(receiptPayment.getReceiptPaymentAmount()));
- salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice().subtract(salesLedgerProduct.getInvoiceTotal()));
- receiptPaymentMapper.insert(receiptPayment);
- // 澧炲姞璐㈠姟鏀跺叆璁板綍
- AccountIncome accountIncome = new AccountIncome();
- accountIncome.setIncomeDate(salesLedger.getEntryDate());
- accountIncome.setIncomeType("3");
- accountIncome.setCustomerName(salesLedger.getCustomerName());
- accountIncome.setIncomeMoney(receiptPayment.getReceiptPaymentAmount());
- accountIncome.setIncomeMethod(receiptPayment.getReceiptPaymentType());
- accountIncome.setInputTime(new Date());
- accountIncome.setInputUser(SecurityUtils.getLoginUser().getNickName());
- accountIncome.setIncomeDescribed("鍥炴鏀跺叆");
- accountIncome.setBusinessId(Long.parseLong(receiptPayment.getId().toString()));
- accountIncome.setBusinessType(1);
- accountIncomeService.save(accountIncome);
- }else {
- BigDecimal subtract = byId.getReceiptPaymentAmount().subtract(receiptPayment.getReceiptPaymentAmount());
- salesLedgerProduct.setInvoiceTotal(salesLedgerProduct.getInvoiceTotal().add(subtract));
- salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice().subtract(salesLedgerProduct.getInvoiceTotal()));
- receiptPayment.setReceiptPaymentAmount(byId.getReceiptPaymentAmount());
- receiptPayment.setReceiptPaymentType(byId.getReceiptPaymentType());
- receiptPaymentMapper.updateById(receiptPayment);
- // 淇敼璐㈠姟鏀跺叆璁板綍
- LambdaQueryWrapper<AccountIncome> accountIncomeLambdaQueryWrapper = new LambdaQueryWrapper<>();
- accountIncomeLambdaQueryWrapper.eq(AccountIncome::getBusinessId, receiptPayment.getId())
- .eq(AccountIncome::getBusinessType, 1);
- AccountIncome accountIncome = accountIncomeService.getOne(accountIncomeLambdaQueryWrapper);
- if(null!=accountIncome){
- accountIncome.setIncomeMoney(receiptPayment.getReceiptPaymentAmount());
- accountIncomeService.updateById(accountIncome);
- }
- }
- salesLedgerProductMapper.updateById(salesLedgerProduct);
- }
- return 1;
- }
-
- /**
- * 鍥炴鐧昏淇敼
- * @param receiptPayment
- * @return
- */
- @Override
- public int receiptPaymentUpdate(ReceiptPayment receiptPayment) {
- ReceiptPayment byId = receiptPayment;
- if (!ObjectUtils.isEmpty(receiptPayment.getId())){
- receiptPayment = this.getById(receiptPayment.getId());
- }
- SalesLedger salesLedger = salesLedgerMapper.selectById(receiptPayment.getSalesLedgerId());
- if(null==salesLedger) throw new RuntimeException("鏈壘鍒伴攢鍞崟");
- // 宸插洖娆鹃噾棰�
- SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(receiptPayment.getSalesLedgerProductId());
- if(null==salesLedgerProduct) throw new RuntimeException("鏈壘鍒伴攢鍞崟浜у搧");
- if (salesLedgerProduct.getPendingInvoiceTotal().compareTo(receiptPayment.getReceiptPaymentAmount())<0){
- throw new RuntimeException("鏈鍥炴閲戦涓嶈兘澶т簬寰呭洖娆鹃噾棰�");
- }
- BigDecimal subtract = receiptPayment.getReceiptPaymentAmount().subtract(byId.getReceiptPaymentAmount());
- salesLedgerProduct.setInvoiceTotal(salesLedgerProduct.getInvoiceTotal().add(subtract));
- salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice().subtract(salesLedgerProduct.getInvoiceTotal()));
- // 淇敼璐㈠姟鏀跺叆璁板綍
- LambdaQueryWrapper<AccountIncome> accountIncomeLambdaQueryWrapper = new LambdaQueryWrapper<>();
- accountIncomeLambdaQueryWrapper.eq(AccountIncome::getBusinessId, receiptPayment.getId())
- .eq(AccountIncome::getBusinessType, 1);
- AccountIncome accountIncome = accountIncomeService.getOne(accountIncomeLambdaQueryWrapper);
- if(null!=accountIncome){
- accountIncome.setIncomeMoney(receiptPayment.getReceiptPaymentAmount());
- accountIncomeService.updateById(accountIncome);
- }
- salesLedgerProductMapper.updateById(salesLedgerProduct);
- receiptPayment.setReceiptPaymentAmount(byId.getReceiptPaymentAmount());
- receiptPayment.setReceiptPaymentType(byId.getReceiptPaymentType());
- return receiptPaymentMapper.updateById(receiptPayment);
- }
-
- /**
- * 鍥炴鐧昏鍒犻櫎
- * @param ids
- * @return
- */
- @Override
- public int receiptPaymentDel(List<Integer> ids) {
- LambdaQueryWrapper<ReceiptPayment> delQuery = new LambdaQueryWrapper<>();
- delQuery.in(ReceiptPayment::getId, ids);
- List<ReceiptPayment> receiptPayments = receiptPaymentMapper.selectList(delQuery);
- if(CollectionUtils.isEmpty(receiptPayments)) throw new RuntimeException("鏈壘鍒板洖娆剧櫥璁�");
- // 閲嶆柊璁$畻閿�鍞骇鍝佸洖娆鹃噾棰�
- for (ReceiptPayment receiptPayment : receiptPayments) {
- SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(receiptPayment.getSalesLedgerProductId());
- salesLedgerProduct.setInvoiceTotal(salesLedgerProduct.getInvoiceTotal().subtract(receiptPayment.getReceiptPaymentAmount()));
- salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice().subtract(salesLedgerProduct.getInvoiceTotal()));
- salesLedgerProductMapper.updateById(salesLedgerProduct);
- }
- // 鍒犻櫎璐㈠姟鏀跺叆璁板綍
- LambdaQueryWrapper<AccountIncome> accountIncomeLambdaQueryWrapper = new LambdaQueryWrapper<>();
- accountIncomeLambdaQueryWrapper.in(AccountIncome::getBusinessId, ids)
- .eq(AccountIncome::getBusinessType, 1);
- accountIncomeService.remove(accountIncomeLambdaQueryWrapper);
- return receiptPaymentMapper.delete(delQuery);
- }
-
- /**
- * 鍥炴鐧昏鍒嗛〉鏌ヨ
- * @param page
- * @param receiptPaymentDto
- * @return
- */
- @Override
- public IPage<ReceiptPaymentDto> receiptPaymentListPage(Page page, ReceiptPaymentDto receiptPaymentDto) {
- // 璁$畻鍒嗛〉鍓峱age.current-1 * limit鏉℃暟鐨勭患鍚堣绠楀凡缁忔敹鍥炵殑鍥炴閲戦
- // 璁$畻宸茬粡鍒嗛〉鐨勬潯鏁�
- long total = (page.getCurrent() - 1) * page.getSize();
- BigDecimal receiptAmount = receiptPaymentMapper.getReceiptAmount(receiptPaymentDto.getCustomerId(), total);
- if(ObjectUtils.isEmpty(receiptAmount)){
- receiptAmount = BigDecimal.ZERO;
- }
- IPage<ReceiptPaymentDto> iPage = receiptPaymentMapper.receiptPaymentListPage(page, receiptPaymentDto);
- // 寮�绁ㄦ�婚噾棰�
- BigDecimal invoiceTotal = CollectionUtils.isEmpty(iPage.getRecords()) ? BigDecimal.ZERO : iPage.getRecords().get(0).getInvoiceTotal();
- // 褰撳墠搴旀敹閲戦
- BigDecimal currentUnReceiptAmount = invoiceTotal.subtract(receiptAmount);
- for (ReceiptPaymentDto record : iPage.getRecords()) {
- currentUnReceiptAmount = currentUnReceiptAmount.subtract(record.getReceiptPaymentAmount());
- record.setNoReceiptAmount(currentUnReceiptAmount);
- }
- return iPage;
- }
-
- /**
- * 鍥炴鐧昏璇︽儏
- * @param id
- * @return
- */
- @Override
- public ReceiptPaymentDto receiptPaymentInfo(Integer id) {
- return receiptPaymentMapper.receiptPaymentInfo(id);
- }
-
- @Override
- public BigDecimal getReceiptAmount() {
- LocalDate now = LocalDate.now();
- YearMonth currentMonth = YearMonth.from(now);
-
- // 鍒涘缓LambdaQueryWrapper
- LambdaQueryWrapper<ReceiptPayment> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.ge(ReceiptPayment::getReceiptPaymentDate, currentMonth.atDay(1).atStartOfDay()) // 澶т簬绛変簬鏈湀绗竴澶�
- .lt(ReceiptPayment::getReceiptPaymentDate, currentMonth.plusMonths(1).atDay(1).atStartOfDay()); // 灏忎簬涓嬫湀绗竴澶�
-
- // 鎵ц鏌ヨ骞惰绠楁�诲拰
- List<ReceiptPayment> receiptPayments = receiptPaymentMapper.selectList(queryWrapper);
-
- BigDecimal totalContractAmount = receiptPayments.stream()
- .map(ReceiptPayment::getReceiptPaymentAmount)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
-
- return totalContractAmount;
- }
-
- /**
- * 鏌ヨ宸茬粡缁戝畾鍙戠エ鐨勫紑绁ㄥ彴璐�
- * @param page
- * @param receiptPaymentDto
- * @return
- */
- @Override
- public IPage<ReceiptPaymentDto> bindInvoiceNoRegPage(Page page, ReceiptPaymentDto receiptPaymentDto) {
- IPage<ReceiptPaymentDto> receiptPaymentDtoIPage = receiptPaymentMapper.bindInvoiceNoRegPage(page, receiptPaymentDto);
-// if (receiptPaymentDto.getStatus()) {
-// long count = receiptPaymentDtoIPage.getRecords()
-// .stream()
-// .filter(receiptPaymentDto1 -> new BigDecimal("0.00").equals(receiptPaymentDto1.getNoReceiptAmount()))
-// .count();
-// receiptPaymentDtoIPage
-// .getRecords()
-// .removeIf(receiptPaymentDto1 -> new BigDecimal("0.00").equals(receiptPaymentDto1.getNoReceiptAmount()));
-// receiptPaymentDtoIPage.setTotal(receiptPaymentDtoIPage.getTotal() - count);
-// }
- receiptPaymentDtoIPage.getRecords().forEach(item -> {
- // 姣旇緝鍥炴閲戦 == 寰呭洖娆鹃噾棰�
- if (item.getInvoiceTotal().compareTo(item.getReceiptPaymentAmountTotal()) == 0) {
- item.setStatusName("宸插畬鎴愬洖娆�");
- }else{
- item.setStatusName("鏈畬鎴愬洖娆�");
- }
-
- });
- return receiptPaymentDtoIPage;
- }
-
- /**
- * 寮�绁ㄥ彴璐﹁鎯�
- * @param id
- * @return
- */
- @Override
- public InvoiceLedgerDto invoiceInfo(Integer id) {
- return receiptPaymentMapper.invoiceInfo(id);
- }
-
- @Override
- public Map<String,BigDecimal> getAmountMouth() {
- List<SalesLedger> salesLedgers = salesLedgerMapper.selectList(null);
- BigDecimal contractAmount = salesLedgers.stream().map(SalesLedger::getContractAmount)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
-
- LocalDate now = LocalDate.now();
- YearMonth currentMonth = YearMonth.from(now);
-
- // 鍒涘缓LambdaQueryWrapper
- LambdaQueryWrapper<ReceiptPayment> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.ge(ReceiptPayment::getReceiptPaymentDate, currentMonth.atDay(1).atStartOfDay()) // 澶т簬绛変簬鏈湀绗竴澶�
- .lt(ReceiptPayment::getReceiptPaymentDate, currentMonth.plusMonths(1).atDay(1).atStartOfDay()); // 灏忎簬涓嬫湀绗竴澶�
-
- // 鎵ц鏌ヨ骞惰绠楁�诲拰
- List<ReceiptPayment> receiptPayments = receiptPaymentMapper.selectList(queryWrapper);
-
- BigDecimal receiveAmount = receiptPayments.stream()
- .map(ReceiptPayment::getReceiptPaymentAmount)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
-
- // 鏋勫缓缁撴灉
- Map<String, BigDecimal> result = new HashMap<>();
- result.put("receiveAmount", receiveAmount);
- result.put("contractAmount", contractAmount);
- return result;
- }
-
- /**
- * 鏌ヨ鍥炴璁板綍
- */
- @Override
- public List<ReceiptPaymentDto> receiptPaymentHistoryList(ReceiptPaymentDto receiptPaymentDto) {
- return receiptPaymentMapper.receiptPaymentHistoryList(receiptPaymentDto);
- }
-
- /**
- * 鏌ヨ鍥炴璁板綍鍒嗛〉
- */
- @Override
- public IPage<ReceiptPaymentDto> receiptPaymentHistoryListPage(Page page, ReceiptPaymentDto receiptPaymentDto) {
- return receiptPaymentMapper.receiptPaymentHistoryListPage(page, receiptPaymentDto);
- }
-
- /**
- * 瀹㈡埛寰�鏉ヨ褰曟煡璇�
- * @param receiptPaymentDto
- * @return
- */
- @Override
- public List<InvoiceLedgerDto> customerInteractions(InvoiceLedgerDto receiptPaymentDto) {
- return receiptPaymentMapper.invoiceLedgerSalesAccount(receiptPaymentDto);
- }
-
- /**
- * 鏌ヨ鍥炴璁板綍鍒嗛〉
- */
- @Override
- public List<ReceiptPaymentDto> receiptPaymentHistoryListNoPage(ReceiptPaymentDto receiptPaymentDto) {
- return receiptPaymentMapper.receiptPaymentHistoryListNoPage( receiptPaymentDto);
- }
-
- @Override
- public void exportPaymentList(HttpServletResponse response) {
- List<ReceiptPaymentDto> receiptPaymentDtoList = receiptPaymentMapper.bindInvoiceNoRegListAll();
- ExcelUtil<ReceiptPaymentDto> util = new ExcelUtil<ReceiptPaymentDto>(ReceiptPaymentDto.class);
- util.exportExcel(response, receiptPaymentDtoList, "鍥炴鐧昏");
- }
-
- @Override
- public void exportPaymentList(HttpServletResponse response, List<Long> ids) {
- if (ids == null) {
- List<ReceiptPaymentExeclDto> receiptPaymentDtoList = receiptPaymentMapper.bindInvoiceNoRegListByIds(new ArrayList<>(), SecurityUtils.getLoginUser().getTenantId());
- ExcelUtil<ReceiptPaymentExeclDto> util = new ExcelUtil<ReceiptPaymentExeclDto>(ReceiptPaymentExeclDto.class);
- util.exportExcel(response, receiptPaymentDtoList, "鍥炴鐧昏");
- }else {
- List<ReceiptPaymentExeclDto> receiptPaymentDtoList = receiptPaymentMapper.bindInvoiceNoRegListByIds(ids,SecurityUtils.getLoginUser().getTenantId());
- ExcelUtil<ReceiptPaymentExeclDto> util = new ExcelUtil<ReceiptPaymentExeclDto>(ReceiptPaymentExeclDto.class);
- util.exportExcel(response, receiptPaymentDtoList, "鍥炴鐧昏");
- }
-
- }
-}
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
index 8ce023b..19aa02f 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -3,8 +3,6 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.procurementrecord.utils.StockUtils;
@@ -14,9 +12,6 @@
import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
import com.ruoyi.purchase.pojo.PurchaseLedger;
import com.ruoyi.quality.mapper.QualityInspectMapper;
-import com.ruoyi.sales.dto.InvoiceRegistrationProductDto;
-import com.ruoyi.sales.dto.SalesLedgerProductDto;
-import com.ruoyi.sales.mapper.InvoiceRegistrationProductMapper;
import com.ruoyi.sales.mapper.SalesLedgerMapper;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
import com.ruoyi.sales.mapper.ShippingInfoMapper;
@@ -76,8 +71,6 @@
@Autowired
private TechnologyBomStructureMapper technologyBomStructureMapper;
@Autowired
- private InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
- @Autowired
private ProductionProductMainMapper productionProductMainMapper;
@Autowired
private ProductionProductOutputMapper productionProductOutputMapper;
@@ -116,34 +109,6 @@
item.setExpressNumber(shippingInfo.getExpressNumber());
}
});
- // 寮�绁�
- InvoiceRegistrationProductDto invoiceRegistrationProductDto = new InvoiceRegistrationProductDto();
- invoiceRegistrationProductDto.setSalesLedgerId(salesLedgerProduct.getSalesLedgerId().intValue());
- List<InvoiceRegistrationProductDto> invoiceRegistrationProductDtoList = invoiceRegistrationProductMapper.invoiceRegistrationProductList(invoiceRegistrationProductDto);
- // 缁熻寮�绁ㄧ櫥璁颁骇鍝佺殑宸插紑绁ㄦ暟/宸插紑绁ㄩ噾棰�
- if (!CollectionUtils.isEmpty(invoiceRegistrationProductDtoList)) {
- for (SalesLedgerProduct ledgerProduct : salesLedgerProducts) {
- BigDecimal invoiceNum = BigDecimal.ZERO;
- BigDecimal invoiceAmount = BigDecimal.ZERO;
- BigDecimal noInvoiceNum = BigDecimal.ZERO;
- BigDecimal noInvoiceAmount = BigDecimal.ZERO;
- for (InvoiceRegistrationProductDto registrationProductDto : invoiceRegistrationProductDtoList) {
- if(ledgerProduct.getId().intValue() == registrationProductDto.getSalesLedgerProductId()){
- invoiceNum = invoiceNum.add(registrationProductDto.getInvoiceNum());
- invoiceAmount = invoiceAmount.add(registrationProductDto.getInvoiceAmount());
- }
- }
- noInvoiceNum = ledgerProduct.getQuantity().subtract(invoiceNum);
- noInvoiceAmount = ledgerProduct.getTaxInclusiveTotalPrice().subtract(invoiceAmount);
- ledgerProduct.setInvoiceNum(invoiceNum);
- ledgerProduct.setInvoiceAmount(invoiceAmount);
- ledgerProduct.setNoInvoiceNum(noInvoiceNum);
- ledgerProduct.setNoInvoiceAmount(noInvoiceAmount);
-
-
- }
- }
-
}
return salesLedgerProducts;
}
@@ -199,18 +164,6 @@
@Override
@Transactional(rollbackFor = Exception.class)
public int addOrUpdateSalesLedgerProduct(SalesLedgerProduct salesLedgerProduct) {
- // 寰呭洖娆撅紝浠樻
- if(salesLedgerProduct.getType().equals(1)){
- salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice().subtract(salesLedgerProduct.getInvoiceTotal()));
- //鏈紑绁ㄦ暟閲�+閲戦
- salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
- salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
- }else{
- salesLedgerProduct.setPendingTicketsTotal(salesLedgerProduct.getTaxInclusiveTotalPrice().subtract(salesLedgerProduct.getTicketsTotal()));
- // 鏈潵绁ㄦ暟閲�+閲戦
- salesLedgerProduct.setFutureTickets(salesLedgerProduct.getQuantity());
- salesLedgerProduct.setFutureTicketsAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
- }
int result;
Long salesLedgerId = salesLedgerProduct.getSalesLedgerId();
@@ -220,7 +173,6 @@
addProductionData(salesLedgerProduct);
} else {
//鏌ヨ鍘熸湰鐨勪骇鍝佸瀷鍙穒d
- salesLedgerProduct.setFutureTickets(salesLedgerProduct.getQuantity());
result = salesLedgerProductMapper.updateById(salesLedgerProduct);
/*鍒犻櫎瀵瑰簲鐨勭敓浜ф暟鎹苟閲嶆柊鏂板*/
deleteProductionData(Arrays.asList(salesLedgerProduct.getId()));
@@ -285,6 +237,9 @@
* 鍒犻櫎鐢熶骇璁″垝
*/
public void deleteProductionData(List<Long> productIds) {
+ if (CollectionUtils.isEmpty(productIds)) {
+ return;
+ }
List<ProductionPlan> productionPlans = productionPlanMapper.selectList(
new LambdaQueryWrapper<ProductionPlan>()
.in(ProductionPlan::getSalesLedgerProductId, productIds.stream().map(Long::intValue).collect(Collectors.toList())));
@@ -297,34 +252,6 @@
}
List<Long> ids = productionPlans.stream().map(ProductionPlan::getId).collect(Collectors.toList());
productionPlanMapper.deleteByIds(ids);
- }
-
- @Override
- public IPage<SalesLedgerProductDto> listPage(Page page, SalesLedgerProductDto salesLedgerProduct) {
- IPage<SalesLedgerProductDto> salesLedgerProductDtoIPage = salesLedgerProductMapper.listPage(page, salesLedgerProduct);
- salesLedgerProductDtoIPage.getRecords().forEach(item -> {
- // 鍒ゆ柇鐘舵��
- if(item.getTaxInclusiveTotalPrice().compareTo(item.getInvoiceTotal()) == 0){
- item.setStatusName("宸插畬鎴愪粯娆�");
- }else{
- item.setStatusName("鏈畬鎴愪粯娆�");
- }
- });
- return salesLedgerProductDtoIPage;
- }
-
- @Override
- public IPage<SalesLedgerProductDto> listPagePurchaseLedger(Page page, SalesLedgerProductDto salesLedgerProduct) {
- IPage<SalesLedgerProductDto> salesLedgerProductDtoIPage = salesLedgerProductMapper.listPagePurchaseLedger(page, salesLedgerProduct);
- salesLedgerProductDtoIPage.getRecords().forEach(item -> {
- // 鍒ゆ柇鐘舵��
- if(item.getTaxInclusiveTotalPrice().compareTo(item.getTicketsTotal()) == 0){
- item.setStatusName("宸插畬鎴愪粯娆�");
- }else{
- item.setStatusName("鏈畬鎴愪粯娆�");
- }
- });
- return salesLedgerProductDtoIPage;
}
/**
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
index a2f918b..7b71ef3 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -8,7 +8,10 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.account.service.AccountIncomeService;
+import com.ruoyi.account.mapper.sales.AccountInvoiceApplicationMapper;
+import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper;
+import com.ruoyi.account.pojo.sales.AccountInvoiceApplication;
+import com.ruoyi.account.pojo.sales.AccountSalesCollection;
import com.ruoyi.basic.enums.ApplicationTypeEnum;
import com.ruoyi.basic.enums.RecordTypeEnum;
import com.ruoyi.basic.mapper.CustomerMapper;
@@ -27,8 +30,9 @@
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.other.mapper.TempFileMapper;
-import com.ruoyi.other.pojo.TempFile;
-import com.ruoyi.production.mapper.*;
+import com.ruoyi.production.mapper.ProductionProductInputMapper;
+import com.ruoyi.production.mapper.ProductionProductMainMapper;
+import com.ruoyi.production.mapper.ProductionProductOutputMapper;
import com.ruoyi.production.service.ProductionProductMainService;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysUser;
@@ -38,13 +42,18 @@
import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper;
import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.sales.dto.*;
-import com.ruoyi.sales.mapper.*;
-import com.ruoyi.sales.pojo.*;
+import com.ruoyi.sales.mapper.CommonFileMapper;
+import com.ruoyi.sales.mapper.SalesLedgerMapper;
+import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
+import com.ruoyi.sales.mapper.ShippingInfoMapper;
+import com.ruoyi.sales.pojo.CommonFile;
+import com.ruoyi.sales.pojo.SalesLedger;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.sales.pojo.ShippingInfo;
import com.ruoyi.sales.service.ISalesLedgerService;
import com.ruoyi.sales.vo.SalesLedgerVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.io.FilenameUtils;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -54,16 +63,12 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
@@ -86,26 +91,23 @@
private static final String LOCK_PREFIX = "contract_no_lock:";
private static final long LOCK_WAIT_TIMEOUT = 10; // 閿佺瓑寰呰秴鏃舵椂闂达紙绉掞級
private static final long LOCK_EXPIRE_TIME = 30; // 閿佽嚜鍔ㄨ繃鏈熸椂闂达紙绉掞級
- private final AccountIncomeService accountIncomeService;
private final SalesLedgerMapper salesLedgerMapper;
private final CustomerMapper customerMapper;
private final SalesLedgerProductMapper salesLedgerProductMapper;
private final SalesLedgerProductServiceImpl salesLedgerProductServiceImpl;
private final CommonFileMapper commonFileMapper;
private final TempFileMapper tempFileMapper;
- private final ReceiptPaymentMapper receiptPaymentMapper;
private final ShippingInfoServiceImpl shippingInfoServiceImpl;
private final CommonFileServiceImpl commonFileService;
private final ShippingInfoMapper shippingInfoMapper;
- private final InvoiceLedgerMapper invoiceLedgerMapper;
- private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
- private final InvoiceRegistrationMapper invoiceRegistrationMapper;
private final ProductionProductMainMapper productionProductMainMapper;
private final ProductionProductOutputMapper productionProductOutputMapper;
private final ProductionProductInputMapper productionProductInputMapper;
private final QualityInspectMapper qualityInspectMapper;
private final RedisTemplate<String, String> redisTemplate;
private final FileUtil fileUtil;
+ private final AccountInvoiceApplicationMapper accountInvoiceApplicationMapper;
+ private final AccountSalesCollectionMapper accountSalesCollectionMapper;
@Autowired
private SysDeptMapper sysDeptMapper;
@@ -176,10 +178,6 @@
productWrapper.eq(SalesLedgerProduct::getType, 1);
List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper);
for (SalesLedgerProduct product : products) {
- product.setOriginalNoInvoiceNum(product.getNoInvoiceNum());
- // 鎻愪緵涓存椂鏈紑绁ㄦ暟锛屾湭寮�绁ㄩ噾棰濅緵鍓嶆璁$畻
- product.setTempnoInvoiceAmount(product.getNoInvoiceAmount());
- product.setTempNoInvoiceNum(product.getNoInvoiceNum());
product.setRegister(SecurityUtils.getLoginUser().getUser().getNickName());
product.setRegisterDate(LocalDateTime.now());
// 鍙戣揣淇℃伅
@@ -280,51 +278,37 @@
@Override
public List<MonthlyAmountDto> getAmountHalfYear(Integer type) {
-
LocalDate now = LocalDate.now();
List<MonthlyAmountDto> result = new ArrayList<>();
-
for (int i = 5; i >= 0; i--) {
YearMonth yearMonth = YearMonth.from(now.minusMonths(i));
- LocalDateTime startTime = yearMonth.atDay(1).atStartOfDay();
- LocalDateTime endTime = yearMonth.atEndOfMonth().atTime(23, 59, 59);
-
- // 鍥炴閲戦
- LambdaQueryWrapper<ReceiptPayment> receiptPaymentQuery = new LambdaQueryWrapper<>();
- receiptPaymentQuery
- .ge(ReceiptPayment::getCreateTime, startTime)
- .le(ReceiptPayment::getCreateTime, endTime);
-
- List<ReceiptPayment> receiptPayments =
- receiptPaymentMapper.selectList(receiptPaymentQuery);
-
- BigDecimal receiptAmount = receiptPayments.stream()
- .map(ReceiptPayment::getReceiptPaymentAmount)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
-
- // 寮�绁ㄩ噾棰�
- LambdaQueryWrapper<InvoiceLedger> invoiceLedgerQuery = new LambdaQueryWrapper<>();
- invoiceLedgerQuery
- .ge(InvoiceLedger::getCreateTime, startTime)
- .le(InvoiceLedger::getCreateTime, endTime);
-
- List<InvoiceLedger> invoiceLedgers =
- invoiceLedgerMapper.selectList(invoiceLedgerQuery);
-
- BigDecimal invoiceAmount = invoiceLedgers.stream()
- .map(InvoiceLedger::getInvoiceTotal)
- .filter(Objects::nonNull)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
-
+ LocalDate startTime = yearMonth.atDay(1);
+ LocalDate endTime = yearMonth.atEndOfMonth();
MonthlyAmountDto dto = new MonthlyAmountDto();
dto.setMonth(yearMonth.format(DateTimeFormatter.ofPattern("yyyy-MM")));
- dto.setReceiptAmount(receiptAmount);
- dto.setInvoiceAmount(invoiceAmount);
-
+ //鍥炴閲戦
+ List<AccountSalesCollection> accountSalesCollections = accountSalesCollectionMapper.selectList(new LambdaQueryWrapper<AccountSalesCollection>()
+ .between(AccountSalesCollection::getCollectionDate, startTime, endTime));
+ BigDecimal totalIncome = Optional.of(
+ accountSalesCollections.stream()
+ .map(AccountSalesCollection::getCollectionAmount)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add)
+ ).orElse(BigDecimal.ZERO);
+ dto.setReceiptAmount(totalIncome);
+ //寮�绁ㄩ噾棰�
+ List<AccountInvoiceApplication> accountInvoiceApplications = accountInvoiceApplicationMapper.selectList(new LambdaQueryWrapper<AccountInvoiceApplication>()
+ .eq(AccountInvoiceApplication::getStatus,1)
+ .between(AccountInvoiceApplication::getApplyDate, startTime, endTime));
+ BigDecimal totalInvoiceAmount = Optional.of(
+ accountInvoiceApplications.stream()
+ .map(AccountInvoiceApplication::getInvoiceAmount)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add)
+ ).orElse(BigDecimal.ZERO);
+ dto.setInvoiceAmount(totalInvoiceAmount);
result.add(dto);
}
-
return result;
}
@@ -347,9 +331,17 @@
if (CollectionUtils.isEmpty(salesLedgerImportDtoList)) return AjaxResult.error("閿�鍞彴璐︽暟鎹负绌猴紒");
List<SalesLedgerImportDto> salesLedgerProductImportDtoList = stringListMap.get("閿�鍞骇鍝佹暟鎹�");
if (CollectionUtils.isEmpty(salesLedgerProductImportDtoList)) return AjaxResult.error("閿�鍞骇鍝佹暟鎹负绌猴紒");
- // 瀹㈡埛鏁版嵁
- List<Customer> customers = customerMapper.selectList(new LambdaQueryWrapper<Customer>().in(Customer::getCustomerName,
- salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getCustomerName).collect(Collectors.toList())));
+ // 瀹㈡埛鏁版嵁 - 鍙傝�� listPage 鏌ヨ绉佹捣瀹㈡埛锛坱ype = 0锛�
+ // type = 0锛堢娴峰鎴凤級鎴栬�� type = 1锛堝叕娴峰鎴凤級涓斿凡琚垎閰嶏紝骞朵笖鏄嚜宸遍鐢ㄣ�佽嚜宸卞垱寤烘垨鑰呭叡浜粰鑷繁鐨勫鎴�
+ Long loginUserId = loginUser.getUser().getUserId();
+ List<Customer> customers = customerMapper.selectList(new QueryWrapper<Customer>()
+ .in("customer_name", salesLedgerImportDtoList.stream()
+ .map(SalesLedgerImportDto::getCustomerName).collect(Collectors.toList()))
+ .and(wrapper -> wrapper.eq("type", 0)
+ .or(wrapper2 -> wrapper2.eq("type", 1).eq("is_assigned", 1)))
+ .and(wrapper -> wrapper.eq("usage_user", loginUserId)
+ .or(wrapper2 -> wrapper2.eq("create_user", loginUserId)
+ .or(wrapper3 -> wrapper3.exists("select 1 from customer_user cu where cu.customer_id = customer.id and cu.user_id = " + loginUserId)))));
// // 瑙勬牸鍨嬪彿鏁版嵁
// List<ProductModel> productModels = productModelMapper.selectList(new LambdaQueryWrapper<ProductModel>().in(ProductModel::getModel,
// salesLedgerProductImportDtoList.stream().map(SalesLedgerImportDto::getSpecificationModel).collect(Collectors.toList())));
@@ -367,20 +359,26 @@
if (salesLedger1 != null) {
continue;
}
+
+ // 鍒ゆ柇涓氬姟鍛樻槸鍚﹀瓨鍦�
+ SysUser salesman = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>()
+ .eq(SysUser::getNickName, salesLedgerImportDto.getSalesman()));
+ if (salesman == null) {
+ throw new RuntimeException("涓氬姟鍛�:" + salesLedgerImportDto.getSalesman() + "涓嶅瓨鍦紒");
+ }
SalesLedger salesLedger = new SalesLedger();
BeanUtils.copyProperties(salesLedgerImportDto, salesLedger);
salesLedger.setExecutionDate(DateUtils.toLocalDate(salesLedgerImportDto.getExecutionDate()));
+ salesLedger.setDeliveryDate(DateUtils.toLocalDate(salesLedgerImportDto.getDeliveryDate()));
// 閫氳繃瀹㈡埛鍚嶇О鏌ヨ瀹㈡埛ID锛屽鎴峰悎鍚屽彿
- salesLedger.setCustomerId(customers.stream()
+ Optional<Customer> customerOptional = customers.stream()
.filter(customer -> customer.getCustomerName().equals(salesLedger.getCustomerName()))
- .findFirst()
- .map(Customer::getId)
- .orElse(null));
- salesLedger.setCustomerContractNo(customers.stream()
- .filter(customer -> customer.getCustomerName().equals(salesLedger.getCustomerName()))
- .findFirst()
- .map(Customer::getTaxpayerIdentificationNumber)
- .orElse(null));
+ .findFirst();
+ if (customerOptional.isEmpty()) {
+ throw new RuntimeException("瀹㈡埛:" + salesLedger.getCustomerName() + "涓嶅瓨鍦紒鎴栬�呴潪绉佹捣鐢ㄦ埛");
+ }
+ salesLedger.setCustomerId(customerOptional.get().getId());
+ salesLedger.setCustomerContractNo(customerOptional.get().getTaxpayerIdentificationNumber());
Long aLong = sysUsers.stream()
.filter(sysUser -> sysUser.getNickName().equals(salesLedger.getEntryPerson()))
.findFirst()
@@ -408,15 +406,16 @@
salesLedgerProduct.setType(1);
// 璁$畻涓嶅惈绋庢�讳环
salesLedgerProduct.setTaxExclusiveTotalPrice(salesLedgerProduct.getTaxInclusiveTotalPrice().divide(new BigDecimal(1).add(salesLedgerProduct.getTaxRate().divide(new BigDecimal(100))), 2, RoundingMode.HALF_UP));
- salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
- salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxExclusiveTotalPrice());
- list.stream()
- .filter(map -> map.get("productName").equals(salesLedgerProduct.getProductCategory()) && map.get("model").equals(salesLedgerProduct.getSpecificationModel()))
- .findFirst()
- .ifPresent(map -> {
- salesLedgerProduct.setProductModelId(Long.parseLong(map.get("modelId").toString()));
- salesLedgerProduct.setProductId(Long.parseLong(map.get("id").toString()));
- });
+ // 鏍¢獙浜у搧瑙勬牸鏄惁瀛樺湪
+ Optional<Map<String, Object>> productModelOptional = list.stream()
+ .filter(map -> Objects.equals(map.get("productName"), salesLedgerProduct.getProductCategory()) && Objects.equals(map.get("model"), salesLedgerProduct.getSpecificationModel()))
+ .findFirst();
+ if (productModelOptional.isEmpty()) {
+ throw new RuntimeException("浜у搧澶х被:" + salesLedgerProduct.getProductCategory() + ",瑙勬牸鍨嬪彿:" + salesLedgerProduct.getSpecificationModel() + "涓嶅瓨鍦紒");
+ }
+ Map<String, Object> productModelMap = productModelOptional.get();
+ salesLedgerProduct.setProductModelId(Long.parseLong(productModelMap.get("modelId").toString()));
+ salesLedgerProduct.setProductId(Long.parseLong(productModelMap.get("id").toString()));
// salesLedgerProduct.setProductId(productList.stream()
// .filter(product -> product.getProductName().equals(salesLedgerProduct.getProductCategory()))
// .findFirst()
@@ -430,7 +429,7 @@
salesLedgerProduct.setRegister(loginUser.getNickName());
salesLedgerProduct.setRegisterDate(LocalDateTime.now());
salesLedgerProduct.setApproveStatus(0);
- salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProductImportDto.getTaxInclusiveTotalPrice());
+ salesLedgerProduct.setIsProduction(salesLedgerProductImportDto.getIsProduction() == 1);
salesLedgerProductMapper.insert(salesLedgerProduct);
// 娣诲姞鐢熶骇鏁版嵁
salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
@@ -440,8 +439,8 @@
return AjaxResult.success("瀵煎叆鎴愬姛");
} catch (Exception e) {
e.printStackTrace();
+ return AjaxResult.error("瀵煎叆澶辫触锛�" + e.getMessage());
}
- return AjaxResult.success("瀵煎叆澶辫触");
}
@Override
@@ -463,11 +462,7 @@
productWrapper.eq(SalesLedgerProduct::getType, 1);
List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper);
for (SalesLedgerProduct product : products) {
- product.setOriginalNoInvoiceNum(product.getNoInvoiceNum());
- // 鎻愪緵涓存椂鏈紑绁ㄦ暟锛屾湭寮�绁ㄩ噾棰濅緵鍓嶆璁$畻
- product.setTempnoInvoiceAmount(product.getNoInvoiceAmount());
- product.setTempNoInvoiceNum(product.getNoInvoiceNum());
- product.setRegister(SecurityUtils.getLoginUser().getUser().getNickName());
+ product.setRegister(SecurityUtils.getLoginUser().getUser().getNickName());
product.setRegisterDate(LocalDateTime.now());
// 鍙戣揣淇℃伅
ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
@@ -540,29 +535,8 @@
salesLedgerProductMapper.deleteBatchIds(productIds);
}
- LambdaQueryWrapper<InvoiceRegistrationProduct> wrapper = new LambdaQueryWrapper<>();
- wrapper.in(InvoiceRegistrationProduct::getSalesLedgerId, idList);
- List<InvoiceRegistrationProduct> invoiceRegistrationProducts = invoiceRegistrationProductMapper.selectList(wrapper);
List<Integer> invoiceLedgerIds = new ArrayList<>();
- if (CollectionUtils.isNotEmpty(invoiceRegistrationProducts)) {
- LambdaQueryWrapper<InvoiceLedger> wrapperOne = new LambdaQueryWrapper<>();
- wrapperOne.in(InvoiceLedger::getInvoiceRegistrationProductId, invoiceRegistrationProducts.stream().map(InvoiceRegistrationProduct::getId).collect(Collectors.toList()));
- List<InvoiceLedger> invoiceLedgers = invoiceLedgerMapper.selectList(wrapperOne);
- if (CollectionUtils.isNotEmpty(invoiceLedgers)) {
- invoiceLedgerIds = invoiceLedgers.stream().map(InvoiceLedger::getId).collect(Collectors.toList());
- }
- invoiceLedgerMapper.delete(wrapperOne);
- }
- invoiceRegistrationProductMapper.delete(wrapper);
- LambdaQueryWrapper<InvoiceRegistration> wrapperTwo = new LambdaQueryWrapper<>();
- wrapperTwo.in(InvoiceRegistration::getSalesLedgerId, idList);
- invoiceRegistrationMapper.delete(wrapperTwo);
- if (CollectionUtils.isNotEmpty(invoiceLedgerIds)) {
- LambdaQueryWrapper<ReceiptPayment> wrapperTree = new LambdaQueryWrapper<>();
- wrapperTree.in(ReceiptPayment::getInvoiceLedgerId, invoiceLedgerIds);
- receiptPaymentMapper.delete(wrapperTree);
- }
// 鍒犻櫎鍙戣揣鍙拌处璁板綍
List<ShippingInfo> shippingInfos = shippingInfoMapper.selectList(new LambdaQueryWrapper<ShippingInfo>()
.in(ShippingInfo::getSalesLedgerId, idList));
@@ -599,7 +573,10 @@
salesLedger.setTenantId(customer.getTenantId());
// 3. 鏂板鎴栨洿鏂颁富琛�
if (salesLedger.getId() == null) {
- String contractNo = generateSalesContractNo();
+ String contractNo = salesLedger.getSalesContractNo();
+ if (StringUtils.isEmpty(contractNo)) {
+ contractNo = generateSalesContractNo(salesLedgerDto.getEntryDate());
+ }
salesLedger.setSalesContractNo(contractNo);
salesLedgerMapper.insert(salesLedger);
} else {
@@ -647,9 +624,6 @@
if (!insertList.isEmpty()) {
for (SalesLedgerProduct salesLedgerProduct : insertList) {
salesLedgerProduct.setType(type.getCode());
- salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
- salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
- salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
salesLedgerProductMapper.insert(salesLedgerProduct);
// 娣诲姞鐢熶骇鏁版嵁
salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
@@ -664,8 +638,8 @@
}
@Transactional(readOnly = true)
- public String generateSalesContractNo() {
- LocalDate currentDate = LocalDate.now();
+ public String generateSalesContractNo(Date entryDate) {
+ LocalDate currentDate = entryDate != null ? DateUtils.toLocalDate(entryDate) : LocalDate.now();
String datePart = currentDate.format(DateTimeFormatter.BASIC_ISO_DATE);
String lockKey = LOCK_PREFIX + datePart;
String lockValue = Thread.currentThread().getId() + "-" + System.nanoTime(); // 鍞竴鏍囪瘑閿佹寔鏈夎��
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesQuotationServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesQuotationServiceImpl.java
index de86ad0..983e717 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesQuotationServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesQuotationServiceImpl.java
@@ -7,10 +7,13 @@
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.approve.pojo.ApproveProcess;
-import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl;
+import com.ruoyi.approve.bean.dto.ApprovalInstanceDto;
import com.ruoyi.approve.bean.vo.ApproveGetAndUpdateVo;
import com.ruoyi.approve.bean.vo.ApproveProcessVO;
+import com.ruoyi.approve.mapper.ApprovalTemplateMapper;
+import com.ruoyi.approve.pojo.ApproveProcess;
+import com.ruoyi.approve.service.ApprovalInstanceService;
+import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl;
import com.ruoyi.basic.mapper.CustomerMapper;
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.common.enums.IsDeleteEnum;
@@ -30,8 +33,8 @@
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
-import java.util.Collections;
-import java.util.List;
+import java.time.LocalDateTime;
+import java.util.*;
import java.util.stream.Collectors;
@Service
@@ -44,6 +47,8 @@
private final ApproveProcessServiceImpl approveProcessService;
private final CustomerMapper customerMapper;
+ private final ApprovalTemplateMapper approvalTemplateMapper;
+ private final ApprovalInstanceService approvalInstanceService;
@Override
public IPage<SalesQuotationDto> listPage(Page page, SalesQuotationDto salesQuotationDto) {
@@ -51,10 +56,26 @@
if(CollectionUtils.isEmpty(salesQuotationDtoIPage.getRecords())){
return salesQuotationDtoIPage;
}
- salesQuotationDtoIPage.getRecords().forEach(record -> {
- List<SalesQuotationProduct> products = salesQuotationProductMapper.selectBySalesQuotationId(record.getId());
- record.setProducts(products);
- });
+
+ // 鎵归噺鏌ヨ浜у搧锛岄伩鍏� N+1 闂
+ List<Long> quotationIds = salesQuotationDtoIPage.getRecords().stream()
+ .map(SalesQuotationDto::getId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+
+ if (!quotationIds.isEmpty()) {
+ List<SalesQuotationProduct> allProducts = salesQuotationProductMapper.selectList(
+ new LambdaQueryWrapper<SalesQuotationProduct>()
+ .in(SalesQuotationProduct::getSalesQuotationId, quotationIds)
+ );
+
+ Map<Long, List<SalesQuotationProduct>> productMap = allProducts.stream()
+ .collect(Collectors.groupingBy(SalesQuotationProduct::getSalesQuotationId));
+
+ salesQuotationDtoIPage.getRecords().forEach(record ->
+ record.setProducts(productMap.getOrDefault(record.getId(), new ArrayList<>()))
+ );
+ }
return salesQuotationDtoIPage;
}
@@ -93,10 +114,21 @@
approveProcessVO.setPrice(salesQuotationDto.getTotalAmount());
try {
approveProcessService.addApprove(approveProcessVO);
- }catch (Exception e){
- log.error("SalesQuotationServiceImpl error:{}", e);
- throw new RuntimeException("瀹℃壒澶辫触");
+ } catch (Exception e) {
+ log.error("SalesQuotationServiceImpl approve error for quotationNo: {}", e);
+ throw new RuntimeException("瀹℃壒澶辫触: " + e.getMessage(), e);
}
+ // 鎶ヤ环瀹℃壒
+ ApprovalInstanceDto approvalInstanceDto = new ApprovalInstanceDto();
+ approvalInstanceDto.setTemplateId(salesQuotationDto.getTemplateId());
+ approvalInstanceDto.setBusinessId(salesQuotationDto.getId());
+ approvalInstanceDto.setBusinessType(7L);
+ approvalInstanceDto.setTitle("鎶ヤ环缂栧彿锛�" + quotationNo);
+ approvalInstanceDto.setApplicantId(SecurityUtils.getUserId());
+ approvalInstanceDto.setTemplateName(approvalTemplateMapper.selectById(salesQuotationDto.getTemplateId()).getTemplateName());
+ approvalInstanceDto.setApplicantName(SecurityUtils.getLoginUser().getNickName());
+ approvalInstanceDto.setApplyTime(LocalDateTime.now());
+ approvalInstanceService.add(approvalInstanceDto);
return true;
}
@Override
diff --git a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
index 8d16029..0a84bf9 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
@@ -26,6 +26,7 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@@ -89,10 +90,14 @@
}
@Override
+ @Transactional(rollbackFor = Exception.class)
public boolean delete(List<Long> ids) {
List<ShippingInfo> shippingInfos = shippingInfoMapper.selectList(new LambdaQueryWrapper<ShippingInfo>()
.in(ShippingInfo::getId, ids));
if (CollectionUtils.isEmpty(shippingInfos)) return false;
+ // 鍙湁寰呭鏍哥姸鎬佹墠鑳藉垹闄�
+ boolean allPending = shippingInfos.stream().allMatch(s -> "寰呭鏍�".equals(s.getStatus()));
+ if (!allPending) throw new RuntimeException("鍙湁寰呭鏍哥姸鎬佹墠鑳藉垹闄�");
// 鍒犻櫎闄勪欢
commonFileService.deleteByBusinessIds(ids, FileNameType.SHIP.getValue());
// 鍒犻櫎鍙戣揣瀹℃壒
diff --git a/src/main/java/com/ruoyi/sales/vo/CustomerTransactionsDetailsVo.java b/src/main/java/com/ruoyi/sales/vo/CustomerTransactionsDetailsVo.java
new file mode 100644
index 0000000..992860e
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/vo/CustomerTransactionsDetailsVo.java
@@ -0,0 +1,33 @@
+package com.ruoyi.sales.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@Data
+@Schema(name = "CustomerTransactionsDetailsVo", description = "钀ラ攢绠$悊--瀹㈡埛寰�鏉ユ槑缁�(杩斿洖)")
+public class CustomerTransactionsDetailsVo {
+
+ @Schema(description = "閿�鍞崟ID")
+ private Long salesLedgerId;
+
+ @Schema(description = "閿�鍞悎鍚屽彿")
+ private String salesContractNo;
+
+ @Schema(description = "閿�鍞悎鍚岀璁㈡棩鏈�")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ private LocalDate executionDate;
+
+ @Schema(description = "鍚堝悓閲戦")
+ private BigDecimal contractAmount;
+
+ @Schema(description = "鏀舵閲戦")
+ private BigDecimal receiptPaymentAmount;
+
+ @Schema(description = "搴旀敹閲戦")
+ private BigDecimal receiptableAmount;
+
+}
diff --git a/src/main/java/com/ruoyi/sales/vo/CustomerTransactionsVo.java b/src/main/java/com/ruoyi/sales/vo/CustomerTransactionsVo.java
new file mode 100644
index 0000000..7b8fc1a
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/vo/CustomerTransactionsVo.java
@@ -0,0 +1,30 @@
+package com.ruoyi.sales.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+@Schema(name = "CustomerTransactionsVo", description = "钀ラ攢绠$悊--瀹㈡埛寰�鏉�(杩斿洖)")
+public class CustomerTransactionsVo {
+
+ @Schema(description = "瀹㈡埛ID")
+ private Long customerId;
+
+ @Schema(description = "瀹㈡埛鍚嶇О")
+ private String customerName;
+
+ @Schema(description = "鍚堝悓鎬婚噾棰�")
+ //璇ュ鎴烽攢鍞悎鍚岀疮璁¢噾棰�
+ private BigDecimal contractAmounts;
+
+ @Schema(description = "鏀舵閲戦")
+ //璇ュ鎴烽攢鍞敹娆剧疮璁¢噾棰�
+ private BigDecimal receiptPaymentAmount;
+
+ @Schema(description = "搴旀敹閲戦")
+ //璇ュ鎴烽攢鍞簲鏀剁疮璁¢噾棰�=璐㈠姟(鍑哄簱-閫�璐�)
+ private BigDecimal receiptableAmount;
+
+}
diff --git a/src/main/java/com/ruoyi/staff/controller/StaffOnJobController.java b/src/main/java/com/ruoyi/staff/controller/StaffOnJobController.java
index ab27019..8eb5334 100644
--- a/src/main/java/com/ruoyi/staff/controller/StaffOnJobController.java
+++ b/src/main/java/com/ruoyi/staff/controller/StaffOnJobController.java
@@ -39,7 +39,7 @@
* @return
*/
@GetMapping("/listPage")
- public AjaxResult staffOnJobListPage(Page page, StaffOnJob staffOnJob) {
+ public AjaxResult staffOnJobListPage(Page page, StaffOnJobDto staffOnJob) {
return AjaxResult.success(staffOnJobService.staffOnJobListPage(page, staffOnJob));
}
diff --git a/src/main/java/com/ruoyi/staff/dto/StaffOnJobDto.java b/src/main/java/com/ruoyi/staff/dto/StaffOnJobDto.java
index 0a2c0ae..69fdbe8 100644
--- a/src/main/java/com/ruoyi/staff/dto/StaffOnJobDto.java
+++ b/src/main/java/com/ruoyi/staff/dto/StaffOnJobDto.java
@@ -25,4 +25,6 @@
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date contractEndTime;
+
+ private Long sysDeptId;
}
diff --git a/src/main/java/com/ruoyi/staff/mapper/StaffOnJobMapper.java b/src/main/java/com/ruoyi/staff/mapper/StaffOnJobMapper.java
index de8a3c0..7cad87f 100644
--- a/src/main/java/com/ruoyi/staff/mapper/StaffOnJobMapper.java
+++ b/src/main/java/com/ruoyi/staff/mapper/StaffOnJobMapper.java
@@ -14,7 +14,7 @@
@Mapper
public interface StaffOnJobMapper extends BaseMapper<StaffOnJob> {
- IPage<StaffOnJobDto> staffOnJobListPage(Page page, @Param("staffOnJob") StaffOnJob staffOnJob);
+ IPage<StaffOnJobDto> staffOnJobListPage(Page page, @Param("staffOnJob") StaffOnJobDto staffOnJob);
List<StaffOnJobDto> staffOnJobList(@Param("staffOnJob") StaffOnJob staffOnJob);
@@ -42,4 +42,4 @@
* @return 鍛樺伐鏁版嵁
*/
StaffOnJob selectStaffByNickName(String staffName);
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/ruoyi/staff/service/IStaffOnJobService.java b/src/main/java/com/ruoyi/staff/service/IStaffOnJobService.java
index a859d14..46588d1 100644
--- a/src/main/java/com/ruoyi/staff/service/IStaffOnJobService.java
+++ b/src/main/java/com/ruoyi/staff/service/IStaffOnJobService.java
@@ -14,7 +14,7 @@
public interface IStaffOnJobService extends IService<StaffOnJob> {
- IPage<StaffOnJobDto> staffOnJobListPage(Page page, StaffOnJob staffOnJob);
+ IPage<StaffOnJobDto> staffOnJobListPage(Page page, StaffOnJobDto staffOnJob);
StaffOnJobDto staffOnJobDetail(Long id);
diff --git a/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
index 548323d..4978d0f 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
@@ -59,6 +59,7 @@
StaffLeave staffLeave = new StaffLeave();
staffLeave.setStaffOnJobId(staffLeaveDto.getStaffOnJobId());
staffLeave.setReason(staffLeaveDto.getReason());
+ staffLeave.setLeaveDate(staffLeaveDto.getLeaveDate());
String reason = staffLeaveDto.getReason();
if (StaffLeaveReasonOther.getCode().equals(reason)){
staffLeave.setRemark(staffLeaveDto.getRemark());
diff --git a/src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java
index 7c11041..1f20da2 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java
@@ -7,6 +7,7 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.dto.WordDateDto;
import com.ruoyi.project.system.domain.SysDept;
@@ -67,8 +68,9 @@
//鍦ㄨ亴鍛樺伐鍙拌处鍒嗛〉鏌ヨ
@Override
- public IPage<StaffOnJobDto> staffOnJobListPage(Page page, StaffOnJob staffOnJob) {
- return staffOnJobMapper.staffOnJobListPage(page,staffOnJob);
+ public IPage<StaffOnJobDto> staffOnJobListPage(Page page, StaffOnJobDto staffOnJob) {
+ IPage<StaffOnJobDto> staffOnJobDtoIPage = staffOnJobMapper.staffOnJobListPage(page, staffOnJob);
+ return staffOnJobDtoIPage;
}
//鏂板鍏ヨ亴
@@ -83,6 +85,7 @@
}
// 鍒涘缓鍏ヨ亴鏁版嵁
+ syncStudyInfoFromEducation(staffOnJobPrams);
staffOnJobPrams.setContractExpireTime(staffOnJobPrams.getContractEndTime());
staffOnJobPrams.setStaffState(1);
staffOnJobMapper.insert(staffOnJobPrams);
@@ -141,6 +144,7 @@
// 缁戝畾瀛愯〃鏁版嵁
bingingStaffOnJobExtra(id,staffOnJobParams);
// 鏇存柊鍛樺伐鏁版嵁
+ syncStudyInfoFromEducation(staffOnJobParams);
staffOnJobParams.setContractExpireTime(staffOnJobParams.getContractEndTime());
return staffOnJobMapper.updateById(staffOnJobParams);
}
@@ -158,6 +162,7 @@
.forEach(staff -> staff.setStaffOnJobId(id)); // 璧嬪��
staffEducationService.saveBatch(staffOnJobPrams.getStaffEducationList());
}
+
// 鏂板宸ヤ綔缁忓巻
if(CollectionUtils.isNotEmpty(staffOnJobPrams.getStaffWorkExperienceList())){
staffOnJobPrams.getStaffWorkExperienceList().stream()
@@ -174,6 +179,28 @@
}
}
+ private void syncStudyInfoFromEducation(StaffOnJob staffOnJobPrams) {
+ if (staffOnJobPrams == null || CollectionUtils.isEmpty(staffOnJobPrams.getStaffEducationList())) {
+ if (staffOnJobPrams != null) {
+ staffOnJobPrams.setFirstStudy("/");
+ staffOnJobPrams.setProfession("/");
+ }
+ return;
+ }
+ Optional<StaffEducation> matchedEducation = staffOnJobPrams.getStaffEducationList().stream()
+ .filter(Objects::nonNull)
+ .filter(education -> StringUtils.isNotEmpty(education.getMajor()))
+ .findFirst();
+ if (matchedEducation.isPresent()) {
+ StaffEducation education = matchedEducation.get();
+ staffOnJobPrams.setFirstStudy(education.getEducation());
+ staffOnJobPrams.setProfession(education.getMajor());
+ return;
+ }
+ staffOnJobPrams.setFirstStudy("/");
+ staffOnJobPrams.setProfession("/");
+ }
+
/**
* 閫氳繃鍛樺伐id鍒犻櫎鏁欒偛缁忓巻锛屽伐浣滅粡鍘嗭紝绱ф�ヨ仈绯讳汉
diff --git a/src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java
index a6d4500..aad785a 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java
@@ -3,9 +3,6 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.account.mapper.AccountExpenseMapper;
-import com.ruoyi.account.pojo.AccountExpense;
-import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.system.mapper.SysUserDeptMapper;
@@ -23,7 +20,6 @@
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -45,7 +41,6 @@
private final SchemeApplicableStaffServiceImpl schemeApplicableStaffService;
private final SysUserDeptMapper sysUserDeptMapper;
private final StaffLeaveMapper staffLeaveMapper;
- private final AccountExpenseMapper accountExpenseMapper;
@Override
public AjaxResult listPage(Page page, StaffSalaryMain staffSalaryMain) {
@@ -99,21 +94,6 @@
detail.setMainId(staffSalaryMain.getId());
});
staffSalaryDetailService.saveBatch(staffSalaryMain.getStaffSalaryDetailList());
- }
- // 鍜岃储鍔¤仈鍔紝鏂板鏀嚭
- if(staffSalaryMain.getStatus().equals(5)){
- AccountExpense accountExpense = new AccountExpense();
- accountExpense.setBusinessType(3);
- accountExpense.setExpenseMoney(staffSalaryMain.getTotalSalary());
- accountExpense.setBusinessId(staffSalaryMain.getId());
- accountExpense.setExpenseDate(new Date());
- accountExpense.setExpenseMethod("2");
- accountExpense.setExpenseType("1");
- accountExpense.setExpenseDescribed(staffSalaryMain.getSalaryTitle());
- accountExpense.setNote(staffSalaryMain.getRemark());
- accountExpense.setInputUser(SecurityUtils.getLoginUser().getNickName());
- accountExpense.setInputTime(new Date());
- accountExpenseMapper.insert(accountExpense);
}
return AjaxResult.success("淇敼鎴愬姛");
}
diff --git a/src/main/java/com/ruoyi/stock/controller/StockInRecordController.java b/src/main/java/com/ruoyi/stock/controller/StockInRecordController.java
index 1887b27..f4ca0cc 100644
--- a/src/main/java/com/ruoyi/stock/controller/StockInRecordController.java
+++ b/src/main/java/com/ruoyi/stock/controller/StockInRecordController.java
@@ -70,4 +70,15 @@
return AjaxResult.success();
}
+ @PostMapping("/reAudit")
+ @Log(title = "鍏ュ簱绠$悊-鍙嶅鍏ュ簱", businessType = BusinessType.UPDATE)
+ @Operation(summary = "鎵归噺鍙嶅鍏ュ簱璁板綍")
+ public AjaxResult reAudit(@RequestBody StockInRecordDto approveDto) {
+ if(CollectionUtils.isEmpty(approveDto.getIds())){
+ return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+ }
+ stockInRecordService.batchReAudit(approveDto.getIds());
+ return AjaxResult.success();
+ }
+
}
diff --git a/src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java b/src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java
index 17d7e77..f4f03ba 100644
--- a/src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java
+++ b/src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java
@@ -40,4 +40,7 @@
@Schema(description = "璁板綍ID鍒楄〃")
private List<Long> ids;
+ @Schema(description = "婧愬崟鍙�")
+ private String sourceOrderNo;
+
}
diff --git a/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java b/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
index bc08eee..33b7599 100644
--- a/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
+++ b/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
@@ -15,6 +15,7 @@
private String productName;
private String model;
private String unit;
+ private String batchNo;
//鍏ュ簱绫诲瀷
diff --git a/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java b/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
index 6b8a807..2c1fecb 100644
--- a/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
+++ b/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
@@ -43,6 +43,9 @@
@Schema(description = "澶囨敞")
private String remark;
+ @Schema(description = "棰勮鏁伴噺")
+ private BigDecimal warnNum;
+
@Schema(description = "绫诲瀷 0鍚堟牸鍏ュ簱 1涓嶅悎鏍煎叆搴�")
private String type;
diff --git a/src/main/java/com/ruoyi/stock/service/StockInRecordService.java b/src/main/java/com/ruoyi/stock/service/StockInRecordService.java
index 249f261..117b70f 100644
--- a/src/main/java/com/ruoyi/stock/service/StockInRecordService.java
+++ b/src/main/java/com/ruoyi/stock/service/StockInRecordService.java
@@ -23,4 +23,6 @@
void exportStockInRecord(HttpServletResponse response, StockInRecordDto stockInRecordDto);
int batchApprove(List<Long> ids, Integer approvalStatus);
+
+ int batchReAudit(List<Long> ids);
}
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
index 7051075..85fc1b1 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
@@ -17,6 +17,8 @@
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.dto.StockUninventoryDto;
import com.ruoyi.stock.execl.StockInRecordExportData;
+import com.ruoyi.production.mapper.ProductionOrderPickMapper;
+import com.ruoyi.production.pojo.ProductionOrderPick;
import com.ruoyi.stock.mapper.StockInRecordMapper;
import com.ruoyi.stock.mapper.StockInventoryMapper;
import com.ruoyi.stock.mapper.StockUninventoryMapper;
@@ -30,6 +32,7 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
+import java.math.BigDecimal;
import java.util.List;
@Service
@@ -39,6 +42,7 @@
private StockInRecordMapper stockInRecordMapper;
private StockInventoryMapper stockInventoryMapper;
private StockUninventoryMapper stockUninventoryMapper;
+ private ProductionOrderPickMapper productionOrderPickMapper;
@Override
public IPage<StockInRecordDto> listPage(Page page, StockInRecordDto stockInRecordDto) {
@@ -152,6 +156,32 @@
return stockUninventoryMapper.selectOne(eq);
}
+ /**
+ * 鍥炴粴鐢熶骇閫�鏂欏叆搴撶殑棰嗘枡璁板綍閫�鏂欐暟閲�
+ * @param stockInRecord 鍏ュ簱璁板綍
+ */
+ private void rollbackFeedReturnQty(StockInRecord stockInRecord) {
+ ProductionOrderPick productionOrderPick = productionOrderPickMapper.selectById(stockInRecord.getRecordId());
+ if (productionOrderPick != null) {
+ BigDecimal returnQty = productionOrderPick.getReturnQty();
+ if (returnQty == null) {
+ returnQty = BigDecimal.ZERO;
+ }
+ BigDecimal newReturnQty = returnQty.subtract(stockInRecord.getStockInNum());
+ if (newReturnQty.compareTo(BigDecimal.ZERO) < 0) {
+ newReturnQty = BigDecimal.ZERO;
+ }
+ productionOrderPick.setReturnQty(newReturnQty);
+ // 閲嶆柊璁$畻瀹為檯鐢ㄩ噺
+ BigDecimal actualQty = productionOrderPick.getQuantity().add(
+ productionOrderPick.getFeedingQty() != null ? productionOrderPick.getFeedingQty() : BigDecimal.ZERO)
+ .subtract(newReturnQty);
+ productionOrderPick.setActualQty(actualQty);
+ productionOrderPick.setReturned(newReturnQty.compareTo(BigDecimal.ZERO) > 0);
+ productionOrderPickMapper.updateById(productionOrderPick);
+ }
+ }
+
@Override
@Transactional(rollbackFor = Exception.class)
public int batchDeletePending(List<Long> ids) {
@@ -162,6 +192,11 @@
}
if (stockInRecord.getApprovalStatus() != null && !ReviewStatusEnum.PENDING_REVIEW.getCode().equals(stockInRecord.getApprovalStatus())) {
throw new BaseException("鍙湁寰呭鎵圭姸鎬佺殑璁板綍鎵嶈兘鍒犻櫎,鍏ュ簱鎵规:" + stockInRecord.getInboundBatches());
+ }
+
+ // 濡傛灉鏄敓浜ч��鏂欏叆搴擄紝鍒犻櫎鏃堕渶瑕佸洖婊氶鏂欒褰曠殑閫�鏂欐暟閲�
+ if (StockInQualifiedRecordTypeEnum.FEED_RETURN_IN.getCode().equals(stockInRecord.getRecordType())) {
+ rollbackFeedReturnQty(stockInRecord);
}
}
return stockInRecordMapper.deleteBatchIds(ids);
@@ -186,6 +221,13 @@
}
stockInRecord.setApprovalStatus(approvalStatus);
stockInRecordMapper.updateById(stockInRecord);
+
+ // 瀹℃壒椹冲洖鏃讹紝濡傛灉鏄敓浜ч��鏂欏叆搴擄紝闇�瑕佸洖婊氶鏂欒褰曠殑閫�鏂欐暟閲�
+ if (ReviewStatusEnum.REJECTED.getCode().equals(approvalStatus) &&
+ StockInQualifiedRecordTypeEnum.FEED_RETURN_IN.getCode().equals(stockInRecord.getRecordType())) {
+ rollbackFeedReturnQty(stockInRecord);
+ }
+
// 瀹℃壒閫氳繃鏃讹紝搴撳瓨澧炲姞
if (ReviewStatusEnum.APPROVED.getCode().equals(approvalStatus)) {
if ("0".equals(stockInRecord.getType())) {
@@ -202,6 +244,7 @@
setQualitity(stockInRecord.getStockInNum());
setBatchNo(stockInRecord.getBatchNo());
setRemark(stockInRecord.getRemark());
+ setWarnNum(stockInRecord.getWarnNum());
setVersion(1);
}});
} else {
@@ -231,4 +274,50 @@
}
return ids.size();
}
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int batchReAudit(List<Long> ids) {
+ if (CollectionUtils.isEmpty(ids)) {
+ throw new BaseException("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+ }
+
+ for (Long id : ids) {
+ StockInRecord stockInRecord = stockInRecordMapper.selectById(id);
+ if (stockInRecord == null) {
+ throw new BaseException("鍏ュ簱璁板綍涓嶅瓨鍦�,鏃犳硶閲嶆柊瀹℃牳!!!");
+ }
+ // 鍙湁椹冲洖鐘舵�佹墠鑳介噸鏂板鏍�
+ if (!ReviewStatusEnum.REJECTED.getCode().equals(stockInRecord.getApprovalStatus())) {
+ throw new BaseException("鍙湁椹冲洖鐘舵�佺殑璁板綍鎵嶈兘閲嶆柊瀹℃牳,鍏ュ簱鎵规:" + stockInRecord.getInboundBatches());
+ }
+
+ // 濡傛灉鏄敓浜ч��鏂欏叆搴擄紝鎭㈠閫�鏂欐暟閲忥紙鍥犱负椹冲洖鏃跺凡鎵e噺锛�
+ if (StockInQualifiedRecordTypeEnum.FEED_RETURN_IN.getCode().equals(stockInRecord.getRecordType())) {
+ ProductionOrderPick productionOrderPick = productionOrderPickMapper.selectById(stockInRecord.getRecordId());
+ if (productionOrderPick != null) {
+ BigDecimal returnQty = productionOrderPick.getReturnQty();
+ if (returnQty == null) {
+ returnQty = BigDecimal.ZERO;
+ }
+ // 閲嶆柊瀹℃牳鏃舵仮澶嶉��鏂欐暟閲�
+ BigDecimal newReturnQty = returnQty.add(stockInRecord.getStockInNum());
+ productionOrderPick.setReturnQty(newReturnQty);
+ // 閲嶆柊璁$畻瀹為檯鐢ㄩ噺
+ BigDecimal actualQty = productionOrderPick.getQuantity().add(
+ productionOrderPick.getFeedingQty() != null ? productionOrderPick.getFeedingQty() : BigDecimal.ZERO)
+ .subtract(newReturnQty);
+ productionOrderPick.setActualQty(actualQty);
+ productionOrderPick.setReturned(newReturnQty.compareTo(BigDecimal.ZERO) > 0);
+ productionOrderPickMapper.updateById(productionOrderPick);
+ }
+ }
+
+ // 灏嗙姸鎬佹敼涓哄緟瀹℃牳
+ stockInRecord.setApprovalStatus(ReviewStatusEnum.PENDING_REVIEW.getCode());
+ stockInRecordMapper.updateById(stockInRecord);
+ }
+
+ return ids.size();
+ }
}
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
index 24605ba..c82ac34 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -168,6 +168,7 @@
stockInRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
stockInRecordDto.setType("0");
stockInRecordDto.setRemark(stockInventoryDto.getRemark());
+ stockInRecordDto.setWarnNum(stockInventoryDto.getWarnNum());
stockInRecordService.add(stockInRecordDto);
return true;
}
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
index 9a6bd9b..851a0e2 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
@@ -4,6 +4,8 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.account.mapper.sales.AccountInvoiceApplicationMapper;
+import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper;
import com.ruoyi.common.enums.ReviewStatusEnum;
import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
@@ -46,6 +48,8 @@
private final StockOutRecordMapper stockOutRecordMapper;
private final StockInventoryMapper stockInventoryMapper;
private final StockUninventoryMapper stockUninventoryMapper;
+ private final AccountSalesCollectionMapper accountSalesCollectionMapper;
+ private final AccountInvoiceApplicationMapper accountInvoiceApplicationMapper;
@Override
public IPage<StockOutRecordDto> listPage(Page page, StockOutRecordDto stockOutRecordDto) {
@@ -77,6 +81,11 @@
@Override
public int batchDelete(List<Long> ids) {
+ //todo 濡傛灉鍑哄簱涓庡紑绁ㄦ敹娆炬湁鍏宠仈鍒欐棤娉曞垹闄�
+ if (accountSalesCollectionMapper.existsByStockOutRecordId(ids) ||
+ accountInvoiceApplicationMapper.existsByStockOutRecordId(ids)) {
+ throw new BaseException("鍑哄簱璁板綍瀛樺湪寮�绁ㄦ敹娆惧叧鑱旀暟鎹�,鏃犳硶鍒犻櫎!!!");
+ }
for (Long id : ids) {
StockOutRecord stockOutRecord = stockOutRecordMapper.selectById(id);
if (stockOutRecord.getType().equals("0")) {
@@ -97,7 +106,8 @@
stockInRecordDto.setBatchNo(stockInventory.getBatchNo());
stockInventoryMapper.updateAddStockInventory(stockInRecordDto);
}
- }else if (stockOutRecord.getType().equals("1")) {
+ }
+ else if (stockOutRecord.getType().equals("1")) {
LambdaQueryWrapper<StockUninventory> wrapper = new LambdaQueryWrapper<StockUninventory>()
.eq(StockUninventory::getProductModelId, stockOutRecord.getProductModelId());
if (StringUtils.isEmpty(stockOutRecord.getBatchNo())) {
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
index 4c7d157..47f7d34 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
@@ -80,21 +80,7 @@
stockInRecordDto.setProductModelId(stockUninventoryDto.getProductModelId());
stockInRecordDto.setType("1");
stockInRecordService.add(stockInRecordDto);
- //鍐嶈繘琛屾柊澧炲簱瀛樻暟閲忓簱瀛�
- //鍏堟煡璇㈠簱瀛樿〃涓殑浜у搧鏄惁瀛樺湪锛屼笉瀛樺湪鏂板锛屽瓨鍦ㄦ洿鏂�
- StockUninventory oldStockUnInventory = stockUninventoryMapper.selectOne(wrapper);
- if (ObjectUtils.isEmpty(oldStockUnInventory)) {
- StockUninventory newStockUnInventory = new StockUninventory();
- newStockUnInventory.setProductModelId(stockUninventoryDto.getProductModelId());
- newStockUnInventory.setQualitity(stockUninventoryDto.getQualitity());
- newStockUnInventory.setLockedQuantity(stockUninventoryDto.getLockedQuantity());
- newStockUnInventory.setBatchNo(stockUninventoryDto.getBatchNo());
- newStockUnInventory.setVersion(1);
- newStockUnInventory.setRemark(stockUninventoryDto.getRemark());
- stockUninventoryMapper.insert(newStockUnInventory);
- }else {
- stockUninventoryMapper.updateAddStockUnInventory(stockUninventoryDto);
- }
+ //瀹℃壒鍐嶆坊鍔�
return 1;
}
diff --git a/src/main/java/com/ruoyi/technology/controller/TechnologyOperationController.java b/src/main/java/com/ruoyi/technology/controller/TechnologyOperationController.java
index c24c93f..ecf4f38 100644
--- a/src/main/java/com/ruoyi/technology/controller/TechnologyOperationController.java
+++ b/src/main/java/com/ruoyi/technology/controller/TechnologyOperationController.java
@@ -24,28 +24,28 @@
private final TechnologyOperationService technologyOperationService;
@GetMapping("/listPage")
- @Log(title = "Technology operation page", businessType = BusinessType.OTHER)
+ @Log(title = "宸ュ簭鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
@Operation(summary = "宸ュ簭鍒嗛〉鏌ヨ")
public R<IPage<TechnologyOperationVo>> listPage(Page<TechnologyOperationDto> page, TechnologyOperationDto technologyOperationDto) {
return R.ok(technologyOperationService.listPage(page, technologyOperationDto));
}
@PostMapping("/add")
- @Log(title = "Add technology operation", businessType = BusinessType.INSERT)
+ @Log(title = "宸ュ簭鏂板", businessType = BusinessType.INSERT)
@Operation(summary = "鏂板宸ュ簭")
public R add(@RequestBody TechnologyOperationDto technologyOperationDto) {
return technologyOperationService.add(technologyOperationDto);
}
@PutMapping("/update")
- @Log(title = "Update technology operation", businessType = BusinessType.UPDATE)
+ @Log(title = "宸ュ簭鏇存柊", businessType = BusinessType.UPDATE)
@Operation(summary = "淇敼宸ュ簭")
public R update(@RequestBody com.ruoyi.technology.pojo.TechnologyOperation technologyOperation) {
return R.ok(technologyOperationService.updateById(technologyOperation));
}
@DeleteMapping("/batchDelete")
- @Log(title = "Delete technology operation", businessType = BusinessType.DELETE)
+ @Log(title = "鍒犻櫎宸ュ簭", businessType = BusinessType.DELETE)
@Operation(summary = "鎵归噺鍒犻櫎宸ュ簭")
public R batchDelete(@RequestBody List<Long> ids) {
return R.ok(technologyOperationService.batchDelete(ids));
diff --git a/src/main/java/com/ruoyi/technology/controller/TechnologyOperationParamController.java b/src/main/java/com/ruoyi/technology/controller/TechnologyOperationParamController.java
index 061a50c..92bb773 100644
--- a/src/main/java/com/ruoyi/technology/controller/TechnologyOperationParamController.java
+++ b/src/main/java/com/ruoyi/technology/controller/TechnologyOperationParamController.java
@@ -36,7 +36,7 @@
}
@DeleteMapping("/batchDelete/{id}")
- @Log(title = "Delete technology operation param", businessType = BusinessType.DELETE)
+ @Log(title = "鍒犻櫎宸ュ簭鍙傛暟", businessType = BusinessType.DELETE)
@Operation(summary = "鍒犻櫎宸ュ簭鍙傛暟")
public AjaxResult batchDelete(@PathVariable("id") Long id) {
return AjaxResult.success(technologyOperationParamService.batchDelete(id));
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java
index 0eff194..6750f03 100644
--- a/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java
+++ b/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java
@@ -9,6 +9,8 @@
import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.technology.bean.dto.TechnologyRoutingDto;
import com.ruoyi.technology.bean.vo.TechnologyRoutingVo;
+import com.ruoyi.production.mapper.ProductionOrderRoutingMapper;
+import com.ruoyi.production.pojo.ProductionOrderRouting;
import com.ruoyi.technology.mapper.*;
import com.ruoyi.technology.pojo.*;
import com.ruoyi.technology.service.TechnologyRoutingService;
@@ -39,6 +41,8 @@
private final TechnologyOperationParamMapper technologyOperationParamMapper;
private final TechnologyParamMapper technologyParamMapper;
private final TechnologyRoutingOperationParamMapper technologyRoutingOperationParamMapper;
+
+ private final ProductionOrderRoutingMapper productionOrderRoutingMapper;
@Override
public IPage<TechnologyRoutingVo> pageTechnologyRouting(Page<TechnologyRoutingDto> page, TechnologyRoutingDto technologyRoutingDto) {
@@ -79,6 +83,13 @@
if (ids == null || ids.isEmpty()) {
return false;
}
+ // 鍒ゆ柇鏄惁鏈夌敓浜ц鍗曠粦瀹氳宸ヨ壓璺嚎
+ Long count = productionOrderRoutingMapper.selectCount(
+ Wrappers.<ProductionOrderRouting>lambdaQuery()
+ .in(ProductionOrderRouting::getTechnologyRoutingId, ids));
+ if (count > 0) {
+ throw new ServiceException("璇ュ伐鑹鸿矾绾垮凡缁戝畾鐢熶骇璁㈠崟锛屾棤娉曞垹闄わ紒");
+ }
List<TechnologyRoutingOperation> routingOperationList = technologyRoutingOperationMapper.selectList(
Wrappers.<TechnologyRoutingOperation>lambdaQuery()
.in(TechnologyRoutingOperation::getTechnologyRoutingId, ids));
diff --git a/src/main/java/com/ruoyi/warehouse/controller/DocumentationFileController.java b/src/main/java/com/ruoyi/warehouse/controller/DocumentationFileController.java
index 9c8517e..f272150 100644
--- a/src/main/java/com/ruoyi/warehouse/controller/DocumentationFileController.java
+++ b/src/main/java/com/ruoyi/warehouse/controller/DocumentationFileController.java
@@ -1,8 +1,5 @@
package com.ruoyi.warehouse.controller;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.account.pojo.AccountFile;
-import com.ruoyi.account.service.AccountFileService;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.warehouse.pojo.DocumentationFile;
import com.ruoyi.warehouse.service.DocumentationFileService;
diff --git a/src/main/java/com/ruoyi/warehouse/mapper/DocumentationFileMapper.java b/src/main/java/com/ruoyi/warehouse/mapper/DocumentationFileMapper.java
index 0617258..94d7eac 100644
--- a/src/main/java/com/ruoyi/warehouse/mapper/DocumentationFileMapper.java
+++ b/src/main/java/com/ruoyi/warehouse/mapper/DocumentationFileMapper.java
@@ -1,9 +1,6 @@
package com.ruoyi.warehouse.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.account.pojo.AccountFile;
import com.ruoyi.warehouse.pojo.DocumentationFile;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
diff --git a/src/main/java/com/ruoyi/warehouse/service/DocumentationFileService.java b/src/main/java/com/ruoyi/warehouse/service/DocumentationFileService.java
index 575ecd4..a5a8836 100644
--- a/src/main/java/com/ruoyi/warehouse/service/DocumentationFileService.java
+++ b/src/main/java/com/ruoyi/warehouse/service/DocumentationFileService.java
@@ -1,9 +1,6 @@
package com.ruoyi.warehouse.service;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.account.pojo.AccountFile;
import com.ruoyi.warehouse.pojo.DocumentationFile;
import java.util.List;
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 6d34f6b..f1a5bf9 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -28,7 +28,7 @@
# 寮�鍙戠幆澧冮厤缃�
server:
# 鏈嶅姟鍣ㄧ殑HTTP绔彛锛岄粯璁や负8080
- port: 7006
+ port: 7005
servlet:
# 搴旂敤鐨勮闂矾寰�
context-path: /
@@ -268,4 +268,3 @@
compressQuality: 0.5 # 鍘嬬缉璐ㄩ噺(0.0-1.0)
knowledge:
one: D:\鏂扮枂澶х綏绱犱紒涓氫骇鍝佷綋绯昏鏄庢枃妗�.md
-
diff --git a/src/main/resources/application-hqjc.yml b/src/main/resources/application-hqjc.yml
new file mode 100644
index 0000000..6157353
--- /dev/null
+++ b/src/main/resources/application-hqjc.yml
@@ -0,0 +1,268 @@
+# 椤圭洰鐩稿叧閰嶇疆
+ruoyi:
+ # 鍚嶇О
+ name: RuoYi
+ # 鐗堟湰
+ version: 3.8.9
+ # 鐗堟潈骞翠唤
+ copyrightYear: 2025
+ # 鏂囦欢璺緞 绀轰緥锛� Windows閰嶇疆D:/ruoyi/uploadPath锛孡inux閰嶇疆 /home/ruoyi/uploadPath锛�
+ profile: /javaWork/product-inventory-management/file
+
+ # 鑾峰彇ip鍦板潃寮�鍏�
+ addressEnabled: false
+ # 楠岃瘉鐮佺被鍨� math 鏁板瓧璁$畻 char 瀛楃楠岃瘉
+ captchaType: math
+ # 鍗忓悓瀹℃壒缂栧彿鍓嶇紑(閰嶇疆鏂囦欢鍚庣紑鍛藉悕)
+ approvalNumberPrefix: NEW
+
+ # 涓帹 Unipush 閰嶇疆
+ getui:
+ appId: PfjyAAE0FK64FaO1w2CMb1
+ appKey: zTMb831OEL6J4GK1uE3Ob4
+ masterSecret: K1GFtsv42v61tXGnF7SGE5
+ domain: https://restapi.getui.cn/v2/
+ # 绂荤嚎鎺ㄩ�佷娇鐢ㄧ殑鍖呭悕/缁勪欢鍚�
+ intentComponent: uni.app.UNI099A590/io.dcloud.PandoraEntry
+
+# 寮�鍙戠幆澧冮厤缃�
+server:
+ # 鏈嶅姟鍣ㄧ殑HTTP绔彛锛岄粯璁や负8080
+ port: 9003
+ servlet:
+ # 搴旂敤鐨勮闂矾寰�
+ context-path: /
+ tomcat:
+ # tomcat鐨刄RI缂栫爜
+ uri-encoding: UTF-8
+ # 杩炴帴鏁版弧鍚庣殑鎺掗槦鏁帮紝榛樿涓�100
+ accept-count: 1000
+ threads:
+ # tomcat鏈�澶х嚎绋嬫暟锛岄粯璁や负200
+ max: 800
+ # Tomcat鍚姩鍒濆鍖栫殑绾跨▼鏁帮紝榛樿鍊�10
+ min-spare: 100
+
+# 鏃ュ織閰嶇疆
+logging:
+ level:
+ com.ruoyi: warn
+ org.springframework: warn
+
+minio:
+ endpoint: http://114.132.189.42/
+ port: 7019
+ secure: false
+ accessKey: admin
+ secretKey: 12345678
+ preview-expiry: 24 # 棰勮鍦板潃榛樿24灏忔椂
+ default-bucket: jxc
+# 鐢ㄦ埛閰嶇疆
+user:
+ password:
+ # 瀵嗙爜鏈�澶ч敊璇鏁�
+ maxRetryCount: 5
+ # 瀵嗙爜閿佸畾鏃堕棿锛堥粯璁�10鍒嗛挓锛�
+ lockTime: 10
+
+# Spring閰嶇疆
+spring:
+ datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driverClassName: com.mysql.cj.jdbc.Driver
+ druid:
+ # 涓诲簱鏁版嵁婧�
+ master:
+ url: jdbc:mysql://172.17.0.1:9002/product-inventory-management-hqjc?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: root
+ password: hqjc@123456..
+ # 浠庡簱鏁版嵁婧�
+ slave:
+ # 浠庢暟鎹簮寮�鍏�/榛樿鍏抽棴
+ enabled: false
+ url:
+ username:
+ password:
+ # 鍒濆杩炴帴鏁�
+ initialSize: 5
+ # 鏈�灏忚繛鎺ユ睜鏁伴噺
+ minIdle: 10
+ # 鏈�澶ц繛鎺ユ睜鏁伴噺
+ maxActive: 20
+ # 閰嶇疆鑾峰彇杩炴帴绛夊緟瓒呮椂鐨勬椂闂�
+ maxWait: 60000
+ # 閰嶇疆杩炴帴瓒呮椂鏃堕棿
+ connectTimeout: 30000
+ # 閰嶇疆缃戠粶瓒呮椂鏃堕棿
+ socketTimeout: 60000
+ # 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣
+ timeBetweenEvictionRunsMillis: 60000
+ # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忕敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
+ minEvictableIdleTimeMillis: 300000
+ # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�澶х敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
+ maxEvictableIdleTimeMillis: 900000
+ # 閰嶇疆妫�娴嬭繛鎺ユ槸鍚︽湁鏁�
+ validationQuery: SELECT 1 FROM DUAL
+ testWhileIdle: true
+ testOnBorrow: false
+ testOnReturn: false
+ webStatFilter:
+ enabled: true
+ statViewServlet:
+ enabled: true
+ # 璁剧疆鐧藉悕鍗曪紝涓嶅~鍒欏厑璁告墍鏈夎闂�
+ allow:
+ url-pattern: /druid/*
+ # 鎺у埗鍙扮鐞嗙敤鎴峰悕鍜屽瘑鐮�
+ login-username: ruoyi
+ login-password: 123456
+ filter:
+ stat:
+ enabled: true
+ # 鎱QL璁板綍
+ log-slow-sql: true
+ slow-sql-millis: 1000
+ merge-sql: true
+ wall:
+ config:
+ multi-statement-allow: true
+ # 璧勬簮淇℃伅
+ messages:
+ # 鍥介檯鍖栬祫婧愭枃浠惰矾寰�
+ basename: i18n/messages
+ # 鏂囦欢涓婁紶
+ servlet:
+ multipart:
+ # 鍗曚釜鏂囦欢澶у皬
+ max-file-size: 1GB
+ # 璁剧疆鎬讳笂浼犵殑鏂囦欢澶у皬
+ max-request-size: 2GB
+ # 鏈嶅姟妯″潡
+ devtools:
+ restart:
+ # 鐑儴缃插紑鍏�
+ enabled: false
+ # redis 閰嶇疆
+ data:
+ mongodb:
+ uri: mongodb://114.132.189.42:9028/chat_memory_db_hqjc
+ # redis 閰嶇疆
+ redis:
+ # 鍦板潃
+# host: 127.0.0.1
+ host: 172.17.0.1
+ # 绔彛锛岄粯璁や负6379
+ port: 6379
+ # 鏁版嵁搴撶储寮�
+ database: 0
+ # 瀵嗙爜
+ # password: root2022!
+ password:
+
+ # 杩炴帴瓒呮椂鏃堕棿
+ timeout: 10s
+ lettuce:
+ pool:
+ # 杩炴帴姹犱腑鐨勬渶灏忕┖闂茶繛鎺�
+ min-idle: 0
+ # 杩炴帴姹犱腑鐨勬渶澶х┖闂茶繛鎺�
+ max-idle: 8
+ # 杩炴帴姹犵殑鏈�澶ф暟鎹簱杩炴帴鏁�
+ max-active: 8
+ # #杩炴帴姹犳渶澶ч樆濉炵瓑寰呮椂闂达紙浣跨敤璐熷�艰〃绀烘病鏈夐檺鍒讹級
+ max-wait: -1ms
+
+ # Quartz瀹氭椂浠诲姟閰嶇疆锛堟柊澧為儴鍒嗭級
+ quartz:
+ job-store-type: jdbc # 浣跨敤鏁版嵁搴撳瓨鍌�
+ jdbc:
+ initialize-schema: never # 棣栨杩愯鏃惰嚜鍔ㄥ垱寤鸿〃缁撴瀯锛屾垚鍔熷悗鏀逛负never
+ schema: classpath:org/quartz/impl/jdbcjobstore/tables_mysql_innodb.sql # MySQL琛ㄧ粨鏋勮剼鏈�
+ properties:
+ org:
+ quartz:
+ scheduler:
+ instanceName: RuoYiScheduler
+ instanceId: AUTO
+ jobStore:
+ class: org.quartz.impl.jdbcjobstore.JobStoreTX
+ driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate # MySQL閫傞厤
+ tablePrefix: qrtz_ # 琛ㄥ悕鍓嶇紑锛屼笌鑴氭湰涓�鑷�
+ isClustered: false # 鍗曡妭鐐规ā寮忥紙闆嗙兢闇�鏀逛负true锛�
+ clusterCheckinInterval: 10000
+ txIsolationLevelSerializable: true
+ threadPool:
+ class: org.quartz.simpl.SimpleThreadPool
+ threadCount: 10 # 绾跨▼姹犲ぇ灏�
+ threadPriority: 5
+ makeThreadsDaemons: true
+ updateCheck: false # 鍏抽棴鐗堟湰妫�鏌�
+# token閰嶇疆
+token:
+ # 浠ょ墝鑷畾涔夋爣璇�
+ header: Authorization
+ # 浠ょ墝瀵嗛挜
+ secret: xpAVjhCjQDaDB7mjPAzMDSbQWXNu2zYkTdDNUsPMS5Xx8QMmQVYN7n74eZrYJxDJ
+ # 浠ょ墝鏈夋晥鏈燂紙榛樿30鍒嗛挓锛�
+ expireTime: 450
+
+# MyBatis Plus閰嶇疆
+mybatis-plus:
+ # 鎼滅储鎸囧畾鍖呭埆鍚� 鏍规嵁鑷繁鐨勯」鐩潵
+ typeAliasesPackage: com.ruoyi.**.pojo
+ # 閰嶇疆mapper鐨勬壂鎻忥紝鎵惧埌鎵�鏈夌殑mapper.xml鏄犲皠鏂囦欢
+ mapperLocations: classpath*:mapper/**/*Mapper.xml
+ # 鍔犺浇鍏ㄥ眬鐨勯厤缃枃浠�
+ configLocation: classpath:mybatis/mybatis-config.xml
+ global-config:
+ enable-sql-runner: true
+ db-config:
+ id-type: auto
+
+# PageHelper鍒嗛〉鎻掍欢
+pagehelper:
+ helperDialect: mysql
+ supportMethodsArguments: true
+ params: count=countSql
+
+# Swagger閰嶇疆
+swagger:
+ # 鏄惁寮�鍚痵wagger
+ enabled: true
+ # 璇锋眰鍓嶇紑
+ pathMapping: /dev-api
+
+# 闃叉XSS鏀诲嚮
+xss:
+ # 杩囨护寮�鍏�
+ enabled: true
+ # 鎺掗櫎閾炬帴锛堝涓敤閫楀彿鍒嗛殧锛�
+ excludes: /system/notice
+ # 鍖归厤閾炬帴
+ urlPatterns: /system/*,/monitor/*,/tool/*
+
+# 浠g爜鐢熸垚
+gen:
+ # 浣滆��
+ author: ruoyi
+ # 榛樿鐢熸垚鍖呰矾寰� system 闇�鏀规垚鑷繁鐨勬ā鍧楀悕绉� 濡� system monitor tool
+ packageName: com.ruoyi.project.system
+ # 鑷姩鍘婚櫎琛ㄥ墠缂�锛岄粯璁ゆ槸true
+ autoRemovePre: false
+ # 琛ㄥ墠缂�锛堢敓鎴愮被鍚嶄笉浼氬寘鍚〃鍓嶇紑锛屽涓敤閫楀彿鍒嗛殧锛�
+ tablePrefix: sys_
+ # 鏄惁鍏佽鐢熸垚鏂囦欢瑕嗙洊鍒版湰鍦帮紙鑷畾涔夎矾寰勶級锛岄粯璁や笉鍏佽
+ allowOverwrite: false
+
+# 鏂囦欢涓婁紶閰嶇疆
+file:
+ temp-dir: /javaWork/product-inventory-management/file/temp/uploads # 涓存椂鐩綍
+ upload-dir: /javaWork/product-inventory-management/file/prod/uploads # 姝e紡鐩綍
+ path: /javaWork/product-inventory-management/file # 涓婁紶鐩綍
+ urlPrefix: /prod-api/common # 閾炬帴鍓嶇紑
+ domain: http://36.134.77.64:9001 # 鍩熷悕鍓嶇紑
+ expired: 120 # 杩囨湡鏃堕棿(鍗曚綅:鍒嗛挓)
+ useLimit: 10 # 浣跨敤娆℃暟
+ compress: true # 鏄惁鍘嬬缉
+ needCompressSize: 10MB # 鍘嬬缉闃堝��
+ compressQuality: 0.5 # 鍘嬬缉璐ㄩ噺(0.0-1.0)
diff --git a/src/main/resources/approve-todo-agent-prompt.txt b/src/main/resources/approve-todo-agent-prompt.txt
index c309da8..f026fee 100644
--- a/src/main/resources/approve-todo-agent-prompt.txt
+++ b/src/main/resources/approve-todo-agent-prompt.txt
@@ -1,4 +1,5 @@
浣犳槸涓�涓鎵瑰緟鍔炲姪鎵嬶紝璐熻矗鍗忓悓鍔炲叕瀹℃壒寰呭姙鐨勬煡璇€�佸鏍搞�佸彇娑堝鏍搞�佷慨鏀广�佸垹闄ゅ拰缁熻鍒嗘瀽銆�
+褰撳墠鏃ユ湡锛歿{currentDate}}锛堜腑鍥芥椂鍖猴級銆�
宸ヤ綔瑕佹眰锛�
1. 鐢ㄦ埛闂緟鍔炲垪琛ㄣ�佸鎵硅繘搴︺�佸鎵硅鎯呫�佺粺璁℃暟鎹椂锛屼紭鍏堣皟鐢ㄥ伐鍏凤紝涓嶈鑷嗛�犳暟鎹��
@@ -16,3 +17,4 @@
13. 鍙湁鈥滄煡璇㈠鎵瑰緟鍔炶鎯呪�濊繖涓伐鍏峰厑璁歌緭鍑鸿嚜鐒惰瑷�鏂囨湰銆�
14. 濡傛灉宸ュ叿杩斿洖鐨勬槸缁熻 JSON锛屼篃鍚屾牱鐩存帴杈撳嚭鍘熷 JSON锛涘叾涓� `description`銆乣summary`銆乣charts` 宸茬粡渚涘墠绔娇鐢ㄣ��
15. 鍥炵瓟浣跨敤涓枃锛涗絾鍦� JSON 鍦烘櫙涓嬶紝鏈�缁堣緭鍑哄繀椤绘槸鍚堟硶 JSON 鏈綋銆�
+16. 鐢ㄦ埛鎻愬埌鈥滀粖骞�/鏈湀/浠婂ぉ/鏈�杩�/涓婃湀/鍘诲勾鈥濈瓑鐩稿鏃堕棿鏃讹紝蹇呴』涓ユ牸鍩轰簬鈥滃綋鍓嶆棩鏈熲�濇崲绠楋紝绂佹鑷鍋囪骞翠唤銆�
diff --git a/src/main/resources/financial-agent-prompt.txt b/src/main/resources/financial-agent-prompt.txt
new file mode 100644
index 0000000..c7a4a3f
--- /dev/null
+++ b/src/main/resources/financial-agent-prompt.txt
@@ -0,0 +1,11 @@
+浣犳槸鏁板瓧鍖栧伐鍘傜殑璐㈠姟鏅鸿兘浣擄紝瑕嗙洊涓氳储铻嶅悎銆佹垚鏈牳绠椼�佸埄娑﹀垎鏋愩�佸簱瀛樿祫閲戙�佸簲鏀跺簲浠樸�佺幇閲戞祦棰勬祴銆佺粡钀ラ璀︿笌缁忚惀椹鹃┒鑸便��
+褰撳墠鏃ユ湡锛歿{currentDate}}锛堜腑鍥芥椂鍖猴級銆�
+
+宸ヤ綔瑙勫垯锛�
+1. 鐢ㄦ埛鎻愬嚭鈥滄煡銆侀棶銆佺粺璁°�佸垎鏋愩�侀璀︺�佸缓璁�佹姤鍛娾�濋渶姹傛椂锛屼紭鍏堣皟鐢ㄥ伐鍏疯繑鍥炵粨鏋勫寲 JSON锛屼笉缂栭�犱笟鍔℃暟鎹��
+2. 鍛戒腑鎴愭湰銆佸埄娑︺�佸簱瀛樿祫閲戙�佺幇閲戞祦銆侀璀︺�侀┚椹惰埍銆佹棩鎶ュ懆鎶ュ満鏅椂锛屼紭鍏堣皟鐢ㄥ搴斿伐鍏枫��
+3. 宸ュ叿杩斿洖 JSON 鏃讹紝鐩存帴杈撳嚭鍘熷 JSON 瀛楃涓诧紝涓嶈棰濆鍖呰9 Markdown锛屼篃涓嶈鍦ㄥ墠鍚庤拷鍔犺В閲婃枃鏈��
+4. 褰撶敤鎴烽棶棰樼己灏戞椂闂磋寖鍥存椂锛岄粯璁や娇鐢ㄥ伐鍏峰唴缃彛寰勶紙濡傝繎30澶┿�佹湰鏈堛�佽繎90澶╋級锛屽苟鍦ㄥ悗缁彲鎻愰啋鐢ㄦ埛琛ュ厖鑼冨洿銆�
+5. 鐢ㄦ埛闂�滀负浠�涔堝埄娑︿笅闄嶁�濃�滃摢涓鍗曚簭鎹熲�濃�滃摢涓鎴锋渶璧氶挶鈥濃�滃摢涓鎴峰埄娑﹁础鐚渶楂樷�濃�滃摢涓溅闂�/宸ュ簭鎴愭湰鏈�楂樷�濈瓑闂鏃讹紝浼樺厛鍩轰簬璁㈠崟鍒╂鼎涓庡伐搴忔垚鏈垎鏋愬伐鍏蜂綔绛斻��
+6. 鍥炵瓟蹇呴』浣跨敤涓枃锛涜嫢鏁版嵁涓嶈冻浠ュ緱鍑虹粨璁猴紝鏄庣‘鎸囧嚭缂哄皯鍝簺鍏抽敭瀛楁鎴栫瓫閫夋潯浠躲��
+7. 鐢ㄦ埛鎻愬埌鈥滀粖骞�/鏈湀/浠婂ぉ/鏈�杩�/涓婃湀/鍘诲勾鈥濈瓑鐩稿鏃堕棿鏃讹紝蹇呴』涓ユ牸鍩轰簬鈥滃綋鍓嶆棩鏈熲�濇崲绠楋紝绂佹鑷鍋囪骞翠唤銆�
diff --git a/src/main/resources/manufacturing-agent-prompt.txt b/src/main/resources/manufacturing-agent-prompt.txt
index c1a30c8..1653bb9 100644
--- a/src/main/resources/manufacturing-agent-prompt.txt
+++ b/src/main/resources/manufacturing-agent-prompt.txt
@@ -1,4 +1,5 @@
浣犳槸浼佷笟鍒堕�犳櫤鑳藉姪鎵嬶紝瑕嗙洊鐢熶骇鐜板満銆佽鍒掋�佸伐鍗曘�佽澶囥�佽川閲忋�佺墿鏂欍�佸紓甯稿鐞嗕竷涓煙銆�
+褰撳墠鏃ユ湡锛歿{currentDate}}锛堜腑鍥芥椂鍖猴級銆�
宸ヤ綔瑙勫垯锛�
1. 鐢ㄦ埛鎻愬嚭鈥滄煡銆侀棶銆侀璀︺�佸垎鏋愨�濋渶姹傛椂锛屼紭鍏堣皟鐢ㄥ伐鍏锋嬁缁撴瀯鍖栫粨鏋滐紝涓嶈鑷嗛�犱笟鍔℃暟鎹��
@@ -6,3 +7,4 @@
3. 宸ュ叿杩斿洖 JSON 鏃讹紝鐩存帴杈撳嚭鍘熷 JSON 瀛楃涓诧紝涓嶈棰濆鍖呰9 Markdown锛屼笉瑕佸湪鍓嶅悗鍔犺В閲婃枃瀛椼��
4. 鍥炵瓟蹇呴』浣跨敤涓枃锛涜嫢鐢ㄦ埛闂缂哄皯鏃堕棿鑼冨洿銆佸叧閿瓧绛夋潯浠讹紝鍙厛缁欓粯璁ゅ彛寰勫苟鎻愮ず鍙ˉ鍏呮潯浠躲��
5. 鑻ユ棤娉曚粠宸ュ叿缁撴灉寰楀埌缁撹锛屾槑纭鏄庣己灏戠殑绛涢�夋潯浠舵垨涓氬姟瀛楁銆�
+6. 鐢ㄦ埛鎻愬埌鈥滀粖骞�/鏈湀/浠婂ぉ/鏈�杩�/涓婃湀/鍘诲勾鈥濈瓑鐩稿鏃堕棿鏃讹紝蹇呴』涓ユ牸鍩轰簬鈥滃綋鍓嶆棩鏈熲�濇崲绠楋紝绂佹鑷鍋囪骞翠唤銆�
diff --git a/src/main/resources/mapper/account/AccountExpenseMapper.xml b/src/main/resources/mapper/account/AccountExpenseMapper.xml
deleted file mode 100644
index 77eed00..0000000
--- a/src/main/resources/mapper/account/AccountExpenseMapper.xml
+++ /dev/null
@@ -1,101 +0,0 @@
-<?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.ruoyi.account.mapper.AccountExpenseMapper">
- <select id="accountExpenseListPage" resultType="com.ruoyi.account.pojo.AccountExpense">
- SELECT
- *
- FROM account_expense
- where
- 1=1
- <if test="accountExpense.entryDateStart != null and accountExpense.entryDateStart != '' ">
- AND expense_date >= DATE_FORMAT(#{accountExpense.entryDateStart},'%Y-%m-%d')
- </if>
- <if test=" accountExpense.supplierName != null and accountExpense.supplierName != ''">
- AND supplier_name like CONCAT('%',#{accountExpense.supplierName},'%')
- </if>
- <if test=" accountExpense.invoiceNumber != null and accountExpense.invoiceNumber != ''">
- AND invoice_number like CONCAT('%',#{accountExpense.invoiceNumber},'%')
- </if>
- <if test="accountExpense.entryDateEnd != null and accountExpense.entryDateEnd != '' ">
- AND expense_date <= DATE_FORMAT(#{accountExpense.entryDateEnd},'%Y-%m-%d')
- </if>
- <if test="accountExpense.expenseType != null and accountExpense.expenseType != '' ">
- AND expense_type = #{accountExpense.expenseType}
- </if>
- <if test="accountExpense.expenseMethod != null and accountExpense.expenseMethod != '' ">
- AND expense_method = #{accountExpense.expenseMethod}
- </if>
- </select>
- <select id="accountExpenseExport" resultType="com.ruoyi.account.pojo.AccountExpense">
- SELECT
- *
- FROM account_expense
- where
- 1=1
- <if test="accountExpense.entryDateStart != null and accountExpense.entryDateStart != '' ">
- AND expense_date >= DATE_FORMAT(#{accountExpense.entryDateStart},'%Y-%m-%d')
- </if>
- <if test="accountExpense.entryDateEnd != null and accountExpense.entryDateEnd != '' ">
- AND expense_date <= DATE_FORMAT(#{accountExpense.entryDateEnd},'%Y-%m-%d')
- </if>
- <if test="accountExpense.expenseType != null and accountExpense.expenseType != '' ">
- AND expense_type = #{accountExpense.expenseType}
- </if>
- <if test="accountExpense.expenseMethod != null and accountExpense.expenseMethod != '' ">
- AND expense_method = #{accountExpense.expenseMethod}
- </if>
- </select>
- <select id="report" resultType="com.ruoyi.account.bean.dto.AccountDto2">
- SELECT
- sdd.dict_label typeName,
- sum(expense_money) account
- FROM account_expense ae
- left join sys_dict_data sdd on ae.expense_type = sdd.dict_value and sdd.dict_type='expense_types'
- where
- 1=1
- <if test="dateQueryDto.entryDateStart != null and dateQueryDto.entryDateStart != '' ">
- AND expense_date >= DATE_FORMAT(#{dateQueryDto.entryDateStart},'%Y-%m-%d')
- </if>
- <if test="dateQueryDto.entryDateEnd != null and dateQueryDto.entryDateEnd != '' ">
- AND expense_date <= DATE_FORMAT(#{dateQueryDto.entryDateEnd},'%Y-%m-%d')
- </if>
- group by sdd.dict_label, ae.expense_type
- </select>
-
- <select id="report1" resultType="java.math.BigDecimal">
- SELECT
- ifnull(sum(expense_money),0) account
- FROM account_expense ai
- where
- expense_type=#{dictValue}
- <if test="dateQueryDto.entryDateStart != null and dateQueryDto.entryDateStart != '' ">
- AND expense_date >= DATE_FORMAT(#{dateQueryDto.entryDateStart},'%Y-%m-%d')
- </if>
- <if test="dateQueryDto.entryDateEnd != null and dateQueryDto.entryDateEnd != '' ">
- AND expense_date <= DATE_FORMAT(#{dateQueryDto.entryDateEnd},'%Y-%m-%d')
- </if>
- </select>
-
- <select id="selectAccountExpenseStats" resultType="com.ruoyi.home.dto.IncomeExpenseAnalysisDto">
- SELECT DATE_FORMAT(expense_date, #{dateFormat}) as dateStr, IFNULL(SUM(expense_money), 0) as amount
- FROM account_expense
- WHERE expense_date BETWEEN #{startDate} AND #{endDate}
- GROUP BY dateStr
- </select>
-
- <select id="selectExpenseComposition" resultType="com.ruoyi.dto.MapDto">
- SELECT sdd.dict_label as name, CAST(IFNULL(SUM(ae.expense_money), 0) AS CHAR) as value
- FROM account_expense ae
- LEFT JOIN sys_dict_data sdd ON ae.expense_type = sdd.dict_value AND sdd.dict_type = 'expense_types'
- <where>
- <if test="startDate != null and startDate != ''">
- AND ae.expense_date >= #{startDate}
- </if>
- <if test="endDate != null and endDate != ''">
- AND ae.expense_date <= #{endDate}
- </if>
- </where>
- GROUP BY ae.expense_type, sdd.dict_label
- </select>
-
-</mapper>
diff --git a/src/main/resources/mapper/account/AccountFileMapper.xml b/src/main/resources/mapper/account/AccountFileMapper.xml
deleted file mode 100644
index 86266d5..0000000
--- a/src/main/resources/mapper/account/AccountFileMapper.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?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.ruoyi.account.mapper.AccountFileMapper">
- <select id="accountFileListPage" resultType="com.ruoyi.account.pojo.AccountFile">
- SELECT
- *
- FROM account_file
- where
- 1=1
- <if test="accountFile.accountId != null and accountFile.accountId != ''">
- AND account_id = #{accountFile.accountId}
- </if>
- <if test="accountFile.name != null and accountFile.name != '' ">
- AND name = #{accountFile.name}
- </if>
- <if test="accountFile.accountType != null and accountFile.accountType != '' ">
- AND account_type = #{accountFile.accountType}
- </if>
- </select>
-</mapper>
diff --git a/src/main/resources/mapper/account/AccountIncomeMapper.xml b/src/main/resources/mapper/account/AccountIncomeMapper.xml
deleted file mode 100644
index a1d4205..0000000
--- a/src/main/resources/mapper/account/AccountIncomeMapper.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?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.ruoyi.account.mapper.AccountIncomeMapper">
-
- <select id="accountIncomeListPage" resultType="com.ruoyi.account.pojo.AccountIncome">
- SELECT
- *
- FROM account_income
- where
- 1=1
- <if test="accountIncome.entryDateStart != null and accountIncome.entryDateStart != '' ">
- AND income_date >= DATE_FORMAT(#{accountIncome.entryDateStart},'%Y-%m-%d')
- </if>
- <if test="accountIncome.customerName != null and accountIncome.customerName != '' ">
- AND customer_name like CONCAT('%',#{accountIncome.customerName},'%')
- </if>
-
- <if test="accountIncome.invoiceNumber != null and accountIncome.invoiceNumber != '' ">
- AND invoice_number like CONCAT('%',#{accountIncome.invoiceNumber},'%')
- </if>
- <if test="accountIncome.entryDateEnd != null and accountIncome.entryDateEnd != '' ">
- AND income_date <= DATE_FORMAT(#{accountIncome.entryDateEnd},'%Y-%m-%d')
- </if>
- <if test="accountIncome.incomeType != null and accountIncome.incomeType != '' ">
- AND income_type = #{accountIncome.incomeType}
- </if>
- <if test="accountIncome.incomeMethodLabel != null and accountIncome.incomeMethodLabel != ''">
- AND (
- (
- business_type = 1
- AND income_method in
- <foreach collection="accountIncome.receiptPaymentMethodList" item="method" open="(" separator="," close=")">
- #{method}
- </foreach>
- )
- OR
- (
- business_type is null
- AND income_method in
- <foreach collection="accountIncome.paymentMethodList" item="method" open="(" separator="," close=")">
- #{method}
- </foreach>
- )
- )
- </if>
- <if test="(accountIncome.incomeMethodLabel == null or accountIncome.incomeMethodLabel == '') and accountIncome.incomeMethod != null and accountIncome.incomeMethod != '' ">
- AND income_method = #{accountIncome.incomeMethod}
- </if>
- </select>
- <select id="accountIncomeExport" resultType="com.ruoyi.account.pojo.AccountIncome">
- SELECT
- *
- FROM account_income
- where
- 1=1
- <if test="accountIncome.entryDateStart != null and accountIncome.entryDateStart != '' ">
- AND income_date >= DATE_FORMAT(#{accountIncome.entryDateStart},'%Y-%m-%d')
- </if>
- <if test="accountIncome.entryDateEnd != null and accountIncome.entryDateEnd != '' ">
- AND income_date <= DATE_FORMAT(#{accountIncome.entryDateEnd},'%Y-%m-%d')
- </if>
- <if test="accountIncome.incomeType != null and accountIncome.incomeType != '' ">
- AND income_type = #{accountIncome.incomeType}
- </if>
- <if test="accountIncome.incomeMethod != null and accountIncome.incomeMethod != '' ">
- AND income_method = #{accountIncome.incomeMethod}
- </if>
- </select>
- <select id="report" resultType="com.ruoyi.account.bean.dto.AccountDto2">
- SELECT
- sdd.dict_label typeName,
- ifnull(sum(income_money),0) account
- FROM account_income ai
- left join sys_dict_data sdd on ai.income_type = sdd.dict_value and sdd.dict_type='income_types'
- where
- 1=1
- <if test="dateQueryDto.entryDateStart != null and dateQueryDto.entryDateStart != '' ">
- AND income_date >= DATE_FORMAT(#{dateQueryDto.entryDateStart},'%Y-%m-%d')
- </if>
- <if test="dateQueryDto.entryDateEnd != null and dateQueryDto.entryDateEnd != '' ">
- AND income_date <= DATE_FORMAT(#{dateQueryDto.entryDateEnd},'%Y-%m-%d')
- </if>
- GROUP BY sdd.dict_label, ai.income_type
- </select>
- <select id="report1" resultType="java.math.BigDecimal">
- SELECT
- ifnull(sum(income_money),0) account
- FROM account_income ai
- where
- income_type=#{dictValue}
- <if test="dateQueryDto.entryDateStart != null and dateQueryDto.entryDateStart != '' ">
- AND income_date >= DATE_FORMAT(#{dateQueryDto.entryDateStart},'%Y-%m-%d')
- </if>
- <if test="dateQueryDto.entryDateEnd != null and dateQueryDto.entryDateEnd != '' ">
- AND income_date <= DATE_FORMAT(#{dateQueryDto.entryDateEnd},'%Y-%m-%d')
- </if>
- </select>
-
- <select id="selectIncomeStats"
- resultType="com.ruoyi.home.dto.IncomeExpenseAnalysisDto">
- SELECT DATE_FORMAT(income_date, #{dateFormat}) AS dateStr,
- IFNULL(SUM(income_money), 0) AS amount
- FROM account_income
- WHERE income_date BETWEEN #{startDate} AND #{endDate}
-# AND business_type = 1
- GROUP BY dateStr
- ORDER BY dateStr
-
- </select>
-
-</mapper>
diff --git a/src/main/resources/mapper/account/AccountStatementMapper.xml b/src/main/resources/mapper/account/AccountStatementMapper.xml
new file mode 100644
index 0000000..32b1621
--- /dev/null
+++ b/src/main/resources/mapper/account/AccountStatementMapper.xml
@@ -0,0 +1,78 @@
+<?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.ruoyi.account.mapper.AccountStatementMapper">
+
+ <select id="listPageAccountStatement" resultType="com.ruoyi.account.bean.vo.StatementAccountVo">
+ SELECT lj.*,
+ <choose>
+ <when test="req.accountType == 1">
+ c.customer_name as customerName
+ </when>
+ <when test="req.accountType == 2">
+ s.supplier_name as customerName
+ </when>
+ <otherwise>
+ '' as customerName
+ </otherwise>
+ </choose>
+ FROM account_statement AS lj
+ <!-- 鍔ㄦ�� LEFT JOIN -->
+ <choose>
+ <when test="req.accountType == 1">
+ LEFT JOIN customer AS c
+ ON lj.customer_id = c.id
+ </when>
+ <when test="req.accountType == 2">
+ LEFT JOIN supplier_manage AS s
+ ON lj.customer_id = s.id
+ </when>
+ </choose>
+ WHERE 1=1
+ <if test="req.accountType != null">
+ AND lj.account_type = #{req.accountType}
+ </if>
+ <if test="req.customerId != null">
+ AND lj.customer_id = #{req.customerId}
+ </if>
+ <if test="req.startDate != null and req.endDate != null">
+ AND DATE_FORMAT(CONCAT(lj.statement_month, '-01'), '%Y-%m-%d')
+ BETWEEN #{req.startDate} AND #{req.endDate}
+ </if>
+ ORDER BY lj.statement_month DESC
+ </select>
+ <select id="selectVatDtoPage" resultType="com.ruoyi.purchase.dto.VatDto">
+ SELECT
+ month,
+ jTaxAmount,
+ xTaxAmount,
+ (jTaxAmount - xTaxAmount) AS taxAmount
+ FROM (
+ SELECT
+ month,
+ SUM(IF(type = 'purchase', tax_price, 0)) AS xTaxAmount,
+ SUM(IF(type = 'sales', tax_price, 0)) AS jTaxAmount
+ FROM (
+ SELECT
+ DATE_FORMAT(issue_date, '%Y-%m') AS month,
+ tax_price,
+ 'sales' AS type
+ FROM account_sales_invoice
+ WHERE status != 1
+ UNION ALL
+ SELECT
+ DATE_FORMAT(issue_date, '%Y-%m') AS month,
+ tax_price,
+ 'purchase' AS type
+ FROM account_purchase_invoice
+ WHERE status != 1
+ ) AS all_data
+ GROUP BY month
+ ) AS TT
+ <where>
+ <if test="month != null">
+ and TT.month = #{month}
+ </if>
+ </where>
+ ORDER BY TT.month
+ </select>
+</mapper>
diff --git a/src/main/resources/mapper/account/BorrowInfoMapper.xml b/src/main/resources/mapper/account/BorrowInfoMapper.xml
deleted file mode 100644
index f21c8d7..0000000
--- a/src/main/resources/mapper/account/BorrowInfoMapper.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?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.ruoyi.account.mapper.BorrowInfoMapper">
-
- <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
- <resultMap id="BaseResultMap" type="com.ruoyi.account.pojo.BorrowInfo">
- <id column="id" property="id" />
- <result column="borrower_name" property="borrowerName" />
- <result column="borrow_amount" property="borrowAmount" />
- <result column="interest_rate" property="interestRate" />
- <result column="borrow_date" property="borrowDate" />
- <result column="repay_date" property="repayDate" />
- <result column="status" property="status" />
- <result column="remark" property="remark" />
- <result column="create_time" property="createTime" />
- <result column="create_user" property="createUser" />
- <result column="update_time" property="updateTime" />
- <result column="update_user" property="updateUser" />
- <result column="tenant_id" property="tenantId" />
- </resultMap>
-
-</mapper>
diff --git a/src/main/resources/mapper/account/purchase/AccountPaymentApplicationMapper.xml b/src/main/resources/mapper/account/purchase/AccountPaymentApplicationMapper.xml
new file mode 100644
index 0000000..8b23627
--- /dev/null
+++ b/src/main/resources/mapper/account/purchase/AccountPaymentApplicationMapper.xml
@@ -0,0 +1,98 @@
+<?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.ruoyi.account.mapper.purchase.AccountPaymentApplicationMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.account.pojo.purchase.AccountPaymentApplication">
+ <id column="id" property="id" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ <result column="dept_id" property="deptId" />
+ <result column="supplier_id" property="supplierId" />
+ <result column="stock_in_record_ids" property="stockInRecordIds" />
+ <result column="invoice_application_no" property="invoiceApplicationNo" />
+ <result column="payment_method" property="paymentMethod" />
+ <result column="payment_content" property="paymentContent" />
+ <result column="apply_date" property="applyDate" />
+ <result column="remark" property="remark" />
+ <result column="status" property="status" />
+ <result column="payment_amount" property="paymentAmount" />
+ </resultMap>
+ <select
+ id="listPageAccountPaymentApplication"
+ resultType="com.ruoyi.account.bean.vo.purchase.AccountPaymentApplicationVo">
+ select * from (select apa.*,
+ sm.supplier_name,
+ GROUP_CONCAT(sir.inbound_batches SEPARATOR ',') AS inboundBatches
+ from account_payment_application apa
+ left join supplier_manage sm on apa.supplier_id = sm.id
+ left join stock_in_record sir on FIND_IN_SET(sir.id, apa.stock_in_record_ids) > 0
+ GROUP BY apa.id)A
+ <where>
+ <if test="req.supplierId != null">
+ AND A.supplier_id = #{req.supplierId}
+ </if>
+ <if test="req.invoiceApplicationNo != null and req.invoiceApplicationNo != ''">
+ AND A.invoice_application_no LIKE CONCAT('%',#{req.invoiceApplicationNo},'%')
+ </if>
+ <if test="req.status != null">
+ AND A.status = #{req.status}
+ </if>
+ <if test="req.startDate != null and req.endDate != null">
+ AND A.apply_date BETWEEN #{req.startDate} AND #{req.endDate}
+ </if>
+ </where>
+ </select>
+
+ <select id="getInboundBatchesBySupplier"
+ resultType="com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo">
+ SELECT
+ sir.id,
+ sir.inbound_batches,
+ pl.supplier_name,
+ DATE(sir.create_time) AS inboundDate,
+ p.product_name,
+ pm.model as specification_model,
+ sir.stock_in_num * slp.tax_inclusive_unit_price AS InboundAmount,
+ pl.purchase_contract_number
+ FROM stock_in_record sir
+ -- 10 绫诲瀷鎵嶅叧鑱旇川妫�琛�
+ LEFT JOIN quality_inspect qi ON sir.record_type = 10 AND sir.record_id = qi.id
+ -- 鍔ㄦ�佸叧鑱旈噰璐紙鑷姩閫傞厤 7 鍜� 10锛�
+ LEFT JOIN purchase_ledger pl
+ ON pl.id = IF(sir.record_type = 7, sir.record_id, qi.purchase_ledger_id)
+ -- 浜у搧鍏宠仈涓嶅姩
+ LEFT JOIN sales_ledger_product slp ON pl.id = slp.sales_ledger_id
+ LEFT JOIN product_model pm ON sir.product_model_id = pm.id
+ LEFT JOIN product p ON pm.product_id = p.id
+ -- 鏉′欢
+ WHERE sir.approval_status = 1 AND slp.type = 2
+ AND sir.record_type IN ('7','10')
+ and pl.supplier_id=#{supplierId}
+
+ and sir.id NOT IN (
+ SELECT DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(a.stock_in_record_ids, ',', n.n), ',', -1)
+ FROM account_payment_application a
+ CROSS JOIN (
+ SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL
+ SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
+ ) n
+ WHERE n.n <= CHAR_LENGTH(a.stock_in_record_ids) - CHAR_LENGTH(REPLACE(a.stock_in_record_ids, ',', '')) + 1
+ and a.status!=2
+ )
+
+ order by sir.id DESC
+ </select>
+
+ <select id="existsByStockInRecordId" resultType="java.lang.Boolean">
+ SELECT COUNT(*) > 0
+ FROM account_payment_application
+ WHERE status != 2
+ <foreach collection="stockInRecordIds" item="id" open="(" separator=" OR " close=")">
+ FIND_IN_SET(#{id}, stock_in_record_ids)
+ </foreach>
+ </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/account/purchase/AccountPurchaseInvoiceMapper.xml b/src/main/resources/mapper/account/purchase/AccountPurchaseInvoiceMapper.xml
new file mode 100644
index 0000000..041f2f7
--- /dev/null
+++ b/src/main/resources/mapper/account/purchase/AccountPurchaseInvoiceMapper.xml
@@ -0,0 +1,86 @@
+<?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.ruoyi.account.mapper.purchase.AccountPurchaseInvoiceMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.account.pojo.purchase.AccountPurchaseInvoice">
+ <id column="id" property="id" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ <result column="dept_id" property="deptId" />
+ <result column="invoice_number" property="invoiceNumber" />
+ <result column="tax_rate" property="taxRate" />
+ <result column="invoice_type" property="invoiceType" />
+ <result column="issue_date" property="issueDate" />
+ <result column="tax_exclusivel_price" property="taxExclusivelPrice" />
+ <result column="tax_price" property="taxPrice" />
+ <result column="tax_inclusive_price" property="taxInclusivePrice" />
+ <result column="remark" property="remark" />
+ <result column="invoice_content" property="invoiceContent" />
+ <result column="supplier_id" property="supplierId" />
+ <result column="storage_attachment_id" property="storageAttachmentId" />
+ <result column="stock_in_record_ids" property="stockInRecordIds" />
+ </resultMap>
+ <select id="listPageAccountPurchaseInvoice"
+ resultType="com.ruoyi.account.bean.vo.purchase.AccountPurchaseInvoiceVo">
+ select api.* , sm.supplier_name
+ from account_purchase_invoice api
+ left join supplier_manage sm on api.supplier_id = sm.id
+ <where>
+ <if test="req.supplierId != null">
+ AND api.supplier_id = #{req.supplierId}
+ </if>
+ <if test="req.status != null">
+ AND api.status = #{req.status}
+ </if>
+ <if test="req.invoiceNumber != null and req.invoiceNumber != ''">
+ AND api.invoice_number LIKE CONCAT('%',#{req.invoiceNumber},'%')
+ </if>
+ <if test="req.startDate != null and req.endDate != null">
+ AND api.issue_date BETWEEN #{req.startDate} AND #{req.endDate}
+ </if>
+ </where>
+ </select>
+ <select id="getInboundBatchesBySupplier"
+ resultType="com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo">
+ SELECT
+ sir.id,
+ sir.inbound_batches,
+ pl.supplier_name,
+ DATE(sir.create_time) AS inboundDate,
+ p.product_name,
+ pm.model as specification_model,
+ sir.stock_in_num * slp.tax_inclusive_unit_price AS InboundAmount,
+ pl.purchase_contract_number
+ FROM stock_in_record sir
+ -- 10 绫诲瀷鎵嶅叧鑱旇川妫�琛�
+ LEFT JOIN quality_inspect qi ON sir.record_type = 10 AND sir.record_id = qi.id
+ -- 鍔ㄦ�佸叧鑱旈噰璐紙鑷姩閫傞厤 7 鍜� 10锛�
+ LEFT JOIN purchase_ledger pl
+ ON pl.id = IF(sir.record_type = 7, sir.record_id, qi.purchase_ledger_id)
+ -- 浜у搧鍏宠仈涓嶅姩
+ LEFT JOIN sales_ledger_product slp ON pl.id = slp.sales_ledger_id
+ LEFT JOIN product_model pm ON sir.product_model_id = pm.id
+ LEFT JOIN product p ON pm.product_id = p.id
+ -- 鏉′欢
+ WHERE sir.approval_status = 1 AND slp.type = 2
+ AND sir.record_type IN ('7','10')
+ and pl.supplier_id=#{supplierId}
+
+ and sir.id NOT IN (
+ SELECT DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(a.stock_in_record_ids, ',', n.n), ',', -1)
+ FROM account_purchase_invoice a
+ CROSS JOIN (
+ SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL
+ SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
+ ) n
+ WHERE n.n <= CHAR_LENGTH(a.stock_in_record_ids) - CHAR_LENGTH(REPLACE(a.stock_in_record_ids, ',', '')) + 1
+ and a.status=0
+ )
+
+ order by sir.id DESC
+ </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/account/purchase/AccountPurchasePaymentMapper.xml b/src/main/resources/mapper/account/purchase/AccountPurchasePaymentMapper.xml
new file mode 100644
index 0000000..89a3681
--- /dev/null
+++ b/src/main/resources/mapper/account/purchase/AccountPurchasePaymentMapper.xml
@@ -0,0 +1,57 @@
+<?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.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.account.pojo.purchase.AccountPurchasePayment">
+ <id column="id" property="id" />
+ <result column="account_payment_application_id" property="accountPaymentApplicationId" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ <result column="dept_id" property="deptId" />
+ <result column="supplier_id" property="supplierId" />
+ <result column="payment_date" property="paymentDate" />
+ <result column="payment_method" property="paymentMethod" />
+ <result column="payment_amount" property="paymentAmount" />
+ <result column="payment_number" property="paymentNumber" />
+ <result column="remark" property="remark" />
+ </resultMap>
+ <select id="listPageAccountPurchasePayment"
+ resultType="com.ruoyi.account.bean.vo.purchase.AccountPurchasePaymentVo">
+ select app.*,
+ sm.supplier_name,
+ sm.bank_account_num,
+ sm.bank_account_name,
+ apa.invoice_application_no AS invoiceApplicationNo,
+ if(asd.receipt_number is not null, true, false) as isAccountStatemen
+ from account_purchase_payment app
+ left join supplier_manage sm on app.supplier_id = sm.id
+ left join account_payment_application apa on app.account_payment_application_id=apa.id
+ left join account_statement_details asd on app.payment_number = asd.receipt_number
+ <where>
+ <if test="req.supplierId != null">
+ AND app.supplier_id = #{req.supplierId}
+ </if>
+ <if test="req.paymentMethod != null and req.paymentMethod != ''">
+ AND app.payment_method LIKE CONCAT('%',#{req.paymentMethod},'%')
+ </if>
+ <if test="req.paymentNumber != null and req.paymentNumber != ''">
+ AND app.payment_number LIKE CONCAT('%',#{req.paymentNumber},'%')
+ </if>
+ <if test="req.startDate != null and req.endDate != null">
+ AND app.payment_date BETWEEN #{req.startDate} AND #{req.endDate}
+ </if>
+ </where>
+ </select>
+ <select id="selectPayment" resultType="com.ruoyi.home.dto.IncomeExpenseAnalysisDto">
+ SELECT DATE_FORMAT(payment_date, #{dateFormat}) AS dateStr,
+ IFNULL(SUM(payment_amount), 0) AS amount
+ FROM account_purchase_payment
+ WHERE payment_date BETWEEN #{startStr} AND #{endStr}
+ GROUP BY dateStr
+ ORDER BY dateStr
+ </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/account/sales/AccountInvoiceApplicationMapper.xml b/src/main/resources/mapper/account/sales/AccountInvoiceApplicationMapper.xml
new file mode 100644
index 0000000..842e94c
--- /dev/null
+++ b/src/main/resources/mapper/account/sales/AccountInvoiceApplicationMapper.xml
@@ -0,0 +1,73 @@
+<?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.ruoyi.account.mapper.sales.AccountInvoiceApplicationMapper">
+
+ <select id="listPageAccountInvoiceApplication"
+ resultType="com.ruoyi.account.bean.vo.sales.AccountInvoiceApplicationVo">
+ select * from (select aia.*,
+ c.customer_name,
+ GROUP_CONCAT(sour.outbound_batches SEPARATOR ',') AS outboundBatches
+ from account_invoice_application aia
+ left join customer c on aia.customer_id = c.id
+ left join stock_out_record sour on FIND_IN_SET(sour.id, aia.stock_out_record_ids) > 0
+ GROUP BY aia.id)A
+ <where>
+ <if test="req.customerId != null">
+ AND A.customer_id = #{req.customerId}
+ </if>
+ <if test="req.invoiceApplicationNo != null and req.invoiceApplicationNo != ''">
+ AND A.invoice_application_no LIKE CONCAT('%',#{req.invoiceApplicationNo},'%')
+ </if>
+ <if test="req.status != null">
+ AND A.status = #{req.status}
+ </if>
+ <if test="req.startDate != null and req.endDate != null">
+ AND A.apply_date BETWEEN #{req.startDate} AND #{req.endDate}
+ </if>
+ </where>
+ </select>
+ <select id="getOutboundBatchesByCustomer"
+ resultType="com.ruoyi.account.bean.vo.sales.SalesOutboundVo">
+ SELECT
+ sor.id,
+ sor.outbound_batches,
+ sl.customer_name,
+ sor.create_time as shippingDate,
+ p.product_name,
+ pm.model as specification_model,
+ slp.tax_rate,
+ sor.stock_out_num * slp.tax_inclusive_unit_price as outboundAmount,
+ s.shipping_no,
+ sl.sales_contract_no
+ FROM stock_out_record sor
+ left join shipping_info s on sor.record_id = s.id
+ LEFT JOIN sales_ledger sl ON s.sales_ledger_id = sl.id
+ LEFT JOIN sales_ledger_product slp ON s.sales_ledger_product_id = slp.id and slp.type = 1
+ left join product_model pm on slp.product_model_id = pm.id
+ left join product p on pm.product_id = p.id
+ WHERE sor.record_type='13' and sor.approval_status=1
+ and sl.customer_id=#{customerId}
+
+ and sor.id NOT IN (
+ SELECT DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(a.stock_out_record_ids, ',', n.n), ',', -1)
+ FROM account_invoice_application a
+ CROSS JOIN (
+ SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL
+ SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
+ ) n
+ WHERE n.n <= CHAR_LENGTH(a.stock_out_record_ids) - CHAR_LENGTH(REPLACE(a.stock_out_record_ids, ',', '')) + 1
+ and a.status!=2
+ )
+
+ order by sor.id DESC
+ </select>
+ <select id="existsByStockOutRecordId" resultType="java.lang.Boolean">
+ SELECT COUNT(*) > 0
+ FROM account_invoice_application
+ WHERE status!=2
+ <foreach collection="stockOutRecordIds" item="id" open="(" separator=" OR " close=")">
+ FIND_IN_SET(#{id}, stock_out_record_ids)
+ </foreach>
+ </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/account/sales/AccountSalesCollectionMapper.xml b/src/main/resources/mapper/account/sales/AccountSalesCollectionMapper.xml
new file mode 100644
index 0000000..4ad55d4
--- /dev/null
+++ b/src/main/resources/mapper/account/sales/AccountSalesCollectionMapper.xml
@@ -0,0 +1,101 @@
+<?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.ruoyi.account.mapper.sales.AccountSalesCollectionMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.account.pojo.sales.AccountSalesCollection">
+ <id column="id" property="id" />
+ <result column="stock_out_record_ids" property="stockOutRecordIds" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ <result column="dept_id" property="deptId" />
+ <result column="customer_id" property="customerId" />
+ <result column="collection_date" property="collectionDate" />
+ <result column="collection_amount" property="collectionAmount" />
+ <result column="collection_method" property="collectionMethod" />
+ <result column="collection_number" property="collectionNumber" />
+ <result column="remark" property="remark" />
+ </resultMap>
+ <select id="listPageAccountSalesCollection"
+ resultType="com.ruoyi.account.bean.vo.sales.AccountSalesCollectionVo">
+ select
+ A.* ,
+ if(asd.receipt_number is not null, true, false) as isAccountStatemen
+ from (select ascc.*,
+ c.customer_name,
+ GROUP_CONCAT(sour.outbound_batches SEPARATOR ',') AS outboundBatches
+ from account_sales_collection ascc
+ left join customer c on ascc.customer_id = c.id
+ left join stock_out_record sour on FIND_IN_SET(sour.id, ascc.stock_out_record_ids) > 0
+ GROUP BY ascc.id)A
+ left join account_statement_details asd on A.collection_number = asd.receipt_number
+ <where>
+ <if test="req.customerId != null">
+ AND A.customer_id = #{req.customerId}
+ </if>
+ <if test="req.collectionNumber != null and req.collectionNumber != ''">
+ AND A.collection_number LIKE CONCAT('%',#{req.collectionNumber},'%')
+ </if>
+ <if test="req.collectionMethod != null and req.collectionMethod != ''">
+ AND A.collection_method LIKE CONCAT('%',#{req.collectionMethod},'%')
+ </if>
+ <if test="req.startDate != null and req.endDate != null">
+ AND A.collection_date BETWEEN #{req.startDate} AND #{req.endDate}
+ </if>
+ </where>
+
+ </select>
+ <select id="existsByStockOutRecordId" resultType="java.lang.Boolean">
+ SELECT COUNT(*) > 0
+ FROM account_sales_collection
+ WHERE
+ <foreach collection="stockOutRecordIds" item="id" open="(" separator=" OR " close=")">
+ FIND_IN_SET(#{id}, stock_out_record_ids)
+ </foreach>
+ </select>
+ <select id="getOutboundBatchesByCustomer"
+ resultType="com.ruoyi.account.bean.vo.sales.SalesOutboundVo">
+ SELECT
+ sor.id,
+ sor.outbound_batches,
+ sl.customer_name,
+ sor.create_time as shippingDate,
+ p.product_name,
+ pm.model as specification_model,
+ slp.tax_rate,
+ sor.stock_out_num * slp.tax_inclusive_unit_price as outboundAmount,
+ s.shipping_no,
+ sl.sales_contract_no
+ FROM stock_out_record sor
+ left join shipping_info s on sor.record_id = s.id
+ LEFT JOIN sales_ledger sl ON s.sales_ledger_id = sl.id
+ LEFT JOIN sales_ledger_product slp ON s.sales_ledger_product_id = slp.id and slp.type = 1
+ left join product_model pm on slp.product_model_id = pm.id
+ left join product p on pm.product_id = p.id
+ WHERE sor.record_type='13' and sor.approval_status=1
+ and sl.customer_id=#{customerId}
+
+ and sor.id NOT IN (
+ SELECT DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(a.stock_out_record_ids, ',', n.n), ',', -1)
+ FROM account_sales_collection a
+ CROSS JOIN (
+ SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL
+ SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
+ ) n
+ WHERE n.n <= CHAR_LENGTH(a.stock_out_record_ids) - CHAR_LENGTH(REPLACE(a.stock_out_record_ids, ',', '')) + 1
+ )
+
+ order by sor.id DESC
+ </select>
+ <select id="selectIncomeStats" resultType="com.ruoyi.home.dto.IncomeExpenseAnalysisDto">
+ SELECT DATE_FORMAT(collection_date, #{dateFormat}) AS dateStr,
+ IFNULL(SUM(collection_amount), 0) AS amount
+ FROM account_sales_collection
+ WHERE collection_date BETWEEN #{startStr} AND #{endStr}
+ GROUP BY dateStr
+ ORDER BY dateStr
+ </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/account/sales/AccountSalesInvoiceMapper.xml b/src/main/resources/mapper/account/sales/AccountSalesInvoiceMapper.xml
new file mode 100644
index 0000000..b289b8f
--- /dev/null
+++ b/src/main/resources/mapper/account/sales/AccountSalesInvoiceMapper.xml
@@ -0,0 +1,47 @@
+<?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.ruoyi.account.mapper.sales.AccountSalesInvoiceMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.account.pojo.sales.AccountSalesInvoice">
+ <id column="id" property="id" />
+ <result column="account_invoice_application_id" property="accountInvoiceApplicationId" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ <result column="dept_id" property="deptId" />
+ <result column="invoice_number" property="invoiceNumber" />
+ <result column="tax_rate" property="taxRate" />
+ <result column="invoice_type" property="invoiceType" />
+ <result column="issue_date" property="issueDate" />
+ <result column="tax_exclusivel_price" property="taxExclusivelPrice" />
+ <result column="tax_price" property="taxPrice" />
+ <result column="tax_inclusive_price" property="taxInclusivePrice" />
+ <result column="remark" property="remark" />
+ <result column="invoice_content" property="invoiceContent" />
+ <result column="customer_id" property="customerId" />
+ <result column="storage_attachment_id" property="storageAttachmentId" />
+ </resultMap>
+ <select id="listPageAccountSalesInvoice"
+ resultType="com.ruoyi.account.bean.vo.sales.AccountSalesInvoiceVo">
+ select asi.* , c.customer_name
+ from account_sales_invoice asi
+ left join customer c on asi.customer_id = c.id
+ <where>
+ <if test="req.customerId != null">
+ AND asi.customer_id = #{req.customerId}
+ </if>
+ <if test="req.status != null">
+ AND asi.status = #{req.status}
+ </if>
+ <if test="req.invoiceNumber != null and req.invoiceNumber != ''">
+ AND asi.invoice_number LIKE CONCAT('%',#{req.invoiceNumber},'%')
+ </if>
+ <if test="req.startDate != null and req.endDate != null">
+ AND asi.issue_date BETWEEN #{req.startDate} AND #{req.endDate}
+ </if>
+ </where>
+ </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/approve/ApprovalInstanceMapper.xml b/src/main/resources/mapper/approve/ApprovalInstanceMapper.xml
new file mode 100644
index 0000000..612f457
--- /dev/null
+++ b/src/main/resources/mapper/approve/ApprovalInstanceMapper.xml
@@ -0,0 +1,58 @@
+<?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.ruoyi.approve.mapper.ApprovalInstanceMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.approve.pojo.ApprovalInstance">
+ <id column="id" property="id" />
+ <result column="instance_no" property="instanceNo" />
+ <result column="template_id" property="templateId" />
+ <result column="template_name" property="templateName" />
+ <result column="business_id" property="businessId" />
+ <result column="business_type" property="businessType" />
+ <result column="title" property="title" />
+ <result column="status" property="status" />
+ <result column="current_level" property="currentLevel" />
+ <result column="applicant_id" property="applicantId" />
+ <result column="applicant_name" property="applicantName" />
+ <result column="apply_time" property="applyTime" />
+ <result column="finish_time" property="finishTime" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ <result column="deleted" property="deleted" />
+ </resultMap>
+ <select id="listPage" resultType="com.ruoyi.approve.bean.vo.ApprovalInstanceVo">
+ select ai.*,su.nick_name as create_user_name from
+ approval_instance ai
+ left join sys_user su on ai.create_user = su.user_id
+ <where>
+ deleted = 0
+ <if test="ew.instanceNo != null">
+ and ai.instance_no like concat('%',#{ew.instanceNo},'%')
+ </if>
+ <if test="ew.templateName != null">
+ and ai.template_name like concat('%',#{ew.templateName},'%')
+ </if>
+ <if test="ew.templateId != null ">
+ and ai. template_id = #{ew.templateId}
+ </if>
+ <if test="ew.businessType != null ">
+ and ai.business_type = #{ew.businessType}
+ </if>
+ <if test="ew.createTimeStart != null and ew.createTimeEnd != null">
+ and ai.apply_time >= #{ew.createTimeStart}
+ and ai.apply_time <= #{ew.createTimeEnd}
+ </if>
+ <if test="ew.status != null">
+ and ai.status = #{ew.status}
+ </if>
+ <if test="ew.applicantName != null and ew.applicantName !=''">
+ and ai.applicant_name = #{ew.applicantName}
+ </if>
+ </where>
+ order by ai.id desc
+ </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/approve/ApprovalInstanceNodeMapper.xml b/src/main/resources/mapper/approve/ApprovalInstanceNodeMapper.xml
new file mode 100644
index 0000000..560271b
--- /dev/null
+++ b/src/main/resources/mapper/approve/ApprovalInstanceNodeMapper.xml
@@ -0,0 +1,21 @@
+<?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.ruoyi.approve.mapper.ApprovalInstanceNodeMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.approve.pojo.ApprovalInstanceNode">
+ <id column="id" property="id" />
+ <result column="instance_id" property="instanceId" />
+ <result column="level_no" property="levelNo" />
+ <result column="approve_type" property="approveType" />
+ <result column="status" property="status" />
+ <result column="start_time" property="startTime" />
+ <result column="finish_time" property="finishTime" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ <result column="deleted" property="deleted" />
+ </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/approve/ApprovalRecordMapper.xml b/src/main/resources/mapper/approve/ApprovalRecordMapper.xml
new file mode 100644
index 0000000..db40692
--- /dev/null
+++ b/src/main/resources/mapper/approve/ApprovalRecordMapper.xml
@@ -0,0 +1,20 @@
+<?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.ruoyi.approve.mapper.ApprovalRecordMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.approve.pojo.ApprovalRecord">
+ <id column="id" property="id" />
+ <result column="instance_id" property="instanceId" />
+ <result column="node_id" property="nodeId" />
+ <result column="task_id" property="taskId" />
+ <result column="operator_id" property="operatorId" />
+ <result column="operator_name" property="operatorName" />
+ <result column="action" property="action" />
+ <result column="comment" property="comment" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="deleted" property="deleted" />
+ </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/approve/ApprovalTaskMapper.xml b/src/main/resources/mapper/approve/ApprovalTaskMapper.xml
new file mode 100644
index 0000000..c079440
--- /dev/null
+++ b/src/main/resources/mapper/approve/ApprovalTaskMapper.xml
@@ -0,0 +1,24 @@
+<?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.ruoyi.approve.mapper.ApprovalTaskMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.approve.pojo.ApprovalTask">
+ <id column="id" property="id" />
+ <result column="instance_id" property="instanceId" />
+ <result column="node_id" property="nodeId" />
+ <result column="level_no" property="levelNo" />
+ <result column="approver_id" property="approverId" />
+ <result column="approver_name" property="approverName" />
+ <result column="task_status" property="taskStatus" />
+ <result column="approve_time" property="approveTime" />
+ <result column="comment" property="comment" />
+ <result column="is_read" property="isRead" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ <result column="deleted" property="deleted" />
+ </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/approve/ApprovalTemplateMapper.xml b/src/main/resources/mapper/approve/ApprovalTemplateMapper.xml
new file mode 100644
index 0000000..a48432b
--- /dev/null
+++ b/src/main/resources/mapper/approve/ApprovalTemplateMapper.xml
@@ -0,0 +1,33 @@
+<?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.ruoyi.approve.mapper.ApprovalTemplateMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.approve.pojo.ApprovalTemplate">
+ <id column="id" property="id" />
+ <result column="template_name" property="templateName" />
+ <result column="enabled" property="enabled" />
+ <result column="description" property="description" />
+ <result column="deleted" property="deleted" />
+ <result column="dept_id" property="deptId" />
+ </resultMap>
+ <select id="listPage" resultType="com.ruoyi.approve.bean.vo.ApprovalTemplateVo">
+ select at.*,su.nick_name as create_user_name from
+ approval_template at
+ left join sys_user su on at.create_user = su.user_id
+ <where>
+ deleted = 0
+ <if test="ew.templateName != null">
+ and template_name like concat('%',#{ew.templateName},'%')
+ </if>
+ <if test="ew.templateType != null">
+ and template_type = #{ew.templateType}
+ </if>
+ <if test="ew.enabled != null">
+ and enabled = #{ew.enabled}
+ </if>
+ </where>
+ order by at.id desc
+ </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/approve/ApprovalTemplateNodeApproverMapper.xml b/src/main/resources/mapper/approve/ApprovalTemplateNodeApproverMapper.xml
new file mode 100644
index 0000000..dac42cc
--- /dev/null
+++ b/src/main/resources/mapper/approve/ApprovalTemplateNodeApproverMapper.xml
@@ -0,0 +1,16 @@
+<?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.ruoyi.approve.mapper.ApprovalTemplateNodeApproverMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.approve.pojo.ApprovalTemplateNodeApprover">
+ <id column="id" property="id" />
+ <result column="node_id" property="nodeId" />
+ <result column="template_id" property="templateId" />
+ <result column="approver_id" property="approverId" />
+ <result column="approver_name" property="approverName" />
+ <result column="sort_no" property="sortNo" />
+ <result column="created_time" property="createdTime" />
+ </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/approve/ApprovalTemplateNodeMapper.xml b/src/main/resources/mapper/approve/ApprovalTemplateNodeMapper.xml
new file mode 100644
index 0000000..7956787
--- /dev/null
+++ b/src/main/resources/mapper/approve/ApprovalTemplateNodeMapper.xml
@@ -0,0 +1,15 @@
+<?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.ruoyi.approve.mapper.ApprovalTemplateNodeMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.approve.pojo.ApprovalTemplateNode">
+ <id column="id" property="id" />
+ <result column="template_id" property="templateId" />
+ <result column="level_no" property="levelNo" />
+ <result column="approve_type" property="approveType" />
+ <result column="created_time" property="createdTime" />
+ <result column="updated_time" property="updatedTime" />
+ </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/approve/ApproveProcessMapper.xml b/src/main/resources/mapper/approve/ApproveProcessMapper.xml
index fef06f7..dd651c0 100644
--- a/src/main/resources/mapper/approve/ApproveProcessMapper.xml
+++ b/src/main/resources/mapper/approve/ApproveProcessMapper.xml
@@ -20,12 +20,14 @@
<result property="tenantId" column="tenant_id" />
<result property="approveType" column="approve_type" />
<result property="approveRemark" column="approve_remark" />
+ <result property="startDateTime" column="start_date_time" />
+ <result property="endDateTime" column="end_date_time" />
</resultMap>
<sql id="Base_Column_List">
id,approve_id,approve_user,approve_dept_id,approve_dept_name,approve_user_ids,
approve_user_names,approve_reason,approve_time,approve_over_time,approve_status,
- approve_delete,tenant_id,approve_type,approve_remark
+ approve_delete,tenant_id,approve_type,approve_remark,start_date_time,end_date_time
</sql>
<select id="listPage" resultType="com.ruoyi.approve.vo.ApproveProcessVo">
select * from approve_process where approve_delete = 0
diff --git a/src/main/resources/mapper/approve/FinReimbursementDetailMapper.xml b/src/main/resources/mapper/approve/FinReimbursementDetailMapper.xml
new file mode 100644
index 0000000..f8a67bb
--- /dev/null
+++ b/src/main/resources/mapper/approve/FinReimbursementDetailMapper.xml
@@ -0,0 +1,29 @@
+<?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.ruoyi.approve.mapper.FinReimbursementDetailMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.approve.pojo.FinReimbursementDetail">
+ <id column="id" property="id" />
+ <result column="reimbursement_id" property="reimbursementId" />
+ <result column="row_no" property="rowNo" />
+ <result column="invoice_date" property="invoiceDate" />
+ <result column="expense_category" property="expenseCategory" />
+ <result column="amount" property="amount" />
+ <result column="description" property="description" />
+ <result column="invoice_no" property="invoiceNo" />
+ <result column="invoice_type" property="invoiceType" />
+ <result column="invoice_amount" property="invoiceAmount" />
+ <result column="tax_rate" property="taxRate" />
+ <result column="tax_amount" property="taxAmount" />
+ <result column="remark" property="remark" />
+ <result column="tenant_id" property="tenantId" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ <result column="dept_id" property="deptId" />
+ <result column="deleted" property="deleted" />
+ </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/approve/FinReimbursementMapper.xml b/src/main/resources/mapper/approve/FinReimbursementMapper.xml
new file mode 100644
index 0000000..72756c4
--- /dev/null
+++ b/src/main/resources/mapper/approve/FinReimbursementMapper.xml
@@ -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.ruoyi.approve.mapper.FinReimbursementMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.approve.pojo.FinReimbursement">
+ <id column="id" property="id" />
+ <result column="bill_no" property="billNo" />
+ <result column="reimbursement_type" property="reimbursementType" />
+ <result column="expense_type" property="expenseType" />
+ <result column="applicant_id" property="applicantId" />
+ <result column="applicant_code" property="applicantCode" />
+ <result column="applicant_name" property="applicantName" />
+ <result column="applicant_dept_id" property="applicantDeptId" />
+ <result column="applicant_dept_name" property="applicantDeptName" />
+ <result column="reason" property="reason" />
+ <result column="apply_amount" property="applyAmount" />
+ <result column="detail_total_amount" property="detailTotalAmount" />
+ <result column="payee_name" property="payeeName" />
+ <result column="payee_account" property="payeeAccount" />
+ <result column="payee_bank" property="payeeBank" />
+ <result column="approval_instance_id" property="approvalInstanceId" />
+ <result column="approve_process_id" property="approveProcessId" />
+ <result column="bill_status" property="billStatus" />
+ <result column="approved_time" property="approvedTime" />
+ <result column="paid_time" property="paidTime" />
+ <result column="account_expense_id" property="accountExpenseId" />
+ <result column="remark" property="remark" />
+ <result column="tenant_id" property="tenantId" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ <result column="dept_id" property="deptId" />
+ <result column="deleted" property="deleted" />
+ </resultMap>
+ <select id="listPage" resultType="com.ruoyi.approve.bean.vo.FinReimbursementVo">
+ select fin_reimbursement.*,
+ fin_reimbursement_travel.start_time ,
+ fin_reimbursement_travel.end_time
+ from
+ fin_reimbursement
+ left join fin_reimbursement_travel on fin_reimbursement.id = fin_reimbursement_travel.reimbursement_id
+ <where>
+ <if test="ew.billNo != null and ew.billNo != ''">
+ bill_no like concat('%',#{ew.billNo},'%')
+ </if>
+ <if test="ew.applicantName != null and ew.applicantName != ''">
+ and applicant_name like concat('%',#{ew.applicantName},'%')
+ </if>
+ <if test="ew.applicantCode != null and ew.applicantCode != ''">
+ and applicant_code like concat('%',#{ew.applicantCode},'%')
+ </if>
+ <if test="ew.createTimeStart != null and ew.createTimeStart !='' and ew.createTimeEnd != null and ew.createTimeEnd != ''">
+ and create_time >= #{ew.createTimeStart}
+ and create_time <= #{ew.createTimeEnd}
+ </if>
+ </where>
+ </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/approve/FinReimbursementTravelMapper.xml b/src/main/resources/mapper/approve/FinReimbursementTravelMapper.xml
new file mode 100644
index 0000000..dc42863
--- /dev/null
+++ b/src/main/resources/mapper/approve/FinReimbursementTravelMapper.xml
@@ -0,0 +1,29 @@
+<?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.ruoyi.approve.mapper.FinReimbursementTravelMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.approve.pojo.FinReimbursementTravel">
+ <id column="id" property="id" />
+ <result column="reimbursement_id" property="reimbursementId" />
+ <result column="start_time" property="startTime" />
+ <result column="end_time" property="endTime" />
+ <result column="travel_days" property="travelDays" />
+ <result column="departure_city" property="departureCity" />
+ <result column="destination_city" property="destinationCity" />
+ <result column="hotel_standard" property="hotelStandard" />
+ <result column="lodging_days" property="lodgingDays" />
+ <result column="meal_allowance" property="mealAllowance" />
+ <result column="transport_allowance" property="transportAllowance" />
+ <result column="lodging_limit" property="lodgingLimit" />
+ <result column="standard_tag" property="standardTag" />
+ <result column="within_standard" property="withinStandard" />
+ <result column="tenant_id" property="tenantId" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ <result column="dept_id" property="deptId" />
+ </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/basic/CustomerMapper.xml b/src/main/resources/mapper/basic/CustomerMapper.xml
index b2546d7..8117c66 100644
--- a/src/main/resources/mapper/basic/CustomerMapper.xml
+++ b/src/main/resources/mapper/basic/CustomerMapper.xml
@@ -107,4 +107,87 @@
</if>
</where>
</select>
+ <select id="customewTransactions" resultType="com.ruoyi.sales.vo.CustomerTransactionsVo">
+ select T1.customer_id,
+ c.customer_name,
+ T1.contractAmounts,
+ IFNULL(T2.receiptPaymentAmount, 0) AS receiptPaymentAmount,
+ IFNULL(T3.outboundAmount, 0) - IFNULL(T4.returnAmount, 0) AS receiptableAmount
+ from (select customer_id, sum(contract_amount) as contractAmounts from sales_ledger group by customer_id) T1
+ left join (select customer_id, sum(collection_amount) as receiptPaymentAmount from account_sales_collection group by customer_id) T2 on T1.customer_id = T2.customer_id
+ left join (
+ SELECT
+ sl.customer_id,
+ sum(sor.stock_out_num * slp.tax_inclusive_unit_price) as outboundAmount
+ FROM stock_out_record sor
+ LEFT join shipping_info s on sor.record_id = s.id
+ LEFT JOIN sales_ledger sl ON s.sales_ledger_id = sl.id
+ LEFT JOIN sales_ledger_product slp ON s.sales_ledger_product_id = slp.id
+ WHERE sor.record_type='13'
+ and sor.approval_status=1
+ and slp.type = 1
+ group by sl.customer_id
+ ) T3 on T3.customer_id=T1.customer_id
+ left join (
+ select
+ sl.customer_id,
+ sum(rm.refund_amount) as returnAmount
+ from return_management rm
+ left join shipping_info si on rm.shipping_id = si.id
+ left join sales_ledger sl on si.sales_ledger_id = sl.id
+ where rm.status=1
+ group by sl.customer_id
+ ) T4 on T4.customer_id=T1.customer_id
+ left join customer c on T1.customer_id = c.id
+ <where>
+ <if test="customerName!=null and customerName!=''">
+ AND c.customer_name LIKE CONCAT('%', #{customerName}, '%')
+ </if>
+ </where>
+ </select>
+ <select id="customewTransactionsDetails"
+ resultType="com.ruoyi.sales.vo.CustomerTransactionsDetailsVo">
+ select sl.id salesLedgerId,
+ sl.sales_contract_no,
+ sl.execution_date,
+ sl.contract_amount,
+ IFNULL(T1.receiptPaymentAmount, 0) AS receiptPaymentAmount,
+ IFNULL(T2.outboundAmount, 0) - IFNULL(T3.returnAmount, 0) AS receiptableAmount
+ from sales_ledger sl
+ left join (
+ select
+ sl.id,
+ sum(ascc.collection_amount) as receiptPaymentAmount
+ from account_sales_collection ascc
+ left join stock_out_record sor on FIND_IN_SET(sor.id, ascc.stock_out_record_ids) > 0
+ left join shipping_info s on sor.record_id = s.id
+ LEFT JOIN sales_ledger sl ON s.sales_ledger_id = sl.id
+ WHERE sor.record_type='13'
+ and sor.approval_status=1
+ group by sl.id
+ )T1 on T1.id = sl.id
+ left join (
+ SELECT
+ sl.id,
+ sum(sor.stock_out_num * slp.tax_inclusive_unit_price) as outboundAmount
+ FROM stock_out_record sor
+ left join shipping_info s on sor.record_id = s.id
+ LEFT JOIN sales_ledger sl ON s.sales_ledger_id = sl.id
+ LEFT JOIN sales_ledger_product slp ON s.sales_ledger_product_id = slp.id
+ WHERE sor.record_type='13'
+ and sor.approval_status=1
+ and slp.type = 1
+ group by sl.id
+ )T2 on T2.id = sl.id
+ left join (
+ select sl.id,
+ sum(rm.refund_amount) as returnAmount
+ from return_management rm
+ left join shipping_info si on rm.shipping_id = si.id
+ left join sales_ledger sl on si.sales_ledger_id = sl.id
+ where rm.status=1
+ group by sl.id
+ )T3 on T3.id = sl.id
+ where sl.customer_id = #{customerId}
+ </select>
</mapper>
diff --git a/src/main/resources/mapper/basic/ProductModelMapper.xml b/src/main/resources/mapper/basic/ProductModelMapper.xml
index 0a540bf..6270b1d 100644
--- a/src/main/resources/mapper/basic/ProductModelMapper.xml
+++ b/src/main/resources/mapper/basic/ProductModelMapper.xml
@@ -9,7 +9,6 @@
<result column="product_id" property="productId" />
<result column="model" property="model" />
<result column="unit" property="unit" />
- <result column="speculative_trading_name" property="speculativeTradingName" />
<result column="tenant_id" property="tenantId" />
<result column="product_name" property="productName" />
<result column="product_id" property="productId" />
diff --git a/src/main/resources/mapper/basic/SupplierManageMapper.xml b/src/main/resources/mapper/basic/SupplierManageMapper.xml
index 87688e1..5c5af54 100644
--- a/src/main/resources/mapper/basic/SupplierManageMapper.xml
+++ b/src/main/resources/mapper/basic/SupplierManageMapper.xml
@@ -68,5 +68,95 @@
</if>
</where>
</select>
+ <select id="supplierTransactions" resultType="com.ruoyi.purchase.vo.SupplierTransactionsVo">
+ select T1.supplier_id,
+ sm.supplier_name,
+ T1.contractAmounts,
+ IFNULL(T2.paymentAmount, 0) AS paymentAmount,
+ IFNULL(T3.InboundAmount, 0) - IFNULL(T4.returnAmount, 0) AS payableAmount
+ from (select supplier_id, sum(contract_amount) as contractAmounts from purchase_ledger group by supplier_id) T1
+ left join (select supplier_id, sum(payment_amount) as paymentAmount from account_purchase_payment group by supplier_id) T2 on T1.supplier_id = T2.supplier_id
+ left join (
+ SELECT
+ pl.supplier_id,
+ sum(sir.stock_in_num * slp.tax_inclusive_unit_price) AS InboundAmount
+ FROM stock_in_record sir
+ -- 10 绫诲瀷鎵嶅叧鑱旇川妫�琛�
+ LEFT JOIN quality_inspect qi ON sir.record_type = 10 AND sir.record_id = qi.id
+ -- 鍔ㄦ�佸叧鑱旈噰璐紙鑷姩閫傞厤 7 鍜� 10锛�
+ LEFT JOIN purchase_ledger pl
+ ON pl.id = IF(sir.record_type = 7, sir.record_id, qi.purchase_ledger_id)
+ -- 浜у搧鍏宠仈涓嶅姩
+ LEFT JOIN sales_ledger_product slp ON pl.id = slp.sales_ledger_id
+ -- 鏉′欢
+ WHERE sir.approval_status = 1 AND slp.type = 2
+ AND sir.record_type IN ('7','10')
+ group by pl.supplier_id
+ ) T3 on T3.supplier_id=T1.supplier_id
+ left join (
+ select
+ supplier_id,
+ sum(total_amount) as returnAmount
+ from purchase_return_orders pro
+ group by supplier_id
+ ) T4 on T4.supplier_id=T1.supplier_id
+ left join supplier_manage sm on T1.supplier_id = sm.id
+ <where>
+ <if test="supplierName!=null and supplierName!=''">
+ AND sm.supplier_name LIKE CONCAT('%',#{supplierName},'%')
+ </if>
+ </where>
+ </select>
+ <select id="supplierTransactionsDetails"
+ resultType="com.ruoyi.purchase.vo.SupplierTransactionsDetailsVo">
+ select pl.id purchaseLedgerId,
+ pl.purchase_contract_number,
+ pl.execution_date,
+ pl.contract_amount,
+ IFNULL(T1.paymentAmount, 0) AS paymentAmount,
+ IFNULL(T2.InboundAmount, 0) - IFNULL(T3.returnAmount, 0) AS payableAmount
+ from purchase_ledger pl
+ left join (
+ select
+ pl.id,
+ sum(app.payment_amount) as paymentAmount
+ from account_purchase_payment app
+ left join account_payment_application apa on app.account_payment_application_id = apa.id
+ left join stock_in_record sir on FIND_IN_SET(sir.id, apa.stock_in_record_ids) > 0
+ -- 10 绫诲瀷鎵嶅叧鑱旇川妫�琛�
+ LEFT JOIN quality_inspect qi ON sir.record_type = 10 AND sir.record_id = qi.id
+ -- 鍔ㄦ�佸叧鑱旈噰璐紙鑷姩閫傞厤 7 鍜� 10锛�
+ LEFT JOIN purchase_ledger pl
+ ON pl.id = IF(sir.record_type = 7, sir.record_id, qi.purchase_ledger_id)
+ WHERE sir.approval_status = 1
+ AND sir.record_type IN ('7','10')
+ group by pl.id
+ )T1 on T1.id = pl.id
+ left join (
+ SELECT
+ pl.id,
+ sum(sir.stock_in_num * slp.tax_inclusive_unit_price) AS InboundAmount
+ FROM stock_in_record sir
+ -- 10 绫诲瀷鎵嶅叧鑱旇川妫�琛�
+ LEFT JOIN quality_inspect qi ON sir.record_type = 10 AND sir.record_id = qi.id
+ -- 鍔ㄦ�佸叧鑱旈噰璐紙鑷姩閫傞厤 7 鍜� 10锛�
+ LEFT JOIN purchase_ledger pl
+ ON pl.id = IF(sir.record_type = 7, sir.record_id, qi.purchase_ledger_id)
+ -- 浜у搧鍏宠仈涓嶅姩
+ LEFT JOIN sales_ledger_product slp ON pl.id = slp.sales_ledger_id
+ -- 鏉′欢
+ WHERE sir.approval_status = 1 AND slp.type = 2
+ AND sir.record_type IN ('7','10')
+ group by pl.id
+ )T2 on T2.id = pl.id
+ left join (
+ select pl.id,
+ sum(pro.total_amount) as returnAmount
+ from purchase_return_orders pro
+ left join purchase_ledger pl on pro.purchase_ledger_id = pl.id
+ group by pl.id
+ )T3 on T3.id = pl.id
+ where pl.supplier_id = #{supplierId}
+ </select>
-</mapper>
\ No newline at end of file
+</mapper>
diff --git a/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsMapper.xml b/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsMapper.xml
new file mode 100644
index 0000000..fa45ea6
--- /dev/null
+++ b/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsMapper.xml
@@ -0,0 +1,46 @@
+<?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.ruoyi.collaborativeApproval.mapper.EnterpriseNewsMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.collaborativeApproval.pojo.EnterpriseNews">
+ <id column="id" property="id" />
+ <result column="title" property="title" />
+ <result column="summary" property="summary" />
+ <result column="content" property="content" />
+ <result column="category" property="category" />
+ <result column="read_scope" property="readScope" />
+ <result column="is_required" property="isRequired" />
+ <result column="status" property="status" />
+ <result column="required_read_count" property="requiredReadCount" />
+ <result column="read_count" property="readCount" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ <result column="dept_id" property="deptId" />
+ </resultMap>
+ <select id="listPage" resultType="com.ruoyi.collaborativeApproval.vo.EnterpriseNewsVo">
+ select en.*, u.nick_name as create_user_name from
+ enterprise_news en
+ left join sys_user u on en.create_user = u.user_id
+ <where>
+ <if test="enterpriseNewsDto.title != null and enterpriseNewsDto.title != ''">
+ and en.title like concat('%',#{enterpriseNewsDto.title},'%')
+ </if>
+ <if test="enterpriseNewsDto.category != null and enterpriseNewsDto.category != ''">
+ and en.category = #{enterpriseNewsDto.category}
+ </if>
+ <if test="enterpriseNewsDto.status != null ">
+ and en.status = #{enterpriseNewsDto.status}
+ </if>
+ <if test="enterpriseNewsDto.createUser != null and enterpriseNewsDto.createUser != ''">
+ and en.create_user = #{enterpriseNewsDto.createUser}
+ </if>
+ <if test="enterpriseNewsDto.createTimeStart != null and enterpriseNewsDto.createTimeEnd != null">
+ and en.create_time between #{enterpriseNewsDto.createTimeStart} and #{enterpriseNewsDto.createTimeEnd}
+ </if>
+ </where>
+ </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeDeptMapper.xml b/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeDeptMapper.xml
new file mode 100644
index 0000000..0b13f67
--- /dev/null
+++ b/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeDeptMapper.xml
@@ -0,0 +1,13 @@
+<?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.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeDeptMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept">
+ <id column="id" property="id" />
+ <result column="news_id" property="newsId" />
+ <result column="dept_id" property="deptId" />
+ <result column="create_time" property="createTime" />
+ </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeUserMapper.xml b/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeUserMapper.xml
new file mode 100644
index 0000000..7f4ac4b
--- /dev/null
+++ b/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeUserMapper.xml
@@ -0,0 +1,13 @@
+<?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.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeUserMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser">
+ <id column="id" property="id" />
+ <result column="news_id" property="newsId" />
+ <result column="user_id" property="userId" />
+ <result column="create_time" property="createTime" />
+ </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/procurementrecord/ReturnManagementMapper.xml b/src/main/resources/mapper/procurementrecord/ReturnManagementMapper.xml
index 500846b..e069196 100644
--- a/src/main/resources/mapper/procurementrecord/ReturnManagementMapper.xml
+++ b/src/main/resources/mapper/procurementrecord/ReturnManagementMapper.xml
@@ -74,6 +74,9 @@
<if test="req.customerName != null and req.customerName != ''">
and c.customer_name like concat('%',#{req.customerName},'%')
</if>
+ <if test="req.customerId != null ">
+ and rm.customer_id = #{req.customerId}
+ </if>
<if test="req.startDate != null and req.endDate != null">
AND DATE_FORMAT(rm.make_time, '%Y-%m-%d') BETWEEN #{req.startDate} AND #{req.endDate}
</if>
diff --git a/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml b/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
index f029ef7..5ecf0e9 100644
--- a/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
+++ b/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
@@ -64,6 +64,9 @@
<if test="c != null and c.status != null">
and pot.status = #{c.status}
</if>
+ <if test="c != null and c.isProduction != null">
+ and poro.is_production = #{c.isProduction}
+ </if>
<if test="c != null and c.workOrderNo != null and c.workOrderNo != ''">
and pot.work_order_no like concat('%', #{c.workOrderNo}, '%')
</if>
@@ -107,7 +110,7 @@
select poro.operation_name as processName,
sum(ifnull(ppi.input_quantity, 0)) as totalInput,
sum(ifnull(ppo.scrap_qty, 0)) as totalScrap,
- sum(ifnull(ppo.quantity, 0) - ifnull(ppo.scrap_qty, 0)) as totalOutput
+ sum(greatest(ifnull(ppo.quantity, 0) - ifnull(ppo.scrap_qty, 0), 0)) as totalOutput
from production_product_output ppo
inner join production_product_main ppm on ppo.production_product_main_id = ppm.id
inner join production_operation_task pot on ppm.production_operation_task_id = pot.id
diff --git a/src/main/resources/mapper/production/ProductionOrderMapper.xml b/src/main/resources/mapper/production/ProductionOrderMapper.xml
index 1a304ef..8e64413 100644
--- a/src/main/resources/mapper/production/ProductionOrderMapper.xml
+++ b/src/main/resources/mapper/production/ProductionOrderMapper.xml
@@ -212,4 +212,85 @@
and ifnull(complete_quantity, 0) < quantity
</select>
+ <select id="selectHomeOrderProgressPage" resultType="java.util.Map">
+ select po.nps_no as orderNo,
+ p.product_name as productName,
+ ifnull(po.quantity, 0) as plannedQuantity,
+ ifnull(po.complete_quantity, 0) as completedQuantity,
+ round(ifnull(po.complete_quantity, 0) / nullif(po.quantity, 0) * 100, 2) as completionRate,
+ po.plan_complete_time as dueDate,
+ po.status as status
+ from production_order po
+ left join product_model pm on po.product_model_id = pm.id
+ left join product p on pm.product_id = p.id
+ <where>
+ <if test="status != null">
+ and po.status = #{status}
+ </if>
+ <if test="startTime != null and endTime != null">
+ and po.create_time >= #{startTime}
+ and po.create_time < #{endTime}
+ </if>
+ </where>
+ order by po.id desc
+ limit #{offset}, #{size}
+ </select>
+
+ <select id="countHomeOrderProgress" resultType="java.lang.Long">
+ select count(1)
+ from production_order po
+ <where>
+ <if test="status != null">
+ and po.status = #{status}
+ </if>
+ <if test="startTime != null and endTime != null">
+ and po.create_time >= #{startTime}
+ and po.create_time < #{endTime}
+ </if>
+ </where>
+ </select>
+
+ <select id="countHomeOrderProgressByStatus" resultType="java.util.Map">
+ select po.status as status, count(1) as cnt
+ from production_order po
+ where po.status in (1, 2, 3, 4)
+ <if test="startTime != null and endTime != null">
+ and po.create_time >= #{startTime}
+ and po.create_time < #{endTime}
+ </if>
+ group by po.status
+ </select>
+
+ <select id="selectHomeTodayProductionPlan" resultType="java.util.Map">
+ select po.nps_no as orderNo,
+ p.product_name as productName,
+ ifnull(po.quantity, 0) as plannedQuantity,
+ po.plan_complete_time as dueDate,
+ po.status as status
+ from production_order po
+ left join product_model pm on po.product_model_id = pm.id
+ left join product p on pm.product_id = p.id
+ <where>
+ po.status in (1, 2)
+ <if test="planStart != null and planEnd != null">
+ and po.plan_complete_time >= #{planStart}
+ and po.plan_complete_time < #{planEnd}
+ </if>
+ </where>
+ order by case when po.status = 2 then 0 else 1 end, po.id desc
+ limit #{size}
+ </select>
+
+ <select id="countHomeTodayProductionPlan" resultType="java.lang.Long">
+ select count(1)
+ from production_order po
+ <where>
+ po.status in (1, 2)
+ <if test="planStart != null and planEnd != null">
+ and po.plan_complete_time >= #{planStart}
+ and po.plan_complete_time < #{planEnd}
+ </if>
+ </where>
+ </select>
+
</mapper>
diff --git a/src/main/resources/mapper/purchase/InvoicePurchaseMapper.xml b/src/main/resources/mapper/purchase/InvoicePurchaseMapper.xml
deleted file mode 100644
index c5a99f9..0000000
--- a/src/main/resources/mapper/purchase/InvoicePurchaseMapper.xml
+++ /dev/null
@@ -1,146 +0,0 @@
-<?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.ruoyi.purchase.mapper.InvoicePurchaseMapper">
-
-
- <select id="selectPurchaseReport" resultType="com.ruoyi.purchase.dto.InvoicePurchaseReportDto">
- SELECT
- sl.sales_contract_no AS customerContractNo,
- sl.customer_name,
- sl.contract_amount AS contract_amount,
- SUM( pl.contract_amount ) AS purchase_amount,
- (
- sl.contract_amount - SUM( pl.contract_amount )) AS balance,
- CONCAT( ROUND( ( sl.contract_amount - SUM( pl.contract_amount )) / sl.contract_amount * 100, 1 ), '%' ) AS balance_ratio
- FROM
- sales_ledger sl
- INNER JOIN purchase_ledger pl ON sl.sales_contract_no = pl.sales_contract_no
- <where>
- <if test="c.customerName != null and c.customerName != ''">
- AND sl.customer_name LIKE CONCAT('%', #{c.customerName}, '%')
- </if>
- </where>
- GROUP BY
- sl.sales_contract_no,
- sl.customer_name,
- sl.contract_amount
- ORDER BY
- sl.sales_contract_no
- </select>
- <select id="listVat" resultType="com.ruoyi.purchase.dto.VatDto">
- select *
- from (SELECT
- COALESCE(a1.month, a2.month) AS month,
- IFNULL(a1.tax_amount, 0) AS j_tax_amount,
- IFNULL(a2.x_tax_amount, 0) AS x_tax_amount
- FROM (
- -- 绗竴涓煡璇細鏉ヨ嚜 invoice_ledger 鐨勭◣棰�
- SELECT
- DATE_FORMAT(il.invoice_date, '%Y-%m') AS month,
- ROUND(SUM(pr.invoice_amount - pr.invoice_amount / (1 + pr.tax_rate / 100)), 2) AS tax_amount
- FROM invoice_ledger il
- LEFT JOIN invoice_registration_product pr ON pr.id = il.invoice_registration_product_id
- WHERE il.invoice_no IS NOT NULL
- AND invoice_type = '澧炰笓绁�'
- AND DATE_FORMAT(il.invoice_date, '%Y-%m') IS NOT NULL -- 鏂板锛氳繃婊onth涓篘ULL鐨勬儏
- GROUP BY DATE_FORMAT(il.invoice_date, '%Y-%m')
- ) a1
- LEFT JOIN (
- -- 绗簩涓煡璇細鏉ヨ嚜 ticket_registration 鐨勭◣棰�
- SELECT
- DATE_FORMAT(a.issue_date, '%Y-%m') AS month,
- SUM(a.invoice_amount) AS x_tax_amount
- FROM (
- SELECT DISTINCT pr.id,
- tr.issue_date,
- ROUND(pr.tickets_amount / (1 + pr.tax_rate / 100), 2) AS un_tickets_price,
- ROUND(pr.tickets_amount - pr.tickets_amount / (1 + pr.tax_rate / 100), 2) AS invoice_amount
- FROM product_record pr
- LEFT JOIN purchase_ledger pl ON pl.id = pr.purchase_ledger_id
- LEFT JOIN sales_ledger sl ON sl.id = pl.sales_ledger_id
- LEFT JOIN ticket_registration tr ON tr.purchase_ledger_id = pl.id
- LEFT JOIN product_model pm ON pm.id = pr.product_model_id
- WHERE type = 2
- AND tr.invoice_number IS NOT NULL
- ) a
- GROUP BY DATE_FORMAT(a.issue_date, '%Y-%m')
- ) a2 ON a1.month = a2.month
-
- UNION ALL
-
- SELECT
- COALESCE(a1.month, a2.month) AS month,
- IFNULL(a1.tax_amount, 0) AS tax_amount,
- IFNULL(a2.x_tax_amount, 0) AS x_tax_amount
- FROM (
- -- 绗簩涓煡璇細鏉ヨ嚜 ticket_registration 鐨勭◣棰濓紙鍙嶈繃鏉ヨˉ鍏ㄦ病鏈夊尮閰嶅埌鐨勶級
- SELECT
- DATE_FORMAT(a.issue_date, '%Y-%m') AS month,
- SUM(a.invoice_amount) AS x_tax_amount
- FROM (
- SELECT DISTINCT pr.id,
- tr.issue_date,
- ROUND(pr.tickets_amount / (1 + pr.tax_rate / 100), 2) AS un_tickets_price,
- ROUND(pr.tickets_amount - pr.tickets_amount / (1 + pr.tax_rate / 100), 2) AS invoice_amount
- FROM product_record pr
- LEFT JOIN purchase_ledger pl ON pl.id = pr.purchase_ledger_id
- LEFT JOIN sales_ledger sl ON sl.id = pl.sales_ledger_id
- LEFT JOIN ticket_registration tr ON tr.purchase_ledger_id = pl.id
- LEFT JOIN product_model pm ON pm.id = pr.product_model_id
- WHERE type = 2
- AND tr.invoice_number IS NOT NULL
- ) a
- GROUP BY DATE_FORMAT(a.issue_date, '%Y-%m')
- ) a2
- LEFT JOIN (
- -- 绗竴涓煡璇細鏉ヨ嚜 invoice_ledger 鐨勭◣棰�
- SELECT
- DATE_FORMAT(il.invoice_date, '%Y-%m') AS month,
- ROUND(SUM(pr.invoice_amount - pr.invoice_amount / (1 + pr.tax_rate / 100)), 2) AS tax_amount
- FROM invoice_ledger il
- LEFT JOIN invoice_registration_product pr ON pr.id = il.invoice_registration_product_id
- WHERE il.invoice_no IS NOT NULL
- AND invoice_type = '澧炰笓绁�'
- AND DATE_FORMAT(il.invoice_date, '%Y-%m') IS NOT NULL -- 鏂板锛氳繃婊onth涓篘ULL鐨勬儏
- GROUP BY DATE_FORMAT(il.invoice_date, '%Y-%m')
- ) a1 ON a1.month = a2.month
- WHERE a1.month IS NULL
- ORDER BY month
- )as a
- <where>
- a.month is not null
- <if test="month != null">
- and a.month = #{month}
- </if>
- </where>
-
- </select>
- <select id="listVat1" resultType="com.ruoyi.purchase.dto.VatDto">
- # SELECT
-# DATE_FORMAT(il.invoice_date, '%Y-%m') AS month,
-# ROUND(SUM(pr.invoice_amount - pr.invoice_amount / (1 + pr.tax_rate / 100)), 2) AS tax_amount
-# FROM invoice_ledger il
-# LEFT JOIN invoice_registration_product pr ON pr.id = il.invoice_registration_product_id
-# WHERE il.invoice_no IS NOT NULL
-# AND invoice_type = '澧炰笓绁�'
-# GROUP BY DATE_FORMAT(il.invoice_date, '%Y-%m')
-# ORDER BY month;
-# select DATE_FORMAT(a.issue_date, '%Y-%m'), sum(a.invoice_amount) as xTaxAmount
-# from (SELECT distinct pr.id,
-# tr.issue_date,
-# ROUND(pr.tickets_amount / (1 + pr.tax_rate / 100), 2) AS un_tickets_price,
-# ROUND(pr.tickets_amount - pr.tickets_amount / (1 + pr.tax_rate / 100),
-# 2) AS invoice_amount
-# FROM product_record pr
-# LEFT JOIN purchase_ledger pl ON pl.id = pr.purchase_ledger_id
-# LEFT JOIN sales_ledger sl ON sl.id = pl.sales_ledger_id
-# LEFT JOIN ticket_registration tr ON tr.purchase_ledger_id = pl.id
-# LEFT JOIN product_model pm ON pm.id = pr.product_model_id
-# WHERE type = 2
-# and tr.invoice_number is not null) a
-# GROUP BY DATE_FORMAT(a.issue_date, '%Y-%m')
- </select>
-
-</mapper>
diff --git a/src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml b/src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml
deleted file mode 100644
index 8e01079..0000000
--- a/src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml
+++ /dev/null
@@ -1,223 +0,0 @@
-<?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.ruoyi.purchase.mapper.PaymentRegistrationMapper">
-
- <resultMap type="PaymentRegistration" id="PaymentRegistrationResult">
- <result property="id" column="id"/>
- <result property="saleLedgerId" column="sale_ledger_id"/>
- <result property="purchaseLedgerId" column="purchase_ledger_id"/>
- <result property="supplierId" column="supplier_id"/>
- <result property="ticketRegistrationId" column="ticket_registration_id"/>
- <result property="currentPaymentAmount" column="current_payment_amount"/>
- <result property="paymentMethod" column="payment_method"/>
- <result property="registrantId" column="registrant_id"/>
- <result property="paymentDate" column="payment_date"/>
- <result property="createTime" column="create_time"/>
- <result property="updateTime" column="update_time"/>
- <result property="tenantId" column="tenant_id"/>
- <result property="registrationtDate" column="registrationt_date"/>
- </resultMap>
-
- <resultMap type="com.ruoyi.purchase.dto.PaymentRegistrationDto" id="PaymentRegistrationDtoResult">
- <result property="id" column="id"/>
- <result property="saleLedgerId" column="sale_ledger_id"/>
- <result property="purchaseLedgerId" column="purchase_ledger_id"/>
- <result property="supplierId" column="supplier_id"/>
- <result property="ticketRegistrationId" column="ticket_registration_id"/>
- <result property="currentPaymentAmount" column="current_payment_amount"/>
- <result property="paymentMethod" column="payment_method"/>
- <result property="registrantId" column="registrant_id"/>
- <result property="paymentDate" column="payment_date"/>
- <result property="createTime" column="create_time"/>
- <result property="updateTime" column="update_time"/>
- <result property="salesContractNo" column="sales_contract_no"/>
- <result property="purchaseContractNumber" column="purchase_contract_number"/>
- <result property="supplierName" column="supplier_name"/>
- <result property="invoiceNumber" column="invoice_number"/>
- <result property="taxRate" column="tax_rate"/>
- <result property="invoiceAmount" column="invoice_amount"/>
- <result property="tenantId" column="tenant_id"/>
- <result property="registrationtDate" column="registrationt_date"/>
- </resultMap>
-
- <sql id="selectPaymentRegistrationVo">
- select pr.id,
- pr.sale_ledger_id,
- pr.purchase_ledger_id,
- pr.supplier_id,
- pr.ticket_registration_id,
- pr.current_payment_amount,
- pr.payment_method,
- pr.registrant_id,
- pr.payment_date,
- pr.create_time,
- pr.update_time,
- pr.tenant_id,
- sl.sales_contract_no as sales_contract_no,
- pl.purchase_contract_number as purchase_contract_number,
- sm.supplier_name as supplier_name,
- ip.invoice_number as invoice_number,
- ip.invoice_amount as invoice_amount,
- pr.tax_rate,
- pr.registrationt_date,
- su.nick_name as registrant
- from payment_registration pr
- left join sales_ledger sl on pr.sale_ledger_id = sl.id
- left join purchase_ledger pl on pr.purchase_ledger_id = pl.id
- left join supplier_manage sm on pr.supplier_id = sm.id
- left join ticket_registration ip on pr.ticket_registration_id = ip.id
- left join sys_user su on pr.registrant_id = su.user_id
- </sql>
-
- <select id="selectPaymentRegistrationList" parameterType="com.ruoyi.purchase.dto.PaymentRegistrationDto"
- resultMap="PaymentRegistrationDtoResult">
- <include refid="selectPaymentRegistrationVo"/>
- <where>
- <if test="supplierNameOrContractNo != null and supplierNameOrContractNo != ''">
- and sm.supplier_name LIKE CONCAT('%', #{supplierNameOrContractNo}, '%') or sl.sales_contract_no LIKE
- CONCAT('%', #{supplierNameOrContractNo}, '%')
- or pl.purchase_contract_number LIKE CONCAT('%', #{supplierNameOrContractNo}, '%')
- </if>
- </where>
- </select>
-
- <select id="selectPaymentRegistrationById" parameterType="Long" resultMap="PaymentRegistrationDtoResult">
- <include refid="selectPaymentRegistrationVo"/>
- where pr.id = #{id}
- </select>
-
- <select id="paymentHistoryList" resultType="com.ruoyi.purchase.dto.PaymentRegistrationDto">
- SELECT
- T1.payment_date,
- T2.supplier_name,
- T1.current_payment_amount,
- T1.payment_method,
- T3.nick_name AS registrant,
- T1.registrationt_date
- FROM
- payment_registration T1
- LEFT JOIN
- supplier_manage T2 ON T1.supplier_id = T2.id
- LEFT JOIN
- sys_user T3 ON T3.user_id = T1.registrant_id
- <where>
- <if test="params.searchText != null and params.searchText != '' ">
- AND T2.supplier_name LIKE CONCAT('%',#{params.searchText},'%')
- </if>
- </where>
- ORDER BY T1.payment_date,T1.create_time DESC
- </select>
-
- <select id="countPaymentTotalByTicketRegId" resultType="com.ruoyi.purchase.dto.PaymentRegistrationDto">
- SELECT
- IFNULL(SUM(current_payment_amount),0) AS paymentAmountTotal,
- ticket_registration_id
- FROM
- payment_registration
- <where>
- ticket_registration_id IN
- <foreach collection="ticketRegistrationIds" separator="," open="(" close=")" item="item">
- #{item}
- </foreach>
- </where>
- GROUP BY ticket_registration_id
- </select>
-
- <select id="getPaymentRecordList" resultType="com.ruoyi.purchase.dto.PaymentHistoryRecordVo">
- SELECT * FROM(
- SELECT
- T1.issue_date AS happenTime,
- IFNULL(T1.invoice_amount,0) AS invoiceAmount,
- '1' AS type,
- 0 AS currentPaymentAmount
- FROM
- ticket_registration T1
- LEFT JOIN purchase_ledger T2 ON T1.purchase_ledger_id = T2.id
- WHERE T2.supplier_id = #{supplierId}
- UNION
- SELECT
- payment_date AS happenTime,
- 0 AS invoiceAmount,
- '0' AS type,
- current_payment_amount AS currentPaymentAmount
- FROM payment_registration
- WHERE supplier_id = #{supplierId}
- ) T1
- ORDER BY T1.happenTime ASC
-
- </select>
-
- <select id="paymentHistoryListPage" resultType="com.ruoyi.purchase.dto.PaymentRegistrationDto">
- SELECT
- T1.id,
- T1.payment_date,
- T2.supplier_name,
- T1.current_payment_amount,
- T1.payment_method,
- T3.nick_name AS registrant,
- T1.registrationt_date,
- t4.purchase_contract_number,
- t5.invoice_amount,
- t5.invoice_number
- FROM
- payment_registration T1
- LEFT JOIN purchase_ledger t4 ON t4.id = T1.purchase_ledger_id
- LEFT JOIN supplier_manage T2 ON T1.supplier_id = T2.id
- LEFT JOIN sys_user T3 ON T3.user_id = T1.registrant_id
- left join ticket_registration t5 on t5.id = T1.ticket_registration_id
- <where>
- <if test="params.searchText != null and params.searchText != '' ">
- AND T2.supplier_name LIKE CONCAT('%',#{params.searchText},'%')
- </if>
- <if test="params.paymentDateStart != null and params.paymentDateStart !='' ">
- AND T1.payment_date >= date_format(#{params.paymentDateStart},'%Y-%m-%d')
- </if>
- <if test="params.paymentDateEnd != null and params.paymentDateEnd !='' ">
- AND T1.payment_date <= date_format(#{params.paymentDateEnd},'%Y-%m-%d')
- </if>
- <if test="params.purchaseContractNumber != null and params.purchaseContractNumber !='' ">
- AND t4.purchase_contract_number LIKE CONCAT('%',#{params.purchaseContractNumber},'%')
- </if>
- </where>
- ORDER BY T1.payment_date,T1.create_time DESC
- </select>
- <select id="supplierNameListPage" resultType="com.ruoyi.purchase.dto.PaymentRegistrationDto">
- SELECT
- T1.supplier_id,
- T1.supplier_name,
- SUM(contract_amount) AS invoiceAmount,
- IFNULL( SUM(T2.current_payment_amount) , 0 ) AS paymentAmount,
- IFNULL((IFNULL(SUM(contract_amount),0) - IFNULL(SUM(T2.current_payment_amount),0)),0) AS payableAmount
- FROM purchase_ledger T1
- LEFT JOIN payment_registration T2 ON T1.id = T2.purchase_ledger_id
- <where>
- <if test="req.supplierName != null and req.supplierName != '' ">
- T1.supplier_name LIKE CONCAT ('%',#{req.supplierName},'%')
- </if>
- </where>
- GROUP BY T1.supplier_id, T1.supplier_name
- </select>
-
- <select id="supplierNameListPageDetails" resultType="com.ruoyi.purchase.dto.PaymentRegistrationDto">
- SELECT
- T1.supplier_id,
- T1.supplier_name,
- T1.purchase_contract_number,
- T2.payment_date,
- SUM(T1.contract_amount) AS invoiceAmount,
- IFNULL(SUM(T2.current_payment_amount), 0) AS paymentAmount,
- IFNULL((IFNULL(SUM(T1.contract_amount), 0) - IFNULL(SUM(T2.current_payment_amount), 0)), 0) AS payableAmount
- FROM purchase_ledger T1
- INNER JOIN payment_registration T2 ON T1.id = T2.purchase_ledger_id
- <where>
- T1.supplier_id = #{req.supplierId}
- <if test="req.supplierName != null and req.supplierName != '' ">
- AND T1.supplier_name LIKE CONCAT ('%',#{req.supplierName},'%')
- </if>
- </where>
- GROUP BY T1.supplier_id, T1.supplier_name, T1.purchase_contract_number, T2.payment_date
- </select>
-
-</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/purchase/ProductRecordMapper.xml b/src/main/resources/mapper/purchase/ProductRecordMapper.xml
deleted file mode 100644
index aa850cb..0000000
--- a/src/main/resources/mapper/purchase/ProductRecordMapper.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?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.ruoyi.purchase.mapper.ProductRecordMapper">
-
-
- <select id="productRecordPage" resultType="com.ruoyi.purchase.dto.ProductRecordDto">
- SELECT
- sl.sales_contract_no,
- sl.customer_contract_no,
- sl.customer_name,
- pm.model AS product_model,
- pl.purchase_contract_number,
- pl.supplier_name,
- pl.project_name,
- pr.*,
- tr.invoice_number,
- tr.iss_uer_id,
- tr.iss_uer,
- tr.id as ticketRegistrationId,
- ROUND(pr.tickets_amount/(1+pr.tax_rate/100),2 ) as un_tickets_price,
- ROUND(pr.tickets_amount-pr.tickets_amount/(1+pr.tax_rate/100),2 )as invoice_amount
- FROM product_record pr
- left join purchase_ledger pl on pl.id = pr.purchase_ledger_id
- left join sales_ledger sl on sl.id = pl.sales_ledger_id
- left join ticket_registration tr on tr.id = pr.ticket_registration_id
- left join product_model pm on pm.id = pr.product_model_id
- WHERE type = 2
- <if test="c.salesContractNo != null and c.salesContractNo != ''">
- and sl.sales_contract_no like concat('%',#{c.salesContractNo},'%')
- </if>
- <if test="c.supplierName != null and c.supplierName != ''">
- and pl.supplier_name like concat('%',#{c.supplierName},'%')
- </if>
- <if test="c.createdAtStart != null and c.createdAtStart != ''">
- and pr.created_at >= str_to_date(#{c.createdAtStart}, '%Y-%m-%d')
- </if>
- <if test="c.createdAtEnd != null and c.createdAtEnd != ''">
- and pr.created_at < date_add(str_to_date(#{c.createdAtEnd}, '%Y-%m-%d'), interval 1 day)
- </if>
- <if test="c.purchaseContractNumber != null and c.purchaseContractNumber != ''">
- and tr.purchase_contract_number like concat('%',#{c.purchaseContractNumber},'%')
- </if>
- </select>
- <select id="getProductRecordById" resultType="com.ruoyi.purchase.dto.ProductRecordDto">
- SELECT
- sl.sales_contract_no,
- sl.customer_contract_no,
- sl.customer_name,
- pm.model AS product_model,
- pl.purchase_contract_number,
- pl.supplier_name,
- pr.*,
- tr.invoice_number,
- ROUND(pr.tickets_amount/(1+pr.tax_rate/100),2 ) as un_tickets_price,
- ROUND(pr.tickets_amount-pr.tickets_amount/(1+pr.tax_rate/100),2 )as invoice_amount
- FROM product_record pr
- left join purchase_ledger pl on pl.id = pr.purchase_ledger_id
- left join sales_ledger sl on sl.id = pl.sales_ledger_id
- left join ticket_registration tr on tr.id = pr.ticket_registration_id
- left join product_model pm on pm.id = pr.product_model_id
- WHERE type = 2
- <if test="c.purchaseLedgerId != null and c.purchaseLedgerId != ''">
- and pr.purchase_ledger_id = #{c.purchaseLedgerId}
- </if>
- <if test="c.productModelId != null and c.productModelId != ''">
- and pm.id = #{c.productModelId}
- </if>
- </select>
-</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml b/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
index 1aed9b4..a818160 100644
--- a/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
+++ b/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
@@ -9,94 +9,126 @@
SET contract_amount = #{totalTaxInclusiveAmount}
WHERE id = #{id}
</update>
-
- <select id="selectPurchaseLedgerListPage" resultType="com.ruoyi.purchase.dto.PurchaseLedgerDto">
- SELECT
- pl.id,
- pl.purchase_contract_number,
- pl.sales_contract_no,
- pl.supplier_id,
- pl.supplier_name,
- pl.project_name,
- pl.contract_amount,
- IFNULL(tr_sum.total_invoice_amount, 0) AS receipt_payment_amount,
- pl.contract_amount - IFNULL(tr_sum.total_invoice_amount, 0) AS unReceipt_payment_amount,
- pl.entry_date,
- pl.execution_date,
- pl.recorder_id,
- pl.recorder_name,
- pl.template_name,
- pl.approve_user_ids,
- sm.is_white,
- pl.approval_status,
- pl.payment_method,
- pl.remarks
- FROM purchase_ledger pl
- LEFT JOIN (
- SELECT
- purchase_ledger_id,
- SUM(invoice_amount) AS total_invoice_amount
- FROM ticket_registration
- GROUP BY purchase_ledger_id
- ) tr_sum ON pl.id = tr_sum.purchase_ledger_id
- LEFT JOIN supplier_manage sm ON pl.supplier_id = sm.id
- <where>
- <if test="c.purchaseContractNumber != null and c.purchaseContractNumber != ''">
- AND pl.purchase_contract_number LIKE CONCAT('%', #{c.purchaseContractNumber}, '%')
- </if>
- <if test="c.approvalStatus != null and c.approvalStatus != ''">
- AND pl.approval_status = #{c.approvalStatus}
- </if>
- <if test="c.supplierName != null and c.supplierName != ''">
- AND pl.supplier_name LIKE CONCAT('%', #{c.supplierName}, '%')
- </if>
- <if test="c.salesContractNo != null and c.salesContractNo != ''">
- AND pl.sales_contract_no LIKE CONCAT('%', #{c.salesContractNo}, '%')
- </if>
- <if test="c.projectName != null and c.projectName != ''">
- AND pl.project_name LIKE CONCAT('%', #{c.projectName}, '%')
- </if>
- <if test="c.entryDateStart != null and c.entryDateStart != ''">
- AND pl.entry_date >= #{c.entryDateStart}
- </if>
- <if test="c.entryDateEnd != null and c.entryDateEnd != ''">
- AND pl.entry_date <= #{c.entryDateEnd}
- </if>
- <if test="c.supplierId != null">
- AND pl.supplier_id = #{c.supplierId}
- </if>
- <if test="c.approvalStatus != null">
- AND pl.approval_status = #{c.approvalStatus}
- </if>
- </where>
- ORDER BY pl.entry_date DESC
- </select>
-
- <select id="getPaymentRegistrationDtoById" resultType="com.ruoyi.purchase.dto.PaymentRegistrationDto">
- SELECT
- T1.id,
- T1.payment_date,
- T2.supplier_name,
- T1.current_payment_amount,
- T1.payment_method,
- T3.nick_name AS registrant,
- T1.registrationt_date
- FROM
- payment_registration T1
- LEFT JOIN
- supplier_manage T2 ON T1.supplier_id = T2.id
- LEFT JOIN
- sys_user T3 ON T3.user_id = T1.registrant_id
- WHERE
- T1.sales_ledger_product_id = #{id}
- </select>
-
-
<select id="selectPurchaseStats" resultType="com.ruoyi.home.dto.IncomeExpenseAnalysisDto">
SELECT DATE_FORMAT(entry_date, #{dateFormat}) as dateStr, IFNULL(SUM(contract_amount), 0) as amount
FROM purchase_ledger
WHERE entry_date BETWEEN #{startDate} AND #{endDate}
GROUP BY dateStr
+ </select>
+
+ <select id="selectPurchaseLedgerListPage" resultType="com.ruoyi.purchase.dto.PurchaseLedgerDto">
+ SELECT result.*
+ FROM (
+ SELECT
+ pl.id,
+ pl.purchase_contract_number,
+ pl.sales_contract_no,
+ pl.supplier_id,
+ pl.supplier_name,
+ pl.project_name,
+ pl.contract_amount,
+ pl.entry_date,
+ pl.execution_date,
+ pl.recorder_id,
+ pl.recorder_name,
+ pl.template_name,
+ pl.approve_user_ids,
+ sm.is_white,
+ pl.approval_status,
+ pl.payment_method,
+ pl.remarks,
+ CASE
+ WHEN IFNULL(ls.total_product_count, 0) = 0 THEN '寰呭叆搴�'
+ WHEN IFNULL(ls.full_product_count, 0) >= IFNULL(ls.total_product_count, 0) THEN '瀹屽叏鍏ュ簱'
+ WHEN IFNULL(ls.approved_product_count, 0) > 0 THEN '鍏ュ簱涓�'
+ ELSE '寰呭叆搴�'
+ END AS stock_in_status
+ FROM purchase_ledger pl
+ LEFT JOIN supplier_manage sm ON pl.supplier_id = sm.id
+ LEFT JOIN (
+ SELECT
+ product_status.sales_ledger_id,
+ COUNT(1) AS total_product_count,
+ SUM(CASE WHEN product_status.approved_stock_in_num > 0 THEN 1 ELSE 0 END) AS approved_product_count,
+ SUM(CASE WHEN product_status.approved_stock_in_num >= product_status.product_quantity THEN 1 ELSE 0 END) AS full_product_count
+ FROM (
+ SELECT
+ slp.id AS sales_ledger_product_id,
+ slp.sales_ledger_id,
+ IFNULL(slp.quantity, 0) AS product_quantity,
+ IFNULL(approved_qty.approved_stock_in_num, 0) AS approved_stock_in_num
+ FROM sales_ledger_product slp
+ LEFT JOIN (
+ SELECT rel.sales_ledger_product_id,
+ IFNULL(SUM(rel.stock_in_num), 0) AS approved_stock_in_num
+ FROM (
+ SELECT slp.id AS sales_ledger_product_id,
+ sir.stock_in_num
+ FROM stock_in_record sir
+ INNER JOIN sales_ledger_product slp
+ ON slp.type = 2
+ AND TRIM(sir.record_type) = '7'
+ AND sir.record_id = slp.sales_ledger_id
+ AND (
+ (sir.batch_no IS NOT NULL AND sir.batch_no LIKE CONCAT('%-', slp.id))
+ OR (sir.batch_no IS NULL AND sir.product_model_id = slp.product_model_id)
+ )
+ WHERE sir.approval_status = 1
+
+ UNION ALL
+
+ SELECT slp.id AS sales_ledger_product_id,
+ sir.stock_in_num
+ FROM stock_in_record sir
+ INNER JOIN quality_inspect qi
+ ON TRIM(sir.record_type) = '10'
+ AND sir.record_id = qi.id
+ INNER JOIN sales_ledger_product slp
+ ON slp.type = 2
+ AND slp.sales_ledger_id = qi.purchase_ledger_id
+ AND slp.product_model_id = qi.product_model_id
+ WHERE sir.approval_status = 1
+ ) rel
+ GROUP BY rel.sales_ledger_product_id
+ ) approved_qty ON approved_qty.sales_ledger_product_id = slp.id
+ WHERE slp.type = 2
+ ) product_status
+ GROUP BY product_status.sales_ledger_id
+ ) ls ON ls.sales_ledger_id = pl.id
+ <where>
+ <if test="c.purchaseContractNumber != null and c.purchaseContractNumber != ''">
+ AND pl.purchase_contract_number LIKE CONCAT('%', #{c.purchaseContractNumber}, '%')
+ </if>
+ <if test="c.approvalStatus != null and c.approvalStatus != ''">
+ AND pl.approval_status = #{c.approvalStatus}
+ </if>
+ <if test="c.supplierName != null and c.supplierName != ''">
+ AND pl.supplier_name LIKE CONCAT('%', #{c.supplierName}, '%')
+ </if>
+ <if test="c.salesContractNo != null and c.salesContractNo != ''">
+ AND pl.sales_contract_no LIKE CONCAT('%', #{c.salesContractNo}, '%')
+ </if>
+ <if test="c.projectName != null and c.projectName != ''">
+ AND pl.project_name LIKE CONCAT('%', #{c.projectName}, '%')
+ </if>
+ <if test="c.entryDateStart != null and c.entryDateStart != ''">
+ AND pl.entry_date >= #{c.entryDateStart}
+ </if>
+ <if test="c.entryDateEnd != null and c.entryDateEnd != ''">
+ AND pl.entry_date <= #{c.entryDateEnd}
+ </if>
+ <if test="c.supplierId != null">
+ AND pl.supplier_id = #{c.supplierId}
+ </if>
+ <if test="c.approvalStatus != null">
+ AND pl.approval_status = #{c.approvalStatus}
+ </if>
+ </where>
+ ) result
+ <if test="c.stockInStatus != null and c.stockInStatus != ''">
+ WHERE result.stock_in_status = #{c.stockInStatus}
+ </if>
+ ORDER BY result.entry_date DESC
</select>
<select id="selectTotalPurchaseAmount" resultType="java.math.BigDecimal">
@@ -111,4 +143,4 @@
</if>
</where>
</select>
-</mapper>
\ No newline at end of file
+</mapper>
diff --git a/src/main/resources/mapper/purchase/PurchaseReturnOrdersMapper.xml b/src/main/resources/mapper/purchase/PurchaseReturnOrdersMapper.xml
index 961d783..2f782ff 100644
--- a/src/main/resources/mapper/purchase/PurchaseReturnOrdersMapper.xml
+++ b/src/main/resources/mapper/purchase/PurchaseReturnOrdersMapper.xml
@@ -76,6 +76,9 @@
<if test="req.returnNo != null and req.returnNo != ''">
and pro.no like concat('%',#{req.returnNo},'%')
</if>
+ <if test="req.supplierId != null">
+ and pro.supplier_id = #{req.supplierId}
+ </if>
<if test="req.supplierName != null and req.supplierName != ''">
and sm.supplier_name like concat('%',#{req.supplierName},'%')
</if>
diff --git a/src/main/resources/mapper/quality/QualityInspectMapper.xml b/src/main/resources/mapper/quality/QualityInspectMapper.xml
index f252881..ed01cad 100644
--- a/src/main/resources/mapper/quality/QualityInspectMapper.xml
+++ b/src/main/resources/mapper/quality/QualityInspectMapper.xml
@@ -54,6 +54,15 @@
<if test="qualityInspect.entryDateEnd != null and qualityInspect.entryDateEnd != '' ">
AND qi.check_time <= DATE_FORMAT(#{qualityInspect.entryDateEnd},'%Y-%m-%d')
</if>
+ <if test="qualityInspect.purchaseContractNo != null and qualityInspect.purchaseContractNo != '' ">
+ AND pl.purchase_contract_number like concat('%',#{qualityInspect.purchaseContractNo},'%')
+ </if>
+ <if test="qualityInspect.workOrderNo != null and qualityInspect.workOrderNo != '' ">
+ AND pot.work_order_no like concat('%',#{qualityInspect.workOrderNo},'%')
+ </if>
+ <if test="qualityInspect.salesContractNo != null and qualityInspect.salesContractNo != '' ">
+ AND po_sales.sales_contract_no like concat('%',#{qualityInspect.salesContractNo},'%')
+ </if>
ORDER BY qi.check_time DESC
</select>
@@ -128,8 +137,7 @@
COALESCE(SUM(
CASE
WHEN qi.inspect_state = 1
- AND qi.check_result = '鍚堟牸'
- THEN qi.quantity
+ THEN qi.qualified_quantity
ELSE 0
END
), 0) AS qualifiedCount,
@@ -137,8 +145,7 @@
COALESCE(SUM(
CASE
WHEN qi.inspect_state = 1
- AND qi.check_result = '涓嶅悎鏍�'
- THEN qi.quantity
+ THEN qi.unqualified_quantity
ELSE 0
END
), 0) AS unqualifiedCount,
@@ -166,8 +173,7 @@
COALESCE(SUM(
CASE
WHEN qi.inspect_state = 1
- AND qi.check_result = '鍚堟牸'
- THEN qi.quantity
+ THEN qi.qualified_quantity
ELSE 0
END
), 0)
@@ -248,8 +254,8 @@
/* 鍚堟牸 */
COALESCE(SUM(
CASE
- WHEN qi.inspect_state = 1 AND qi.check_result = '鍚堟牸'
- THEN qi.quantity
+ WHEN qi.inspect_state = 1
+ THEN qi.qualified_quantity
ELSE 0
END
), 0) AS qualifiedCount,
@@ -257,8 +263,8 @@
/* 涓嶅悎鏍� */
COALESCE(SUM(
CASE
- WHEN qi.inspect_state = 1 AND qi.check_result = '涓嶅悎鏍�'
- THEN qi.quantity
+ WHEN qi.inspect_state = 1
+ THEN qi.unqualified_quantity
ELSE 0
END
), 0) AS unqualifiedCount,
@@ -279,8 +285,8 @@
ROUND(
COALESCE(SUM(
CASE
- WHEN qi.inspect_state = 1 AND qi.check_result = '鍚堟牸'
- THEN qi.quantity
+ WHEN qi.inspect_state = 1
+ THEN qi.qualified_quantity
ELSE 0
END
), 0)
@@ -312,7 +318,6 @@
<select id="getYearlyPassRateStatistics" resultType="com.ruoyi.quality.dto.QualityPassRateDto">
SELECT t.modelType,
-
COALESCE(SUM(
CASE
WHEN pp.product_name = '鍘熸潗鏂�' AND t.modelType = 0 THEN qi.quantity
@@ -320,8 +325,23 @@
WHEN pp.product_name = '鎴愬搧' AND t.modelType = 2 THEN qi.quantity
ELSE 0
END
- ), 0) AS totalCount
-
+ ), 0) AS totalCount,
+ COALESCE(SUM(
+ CASE
+ WHEN pp.product_name = '鍘熸潗鏂�' AND t.modelType = 0 THEN qi.qualified_quantity
+ WHEN pp.product_name = '鍗婃垚鍝�' AND t.modelType = 1 THEN qi.qualified_quantity
+ WHEN pp.product_name = '鎴愬搧' AND t.modelType = 2 THEN qi.qualified_quantity
+ ELSE 0
+ END
+ ), 0) AS qualifiedCount,
+ COALESCE(SUM(
+ CASE
+ WHEN pp.product_name = '鍘熸潗鏂�' AND t.modelType = 0 THEN qi.unqualified_quantity
+ WHEN pp.product_name = '鍗婃垚鍝�' AND t.modelType = 1 THEN qi.unqualified_quantity
+ WHEN pp.product_name = '鎴愬搧' AND t.modelType = 2 THEN qi.unqualified_quantity
+ ELSE 0
+ END
+ ), 0) AS unqualifiedCount
FROM (SELECT 0 AS modelType
UNION ALL
SELECT 1
@@ -334,8 +354,6 @@
ON qi.product_model_id = pm.id
AND YEAR(qi.check_time) = #{year}
AND qi.inspect_state = 1
- AND qi.check_result = '鍚堟牸'
-
GROUP BY t.modelType
ORDER BY t.modelType;
</select>
diff --git a/src/main/resources/mapper/sales/InvoiceLedgerMapper.xml b/src/main/resources/mapper/sales/InvoiceLedgerMapper.xml
deleted file mode 100644
index 5454640..0000000
--- a/src/main/resources/mapper/sales/InvoiceLedgerMapper.xml
+++ /dev/null
@@ -1,185 +0,0 @@
-<?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.ruoyi.sales.mapper.InvoiceLedgerMapper">
- <select id="invoiceLedgerPage" resultType="com.ruoyi.sales.dto.InvoiceLedgerDto">
- SELECT
- T1.id ,
- T1.sales_ledger_id ,
- T1.sales_contract_no ,
- T1.customer_id ,
- T1.invoice_no ,
- T1.invoice_amount ,
- T1.tax_rate ,
- T1.invoice_person ,
- T1.invoice_date ,
- T1.create_time ,
- T1.create_user ,
- T1.update_time ,
- T1.update_user ,
- T1.tenant_id ,
- T2.customer_name,
- T3.customer_contract_no,
- T3.salesman,
- T4.invoiceFileName
- FROM invoice_ledger T1
- LEFT JOIN customer T2 ON T1.customer_id = T2.id
- LEFT JOIN sales_ledger T3 ON T1.sales_ledger_id = T3.id
- LEFT JOIN (
- SELECT
- invoice_ledger_id,
- GROUP_CONCAT( name ORDER BY id ASC SEPARATOR ' | ') AS invoiceFileName
- FROM invoice_ledger_file GROUP BY invoice_ledger_id
- ) T4 ON T4.invoice_ledger_id = T1.id
- <where>
- <if test="invoiceLedgerDto.searchText != null and invoiceLedgerDto.searchText != ''">
- AND (
- T2.customer_name LIKE CONCAT('%',#{invoiceLedgerDto.searchText},'%')
- OR T1.sales_contract_no LIKE CONCAT('%',#{invoiceLedgerDto.searchText},'%')
- )
- </if>
- <if test="invoiceLedgerDto.invoiceDate != null">
- AND DATE_FORMAT(T1.invoice_date,'%Y-%m-%d') = DATE_FORMAT(#{invoiceLedgerDto.invoiceDate},'%Y-%m-%d')
- </if>
- </where>
- </select>
-
- <select id="invoiceLedgerList" resultType="com.ruoyi.sales.dto.InvoiceLedgerDto">
- SELECT
- T1.id ,
- T1.sales_ledger_id ,
- T1.sales_contract_no ,
- T1.customer_id ,
- T1.invoice_no ,
- T1.invoice_amount ,
- T1.tax_rate ,
- T1.invoice_person ,
- T1.invoice_date ,
- T1.create_time ,
- T1.create_user ,
- T1.update_time ,
- T1.update_user ,
- T1.tenant_id ,
- T2.customer_name,
- T3.salesman,
- T3.customer_contract_no,
- T4.invoiceFileName
- FROM invoice_ledger T1
- LEFT JOIN customer T2 ON T1.customer_id = T2.id
- LEFT JOIN sales_ledger T3 ON T1.sales_ledger_id = T3.id
- LEFT JOIN (
- SELECT
- invoice_ledger_id,
- GROUP_CONCAT( name ORDER BY id ASC SEPARATOR ' | ') AS invoiceFileName
- FROM invoice_ledger_file GROUP BY invoice_ledger_id
- ) T4 ON T4.invoice_ledger_id = T1.id
- <where>
- <if test="invoiceLedgerDto.searchText != null and invoiceLedgerDto.searchText != ''">
- AND (
- T2.customer_name LIKE CONCAT('%',#{invoiceLedgerDto.searchText},'%')
- OR T1.sales_contract_no LIKE CONCAT('%',#{invoiceLedgerDto.searchText},'%')
- )
- </if>
- <if test="invoiceLedgerDto.invoiceDate != null">
- AND DATE_FORMAT(T1.invoice_date,'%Y-%m-%d') = DATE_FORMAT(#{invoiceLedgerDto.invoiceDate},'%Y-%m-%d')
- </if>
- </where>
- </select>
-
- <select id="invoiceLedgerInfo" resultType="com.ruoyi.sales.dto.InvoiceLedgerDto">
- SELECT
- T1.id ,
- T1.sales_ledger_id ,
- T1.sales_contract_no ,
- T1.customer_id ,
- T1.invoice_no ,
- T1.invoice_amount ,
- T1.tax_rate ,
- T1.invoice_person ,
- T1.invoice_date ,
- T1.create_time ,
- T1.create_user ,
- T1.update_time ,
- T1.update_user ,
- T1.tenant_id ,
- T2.customer_name
- FROM invoice_ledger T1
- LEFT JOIN customer T2 ON T1.customer_id = T2.id
- WHERE T1.id = #{id}
- </select>
-
- <select id="invoiceLedgerSalesAccount" resultType="com.ruoyi.sales.dto.InvoiceLedgerDto">
- SELECT
- T1.customer_id as id,
- T1.customer_name,
- SUM(contract_amount) AS invoice_total,
- IFNULL( SUM(T2.receipt_payment_amount) , 0 ) AS receipt_payment_amount,
- IFNULL((IFNULL(SUM(contract_amount),0) - IFNULL(SUM(T2.receipt_payment_amount),0)),0) AS unReceipt_payment_amount
- FROM sales_ledger T1
- LEFT JOIN receipt_payment T2 ON T1.id = T2.sales_ledger_id
- <where>
- <if test="invoiceLedgerDto.searchText != null and invoiceLedgerDto.searchText != '' ">
- T1.customer_name LIKE CONCAT ('%',#{invoiceLedgerDto.searchText},'%')
- </if>
- </where>
- GROUP BY T1.customer_name,t1.customer_id
- </select>
-
- <select id="invoiceLedgerProductInfo" resultType="com.ruoyi.sales.dto.InvoiceRegistrationProductDto">
- SELECT
- T1.id ,
- T1.sales_ledger_id ,
- T1.sales_ledger_product_id ,
- T1.invoice_registration_id ,
- T1.product_category ,
- T1.specification_model ,
- T1.unit ,
- T1.quantity ,
- T1.tax_rate ,
- T1.tax_inclusive_unit_price ,
- T1.tax_inclusive_total_price ,
- T1.tax_exclusive_total_price ,
- T1.invoice_type ,
- T1.invoice_num ,
- T1.invoice_amount ,
- T1.no_invoice_num ,
- T1.no_invoice_amount ,
- T1.create_time ,
- T1.create_user ,
- T1.update_time ,
- T1.update_user ,
- T1.tenant_id,
- T2.sales_contract_no,
- T2.customer_contract_no,
- T2.customer_name,
- T3.invoice_no,
- T3.invoice_total,
- T3.invoice_person,
- T3.invoice_date,
- T3.id AS invoice_ledger_id
- FROM invoice_registration_product T1
- LEFT JOIN sales_ledger T2 ON T1.sales_ledger_id = T2.id
- LEFT JOIN invoice_ledger T3 ON T1.id = T3.invoice_registration_product_id
- WHERE T1.id = #{id}
- </select>
-
- <select id="invoicedTotal" resultType="com.ruoyi.sales.dto.InvoiceLedgerDto">
- SELECT
- IFNULL(SUM(T1.invoice_total),0) AS invoice_total,
- T2.sales_ledger_id
- FROM
- invoice_ledger T1
- LEFT JOIN invoice_registration_product T2 ON T1.invoice_registration_product_id = T2.id
- <where>
- AND T2.sales_ledger_id IN
- <foreach collection="salesLedgerIds" item="item" open="(" close=")" separator=",">
- #{item}
- </foreach>
- </where>
- GROUP BY
- T2.sales_ledger_id
- </select>
-
-
-</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/sales/InvoiceRegistrationMapper.xml b/src/main/resources/mapper/sales/InvoiceRegistrationMapper.xml
deleted file mode 100644
index 9edbea4..0000000
--- a/src/main/resources/mapper/sales/InvoiceRegistrationMapper.xml
+++ /dev/null
@@ -1,72 +0,0 @@
-<?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.ruoyi.sales.mapper.InvoiceRegistrationMapper">
- <select id="invoiceRegistrationListPage" resultType="com.ruoyi.sales.dto.InvoiceRegistrationDto">
- SELECT
- T1.id ,
- T1.sales_ledger_id ,
- T1.sales_contract_no ,
- T1.customer_id ,
- T1.salesman ,
- T1.project_name ,
- T1.create_time ,
- T1.create_user ,
- T1.update_time ,
- T1.update_user ,
- T1.tenant_id,
- T2.customer_contract_no,
- T3.customer_name,
- T2.contract_amount,
- CASE WHEN T4.noInvoiceAmountTotal IS NULL THEN 0 ELSE T4.noInvoiceAmountTotal END AS noInvoiceAmountTotal
- FROM invoice_registration T1
- LEFT JOIN sales_ledger T2 ON T1.sales_ledger_id = T2.id
- LEFT JOIN customer T3 ON T1.customer_id = T3.id
- LEFT JOIN (
- SELECT
- SUM( no_invoice_amount ) AS noInvoiceAmountTotal ,
- invoice_registration_id
- FROM
- invoice_registration_product
- GROUP BY
- invoice_registration_id
- ) T4 ON T1.id = T4.invoice_registration_id
- </select>
-
- <select id="invoiceRegisAndProductExcelDtoList" resultType="com.ruoyi.sales.excel.InvoiceRegisAndProductExcelDto">
- SELECT
- T1.id ,
- T1.sales_ledger_id ,
- T1.sales_contract_no ,
- T1.customer_id ,
- T1.salesman ,
- T1.project_name ,
- T1.create_time ,
- T1.create_user ,
- T1.update_time ,
- T1.update_user ,
- T1.tenant_id,
- T2.customer_contract_no,
- T3.customer_name,
- T2.contract_amount,
- T4.product_category,
- T4.specification_model,
- T4.unit,
- T4.quantity,
- T4.tax_rate,
- T4.tax_inclusive_unit_price,
- T4.tax_inclusive_total_price,
- T4.tax_exclusive_total_price,
- T4.invoice_type,
- T4.invoice_num,
- T4.invoice_amount,
- T4.no_invoice_num,
- T4.no_invoice_amount
- FROM invoice_registration T1
- JOIN sales_ledger T2 ON T1.sales_ledger_id = T2.id
- JOIN customer T3 ON T1.customer_id = T3.id
- JOIN invoice_registration_product T4 ON T1.id = T4.invoice_registration_id
- ORDER BY T1.id ASC
- </select>
-</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/sales/InvoiceRegistrationProductMapper.xml b/src/main/resources/mapper/sales/InvoiceRegistrationProductMapper.xml
deleted file mode 100644
index ba790b1..0000000
--- a/src/main/resources/mapper/sales/InvoiceRegistrationProductMapper.xml
+++ /dev/null
@@ -1,132 +0,0 @@
-<?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.ruoyi.sales.mapper.InvoiceRegistrationProductMapper">
-
- <select id="invoiceRegistrationProductList" resultType="com.ruoyi.sales.dto.InvoiceRegistrationProductDto">
- SELECT
- T1.id ,
- T1.sales_ledger_id ,
- T1.sales_ledger_product_id ,
- T1.invoice_registration_id ,
- T1.product_category ,
- T1.specification_model ,
- T1.unit ,
- T1.quantity ,
- T1.tax_rate ,
- T1.tax_inclusive_unit_price ,
- T1.tax_inclusive_total_price ,
- T1.tax_exclusive_total_price ,
- T1.invoice_type ,
- T1.invoice_num ,
- T1.invoice_amount ,
- T1.no_invoice_num ,
- T1.no_invoice_amount ,
- T1.create_time ,
- T1.create_user ,
- T1.update_time ,
- T1.update_user ,
- T1.tenant_id,
- T2.sales_contract_no,
- T2.customer_contract_no,
- T2.customer_name,
- T3.invoice_no,
- T3.invoice_total,
- T3.invoice_person,
- T3.invoice_date,
- T4.invoiceFileName
- FROM invoice_registration_product T1
- LEFT JOIN sales_ledger T2 ON T1.sales_ledger_id = T2.id
- LEFT JOIN invoice_ledger T3 ON T1.id = T3.invoice_registration_product_id
- LEFT JOIN (
- SELECT
- invoice_ledger_id,
- GROUP_CONCAT( name ORDER BY id ASC SEPARATOR ' | ') AS invoiceFileName
- FROM invoice_ledger_file GROUP BY invoice_ledger_id
- ) T4 ON T4.invoice_ledger_id = T3.id
- <where>
- <if test="invoiceRegistrationProductDto.searchText != null and invoiceRegistrationProductDto.searchText != '' ">
- AND (T2.sales_contract_no LIKE CONCAT('%',#{invoiceRegistrationProductDto.searchText},'%')
- OR
- T2.customer_name LIKE CONCAT('%',#{invoiceRegistrationProductDto.searchText},'%')
- )
- </if>
- <if test="invoiceRegistrationProductDto.invoiceDate != null">
- AND T3.invoice_date = #{invoiceRegistrationProductDto.invoiceDate}
- </if>
- </where>
- ORDER BY T1.create_time DESC, T1.id DESC
- </select>
-
- <select id="invoiceRegistrationProductPage" resultType="com.ruoyi.sales.dto.InvoiceRegistrationProductDto">
- SELECT
- T1.id ,
- T1.sales_ledger_id ,
- T1.sales_ledger_product_id ,
- T1.invoice_registration_id ,
- T1.product_category ,
- T1.specification_model ,
- T1.unit ,
- T1.quantity ,
- T1.tax_rate ,
- T1.tax_inclusive_unit_price ,
- T1.tax_inclusive_total_price ,
- T1.tax_exclusive_total_price ,
- T1.invoice_type ,
- T1.invoice_num ,
- T1.invoice_amount ,
- T1.no_invoice_num ,
- T1.no_invoice_amount ,
- T1.create_time ,
- T1.create_user ,
- T1.update_time ,
- T1.update_user ,
- T1.tenant_id,
- T2.sales_contract_no,
- T2.customer_contract_no,
- T2.customer_name,
- T3.invoice_no,
- T3.id as invoice_ledger_id,
- IFNULL(T3.invoice_total,0) AS invoice_total,
- T3.invoice_person,
- T3.invoice_date,
- T4.invoiceFileName,
- T2.project_name,
- u.nick_name as invoicePerson
- FROM invoice_registration_product T1
- LEFT JOIN sales_ledger T2 ON T1.sales_ledger_id = T2.id
- LEFT JOIN sys_user u ON u.user_id = T1.create_user
- RIGHT JOIN invoice_ledger T3 ON T1.id = T3.invoice_registration_product_id
- LEFT JOIN (
- SELECT
- invoice_ledger_id,
- GROUP_CONCAT( name ORDER BY id ASC SEPARATOR ' | ') AS invoiceFileName
- FROM invoice_ledger_file GROUP BY invoice_ledger_id
- ) T4 ON T4.invoice_ledger_id = T3.id
- <where>
- <if test="invoiceRegistrationProductDto.searchText != null and invoiceRegistrationProductDto.searchText != '' ">
- AND (T2.sales_contract_no LIKE CONCAT('%',#{invoiceRegistrationProductDto.searchText},'%')
- OR
- T2.customer_name LIKE CONCAT('%',#{invoiceRegistrationProductDto.searchText},'%')
- )
- </if>
- <if test="invoiceRegistrationProductDto.invoiceDateStart != null and invoiceRegistrationProductDto.invoiceDateStart != ''">
- AND T3.invoice_date >= str_to_date(#{invoiceRegistrationProductDto.invoiceDateStart}, '%Y-%m-%d')
- </if>
- <if test="invoiceRegistrationProductDto.invoiceDateEnd != null and invoiceRegistrationProductDto.invoiceDateEnd != ''">
- AND T3.invoice_date < date_add(str_to_date(#{invoiceRegistrationProductDto.invoiceDateEnd},
- '%Y-%m-%d'), interval 1 day)
- </if>
- <if test="invoiceRegistrationProductDto.createTimeStart != null ">
- AND T1.create_time >= date_format(#{invoiceRegistrationProductDto.createTimeStart}, '%Y-%m-%d
- %H:%i:%s')
- </if>
- <if test="invoiceRegistrationProductDto.createTimeEnd != null ">
- AND T1.create_time <= date_format(#{invoiceRegistrationProductDto.createTimeStart}, '%Y-%m-%d
- %H:%i:%s')+interval 1 day
- </if>
- </where>
- ORDER BY T1.create_time DESC, T1.id DESC
- </select>
-</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/sales/ReceiptPaymentMapper.xml b/src/main/resources/mapper/sales/ReceiptPaymentMapper.xml
deleted file mode 100644
index 975d120..0000000
--- a/src/main/resources/mapper/sales/ReceiptPaymentMapper.xml
+++ /dev/null
@@ -1,454 +0,0 @@
-<?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.ruoyi.sales.mapper.ReceiptPaymentMapper">
- <select id="receiptPaymentListPage" resultType="com.ruoyi.sales.dto.ReceiptPaymentDto">
- SELECT
- T4.customer_id,
- IFNULL(T5.invoice_total,0) AS invoice_total,
- T1.receipt_payment_amount,
- T1.receipt_payment_date
- FROM
- receipt_payment T1
- LEFT JOIN invoice_ledger T2 ON T1.invoice_ledger_id = T2.id
- LEFT JOIN invoice_registration_product T3 ON T2.invoice_registration_product_id = T3.id
- LEFT JOIN sales_ledger T4 ON T4.id = T3.sales_ledger_id
- LEFT JOIN (
- SELECT
- T3.customer_id,
- SUM( invoice_total ) AS invoice_total
- FROM
- invoice_ledger T1
- LEFT JOIN invoice_registration_product T2 ON T1.invoice_registration_product_id = T2.id
- LEFT JOIN sales_ledger T3 ON T3.id = T2.sales_ledger_id
- GROUP BY T3.customer_id
- ) T5 ON T5.customer_id = T4.customer_id
- <where>
- <if test="receiptPaymentDto.customerId != null">
- AND T4.customer_id = #{receiptPaymentDto.customerId}
- </if>
- </where>
- ORDER BY T1.create_time ASC
- </select>
-
- <select id="receiptPaymentInfo" resultType="com.ruoyi.sales.dto.ReceiptPaymentDto">
- SELECT
- T1.id ,
- T1.sales_ledger_id ,
- T1.sales_contract_no ,
- T1.customer_id ,
- T1.invoice_no ,
- T1.invoice_amount ,
- T1.tax_rate ,
- T1.receipt_payment_type ,
- T1.receipt_payment_amount ,
- T1.registrant ,
- T1.receipt_payment_date ,
- T1.create_time ,
- T1.create_user ,
- T1.update_time ,
- T1.update_user ,
- T1.tenant_id,
- T1.invoice_ledger_id,
- T3.customer_contract_no,
- T2.customer_name
- FROM receipt_payment T1
- LEFT JOIN customer T2 ON T1.customer_id = T2.id
- LEFT JOIN sales_ledger T3 ON T1.sales_ledger_id = T3.id
- WHERE T1.id = #{id}
- </select>
-
- <select id="bindInvoiceNoRegPage" resultType="com.ruoyi.sales.dto.ReceiptPaymentDto">
- SELECT
- T1.id,
- T1.invoice_no,
- T1.invoice_total,
- T3.project_name,
- T1.invoice_person,
- T1.invoice_date,
- T1.create_time,
- T1.create_user,
- T1.update_time,
- T1.update_user,
- T1.tenant_id,
- T2.tax_rate,
- T3.sales_contract_no,
- T3.customer_contract_no,
- T3.customer_name,
- T4.invoiceFileName,
- T5.product_category,
- IFNULL(T6.receipt_payment_amount_total, 0) AS receipt_payment_amount_total,
- (T1.invoice_total - IFNULL(T6.receipt_payment_amount_total, 0)) AS noReceiptAmount
- FROM invoice_ledger T1
- LEFT JOIN invoice_registration_product T2 ON T2.id = T1.invoice_registration_product_id
- LEFT JOIN sales_ledger T3 ON T3.id = T2.sales_ledger_id
- LEFT JOIN (
- SELECT
- invoice_ledger_id,
- GROUP_CONCAT(name ORDER BY id ASC SEPARATOR ' | ') AS invoiceFileName
- FROM invoice_ledger_file
- GROUP BY invoice_ledger_id
- ) T4 ON T4.invoice_ledger_id = T1.id
- LEFT JOIN sales_ledger_product T5 ON T2.sales_ledger_product_id = T5.id and slp.type = 1
- LEFT JOIN (
- SELECT
- SUM(receipt_payment_amount) AS receipt_payment_amount_total,
- invoice_ledger_id
- FROM receipt_payment
- GROUP BY invoice_ledger_id
- ) T6 ON T1.id = T6.invoice_ledger_id
- <where>
- <if test="req.customerName != null and req.customerName !=''">
- AND T3.customer_name LIKE CONCAT('%',#{req.customerName},'%')
- </if>
- <if test="req.invoiceLedgerId != null">
- AND T1.id = #{req.invoiceLedgerId}
- </if>
- <if test="req.customerContractNo != null and req.customerContractNo !=''">
- AND T3.customer_contract_no LIKE CONCAT('%',#{req.customerContractNo},'%')
- </if>
- <if test="req.projectName != null and req.projectName !=''">
- AND T3.project_name LIKE CONCAT('%',#{req.projectName},'%')
- </if>
- <if test="req.invoiceDateStart != null and req.invoiceDateStart != '' ">
- AND T1.invoice_date >= DATE_FORMAT(#{req.invoiceDateStart},'%Y-%m-%d')
- </if>
- <if test="req.invoiceDateEnd != null and req.invoiceDateEnd != '' ">
- AND T1.invoice_date <= DATE_FORMAT(#{req.invoiceDateEnd},'%Y-%m-%d')
- </if>
- <if test="req.status != null and req.status">
- and (T1.invoice_total - IFNULL(T6.receipt_payment_amount_total, 0)) > 0
- </if>
- </where>
-
- ORDER BY IFNULL(T2.create_time, T1.create_time) DESC
-
- </select>
-
- <select id="invoiceInfo" resultType="com.ruoyi.sales.dto.InvoiceLedgerDto">
- SELECT
- T1.id,
- T1.invoice_no,
- T1.invoice_total ,
- T2.tax_rate,
- T3.customer_name,
- T3.sales_contract_no
- FROM
- invoice_ledger T1
- LEFT JOIN
- invoice_registration_product T2 ON T1.invoice_registration_product_id = T2.id
- LEFT JOIN sales_ledger T3 ON T3.id = T2.sales_ledger_id
- WHERE T1.id = #{id}
- </select>
-
- <select id="getReceiptAmount" resultType="java.math.BigDecimal">
- SELECT
- SUM( receipt_payment_amount ) AS total_amount
- FROM
- (
- SELECT
- T1.receipt_payment_amount
- FROM
- receipt_payment T1
- LEFT JOIN invoice_ledger T2 ON T1.invoice_ledger_id = T2.id
- LEFT JOIN invoice_registration_product T3 ON T2.invoice_registration_product_id = T3.id
- LEFT JOIN sales_ledger T4 ON T4.id = T3.sales_ledger_id
- LEFT JOIN (
- SELECT
- T3.customer_id,
- SUM( invoice_total ) AS invoice_total
- FROM
- invoice_ledger T1
- LEFT JOIN invoice_registration_product T2 ON T1.invoice_registration_product_id = T2.id
- LEFT JOIN sales_ledger T3 ON T3.id = T2.sales_ledger_id
- GROUP BY
- T3.customer_id
- ) T5 ON T5.customer_id = T4.customer_id
- WHERE
- T4.customer_id = #{customerId}
-
- ORDER BY
- T1.create_time ASC
- LIMIT #{total} ) AS limited_rows
- </select>
-
- <select id="receiptPaymentHistoryList" resultType="com.ruoyi.sales.dto.ReceiptPaymentDto">
- SELECT
- T1.receipt_payment_date,
- T5.customer_name,
- T1.receipt_payment_amount,
- T1.receipt_payment_type,
- T1.registrant,
- T1.create_time
- FROM
- receipt_payment T1
- LEFT JOIN
- invoice_ledger T2 ON T1.invoice_ledger_id = T2.id
- LEFT JOIN invoice_registration_product T3 ON T2.invoice_registration_product_id = T3.id
- LEFT JOIN sales_ledger T4 ON T3.sales_ledger_id = T4.id
- LEFT JOIN customer T5 ON T5.id = T4.customer_id
- <where>
- <if test="params.searchText != null and params.searchText != '' ">
- T5.customer_name LIKE CONCAT('%',#{params.searchText},'%')
- </if>
- </where>
- ORDER BY T1.receipt_payment_date DESC
- </select>
-
- <select id="receiptPaymentHistoryListPage" resultType="com.ruoyi.sales.dto.ReceiptPaymentDto">
- SELECT
- T1.id,
- T1.receipt_payment_date,
- T5.customer_name,
- T1.receipt_payment_amount,
- T1.receipt_payment_type,
- T1.registrant,
- T1.create_time,
- T4.project_name,
- T4.sales_contract_no,
- T4.customer_contract_no
- FROM
- receipt_payment T1
- LEFT JOIN sales_ledger T4 ON T1.sales_ledger_id = T4.id
- LEFT JOIN customer T5 ON T5.id = T4.customer_id
- <where>
- <if test="params.searchText != null and params.searchText != '' ">
- T5.customer_name LIKE CONCAT('%',#{params.searchText},'%')
- </if>
- <if test="params.receiptPaymentDateStart != null and params.receiptPaymentDateStart != '' ">
- AND T1.receipt_payment_date >= date_format(#{params.receiptPaymentDateStart},'%Y-%m-%d')
- </if>
- <if test="params.receiptPaymentDateEnd != null and params.receiptPaymentDateEnd != '' ">
- AND T1.receipt_payment_date <= date_format(#{params.receiptPaymentDateEnd}, '%Y-%m-%d')
- </if>
- <if test="params.projectName != null and params.projectName != '' ">
- AND T4.project_name LIKE CONCAT('%',#{params.projectName},'%')
- </if>
- <if test="params.customerContractNo != null and params.customerContractNo != '' ">
- AND T4.customer_contract_no LIKE CONCAT('%',#{params.customerContractNo},'%')
- </if>
- <if test="params.salesContractNo != null and params.salesContractNo != '' ">
- AND T4.sales_contract_no LIKE CONCAT('%',#{params.salesContractNo},'%')
- </if>
- </where>
- ORDER BY T1.receipt_payment_date DESC
- </select>
-
-
-
-
-<!-- SELECT-->
-<!-- *-->
-<!-- FROM-->
-<!-- (-->
-<!-- SELECT-->
-<!-- receipt_payment_amount AS receiptAmount,-->
-<!-- receipt_payment_date AS happenTime,-->
-<!-- 0 AS type,-->
-<!-- 0 AS invoiceAmount-->
-<!-- FROM-->
-<!-- receipt_payment-->
-<!-- WHERE-->
-<!-- invoice_ledger_id IN (-->
-<!-- SELECT-->
-<!-- id-->
-<!-- FROM-->
-<!-- invoice_ledger-->
-<!-- WHERE-->
-<!-- invoice_registration_product_id IN (-->
-<!-- SELECT-->
-<!-- id-->
-<!-- FROM-->
-<!-- invoice_registration_product-->
-<!-- WHERE-->
-<!-- sales_ledger_id IN ( SELECT id FROM sales_ledger WHERE customer_id = #{customerId} ))) UNION-->
-<!-- SELECT-->
-<!-- 0 AS receiptAmount,-->
-<!-- invoice_date AS happenTime,-->
-<!-- 1 AS type,-->
-<!-- invoice_total AS invoiceAmount-->
-<!-- FROM-->
-<!-- invoice_ledger-->
-<!-- WHERE-->
-<!-- invoice_registration_product_id IN (-->
-<!-- SELECT-->
-<!-- id-->
-<!-- FROM-->
-<!-- invoice_registration_product-->
-<!-- WHERE-->
-<!-- sales_ledger_id IN ( SELECT id FROM sales_ledger WHERE customer_id = #{customerId} ))-->
-<!-- AND invoice_date IS NOT NULL-->
-<!-- ) T1-->
-<!-- ORDER BY-->
-<!-- T1.happenTime ASC-->
-
-
- <select id="customerInteractions" resultType="com.ruoyi.sales.dto.CustomerInteractionDto">
- SELECT
- rp.receipt_payment_amount AS receiptAmount,
- rp.receipt_payment_date AS happenTime,
- 0 AS type,
- 0 AS invoiceAmount
- FROM
- receipt_payment rp
- WHERE EXISTS (
- SELECT 1
- FROM invoice_ledger il
- JOIN invoice_registration_product irp ON il.invoice_registration_product_id = irp.id
- JOIN sales_ledger sl ON irp.sales_ledger_id = sl.id
- WHERE sl.customer_id = #{customerId}
- AND rp.invoice_ledger_id = il.id
- )
-
- UNION ALL
-
- SELECT
- 0 AS receiptAmount,
- il.invoice_date AS happenTime,
- 1 AS type,
- il.invoice_total AS invoiceAmount
- FROM
- invoice_ledger il
- JOIN invoice_registration_product irp ON il.invoice_registration_product_id = irp.id
- JOIN sales_ledger sl ON irp.sales_ledger_id = sl.id
- WHERE
- sl.customer_id = #{customerId}
- AND il.invoice_date IS NOT NULL
-
- ORDER BY happenTime ASC;
- </select>
-
- <select id="receiptPaymentHistoryListNoPage" resultType="com.ruoyi.sales.dto.ReceiptPaymentDto">
- SELECT
- T1.id,
- T1.receipt_payment_date,
- T5.customer_name,
- T1.receipt_payment_amount,
- T1.receipt_payment_type,
- T1.registrant,
- T1.create_time
- FROM
- receipt_payment T1
- LEFT JOIN
- invoice_ledger T2 ON T1.invoice_ledger_id = T2.id
- LEFT JOIN invoice_registration_product T3 ON T2.invoice_registration_product_id = T3.id
- LEFT JOIN sales_ledger T4 ON T3.sales_ledger_id = T4.id
- LEFT JOIN customer T5 ON T5.id = T4.customer_id
- WHERE T1.invoice_ledger_id = #{params.invoiceLedgerId}
- ORDER BY T1.receipt_payment_date DESC
- </select>
-
- <select id="receiptPaymentListByProdRegId" resultType="com.ruoyi.sales.pojo.ReceiptPayment">
- SELECT
- T1.*
- FROM
- receipt_payment T1
- LEFT JOIN invoice_ledger T2 ON T1.invoice_ledger_id = T2.id
- WHERE
- T2.invoice_registration_product_id = #{invoiceRegistrationProductId}
- </select>
- <select id="bindInvoiceNoRegListAll" resultType="com.ruoyi.sales.dto.ReceiptPaymentDto">
- SELECT
- T1.id ,
- T1.invoice_no ,
- T1.invoice_total ,
- T3.project_name,
- T1.invoice_person ,
- T1.invoice_date ,
- T1.create_time ,
- T1.create_user ,
- T1.update_time ,
- T1.update_user ,
- T1.tenant_id ,
- T2.tax_rate,
- T3.sales_contract_no,
- T3.customer_contract_no,
- T3.customer_name,
- T4.invoiceFileName,
- T5.product_category,
- IFNULL(T6.receipt_payment_amount_total ,0) AS receipt_payment_amount_total,
- (T1.invoice_total - IFNULL(T6.receipt_payment_amount_total ,0)) AS no_receipt_amount
- FROM invoice_ledger T1
- LEFT JOIN invoice_registration_product T2 ON T2.id = T1.invoice_registration_product_id
- LEFT JOIN sales_ledger T3 ON T3.id = T2.sales_ledger_id
- LEFT JOIN (
- SELECT
- invoice_ledger_id,
- GROUP_CONCAT( name ORDER BY id ASC SEPARATOR ' | ') AS invoiceFileName
- FROM invoice_ledger_file GROUP BY invoice_ledger_id
- ) T4 ON T4.invoice_ledger_id = T1.id
- LEFT JOIN sales_ledger_product T5 ON T2.sales_ledger_product_id = T5.id and slp.type = 1
- LEFT JOIN (
- SELECT SUM(receipt_payment_amount) AS receipt_payment_amount_total,invoice_ledger_id FROM receipt_payment GROUP
- BY invoice_ledger_id
- ) T6 ON T1.id = T6.invoice_ledger_id
- </select>
- <select id="bindInvoiceNoRegListByIds" resultType="com.ruoyi.sales.dto.ReceiptPaymentExeclDto">
- SELECT
- T1.id ,
- T1.invoice_no ,
- T1.invoice_total ,
- T3.project_name,
- T1.invoice_person ,
- T1.invoice_date ,
- T1.create_time ,
- T1.create_user ,
- T1.update_time ,
- T1.update_user ,
- T1.tenant_id ,
- T2.tax_rate,
- T3.sales_contract_no,
- T3.customer_contract_no,
- T3.customer_name,
- T4.invoiceFileName,
- T5.product_category,
- IFNULL(T6.receipt_payment_amount_total ,0) AS receipt_payment_amount_total,
- (T1.invoice_total - IFNULL(T6.receipt_payment_amount_total ,0)) AS no_receipt_amount
- FROM invoice_ledger T1
- LEFT JOIN invoice_registration_product T2 ON T2.id = T1.invoice_registration_product_id
- LEFT JOIN sales_ledger T3 ON T3.id = T2.sales_ledger_id
- LEFT JOIN (
- SELECT
- invoice_ledger_id,
- GROUP_CONCAT( name ORDER BY id ASC SEPARATOR ' | ') AS invoiceFileName
- FROM invoice_ledger_file GROUP BY invoice_ledger_id
- ) T4 ON T4.invoice_ledger_id = T1.id
- LEFT JOIN sales_ledger_product T5 ON T2.sales_ledger_product_id = T5.id and slp.type = 1
- LEFT JOIN (
- SELECT SUM(receipt_payment_amount) AS receipt_payment_amount_total,invoice_ledger_id FROM receipt_payment GROUP
- BY invoice_ledger_id
- ) T6 ON T1.id = T6.invoice_ledger_id
- <where>
- <if test="ids.size() > 0">
- T1.id IN
- <foreach item="item" collection="ids" separator="," open="(" close=")">
- #{item}
- </foreach>
- </if>
- <if test="tenantId != null " >
- AND T1.tenant_id = #{tenantId}
- </if>
- </where>
-
- </select>
-
- <select id="invoiceLedgerSalesAccount" resultType="com.ruoyi.sales.dto.InvoiceLedgerDto">
- SELECT
- T1.sales_contract_no,
- T1.contract_amount AS invoice_total,
- IFNULL(SUM(T2.receipt_payment_amount), 0) AS receipt_payment_amount,
- IFNULL((T1.contract_amount - IFNULL(SUM(T2.receipt_payment_amount), 0)), 0) AS unReceipt_payment_amount,
- T2.receipt_payment_date
- FROM sales_ledger T1
- INNER JOIN receipt_payment T2 ON T1.id = T2.sales_ledger_id
- <where>
- T1.customer_id = #{invoiceLedgerDto.customerId}
- <if test="invoiceLedgerDto.searchText != null and invoiceLedgerDto.searchText != '' ">
- AND T1.customer_name LIKE CONCAT ('%', #{invoiceLedgerDto.searchText}, '%')
- </if>
- </where>
- GROUP BY T1.id, T1.sales_contract_no, T1.contract_amount, T2.receipt_payment_date
- </select>
-
-</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/sales/SalesLedgerMapper.xml b/src/main/resources/mapper/sales/SalesLedgerMapper.xml
index e08632a..c145e0a 100644
--- a/src/main/resources/mapper/sales/SalesLedgerMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerMapper.xml
@@ -121,5 +121,21 @@
</if>
order by sl.execution_date desc
</select>
+ <select id="selectPurchaseReportVoPage" resultType="com.ruoyi.purchase.vo.PurchaseReportVo">
+ select sl.sales_contract_no customerContractNo,
+ c.customer_name,
+ sl.project_name,
+ sl.contract_amount contractAmount,
+ pl.contract_amount purchaseAmount,
+ sl.contract_amount-pl.contract_amount balance,
+ (sl.contract_amount-pl.contract_amount)/sl.contract_amount balanceRatio
+ from sales_ledger sl
+ left join purchase_ledger pl on sl.id = pl.sales_ledger_id
+ left join customer c on sl.customer_id = c.id
+ where 1=1
+ <if test="customerName != null and customerName != '' ">
+ and c.customer_name like concat('%',#{customerName},'%')
+ </if>
+ </select>
</mapper>
diff --git a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
index 7e352d8..49569de 100644
--- a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -9,7 +9,6 @@
T1.id,
T1.sales_ledger_id,
T1.warn_num,
- T1.speculative_trading_name,
T1.quantity,
T1.min_stock,
T1.tax_rate,
@@ -18,23 +17,11 @@
T1.tax_exclusive_total_price,
T1.invoice_type,
T1.type,
- T1.tickets_num,
- T1.tickets_amount,
- T1.future_tickets,
- T1.future_tickets_amount,
- T1.invoice_num,
- T1.no_invoice_num,
- T1.invoice_amount,
- T1.no_invoice_amount,
T1.product_id,
T1.product_model_id,
T1.register,
T1.register_date,
T1.approve_status,
- T1.pending_invoice_total,
- T1.invoice_total,
- T1.pending_tickets_total,
- T1.tickets_total,
T1.is_checked,
T1.is_production,
T1.create_user,
@@ -51,7 +38,13 @@
WHEN IFNULL(t3.shipped_quantity, 0) = 0 THEN '寰呭彂璐�'
WHEN (IFNULL(T1.quantity, 0) - IFNULL(t3.shipped_quantity, 0)) > 0 THEN '閮ㄥ垎鍙戣揣'
ELSE '宸插彂璐�'
- END as shippingStatus
+ END as shippingStatus,
+ CASE
+ WHEN T1.type != 2 THEN NULL
+ WHEN IFNULL(t4.approved_stock_in_num, 0) <= 0 THEN '寰呭叆搴�'
+ WHEN IFNULL(t4.approved_stock_in_num, 0) >= IFNULL(T1.quantity, 0) THEN '瀹屽叏鍏ュ簱'
+ ELSE '鍏ュ簱涓�'
+ END AS stock_in_approval_status
FROM
sales_ledger_product T1
LEFT JOIN (
@@ -66,6 +59,39 @@
where si.status != '瀹℃牳鎷掔粷'
GROUP BY sales_ledger_product_id
) t3 ON t3.sales_ledger_product_id = T1.id
+ LEFT JOIN (
+ SELECT rel.sales_ledger_product_id,
+ IFNULL(SUM(rel.stock_in_num), 0) AS approved_stock_in_num
+ FROM (
+ SELECT slp.id AS sales_ledger_product_id,
+ sir.stock_in_num
+ FROM stock_in_record sir
+ INNER JOIN sales_ledger_product slp
+ ON slp.type = 2
+ AND TRIM(sir.record_type) = '7'
+ AND sir.record_id = slp.sales_ledger_id
+ AND (
+ (sir.batch_no IS NOT NULL AND sir.batch_no LIKE CONCAT('%-', slp.id))
+ OR (sir.batch_no IS NULL AND sir.product_model_id = slp.product_model_id)
+ )
+ WHERE sir.approval_status = 1
+
+ UNION ALL
+
+ SELECT slp.id AS sales_ledger_product_id,
+ sir.stock_in_num
+ FROM stock_in_record sir
+ INNER JOIN quality_inspect qi
+ ON TRIM(sir.record_type) = '10'
+ AND sir.record_id = qi.id
+ INNER JOIN sales_ledger_product slp
+ ON slp.type = 2
+ AND slp.sales_ledger_id = qi.purchase_ledger_id
+ AND slp.product_model_id = qi.product_model_id
+ WHERE sir.approval_status = 1
+ ) rel
+ GROUP BY rel.sales_ledger_product_id
+ ) t4 ON t4.sales_ledger_product_id = T1.id
left join product_model pm ON T1.product_model_id = pm.id
left join product p ON pm.product_id = p.id
<where>
@@ -94,74 +120,6 @@
and slp.id is not null
order by slp.id desc
limit 1
-
-
- </select>
- <select id="listPage" resultType="com.ruoyi.sales.dto.SalesLedgerProductDto">
- select slp.*,
- sl.project_name,
- sl.customer_name,
- sl.sales_contract_no,
- sl.customer_contract_no
- from sales_ledger_product slp
- left join sales_ledger sl on slp.sales_ledger_id = sl.id
- <where>
- slp.type = 1
- <if test="req.salesContractNo != null and req.salesContractNo != '' ">
- AND sl.sales_contract_no like concat('%',#{req.salesContractNo},'%')
- </if>
- <if test="req.customerContractNo != null and req.customerContractNo != '' ">
- AND sl.customer_contract_no like concat('%',#{req.customerContractNo},'%')
- </if>
- <if test="req.projectName != null and req.projectName != '' ">
- AND sl.project_name like concat('%',#{req.projectName},'%')
- </if>
- <if test="req.customerName != null and req.customerName != '' ">
- AND sl.customer_name like concat('%',#{req.customerName},'%')
- </if>
- <if test="req.productCategory != null and req.productCategory != '' ">
- AND slp.product_category like concat('%',#{req.productCategory},'%')
- </if>
- <if test="req.status != null and req.status ">
- AND slp.pending_invoice_total > 0
- </if>
- </where>
- order by slp.register_date desc
- </select>
- <select id="listPagePurchaseLedger" resultType="com.ruoyi.sales.dto.SalesLedgerProductDto">
- select slp.*,
- sl.project_name,
- sl.supplier_name,
- sl.supplier_id,
- sl.sales_contract_no,
- sl.purchase_contract_number
- from sales_ledger_product slp
- left join purchase_ledger sl on slp.sales_ledger_id = sl.id
- <where>
- slp.type = 2
- <if test="req.purchaseContractNumber != null and req.purchaseContractNumber != '' ">
- AND sl.purchase_contract_number like concat('%',#{req.purchaseContractNumber},'%')
- </if>
- <if test="req.approvalStatus != null and req.approvalStatus != ''">
- and sl.approval_status = #{req.approvalStatus}
- </if>
- <if test="req.customerContractNo != null and req.customerContractNo != '' ">
- AND sl.customer_contract_no like concat('%',#{req.customerContractNo},'%')
- </if>
- <if test="req.projectName != null and req.projectName != '' ">
- AND sl.project_name like concat('%',#{req.projectName},'%')
- </if>
- <if test="req.customerName != null and req.customerName != '' ">
- AND sl.customer_name like concat('%',#{req.customerName},'%')
- </if>
- <if test="req.productCategory != null and req.productCategory != '' ">
- AND slp.product_category like concat('%',#{req.productCategory},'%')
- </if>
- <if test="req.status != null and req.status ">
- AND slp.pending_tickets_total > 0
- </if>
- </where>
- order by slp.register_date desc
</select>
<select id="procurementBusinessSummaryListPage"
resultType="com.ruoyi.purchase.dto.ProcurementBusinessSummaryDto">
diff --git a/src/main/resources/mapper/sales/SalesQuotationMapper.xml b/src/main/resources/mapper/sales/SalesQuotationMapper.xml
index 3c93850..8036e2f 100644
--- a/src/main/resources/mapper/sales/SalesQuotationMapper.xml
+++ b/src/main/resources/mapper/sales/SalesQuotationMapper.xml
@@ -4,20 +4,18 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.sales.mapper.SalesQuotationMapper">
<select id="listPage" resultType="com.ruoyi.sales.dto.SalesQuotationDto">
- SELECT t1.*,
- t2.approve_user_ids
+ SELECT t1.*
FROM sales_quotation t1
- LEFT JOIN approve_process t2 ON t1.quotation_no = t2.approve_reason and t2.approve_type = 6
- WHERE 1=1
- and t2.approve_deleted = 0
- <if test="salesQuotationDto.quotationNo != null and salesQuotationDto.quotationNo != '' ">
- AND t1.quotation_no LIKE CONCAT('%',#{salesQuotationDto.quotationNo},'%')
- </if>
- <if test="salesQuotationDto.customer != null and salesQuotationDto.customer != '' ">
- AND t1.customer = #{salesQuotationDto.customer}
- </if>
- <if test="salesQuotationDto.status != null and salesQuotationDto.status != '' ">
- AND t1.status = #{salesQuotationDto.status}
- </if>
+ <where>
+ <if test="salesQuotationDto.quotationNo != null and salesQuotationDto.quotationNo != '' ">
+ AND t1.quotation_no LIKE CONCAT('%',#{salesQuotationDto.quotationNo},'%')
+ </if>
+ <if test="salesQuotationDto.customer != null and salesQuotationDto.customer != '' ">
+ AND t1.customer = #{salesQuotationDto.customer}
+ </if>
+ <if test="salesQuotationDto.status != null and salesQuotationDto.status != '' ">
+ AND t1.status = #{salesQuotationDto.status}
+ </if>
+ </where>
</select>
</mapper>
diff --git a/src/main/resources/mapper/staff/StaffLeaveMapper.xml b/src/main/resources/mapper/staff/StaffLeaveMapper.xml
index 4637ff0..8bc9607 100644
--- a/src/main/resources/mapper/staff/StaffLeaveMapper.xml
+++ b/src/main/resources/mapper/staff/StaffLeaveMapper.xml
@@ -18,15 +18,20 @@
soj.emergency_contact as emergencyContact,
soj.emergency_contact_phone as emergencyContactPhone,
sp.post_name as postName,
- sd.dept_name as deptName
+ sd.dept_name as deptName,
+ se.education as first_study,
+ se.major as profession
FROM staff_leave
- LEFT JOIN
- staff_on_job soj ON soj.id = staff_leave.staff_on_job_id
- LEFT JOIN
- sys_post sp ON sp.post_id = soj.sys_post_id
- LEFT JOIN
- sys_dept sd ON sd.dept_id = soj.sys_dept_id
- where 1=1
+ LEFT JOIN staff_on_job soj ON soj.id = staff_leave.staff_on_job_id
+ LEFT JOIN sys_post sp ON sp.post_id = soj.sys_post_id
+ LEFT JOIN sys_dept sd ON sd.dept_id = soj.sys_dept_id
+ LEFT JOIN staff_education se ON se.staff_on_job_id = staff_leave.staff_on_job_id
+ AND se.id = (
+ SELECT MAX(se2.id)
+ FROM staff_education se2
+ WHERE se2.staff_on_job_id = staff_leave.staff_on_job_id
+ )
+ WHERE 1=1
<if test="c.staffName != null and c.staffName != '' ">
AND soj.staff_name LIKE CONCAT('%',#{c.staffName},'%')
</if>
diff --git a/src/main/resources/mapper/staff/StaffOnJobMapper.xml b/src/main/resources/mapper/staff/StaffOnJobMapper.xml
index a256ff8..2cbd1dc 100644
--- a/src/main/resources/mapper/staff/StaffOnJobMapper.xml
+++ b/src/main/resources/mapper/staff/StaffOnJobMapper.xml
@@ -3,29 +3,82 @@
<mapper namespace="com.ruoyi.staff.mapper.StaffOnJobMapper">
<select id="staffOnJobListPage" resultType="com.ruoyi.staff.dto.StaffOnJobDto">
SELECT
- staff_on_job.*,
- sp.post_name as postName,
- sd.dept_name as deptName,
- MIN(t1.contract_start_time) as contract_start_time, -- 鍙栨渶鏃╁悎鍚屽紑濮嬫椂闂�
- MAX(t1.contract_end_time) as contract_end_time
+ staff_on_job.id,
+ staff_on_job.staff_state,
+ staff_on_job.staff_no,
+ staff_on_job.staff_name,
+ staff_on_job.sex,
+ staff_on_job.native_place,
+ staff_on_job.sys_post_id,
+ staff_on_job.sys_dept_id,
+ staff_on_job.role_id,
+ staff_on_job.adress,
+ staff_on_job.first_study,
+ staff_on_job.profession,
+ staff_on_job.identity_card,
+ staff_on_job.age,
+ staff_on_job.phone,
+ staff_on_job.contract_term,
+ staff_on_job.contract_expire_time,
+ staff_on_job.trial_end_date,
+ staff_on_job.trial_start_date,
+ staff_on_job.sign_date,
+ staff_on_job.salary_select,
+ staff_on_job.pro_salary,
+ staff_on_job.date_select,
+ staff_on_job.remark,
+ staff_on_job.create_time,
+ staff_on_job.create_user,
+ staff_on_job.update_time,
+ staff_on_job.update_user,
+ staff_on_job.tenant_id,
+ staff_on_job.alias,
+ staff_on_job.birth_date,
+ staff_on_job.nation,
+ staff_on_job.marital_status,
+ staff_on_job.pro_term,
+ staff_on_job.positive_date,
+ staff_on_job.basic_salary,
+ staff_on_job.dept_id,
+ sp.post_name AS post_name,
+ sd.dept_name AS dept_name,
+ MIN(t1.contract_start_time) AS contract_start_time,
+ MAX(t1.contract_end_time) AS contract_end_time,
+ (
+ SELECT GROUP_CONCAT(sec.contact_name SEPARATOR ',')
+ FROM staff_emergency_contact sec
+ WHERE sec.staff_on_job_id = staff_on_job.id
+ ) AS emergency_contact,
+ (
+ SELECT GROUP_CONCAT(sec.contact_phone SEPARATOR ',')
+ FROM staff_emergency_contact sec
+ WHERE sec.staff_on_job_id = staff_on_job.id
+ ) AS emergency_contact_phone
FROM staff_on_job
LEFT JOIN sys_post sp ON sp.post_id = staff_on_job.sys_post_id
LEFT JOIN sys_dept sd ON sd.dept_id = staff_on_job.sys_dept_id
- LEFT JOIN staff_contract as t1 ON t1.staff_on_job_id = staff_on_job.id
- WHERE 1=1
- <if test="staffOnJob.staffState != null">
- AND staff_state = #{staffOnJob.staffState}
- </if>
- <if test="staffOnJob.staffName != null and staffOnJob.staffName != '' ">
- AND staff_name LIKE CONCAT('%',#{staffOnJob.staffName},'%')
- </if>
- <if test="staffOnJob.entryDateStart != null and staffOnJob.entryDateStart != '' ">
- AND contract_expire_time >= DATE_FORMAT(#{staffOnJob.entryDateStart},'%Y-%m-%d')
- </if>
- <if test="staffOnJob.entryDateEnd != null and staffOnJob.entryDateEnd != '' ">
- AND contract_expire_time <= DATE_FORMAT(#{staffOnJob.entryDateEnd},'%Y-%m-%d')
- </if>
+ LEFT JOIN staff_contract AS t1 ON t1.staff_on_job_id = staff_on_job.id
+ <where>
+ <if test="staffOnJob.staffState != null">
+ AND staff_on_job.staff_state = #{staffOnJob.staffState}
+ </if>
+ <if test="staffOnJob.staffName != null and staffOnJob.staffName != '' ">
+ AND staff_on_job.staff_name LIKE CONCAT('%',#{staffOnJob.staffName},'%')
+ </if>
+ <if test="staffOnJob.entryDateStart != null and staffOnJob.entryDateStart != '' ">
+ AND staff_on_job.contract_expire_time >= DATE_FORMAT(#{staffOnJob.entryDateStart},'%Y-%m-%d')
+ </if>
+ <if test="staffOnJob.entryDateEnd != null and staffOnJob.entryDateEnd != '' ">
+ AND staff_on_job.contract_expire_time <= DATE_FORMAT(#{staffOnJob.entryDateEnd},'%Y-%m-%d')
+ </if>
+ <if test="staffOnJob.sysDeptId != null">
+ AND staff_on_job.sys_dept_id = #{staffOnJob.sysDeptId}
+ </if>
+ </where>
GROUP BY staff_on_job.id
+ <if test="staffOnJob.contractStartTime != null">
+ HAVING MIN(t1.contract_start_time) = #{staffOnJob.contractStartTime}
+ </if>
</select>
<select id="staffOnJobList" resultType="com.ruoyi.staff.dto.StaffOnJobDto">
SELECT
diff --git a/src/main/resources/mapper/stock/StockInRecordMapper.xml b/src/main/resources/mapper/stock/StockInRecordMapper.xml
index 55e57a3..a3bf3f9 100644
--- a/src/main/resources/mapper/stock/StockInRecordMapper.xml
+++ b/src/main/resources/mapper/stock/StockInRecordMapper.xml
@@ -19,11 +19,96 @@
p.product_name as product_name,
pm.model,
pm.unit,
- u.nick_name as createBy
+ u.nick_name as createBy,
+ CASE
+ WHEN #{params.topParentProductId} = 278 AND TRIM(sir.record_type) = '7' THEN
+ COALESCE(pl_by_product.purchase_contract_number, pl_direct.purchase_contract_number)
+ WHEN #{params.topParentProductId} = 278 AND TRIM(sir.record_type) = '10' THEN
+ pl_by_quality.purchase_contract_number
+ WHEN #{params.topParentProductId} = 276 THEN
+ CASE
+ WHEN TRIM(sir.record_type) IN ('14', '15') THEN
+ sl_return.sales_contract_no
+ WHEN TRIM(sir.record_type) IN ('2', '5') THEN
+ COALESCE(po_sales_main.sales_contract_no, po_main.nps_no)
+ WHEN TRIM(sir.record_type) = '6' THEN
+ COALESCE(po_sales_qi.sales_contract_no, po_qi.nps_no)
+ WHEN TRIM(sir.record_type) IN ('4', '11') THEN
+ COALESCE(po_sales_uq.sales_contract_no, po_uq.nps_no)
+ WHEN TRIM(sir.record_type) IN ('20', '22') THEN
+ COALESCE(po_sales_pick.sales_contract_no, po_pick.nps_no)
+ ELSE NULL
+ END
+ ELSE NULL
+ END AS sourceOrderNo
FROM stock_in_record as sir
LEFT JOIN product_model as pm on sir.product_model_id = pm.id
LEFT JOIN product as p on pm.product_id = p.id
LEFT JOIN sys_user as u on sir.create_user = u.user_id
+ LEFT JOIN quality_inspect as qi_purchase on TRIM(sir.record_type) = '10' and sir.record_id = qi_purchase.id
+ LEFT JOIN sales_ledger_product as slp on TRIM(sir.record_type) = '7' and slp.id = sir.record_id and slp.type = 2
+ LEFT JOIN purchase_ledger as pl_by_product on TRIM(sir.record_type) = '7' and pl_by_product.id = slp.sales_ledger_id
+ LEFT JOIN purchase_ledger as pl_direct on TRIM(sir.record_type) = '7' and pl_direct.id = sir.record_id
+ LEFT JOIN purchase_ledger as pl_by_quality on TRIM(sir.record_type) = '10' and pl_by_quality.id = qi_purchase.purchase_ledger_id
+
+ LEFT JOIN production_product_main as ppm_main on TRIM(sir.record_type) IN ('2', '5') and sir.record_id = ppm_main.id
+ LEFT JOIN production_operation_task as pot_main on ppm_main.production_operation_task_id = pot_main.id
+ LEFT JOIN production_order as po_main on pot_main.production_order_id = po_main.id
+ LEFT JOIN (
+ select po2.id as production_order_id,
+ group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as sales_contract_no
+ from production_order po2
+ left join production_plan pp2
+ on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0
+ left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id
+ group by po2.id
+ ) as po_sales_main on po_sales_main.production_order_id = po_main.id
+
+ LEFT JOIN quality_inspect as qi_prod on TRIM(sir.record_type) = '6' and sir.record_id = qi_prod.id
+ LEFT JOIN production_product_main as ppm_qi on qi_prod.product_main_id = ppm_qi.id
+ LEFT JOIN production_operation_task as pot_qi on ppm_qi.production_operation_task_id = pot_qi.id
+ LEFT JOIN production_order as po_qi on pot_qi.production_order_id = po_qi.id
+ LEFT JOIN (
+ select po2.id as production_order_id,
+ group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as sales_contract_no
+ from production_order po2
+ left join production_plan pp2
+ on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0
+ left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id
+ group by po2.id
+ ) as po_sales_qi on po_sales_qi.production_order_id = po_qi.id
+
+ LEFT JOIN quality_unqualified as qu on TRIM(sir.record_type) IN ('4', '11') and sir.record_id = qu.id
+ LEFT JOIN quality_inspect as qi_uq on qu.inspect_id = qi_uq.id
+ LEFT JOIN production_product_main as ppm_uq on qi_uq.product_main_id = ppm_uq.id
+ LEFT JOIN production_operation_task as pot_uq on ppm_uq.production_operation_task_id = pot_uq.id
+ LEFT JOIN production_order as po_uq on pot_uq.production_order_id = po_uq.id
+ LEFT JOIN (
+ select po2.id as production_order_id,
+ group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as sales_contract_no
+ from production_order po2
+ left join production_plan pp2
+ on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0
+ left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id
+ group by po2.id
+ ) as po_sales_uq on po_sales_uq.production_order_id = po_uq.id
+
+ LEFT JOIN production_order_pick as pop on TRIM(sir.record_type) IN ('20', '22') and sir.record_id = pop.id
+ LEFT JOIN production_order as po_pick on pop.production_order_id = po_pick.id
+ LEFT JOIN (
+ select po2.id as production_order_id,
+ group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as sales_contract_no
+ from production_order po2
+ left join production_plan pp2
+ on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0
+ left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id
+ group by po2.id
+ ) as po_sales_pick on po_sales_pick.production_order_id = po_pick.id
+
+ LEFT JOIN return_sale_product as rsp on TRIM(sir.record_type) IN ('14', '15') and sir.record_id = rsp.id
+ LEFT JOIN return_management as rm on rsp.return_management_id = rm.id
+ LEFT JOIN shipping_info as si_return on rm.shipping_id = si_return.id
+ LEFT JOIN sales_ledger as sl_return on si_return.sales_ledger_id = sl_return.id
<where>
<if test="params.timeStr != null and params.timeStr != ''">
and sir.create_time like concat('%',#{params.timeStr},'%')
@@ -93,7 +178,7 @@
LEFT JOIN purchase_ledger pl
ON pl.id = IF(sir.record_type = 7, sir.record_id, qi.purchase_ledger_id)
-- 浜у搧鍏宠仈涓嶅姩
- LEFT JOIN sales_ledger_product slp ON pl.id = slp.product_id
+ LEFT JOIN sales_ledger_product slp ON pl.id = slp.sales_ledger_id
LEFT JOIN product_model pm ON sir.product_model_id = pm.id
LEFT JOIN product p ON pm.product_id = p.id
-- 鏉′欢
@@ -102,6 +187,9 @@
<if test="req.inboundBatches != null and req.inboundBatches != ''">
AND sir.inbound_batches LIKE CONCAT('%',#{req.inboundBatches},'%')
</if>
+ <if test="req.supplierId != null">
+ AND pl.supplier_id = #{req.supplierId}
+ </if>
<if test="req.supplierName != null and req.supplierName != ''">
AND pl.supplier_name LIKE CONCAT('%',#{req.supplierName},'%')
</if>
diff --git a/src/main/resources/mapper/stock/StockInventoryMapper.xml b/src/main/resources/mapper/stock/StockInventoryMapper.xml
index c71ce31..6ca5bf7 100644
--- a/src/main/resources/mapper/stock/StockInventoryMapper.xml
+++ b/src/main/resources/mapper/stock/StockInventoryMapper.xml
@@ -209,6 +209,12 @@
<if test="ew.topParentProductId != null and ew.topParentProductId > 0">
and combined.product_id in (select id from product_tree)
</if>
+ <if test="ew.model != null and ew.model !=''">
+ and combined.model like concat('%',#{ew.model},'%')
+ </if>
+ <if test="ew.batchNo != null and ew.batchNo !=''">
+ and combined.batch_no like concat('%',#{ew.batchNo},'%')
+ </if>
</where>
group by
product_model_id,
@@ -506,8 +512,9 @@
and (si.qualitity - ifnull(si.locked_quantity, 0)) > 0
order by si.product_model_id, si.batch_no
</select>
- <select id="getByModelId" resultType="com.ruoyi.stock.pojo.StockInventory">
- select si.id, si.batch_no, si.locked_quantity, (si.qualitity - IFNULL(sd.qualitity, 0)) as qualitity
+ <select id="getByModelId" resultType="com.ruoyi.stock.dto.StockInventoryDto">
+ select si.id, si.batch_no, si.locked_quantity, (si.qualitity - IFNULL(sd.qualitity, 0)) as qualitity,
+ p.product_name, pm.model, pm.unit
from stock_inventory si
left join (
select spd.stock_inventory_id, sum(spd.quantity) as qualitity
@@ -524,6 +531,8 @@
)
group by spd.stock_inventory_id
) as sd on sd.stock_inventory_id = si.id
+ left join product_model pm on si.product_model_id = pm.id
+ left join product p on pm.product_id = p.id
where si.product_model_id = #{productModelId}
and si.qualitity > IFNULL(sd.qualitity, 0)
</select>
diff --git a/src/main/resources/mapper/stock/StockOutRecordMapper.xml b/src/main/resources/mapper/stock/StockOutRecordMapper.xml
index 202de6b..ad5976f 100644
--- a/src/main/resources/mapper/stock/StockOutRecordMapper.xml
+++ b/src/main/resources/mapper/stock/StockOutRecordMapper.xml
@@ -100,6 +100,7 @@
sor.create_time as shippingDate,
p.product_name,
pm.model as specification_model,
+ slp.tax_rate,
sor.stock_out_num * slp.tax_inclusive_unit_price as outboundAmount,
s.shipping_no,
sl.sales_contract_no
@@ -116,6 +117,9 @@
<if test="req.customerName != null and req.customerName != ''">
AND sl.customer_name LIKE CONCAT('%',#{req.customerName},'%')
</if>
+ <if test="req.customerId != null ">
+ AND sl.customer_id = #{req.customerId}
+ </if>
<if test="req.startDate != null and req.endDate != null">
AND s.shipping_date BETWEEN #{req.startDate} AND #{req.endDate}
</if>
diff --git a/src/main/resources/mapper/system/SysNoticeMapper.xml b/src/main/resources/mapper/system/SysNoticeMapper.xml
index 3dd5735..14372d8 100644
--- a/src/main/resources/mapper/system/SysNoticeMapper.xml
+++ b/src/main/resources/mapper/system/SysNoticeMapper.xml
@@ -10,11 +10,16 @@
<result property="noticeType" column="notice_type" />
<result property="noticeContent" column="notice_content" />
<result property="status" column="status" />
+ <result property="senderId" column="sender_id" />
+ <result property="consigneeId" column="consignee_id" />
+ <result property="jumpPath" column="jump_path" />
+ <result property="appJumpPath" column="app_jump_path" />
<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" />
+ <result property="tenantId" column="tenant_id" />
</resultMap>
<sql id="selectNoticeVo">
diff --git a/src/main/resources/purchase-agent-prompt.txt b/src/main/resources/purchase-agent-prompt.txt
index 97f7eb2..2fd5021 100644
--- a/src/main/resources/purchase-agent-prompt.txt
+++ b/src/main/resources/purchase-agent-prompt.txt
@@ -1,5 +1,6 @@
浣犳槸浼佷笟閲囪喘鏅鸿兘鍔╃悊銆�
浣犵殑鐩爣鏄府鍔╃敤鎴峰揩閫熷畬鎴愰噰璐浉鍏充俊鎭煡璇笌瑙h銆�
+褰撳墠鏃ユ湡锛歿{currentDate}}锛堜腑鍥芥椂鍖猴級銆�
宸ヤ綔瑙勫垯锛�
1. 浼樺厛璋冪敤宸ュ叿鍑芥暟鑾峰彇閲囪喘鍙拌处銆佷粯娆俱�佸彂绁ㄣ�侀��璐х瓑缁撴瀯鍖栨暟鎹��
@@ -9,6 +10,8 @@
5. 鐢ㄦ埛闂�滄渶杩�7澶╀緵搴斿晢鍒拌揣寮傚父鈥濃�滃埌璐ч棶棰樷�濃�滃埌璐у紓甯糕�濇椂锛岃皟鐢ㄢ�滄煡璇㈤噰璐埌璐у紓甯糕�濄��
6. 鐢ㄦ埛闂�滃緟浠樻閲囪喘鍗曗�濃�滄湭浠樻閲囪喘鍗曗�濃�滄湭浠樻竻閲囪喘璁㈠崟鈥濇椂锛岃皟鐢ㄢ�滄煡璇㈠緟浠樻閲囪喘鍗曗�濄��
7. 鐢ㄦ埛闂�滄湰鏈堥噰璐��璐ф儏鍐碘�濃�滈噰璐��璐у垪琛ㄢ�濃�滈��鏂�/鎷掓敹鎯呭喌鈥濇椂锛岃皟鐢ㄢ�滄煡璇㈤噰璐��璐ф儏鍐碘�濄��
-8. 缁撴灉鐢ㄧ畝娲佷腑鏂囧洖绛旓紝鍏堢粰缁撹锛屽啀缁欏叧閿暟鎹偣銆�
-9. 涓嶈缂栭�犻噰璐暟鎹紝鎵�鏈夌粨璁哄繀椤诲熀浜庡伐鍏疯繑鍥炪��
-10. 鏃犳硶鐩存帴寰楀嚭缁撹鏃讹紝鏄庣‘璇存槑缂哄皯鍝簺瀛楁鎴栫瓫閫夋潯浠躲��
+8. 宸ュ叿杩斿洖 JSON 鏃讹紝鐩存帴杈撳嚭鍘熷 JSON 瀛楃涓诧紝涓嶈棰濆鍖呰9 Markdown锛屼篃涓嶈鍦ㄥ墠鍚庤拷鍔犺В閲婃枃鏈��
+9. 鍙湁鍦ㄦ湭璋冪敤 JSON 宸ュ叿鏃讹紝鎵嶄娇鐢ㄧ畝娲佷腑鏂囧洖绛旓紝鍏堢粰缁撹锛屽啀缁欏叧閿暟鎹偣銆�
+10. 涓嶈缂栭�犻噰璐暟鎹紝鎵�鏈夌粨璁哄繀椤诲熀浜庡伐鍏疯繑鍥炪��
+11. 鏃犳硶鐩存帴寰楀嚭缁撹鏃讹紝鏄庣‘璇存槑缂哄皯鍝簺瀛楁鎴栫瓫閫夋潯浠躲��
+12. 鐢ㄦ埛鎻愬埌鈥滀粖骞�/鏈湀/浠婂ぉ/鏈�杩�/涓婃湀/鍘诲勾鈥濈瓑鐩稿鏃堕棿鏃讹紝蹇呴』涓ユ牸鍩轰簬鈥滃綋鍓嶆棩鏈熲�濇崲绠楋紝绂佹鑷鍋囪骞翠唤銆�
diff --git a/src/main/resources/sales-agent-prompt.txt b/src/main/resources/sales-agent-prompt.txt
index 5cd87ff..3a43502 100644
--- a/src/main/resources/sales-agent-prompt.txt
+++ b/src/main/resources/sales-agent-prompt.txt
@@ -1,7 +1,9 @@
浣犳槸浼佷笟閿�鍞姪鎵嬶紝瑕嗙洊瀹㈡埛妗f銆侀攢鍞姤浠枫�侀攢鍞彴璐︺�侀攢鍞��璐с�佸鎴峰線鏉ャ�佸彂璐у彴璐︺�佹寚鏍囩粺璁°�佸鎴锋祦澶遍闄╁垎鏋愩�佸洖娆句笌鎶ヤ环绛栫暐寤鸿绛夊満鏅��
+褰撳墠鏃ユ湡锛歿{currentDate}}锛堜腑鍥芥椂鍖猴級銆�
宸ヤ綔瑙勫垯锛�
1. 鐢ㄦ埛鎻愬嚭鈥滄煡銆侀棶銆佺粺璁°�佸垎鏋愩�佸缓璁�濋渶姹傛椂锛屼紭鍏堣皟鐢ㄥ伐鍏疯繑鍥炵粨鏋勫寲鏁版嵁锛屼笉缂栭�犱笟鍔℃暟鎹��
2. 鍛戒腑鈥滃鎴锋祦澶遍闄╁垎鏋愨�濇垨鈥滃洖娆句笌鎶ヤ环绛栫暐寤鸿鈥濇椂锛屼紭鍏堜娇鐢ㄥ伐鍏疯緭鍑虹粨鏋勫寲 JSON銆�
3. 宸ュ叿杩斿洖 JSON 鏃讹紝鐩存帴杈撳嚭鍘熷 JSON 瀛楃涓诧紝涓嶈棰濆鍖呰9 Markdown锛屼篃涓嶈鍦ㄥ墠鍚庤拷鍔犺В閲婃枃鏈��
4. 鍥炲蹇呴』浣跨敤涓枃锛涜嫢鐢ㄦ埛缂哄皯鏃堕棿鑼冨洿銆佸叧閿瘝绛夋潯浠讹紝鍙厛浣跨敤榛樿鍙e緞骞舵彁绀哄彲琛ュ厖鏉′欢銆�
5. 鑻ユ暟鎹笉瓒充互寰楀嚭缁撹锛屾槑纭寚鍑虹己灏戠殑绛涢�夋潯浠舵垨鍏抽敭瀛楁銆�
+6. 鐢ㄦ埛鎻愬埌鈥滀粖骞�/鏈湀/浠婂ぉ/鏈�杩�/涓婃湀/鍘诲勾鈥濈瓑鐩稿鏃堕棿鏃讹紝蹇呴』涓ユ牸鍩轰簬鈥滃綋鍓嶆棩鏈熲�濇崲绠楋紝绂佹鑷鍋囪骞翠唤銆�
diff --git "a/src/main/resources/static/\351\224\200\345\224\256\345\217\260\350\264\246\345\257\274\345\205\245\346\250\241\346\235\277.xlsx" "b/src/main/resources/static/\351\224\200\345\224\256\345\217\260\350\264\246\345\257\274\345\205\245\346\250\241\346\235\277.xlsx"
index 9558711..0dad163 100644
--- "a/src/main/resources/static/\351\224\200\345\224\256\345\217\260\350\264\246\345\257\274\345\205\245\346\250\241\346\235\277.xlsx"
+++ "b/src/main/resources/static/\351\224\200\345\224\256\345\217\260\350\264\246\345\257\274\345\205\245\346\250\241\346\235\277.xlsx"
Binary files differ
--
Gitblit v1.9.3