From ac02be1aec94d28e83edd506479480a4bf9d86eb Mon Sep 17 00:00:00 2001 From: zhouhefeng Date: Thu, 31 Jul 2025 15:35:08 +0800 Subject: [PATCH 1/2] commit --- .../java/com/budwk/app/base/model/Audit.java | 1 + .../qsv/dto/QsvCheckAnswerResult.java | 21 - .../controller/AssetCategoryController.java | 91 +++ .../AssetDepreciationRecordController.java | 113 ++++ .../controller/AssetManageController.java | 218 +++++++ .../AssetStocktakingController.java | 75 +++ .../AssetStocktakingPlanController.java | 88 +++ .../com/budwk/app/zhgh/asset/model/Asset.java | 142 +++++ .../app/zhgh/asset/model/AssetCategory.java | 43 ++ .../asset/model/AssetDepreciationRecord.java | 68 +++ .../zhgh/asset/model/AssetStocktaking.java | 97 +++ .../asset/model/AssetStocktakingPlan.java | 48 ++ .../app/zhgh/asset/param/AssetPageForm.java | 30 + .../AssetDepreciationRecordService.java | 33 + .../app/zhgh/asset/service/AssetService.java | 15 + .../service/AssetStocktakingService.java | 15 + .../AssetDepreciationRecordServiceImpl.java | 192 ++++++ .../asset/service/impl/AssetServiceImpl.java | 86 +++ .../impl/AssetStocktakingServiceImpl.java | 120 ++++ .../qsv/controller/QsvActivityController.java | 42 +- .../qsv/controller/QsvQuizRankController.java | 25 +- .../qsv/controller/QsvSurveyController.java | 52 +- .../qsv/dto/QsvCheckAnswerResult.java | 17 + .../qsv/h5controller/H5QsvController.java | 18 +- .../qsv/h5controller/H5QsvQuizController.java | 153 ++--- .../h5controller/H5QsvSurveyController.java | 44 +- .../qsv/models/QsvActivity.java | 22 +- .../qsv/models/QsvOption.java | 18 +- .../qsv/models/QsvSubject.java | 10 +- .../qsv/models/QsvUserAnswerRecord.java | 5 +- .../qsv/param/QsvAnswerParam.java | 10 +- .../qsv/param/QsvQuizRankPageForm.java | 10 +- .../qsv/service/QsvActivityService.java | 5 +- .../qsv/service/QsvQuizRankService.java | 10 +- .../qsv/service/QsvQuizService.java | 8 +- .../qsv/service/QsvSurveyService.java | 11 +- .../service/QsvUserAnswerRecordService.java | 9 +- .../service/impl/QsvActivityServiceImpl.java | 6 +- .../service/impl/QsvQuizRankServiceImpl.java | 16 +- .../qsv/service/impl/QsvQuizServiceImpl.java | 10 +- .../service/impl/QsvSurveyServiceImpl.java | 129 +++- .../impl/QsvUserAnswerRecordServiceImpl.java | 54 +- .../model/EnrollmentRegistration.java | 23 + .../HealthCheckupCampusController.java | 125 ++++ .../HealthCheckupListController.java | 295 +++++++++ .../HealthCheckupProjectMangeController.java | 210 +++++++ .../HealthCheckupSingleController.java | 278 +++++++++ .../model/HealthCheckupCampus.java | 40 ++ .../model/HealthCheckupProject.java | 78 +++ .../model/HealthCheckupProjectSubject.java | 54 ++ .../model/HealthCheckupUnionConfirm.java | 52 ++ .../model/HealthCheckupUser.java | 76 +++ .../model/HealthCheckupUserCompanion.java | 66 ++ .../model/HealthCheckupUserSelection.java | 59 ++ .../service/HealthCheckupProjectService.java | 24 + .../service/HealthCheckupSingleService.java | 46 ++ .../impl/HealthCheckupProjectServiceImpl.java | 125 ++++ .../impl/HealthCheckupSingleServiceImpl.java | 273 +++++++++ .../template/HealthCheckupImportTemp.java | 25 + .../ActivityBudgetApplyController.java | 114 ++++ .../ActivityBudgetApplyListController.java | 167 +++++ ...tivityBudgetApplyStatisticsController.java | 129 ++++ ...tivityBudgetQueryStatisticsController.java | 97 +++ .../ActivityBudgetSchoolAuditController.java | 116 ++++ .../OutlayActBudgetApplyPostInterceptor.java | 130 ++++ .../OutlayActBudgetSchoolPostInterceptor.java | 35 ++ .../activityBudget/models/ActivityBudget.java | 140 +++++ .../models/ActivityBudgetDetails.java | 58 ++ .../models/ActivityBudgetType.java | 56 ++ .../ActivityBudgetApplyStatisticsService.java | 12 + .../ActivityBudgetQueryStatisticsService.java | 11 + .../service/ActivityBudgetService.java | 28 + ...ivityBudgetApplyStatisticsServiceImpl.java | 100 +++ ...ivityBudgetQueryStatisticsServiceImpl.java | 90 +++ .../impl/ActivityBudgetServiceImpl.java | 249 ++++++++ .../template/ActivityBudgetTemp.java | 55 ++ .../outlayManage/model/OutlayUseDetail.java | 79 +++ .../OutlayManageSchoolController.java | 125 ++++ ...OutlayManageSchoolUseDetailController.java | 128 ++++ .../school/model/OutlayManageSchool.java | 46 ++ .../service/OutlayUseDetailService.java | 16 + .../impl/OutlayUseDetailServiceImpl.java | 71 +++ .../OutlayManageUnionController.java | 143 +++++ .../OutlayManageUnionUseDetailController.java | 117 ++++ .../union/model/OutlayManageUnion.java | 62 ++ .../OutlayReimburseApplyListController.java | 80 +++ .../OutlayReimburseApplyPostInterceptor.java | 34 ++ ...ReimburseSchoolZxAuditPostInterceptor.java | 16 + .../model/OutlayReimburse.java | 124 ++++ .../OutlayReimburseApplyListService.java | 40 ++ .../OutlayReimburseApplyListServiceImpl.java | 260 ++++++++ .../controller/ThirtyTeachController.java | 236 ++++++++ .../ThirtyTeachSummaryController.java | 131 ++++ .../param/ThirtyTeachPageForm.java | 23 + .../service/ThirtyTeachService.java | 15 + .../service/impl/ThirtyTeachServiceImpl.java | 77 +++ .../thirtyTeach/template/ThirtyTeachTemp.java | 31 + .../platform/zhgh/activity/qsv/quiz/rank.html | 111 ---- .../zhgh/activity/qsv/survey/index.html | 70 --- .../platform/zhgh/asset/category/index.html | 161 +++++ .../platform/zhgh/asset/common/assetForm.js | 349 +++++++++++ .../platform/zhgh/asset/common/assetInfo.js | 164 +++++ .../zhgh/asset/common/assetStocktakingForm.js | 146 +++++ .../zhgh/asset/depreciation/index.html | 202 +++++++ .../platform/zhgh/asset/manage/index.html | 205 +++++++ .../zhgh/asset/stocktaking/index.html | 232 +++++++ .../zhgh/asset/stocktakingPlan/index.html | 212 +++++++ .../qsv/activity/basicForm.js | 34 +- .../qsv/activity/index.html | 11 +- .../qsv/activity/optionImg.js | 4 +- .../dayofficework/qsv/activity/setting.js | 39 ++ .../qsv/activity/subjectForm.js | 109 +++- .../dayofficework/qsv/activity/txtImport.js | 526 ++++++++++++++++ .../zhgh/dayofficework/qsv/quiz/rank.html | 129 ++++ .../qsv/survey/answer.js | 16 +- .../zhgh/dayofficework/qsv/survey/index.html | 74 +++ .../qsv/survey/report.js | 11 +- .../zhgh/healthCheckup/campus/index.html | 165 +++++ .../zhgh/healthCheckup/listMange/index.html | 338 +++++++++++ .../healthCheckup/projectMange/index.html | 572 ++++++++++++++++++ .../healthCheckup/statisticsSingle/index.html | 460 ++++++++++++++ .../outlay/activityBudget/apply/form.html | 337 +++++++++++ .../activityBudget/applyList/index.html | 253 ++++++++ .../activityBudget/applyStatistics/index.html | 224 +++++++ .../activityBudget/queryStatistics/index.html | 172 ++++++ .../activityBudget/schoolAudit/form.html | 69 +++ .../activityBudget/schoolAudit/index.html | 121 ++++ .../outlay/activityBudget/view/index.html | 110 ++++ .../outlayManage/common/editDetailDialog.js | 90 +++ .../outlayManage/school/manage/index.html | 183 ++++++ .../outlayManage/school/useDetail/index.html | 155 +++++ .../outlayManage/union/manage/index.html | 182 ++++++ .../union/useDetail/detailInfo.js | 101 ++++ .../outlayManage/union/useDetail/index.html | 125 ++++ .../outlay/outlayReimburse/apply/form.html | 323 ++++++++++ .../outlay/outlayReimburse/apply/index.html | 61 ++ .../outlay/outlayReimburse/view/index.html | 10 + .../zhgh/thirtyTeach/manage/index.html | 305 ++++++++++ .../zhgh/thirtyTeach/summary/index.html | 111 ++++ 139 files changed, 14203 insertions(+), 539 deletions(-) delete mode 100644 src/main/java/com/budwk/app/zhgh/activity/qsv/dto/QsvCheckAnswerResult.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/controller/AssetCategoryController.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/controller/AssetDepreciationRecordController.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/controller/AssetManageController.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/controller/AssetStocktakingController.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/controller/AssetStocktakingPlanController.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/model/Asset.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/model/AssetCategory.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/model/AssetDepreciationRecord.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/model/AssetStocktaking.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/model/AssetStocktakingPlan.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/param/AssetPageForm.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/service/AssetDepreciationRecordService.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/service/AssetService.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/service/AssetStocktakingService.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/service/impl/AssetDepreciationRecordServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/service/impl/AssetServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/asset/service/impl/AssetStocktakingServiceImpl.java rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/controller/QsvActivityController.java (78%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/controller/QsvQuizRankController.java (67%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/controller/QsvSurveyController.java (67%) create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/qsv/dto/QsvCheckAnswerResult.java rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/h5controller/H5QsvController.java (59%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/h5controller/H5QsvQuizController.java (75%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/h5controller/H5QsvSurveyController.java (69%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/models/QsvActivity.java (79%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/models/QsvOption.java (74%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/models/QsvSubject.java (86%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/models/QsvUserAnswerRecord.java (95%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/param/QsvAnswerParam.java (54%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/param/QsvQuizRankPageForm.java (50%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/service/QsvActivityService.java (50%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/service/QsvQuizRankService.java (60%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/service/QsvQuizService.java (65%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/service/QsvSurveyService.java (50%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/service/QsvUserAnswerRecordService.java (62%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/service/impl/QsvActivityServiceImpl.java (63%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/service/impl/QsvQuizRankServiceImpl.java (91%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/service/impl/QsvQuizServiceImpl.java (76%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/service/impl/QsvSurveyServiceImpl.java (66%) rename src/main/java/com/budwk/app/zhgh/{activity => dayofficework}/qsv/service/impl/QsvUserAnswerRecordServiceImpl.java (82%) create mode 100644 src/main/java/com/budwk/app/zhgh/enrollmentRegistration/model/EnrollmentRegistration.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/controller/HealthCheckupCampusController.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/controller/HealthCheckupListController.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/controller/HealthCheckupProjectMangeController.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/controller/HealthCheckupSingleController.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupCampus.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupProject.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupProjectSubject.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUnionConfirm.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUser.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUserCompanion.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUserSelection.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/service/HealthCheckupProjectService.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/service/HealthCheckupSingleService.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/service/impl/HealthCheckupProjectServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/service/impl/HealthCheckupSingleServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/healthCheckup/template/HealthCheckupImportTemp.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetApplyController.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetApplyListController.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetApplyStatisticsController.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetQueryStatisticsController.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetSchoolAuditController.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/interceptor/OutlayActBudgetApplyPostInterceptor.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/interceptor/OutlayActBudgetSchoolPostInterceptor.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/models/ActivityBudget.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/models/ActivityBudgetDetails.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/models/ActivityBudgetType.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/ActivityBudgetApplyStatisticsService.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/ActivityBudgetQueryStatisticsService.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/ActivityBudgetService.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/impl/ActivityBudgetApplyStatisticsServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/impl/ActivityBudgetQueryStatisticsServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/impl/ActivityBudgetServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/activityBudget/template/ActivityBudgetTemp.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/outlayManage/model/OutlayUseDetail.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/outlayManage/school/controller/OutlayManageSchoolController.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/outlayManage/school/controller/OutlayManageSchoolUseDetailController.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/outlayManage/school/model/OutlayManageSchool.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/outlayManage/service/OutlayUseDetailService.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/outlayManage/service/impl/OutlayUseDetailServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/outlayManage/union/controller/OutlayManageUnionController.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/outlayManage/union/controller/OutlayManageUnionUseDetailController.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/outlayManage/union/model/OutlayManageUnion.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/controller/OutlayReimburseApplyListController.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/interceptor/OutlayReimburseApplyPostInterceptor.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/interceptor/OutlayReimburseSchoolZxAuditPostInterceptor.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/model/OutlayReimburse.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/service/OutlayReimburseApplyListService.java create mode 100644 src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/service/impl/OutlayReimburseApplyListServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/thirtyTeach/controller/ThirtyTeachController.java create mode 100644 src/main/java/com/budwk/app/zhgh/thirtyTeach/controller/ThirtyTeachSummaryController.java create mode 100644 src/main/java/com/budwk/app/zhgh/thirtyTeach/param/ThirtyTeachPageForm.java create mode 100644 src/main/java/com/budwk/app/zhgh/thirtyTeach/service/ThirtyTeachService.java create mode 100644 src/main/java/com/budwk/app/zhgh/thirtyTeach/service/impl/ThirtyTeachServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/thirtyTeach/template/ThirtyTeachTemp.java delete mode 100644 src/main/resources/views/platform/zhgh/activity/qsv/quiz/rank.html delete mode 100644 src/main/resources/views/platform/zhgh/activity/qsv/survey/index.html create mode 100644 src/main/resources/views/platform/zhgh/asset/category/index.html create mode 100644 src/main/resources/views/platform/zhgh/asset/common/assetForm.js create mode 100644 src/main/resources/views/platform/zhgh/asset/common/assetInfo.js create mode 100644 src/main/resources/views/platform/zhgh/asset/common/assetStocktakingForm.js create mode 100644 src/main/resources/views/platform/zhgh/asset/depreciation/index.html create mode 100644 src/main/resources/views/platform/zhgh/asset/manage/index.html create mode 100644 src/main/resources/views/platform/zhgh/asset/stocktaking/index.html create mode 100644 src/main/resources/views/platform/zhgh/asset/stocktakingPlan/index.html rename src/main/resources/views/platform/zhgh/{activity => dayofficework}/qsv/activity/basicForm.js (91%) rename src/main/resources/views/platform/zhgh/{activity => dayofficework}/qsv/activity/index.html (90%) rename src/main/resources/views/platform/zhgh/{activity => dayofficework}/qsv/activity/optionImg.js (94%) create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/setting.js rename src/main/resources/views/platform/zhgh/{activity => dayofficework}/qsv/activity/subjectForm.js (86%) create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/txtImport.js create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/qsv/quiz/rank.html rename src/main/resources/views/platform/zhgh/{activity => dayofficework}/qsv/survey/answer.js (79%) create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/qsv/survey/index.html rename src/main/resources/views/platform/zhgh/{activity => dayofficework}/qsv/survey/report.js (88%) create mode 100644 src/main/resources/views/platform/zhgh/healthCheckup/campus/index.html create mode 100644 src/main/resources/views/platform/zhgh/healthCheckup/listMange/index.html create mode 100644 src/main/resources/views/platform/zhgh/healthCheckup/projectMange/index.html create mode 100644 src/main/resources/views/platform/zhgh/healthCheckup/statisticsSingle/index.html create mode 100644 src/main/resources/views/platform/zhgh/outlay/activityBudget/apply/form.html create mode 100644 src/main/resources/views/platform/zhgh/outlay/activityBudget/applyList/index.html create mode 100644 src/main/resources/views/platform/zhgh/outlay/activityBudget/applyStatistics/index.html create mode 100644 src/main/resources/views/platform/zhgh/outlay/activityBudget/queryStatistics/index.html create mode 100644 src/main/resources/views/platform/zhgh/outlay/activityBudget/schoolAudit/form.html create mode 100644 src/main/resources/views/platform/zhgh/outlay/activityBudget/schoolAudit/index.html create mode 100644 src/main/resources/views/platform/zhgh/outlay/activityBudget/view/index.html create mode 100644 src/main/resources/views/platform/zhgh/outlay/outlayManage/common/editDetailDialog.js create mode 100644 src/main/resources/views/platform/zhgh/outlay/outlayManage/school/manage/index.html create mode 100644 src/main/resources/views/platform/zhgh/outlay/outlayManage/school/useDetail/index.html create mode 100644 src/main/resources/views/platform/zhgh/outlay/outlayManage/union/manage/index.html create mode 100644 src/main/resources/views/platform/zhgh/outlay/outlayManage/union/useDetail/detailInfo.js create mode 100644 src/main/resources/views/platform/zhgh/outlay/outlayManage/union/useDetail/index.html create mode 100644 src/main/resources/views/platform/zhgh/outlay/outlayReimburse/apply/form.html create mode 100644 src/main/resources/views/platform/zhgh/outlay/outlayReimburse/apply/index.html create mode 100644 src/main/resources/views/platform/zhgh/outlay/outlayReimburse/view/index.html create mode 100644 src/main/resources/views/platform/zhgh/thirtyTeach/manage/index.html create mode 100644 src/main/resources/views/platform/zhgh/thirtyTeach/summary/index.html diff --git a/src/main/java/com/budwk/app/base/model/Audit.java b/src/main/java/com/budwk/app/base/model/Audit.java index b5b2b911..95beead7 100644 --- a/src/main/java/com/budwk/app/base/model/Audit.java +++ b/src/main/java/com/budwk/app/base/model/Audit.java @@ -64,6 +64,7 @@ public class Audit extends BaseModel { @ColDefine(type = ColType.INT) private Integer auditType; + public Date nowDate() { return new Date(); } diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/dto/QsvCheckAnswerResult.java b/src/main/java/com/budwk/app/zhgh/activity/qsv/dto/QsvCheckAnswerResult.java deleted file mode 100644 index 64cbbd87..00000000 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/dto/QsvCheckAnswerResult.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.budwk.app.zhgh.activity.qsv.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Builder; -import lombok.Data; -import lombok.experimental.Accessors; - -@ApiModel(value = "答题得分计算结果") -@Data -@Accessors(chain = true) -@Builder -public class QsvCheckAnswerResult { - - @ApiModelProperty(value = "是否正确") - private boolean isCorrect; - - @ApiModelProperty(value = "得分") - private float score; - -} diff --git a/src/main/java/com/budwk/app/zhgh/asset/controller/AssetCategoryController.java b/src/main/java/com/budwk/app/zhgh/asset/controller/AssetCategoryController.java new file mode 100644 index 00000000..eff037a5 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/controller/AssetCategoryController.java @@ -0,0 +1,91 @@ +package com.budwk.app.zhgh.asset.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.asset.model.AssetCategory; +import com.budwk.app.zhgh.asset.param.AssetPageForm; +import com.budwk.app.zhgh.asset.service.AssetService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.util.List; + +/** + * @author zhf + * @date 2025/7/16 15:05 + * @description 资产类别 + */ +@IocBean +@At("/platform/asset/category") +@Ok("json:full") +@Slf4j +@Api(tags = "资产类别") +public class AssetCategoryController { + + @Inject + private BaseService baseService; + + @At("") + @Ok("beetl:/platform/zhgh/asset/category/index.html") + @SaCheckPermission("asset.category") + public void index() { + } + + + @At + @ApiOperation("分页查询") + @SaCheckPermission("asset.category") + public Result pageData(AssetPageForm pageForm) { + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup group = new SqlExpressionGroup(); + group.orLike("categoryName", pageForm.getSearchKeyword()); + group.orLike("categoryCode", pageForm.getSearchKeyword()); + cnd.and(group); + } + Sql sql = Sqls.create(""" + SELECT * FROM `asset_category` + $condition + """); + cnd.asc("categoryCode"); + sql.setCondition(cnd); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + + @At + @ApiOperation("资产类型新增/编辑") + @SaCheckPermission("asset.category") + public Result doSubmit(AssetCategory assetCategory) { + baseService.insertOrUpdate(assetCategory); + return Result.success(); + } + + @At + @ApiOperation("资产类型新增") + @SaCheckPermission("asset.category") + public Result doDelete(String id) { + baseService.dao().delete(AssetCategory.class, id); + return Result.success(); + } + + @At + @ApiOperation("全部资产类型") + public Result queryCategory() { + List categoryList = baseService.dao().query(AssetCategory.class, Cnd.NEW().asc("categoryCode")); + return Result.success(categoryList); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/controller/AssetDepreciationRecordController.java b/src/main/java/com/budwk/app/zhgh/asset/controller/AssetDepreciationRecordController.java new file mode 100644 index 00000000..6f0cb071 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/controller/AssetDepreciationRecordController.java @@ -0,0 +1,113 @@ +package com.budwk.app.zhgh.asset.controller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.zhgh.asset.param.AssetPageForm; +import com.budwk.app.zhgh.asset.service.AssetDepreciationRecordService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.List; + +/** + * @author zhf + * @date 2025/7/17 11:32 + * @description 资产折旧 + */ +@IocBean +@At("/platform/asset/depreciation") +@Ok("json:full") +@Slf4j +@Api(tags = "资产折旧管理") +public class AssetDepreciationRecordController { + + + @Inject + private AssetDepreciationRecordService assetDepreciationRecordService; + + @At("") + @Ok("beetl:/platform/zhgh/asset/depreciation/index.html") + @SaCheckPermission("asset.depreciation") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("asset.depreciation") + public Result pageData(AssetPageForm pageForm) { + Sql sql = assetDepreciationRecordService.getSql(pageForm); + Pagination pagination = assetDepreciationRecordService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @ApiOperation("资产折旧信息删除") + @SLog(type = "assetDepreciation", tag = "资产折旧", msg = "删除了一条资产折旧信息") + @SaCheckPermission("asset.depreciation") + public Result doDelete(String id) { + assetDepreciationRecordService.clear(Cnd.where("assetId", "=", id)); + return Result.success(); + } + + @At + @ApiOperation("资产折旧") + @SLog(type = "assetDepreciation", tag = "资产折旧", msg = "一键折旧资产") + @SaCheckPermission("asset.depreciation") + public Result doDepreciation() { + assetDepreciationRecordService.doDepreciation(); + return Result.success(); + } + + @At + @ApiOperation("按条件导出资产折旧信息") + @SaCheckPermission("asset.depreciation") + @SLog(type = "assetDepreciation", tag = "资产折旧", msg = "按条件导出资产折旧信息") + public void doExport(AssetPageForm pageForm, HttpServletResponse response) { + Sql sql = assetDepreciationRecordService.getSql(pageForm); + List list = assetDepreciationRecordService.listMap(sql); + try { + List exportEntities = new ArrayList<>(); + exportEntities.add(new ExcelExportEntity("资产编号", "assetNumber", 20)); + exportEntities.add(new ExcelExportEntity("资产名称", "assetName", 20)); + exportEntities.add(new ExcelExportEntity("类别名称", "categoryName", 20)); + exportEntities.add(new ExcelExportEntity("责任人", "assetUseUserName", 20)); + ExcelExportEntity assetAllMoneyEntity = new ExcelExportEntity("原值(元)", "assetAllMoney", 20); + assetAllMoneyEntity.setType(10); + exportEntities.add(assetAllMoneyEntity); + ExcelExportEntity assetSurplusMoneyEntity = new ExcelExportEntity("净值(元)", "assetSurplusMoney", 20); + assetSurplusMoneyEntity.setType(10); + exportEntities.add(assetSurplusMoneyEntity); + ExcelExportEntity assetDepreciationMoneyEntity = new ExcelExportEntity("累计折旧(元)", "assetDepreciationMoney", 20); + assetDepreciationMoneyEntity.setType(10); + exportEntities.add(assetDepreciationMoneyEntity); + exportEntities.add(new ExcelExportEntity("预计使用月份", "assetUsageMonth", 20)); + + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, list); + CommonDownloadUtil.download("资产折旧信息.xlsx", workbook, response); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/controller/AssetManageController.java b/src/main/java/com/budwk/app/zhgh/asset/controller/AssetManageController.java new file mode 100644 index 00000000..a0ca0d3d --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/controller/AssetManageController.java @@ -0,0 +1,218 @@ +package com.budwk.app.zhgh.asset.controller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.asset.model.Asset; +import com.budwk.app.zhgh.asset.model.AssetDepreciationRecord; +import com.budwk.app.zhgh.asset.model.AssetStocktaking; +import com.budwk.app.zhgh.asset.param.AssetPageForm; +import com.budwk.app.zhgh.asset.service.AssetDepreciationRecordService; +import com.budwk.app.zhgh.asset.service.AssetService; +import com.budwk.app.zhgh.staffmanage.member.param.MemberInfoPageForm; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +/** + * @author zhf + * @date 2025/7/16 14:33 + * @description 资产台账管理 + */ +@IocBean +@At("/platform/asset/manage") +@Ok("json:full") +@Slf4j +@Api(tags = "资产台账管理") +public class AssetManageController { + + @Inject + private AssetService assetService; + @Inject + private AssetDepreciationRecordService assetDepreciationRecordService; + + @At("") + @Ok("beetl:/platform/zhgh/asset/manage/index.html") + @SaCheckPermission("asset.manage") + public void index() { + } + + + @At + @ApiOperation("分页查询") + @SaCheckPermission("asset.manage") + public Result pageData(AssetPageForm pageForm) { + Sql sql = assetService.getSql(pageForm); + Pagination pagination = assetService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + + @At + @ApiOperation("资产新增") + @SLog(type = "assetManage", tag = "资产管理", msg = "新增了一条资产信息") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("asset.manage") + public Result doAdd(Asset asset) { + int year = Calendar.getInstance().get(Calendar.YEAR); + if (StrUtil.isBlank(asset.getAssetNumber())) { + Sql sql = Sqls.create(""" + SELECT count(1) FROM `asset` where LEFT(assetNumber,4) = @year and LENGTH(assetNumber) = 8 + """).setParam("year", year); + int count = assetService.count(sql); + String bh = String.format("%04d", count + 1); + asset.setAssetNumber(year + bh); + } + asset.setApplyUserId(SecurityUtil.getUserId()); + assetService.insert(asset); + + //增加折旧表记录 + AssetDepreciationRecord record = assetDepreciationRecordService.initAssetDepreciationRecord(asset.getAssetUnitPrice(), asset.getAssetQuantity(), asset.getAssetUsedDate(), asset.getAssetRetiredAssetsDate()); + if (ObjectUtil.isNotEmpty(record)) { + record.setAssetId(asset.getId()); + assetService.insert(record); + } + return Result.success(); + } + + @At + @ApiOperation("资产编辑") + @Aop(TransAop.READ_COMMITTED) + @SLog(type = "assetManage", tag = "资产管理", msg = "编辑了一条资产信息") + @SaCheckPermission("asset.manage") + public Result doEdit(Asset asset) { + assetService.update(asset); + + //增加折旧表记录 + Asset fetch = assetService.fetch(asset.getId()); + //如果资产类型不等于原来的或者预计报废时间不等于原来的 + if (!fetch.getAssetCategoryId().equals(asset.getAssetCategoryId()) || !fetch.getAssetRetiredAssetsDate().equals(asset.getAssetRetiredAssetsDate())) { + assetDepreciationRecordService.clear(Cnd.where("assetId", "=", asset.getId())); + AssetDepreciationRecord record = assetDepreciationRecordService.initAssetDepreciationRecord(asset.getAssetUnitPrice(), asset.getAssetQuantity(), asset.getAssetUsedDate(), asset.getAssetRetiredAssetsDate()); + if (ObjectUtil.isNotEmpty(record)) { + record.setAssetId(asset.getId()); + assetService.insert(record); + } + } + + + return Result.success(); + } + + + @At + @ApiOperation("资产删除") + @Aop(TransAop.READ_COMMITTED) + @SLog(type = "assetManage", tag = "资产管理", msg = "删除了一条资产信息") + @SaCheckPermission("asset.manage") + public Result doDelete(String id) { + assetDepreciationRecordService.clear(Cnd.where("assetId", "=", id)); + assetService.delete(id); + assetService.dao().clear(AssetStocktaking.class, Cnd.where("assetId", "=", id)); + return Result.success(); + } + + + @At + @ApiOperation("查询资产单条记录") + @SaCheckPermission("asset.manage") + public Result findOne(String id) { + return Result.success(assetService.fetch(id)); + } + + @At + @ApiOperation("查询资产单条记录并跟关联的信息") + @SaCheckPermission("asset.manage") + public Result fondOneAsset(String id) { + return Result.success(assetService.findOne(id)); + } + + @At + @ApiOperation("查询责任人") + @SaCheckPermission("asset.manage") + public Result searchAssetUseUser(String query) { + Cnd cnd = Cnd.NEW(); + cnd.where().orLike("username", query); + cnd.where().orLike("loginname", query); + cnd.where().orLike("id", query); + Sql sql = Sqls.create(""" + SELECT + id, + loginname, + username, + unionName, + unionId + FROM + `vw_user` + $condition + """); + sql.setCondition(cnd); + Pagination pagination = assetService.listPage(1, 10, sql); + return Result.success(pagination.getList()); + } + + + @At + @ApiOperation("按条件导出资产台账") + @SaCheckPermission("asset.manage") + @SLog(type = "assetManage", tag = "资产台账", msg = "按条件导出资产台账") + public void doExport(AssetPageForm pageForm, HttpServletResponse response) { + Sql sql = assetService.getSql(pageForm); + List list = assetService.listMap(sql); + try { + List exportEntities = new ArrayList<>(); + exportEntities.add(new ExcelExportEntity("资产编号", "assetNumber", 20)); + exportEntities.add(new ExcelExportEntity("资产名称", "assetName", 20)); + exportEntities.add(new ExcelExportEntity("类别名称", "categoryName", 20)); + exportEntities.add(new ExcelExportEntity("资产规格型号", "assetSpecs", 20)); + exportEntities.add(new ExcelExportEntity("供应商名称", "assetSupplierName", 20)); + exportEntities.add(new ExcelExportEntity("采购方式", "assetFundingSubjectName", 20)); + exportEntities.add(new ExcelExportEntity("用途", "assetPurposeName", 20)); + ExcelExportEntity assetUnitPriceEntity = new ExcelExportEntity("单价(元)", "assetUnitPrice", 20); + assetUnitPriceEntity.setType(10); + exportEntities.add(assetUnitPriceEntity); + ExcelExportEntity assetQuantityEntity = new ExcelExportEntity("数量(台/件)", "assetQuantity", 20); + assetUnitPriceEntity.setType(10); + exportEntities.add(assetQuantityEntity); + exportEntities.add(new ExcelExportEntity("开始使用日期", "assetUsedDate", 30)); + exportEntities.add(new ExcelExportEntity("预计报废时间", "assetRetiredAssetsDate", 30)); + exportEntities.add(new ExcelExportEntity("责任人", "assetUseUserName", 30)); + exportEntities.add(new ExcelExportEntity("使用/管理部门", "assetUseUnionName", 30)); + exportEntities.add(new ExcelExportEntity("存放地点", "assetStorageLocation", 30)); + exportEntities.add(new ExcelExportEntity("使用状况", "assetUsageStateName", 30)); + + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, list); + CommonDownloadUtil.download("资产台账.xlsx", workbook, response); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/controller/AssetStocktakingController.java b/src/main/java/com/budwk/app/zhgh/asset/controller/AssetStocktakingController.java new file mode 100644 index 00000000..a0c20052 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/controller/AssetStocktakingController.java @@ -0,0 +1,75 @@ +package com.budwk.app.zhgh.asset.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.asset.model.Asset; +import com.budwk.app.zhgh.asset.model.AssetStocktaking; +import com.budwk.app.zhgh.asset.param.AssetPageForm; +import com.budwk.app.zhgh.asset.service.AssetStocktakingService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @author zhf + * @date 2025/7/17 16:06 + * @description 资产盘点 + */ +@IocBean +@At("/platform/asset/stocktaking") +@Ok("json:full") +@Slf4j +@Api(tags = "资产盘点管理") +public class AssetStocktakingController { + + + @Inject + private AssetStocktakingService assetStocktakingService; + + @At("") + @Ok("beetl:/platform/zhgh/asset/stocktaking/index.html") + @SaCheckPermission("asset.stocktaking") + public void index() { + } + + + @At + @ApiOperation("分页查询") + @SaCheckPermission("asset.stocktaking") + public Result pageData(AssetPageForm pageForm) { + Sql sql = assetStocktakingService.getSql(pageForm); + Pagination pagination = assetStocktakingService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @ApiOperation("资产盘点提交") + @Aop(TransAop.READ_COMMITTED) + @SLog(type = "AssetStocktaking", tag = "资产盘点", msg = "提交了一条资产盘点信息") + @SaCheckPermission("asset.stocktaking") + public Result doSubmit(AssetStocktaking assetStocktaking) { + + assetStocktakingService.doSubmit(assetStocktaking); + + return Result.success(); + } + + @At + @ApiOperation("删除资产盘点") + @Aop(TransAop.READ_COMMITTED) + @SLog(type = "AssetStocktaking", tag = "资产盘点", msg = "删除了一条资产盘点信息") + @SaCheckPermission("asset.stocktaking") + public Result doDelete(String id,String assetStocktakingPlanId) { + assetStocktakingService.doDelete(id,assetStocktakingPlanId); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/controller/AssetStocktakingPlanController.java b/src/main/java/com/budwk/app/zhgh/asset/controller/AssetStocktakingPlanController.java new file mode 100644 index 00000000..e41d7f98 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/controller/AssetStocktakingPlanController.java @@ -0,0 +1,88 @@ +package com.budwk.app.zhgh.asset.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.asset.model.AssetStocktakingPlan; +import com.budwk.app.zhgh.asset.param.AssetPageForm; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.util.List; + +/** + * @author zhf + * @date 2025/7/17 14:40 + * @description 资产盘点计划 + */ +@IocBean +@At("/platform/asset/stocktakingPlan") +@Ok("json:full") +@Slf4j +@Api(tags = "资产折旧管理") +public class AssetStocktakingPlanController { + + + @Inject + private BaseService baseService; + + + @At("") + @Ok("beetl:/platform/zhgh/asset/stocktakingPlan/index.html") + @SaCheckPermission("asset.stocktakingPlan") + public void index() { + } + + + @At + @ApiOperation("分页查询") + @SaCheckPermission("asset.stocktakingPlan") + public Result pageData(PageForm pageForm, Integer year) { + Sql sql = Sqls.create(""" + select * from asset_stocktaking_plan $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("year", "=", year); + sql.setCondition(cnd); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @ApiOperation("提交资产盘点计划/新增/编辑") + @SLog(type = "asset", tag = "资产管理", msg = "提交资产盘点计划/新增/编辑") + @SaCheckPermission("asset.stocktakingPlan") + public Result doSubmit(AssetStocktakingPlan assetStocktakingPlan) { + baseService.insertOrUpdate(assetStocktakingPlan); + return Result.success(); + } + + @At + @ApiOperation("资产盘点计划删除") + @SLog(type = "asset", tag = "资产管理", msg = "删除了一条资产盘点计划") + @SaCheckPermission("asset.stocktakingPlan") + public Result doDelete(String id) { + baseService.dao().delete(AssetStocktakingPlan.class, id); + return Result.success(); + } + + @At + @ApiOperation("按年度查询资产盘点计划") + @SaCheckPermission("asset.stocktakingPlan") + public Result queryStocktakingPlan(Integer year) { + List planList = baseService.dao().query(AssetStocktakingPlan.class, Cnd.NEW().andEX(AssetStocktakingPlan::getYear, "=", year)); + return Result.success(planList); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/model/Asset.java b/src/main/java/com/budwk/app/zhgh/asset/model/Asset.java new file mode 100644 index 00000000..1d632ce2 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/model/Asset.java @@ -0,0 +1,142 @@ +package com.budwk.app.zhgh.asset.model; + +import cn.hutool.json.JSONObject; +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + * @author zhf + * @date 2025/7/15 11:26 + * @description 资产 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@Table("asset") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("资产信息表") +public class Asset extends BaseModel implements Serializable { + + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + + @Column + @Comment("资产编号") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String assetNumber; + + @Column + @Comment("资产名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String assetName; + + @Column + @Comment("资产类别Id") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String assetCategoryId; + + @Column + @Comment("资产规格型号") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String assetSpecs; + + @Column + @Comment("供应商名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String assetSupplierName; + + @Column + @Comment("采购方式") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String assetFundingSubjectName; + + @Column + @Comment("用途") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String assetPurposeName; + + @Column + @Comment("单价") + @ColDefine(customType = "decimal(6,2)") + private BigDecimal assetUnitPrice; + + @Column + @Comment("数量") + @ColDefine(type = ColType.INT) + private Integer assetQuantity; + + @Column + @Comment("资产类型(1.校工会2.分工会)") + @ColDefine(type = ColType.INT) + private Integer assetTypeCode; + + @Column + @Comment("开始使用日期") + @ColDefine(type = ColType.DATE) + private Date assetUsedDate; + + @Column + @Comment("报废时间") + @ColDefine(type = ColType.DATE) + private Date assetRetiredAssetsDate; + + @Column + @Comment("发票/购买信息") + @ColDefine(type = ColType.MYSQL_JSON) + private List assetInvoiceFiles; + + @Column + @Comment("资产图片") + @ColDefine(type = ColType.MYSQL_JSON) + private List assetFiles; + + @Column + @Comment("备注") + @ColDefine(type = ColType.VARCHAR,width = 200) + private String assetNotes; + + @Column + @Comment("录入人Id") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String applyUserId; + + @Column + @Comment("使用状况") + @ColDefine(type = ColType.VARCHAR,width = 30) + private String assetUsageStateName; + + @Column + @Comment("责任人") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String assetUseUserId; + + @Column + @Comment("使用/管理部门") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String assetUseUnionId; + + @Column + @Comment("使用/管理部门") + @ColDefine(type = ColType.VARCHAR,width = 30) + private String assetUseUnionName; + + @Column + @Comment("存放地点") + @ColDefine(type = ColType.VARCHAR,width = 30) + private String assetStorageLocation; + + +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/model/AssetCategory.java b/src/main/java/com/budwk/app/zhgh/asset/model/AssetCategory.java new file mode 100644 index 00000000..2dc6493a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/model/AssetCategory.java @@ -0,0 +1,43 @@ +package com.budwk.app.zhgh.asset.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; + +/** + * @author zhf + * @date 2025/7/16 14:17 + * @description 资产类别 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("asset_category") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("资产类别表") +public class AssetCategory extends BaseModel implements Serializable { + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + @Column + @Comment("内容") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String categoryName; + + @Column + @Comment("编码") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String categoryCode; + + @Column + @Comment("折旧年限(年)") + @ColDefine(type = ColType.INT) + private int depreciationYear; +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/model/AssetDepreciationRecord.java b/src/main/java/com/budwk/app/zhgh/asset/model/AssetDepreciationRecord.java new file mode 100644 index 00000000..ad976168 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/model/AssetDepreciationRecord.java @@ -0,0 +1,68 @@ +package com.budwk.app.zhgh.asset.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * @author zhf + * @date 2025/7/16 14:19 + * @description 资产折旧记录表 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("asset_depreciation_record") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("资产折旧记录表") +public class AssetDepreciationRecord extends BaseModel implements Serializable { + + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + + @Column + @Comment("资产登记id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String assetId; + + + @Column + @Comment("剩余月") + @ColDefine(type = ColType.INT) + private Integer assetRemainingMonths; + + @Column + @Comment("资产全部的价值") + @ColDefine(customType = "decimal(6,2)") + private BigDecimal assetAllMoney; + + @Column + @Comment("剩余价值") + @ColDefine(customType = "decimal(6,2)") + private BigDecimal assetSurplusMoney; + + @Column + @Comment("累计折旧多少钱") + @ColDefine(customType = "decimal(6,2)") + private BigDecimal assetDepreciationMoney; + + @Column + @Comment("平均一个月多少钱") + @ColDefine(customType = "decimal(6,2)") + private BigDecimal assetAverageMonthMoney; + + @Column + @Comment("折旧到期时间") + @ColDefine(type = ColType.DATE) + private Date assetRetiredAssetsDate; +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/model/AssetStocktaking.java b/src/main/java/com/budwk/app/zhgh/asset/model/AssetStocktaking.java new file mode 100644 index 00000000..5565a8a8 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/model/AssetStocktaking.java @@ -0,0 +1,97 @@ +package com.budwk.app.zhgh.asset.model; + +import cn.hutool.json.JSONObject; +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; +import java.util.List; + +/** + * @author zhf + * @date 2025/7/17 15:40 + * @description 资产盘点 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("asset_stocktaking") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("资产盘点表") +public class AssetStocktaking extends BaseModel implements Serializable { + + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + + @Column + @Comment("资产登记id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String assetId; + + @Column + @Comment("盘点计划id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String assetStocktakingPlanId; + + + @Column + @Comment("旧责任人") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String oldAssetUseUserId; + + @Column + @Comment("旧责任人姓名") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String oldAssetUseUserName; + + @Column + @Comment("旧责任人工号") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String oldAssetUseLoginName; + + + @Column + @Comment("旧使用/管理部门") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String oldAssetUseUnionId; + + @Column + @Comment("旧使用/管理部门") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String oldAssetUseUnionName; + + @Column + @Comment("旧存放地点") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String oldAssetStorageLocation; + + @Column + @Comment("旧使用状况") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String oldAssetUsageStateName; + + @Column + @Comment("旧资产图片") + @ColDefine(type = ColType.MYSQL_JSON) + private List oldAssetFiles; + + @Column + @Comment("旧备注") + @ColDefine(type = ColType.VARCHAR, width = 200) + private String oldAssetNotes; + + private String assetUsageStateName; + private String assetStorageLocation; + private String assetUseUserId; + private String assetNotes; + private List assetFiles; + + +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/model/AssetStocktakingPlan.java b/src/main/java/com/budwk/app/zhgh/asset/model/AssetStocktakingPlan.java new file mode 100644 index 00000000..8f89c4a8 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/model/AssetStocktakingPlan.java @@ -0,0 +1,48 @@ +package com.budwk.app.zhgh.asset.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; + +/** + * @author zhf + * @date 2025/7/17 12:11 + * @description 资产盘点 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("asset_stocktaking_plan") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("资产盘点计划表") +public class AssetStocktakingPlan extends BaseModel implements Serializable { + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + @Column + @Comment("年度") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String year; + + @Column + @Comment("开始时间") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String startDate; + + @Column + @Comment("时间") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String endDate; + + @Column + @Comment("说明") + @ColDefine(type = ColType.VARCHAR, width = 300) + private String note; +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/param/AssetPageForm.java b/src/main/java/com/budwk/app/zhgh/asset/param/AssetPageForm.java new file mode 100644 index 00000000..6a87388c --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/param/AssetPageForm.java @@ -0,0 +1,30 @@ +package com.budwk.app.zhgh.asset.param; + +import com.budwk.app.base.param.PageForm; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author zhf + * @date 2025/7/16 14:43 + * @description 资产查询pageForm + */ +@EqualsAndHashCode(callSuper = false) +@Data +public class AssetPageForm extends PageForm { + + + + //资产类型(1.校工会2.分工会) + private Integer assetTypeCode; + //资产类别Id + private String assetCategoryId; + //使用状况 + private String assetUsageStateName; + //使用/管理部门 + private String assetUseUnionId; + //盘点时间段 + private String assetStocktakingPlanId; + //是否盘点 + private Boolean isStocktaking; +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/service/AssetDepreciationRecordService.java b/src/main/java/com/budwk/app/zhgh/asset/service/AssetDepreciationRecordService.java new file mode 100644 index 00000000..9695250e --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/service/AssetDepreciationRecordService.java @@ -0,0 +1,33 @@ +package com.budwk.app.zhgh.asset.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.asset.model.AssetDepreciationRecord; +import com.budwk.app.zhgh.asset.param.AssetPageForm; +import org.nutz.dao.sql.Sql; + +import java.math.BigDecimal; +import java.util.Date; + +public interface AssetDepreciationRecordService extends BaseService { + + + /** + *计算折旧记录 + * @param assetUnitPrice 单价 + * @param assetQuantity 数量 + * @param assetUsedDate 开始使用日期 + * @param assetRetiredAssetsDate 预计折旧到期时间 + * @return + */ + AssetDepreciationRecord initAssetDepreciationRecord(BigDecimal assetUnitPrice,Integer assetQuantity,Date assetUsedDate, Date assetRetiredAssetsDate); + + + + + Sql getSql(AssetPageForm pageForm); + + void doDepreciation(); + + + +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/service/AssetService.java b/src/main/java/com/budwk/app/zhgh/asset/service/AssetService.java new file mode 100644 index 00000000..325306fc --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/service/AssetService.java @@ -0,0 +1,15 @@ +package com.budwk.app.zhgh.asset.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.asset.model.Asset; +import com.budwk.app.zhgh.asset.param.AssetPageForm; +import org.nutz.dao.sql.Sql; +import org.nutz.lang.util.NutMap; + +public interface AssetService extends BaseService { + + + Sql getSql(AssetPageForm pageForm); + + NutMap findOne(String id); +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/service/AssetStocktakingService.java b/src/main/java/com/budwk/app/zhgh/asset/service/AssetStocktakingService.java new file mode 100644 index 00000000..f48cc597 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/service/AssetStocktakingService.java @@ -0,0 +1,15 @@ +package com.budwk.app.zhgh.asset.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.asset.model.AssetStocktaking; +import com.budwk.app.zhgh.asset.param.AssetPageForm; +import org.nutz.dao.sql.Sql; + +public interface AssetStocktakingService extends BaseService { + + + Sql getSql(AssetPageForm pageForm); + + void doSubmit(AssetStocktaking assetStocktaking); + void doDelete(String id,String assetStocktakingPlanId); +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/service/impl/AssetDepreciationRecordServiceImpl.java b/src/main/java/com/budwk/app/zhgh/asset/service/impl/AssetDepreciationRecordServiceImpl.java new file mode 100644 index 00000000..f1bab5b3 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/service/impl/AssetDepreciationRecordServiceImpl.java @@ -0,0 +1,192 @@ +package com.budwk.app.zhgh.asset.service.impl; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.asset.model.Asset; +import com.budwk.app.zhgh.asset.model.AssetDepreciationRecord; +import com.budwk.app.zhgh.asset.param.AssetPageForm; +import com.budwk.app.zhgh.asset.service.AssetDepreciationRecordService; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.Date; +import java.util.List; + +/** + * @author zhf + * @date 2025/7/16 14:30 + * @description + */ +@IocBean(args = {"refer:dao"}) +public class AssetDepreciationRecordServiceImpl extends BaseServiceImpl implements AssetDepreciationRecordService { + public AssetDepreciationRecordServiceImpl(Dao dao) { + super(dao); + } + + @Override + public AssetDepreciationRecord initAssetDepreciationRecord(BigDecimal assetUnitPrice, Integer assetQuantity, Date assetUsedDate, Date assetRetiredAssetsDate) { + // 将 Date 转换为 LocalDate + LocalDate assetUsedDateLocalDate = assetUsedDate.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + LocalDate assetRetiredAssetsDateLocalDate = assetRetiredAssetsDate.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + + // 计算资产使用时间到折旧到期时间多少个月 + long wholeMonth = ChronoUnit.MONTHS.between(assetUsedDateLocalDate, assetRetiredAssetsDateLocalDate); + //计算资产使用时间到现在使用了几个月 + long usedMonth = ChronoUnit.MONTHS.between(assetUsedDateLocalDate, LocalDate.now()); + AssetDepreciationRecord record = new AssetDepreciationRecord(); + //如果折旧到期时间小于现在时间直接设为0 + if (assetRetiredAssetsDateLocalDate.isBefore(LocalDate.now())) { + //预计折旧到期时间 + record.setAssetRetiredAssetsDate(assetRetiredAssetsDate); + //资产剩余的月 + record.setAssetRemainingMonths(0); + //资产全部的金额 + record.setAssetAllMoney(assetUnitPrice.multiply(new BigDecimal(assetQuantity))); + //资产平均每月价值 + record.setAssetAverageMonthMoney(record.getAssetAllMoney().divide(new BigDecimal(wholeMonth), 2, RoundingMode.DOWN)); + //剩余价值 + record.setAssetSurplusMoney(BigDecimal.ZERO); + record.setAssetDepreciationMoney(assetUnitPrice.multiply(new BigDecimal(assetQuantity))); + return record; + } else if (wholeMonth - usedMonth >= 0) { + //预计折旧到期时间 + record.setAssetRetiredAssetsDate(assetRetiredAssetsDate); + //资产剩余的月 + record.setAssetRemainingMonths((int) (wholeMonth - usedMonth < 0 ? 0 : wholeMonth - usedMonth)); + //资产全部的金额 + record.setAssetAllMoney(assetUnitPrice.multiply(new BigDecimal(assetQuantity))); + //资产平均每月价值 + record.setAssetAverageMonthMoney(record.getAssetAllMoney().divide(new BigDecimal(wholeMonth), 2, RoundingMode.DOWN)); + //剩余价值 + if (usedMonth == 0) { + //如果等于0代表一个月都没用到直接设为全部的金额 + record.setAssetSurplusMoney(assetUnitPrice.multiply(new BigDecimal(assetQuantity))); + } else { + record.setAssetSurplusMoney(record.getAssetAverageMonthMoney().multiply(BigDecimal.valueOf(record.getAssetRemainingMonths()))); + } + //累计折旧多少钱 + record.setAssetDepreciationMoney(record.getAssetAverageMonthMoney().multiply(BigDecimal.valueOf(usedMonth))); + return record; + } + return null; + } + + @Override + public Sql getSql(AssetPageForm pageForm) { + Sql sql = Sqls.create(""" + SELECT + t2.*, + t1.assetAllMoney, + t1.assetSurplusMoney, + t1.assetDepreciationMoney, + IFNULL(t3.depreciationYear, 0) * 12 AS assetUsageMonth, + t3.categoryName, + t4.username AS assetUseUserName + FROM + asset_depreciation_record t1 + LEFT JOIN `asset` t2 ON t2.id = t1.assetId + LEFT JOIN asset_category t3 ON t3.id = t2.assetCategoryId + LEFT JOIN sys_user t4 ON t4.id = t2.assetUseUserId + $condition + """); + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup group = new SqlExpressionGroup(); + group.orLike("t2.assetNumber", pageForm.getSearchKeyword()); + group.orLike("t2.assetName", pageForm.getSearchKeyword()); + cnd.and(group); + } + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.and("t2.assetUseUnionId", "=", SecurityUtil.getUnionId()); + } + cnd.andEX("t2.assetUseUnionId", "=", pageForm.getAssetUseUnionId()); + cnd.andEX("t2.assetCategoryId", "=", pageForm.getAssetCategoryId()); + cnd.andEX("t2.assetTypeCode", "=", pageForm.getAssetTypeCode()); + cnd.andEX("t2.assetUsageStateName", "=", pageForm.getAssetUsageStateName()); + sql.setCondition(cnd); + return sql; + } + + @Override + public void doDepreciation() { + //查询所有资产中剩余价值不等于0的 + Sql sql = Sqls.create(""" + SELECT + t2.*, + t1.assetUnitPrice, + t1.assetQuantity, + t1.assetUsedDate, + t1.assetUsageStateName + FROM + `asset` t1 + LEFT JOIN asset_depreciation_record t2 ON t1.id = t2.assetId + WHERE + t2.assetSurplusMoney > 0 + """); + List assetList = listMap(sql); + + //找出可以折旧的资产id + List assetIds = assetList.stream().map(v -> v.getString("assetId")).toList(); + + //根据上面的id找出折旧表里面的记录 + List depreciationRecordList = query(Cnd.where("assetId", "in", assetIds)); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + depreciationRecordList.forEach(record -> { + //找出该资产的使用状况是不是正常的 + NutMap map = assetList.stream().filter(v -> v.getString("assetId").equals(record.getAssetId())).findFirst().orElse(null); + LocalDate assetRetiredAssetsLocalDate = LocalDate.parse(map.getString("assetRetiredAssetsDate"), formatter); + + + if (map != null && !"正常".equals(map.getString("assetUsageStateName"))) { + //如果这个资产不是正常的就直接把剩余价值设为0,剩余月份也设为0 + record.setAssetSurplusMoney(BigDecimal.ZERO); + record.setAssetRemainingMonths(0); + } else if (assetRetiredAssetsLocalDate.isBefore(LocalDate.now())) { + //如果这个资产折旧到期时间小于现在时间直接设为0 + record.setAssetSurplusMoney(BigDecimal.ZERO); + record.setAssetRemainingMonths(0); + } else { + //转换时间为我上面方法所需要的类型 + BigDecimal assetUnitPrice = new BigDecimal(map.getString("assetUnitPrice")); + + int assetQuantity = map.getInt("assetQuantity"); + + LocalDateTime assetUsedLocalDateTime = LocalDateTime.parse(map.getString("assetUsedDate"), formatter); + Date assetUsedDate = Date.from(assetUsedLocalDateTime.atZone(ZoneId.systemDefault()).toInstant()); + + LocalDateTime assetRetiredAssetsLocalDateTime = LocalDateTime.parse(map.getString("assetRetiredAssetsDate"), formatter); + Date assetRetiredAssetsDate = Date.from(assetRetiredAssetsLocalDateTime.atZone(ZoneId.systemDefault()).toInstant()); + //算出剩余的月份和价值 + AssetDepreciationRecord inited = initAssetDepreciationRecord(assetUnitPrice, assetQuantity, assetUsedDate, assetRetiredAssetsDate); + //如果返回空代表一个月也没使用不增加 + if (ObjectUtil.isNotEmpty(inited)) { + record.setAssetRemainingMonths(inited.getAssetRemainingMonths()); + record.setAssetSurplusMoney(inited.getAssetSurplusMoney()); + record.setAssetDepreciationMoney(inited.getAssetDepreciationMoney()); + } + } + }); + update(depreciationRecordList); + + } +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/service/impl/AssetServiceImpl.java b/src/main/java/com/budwk/app/zhgh/asset/service/impl/AssetServiceImpl.java new file mode 100644 index 00000000..7711852b --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/service/impl/AssetServiceImpl.java @@ -0,0 +1,86 @@ +package com.budwk.app.zhgh.asset.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.asset.model.Asset; +import com.budwk.app.zhgh.asset.model.AssetStocktaking; +import com.budwk.app.zhgh.asset.param.AssetPageForm; +import com.budwk.app.zhgh.asset.service.AssetService; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; + +/** + * @author zhf + * @date 2025/7/16 14:28 + * @description + */ +@IocBean(args = {"refer:dao"}) +public class AssetServiceImpl extends BaseServiceImpl implements AssetService { + public AssetServiceImpl(Dao dao) { + super(dao); + } + + @Override + public Sql getSql(AssetPageForm pageForm) { + Sql sql = Sqls.create(""" + SELECT + t1.*, + t3.categoryName, + t4.username AS assetUseUserName + FROM + `asset` t1 + LEFT JOIN asset_depreciation_record t2 ON t1.id = t2.assetId + LEFT JOIN asset_category t3 ON t3.id = t1.assetCategoryId + LEFT JOIN sys_user t4 ON t4.id = t1.assetUseUserId + $condition + """); + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup group = new SqlExpressionGroup(); + group.orLike("t1.assetNumber", pageForm.getSearchKeyword()); + group.orLike("t1.assetName", pageForm.getSearchKeyword()); + cnd.and(group); + } + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.and("t1.assetUseUnionId", "=", SecurityUtil.getUnionId()); + } + cnd.andEX("t1.assetUseUnionId", "=", pageForm.getAssetUseUnionId()); + cnd.andEX("t1.assetCategoryId", "=", pageForm.getAssetCategoryId()); + cnd.andEX("t1.assetTypeCode", "=", pageForm.getAssetTypeCode()); + cnd.andEX("t1.assetUsageStateName", "=", pageForm.getAssetUsageStateName()); + sql.setCondition(cnd); + return sql; + } + + @Override + public NutMap findOne(String id) { + + Sql sql = Sqls.create(""" + SELECT + t1.*, + t3.categoryName AS assetCategoryName, + t3.depreciationYear AS assetDepreciationYear, + t4.username AS assetUseUserName + FROM + `asset` t1 + LEFT JOIN asset_depreciation_record t2 ON t1.id = t2.assetId + LEFT JOIN asset_category t3 ON t3.id = t1.assetCategoryId + LEFT JOIN sys_user t4 ON t4.id = t1.assetUseUserId + WHERE + t1.id = @id + """).setParam("id",id); + NutMap nutMap = (NutMap) dao().execute(sql.setCallback(Sqls.callback.map())).getResult(); + + nutMap.setv("assetStocktakingList", dao().query(AssetStocktaking.class, + Cnd.where("assetId", "=", id))); + return nutMap; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/asset/service/impl/AssetStocktakingServiceImpl.java b/src/main/java/com/budwk/app/zhgh/asset/service/impl/AssetStocktakingServiceImpl.java new file mode 100644 index 00000000..a9473e08 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/asset/service/impl/AssetStocktakingServiceImpl.java @@ -0,0 +1,120 @@ +package com.budwk.app.zhgh.asset.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.asset.model.Asset; +import com.budwk.app.zhgh.asset.model.AssetStocktaking; +import com.budwk.app.zhgh.asset.param.AssetPageForm; +import com.budwk.app.zhgh.asset.service.AssetStocktakingService; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.dao.util.cri.Static; +import org.nutz.ioc.loader.annotation.IocBean; + +/** + * @author zhf + * @date 2025/7/17 16:08 + * @description + */ +@IocBean(args = {"refer:dao"}) +public class AssetStocktakingServiceImpl extends BaseServiceImpl implements AssetStocktakingService { + public AssetStocktakingServiceImpl(Dao dao) { + super(dao); + } + + @Override + public Sql getSql(AssetPageForm pageForm) { + Sql sql = Sqls.create(""" + SELECT + t1.*, + t3.categoryName, + t4.username AS assetUseUserName, + COUNT(t5.assetId) AS isStocktaking + FROM + `asset` t1 + LEFT JOIN asset_depreciation_record t2 ON t1.id = t2.assetId + LEFT JOIN asset_category t3 ON t3.id = t1.assetCategoryId + LEFT JOIN sys_user t4 ON t4.id = t1.assetUseUserId + LEFT JOIN asset_stocktaking t5 ON t5.assetId = t1.id + AND t5.assetStocktakingPlanId =@assetStocktakingPlanId + $condition + $stocktakingCnd + """).setParam("assetStocktakingPlanId", pageForm.getAssetStocktakingPlanId()); + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup group = new SqlExpressionGroup(); + group.orLike("t1.assetNumber", pageForm.getSearchKeyword()); + group.orLike("t1.assetName", pageForm.getSearchKeyword()); + cnd.and(group); + } + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.and("t1.assetUseUnionId", "=", SecurityUtil.getUnionId()); + } + if (pageForm.getIsStocktaking() != null) { + sql.setVar("stocktakingCnd", "HAVING COUNT(t5.assetId) " + (pageForm.getIsStocktaking() ? ">" : "=") + "0"); + } + cnd.andEX("t1.assetUseUnionId", "=", pageForm.getAssetUseUnionId()); + cnd.andEX("t1.assetCategoryId", "=", pageForm.getAssetCategoryId()); + cnd.andEX("t1.assetTypeCode", "=", pageForm.getAssetTypeCode()); + cnd.andEX("t1.assetUsageStateName", "=", pageForm.getAssetUsageStateName()); + sql.setCondition(cnd); + return sql; + } + + @Override + public void doSubmit(AssetStocktaking assetStocktaking) { + + Asset asset = dao().fetch(Asset.class, assetStocktaking.getAssetId()); + //插入盘点表记录上一次的数据 + //查询旧的责任人是谁 + View_user oldUser = dao().fetch(View_user.class, Cnd.where("id", "=", asset.getAssetUseUserId())); + assetStocktaking.setOldAssetFiles(asset.getAssetFiles()); + assetStocktaking.setOldAssetNotes(asset.getAssetNotes()); + assetStocktaking.setOldAssetStorageLocation(asset.getAssetStorageLocation()); + assetStocktaking.setOldAssetUseUserId(asset.getAssetUseUserId()); + assetStocktaking.setOldAssetUseUserName(oldUser.getUsername()); + assetStocktaking.setOldAssetUseLoginName(oldUser.getLoginname()); + assetStocktaking.setOldAssetUseUnionId(asset.getAssetUseUnionId()); + assetStocktaking.setOldAssetUseUnionName(asset.getAssetUseUnionName()); + assetStocktaking.setOldAssetUsageStateName(asset.getAssetUsageStateName()); + insert(assetStocktaking); + //跟新资产信息表,资产信息表始终是最新的数据 + View_user user = dao().fetch(View_user.class, Cnd.where("id", "=", assetStocktaking.getAssetUseUserId())); + asset.setAssetFiles(assetStocktaking.getAssetFiles()); + asset.setAssetNotes(assetStocktaking.getAssetNotes()); + asset.setAssetStorageLocation(assetStocktaking.getAssetStorageLocation()); + asset.setAssetUseUserId(assetStocktaking.getAssetUseUserId()); + asset.setAssetUseUnionId(user.getUnionId()); + asset.setAssetUseUnionName(user.getUnionName()); + asset.setAssetUsageStateName(assetStocktaking.getAssetUsageStateName()); + dao().update(asset); + } + + @Override + public void doDelete(String id, String assetStocktakingPlanId) { + //找出盘点的信息,修改到资产信息表 + AssetStocktaking assetStocktaking = fetch(Cnd.where("assetId", "=", id) + .and("assetStocktakingPlanId", "=", assetStocktakingPlanId)); + Asset asset = dao().fetch(Asset.class, assetStocktaking.getAssetId()); + asset.setAssetFiles(assetStocktaking.getOldAssetFiles()); + asset.setAssetNotes(assetStocktaking.getOldAssetNotes()); + asset.setAssetStorageLocation(assetStocktaking.getOldAssetStorageLocation()); + asset.setAssetUseUserId(assetStocktaking.getOldAssetUseUserId()); + asset.setAssetUseUnionId(assetStocktaking.getOldAssetUseUnionId()); + asset.setAssetUseUnionName(assetStocktaking.getOldAssetUseUnionName()); + asset.setAssetUsageStateName(assetStocktaking.getOldAssetUsageStateName()); + dao().update(asset); + //删除盘点信息 + clear(Cnd.where("assetId", "=", id) + .and("assetStocktakingPlanId", "=", assetStocktakingPlanId)); + + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/controller/QsvActivityController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvActivityController.java similarity index 78% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/controller/QsvActivityController.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvActivityController.java index ffd1378f..0832609f 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/controller/QsvActivityController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvActivityController.java @@ -1,15 +1,14 @@ -package com.budwk.app.zhgh.activity.qsv.controller; +package com.budwk.app.zhgh.dayofficework.qsv.controller; -import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; -import com.budwk.app.base.service.BaseService; -import com.budwk.app.zhgh.activity.qsv.models.QsvActivity; -import com.budwk.app.zhgh.activity.qsv.models.QsvOption; -import com.budwk.app.zhgh.activity.qsv.models.QsvSubject; -import com.budwk.app.zhgh.activity.qsv.service.QsvActivityService; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvActivity; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvOption; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvSubject; +import com.budwk.app.zhgh.dayofficework.qsv.service.QsvActivityService; import io.swagger.annotations.ApiOperation; import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.dao.Cnd; @@ -28,6 +27,7 @@ import java.util.List; @IocBean @At("/platform/qsv/activity") @Ok("json:full") +@ApiOperation("问卷调查管理") public class QsvActivityController { @Inject @@ -36,16 +36,17 @@ public class QsvActivityController { private QsvActivityService qsvActivityService; @At("") - @Ok("beetl:/platform/zhgh/activity/qsv/activity/index.html") + @Ok("beetl:/platform/zhgh/dayofficework/qsv/activity/index.html") @SaCheckPermission("qsv.activity") public void index() { } + +// 分页查询 @At @SaCheckPermission("qsv.activity") - @ApiOperation("分页查询") - public Result pageData(@Valid PageForm pageForm, Integer year,String title) { + public Result pageData(@Valid PageForm pageForm, Integer year, String title) { Cnd cnd = Cnd.NEW(); cnd.andEX("YEAR(startTime)", "=", year); cnd.and(Cnd.likeEX("title",title)); @@ -54,9 +55,11 @@ public class QsvActivityController { } +// 保存问卷基础信息 @At @SaCheckPermission("qsv.activity") @ApiOperation("保存问卷基础信息") + @SLog(type = "qsv.activity", tag = "保存问卷基础信息", msg = "保存问卷基础信息") public Result save(QsvActivity qsvActivity) { if (qsvActivity.getCategory().equals("QUIZ")) { if (qsvActivity.getMode().equals("SCHEDULED")) { @@ -76,20 +79,25 @@ public class QsvActivityController { return Result.success(activity); } +// 删除问卷 @At @SaCheckPermission("qsv.activity") @ApiOperation("删除问卷") + @SLog(type = "qsv.activity", tag = "删除问卷", msg = "删除问卷") public Result delete(@Valid String id) { dao.delete(QsvActivity.class, id); return Result.success(); } + +// 保存问卷题目 @At @SaCheckPermission("qsv.activity") - @ApiOperation("保存问卷题目") @Aop(TransAop.READ_COMMITTED) + @ApiOperation("保存问卷题目") + @SLog(type = "qsv.activity", tag = "保存问卷题目", msg = "保存问卷题目") public Result saveSubjects(@Param("activityId") @Valid String activityId, @Param("subjects") QsvSubject[] qsvSubjects) { - List subjects = dao.query(QsvSubject.class, Cnd.where(QsvSubject::getActivityId, "=", activityId)); + List subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId)); List subjectIds = subjects.stream().map(QsvSubject::getId).toList(); //新题目 @@ -111,7 +119,7 @@ public class QsvActivityController { List newOptions = qsvSubject.getOptions(); List optionIds = newOptions.stream().map(QsvOption::getId).toList(); - List oldOptions = dao.query(QsvOption.class, Cnd.where(QsvOption::getSubjectId, "=", qsvSubject.getId())); + List oldOptions = dao.query(QsvOption.class, Cnd.where("subjectId", "=", qsvSubject.getId())); List oldOptionIds = oldOptions.stream().map(QsvOption::getId).toList(); @@ -127,7 +135,7 @@ public class QsvActivityController { List correctOptionIds = newOptions.stream().filter(QsvOption::getIsCorrect).map(QsvOption::getId).toList(); qsvSubject.setCorrectAnswer(correctOptionIds); } else { - dao.clear(QsvOption.class, Cnd.where(QsvOption::getSubjectId, "=", qsvSubject.getId())); + dao.clear(QsvOption.class, Cnd.where("subjectId", "=", qsvSubject.getId())); } dao.update(qsvSubject); } @@ -135,12 +143,14 @@ public class QsvActivityController { return Result.success(); } +// 查询问卷题目 @At @SaCheckPermission("qsv.activity") @ApiOperation("查询问卷题目") + @SLog(type = "qsv.activity", tag = "查询问卷题目", msg = "查询问卷题目") public Result listSubjects(@Valid String activityId) { - List subjects = dao.query(QsvSubject.class, Cnd.where(QsvSubject::getActivityId, "=", activityId).asc(QsvSubject::getSortNum)); - dao.fetchLinks(subjects, "options",Cnd.NEW().asc(QsvOption::getSortNum)); + List subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId).asc("sortNum")); + dao.fetchLinks(subjects, "options",Cnd.NEW().asc("sortNum")); return Result.success(subjects); } diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/controller/QsvQuizRankController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvQuizRankController.java similarity index 67% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/controller/QsvQuizRankController.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvQuizRankController.java index acb6bb39..1aa0e2eb 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/controller/QsvQuizRankController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvQuizRankController.java @@ -1,21 +1,16 @@ -package com.budwk.app.zhgh.activity.qsv.controller; +package com.budwk.app.zhgh.dayofficework.qsv.controller; import cn.dev33.satoken.annotation.SaCheckPermission; import com.budwk.app.base.page.Pagination; -import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; -import com.budwk.app.base.service.BaseService; -import com.budwk.app.zhgh.activity.qsv.models.QsvActivity; -import com.budwk.app.zhgh.activity.qsv.param.QsvQuizRankPageForm; -import com.budwk.app.zhgh.activity.qsv.service.QsvQuizRankService; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvActivity; +import com.budwk.app.zhgh.dayofficework.qsv.param.QsvQuizRankPageForm; +import com.budwk.app.zhgh.dayofficework.qsv.service.QsvQuizRankService; import io.swagger.annotations.ApiOperation; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; -import org.nutz.dao.Sqls; -import org.nutz.dao.sql.Sql; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.util.NutMap; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; @@ -26,6 +21,7 @@ import java.util.List; @IocBean @At("/platform/qsv/quizRank") @Ok("json:full") +@ApiOperation("答题得分统计") public class QsvQuizRankController { @Inject @@ -34,25 +30,27 @@ public class QsvQuizRankController { private QsvQuizRankService qsvQuizRankService; @At("") - @Ok("beetl:/platform/zhgh/activity/qsv/quiz/rank.html") + @Ok("beetl:/platform/zhgh/dayofficework/qsv/quiz/rank.html") @SaCheckPermission("qsv.quiz.rank") public void index() { } +// 根据年度查询问卷 @At @SaCheckPermission("qsv.quiz.rank") @ApiOperation("根据年度查询问卷") public Result listQuiz(Integer year) { - Cnd cnd = Cnd.where(QsvActivity::getCategory, "=", "QUIZ"); + Cnd cnd = Cnd.where("category", "=", "QUIZ"); cnd.andEX("YEAR(startTime)", "=", year); - cnd.desc(QsvActivity::getCreatedAt); + cnd.desc("category"); List list = dao.query(QsvActivity.class, cnd); return Result.success(list); } @At @SaCheckPermission("qsv.quiz.rank") + @ApiOperation("分页查询") public Result pageData(@Valid QsvQuizRankPageForm pageForm) { Pagination pagination = qsvQuizRankService.pageData(pageForm); return Result.success(pagination); @@ -61,7 +59,8 @@ public class QsvQuizRankController { @At @Ok("void") @SaCheckPermission("qsv.quiz.rank") - public void exportXlsx(@Valid QsvQuizRankPageForm pageForm, HttpServletResponse response) { + @ApiOperation("导出数据") + public void exportXlsx(QsvQuizRankPageForm pageForm, HttpServletResponse response) { qsvQuizRankService.exportXlsx(pageForm, response); } diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/controller/QsvSurveyController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvSurveyController.java similarity index 67% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/controller/QsvSurveyController.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvSurveyController.java index 95804734..21877938 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/controller/QsvSurveyController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvSurveyController.java @@ -1,24 +1,18 @@ -package com.budwk.app.zhgh.activity.qsv.controller; +package com.budwk.app.zhgh.dayofficework.qsv.controller; import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONObject; +import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; -import com.budwk.app.zhgh.activity.qsv.models.QsvActivity; -import com.budwk.app.zhgh.activity.qsv.models.QsvSubject; -import com.budwk.app.zhgh.activity.qsv.models.QsvUserAnswerRecord; -import com.budwk.app.zhgh.activity.qsv.param.QsvQuizRankPageForm; -import com.budwk.app.zhgh.activity.qsv.service.QsvActivityService; -import com.budwk.app.zhgh.activity.qsv.service.QsvQuizRankService; -import com.budwk.app.zhgh.activity.qsv.service.QsvSurveyService; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvUserAnswerRecord; +import com.budwk.app.zhgh.dayofficework.qsv.service.QsvActivityService; +import com.budwk.app.zhgh.dayofficework.qsv.service.QsvSurveyService; import io.swagger.annotations.ApiOperation; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; -import org.nutz.dao.Sqls; -import org.nutz.dao.sql.Sql; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.lang.util.NutMap; @@ -27,13 +21,12 @@ import org.nutz.mvc.annotation.Ok; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; -import java.util.ArrayList; import java.util.List; -import java.util.Map; @IocBean @At("/platform/qsv/survey") @Ok("json:full") +@ApiOperation("调查统计") public class QsvSurveyController { @Inject @@ -44,7 +37,7 @@ public class QsvSurveyController { private QsvSurveyService qsvSurveyService; @At("") - @Ok("beetl:/platform/zhgh/activity/qsv/survey/index.html") + @Ok("beetl:/platform/zhgh/dayofficework/qsv/survey/index.html") @SaCheckPermission("qsv.survey") public void index() { @@ -53,50 +46,67 @@ public class QsvSurveyController { @At @SaCheckPermission("qsv.survey") + @ApiOperation("分页查询") public Result pageData(@Valid PageForm pageForm, Integer year) { - Cnd cnd = Cnd.where(QsvActivity::getCategory, "=", "SURVEY"); + Cnd cnd = Cnd.where("category", "=", "SURVEY"); cnd.andEX("YEAR(startTime)", "=", year); - cnd.desc(QsvActivity::getCreatedAt); + cnd.desc("category"); Pagination pagination = qsvActivityService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), cnd); return Result.success(pagination); } @At @SaCheckPermission("qsv.survey") - @ApiOperation("报告") + @ApiOperation("生成报告") public Result report(@Valid String activityId) { List report = qsvSurveyService.report(activityId); return Result.success(report); } + + @At + @Ok("void") + @SaCheckPermission("qsv.survey") + @ApiOperation("导出报告") + public void exportReportXlsx(String activityId, HttpServletResponse response) { + qsvSurveyService.exportReportXlsx(activityId, response); + } + + @At @SaCheckPermission("qsv.survey") @ApiOperation("选项选择详情") public Result selectOptionUsers(@Valid String activityId, @Valid String subjectId, @Valid String optionId) { - List answerRecords = dao.query(QsvUserAnswerRecord.class, Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId)); + List answerRecords = dao.query(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId)); List selectOptionUsers = answerRecords.stream().filter(ext -> ObjectUtil.isNotNull(ext.getExtJson().get(subjectId, JSONObject.class)) && ext.getExtJson().get(subjectId, JSONObject.class).getJSONArray("optionIds").contains(optionId)).toList(); return Result.success(selectOptionUsers); } + @At @SaCheckPermission("qsv.survey") @ApiOperation("用户答题") - public Result userAnswer(@Valid String activityId) { - NutMap map = qsvSurveyService.userAnswer(activityId); + @SLog(type = "qsv.survey", tag = "用户答题", msg = "用户答了一题") + public Result userAnswer(PageForm pageForm, @Valid String activityId) { + NutMap map = qsvSurveyService.userAnswer(pageForm, activityId); return Result.success(map); } + @At @SaCheckPermission("qsv.survey") @ApiOperation("删除用户答题记录") + @SLog(type = "qsv.survey", tag = "删除用户答题记录", msg = "删除用户答题记录") public Result deleteUserAnswer(@Valid String id) { dao.delete(QsvUserAnswerRecord.class, id); return Result.success(); } + @At + @Ok("void") @SaCheckPermission("qsv.survey") - @ApiOperation("导出用户答题记录xlsx") + @ApiOperation("导出用户答题记录") public void exportUserAnswerXlsx(@Valid String activityId, HttpServletResponse response) { qsvSurveyService.exportUserAnswerXlsx(activityId, response); } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/dto/QsvCheckAnswerResult.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/dto/QsvCheckAnswerResult.java new file mode 100644 index 00000000..0b73f548 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/dto/QsvCheckAnswerResult.java @@ -0,0 +1,17 @@ +package com.budwk.app.zhgh.dayofficework.qsv.dto; + +import lombok.Builder; +import lombok.Data; +import lombok.experimental.Accessors; + +//答题得分计算结果 +@Data +@Accessors(chain = true) +@Builder +public class QsvCheckAnswerResult { + + private boolean isCorrect; + + private float score; + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/h5controller/H5QsvController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvController.java similarity index 59% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/h5controller/H5QsvController.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvController.java index d9f326c0..60723e07 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/h5controller/H5QsvController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvController.java @@ -1,13 +1,9 @@ -package com.budwk.app.zhgh.activity.qsv.h5controller; +package com.budwk.app.zhgh.dayofficework.qsv.h5controller; -import cn.dev33.satoken.annotation.SaCheckLogin; -import cn.dev33.satoken.annotation.SaCheckPermission; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; -import com.budwk.app.zhgh.activity.qsv.models.QsvActivity; -import com.budwk.app.zhgh.activity.qsv.service.QsvActivityService; -import io.swagger.annotations.ApiOperation; +import com.budwk.app.zhgh.dayofficework.qsv.service.QsvActivityService; import lombok.extern.slf4j.Slf4j; import org.nutz.dao.Cnd; import org.nutz.ioc.loader.annotation.Inject; @@ -27,19 +23,17 @@ public class H5QsvController { private QsvActivityService qsvActivityService; @At("") - @Ok("beetl:/platform/zhghh5/activity/qsv/index.html") - @SaCheckPermission("h5.qsv") + @Ok("beetl:/mobile/qsv/index.html") public void index() { } +// 分页查询 @At - @SaCheckPermission("h5.qsv") - @ApiOperation("分页查询") public Result pageData(@Valid PageForm pageForm, @Valid String category) { Cnd cnd = Cnd.NEW(); - cnd.andEX(QsvActivity::getCategory, "=", category); - cnd.desc(QsvActivity::getStartTime); + cnd.andEX("category", "=", category); + cnd.desc("startTime"); Pagination pagination = qsvActivityService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), cnd); return Result.success(pagination); } diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/h5controller/H5QsvQuizController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvQuizController.java similarity index 75% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/h5controller/H5QsvQuizController.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvQuizController.java index d1020f46..8f875880 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/h5controller/H5QsvQuizController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvQuizController.java @@ -1,20 +1,19 @@ -package com.budwk.app.zhgh.activity.qsv.h5controller; +package com.budwk.app.zhgh.dayofficework.qsv.h5controller; -import cn.dev33.satoken.annotation.SaCheckLogin; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONObject; -import com.budwk.app.base.exception.BaseException; +import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.result.Result; import com.budwk.app.web.commons.auth.utils.SecurityUtil; -import com.budwk.app.zhgh.activity.qsv.dto.QsvCheckAnswerResult; -import com.budwk.app.zhgh.activity.qsv.models.QsvActivity; -import com.budwk.app.zhgh.activity.qsv.models.QsvOption; -import com.budwk.app.zhgh.activity.qsv.models.QsvSubject; -import com.budwk.app.zhgh.activity.qsv.models.QsvUserAnswerRecord; -import com.budwk.app.zhgh.activity.qsv.param.QsvAnswerParam; -import com.budwk.app.zhgh.activity.qsv.service.QsvQuizService; -import com.budwk.app.zhgh.activity.qsv.service.QsvUserAnswerRecordService; +import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope; +import com.budwk.app.zhgh.dayofficework.qsv.dto.QsvCheckAnswerResult; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvActivity; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvSubject; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvUserAnswerRecord; +import com.budwk.app.zhgh.dayofficework.qsv.param.QsvAnswerParam; +import com.budwk.app.zhgh.dayofficework.qsv.service.QsvQuizService; +import com.budwk.app.zhgh.dayofficework.qsv.service.QsvUserAnswerRecordService; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.nutz.dao.Cnd; @@ -45,24 +44,28 @@ public class H5QsvQuizController { private QsvQuizService qsvQuizService; @At("") - @Ok("beetl:/platform/zhghh5/activity/qsv/quiz/index.html") - @SaCheckLogin + @Ok("beetl:/mobile/qsv/quiz/index.html") public void index() { } @At - @Ok("beetl:/platform/zhghh5/activity/qsv/quiz/result.html") - @SaCheckLogin + @Ok("beetl:/mobile/qsv/quiz/result.html") public void result() { } +// 题目列表 @At - @SaCheckLogin - @ApiOperation("题目列表") public Result subjects(@Valid String activityId) { QsvActivity activity = dao.fetch(QsvActivity.class, activityId); + + int count = dao.count(ActivityUserScope.class, Cnd.where("groupId", "=", activity.getGroupId()) + .and("userId", "=", SecurityUtil.getUserId())); + if (count != 1) { + return Result.error("您无需参加此次答题,感谢您的关注!"); + } + String mode = activity.getMode(); //能否重复答题 Boolean repeatable = activity.getRepeatable(); @@ -72,52 +75,54 @@ public class H5QsvQuizController { Integer maxAttempts = activity.getMaxAttempts(); //题目显示模式 String displayMode = activity.getDisplayMode(); + // 重复答题,显示提示 + Boolean repeatTips = false; //最终返回的题目数据 List resultSubjects = new ArrayList<>(); String answerRecordId = null; //查询用户的答题记录 - List answerRecords = dao.query(QsvUserAnswerRecord.class, Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId) - .and(QsvUserAnswerRecord::getUserId, "=", SecurityUtil.getUserId())); + List answerRecords = dao.query(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId) + .and("userId", "=", SecurityUtil.getUserId())); - if (activity.getEndTime().after(new Date())) { + if (activity.getEndTime().before(new Date())) { //已结束 查询最新一次的答题记录 Optional lastRecordOptional = answerRecords.stream().max(Comparator.comparing(QsvUserAnswerRecord::getAnswerTime)); if (lastRecordOptional.isPresent()) { List subjectIds = lastRecordOptional.get().getSubjectIds(); - Cnd cnd = Cnd.where(QsvSubject::getId, "in", subjectIds); + Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); resultSubjects = dao.query(QsvSubject.class, cnd); answerRecordId = lastRecordOptional.get().getId(); }else{ //没生成过 那就看全部的题目 - List subjects = dao.query(QsvSubject.class, Cnd.where(QsvSubject::getActivityId, "=", activityId)); + List subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId)); QsvUserAnswerRecord answerRecord = qsvUserAnswerRecordService.insertRecord(activityId, subjects.stream().map(QsvSubject::getId).collect(Collectors.toList())); answerRecordId = answerRecord.getId(); List subjectIds = answerRecord.getSubjectIds(); - Cnd cnd = Cnd.where(QsvSubject::getId, "in", subjectIds); + Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); resultSubjects = dao.query(QsvSubject.class, cnd); } } else { - if (mode.equals("REGULAR")) { + if ("REGULAR".equals(mode)) { if (ObjectUtil.isEmpty(answerRecords)) { //首次进来生成答题记录 - if (displayMode.equals("ALL")) { - resultSubjects = dao.query(QsvSubject.class, Cnd.where(QsvSubject::getActivityId, "=", activityId)); + if ("ALL".equals(displayMode)) { + resultSubjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId).asc("sortNum")); answerRecordId = qsvUserAnswerRecordService.insertRecord(activityId, resultSubjects.stream().map(QsvSubject::getId).collect(Collectors.toList())).getId(); - } else if (displayMode.equals("RANDOM")) { + } else if ("RANDOM".equals(displayMode)) { //单次随机抽取题目数量 Integer randomCount = activity.getRandomCount(); - List subjects = dao.query(QsvSubject.class, Cnd.where(QsvSubject::getActivityId, "=", activityId)); + List subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId)); if (subjects.size() < randomCount) { - throw new BaseException("题目数不够,无法生成题目"); + throw new RuntimeException("题目数不够,无法生成题目"); } //从subjects里随机抽取randomCount个题目 @@ -127,60 +132,70 @@ public class H5QsvQuizController { answerRecordId = answerRecord.getId(); List subjectIds = answerRecord.getSubjectIds(); - Cnd cnd = Cnd.where(QsvSubject::getId, "in", subjectIds); + Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); resultSubjects = dao.query(QsvSubject.class, cnd); } } else { - if (displayMode.equals("ALL")) { + if ("ALL".equals(displayMode)) { //判断能否重复答题 如果可重复要根据次数判断是否再次生成记录 不能重复直接返回最新的一次记录 if (repeatable) { //已回答次数 if (answerRecords.size() < maxAttempts) { //生成答题记录 - List subjects = dao.query(QsvSubject.class, Cnd.where(QsvSubject::getActivityId, "=", activityId)); - answerRecordId = qsvUserAnswerRecordService.insertRecord(activityId, subjects.stream().map(QsvSubject::getId).collect(Collectors.toList())).getId(); - QsvUserAnswerRecord answerRecord = dao.fetch(QsvUserAnswerRecord.class, answerRecordId); + QsvUserAnswerRecord fetch = dao.fetch(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId) + .and("userId", "=", SecurityUtil.getUserId()).and("isFinish", "=", false) + .desc("randomNumber")); + List subjectIds = new ArrayList<>(); + if (fetch == null) { + List subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId).asc("sortNum")); + answerRecordId = qsvUserAnswerRecordService.insertRecord(activityId, subjects.stream().map(QsvSubject::getId).collect(Collectors.toList())).getId(); + QsvUserAnswerRecord answerRecord = dao.fetch(QsvUserAnswerRecord.class, answerRecordId); + subjectIds = answerRecord.getSubjectIds(); - List subjectIds = answerRecord.getSubjectIds(); - Cnd cnd = Cnd.where(QsvSubject::getId, "in", subjectIds); + } else { + subjectIds = fetch.getSubjectIds(); + answerRecordId = fetch.getId(); + } + Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); resultSubjects = dao.query(QsvSubject.class, cnd); + repeatTips = true; } else { //已达到最大次数 返回最新一次记录 Optional maxAnswerRecordOptional = answerRecords.stream().max(Comparator.comparingLong(QsvUserAnswerRecord::getRandomNumber)); if (maxAnswerRecordOptional.isPresent()) { List subjectIds = maxAnswerRecordOptional.get().getSubjectIds(); - Cnd cnd = Cnd.where(QsvSubject::getId, "in", subjectIds); + Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); resultSubjects = dao.query(QsvSubject.class, cnd); answerRecordId = maxAnswerRecordOptional.get().getId(); } else { - throw new BaseException("业务异常"); + throw new RuntimeException("业务异常"); } } } else { Optional maxAnswerRecordOptional = answerRecords.stream().max(Comparator.comparingLong(QsvUserAnswerRecord::getRandomNumber)); if (maxAnswerRecordOptional.isPresent()) { List subjectIds = maxAnswerRecordOptional.get().getSubjectIds(); - Cnd cnd = Cnd.where(QsvSubject::getId, "in", subjectIds); + Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); resultSubjects = dao.query(QsvSubject.class, cnd); answerRecordId = maxAnswerRecordOptional.get().getId(); } else { - throw new BaseException("业务异常"); + throw new RuntimeException("业务异常"); } } - } else if (displayMode.equals("RANDOM")) { + } else if ("RANDOM".equals(displayMode)) { //判断是否有未答完的记录 Optional notFinishRecordOptional = answerRecords.stream().filter(r -> !r.getIsFinish()).findFirst(); if (notFinishRecordOptional.isPresent()) { List subjectIds = notFinishRecordOptional.get().getSubjectIds(); - Cnd cnd = Cnd.where(QsvSubject::getId, "in", subjectIds); + Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); resultSubjects = dao.query(QsvSubject.class, cnd); @@ -202,11 +217,11 @@ public class H5QsvQuizController { if (answerRecords.size() < totalRandom) { //进行下一次抽取 List subjectIds = answerRecords.stream().map(QsvUserAnswerRecord::getSubjectIds).flatMap(Collection::stream).toList(); - List subjects = dao.query(QsvSubject.class, Cnd.where(QsvSubject::getActivityId, "=", activityId) - .and(QsvSubject::getId, "not in", subjectIds)); + List subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId) + .and("id", "not in", subjectIds).asc("sortNum")); if (subjects.size() < randomCount) { - throw new BaseException("题目数不够,无法生成题目"); + throw new RuntimeException("题目数不够,无法生成题目"); } //从subjects里随机抽取randomCount个题目 @@ -218,13 +233,13 @@ public class H5QsvQuizController { Optional maxAnswerRecordOptional = answerRecords.stream().max(Comparator.comparingLong(QsvUserAnswerRecord::getRandomNumber)); if (maxAnswerRecordOptional.isPresent()) { List subjectIds = maxAnswerRecordOptional.get().getSubjectIds(); - Cnd cnd = Cnd.where(QsvSubject::getId, "in", subjectIds); + Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); resultSubjects = dao.query(QsvSubject.class, cnd); answerRecordId = maxAnswerRecordOptional.get().getId(); } else { - throw new BaseException("业务异常"); + throw new RuntimeException("业务异常"); } } // }else{ @@ -233,13 +248,13 @@ public class H5QsvQuizController { } } } - } else if (mode.equals("SCHEDULED")) { + } else if ("SCHEDULED".equals(mode)) { //定时定题 //查询今天的题目 - List todayRecords = dao.query(QsvUserAnswerRecord.class, Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId) - .and(QsvUserAnswerRecord::getUserId, "=", SecurityUtil.getUserId()) - .and(QsvUserAnswerRecord::getAttemptDate, "=", DateUtil.today()) + List todayRecords = dao.query(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId) + .and("userId", "=", SecurityUtil.getUserId()) + .and("attemptDate", "=", DateUtil.today()) ); if (ObjectUtil.isNotEmpty(todayRecords)) { @@ -248,13 +263,13 @@ public class H5QsvQuizController { //如果今天已生成的题目已答完并且还可以重复答 if (todayAllFinish && todayRecords.size() < maxAttempts) { //生成今天的记录 - List subjects = dao.query(QsvSubject.class, Cnd.where(QsvSubject::getActivityId, "=", activityId) - .and(QsvSubject::getDisplayDate, "=", DateUtil.today())); + List subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId) + .and("displayDate", "=", DateUtil.today()).asc("sortNum")); QsvUserAnswerRecord answerRecord = qsvUserAnswerRecordService.insertRecord(activityId, subjects.stream().map(QsvSubject::getId).collect(Collectors.toList())); answerRecordId = answerRecord.getId(); List subjectIds = answerRecord.getSubjectIds(); - Cnd cnd = Cnd.where(QsvSubject::getId, "in", subjectIds); + Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); resultSubjects = dao.query(QsvSubject.class, cnd); @@ -265,23 +280,23 @@ public class H5QsvQuizController { answerRecordId = maxTodayRecord.get().getId(); List subjectIds = maxTodayRecord.get().getSubjectIds(); - Cnd cnd = Cnd.where(QsvSubject::getId, "in", subjectIds); + Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); resultSubjects = dao.query(QsvSubject.class, cnd); } else { - throw new BaseException("业务异常"); + throw new RuntimeException("业务异常"); } } } else { //生成今天的记录 - List subjects = dao.query(QsvSubject.class, Cnd.where(QsvSubject::getActivityId, "=", activityId) - .and(QsvSubject::getDisplayDate, "=", DateUtil.today())); + List subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId) + .and("displayDate", "=", DateUtil.today()).asc("sortNum")); QsvUserAnswerRecord answerRecord = qsvUserAnswerRecordService.insertRecord(activityId, subjects.stream().map(QsvSubject::getId).collect(Collectors.toList())); answerRecordId = answerRecord.getId(); List subjectIds = answerRecord.getSubjectIds(); - Cnd cnd = Cnd.where(QsvSubject::getId, "in", subjectIds); + Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); resultSubjects = dao.query(QsvSubject.class, cnd); @@ -289,25 +304,26 @@ public class H5QsvQuizController { } } - dao.fetchLinks(resultSubjects, "options", Cnd.NEW().asc(QsvOption::getSortNum)); + dao.fetchLinks(resultSubjects, "options", Cnd.NEW().asc("sortNum")); resultSubjects.forEach(v -> v.setUserSelectOptionIds(new ArrayList<>())); - NutMap result = NutMap.NEW().addv("subjects", resultSubjects).addv("answerRecordId", answerRecordId).addv("activity", activity); + NutMap result = NutMap.NEW().addv("subjects", resultSubjects).addv("answerRecordId", answerRecordId) + .addv("activity", activity).addv("repeatTips", repeatTips); return Result.success(result); } +// 答题记录 @At - @SaCheckLogin - @ApiOperation("答题记录") public Result answerRecord(@Valid String answerRecordId) { QsvUserAnswerRecord record = dao.fetch(QsvUserAnswerRecord.class, answerRecordId); return Result.success(record); } +// 提交答题 @At - @SaCheckLogin @ApiOperation("提交答题") + @SLog(type = "qsv.quiz", tag = "提交答题", msg = "问卷调查提交答题") public Result submitAnswer(@Valid @Param("answer") QsvAnswerParam qsvAnswerParam) { QsvUserAnswerRecord answerRecord = dao.fetch(QsvUserAnswerRecord.class, qsvAnswerParam.getAnswerRecordId()); JSONObject extJson = answerRecord.getExtJson(); @@ -345,25 +361,24 @@ public class H5QsvQuizController { } @At - @SaCheckLogin public Result historyScore(@Valid String activityId) { - List answerRecords = dao.query(QsvUserAnswerRecord.class, Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId).and(QsvUserAnswerRecord::getUserId, "=", SecurityUtil.getUserId()).desc(QsvUserAnswerRecord::getCreatedAt)); + List answerRecords = dao.query(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId) + .and("userId", "=", SecurityUtil.getUserId()).desc("createdAt")); return Result.success(answerRecords); } @At - @SaCheckLogin @ApiOperation("答题记录(结果页展示)") public Result answerResult(@Valid String answerRecordId) { QsvUserAnswerRecord answerRecord = dao.fetch(QsvUserAnswerRecord.class, answerRecordId); List subjectIds = answerRecord.getSubjectIds(); - Cnd cnd = Cnd.where(QsvSubject::getId, "in", subjectIds); + Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); List subjects = dao.query(QsvSubject.class, cnd); - dao.fetchLinks(subjects, "options", Cnd.NEW().asc(QsvOption::getSortNum)); + dao.fetchLinks(subjects, "options", Cnd.NEW().asc("sortNum")); subjects.forEach(v -> v.setUserSelectOptionIds(new ArrayList<>())); diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/h5controller/H5QsvSurveyController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvSurveyController.java similarity index 69% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/h5controller/H5QsvSurveyController.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvSurveyController.java index d1176508..03cbe753 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/h5controller/H5QsvSurveyController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvSurveyController.java @@ -1,16 +1,15 @@ -package com.budwk.app.zhgh.activity.qsv.h5controller; +package com.budwk.app.zhgh.dayofficework.qsv.h5controller; -import cn.dev33.satoken.annotation.SaCheckLogin; -import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONObject; import com.budwk.app.base.result.Result; import com.budwk.app.web.commons.auth.utils.SecurityUtil; -import com.budwk.app.zhgh.activity.qsv.models.QsvActivity; -import com.budwk.app.zhgh.activity.qsv.models.QsvSubject; -import com.budwk.app.zhgh.activity.qsv.models.QsvUserAnswerRecord; -import com.budwk.app.zhgh.activity.qsv.param.QsvAnswerParam; -import com.budwk.app.zhgh.activity.qsv.service.QsvUserAnswerRecordService; +import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvActivity; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvSubject; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvUserAnswerRecord; +import com.budwk.app.zhgh.dayofficework.qsv.param.QsvAnswerParam; +import com.budwk.app.zhgh.dayofficework.qsv.service.QsvUserAnswerRecordService; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; import org.nutz.ioc.loader.annotation.Inject; @@ -36,32 +35,37 @@ public class H5QsvSurveyController { private QsvUserAnswerRecordService qsvUserAnswerRecordService; @At("") - @Ok("beetl:/platform/zhghh5/activity/qsv/survey/index.html") - @SaCheckLogin + @Ok("beetl:/mobile/qsv/survey/index.html") public void index() { } @At - @SaCheckLogin - public Result subjects(@Valid String activityId) { + public Result subjects(String activityId) { QsvActivity activity = dao.fetch(QsvActivity.class, activityId); + + int count = dao.count(ActivityUserScope.class, Cnd.where("groupId", "=", activity.getGroupId()) + .and("userId", "=", SecurityUtil.getUserId())); + if (count != 1) { + return Result.error("您无需参加此次投票,感谢您的关注!"); + } + String answerRecordId = null; - QsvUserAnswerRecord answerRecord = dao.fetch(QsvUserAnswerRecord.class, Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId).and(QsvUserAnswerRecord::getUserId, "=", SecurityUtil.getUserId()) - .and(QsvUserAnswerRecord::getUserId, "=", SecurityUtil.getUserId())); + QsvUserAnswerRecord answerRecord = dao.fetch(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId) + .and("userId", "=", SecurityUtil.getUserId())); if (answerRecord == null) { - List subjects = dao.query(QsvSubject.class, Cnd.where(QsvSubject::getActivityId, "=", activityId)); + List subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId).asc("sortNum")); qsvUserAnswerRecordService.insertRecord(activityId, subjects.stream().map(QsvSubject::getId).toList()); } QsvUserAnswerRecord answerRecord2 = dao.fetch(QsvUserAnswerRecord.class, - Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId) - .and(QsvUserAnswerRecord::getUserId, "=", SecurityUtil.getUserId())); + Cnd.where("activityId", "=", activityId) + .and("userId", "=", SecurityUtil.getUserId())); answerRecordId = answerRecord2.getId(); - List subjects = dao.query(QsvSubject.class, Cnd.where(QsvSubject::getId, "in", answerRecord2.getSubjectIds())); - dao.fetchLinks(subjects, "options"); + List subjects = dao.query(QsvSubject.class, Cnd.where("id", "in", answerRecord2.getSubjectIds()).asc("sortNum")); + dao.fetchLinks(subjects, "options", Cnd.NEW().asc("sortNum")); for (QsvSubject subject : subjects) { if (subject.getUserSelectOptionIds() == null) { @@ -74,14 +78,12 @@ public class H5QsvSurveyController { } @At - @SaCheckLogin public Result answerRecord(@Valid String answerRecordId) { QsvUserAnswerRecord record = dao.fetch(QsvUserAnswerRecord.class, answerRecordId); return Result.success(record); } @At - @SaCheckLogin public Result submitAnswer(@Valid @Param("answer") QsvAnswerParam qsvAnswerParam) { QsvUserAnswerRecord answerRecord = dao.fetch(QsvUserAnswerRecord.class, qsvAnswerParam.getAnswerRecordId()); JSONObject extJson = answerRecord.getExtJson(); diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/models/QsvActivity.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/models/QsvActivity.java similarity index 79% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/models/QsvActivity.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/models/QsvActivity.java index 7a0fb72c..35541473 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/models/QsvActivity.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/models/QsvActivity.java @@ -1,8 +1,6 @@ -package com.budwk.app.zhgh.activity.qsv.models; +package com.budwk.app.zhgh.dayofficework.qsv.models; import com.budwk.app.base.model.BaseModel; -import com.budwk.app.sys.models.Sys_home_activity; -import com.budwk.app.sys.services.SysHomeConvert; import lombok.Data; import lombok.EqualsAndHashCode; import org.nutz.dao.entity.annotation.*; @@ -11,12 +9,12 @@ import org.nutz.dao.interceptor.annotation.PrevInsert; import java.io.Serializable; import java.util.Date; -@Data @EqualsAndHashCode(callSuper = true) +@Data @Table("qsv_activity") @TableMeta("{'mysql-charset':'utf8mb4'}") @Comment("问卷调查投票活动表") -public class QsvActivity extends BaseModel implements Serializable, SysHomeConvert { +public class QsvActivity extends BaseModel implements Serializable { @Name @Comment("ID") @ColDefine(type = ColType.VARCHAR, width = 32) @@ -109,18 +107,4 @@ public class QsvActivity extends BaseModel implements Serializable, SysHomeConve @Comment("封面图片") @ColDefine(type = ColType.VARCHAR, width = 255) private String cover; - - @Override - public Sys_home_activity covertToSysHomeActivity() { - Sys_home_activity sysHomeActivity = new Sys_home_activity(); - sysHomeActivity.setId(this.getId()); - sysHomeActivity.setName(this.getTitle()); - sysHomeActivity.setCover(this.getCover()); - sysHomeActivity.setH5Url("/platform/h5/qsv"); - sysHomeActivity.setStartDate(this.getStartTime()); - sysHomeActivity.setEndDate(this.getEndTime()); - sysHomeActivity.setAllowUserGroupId(this.getGroupId()); - sysHomeActivity.setEnable(true); - return sysHomeActivity; - } } diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/models/QsvOption.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/models/QsvOption.java similarity index 74% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/models/QsvOption.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/models/QsvOption.java index 09ab637a..9c693558 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/models/QsvOption.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/models/QsvOption.java @@ -1,4 +1,4 @@ -package com.budwk.app.zhgh.activity.qsv.models; +package com.budwk.app.zhgh.dayofficework.qsv.models; import com.budwk.app.base.model.BaseModel; import lombok.Data; @@ -6,12 +6,14 @@ import lombok.EqualsAndHashCode; import org.nutz.dao.entity.annotation.*; import org.nutz.dao.interceptor.annotation.PrevInsert; -@Data +import java.io.Serializable; + @EqualsAndHashCode(callSuper = true) +@Data @Table("qsv_option") @TableMeta("{'mysql-charset':'utf8mb4'}") @Comment("问卷调查投票选项表") -public class QsvOption extends BaseModel { +public class QsvOption extends BaseModel implements Serializable { @Name @Comment("ID") @@ -39,6 +41,16 @@ public class QsvOption extends BaseModel { @ColDefine(type = ColType.VARCHAR, width = 255) private String imgUrl; + @Column + @Comment("链接地址") + @ColDefine(type = ColType.VARCHAR, width = 255) + private String link; + + @Column + @Comment("详情") + @ColDefine(customType = "longtext") + private String description; + @Column @Comment("排序") @ColDefine(type = ColType.INT) diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/models/QsvSubject.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/models/QsvSubject.java similarity index 86% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/models/QsvSubject.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/models/QsvSubject.java index 1bdc8ec4..b72f5bc6 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/models/QsvSubject.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/models/QsvSubject.java @@ -1,4 +1,4 @@ -package com.budwk.app.zhgh.activity.qsv.models; +package com.budwk.app.zhgh.dayofficework.qsv.models; import com.budwk.app.base.model.BaseModel; import lombok.Data; @@ -6,6 +6,7 @@ import lombok.EqualsAndHashCode; import org.nutz.dao.entity.annotation.*; import org.nutz.dao.interceptor.annotation.PrevInsert; +import java.io.Serializable; import java.util.Date; import java.util.List; @@ -14,7 +15,7 @@ import java.util.List; @Table("qsv_subject") @TableMeta("{'mysql-charset':'utf8mb4'}") @Comment("问卷调查投票题目表") -public class QsvSubject extends BaseModel { +public class QsvSubject extends BaseModel implements Serializable { @Name @Comment("ID") @@ -52,6 +53,11 @@ public class QsvSubject extends BaseModel { @ColDefine(type = ColType.DATE) private Date displayDate; + @Column + @Comment("多选,最多选几个") + @ColDefine(type = ColType.INT, width = 1) + private Integer maxMulti; + @Column @Comment("排序") @ColDefine(type = ColType.INT, width = 1) diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/models/QsvUserAnswerRecord.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/models/QsvUserAnswerRecord.java similarity index 95% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/models/QsvUserAnswerRecord.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/models/QsvUserAnswerRecord.java index 27d2b3c4..26502f9c 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/models/QsvUserAnswerRecord.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/models/QsvUserAnswerRecord.java @@ -1,4 +1,4 @@ -package com.budwk.app.zhgh.activity.qsv.models; +package com.budwk.app.zhgh.dayofficework.qsv.models; import cn.hutool.json.JSONObject; import com.budwk.app.base.model.BaseModel; @@ -7,6 +7,7 @@ import lombok.EqualsAndHashCode; import org.nutz.dao.entity.annotation.*; import org.nutz.dao.interceptor.annotation.PrevInsert; +import java.io.Serializable; import java.util.Date; import java.util.List; @@ -15,7 +16,7 @@ import java.util.List; @Table("qsv_user_answer_record") @TableMeta("{'mysql-charset':'utf8mb4'}") @Comment("问卷调查投票记录表") -public class QsvUserAnswerRecord extends BaseModel { +public class QsvUserAnswerRecord extends BaseModel implements Serializable { @Name @Comment("ID") diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/param/QsvAnswerParam.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/param/QsvAnswerParam.java similarity index 54% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/param/QsvAnswerParam.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/param/QsvAnswerParam.java index ea00d338..c614794a 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/param/QsvAnswerParam.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/param/QsvAnswerParam.java @@ -1,25 +1,19 @@ -package com.budwk.app.zhgh.activity.qsv.param; +package com.budwk.app.zhgh.dayofficework.qsv.param; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.List; @Data -@ApiModel(value = "答题参数") +//答题参数 public class QsvAnswerParam { - @ApiModelProperty("答题活动") private String activityId; - @ApiModelProperty("答题记录") private String answerRecordId; - @ApiModelProperty("答题题目") private List subjects; - @ApiModelProperty("答题用时") private Integer answerTime; @Data diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/param/QsvQuizRankPageForm.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/param/QsvQuizRankPageForm.java similarity index 50% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/param/QsvQuizRankPageForm.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/param/QsvQuizRankPageForm.java index 37cf28b4..f655918a 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/param/QsvQuizRankPageForm.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/param/QsvQuizRankPageForm.java @@ -1,8 +1,6 @@ -package com.budwk.app.zhgh.activity.qsv.param; +package com.budwk.app.zhgh.dayofficework.qsv.param; import com.budwk.app.base.param.PageForm; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -10,19 +8,15 @@ import java.util.Date; @EqualsAndHashCode(callSuper = true) @Data -@ApiModel("问卷排名得分分页查询参数") +//问卷排名得分分页查询参数 public class QsvQuizRankPageForm extends PageForm { - @ApiModelProperty("活动ID") private String activityId; - @ApiModelProperty("分工会ID") private String unionId; - @ApiModelProperty("单位ID") private String unitId; - @ApiModelProperty("答题日期") private Date attemptDate; } diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/QsvActivityService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvActivityService.java similarity index 50% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/service/QsvActivityService.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvActivityService.java index d9675190..27278a2b 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/QsvActivityService.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvActivityService.java @@ -1,7 +1,8 @@ -package com.budwk.app.zhgh.activity.qsv.service; +package com.budwk.app.zhgh.dayofficework.qsv.service; + import com.budwk.app.base.service.BaseService; -import com.budwk.app.zhgh.activity.qsv.models.QsvActivity; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvActivity; public interface QsvActivityService extends BaseService { } diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/QsvQuizRankService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvQuizRankService.java similarity index 60% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/service/QsvQuizRankService.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvQuizRankService.java index f50b1603..b6a43c52 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/QsvQuizRankService.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvQuizRankService.java @@ -1,13 +1,13 @@ -package com.budwk.app.zhgh.activity.qsv.service; +package com.budwk.app.zhgh.dayofficework.qsv.service; + + import com.budwk.app.base.page.Pagination; import com.budwk.app.base.service.BaseService; -import com.budwk.app.zhgh.activity.qsv.models.QsvUserAnswerRecord; -import com.budwk.app.zhgh.activity.qsv.param.QsvQuizRankPageForm; -import org.nutz.lang.util.NutMap; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvUserAnswerRecord; +import com.budwk.app.zhgh.dayofficework.qsv.param.QsvQuizRankPageForm; import javax.servlet.http.HttpServletResponse; -import java.util.List; public interface QsvQuizRankService extends BaseService { diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/QsvQuizService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvQuizService.java similarity index 65% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/service/QsvQuizService.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvQuizService.java index 34843b41..8532af0f 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/QsvQuizService.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvQuizService.java @@ -1,8 +1,10 @@ -package com.budwk.app.zhgh.activity.qsv.service; +package com.budwk.app.zhgh.dayofficework.qsv.service; + + import com.budwk.app.base.service.BaseService; -import com.budwk.app.zhgh.activity.qsv.dto.QsvCheckAnswerResult; -import com.budwk.app.zhgh.activity.qsv.models.QsvUserAnswerRecord; +import com.budwk.app.zhgh.dayofficework.qsv.dto.QsvCheckAnswerResult; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvUserAnswerRecord; import java.util.List; diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/QsvSurveyService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvSurveyService.java similarity index 50% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/service/QsvSurveyService.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvSurveyService.java index 8e8196e7..eca20ddc 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/QsvSurveyService.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvSurveyService.java @@ -1,18 +1,21 @@ -package com.budwk.app.zhgh.activity.qsv.service; +package com.budwk.app.zhgh.dayofficework.qsv.service; +import com.budwk.app.base.param.PageForm; import com.budwk.app.base.service.BaseService; -import com.budwk.app.zhgh.activity.qsv.models.QsvUserAnswerRecord; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvUserAnswerRecord; import org.nutz.lang.util.NutMap; import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; import java.util.List; public interface QsvSurveyService extends BaseService { List report(String activityId); + void exportReportXlsx(String activityId, HttpServletResponse response); + void exportUserAnswerXlsx(String activityId, HttpServletResponse response); - NutMap userAnswer(String activityId); +// NutMap userAnswer(String activityId); + NutMap userAnswer(PageForm pageForm, String activityId); } diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/QsvUserAnswerRecordService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvUserAnswerRecordService.java similarity index 62% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/service/QsvUserAnswerRecordService.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvUserAnswerRecordService.java index 33504653..bb2ae45b 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/QsvUserAnswerRecordService.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvUserAnswerRecordService.java @@ -1,9 +1,10 @@ -package com.budwk.app.zhgh.activity.qsv.service; +package com.budwk.app.zhgh.dayofficework.qsv.service; + + import com.budwk.app.base.service.BaseService; -import com.budwk.app.zhgh.activity.qsv.models.QsvSubject; -import com.budwk.app.zhgh.activity.qsv.models.QsvUserAnswerRecord; -import com.budwk.app.zhgh.activity.qsv.param.QsvAnswerParam; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvUserAnswerRecord; +import com.budwk.app.zhgh.dayofficework.qsv.param.QsvAnswerParam; import java.util.List; diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/impl/QsvActivityServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvActivityServiceImpl.java similarity index 63% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/service/impl/QsvActivityServiceImpl.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvActivityServiceImpl.java index 13d643e2..1d77d6b7 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/impl/QsvActivityServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvActivityServiceImpl.java @@ -1,8 +1,8 @@ -package com.budwk.app.zhgh.activity.qsv.service.impl; +package com.budwk.app.zhgh.dayofficework.qsv.service.impl; import com.budwk.app.base.service.impl.BaseServiceImpl; -import com.budwk.app.zhgh.activity.qsv.models.QsvActivity; -import com.budwk.app.zhgh.activity.qsv.service.QsvActivityService; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvActivity; +import com.budwk.app.zhgh.dayofficework.qsv.service.QsvActivityService; import org.nutz.dao.Dao; import org.nutz.ioc.loader.annotation.IocBean; diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/impl/QsvQuizRankServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvQuizRankServiceImpl.java similarity index 91% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/service/impl/QsvQuizRankServiceImpl.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvQuizRankServiceImpl.java index 2b8585e9..3cc084a3 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/impl/QsvQuizRankServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvQuizRankServiceImpl.java @@ -1,18 +1,17 @@ -package com.budwk.app.zhgh.activity.qsv.service.impl; +package com.budwk.app.zhgh.dayofficework.qsv.service.impl; import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.entity.ExportParams; import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; import cn.hutool.core.util.StrUtil; -import com.budwk.app.base.exception.BaseException; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.service.impl.BaseServiceImpl; import com.budwk.app.base.utils.CommonDownloadUtil; -import com.budwk.app.zhgh.activity.qsv.models.QsvActivity; -import com.budwk.app.zhgh.activity.qsv.models.QsvUserAnswerRecord; -import com.budwk.app.zhgh.activity.qsv.param.QsvQuizRankPageForm; -import com.budwk.app.zhgh.activity.qsv.service.QsvQuizRankService; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvActivity; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvUserAnswerRecord; +import com.budwk.app.zhgh.dayofficework.qsv.param.QsvQuizRankPageForm; +import com.budwk.app.zhgh.dayofficework.qsv.service.QsvQuizRankService; import org.apache.poi.ss.usermodel.Workbook; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; @@ -24,7 +23,6 @@ import org.nutz.lang.util.NutMap; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; -import java.util.Date; import java.util.List; @IocBean(args = {"refer:dao"}) @@ -60,7 +58,7 @@ public class QsvQuizRankServiceImpl extends BaseServiceImpl QsvActivity activity = dao().fetch(QsvActivity.class, activityId); if (activity == null) { - throw new BaseException("活动不存在: " + activityId); + throw new RuntimeException("活动不存在: " + activityId); } String mode = activity.getMode(); @@ -95,9 +93,9 @@ public class QsvQuizRankServiceImpl extends BaseServiceImpl t1.userId, t1.userName, t1.loginName, + u.sex, t1.unitName, t1.unionName, - t1.sex, u.mobile, t1.totalScore, t1.attemptDate, diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/impl/QsvQuizServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvQuizServiceImpl.java similarity index 76% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/service/impl/QsvQuizServiceImpl.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvQuizServiceImpl.java index 783e0969..b6f5b676 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/impl/QsvQuizServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvQuizServiceImpl.java @@ -1,11 +1,11 @@ -package com.budwk.app.zhgh.activity.qsv.service.impl; +package com.budwk.app.zhgh.dayofficework.qsv.service.impl; import cn.hutool.core.util.ObjectUtil; import com.budwk.app.base.service.impl.BaseServiceImpl; -import com.budwk.app.zhgh.activity.qsv.dto.QsvCheckAnswerResult; -import com.budwk.app.zhgh.activity.qsv.models.QsvSubject; -import com.budwk.app.zhgh.activity.qsv.models.QsvUserAnswerRecord; -import com.budwk.app.zhgh.activity.qsv.service.QsvQuizService; +import com.budwk.app.zhgh.dayofficework.qsv.dto.QsvCheckAnswerResult; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvSubject; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvUserAnswerRecord; +import com.budwk.app.zhgh.dayofficework.qsv.service.QsvQuizService; import org.nutz.dao.Dao; import org.nutz.ioc.loader.annotation.IocBean; diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/impl/QsvSurveyServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvSurveyServiceImpl.java similarity index 66% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/service/impl/QsvSurveyServiceImpl.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvSurveyServiceImpl.java index 6f273596..70bc7e95 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/impl/QsvSurveyServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvSurveyServiceImpl.java @@ -1,22 +1,25 @@ -package com.budwk.app.zhgh.activity.qsv.service.impl; +package com.budwk.app.zhgh.dayofficework.qsv.service.impl; import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.entity.ExportParams; import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.afterturn.easypoi.excel.export.ExcelExportService; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONArray; import cn.hutool.json.JSONObject; -import com.budwk.app.base.exception.BaseException; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; import com.budwk.app.base.service.impl.BaseServiceImpl; import com.budwk.app.base.utils.CommonDownloadUtil; -import com.budwk.app.zhgh.activity.qsv.models.QsvActivity; -import com.budwk.app.zhgh.activity.qsv.models.QsvOption; -import com.budwk.app.zhgh.activity.qsv.models.QsvSubject; -import com.budwk.app.zhgh.activity.qsv.models.QsvUserAnswerRecord; -import com.budwk.app.zhgh.activity.qsv.service.QsvSurveyService; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvActivity; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvOption; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvSubject; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvUserAnswerRecord; +import com.budwk.app.zhgh.dayofficework.qsv.service.QsvSurveyService; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; import org.nutz.dao.Sqls; @@ -47,7 +50,8 @@ public class QsvSurveyServiceImpl extends BaseServiceImpl i try { // 查询用户答题记录 - List answerRecords = dao().query(QsvUserAnswerRecord.class, Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId)); + List answerRecords = dao().query(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId) + .and("isFinish", "=", true)); // 将答题记录的扩展JSON转换为JSONObject列表 List answerExtList = answerRecords.stream().map(QsvUserAnswerRecord::getExtJson).toList(); @@ -57,7 +61,7 @@ public class QsvSurveyServiceImpl extends BaseServiceImpl i List subjectIds = subjects.stream().map(v -> v.getString("id")).toList(); // 查询题目选项列表 - List options = dao().query(QsvOption.class, Cnd.where("subjectId", "in", subjectIds).asc(QsvOption::getSortNum)); + List options = dao().query(QsvOption.class, Cnd.where("subjectId", "in", subjectIds).asc("sortNum")); // 按题目ID分组选项 Map> optionsGroup = options.stream().collect(Collectors.groupingBy(QsvOption::getSubjectId)); @@ -79,6 +83,10 @@ public class QsvSurveyServiceImpl extends BaseServiceImpl i } // 处理单选类型题目 处理多选类型题目 else if ("radio".equals(subjectType) || "checkbox".equals(subjectType)) { + long selectTotal = answerExtList.stream() + .filter(ext -> ext.containsKey(subject.getString("id"))) + .count(); + subjectOptions.forEach(subjectOption -> { long selectCount = answerExtList.stream() .filter(ext -> @@ -89,15 +97,22 @@ public class QsvSurveyServiceImpl extends BaseServiceImpl i && jsonObject.getJSONArray("optionIds").contains(subjectOption.getString("id")); }) .count(); + long round = Math.round((double) selectCount / selectTotal * 100); + subjectOption.put("selectPercent", round + "%"); subjectOption.put("selectCount", selectCount); }); - long selectTotal = answerExtList.stream() - .filter(ext -> ext.containsKey(subject.getString("id"))) - .count(); + subjectOptions.sort((o1, o2) -> { + int count1 = o1.getInt("selectCount"); + int count2 = o2.getInt("selectCount"); + if (count1 == count2) { + return Integer.compare(o1.getInt("sortNum"), o2.getInt("sortNum")); + } + return Integer.compare(count2, count1); + }); + subject.put("selectTotal", selectTotal); } - // 添加选项到题目中 subject.addv("options", subjectOptions); } @@ -105,10 +120,36 @@ public class QsvSurveyServiceImpl extends BaseServiceImpl i return subjects; } catch (Exception e) { log.error("报告生成失败", e); - throw new BaseException("报告生成失败", e); + throw new RuntimeException("报告生成失败", e); } } + + @Override + public void exportReportXlsx(String activityId, HttpServletResponse response) { + List report = report(activityId); + + List exportEntities = new ArrayList<>(); + exportEntities.add(new ExcelExportEntity("选项名称", "text", 20)); + exportEntities.add(new ExcelExportEntity("选择人数", "selectCount", 20)); + exportEntities.add(new ExcelExportEntity("选择比例", "selectPercent", 20)); + + Map> listMap = report.stream().collect(Collectors.groupingBy(v -> v.getString("id"))); + Workbook workbook = new XSSFWorkbook(); + listMap.forEach((k, v) -> { + NutMap nutMap = v.get(0); + ExcelExportService service = new ExcelExportService(); + ExportParams exportParams = new ExportParams(); + exportParams.setTitle(nutMap.getString("title")); + exportParams.setSheetName(nutMap.getString("title")); + exportParams.setType(ExcelType.XSSF); + service.createSheetForMap(workbook, exportParams, exportEntities, nutMap.getList("options", NutMap.class)); + }); + + CommonDownloadUtil.download("调研分析.xlsx", workbook, response); + + } + @Override public void exportUserAnswerXlsx(String activityId, HttpServletResponse response) { // 检查活动ID是否为空 @@ -124,19 +165,20 @@ public class QsvSurveyServiceImpl extends BaseServiceImpl i } // 查询用户答题记录 - List answerRecords = dao().query(QsvUserAnswerRecord.class, Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId)); + List answerRecords = dao().query(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId) + .and("isFinish", "=", true)); // 将答题记录的扩展JSON转换为JSONObject列表 List answerExtList = answerRecords.stream().map(QsvUserAnswerRecord::getExtJson).toList(); // 查询活动题目列表 - List subjects = dao().query(QsvSubject.class, Cnd.where(QsvSubject::getActivityId, "=", activityId)); + List subjects = dao().query(QsvSubject.class, Cnd.where("activityId", "=", activityId)); // 将题目列表转换为Map Map subjectMap = subjects.stream().collect(Collectors.toMap(QsvSubject::getId, v -> v)); // 获取题目ID列表 List subjectIds = subjects.stream().map(QsvSubject::getId).toList(); // 查询题目选项列表 - List options = dao().query(QsvOption.class, Cnd.where("subjectId", "in", subjectIds).asc(QsvOption::getSortNum)); + List options = dao().query(QsvOption.class, Cnd.where("subjectId", "in", subjectIds).asc("sortNum")); // 将选项列表转换为Map Map optionMap = options.stream().collect(Collectors.toMap(QsvOption::getId, v -> v)); @@ -154,39 +196,74 @@ public class QsvSurveyServiceImpl extends BaseServiceImpl i } } catch (Exception e) { log.error("导出Excel失败", e); - throw new BaseException("导出Excel失败", e); + throw new RuntimeException("导出Excel失败", e); } } @Override - public NutMap userAnswer(String activityId) { + public NutMap userAnswer(PageForm pageForm, String activityId) { // 检查活动ID是否为空 if (activityId == null || activityId.isEmpty()) { throw new IllegalArgumentException("活动ID不能为空"); } try { + Cnd cnd = Cnd.NEW(); + cnd.and("activityId", "=", activityId); + cnd.and("isFinish", "=", true); +// Cnd.where("activityId", "=", activityId) +// .and("isFinish", "=", true) + Pagination pagination = listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), cnd); + List answerRecords = pagination.getList(); + // 查询用户答题记录 - List answerRecords = dao().query(QsvUserAnswerRecord.class, Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId)); +// List answerRecords = dao().query(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId) +// .and("isFinish", "=", true)); // 将答题记录的扩展JSON转换为JSONObject列表 - List answerExtList = answerRecords.stream().map(QsvUserAnswerRecord::getExtJson).toList(); +// List answerExtList = answerRecords.stream().map(QsvUserAnswerRecord::getExtJson).toList(); // 查询活动题目列表 - List subjects = dao().query(QsvSubject.class, Cnd.where(QsvSubject::getActivityId, "=", activityId)); + List subjects = dao().query(QsvSubject.class, Cnd.where("activityId", "=", activityId)); // 将题目列表转换为Map Map subjectMap = subjects.stream().collect(Collectors.toMap(QsvSubject::getId, v -> v)); // 获取题目ID列表 List subjectIds = subjects.stream().map(QsvSubject::getId).toList(); // 查询题目选项列表 - List options = dao().query(QsvOption.class, Cnd.where("subjectId", "in", subjectIds).asc(QsvOption::getSortNum)); + List options = dao().query(QsvOption.class, Cnd.where("subjectId", "in", subjectIds).asc("sortNum")); // 将选项列表转换为Map Map optionMap = options.stream().collect(Collectors.toMap(QsvOption::getId, v -> v)); // 构建Excel导出实体 List excelExportEntities = buildExcelExportEntities(subjects); // 构建答题记录列表 - List list = buildAnswerRecords(answerRecords, subjectMap, options); + List list = answerRecords.stream().map(record -> { + NutMap map = NutMap.NEW() + .addv("id", record.getString("id")) + .addv("loginName", record.getString("loginName")) + .addv("userName", record.getString("userName")) + .addv("unitName", record.getString("unitName")) + .addv("unionName", record.getString("unionName")); + JSONObject extJson = record.getAs("extJson", JSONObject.class); + extJson.forEach((k, v) -> { + JSONObject jsonVal = (JSONObject) v; + + String type = subjectMap.get(k).getType(); + if (type.equals("text")) { + map.addv(k, jsonVal.getStr("text")); + } else if (type.equals("radio") || type.equals("checkbox")) { + JSONArray optionIds = jsonVal.getJSONArray("optionIds"); + String selectOptionTexts = options.stream().filter(option -> optionIds.contains(option.getId())) + .map(QsvOption::getText).collect(Collectors.joining(";")); + map.addv(k, selectOptionTexts); + } + }); + return map; + }).toList(); + pagination.setList(list); + + +// List list = buildAnswerRecords(answerRecords, subjectMap, options); // 构建表格列信息 List tableColumns = excelExportEntities.stream() @@ -195,9 +272,9 @@ public class QsvSurveyServiceImpl extends BaseServiceImpl i return NutMap.NEW() .addv("tableColumns", tableColumns) - .addv("tableData", list); + .addv("tableData", pagination); } catch (Exception e) { - throw new BaseException("获取用户答题记录失败", e); + throw new RuntimeException("获取用户答题记录失败", e); } } diff --git a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/impl/QsvUserAnswerRecordServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvUserAnswerRecordServiceImpl.java similarity index 82% rename from src/main/java/com/budwk/app/zhgh/activity/qsv/service/impl/QsvUserAnswerRecordServiceImpl.java rename to src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvUserAnswerRecordServiceImpl.java index c767b680..e22005ca 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/qsv/service/impl/QsvUserAnswerRecordServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvUserAnswerRecordServiceImpl.java @@ -1,24 +1,22 @@ -package com.budwk.app.zhgh.activity.qsv.service.impl; +package com.budwk.app.zhgh.dayofficework.qsv.service.impl; import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Dict; import cn.hutool.json.JSONObject; -import com.budwk.app.base.exception.BaseException; import com.budwk.app.base.service.impl.BaseServiceImpl; import com.budwk.app.sys.views.View_user; import com.budwk.app.web.commons.auth.utils.SecurityUtil; -import com.budwk.app.zhgh.activity.qsv.models.QsvActivity; -import com.budwk.app.zhgh.activity.qsv.models.QsvSubject; -import com.budwk.app.zhgh.activity.qsv.models.QsvUserAnswerRecord; -import com.budwk.app.zhgh.activity.qsv.param.QsvAnswerParam; -import com.budwk.app.zhgh.activity.qsv.service.QsvUserAnswerRecordService; -import io.swagger.annotations.ApiOperation; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvActivity; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvSubject; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvUserAnswerRecord; +import com.budwk.app.zhgh.dayofficework.qsv.param.QsvAnswerParam; +import com.budwk.app.zhgh.dayofficework.qsv.service.QsvUserAnswerRecordService; import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.dao.Chain; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; +import org.nutz.ioc.aop.Aop; import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.util.NutMap; import java.util.*; @@ -37,7 +35,7 @@ public class QsvUserAnswerRecordServiceImpl extends BaseServiceImpl subjects = dao().query(QsvSubject.class, Cnd.where("id", "in", subjectIds)); float score = 0; @@ -113,12 +111,12 @@ public class QsvUserAnswerRecordServiceImpl extends BaseServiceImpl campusList = baseService.dao().query(HealthCheckupCampus.class, Cnd.NEW().asc("campusCode")); + return Result.success(campusList); + } catch (Exception e) { + e.printStackTrace(); + return Result.error(); + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/healthCheckup/controller/HealthCheckupListController.java b/src/main/java/com/budwk/app/zhgh/healthCheckup/controller/HealthCheckupListController.java new file mode 100644 index 00000000..f44751b3 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/healthCheckup/controller/HealthCheckupListController.java @@ -0,0 +1,295 @@ +package com.budwk.app.zhgh.healthCheckup.controller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.ExcelImportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.ImportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.alibaba.excel.annotation.write.style.ContentRowHeight; +import com.alibaba.excel.annotation.write.style.HeadRowHeight; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.model.ExcelImportRes; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.base.utils.EasyExcelUtil; +import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope; +import com.budwk.app.zhgh.healthCheckup.model.*; +import com.budwk.app.zhgh.healthCheckup.service.HealthCheckupProjectService; +import com.budwk.app.zhgh.healthCheckup.template.HealthCheckupImportTemp; +import com.budwk.app.zhgh.integral.controller.IntegralManageController; +import com.budwk.app.zhgh.welfare.mode.WelfareUserImportExcel; +import com.budwk.app.zhgh.welfare.model.WelfareList; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.formula.functions.T; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.Daos; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.AdaptBy; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; +import org.nutz.mvc.upload.TempFile; +import org.nutz.mvc.upload.UploadAdaptor; + +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @ClassName HealthCheckupListController + * @Description TODO + * @Author zhf + * @Date 2023/7/18 8:43 + */ +@IocBean +@Ok("json:full") +@Slf4j +@Api(tags = "体检名单") +@At("/platform/healthCheckup/list/mange") +public class HealthCheckupListController { + + @Inject + private Dao dao; + + @Inject + private HealthCheckupProjectService healthCheckupProjectService; + + @At("") + @Ok("beetl:/platform/zhgh/healthCheckup/listMange/index.html") + @SaCheckPermission("healthCheckup.list.mange") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("healthCheckup.list.mange") + public Result pageData(PageForm pageForm, + String projectId, + String unionId, + String unitId) { + List confirms = dao.query(HealthCheckupUnionConfirm.class, Cnd.where("projectId", "=", projectId)); + + HealthCheckupProject project = healthCheckupProjectService.findOne(projectId); + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(""" + SELECT + hcu.userId AS id, + hcu.loginName, + hcu.userName, + hcu.sex, + hcu.unionId, + hcu.unionName, + hcu.unitName, + hcus.selectTime, + hcus.campus, + hcus.subjectId, + ca.campusName + FROM + health_checkup_user hcu + LEFT JOIN health_checkup_user_selection hcus ON hcu.userId = hcus.selectUserId + AND hcus.projectId=@projectId + LEFT JOIN health_checkup_campus ca on ca.id=hcus.campus + $condition + """).setParam("projectId", projectId); + sql.setCondition(cnd); + cnd.andEX("hcu.projectId", "=", projectId); + cnd.andEX("hcu.unionId", "=", unionId); + cnd.andEX("hcu.unitId", "=", unitId); + + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.andEX("hcu.unionId", "=", SecurityUtil.getUnionId()); + } + + if (StrUtil.isNotBlank(pageForm.getSearchName()) && StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + cnd.and(Cnd.likeEX(pageForm.getSearchName(), pageForm.getSearchKeyword())); + } + cnd.groupBy("hcu.userId"); + if (StrUtil.isNotBlank(pageForm.getPageOrderName()) && Strings.isNotBlank(pageForm.getPageOrderBy())) { + cnd.orderBy(pageForm.getPageOrderName(), "ascending".equalsIgnoreCase(pageForm.getPageOrderBy()) ? "ASC" : "DESC"); + } else { + cnd.desc("hcus.selectTime").asc("hcu.unitId"); + } + Pagination pagination = healthCheckupProjectService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + List paginationList = pagination.getList(); + + paginationList.forEach(v -> { + if (StrUtil.isNotBlank(v.getString("subjectId"))) { + List subjects = project.getHealthCheckupProjectSubjects(); + HealthCheckupProjectSubject subject = subjects.stream().filter(s -> s.getId().equals(v.getString("subjectId"))).findFirst().orElse(null); + v.setv("optionName", subject.getOptionName()); + } + + if (StrUtil.isNotBlank(v.getString("unionId"))) { + HealthCheckupUnionConfirm confirm = confirms.stream().filter(o -> o.getUnionId().equals(v.getString("unionId"))).findFirst().orElse(null); + v.setv("isAudit", confirm != null ? confirm.getIsAudit() : ""); + v.setv("auditTime", confirm != null ? confirm.getAuditTime() : ""); + } + }); + return Result.success(pagination); + } + + @At + @ApiOperation("体检名单确认") + @Aop(TransAop.READ_COMMITTED) + @SLog(type = "healthCheckup", tag = "体检管理", msg = "体检名单确认") + @SaCheckPermission("healthCheckup.list.mange") + public Result doAuditUser(String projectId, + String unionId, + Boolean flag) { + if (flag) { + dao.update(HealthCheckupUnionConfirm.class, Chain.make("isAudit", true) + .add("auditTime", DateUtil.date()) + .add("auditUser", SecurityUtil.getUserId()), + Cnd.where("projectId", "=", projectId).and("unionId", "=", unionId)); + } else { + dao.update(HealthCheckupUnionConfirm.class, Chain.make("isAudit", null) + .add("auditTime", null) + .add("auditUser", null), + Cnd.where("projectId", "=", projectId).and("unionId", "=", unionId)); + } + return Result.success(); + } + + + @At + @ApiOperation("体检名单管理员编辑选择记录") + @SLog(type = "healthCheckup", tag = "体检管理", msg = "管理员编辑了一条选择记录") + @SaCheckPermission("healthCheckup.list.mange") + public Result doEditHealthCheckupData(String subjectId, String campus, String projectId, String userId) { + + //查询用户有没有选择过套餐 + HealthCheckupUserSelection userSelection = healthCheckupProjectService.dao().fetch(HealthCheckupUserSelection.class, + Cnd.where("projectId", "=", projectId).and("selectUserId", "=", userId)); + //如果选择过套餐就修改选择的套餐id + if (Lang.isNotEmpty(userSelection)) { + userSelection.setSubjectId(subjectId); + userSelection.setCampus(campus); + healthCheckupProjectService.update(userSelection); + } else { + //如果没有选择过套餐添加一条记录 + HealthCheckupUserSelection checkupUserSelection = new HealthCheckupUserSelection(); + checkupUserSelection.setSelectUserId(userId); + checkupUserSelection.setProjectId(projectId); + checkupUserSelection.setSubjectId(subjectId); + checkupUserSelection.setCampus(campus); + checkupUserSelection.setSelectTime(new Date()); + healthCheckupProjectService.insert(checkupUserSelection); + } + return Result.success(); + } + + + @At + @ApiOperation("体检名单导入名单") + @SLog(type = "healthCheckup", tag = "体检管理", msg = "管理员导入了体检名单") + @SaCheckPermission("healthCheckup.list.mange") + @Aop(TransAop.READ_COMMITTED) + @AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"}) + public Result healthImport(TempFile file, String healthProjectId) { + // 读取数据 + List ts = EasyExcelUtil.syncReadModel(file.getFile(), HealthCheckupImportTemp.class, 0, 1); + List healthCheckupImportTemps = JSONUtil.parseArray(JSONUtil.toJsonStr(ts)).toList(HealthCheckupImportTemp.class); + List loginNames = healthCheckupImportTemps.stream().filter(v -> Strings.isNotBlank(v.getLoginName())).map(v -> v.getLoginName()).collect(Collectors.toList()); + //全部的体检名单 + List healthCheckupUserList = dao.query(HealthCheckupUser.class, Cnd.where(HealthCheckupUser::getProjectId, "=", healthProjectId)); + + + List userList = dao.query(View_user.class, Cnd.where(View_user::getLoginname, "in", loginNames)); + + HealthCheckupProject checkupProject = dao.fetch(HealthCheckupProject.class, healthProjectId); + ActivityUserScope userScope = dao.fetch(ActivityUserScope.class, Cnd.where("groupId", "=", checkupProject.getActivityGroupId())); + List userScopeList = new ArrayList<>(); + for (int i = 0; i < healthCheckupImportTemps.size(); i++) { + HealthCheckupImportTemp excel = healthCheckupImportTemps.get(i); + if (StrUtil.isBlank(excel.getLoginName())) { + excel.setErrInfo("工号为空", i + 1); + continue; + } + + // 不能在excel里重复 + if (healthCheckupImportTemps.stream().filter(s -> s.getLoginName().equals(excel.getLoginName())).count() > 1) { + excel.setErrInfo("重复数据", i + 1); + } + + View_user user = userList.stream().filter(s -> s.getLoginname().equals(excel.getLoginName())).findFirst().orElse(null); + if (user == null) { + excel.setErrInfo("无此用户", i + 1); + continue; + } + + if (healthCheckupUserList.stream().anyMatch(s -> s.getUserId().equals(user.getId()))) { + excel.setErrInfo("该用户已加入体检名单", i + 1); + continue; + } + + ActivityUserScope s = new ActivityUserScope(); + s.setGroupId(userScope.getGroupId()); + s.setGroupName(userScope.getGroupName()); + s.setUserId(user.getId()); + s.setCreator(SecurityUtil.getUserId()); + userScopeList.add(s); + } + ; + + dao.insert(userScopeList); + // 创建结果集 + ExcelImportRes excelImportRes = new ExcelImportRes<>(); + excelImportRes.setTotalRecords(healthCheckupImportTemps.size()); + // 添加错误记录 + excelImportRes.setErrorDetails(healthCheckupImportTemps.stream().filter(s -> StrUtil.isNotBlank(s.getErrMsg())).collect(Collectors.toList())); + excelImportRes.setFailedCount(excelImportRes.getErrorDetails().size()); + + return Result.success(excelImportRes); + } + + @At + @Ok("void") + @ApiOperation("下载体检参加人员导入模版") + @SaCheckPermission("healthCheckup.list.mange") + public void downloadTem(HttpServletResponse response) { + try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();) { + + EasyExcel.write(byteArrayOutputStream, HealthCheckupImportTemp.class) + .sheet("参加人员导入模版") + .doWrite(ArrayList::new); + CommonDownloadUtil.download("参加人员导入模版.xlsx", byteArrayOutputStream.toByteArray(), response); + } catch (Exception e) { + log.error("下载参加人员导入模版失败", e); + } + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/healthCheckup/controller/HealthCheckupProjectMangeController.java b/src/main/java/com/budwk/app/zhgh/healthCheckup/controller/HealthCheckupProjectMangeController.java new file mode 100644 index 00000000..5cd695fd --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/healthCheckup/controller/HealthCheckupProjectMangeController.java @@ -0,0 +1,210 @@ +package com.budwk.app.zhgh.healthCheckup.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.zhgh.healthCheckup.model.*; +import com.budwk.app.zhgh.healthCheckup.service.HealthCheckupProjectService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.Daos; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @ClassName HealthCheckupProjectMangeController + * @Description TODO + * @Author zhf + * @Date 2023/7/17 10:58 + */ +@IocBean +@Ok("json:full") +@Api(tags = "体检项目") +@At("/platform/healthCheckup/project/mange") +public class HealthCheckupProjectMangeController { + + @Inject + private HealthCheckupProjectService healthCheckupProjectService; + + + @At("") + @Ok("beetl:/platform/zhgh/healthCheckup/projectMange/index.html") + @SaCheckPermission("healthCheckup.projectMange") + public void index() { + } + + + @At + @ApiOperation("分页查询") + @SaCheckPermission("healthCheckup.projectMange") + public Result pageData(PageForm pageForm, + Integer year, + String name) { + Sql sql = Sqls.create(""" + SELECT + hcp.id, + hcp.`year`, + hcp.`name`, + hcp.choiceTimeStart, + hcp.choiceTimeEnd, + hcp.activityGroupId, + hcp.cover, + hcp.activityGroupName, + hcp.healthCheckupType, + IF((select count(userId) from health_checkup_user hcu where hcu.projectId = hcp.id) > 0,true,false) AS isHasUserList, + IF(NOW() > hcp.choiceTimeStart AND NOW() < hcp.choiceTimeEnd, true, false) AS isWithinChoiceTime, + IF(NOW() < hcp.choiceTimeStart, true, false) AS canCreated + FROM + health_checkup_project hcp + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("hcp.`year`", "=", year); + cnd.andEX("hcp.`name`", "=", name); + cnd.desc("hcp.choiceTimeStart"); + sql.setCondition(cnd); + return Result.success(healthCheckupProjectService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql)); + } + + @At + @ApiOperation("体检名单确认") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("healthCheckup.projectMange") + @SLog(type = "healthCheckup", tag = "体检管理", msg = "提交体检项目") + public Result doAdd(HealthCheckupProject healthCheckupProject, @Param(value = "deleteRowIds") String[] deleteRowIds) { + + + String projectId; + //如果是保存 + if (StrUtil.isBlank(healthCheckupProject.getId())) { + healthCheckupProject.setYear(DateUtil.thisYear()); + HealthCheckupProject checkupProject = healthCheckupProjectService.insertWith(healthCheckupProject, "healthCheckupProjectSubjects"); + projectId = checkupProject.getId(); + } else { + projectId = healthCheckupProject.getId(); + healthCheckupProjectService.dao().clear(HealthCheckupProjectSubject.class, Cnd.where("id", "in", deleteRowIds)); + healthCheckupProject.getHealthCheckupProjectSubjects().forEach(v -> { + v.setProjectId(healthCheckupProject.getId()); + }); + healthCheckupProjectService.dao().insertOrUpdate(healthCheckupProject.getHealthCheckupProjectSubjects()); + healthCheckupProjectService.update(healthCheckupProject); + } + + healthCheckupProjectService.dao().clear(HealthCheckupUnionConfirm.class, Cnd.where("projectId", "=", projectId)); + List unionList = healthCheckupProjectService.dao().query(Sys_union.class, Cnd.NEW()); + List confirmList = new ArrayList<>(); + unionList.forEach(item -> { + HealthCheckupUnionConfirm c = new HealthCheckupUnionConfirm(); + c.setProjectId(projectId); + c.setUnionId(item.getId()); + c.setIsAudit(false); + confirmList.add(c); + }); + healthCheckupProjectService.dao().insert(confirmList); + return Result.success(); + } + + @At + @ApiOperation("查询体检项目内容") + @SLog(type = "healthCheckup", tag = "体检管理", msg = "查询体检项目内容") + public Result findOne(String id) { + return Result.success(healthCheckupProjectService.findOne(id)); + } + + @At + @ApiOperation("删除体检项目") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("healthCheckup.projectMange") + @SLog(type = "healthCheckup", tag = "体检管理", msg = "删除了一条体检项目") + public Result doDelete(String id) { + healthCheckupProjectService.delete(id); + healthCheckupProjectService.dao().clear(HealthCheckupProjectSubject.class, Cnd.where("projectId", "=", id)); + return Result.success(); + } + + @At + @ApiOperation("按年份获取体检项目") + @SLog(type = "healthCheckup", tag = "体检管理", msg = "查询了所有的体检项目") + public Result getHealthCheckupProject(Integer year) { + List projectList = healthCheckupProjectService.query(Cnd.NEW().andEX("year", "=", year).desc("choiceTimeStart")); + return Result.success(projectList); + } + + + /** + * 创建体检名单 + * + * @param healthCheckupProject + * @return + */ + @At + @ApiOperation("创建体检名单") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("healthCheckup.projectMange") + @SLog(type = "healthCheckup", tag = "体检管理", msg = "创建体检名单") + public Result createUserList(HealthCheckupProject healthCheckupProject) { + healthCheckupProjectService.addHealthCheckupUser(healthCheckupProject); + return Result.success(); + } + + + /** + * 更新名单 + * + * @param healthCheckupProject + * @return + */ + @At + @ApiOperation("更新体检名单") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("healthCheckup.projectMange") + @SLog(type = "healthCheckup", tag = "体检管理", msg = "更新体检名单") + public Result renewUserList(HealthCheckupProject healthCheckupProject) { + healthCheckupProjectService.renewHealthCheckupUser(healthCheckupProject); + return Result.success(); + } + + + /** + * 重置名单 + * + * @param healthCheckupProject + * @return + */ + @At + @ApiOperation("重置体检名单") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("healthCheckup.projectMange") + @SLog(type = "healthCheckup", tag = "体检管理", msg = "重置体检名单") + public Result resetUserList(HealthCheckupProject healthCheckupProject) { + //重置名单,清空已选择的用户记录 + Sql sql = Sqls.create("select id,selectUserId from health_checkup_user_selection where projectId = @projectId").setParam("projectId", healthCheckupProject.getId()); + List list = (List) Daos.query(healthCheckupProjectService.dao(), sql.toString(), Sqls.callback.maps()); + List userSelectionIds = list.stream().map(v -> v.getString("id")).collect(Collectors.toList()); + List userIds = list.stream().map(v -> v.getString("selectUserId")).collect(Collectors.toList()); + + healthCheckupProjectService.dao().clear(HealthCheckupUserSelection.class, Cnd.where("selectUserId", "in", userIds)); + healthCheckupProjectService.dao().clear(HealthCheckupUserCompanion.class, Cnd.where("userSelectionId", "in", userSelectionIds)); + healthCheckupProjectService.dao().clear(HealthCheckupUser.class, Cnd.where("projectId", "=", healthCheckupProject.getId())); + healthCheckupProjectService.addHealthCheckupUser(healthCheckupProject); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/healthCheckup/controller/HealthCheckupSingleController.java b/src/main/java/com/budwk/app/zhgh/healthCheckup/controller/HealthCheckupSingleController.java new file mode 100644 index 00000000..f2a6bab5 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/healthCheckup/controller/HealthCheckupSingleController.java @@ -0,0 +1,278 @@ +package com.budwk.app.zhgh.healthCheckup.controller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.base.utils.ManyAddOrRenewUtil; +import com.budwk.app.zhgh.healthCheckup.model.HealthCheckupProject; +import com.budwk.app.zhgh.healthCheckup.model.HealthCheckupProjectSubject; +import com.budwk.app.zhgh.healthCheckup.model.HealthCheckupUserSelection; +import com.budwk.app.zhgh.healthCheckup.service.HealthCheckupSingleService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @ClassName HealthCheckupSingleController + * @Description TODO + * @Author zhf + * @Date 2023/7/18 13:53 + */ +@IocBean +@Ok("json:full") +@Api(tags = "体检数据统计") +@At("/platform/healthCheckup/statistics/single") +public class HealthCheckupSingleController { + + + @Inject + private HealthCheckupSingleService healthCheckupSingleService; + @Inject + private ManyAddOrRenewUtil manyAddOrRenewUtil; + + @At("") + @Ok("beetl:/platform/zhgh/healthCheckup/statisticsSingle/index.html") + @SaCheckPermission("healthCheckup.statisticsSingle") + public void index() { + } + + + @At + @ApiOperation("首页查询") + @SaCheckPermission("healthCheckup.statisticsSingle") + public Result pageData(String projectId, + String unionId) { + NutMap nutMap = healthCheckupSingleService.pageData(projectId, unionId); + return Result.success(nutMap); + } + + /** + * 每个分工会领取人员/未领取人员 + * + * @param page + * @param isSelected 是否领取 + * @param projectId + * @param unionId + * @return + */ + @At + @ApiOperation("每个分工会领取人员/未领取人员") + @SaCheckPermission("healthCheckup.statisticsSingle") + public Result receivePageData(PageForm page, String isSelected, + String projectId, + String unionId) { + List labelList = healthCheckupSingleService.receivePageDataColumns(projectId); + Pagination list = healthCheckupSingleService.receivePageData(page.getPageNumber(), page.getPageSize(), page.getSearchName(), page.getSearchKeyword(), projectId, unionId, isSelected); + return Result.success(NutMap.NEW().addv("list", list).addv("label", labelList)); + } + + + /** + * 导出已选/未选人员名单 + * + * @param projectId + * @param unionId + * @param year + * @param flag + * @param response + */ + @At + @Ok("void") + @ApiOperation("导出已选/未选人员名单") + @SaCheckPermission("healthCheckup.statisticsSingle") + public void exportReceiveDetail(String projectId, + String unionId, + Integer year, + boolean flag, HttpServletResponse response) { + + List entityList = new ArrayList<>() {{ + add(new ExcelExportEntity("职工号", "loginName", 20)); + add(new ExcelExportEntity("姓名", "userName", 20)); + add(new ExcelExportEntity("性别", "sex", 20)); + add(new ExcelExportEntity("出生年月", "birthday", 20)); + add(new ExcelExportEntity("年龄", "age", 20)); + add(new ExcelExportEntity("婚姻状况", "marriage", 20)); + add(new ExcelExportEntity("证件号", "idCard", 20)); + add(new ExcelExportEntity("部门", "unitName", 20)); + add(new ExcelExportEntity("部门编码", "unitCode", 20)); + add(new ExcelExportEntity("自选项目", "subjectName", 20)); + add(new ExcelExportEntity("自选院区", "campusName", 50)); + }}; + + List list; + if (flag) { + //已选人员 + list = healthCheckupSingleService.receivePageData(projectId, unionId, "0"); + } else { + //未选人员 + list = healthCheckupSingleService.receivePageData(projectId, unionId, "1"); + } + //获取当前年 + Calendar calendar = Calendar.getInstance(); + int thisYear = calendar.get(Calendar.YEAR); + list.forEach(v -> { + int substring = 0; + if (Strings.isNotBlank(v.getString("birthday"))) { + substring = Integer.parseInt(v.getString("birthday").substring(0, 4)); + } else if (Strings.isNotBlank(v.getString("idCard")) && v.getString("idCard").length() >= 10) { + substring = Integer.parseInt(v.getString("idCard").substring(6, 10)); + } + v.put("age", thisYear - substring); + }); + + List list2 = list.stream().filter(v -> Strings.isNotBlank(v.getString("unionName"))).collect(Collectors.toList()); + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + exportParams.setSheetName(year + "年教职工体检项目及地点统计表"); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, list2); + CommonDownloadUtil.download((flag ? year + "年教职工体检项目及地点统计表" : "未选名单") + ".xlsx", workbook, response); + } + + + @At + @Ok("void") + @ApiOperation("导出教职工家属体检登记表") + @SaCheckPermission("healthCheckup.statisticsSingle") + public void exportUserCompanion(String projectId, + String unionId, + Integer year, HttpServletResponse response) { + Sql sql = Sqls.create(""" + SELECT + u.username, + u.unitname unitName, + u.mobile, + hcuc.userName familyName, + hcuc.sex, + hcuc.marry isMarried, + hcuc.idCard, + hcc.campusName, + ( + SELECT + GROUP_CONCAT( hcps.optionName ) + FROM + health_checkup_user_selection hcus + LEFT JOIN `health_checkup_project_subject` hcps ON hcps.id = hcus.subjectId + WHERE + hcus.projectId = @projectId + AND hcus.selectUserId = u.id + ) optionName + FROM + `health_checkup_user_companion` hcuc + LEFT JOIN `health_checkup_user_selection` hcus ON hcus.id = hcuc.userSelectionId + LEFT JOIN `health_checkup_campus` hcc ON hcc.id = hcus.campus + LEFT JOIN `vw_user` u ON u.id = hcus.selectUserId + LEFT JOIN `health_checkup_project` hcp ON hcp.id = hcus.projectId + $condition + """).setParam("projectId", projectId); + Cnd cnd = Cnd.NEW(); + cnd.andEX("hcus.projectId", "=", projectId); + cnd.andEX("u.unionid", "=", unionId); + cnd.andEX("hcp.year", "=", year); + cnd.asc("u.unioncode"); + sql.setCondition(cnd); + //家属信息表 + List companionList = healthCheckupSingleService.listMap(sql); + + for (int i = 0; i < companionList.size(); i++) { + companionList.get(i).put("index", i + 1); + } + + List entityList = new ArrayList<>() {{ + add(new ExcelExportEntity("序号", "index", 20)); + add(new ExcelExportEntity("教职工姓名", "username", 20)); + add(new ExcelExportEntity("学院(部门)", "unitName", 20)); + add(new ExcelExportEntity("手机", "mobile", 20)); + add(new ExcelExportEntity("体检人姓名", "familyName", 20)); + add(new ExcelExportEntity("性别", "sex", 20)); + add(new ExcelExportEntity("婚否", "isMarried", 20)); + add(new ExcelExportEntity("体检人身份证号", "idCard", 50)); + add(new ExcelExportEntity("自选项目", "optionName", 50)); + add(new ExcelExportEntity("自选院区", "campusName", 50)); + }}; + + try { + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + exportParams.setTitle(year + "教职工家属体检登记表"); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, companionList); + CommonDownloadUtil.download(year + "教职工家属体检登记表.xlsx", workbook, response); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + @At + @ApiOperation("管理员一键代选") + @Ok("json:full") + @SaCheckPermission("healthCheckup.statisticsSingle") + @SLog(type = "healthCheckup", tag = "体检管理", msg = "管理员一键代选") + public Result doSelectByAdmin(String projectId, String optionId, String campus) { + Dao dao = healthCheckupSingleService.dao(); + HealthCheckupProject project = dao.fetch(HealthCheckupProject.class, projectId); + HealthCheckupProjectSubject subject = dao.fetch(HealthCheckupProjectSubject.class, optionId); + + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(""" + SELECT + u.id, + u.loginname loginName, + u.username userName, + u.sex, + u.birthday, + u.unitname unitName, + u.unionname unionName, + u.idcard idCard, + u.mobile + FROM + `activity_user_scope` aus + LEFT JOIN `vw_user` u ON u.id = aus.userId + $projectCnd $condition + """); + + cnd.and("aus.groupId", "=", project.getActivityGroupId()); + sql.setVar("projectCnd", "AND u.id NOT IN ( SELECT selectUserId FROM `health_checkup_user_selection` WHERE projectId = '" + projectId + "' AND selectUserId IS NOT NULL )"); + cnd.groupBy("u.loginname"); + sql.setCondition(cnd); + List mapList = healthCheckupSingleService.listMap(sql); + + List userIds = mapList.stream().map(v -> v.getString("id")).collect(Collectors.toList()); + //题目id + List selections = userIds.stream().map(v -> { + HealthCheckupUserSelection selection = new HealthCheckupUserSelection(); + selection.setProjectId(projectId); + selection.setSelectUserId(v); + selection.setCampus(campus); + selection.setSubjectId(optionId); + return selection; + }).collect(Collectors.toList()); + manyAddOrRenewUtil.asyncExecuteFastInsert(selections,null); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupCampus.java b/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupCampus.java new file mode 100644 index 00000000..76a0811f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupCampus.java @@ -0,0 +1,40 @@ +package com.budwk.app.zhgh.healthCheckup.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serializable; + +/** + * @ClassName HealthCheckupCampus + * @Description TODO 体检院区 + * @Author zzr + * @Date 2023/7/20 09:50 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("health_checkup_campus") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("体检院区表") +public class HealthCheckupCampus extends BaseModel implements Serializable { + + @Column + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("院区编码") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String campusCode; + + @Column + @Comment("院区名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String campusName; +} diff --git a/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupProject.java b/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupProject.java new file mode 100644 index 00000000..d9d67564 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupProject.java @@ -0,0 +1,78 @@ +package com.budwk.app.zhgh.healthCheckup.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * @ClassName HealthCheckupProject + * @Description TODO + * @Author zhf + * @Date 2023/7/17 10:40 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("health_checkup_project") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("体检项目表") +public class HealthCheckupProject extends BaseModel implements Serializable { + + @Column + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("年度") + @ColDefine(type = ColType.INT, width = 4) + private Integer year; + + @Column + @Comment("项目名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String name; + + @Column + @Comment("体检对象类型") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String healthCheckupType; + + @Column + @Comment("选择开始时间") + @ColDefine(type = ColType.DATETIME) + private Date choiceTimeStart; + + @Column + @Comment("选择结束时间") + @ColDefine(type = ColType.DATETIME) + private Date choiceTimeEnd; + + @Column + @Comment("发送对象") + @ColDefine(type = ColType.INT, width = 32) + private Integer activityGroupId; + + @Column + @Comment("发送对象名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String activityGroupName; + + + @Column + @Comment("封面") + @ColDefine(type = ColType.VARCHAR, width = 200) + private String cover; + + + @Many(field = "projectId") + private List healthCheckupProjectSubjects; + +} diff --git a/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupProjectSubject.java b/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupProjectSubject.java new file mode 100644 index 00000000..45b9fe19 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupProjectSubject.java @@ -0,0 +1,54 @@ +package com.budwk.app.zhgh.healthCheckup.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serializable; + +/** + * @ClassName HealthCheckupProjectSubject + * @Description 体检套餐 + * @Author zhf + * @Date 2023/7/17 10:51 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("health_checkup_project_subject") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("体检套餐表") +public class HealthCheckupProjectSubject extends BaseModel implements Serializable { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("所属项目") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String projectId; + + @Column + @Comment("选项名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String optionName; + + @Column + @Comment("选项排序") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String optionSort; + + @Column + @Comment("图片地址") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String imgUrl; + + @Column + @Comment("说明描述") + @ColDefine(type = ColType.TEXT) + private String description; +} diff --git a/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUnionConfirm.java b/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUnionConfirm.java new file mode 100644 index 00000000..154f4f4e --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUnionConfirm.java @@ -0,0 +1,52 @@ +package com.budwk.app.zhgh.healthCheckup.model; + + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serializable; +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +@Table("health_checkup_union_confirm") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("分工会体检确认表") +public class HealthCheckupUnionConfirm extends BaseModel implements Serializable { + + @Column + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("所属项目") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String projectId; + + @Column + @Comment("工会id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("是否确认") + @ColDefine(type = ColType.BOOLEAN) + private Boolean isAudit; + + @Column + @Comment("确认时间") + @ColDefine(type = ColType.DATETIME) + private Date auditTime; + + @Column + @Comment("操作人") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String auditUser; + +} diff --git a/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUser.java b/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUser.java new file mode 100644 index 00000000..bba44ff1 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUser.java @@ -0,0 +1,76 @@ +package com.budwk.app.zhgh.healthCheckup.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serializable; + +/** + * @version 1.0 + * @Author zzr + * @name:HealthCheckupUser + * @Date 2024/7/24 15:42 + * @注释 体检用户 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("health_checkup_user") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("体检名单表") +public class HealthCheckupUser extends BaseModel implements Serializable { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("所属项目") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String projectId; + + @Column + @Comment("用户id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String userId; + + @Column + @Comment("用户姓名") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String userName; + + @Column + @Comment("性别") + @ColDefine(type = ColType.VARCHAR, width = 10) + private String sex; + + @Column + @Comment("工号") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String loginName; + + @Column + @Comment("所属工会") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String unionName; + + @Column + @Comment("工会Id") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionId; + + @Column + @Comment("所属单位") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String unitName; + + @Column + @Comment("单位Id") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unitId; + +} diff --git a/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUserCompanion.java b/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUserCompanion.java new file mode 100644 index 00000000..976d26e4 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUserCompanion.java @@ -0,0 +1,66 @@ +package com.budwk.app.zhgh.healthCheckup.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serializable; + + +/** + * @ClassName HealthCheckupUserCompanion + * @Description TODO 体检家属表 + * @Author zzr + * @Date 2023/7/20 10:40 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@Table("health_checkup_user_companion") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("体检家属表") +public class HealthCheckupUserCompanion extends BaseModel implements Serializable { + + @Name + @Comment("id") + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("体检选择表Id") + private String userSelectionId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("姓名") + private String userName; + + @Column + @ColDefine(type = ColType.CHAR, width = 1) + @Comment("性别") + private String sex; + + @Column + @ColDefine(type = ColType.INT) + @Comment("年龄") + private Integer age; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 10) + @Comment("婚否") + private String marry; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 18) + @Comment("身份证号") + private String idCard; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 18) + @Comment("手机号") + private String mobile; + +} diff --git a/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUserSelection.java b/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUserSelection.java new file mode 100644 index 00000000..6d6b381d --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/healthCheckup/model/HealthCheckupUserSelection.java @@ -0,0 +1,59 @@ +package com.budwk.app.zhgh.healthCheckup.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * @ClassName HealthCheckupUserSelection + * @Description TODO + * @Author zhf + * @Date 2023/7/18 9:20 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("health_checkup_user_selection") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("体检教职工选择表") +public class HealthCheckupUserSelection extends BaseModel implements Serializable { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("所属项目") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String projectId; + + @Column + @Comment("所属选项") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String subjectId; + + @Column + @Comment("选择用户") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String selectUserId; + + @Column + @Comment("选择院区") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String campus; + + @Column + @Comment("选择时间") + @ColDefine(type = ColType.DATETIME) + private Date selectTime; + + @Many(field = "userSelectionId") + private List companionList; +} diff --git a/src/main/java/com/budwk/app/zhgh/healthCheckup/service/HealthCheckupProjectService.java b/src/main/java/com/budwk/app/zhgh/healthCheckup/service/HealthCheckupProjectService.java new file mode 100644 index 00000000..cbd20d88 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/healthCheckup/service/HealthCheckupProjectService.java @@ -0,0 +1,24 @@ +package com.budwk.app.zhgh.healthCheckup.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.healthCheckup.model.HealthCheckupProject; +import org.nutz.lang.util.NutMap; + +public interface HealthCheckupProjectService extends BaseService { + + + HealthCheckupProject findOne(String id); + + + /** + * 添加体检用户 + * @param healthCheckupProject + */ + void addHealthCheckupUser(HealthCheckupProject healthCheckupProject); + + /** + * 更新体检用户 + * @param healthCheckupProject + */ + void renewHealthCheckupUser(HealthCheckupProject healthCheckupProject); +} diff --git a/src/main/java/com/budwk/app/zhgh/healthCheckup/service/HealthCheckupSingleService.java b/src/main/java/com/budwk/app/zhgh/healthCheckup/service/HealthCheckupSingleService.java new file mode 100644 index 00000000..011ec646 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/healthCheckup/service/HealthCheckupSingleService.java @@ -0,0 +1,46 @@ +package com.budwk.app.zhgh.healthCheckup.service; + +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.healthCheckup.model.HealthCheckupProject; +import org.nutz.lang.util.NutMap; + +import java.util.List; + +public interface HealthCheckupSingleService extends BaseService { + + /** + * 分页查询 + * + * @param projectId 福利id + * @return + */ + NutMap pageData(String projectId,String unionId); + + + /** + * 导出发放详细表 + * + * @param projectId + * @return + */ + List receivePageDataColumns(String projectId); + + + /** + * 领取详情分页 + * + * @param projectId 体检id + * @return + */ + Pagination receivePageData(Integer pageNumber, Integer pageSize, String searchName, String searchKeyword, String projectId, String unionId, String isSelected); + + + /** + * 领取详情不分页 + * + * @param projectId 体检id + * @return + */ + List receivePageData(String projectId, String unionId,String isSelected); +} diff --git a/src/main/java/com/budwk/app/zhgh/healthCheckup/service/impl/HealthCheckupProjectServiceImpl.java b/src/main/java/com/budwk/app/zhgh/healthCheckup/service/impl/HealthCheckupProjectServiceImpl.java new file mode 100644 index 00000000..6c2407ea --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/healthCheckup/service/impl/HealthCheckupProjectServiceImpl.java @@ -0,0 +1,125 @@ +package com.budwk.app.zhgh.healthCheckup.service.impl; + +import cn.hutool.core.date.DateUtil; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.base.utils.ManyAddOrRenewUtil; +import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope; +import com.budwk.app.zhgh.healthCheckup.model.HealthCheckupProject; +import com.budwk.app.zhgh.healthCheckup.model.HealthCheckupUser; +import com.budwk.app.zhgh.healthCheckup.model.HealthCheckupUserCompanion; +import com.budwk.app.zhgh.healthCheckup.model.HealthCheckupUserSelection; +import com.budwk.app.zhgh.healthCheckup.service.HealthCheckupProjectService; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.entity.annotation.Comment; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.Daos; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.Mirror; +import org.nutz.lang.Strings; +import org.nutz.lang.random.R; +import org.nutz.lang.util.NutMap; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @ClassName HealthCheckupProjectServiceImpl + * @Description TODO + * @Author zhf + * @Date 2023/7/17 14:48 + */ +@IocBean(args = {"refer:dao"}) +public class HealthCheckupProjectServiceImpl extends BaseServiceImpl implements HealthCheckupProjectService { + + + @Inject + private ManyAddOrRenewUtil manyAddOrRenewUtil; + + public HealthCheckupProjectServiceImpl(Dao dao) { + super(dao); + } + + @Override + public HealthCheckupProject findOne(String id) { + HealthCheckupProject project = fetchLinks(fetch(id), "healthCheckupProjectSubjects", Cnd.NEW().asc("optionSort")); + + + return project; + } + + + @Override + public void addHealthCheckupUser(HealthCheckupProject healthCheckupProject) { + List needAddUsers = getHealthCheckupUserListByProject(healthCheckupProject); + manyAddOrRenewUtil.asyncExecuteFastInsert(needAddUsers, null); + } + + + @Override + @Aop(TransAop.READ_COMMITTED) + public void renewHealthCheckupUser(HealthCheckupProject healthCheckupProject) { + //全部组别人员 + List allGroupUsers = getHealthCheckupUserListByProject(healthCheckupProject); + //已选取人员,选择表的人员 + List userList = dao().query(HealthCheckupUser.class, Cnd.where("projectId", "=", healthCheckupProject.getId())); + // 找出在 userList 中但不在allGroupUsers中的userId,这部分人要删除体检信息 + List needDeleteUserIds = userList.stream() + .map(HealthCheckupUser::getUserId) + .filter(selectUserId -> allGroupUsers.stream() + .noneMatch(user -> user.getUserId().equals(selectUserId))) + .collect(Collectors.toList()); + + //获取生成名单中没有的用户,这部分要添加 + Sql sql = Sqls.create("select userId from health_checkup_user where projectId = @projectId").setParam("projectId", healthCheckupProject.getId()); + List sourceSelectionUserMaps = (List) Daos.query(dao(), sql.toString(), Sqls.callback.maps()); + Set sourceSelectionUserIds = sourceSelectionUserMaps.stream().map(v -> v.getString("userId")).collect(Collectors.toSet()); + //找出原来名单中没有的人,没有的就可以新增 + List canInsertSelectionUsers = allGroupUsers.stream().filter(v -> !sourceSelectionUserIds.contains(v.getId())).collect(Collectors.toList()); + + //过滤出原有名单中没有的,可以新增 + List needInsertSelectionUsers = canInsertSelectionUsers.parallelStream() + .filter(v -> !sourceSelectionUserIds.contains(v.getUserId())) + .collect(Collectors.toList()); + + List userSelectionIds = userList.stream().filter(needDeleteUserIds::contains).map(HealthCheckupUser::getId).collect(Collectors.toList()); + dao().clear(HealthCheckupUser.class, Cnd.where("userId", "in", needDeleteUserIds)); + dao().clear(HealthCheckupUserSelection.class, Cnd.where("selectUserId", "in", needDeleteUserIds)); + dao().clear(HealthCheckupUserCompanion.class, Cnd.where("userSelectionId", "in", userSelectionIds)); + + manyAddOrRenewUtil.asyncExecuteFastInsert(needInsertSelectionUsers, null); + } + + + public List getHealthCheckupUserListByProject(HealthCheckupProject healthCheckupProject) { + String projectId = healthCheckupProject.getId(); + List groupUsers = dao().query(ActivityUserScope.class, Cnd.where("groupId", "=", healthCheckupProject.getActivityGroupId())); + List userIds = groupUsers.stream().map(ActivityUserScope::getUserId).collect(Collectors.toList()); + List userMapList = dao().query(View_user.class, Cnd.where("id", "in", userIds)); + return userMapList.stream().map(v -> { + HealthCheckupUser user = new HealthCheckupUser(); + user.setId(R.UU32()); + user.setProjectId(projectId); + user.setUserId(v.getId()); + user.setLoginName(v.getLoginname()); + user.setUserName(v.getUsername()); + user.setSex(v.getSex()); + user.setUnitId(v.getUnitId()); + user.setUnitName(v.getUnitName()); + user.setUnionId(v.getUnionId()); + user.setUnionName(v.getUnionName()); + return user; + }).collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/healthCheckup/service/impl/HealthCheckupSingleServiceImpl.java b/src/main/java/com/budwk/app/zhgh/healthCheckup/service/impl/HealthCheckupSingleServiceImpl.java new file mode 100644 index 00000000..dd62a762 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/healthCheckup/service/impl/HealthCheckupSingleServiceImpl.java @@ -0,0 +1,273 @@ +package com.budwk.app.zhgh.healthCheckup.service.impl; + +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.healthCheckup.model.HealthCheckupProject; +import com.budwk.app.zhgh.healthCheckup.model.HealthCheckupProjectSubject; +import com.budwk.app.zhgh.healthCheckup.service.HealthCheckupProjectService; +import com.budwk.app.zhgh.healthCheckup.service.HealthCheckupSingleService; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.Static; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@IocBean(args = {"refer:dao"}) +public class HealthCheckupSingleServiceImpl extends BaseServiceImpl implements HealthCheckupSingleService { + public HealthCheckupSingleServiceImpl(Dao dao) { + super(dao); + } + + @Inject + private HealthCheckupProjectService healthCheckupProjectService; + + @Override + public NutMap pageData(String projectId, String unionId) { + HealthCheckupProject project = healthCheckupProjectService.findOne(projectId); + Sql sql = Sqls.create(""" + SELECT + su.id, + su.name unionName, + (SELECT count( 1 ) FROM `health_checkup_user` hcu WHERE hcu.projectId=@projectId and hcu.unionId = su.id ) sumCount + FROM + sys_union su + $condition + """).setParam("projectId", projectId); + Cnd cnd = Cnd.NEW(); + cnd.andEX("su.id", "=", unionId); + cnd.asc("su.unionCode"); + sql.setCondition(cnd); + //分工会参加体检人数汇总 + List healthCheckupList = listMap(sql); + //该体检项目下的套餐 + List subjectList = project.getHealthCheckupProjectSubjects(); + + //体检人员详情 + List userSelectList = this.getUserSelectionByProjectId(projectId); + + for (NutMap healthCheckup : healthCheckupList) { + List thisUnionSelectList = userSelectList.stream().filter(x -> + x.getString("unionId").equals(healthCheckup.getString("id")) && + x.getString("projectId").equals(projectId)).collect(Collectors.toList()); + + subjectList.forEach(o -> { + //每一项选择的人数 + Cnd optionCountCnd = Cnd.NEW(); + Sql optionCountSql = Sqls.create(""" + SELECT + COUNT(*) + FROM + `health_checkup_user_selection` hs + LEFT JOIN health_checkup_user hcu ON hcu.userId = hs.selectUserId + AND hcu.projectId = @projectId + $condition + """).setParam("projectId", projectId); + optionCountCnd.andEX("hcu.unionId", "=", healthCheckup.getString("id")); + optionCountCnd.andEX("hs.projectId", "=", projectId); + optionCountCnd.andEX("hs.subjectId", "=", o.getId()); + optionCountSql.setCondition(optionCountCnd); + int count = count(optionCountSql); + healthCheckup.put(o.getOptionName(), count); + }); + //已选人数 + healthCheckup.put("totalCount", thisUnionSelectList.stream().map(v -> v.getString("selectUserId")).distinct().count()); + //未选人数 + healthCheckup.put("unselectedTeacherSum", healthCheckup.getInt("sumCount") - healthCheckup.getInt("totalCount")); + } + //表格列数据 + List labelList = new ArrayList<>(); + labelList.add(NutMap.NEW().addv("label", "本次体检人数").addv("prop", "sumCount")); + subjectList.forEach(v -> { + labelList.add(NutMap.NEW().addv("label", v.getOptionName()).addv("prop", v.getOptionName())); + }); + labelList.add(NutMap.NEW().addv("label", "参加人数").addv("prop", "totalCount")); + labelList.add(NutMap.NEW().addv("label", "未选人数").addv("prop", "unselectedTeacherSum")); + + return NutMap.NEW().addv("tableList", healthCheckupList).addv("tableColumn", labelList); + } + + /** + * 体检参加人员 + * + * @param projectId + * @return + */ + public List getUserSelectionByProjectId(String projectId) { + Cnd cnd = Cnd.NEW(); + cnd.and("hcu.unionId", "is not", null); + cnd.andEX("hu.projectId", "=", projectId); + cnd.asc("hu.selectUserId"); + Sql sql = Sqls.create(""" + SELECT + hu.subjectId, + hu.selectTime, + hu.projectId, + hu.selectUserId, + hcu.unionId + FROM + `health_checkup_user_selection` hu + LEFT JOIN `health_checkup_user` hcu ON hcu.userId = hu.selectUserId and hcu.projectId=@projectId + $condition + """).setParam("projectId", projectId); + sql.setCondition(cnd); + return listMap(sql); + } + + + @Override + public List receivePageDataColumns(String projectId) { + List labelList = new ArrayList<>(); + labelList.add(NutMap.NEW().addv("label", "工号").addv("prop", "loginName")); + labelList.add(NutMap.NEW().addv("label", "姓名").addv("prop", "userName")); + labelList.add(NutMap.NEW().addv("label", "联系电话").addv("prop", "mobile")); + labelList.add(NutMap.NEW().addv("label", "身份证").addv("prop", "idCard").addv("width", 20)); + labelList.add(NutMap.NEW().addv("label", "人员类型").addv("prop", "personType")); + labelList.add(NutMap.NEW().addv("label", "工会").addv("prop", "unionName")); + labelList.add(NutMap.NEW().addv("label", "单位").addv("prop", "unitName")); + return labelList; + } + + @Override + public Pagination receivePageData(Integer pageNumber, Integer pageSize, String searchName, + String searchKeyword, String projectId, String unionId, String isSelected) { + Sql sql = null; + Cnd cnd = Cnd.NEW(); + if (Strings.isNotBlank(isSelected)) { + //查看已选择体检 + if ("0".equals(isSelected)) { + sql = Sqls.create(""" + SELECT + u.loginname AS loginName, + u.username AS userName, + u.sex, + u.birthday, + u.personType, + u.unitname AS unitName, + u.unionname AS unionName, + u.idcard AS idCard, + u.mobile + FROM + `health_checkup_user_selection` hcus + LEFT JOIN `vw_user` u ON u.id = hcus.selectUserId + LEFT JOIN `health_checkup_project_subject` hcps ON hcps.id = hcus.subjectId + $condition + """).setParam("projectId", projectId); + cnd.and("hcus.projectId", "=", projectId); + cnd.andEX("u.unionId", "=", unionId); + cnd.desc("hcus.subjectId"); + } else if ("1".equals(isSelected)) {//查看未选择体检 + sql = Sqls.create(""" + SELECT + u.id, + hcu.loginName, + hcu.userName, + hcu.sex, + u.birthday, + u.personType, + hcu.unitName, + hcu.unionName, + u.idcard idCard, + u.mobile + FROM + `health_checkup_user` hcu + LEFT JOIN `vw_user` u ON u.id = hcu.userId + $condition + """); + cnd.and(new Static("u.id NOT IN ( SELECT selectUserId FROM `health_checkup_user_selection` WHERE projectId = '" + projectId + "' AND selectUserId IS NOT NULL )")); + cnd.andEX("hcu.unionId", "=", unionId); + cnd.andEX("hcu.projectId", "=", projectId); + } + } + if (Strings.isNotBlank(searchName) && Strings.isNotBlank(searchKeyword)) { + cnd.and(searchName, "like", "%" + searchKeyword + "%"); + } + + + cnd.asc("u.unionCode"); + cnd.groupBy("u.loginname"); + sql.setCondition(cnd); + return listPageMap(pageNumber, pageSize, sql); + } + + @Override + public List receivePageData(String projectId, String unionId, String isSelected) { + Sql sql = null; + Cnd cnd = Cnd.NEW(); + if (Strings.isNotBlank(isSelected)) { + //查看已选择体检 + if ("0".equals(isSelected)) { + sql = Sqls.create(""" + SELECT + u.loginname AS loginName, + u.username AS userName, + u.sex, + u.birthday, + u.personType, + u.unitName, + u.unitCode, + u.marriage, + u.unionName, + u.idCard, + u.mobile, + hcps.optionName subjectName, + hcc.campusName, + ( + SELECT + GROUP_CONCAT( hcps.optionName ) + FROM + health_checkup_user_selection hcus + LEFT JOIN `health_checkup_project_subject` hcps ON hcps.id = hcus.subjectId + WHERE + hcus.projectId = @projectId + AND hcus.selectUserId = u.id + ) optionName + FROM + `health_checkup_user_selection` hcus + LEFT JOIN `vw_user` u ON u.id = hcus.selectUserId + LEFT JOIN `health_checkup_user` hcu ON hcu.userId = hcus.selectUserId and hcu.projectId=@projectId + LEFT JOIN `health_checkup_project_subject` hcps ON hcps.id = hcus.subjectId + LEFT JOIN `health_checkup_campus` hcc ON hcc.id = hcus.campus + $condition + """).setParam("projectId", projectId); + cnd.and("hcus.projectId", "=", projectId); + cnd.desc("hcus.subjectId"); + } else if ("1".equals(isSelected)) {//查看未选择体检 + sql = Sqls.create(""" + SELECT + u.id, + hcu.loginName, + hcu.userName, + hcu.sex, + u.birthday, + u.marriage, + u.personType, + hcu.unitName, + hcu.unionName, + u.idcard idCard, + u.mobile + FROM + `health_checkup_user` hcu + LEFT JOIN `vw_user` u ON u.id = hcu.userId + $condition + """); + sql.setVar("projectCnd", projectId); + cnd.and(new Static("u.id NOT IN ( SELECT selectUserId FROM `health_checkup_user_selection` WHERE projectId = '" + projectId + "' AND selectUserId IS NOT NULL )")); + } + + } + cnd.andEX("hcu.projectId", "=", projectId); + cnd.andEX("hcu.unionId", "=", unionId); + cnd.asc("u.unionCode"); + cnd.groupBy("u.loginname"); + sql.setCondition(cnd); + return listMap(sql); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/healthCheckup/template/HealthCheckupImportTemp.java b/src/main/java/com/budwk/app/zhgh/healthCheckup/template/HealthCheckupImportTemp.java new file mode 100644 index 00000000..456b899a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/healthCheckup/template/HealthCheckupImportTemp.java @@ -0,0 +1,25 @@ +package com.budwk.app.zhgh.healthCheckup.template; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.alibaba.excel.annotation.write.style.ContentRowHeight; +import com.alibaba.excel.annotation.write.style.HeadRowHeight; +import com.budwk.app.base.model.ExcelImportError; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode +@ContentRowHeight(20) // 内容行高 +@HeadRowHeight(20) // 表头行高 +@ColumnWidth(25) +public class HealthCheckupImportTemp extends ExcelImportError { + + @ExcelProperty("工号" ) + private String loginName; + + @ExcelProperty("姓名") + private String userName; + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetApplyController.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetApplyController.java new file mode 100644 index 00000000..7ba81c87 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetApplyController.java @@ -0,0 +1,114 @@ +package com.budwk.app.zhgh.outlay.activityBudget.conteoller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import com.alibaba.excel.EasyExcel; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.zhgh.integral.controller.IntegralManageController; +import com.budwk.app.zhgh.outlay.activityBudget.models.ActivityBudget; +import com.budwk.app.zhgh.outlay.activityBudget.service.ActivityBudgetService; +import com.budwk.app.zhgh.outlay.activityBudget.template.ActivityBudgetTemp; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; + +/** + * @author zhf + * @date 2025/7/21 11:30 + * @description 预算申报 + */ +@IocBean +@Ok("json:full") +@Slf4j +@Api(tags = "预算申报") +@At("/platform/activity/budget/apply") +public class ActivityBudgetApplyController { + + + @Inject + private ActivityBudgetService activityBudgetService; + + + @At("") + @Ok("beetl:/platform/zhgh/outlay/activityBudget/apply/index.html") + @SaCheckPermission("activity.budget.apply") + public void index() { + } + + @At("/form") + @Ok("beetl:/platform/zhgh/outlay/activityBudget/apply/form.html") + @SaCheckPermission("activity.budget.apply") + public void form() { + } + + + @At + @ApiOperation("提交年度预算申报") + @SaCheckPermission("activity.budget.apply") + @Aop(TransAop.READ_COMMITTED) + @SLog(type = "activityBudgetApply", tag = "年度预算申报-预算申报", msg = "提交年度预算申报") + public Result doSubmit(@Param("activityBudget") ActivityBudget activityBudget, Boolean flag) { + return activityBudgetService.doSubmit(activityBudget, flag); + } + + + + @At + @ApiOperation("查询校工会申报的年度预算") + @SaCheckPermission("activity.budget.apply") + public Result getSchoolBudget() { + Sql sql = Sqls.create(""" + SELECT + ab.* + FROM + activity_budget ab + LEFT JOIN wf_process_instance ins ON ins.businessNo = ab.id + WHERE + YEAR(ab.applyDate) = @year + AND ins.state = 20 + AND ab.outlayManageSource = 'ACTIVITY_BUDGET_TYPE_ONE' + """).setParam("year", DateUtil.thisYear()); + List budgetList = activityBudgetService.listMap(sql); + return Result.success(budgetList); + } + + @At + @Ok("void") + @ApiOperation("下载导入的模版") + @SaCheckPermission("activity.budget.apply") + public void downloadImport(HttpServletResponse response) { + try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();) { + EasyExcel.write(byteArrayOutputStream, ActivityBudgetTemp.class) + .sheet("预算申报模版") + .doWrite(ArrayList::new); + CommonDownloadUtil.download("预算申报模版.xlsx", byteArrayOutputStream.toByteArray(), response); + } catch (Exception e) { + log.error("下载福利名单导入模版失败", e); + } + } + + + + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetApplyListController.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetApplyListController.java new file mode 100644 index 00000000..a77a760a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetApplyListController.java @@ -0,0 +1,167 @@ +package com.budwk.app.zhgh.outlay.activityBudget.conteoller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.flow.entity.ProcessInstance; +import com.budwk.app.flow.entity.ProcessTask; +import com.budwk.app.zhgh.outlay.activityBudget.models.ActivityBudget; +import com.budwk.app.zhgh.outlay.activityBudget.models.ActivityBudgetDetails; +import com.budwk.app.zhgh.outlay.activityBudget.service.ActivityBudgetService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.checkerframework.checker.units.qual.C; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.util.List; +import java.util.Map; + +/** + * @author zhf + * @date 2025/7/24 11:46 + * @description 我的申报 + */ + +@IocBean +@Ok("json:full") +@Slf4j +@Api(tags = "我的预算申报") +@At("/platform/activity/budget/applyList") +public class ActivityBudgetApplyListController { + + @Inject + private ActivityBudgetService activityBudgetService; + + + @At("") + @Ok("beetl:/platform/zhgh/outlay/activityBudget/applyList/index.html") + @SaCheckPermission("activity.budget.applyList") + public void index() { + } + + @At("/view") + @Ok("beetl:/platform/zhgh/outlay/activityBudget/view/index.html") + @SaCheckPermission("activity.budget.applyList") + public void view() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("activity.budget.applyList") + public Result pageData(PageForm pageForm, Integer year, String activityMatter) { + + Sql sqlByApplyList = activityBudgetService.getSqlByApplyList(pageForm, year, activityMatter, Cnd.NEW()); + Pagination pagination = activityBudgetService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sqlByApplyList); + return Result.success(pagination); + } + + @At + @ApiOperation("批量删除申报数据") + @SaCheckPermission("activity.budget.applyList") + @Aop(TransAop.READ_COMMITTED) + @SLog(type = "activityBudgetApplyList", tag = "年度预算申报-我的申报", msg = "删除了${ids.length}条数据,${ids}") + public Result batchDelete(@Param("ids[]") @Valid String[] ids) { + if (ObjectUtil.isNotEmpty(ids)) { + activityBudgetService.clear(Cnd.where("id", "in", ids)); + activityBudgetService.dao().clear(ActivityBudgetDetails.class, Cnd.where("budgetId", "in", ids)); + List instanceList = activityBudgetService.dao().query(ProcessInstance.class, Cnd.where(ProcessInstance::getBusinessNo, "in", ids)); + if (ObjectUtil.isNotEmpty(instanceList)) { + List instanceIds = instanceList.stream().map(ProcessInstance::getId).toList(); + activityBudgetService.dao().clear(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "in", instanceIds)); + activityBudgetService.dao().clear(ProcessInstance.class, Cnd.where(ProcessInstance::getBusinessNo, "in", ids)); + } + } + return Result.success(); + } + + @At + @ApiOperation("删除一条申报数据") + @SaCheckPermission("activity.budget.applyList") + @Aop(TransAop.READ_COMMITTED) + @SLog(type = "activityBudgetApplyList", tag = "年度预算申报-我的申报", msg = "删除了一条条数据,${id}") + public Result doDelete(String id) { + activityBudgetService.dao().delete(ActivityBudget.class, id); + activityBudgetService.dao().clear(ActivityBudgetDetails.class, Cnd.where("budgetId", "=", id)); + ProcessInstance instance = activityBudgetService.dao().fetch(ProcessInstance.class, Cnd.where(ProcessInstance::getBusinessNo, "=", id)); + if (ObjectUtil.isNotEmpty(instance)) { + activityBudgetService.dao().clear(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "=", instance.getId())); + activityBudgetService.dao().delete(ProcessInstance.class, instance.getId()); + } + return Result.success(); + } + + @At + @ApiOperation("提交申报数据") + @SaCheckPermission("activity.budget.applyList") + @SLog(type = "activityBudgetApplyList", tag = "年度预算申报-我的申报", msg = "提交了${ids.length}条数据,${ids}") + public Result batchSubmit(@Valid @Param("ids[]") String[] ids) { + List budgetList = activityBudgetService.query(Cnd.where("id", "in", ids)); + List budgets = budgetList.stream().filter(a -> + ObjectUtil.isEmpty(a.getDeclareTotalBudgetMoney()) + || ObjectUtil.isEmpty(a.getHelpUnitName()) + || ObjectUtil.isEmpty(a.getOutlayManageSource())).toList(); + List names = budgets.stream().map(ActivityBudget::getActivityMatter).toList(); + if (ObjectUtil.isNotEmpty(names)) { + return Result.error("请完善活动预算信息【:" + StrUtil.join(",", names) + "】"); + } + budgetList.forEach(b -> { + b.setTotalBudgetMoney(b.getDeclareTotalBudgetMoney()); + b.setAuditState(1); + }); + activityBudgetService.update(budgetList); + return Result.success(); + } + + + @At + @ApiOperation("查询单个预算详细信息") + @SaCheckPermission("activity.budget.applyList") + public Result findOne(String id) { + return Result.success(activityBudgetService.findOne(id)); + } + + + @At + @ApiOperation("查询申报的金额") + @SaCheckPermission("activity.budget.applyList") + public Result getApplyMoney(Integer year, String activityMatter) { + Cnd cnd = Cnd.NEW(); + cnd.andEX("info.isSchoolBudget", "=", 0); + cnd.andEX("ins.state", "=", 20); + Sql sql = activityBudgetService.getSqlByApplyList(null, year, activityMatter, cnd); + sql.setCondition(cnd); + List list = activityBudgetService.listMap(sql); + double declareTotalBudgetMoney = list.stream().mapToDouble(map -> map.getDouble("declareTotalBudgetMoney")).sum(); + double totalBudgetMoney = list.stream().mapToDouble(map -> map.getDouble("totalBudgetMoney")).sum(); + return Result.success(Map.of("declareTotalBudgetMoney", declareTotalBudgetMoney, "totalBudgetMoney", totalBudgetMoney)); + } + + + @At + @Ok("void") + @SaCheckPermission("activity.budget.applyList") + public void doExport(@Valid Integer year, String activityMatter, HttpServletResponse response) { + + activityBudgetService.doExport(year, activityMatter, response); + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetApplyStatisticsController.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetApplyStatisticsController.java new file mode 100644 index 00000000..b221d231 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetApplyStatisticsController.java @@ -0,0 +1,129 @@ +package com.budwk.app.zhgh.outlay.activityBudget.conteoller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.sys.models.Sys_dict; +import com.budwk.app.sys.services.SysDictService; +import com.budwk.app.zhgh.outlay.activityBudget.service.ActivityBudgetApplyStatisticsService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author zhf + * @date 2025/7/24 17:28 + * @description + */ + +@IocBean +@Ok("json:full") +@Slf4j +@Api(tags = "预算汇总") +@At("/platform/activity/budget/applyStatistics") +public class ActivityBudgetApplyStatisticsController { + + + @Inject + private ActivityBudgetApplyStatisticsService activityBudgetService; + + @Inject + private SysDictService sysDictService; + + @At("") + @Ok("beetl:/platform/zhgh/outlay/activityBudget/applyStatistics/index.html") + @SaCheckPermission("activity.budget.applyStatistics") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("activity.budget.applyStatistics") + public Result pageData(PageForm pageForm, Integer year, String unionId, String clubId, String outlayManageSource, String activityMatter) { + Sql sql = activityBudgetService.getsql(year, unionId, clubId, outlayManageSource, activityMatter); + Pagination pagination = activityBudgetService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @ApiOperation("查询预算有多少钱") + @SaCheckPermission("activity.budget.applyStatistics") + public Result getApplyMoney(Integer year, String unionId, String clubId, String outlayManageSource, String activityMatter) { + Sql sql = activityBudgetService.getsql(year, unionId, clubId, outlayManageSource, activityMatter); + List list = activityBudgetService.listMap(sql); + list = list.stream().filter(v -> !v.getBoolean("isSchoolBudget")).toList(); + double declareTotalBudgetMoney = list.stream().mapToDouble(map -> map.getDouble("declareTotalBudgetMoney")).sum(); + double totalBudgetMoney = list.stream().mapToDouble(map -> map.getDouble("totalBudgetMoney")).sum(); + return Result.success(Map.of("declareTotalBudgetMoney", declareTotalBudgetMoney, "totalBudgetMoney", totalBudgetMoney)); + } + + @At + @Ok("void") + @ApiOperation("导出") + @SaCheckPermission("activity.budget.applyStatistics") + public void doExport(@Valid Integer year, String clubId, String unionId, @Valid String outlayManageSource, HttpServletResponse response) { + Sql sql = activityBudgetService.getsql(year, unionId, clubId, outlayManageSource, null); + List mapList = activityBudgetService.listMap(sql); + List dictList = sysDictService.getSubListByCode("ACTIVITY_BUDGET_TYPE"); + mapList.forEach(map -> { + Sys_dict dict = dictList.stream().filter(d -> d.getCode().equals(map.getString("outlayManageSource"))).findFirst().orElse(null); + map.put("outlayManageSource", dict.getName()); + }); + ArrayList entities = new ArrayList<>(); + entities.add(new ExcelExportEntity("年度", "year", 20)); + entities.add(new ExcelExportEntity("申报人姓名", "userName", 20)); + entities.add(new ExcelExportEntity("申报人工号", "loginName", 20)); + entities.add(new ExcelExportEntity("联系方式", "mobile", 20)); + entities.add(new ExcelExportEntity("申报类型", "outlayManageSource", 20)); + entities.add(new ExcelExportEntity("申报单位", "helpUnitName", 20)); + entities.add(new ExcelExportEntity("事项", "activityMatter", 20)); + ExcelExportEntity draftCodeEntity = new ExcelExportEntity("申报预算金额", "declareTotalBudgetMoney", 20); + draftCodeEntity.setType(10); + entities.add(draftCodeEntity); + ExcelExportEntity draftCodeEntity2 = new ExcelExportEntity("审核预算金额", "totalBudgetMoney", 20); + draftCodeEntity2.setType(10); + entities.add(draftCodeEntity2); + entities.add(new ExcelExportEntity("申报时间", "applyDate", 20)); + + + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, mapList); + CommonDownloadUtil.download("预算申报汇总表.xlsx", workbook, response); + } + + + @At + @ApiOperation("删除申报记录") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("activity.budget.applyStatistics") + @SLog(type = "activity.budget.applyStatistics", tag = "删除申报记录", msg = "删除申报记录:${args[0]}") + public Result doDelete(String id) { + activityBudgetService.doDelete(id); + return Result.success(); + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetQueryStatisticsController.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetQueryStatisticsController.java new file mode 100644 index 00000000..945431e1 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetQueryStatisticsController.java @@ -0,0 +1,97 @@ +package com.budwk.app.zhgh.outlay.activityBudget.conteoller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.zhgh.outlay.activityBudget.service.ActivityBudgetQueryStatisticsService; +import com.budwk.app.zhgh.outlay.activityBudget.service.ActivityBudgetService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.random.R; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; + +/** + * @author zhf + * @date 2025/7/24 16:35 + * @description + */ +@IocBean +@Ok("json:full") +@Slf4j +@Api(tags = "预算汇总") +@At("/platform/activity/budget/queryStatistics") +public class ActivityBudgetQueryStatisticsController { + + + + @Inject + private ActivityBudgetQueryStatisticsService statisticsService; + + + @At("") + @Ok("beetl:/platform/zhgh/outlay/activityBudget/queryStatistics/index.html") + @SaCheckPermission("activity.budget.queryStatistics") + public void index() { + } + + + @At + @ApiOperation("分页查询") + @SaCheckPermission("activity.budget.queryStatistics") + public Result pageData(@Valid Integer year, String clubId, String unionId, @Valid String outlayManageSource) { + return Result.success(statisticsService.getDataByBudgetTypeCode(year, clubId, unionId, outlayManageSource)); + } + + @At + @Ok("void") + @ApiOperation("导出") + @SaCheckPermission("activity.budget.queryStatistics") + public void doExport(@Valid Integer year, String clubId, String unionId, @Valid String outlayManageSource, HttpServletResponse response) { + List mapList = statisticsService.getDataByBudgetTypeCode(year, clubId, unionId, outlayManageSource); + if (outlayManageSource.equals("ACTIVITY_BUDGET_TYPE_TWO")){ + mapList.forEach(m->{ + if (StrUtil.isEmpty(m.getString("unionName"))){ + m.put("unionName",m.getString("unitName")); + m.put("unionCode",m.getString("unionId")); + } + }); + } + ArrayList entities = new ArrayList<>(); + entities.add(new ExcelExportEntity("年度", "year", 20)); + if (List.of("ACTIVITY_BUDGET_TYPE_ONE").contains(outlayManageSource)) { + entities.add(new ExcelExportEntity("事项", "activityMatter", 50)); + }else if (outlayManageSource.equals("ACTIVITY_BUDGET_TYPE_TWO")) { + entities.add(new ExcelExportEntity("编码", "unionCode", 20)); + entities.add(new ExcelExportEntity("分工会", "unionName", 20)); + }else if (outlayManageSource.equals("ACTIVITY_BUDGET_TYPE_THREE")) { + entities.add(new ExcelExportEntity("编码", "clubCode", 20)); + entities.add(new ExcelExportEntity("协会名称", "clubName", 20)); + } + ExcelExportEntity draftCodeEntity = new ExcelExportEntity("预算金额", "totalBudgetMoney", 20); + draftCodeEntity.setType(10); + entities.add(draftCodeEntity); + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, mapList); + CommonDownloadUtil.download("预算申报汇总表.xlsx", workbook, response); + } + + + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetSchoolAuditController.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetSchoolAuditController.java new file mode 100644 index 00000000..a6522382 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/conteoller/ActivityBudgetSchoolAuditController.java @@ -0,0 +1,116 @@ +package com.budwk.app.zhgh.outlay.activityBudget.conteoller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.flow.enums.ProcessTaskStateEnum; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.outlay.activityBudget.service.ActivityBudgetService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.util.List; + +/** + * @author zhf + * @date 2025/7/29 10:59 + * @description 校工会审核 + */ +@IocBean +@Ok("json:full") +@Slf4j +@Api(tags = "校工会审核年度预算申报") +@At("/platform/activity/budget/schoolAudit") +public class ActivityBudgetSchoolAuditController { + + @Inject + private ActivityBudgetService activityBudgetService; + + + @At("") + @Ok("beetl:/platform/zhgh/outlay/activityBudget/schoolAudit/index.html") + @SaCheckPermission("activity.budget.schoolAudit") + public void index() { + } + + @At("/form") + @Ok("beetl:/platform/zhgh/outlay/activityBudget/schoolAudit/form.html") + @SaCheckPermission("activity.budget.schoolAudit") + public void form() { + } + + + @At + @ApiOperation("分页查询") + @SaCheckPermission("activity.budget.schoolAudit") + public Result pageData(PageForm pageForm, + Integer year, + String unionId, + String clubId, + Boolean approval, + String outlayManageSource, + String activityMatter) { + Sql sql = Sqls.create(""" + SELECT + info.*, + YEAR(info.applyDate) year, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariale, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariale + FROM + wf_process_task t + LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId + LEFT JOIN activity_budget info ON info.id = ins.businessNo + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("t.taskName", "=", "b6f29037-972d-4b97-8677-c3b3672ef0dc"); + cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId())); + cnd.andEX("info.unionId", "=", unionId); + cnd.andEX("info.outlayManageSource", "=", outlayManageSource); + + if (approval) { + cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.WITHDRAW.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode())); + } else { + cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode()); + } + + cnd.desc("t.createdAt"); + + cnd.andEX("YEAR(info.applyDate)", "=", year); + cnd.and(Cnd.likeEX("info.activityMatter", activityMatter)); + + if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.desc("info.applyDate"); + } else { + cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } + sql.setCondition(cnd); + Pagination pageVO = activityBudgetService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pageVO); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/interceptor/OutlayActBudgetApplyPostInterceptor.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/interceptor/OutlayActBudgetApplyPostInterceptor.java new file mode 100644 index 00000000..1d38c4b2 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/interceptor/OutlayActBudgetApplyPostInterceptor.java @@ -0,0 +1,130 @@ +package com.budwk.app.zhgh.outlay.activityBudget.interceptor; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.result.Result; +import com.budwk.app.flow.constant.FlowConst; +import com.budwk.app.flow.engine.FlowInterceptor; +import com.budwk.app.flow.engine.core.Execution; +import com.budwk.app.flow.engine.core.ServiceContext; +import com.budwk.app.flow.entity.ProcessInstance; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.outlay.activityBudget.models.ActivityBudget; +import com.budwk.app.zhgh.outlay.activityBudget.models.ActivityBudgetDetails; +import com.budwk.app.zhgh.outlay.activityBudget.service.ActivityBudgetService; +import com.budwk.app.zhgh.outlay.outlayManage.school.model.OutlayManageSchool; +import com.budwk.app.zhgh.outlay.outlayManage.union.model.OutlayManageUnion; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.json.Json; + +import java.util.List; + +/** + * @author zhf + * @date 2025/7/28 17:01 + * @description 活动预算申报提交后置拦截器 + */ +public class OutlayActBudgetApplyPostInterceptor implements FlowInterceptor { + + + @Override + public void intercept(Execution execution) { + String formDataStr = execution.getArgs().getStr(FlowConst.FORM_DATA); + ActivityBudget activityBudget = Json.fromJson(ActivityBudget.class, formDataStr); + + Dao dao = ServiceContext.find(Dao.class); + + if (StrUtil.isEmpty(activityBudget.getId())) { + activityBudget.setUserId(SecurityUtil.getUserId()); + activityBudget.setLoginName(SecurityUtil.getUserLoginname()); + activityBudget.setUserName(SecurityUtil.getUserUsername()); + //查询分工会这个项目有没有申报过 +// if (List.of("ACTIVITY_BUDGET_TYPE_TWO").contains(activityBudget.getBudgetTypeCode())) { +// int activityMatterCount = dao.count(ActivityBudget.class, Cnd.where("activityMatter", "=", +// activityBudget.getActivityMatter()).and("unionId", "=", SecurityUtil.getUnionId())); +// if (activityMatterCount > 0) { +// return Result.error(activityBudget.getActivityMatter() + "已填写申请!"); +// } +// } + } + //删除预算详情表 + if (StrUtil.isNotBlank(activityBudget.getId())) { + dao.clear(ActivityBudgetDetails.class, Cnd.where("budgetId", "=", activityBudget.getId())); + } + + if (List.of("superadmin").contains(SecurityUtil.getUserLoginname())) { + //如果是超级管理员就可以直接提交不用审核 + activityBudget.setTotalBudgetMoney(activityBudget.getDeclareTotalBudgetMoney()); + ActivityBudget budget = null; + if (StrUtil.isNotBlank(activityBudget.getId())) { + budget = dao.fetch(ActivityBudget.class, activityBudget.getId()); + } + //如果申报的是校工会预算 + if (activityBudget.getOutlayManageSource().equals("ACTIVITY_BUDGET_TYPE_ONE")) { + OutlayManageSchool outlayManageSchool = dao.fetch(OutlayManageSchool.class, Cnd.where("year", "=", DateUtil.thisYear())); + if (ObjectUtil.isNotEmpty(outlayManageSchool)) { + if (StrUtil.isNotBlank(activityBudget.getId())) { + //如果传过来有预算Id,代表是修改的,那么就减去原来的金额 + outlayManageSchool.setTotalQuota(outlayManageSchool.getTotalQuota().subtract(budget.getTotalBudgetMoney())); + } + //直接修改为现在传过来的金额 + outlayManageSchool.setTotalQuota(outlayManageSchool.getTotalQuota().add(activityBudget.getTotalBudgetMoney())); + dao.updateIgnoreNull(outlayManageSchool); + } + } else if (activityBudget.getOutlayManageSource().equals("ACTIVITY_BUDGET_TYPE_TWO")) { + //如果申报的是分工会预算 + OutlayManageUnion outlayManageUnion = dao.fetch(OutlayManageUnion.class, + Cnd.where("year", "=", DateUtil.thisYear()) + .and("unionId", "=", activityBudget.getUnionId())); + if (ObjectUtil.isNotEmpty(outlayManageUnion)) { + if (StrUtil.isNotBlank(activityBudget.getId())) { + outlayManageUnion.setTotalQuota(outlayManageUnion.getTotalQuota().subtract(budget.getTotalBudgetMoney())); + } + outlayManageUnion.setTotalQuota(outlayManageUnion.getTotalQuota().add(activityBudget.getTotalBudgetMoney())); + dao.updateIgnoreNull(outlayManageUnion); + } + } else if (activityBudget.getOutlayManageSource().equals("ACTIVITY_BUDGET_TYPE_THREE")) { + //如果不等于校工会预算才往表里面加预算 + //代表协会可能用的是校工会的预算 +// if (!activityBudget.getIsSchoolBudget()) { +// jf_club jfClub = dao.fetch(jf_club.class, Cnd.where("year", "=", DateUtil.getYear()) +// .and("club_id", "=", activityBudget.getClubId())); +// if (ObjectUtil.isNotEmpty(jfClub)) { +// if (StrUtil.isNotBlank(activityBudget.getId())) { +// jfClub.setTotalQuota(jfClub.getTotalQuota().subtract(budget.getTotalBudgetMoney())); +// } +// jfClub.setTotalQuota(jfClub.getTotalQuota().add(activityBudget.getTotalBudgetMoney())); +// dao.updateIgnoreNull(jfClub); +// } +// } + } else if (activityBudget.getOutlayManageSource().equals("ACTIVITY_BUDGET_TYPE_FOUR")) { + // 更新其他经费表 +// JfOther jfOther = dao.fetch(JfOther.class, Cnd.where("year", "=", DateUtil.getYear())); +// if (ObjectUtil.isNotEmpty(jfOther)) { +// if (StrUtil.isNotBlank(activityBudget.getId())) { +// jfOther.setTotalQuota(jfOther.getTotalQuota().subtract(budget.getTotalBudgetMoney())); +// } +// jfOther.setTotalQuota(jfOther.getTotalQuota().add(activityBudget.getTotalBudgetMoney())); +// dao.updateIgnoreNull(jfOther); +// } + } + } + + + dao.insertOrUpdate(activityBudget); +// for (ActivityBudgetDetails details : activityBudget.getBudgetDetails()) { +// details.setBudgetId(activityBudget.getId()); +// } +// //添加预算详情表 +// dao.insert(activityBudget.getBudgetDetails()); + + execution.getArgs().set(FlowConst.FORM_DATA,Json.toJson(activityBudget)); + + int instanceId = execution.getArgs().getInt(FlowConst.PROCESS_INSTANCE_ID_KEY); + dao.update(ProcessInstance.class, Chain.make("businessNo", activityBudget.getId()), Cnd.where(ProcessInstance::getId, "=", instanceId)); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/interceptor/OutlayActBudgetSchoolPostInterceptor.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/interceptor/OutlayActBudgetSchoolPostInterceptor.java new file mode 100644 index 00000000..5c03d4b3 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/interceptor/OutlayActBudgetSchoolPostInterceptor.java @@ -0,0 +1,35 @@ +package com.budwk.app.zhgh.outlay.activityBudget.interceptor; + +import com.budwk.app.flow.constant.FlowConst; +import com.budwk.app.flow.engine.FlowInterceptor; +import com.budwk.app.flow.engine.core.Execution; +import com.budwk.app.flow.engine.core.ServiceContext; +import com.budwk.app.flow.entity.ProcessInstance; +import com.budwk.app.zhgh.outlay.activityBudget.models.ActivityBudget; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.json.Json; +import org.nutz.lang.util.NutMap; + +/** + * @author zhf + * @date 2025/7/28 17:01 + * @description 活动预算申报提交后置拦截器 + */ +public class OutlayActBudgetSchoolPostInterceptor implements FlowInterceptor { + @Override + public void intercept(Execution execution) { + + String formDataStr = execution.getArgs().getStr(FlowConst.FORM_DATA); + NutMap activityBudget = Json.fromJson(NutMap.class, formDataStr); + + Dao dao = ServiceContext.find(Dao.class); + dao.update(ActivityBudget.class, Chain.make("totalBudgetMoney", execution.getArgs().getStr("tf_totalBudgetMoney")), + Cnd.where("id", "=", activityBudget.getString("id"))); + execution.getArgs().set(FlowConst.FORM_DATA, Json.toJson(activityBudget)); + + int instanceId = execution.getArgs().getInt(FlowConst.PROCESS_INSTANCE_ID_KEY); + dao.update(ProcessInstance.class, Chain.make("businessNo", activityBudget.getString("id")), Cnd.where(ProcessInstance::getId, "=", instanceId)); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/models/ActivityBudget.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/models/ActivityBudget.java new file mode 100644 index 00000000..48d9e93f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/models/ActivityBudget.java @@ -0,0 +1,140 @@ +package com.budwk.app.zhgh.outlay.activityBudget.models; + +import com.budwk.app.base.model.Audit; +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; + +/** + * @ClassName ActivityBudget + * @Description TODO + * @Author zhf + * @Date 2024/12/3 10:09 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("activity_budget") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("活动预算") +public class ActivityBudget extends BaseModel implements Serializable { + + @Column + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + @Column + @Comment("用户ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String userId; + + @Column + @Comment("用户姓名") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String userName; + + @Column + @Comment("用户工号") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String loginName; + @Column + @Comment("联系方式") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String mobile; + + @Column + @Comment("活动时间") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String activityDate; + + @Column + @Comment("活动事项") + @ColDefine(type = ColType.VARCHAR, width = 200) + private String activityMatter; + + @Column + @Comment("活动内容") + @ColDefine(type = ColType.TEXT) + private String activityContent; + + @Column + @Comment("预算金额") + @ColDefine(customType = "decimal(10,2)") + private BigDecimal totalBudgetMoney; + @Column + @Comment("申报金额") + @ColDefine(customType = "decimal(10,2)") + private BigDecimal declareTotalBudgetMoney; + + @Column + @Comment("预算类型") + @ColDefine(type = ColType.VARCHAR, width = 200) + private String outlayManageSource; + @Column + @Comment("创建人工会") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("创建人所属社团") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String clubId; + + @Column + @Comment("举办单位") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String helpUnitName; + + @Column + @Comment("申报时间") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String applyDate; + + @Column + @Comment("校工会审核") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String schoolAuditId; + + @Column + @Comment("签字") + @ColDefine(type = ColType.VARCHAR, width = 200) + private String applySign; + + @Column + @Comment("审核状态") + @Default("0") + @ColDefine(type = ColType.INT) + private Integer auditState; + + @Column + @Comment("是否属于校工会预算") + @Default("0") + @ColDefine(type = ColType.BOOLEAN) + private Boolean isSchoolBudget; + + @Column + @Comment("是否可以重复报销") + @Default("1") + @ColDefine(type = ColType.BOOLEAN) + private Boolean isRepeatReimburse; + + @Column + @Comment("校工会预算") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String schoolBudgetId; + + @Many(field = "budgetId") + private List budgetDetails; + + private Audit schoolAudit; + private List allocationEditAuditList; + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/models/ActivityBudgetDetails.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/models/ActivityBudgetDetails.java new file mode 100644 index 00000000..aa03efcb --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/models/ActivityBudgetDetails.java @@ -0,0 +1,58 @@ +package com.budwk.app.zhgh.outlay.activityBudget.models; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @ClassName ActivityBudgetDetails + * @Description TODO + * @Author zhf + * @Date 2024/12/3 10:15 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@Table("activity_budget_details") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("活动预算记录详情") +public class ActivityBudgetDetails extends BaseModel implements Serializable { + + @Column + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + @Column + @Comment("申报id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String budgetId; + + @Column + @Comment("类别") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String detailName; + + @Column + @Comment("预算金额") + @ColDefine(customType = "decimal(10,2)") + private BigDecimal budgetMoney; + + @Column + @Comment("金额") + @ColDefine(customType = "decimal(10,2)") + private BigDecimal money; + + @Column + @Comment("排序") + @ColDefine(type = ColType.INT) + private Integer detailsOrder; + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/models/ActivityBudgetType.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/models/ActivityBudgetType.java new file mode 100644 index 00000000..7ecb5fe7 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/models/ActivityBudgetType.java @@ -0,0 +1,56 @@ +package com.budwk.app.zhgh.outlay.activityBudget.models; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; + +/** + * @ClassName ActivityBudgetType + * @Description TODO + * @Author zhf + * @Date 2024/12/3 14:55 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@Table("activity_budget_type") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("活动预算类型") +public class ActivityBudgetType extends BaseModel implements Serializable { + + @Column + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + @Column + @Comment("类型") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String budgetTypeName; + + @Column + @Comment("金额") + @ColDefine(type = ColType.FLOAT, width = 10, precision = 2) + private Double budgetTypeMoney; + + @Column + @Comment("备注") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String note; + + @Column + @Comment("年度") + @ColDefine(type = ColType.INT) + private Integer year; + + @Column + @Comment("排序") + @ColDefine(type = ColType.INT) + private Integer location; +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/ActivityBudgetApplyStatisticsService.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/ActivityBudgetApplyStatisticsService.java new file mode 100644 index 00000000..3ae39055 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/ActivityBudgetApplyStatisticsService.java @@ -0,0 +1,12 @@ +package com.budwk.app.zhgh.outlay.activityBudget.service; + +import com.budwk.app.base.service.BaseService; +import org.nutz.dao.sql.Sql; + +public interface ActivityBudgetApplyStatisticsService extends BaseService { + + Sql getsql(Integer year, String unionId,String clubId, String outlayManageSource,String activityMatter); + + + void doDelete(String id); +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/ActivityBudgetQueryStatisticsService.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/ActivityBudgetQueryStatisticsService.java new file mode 100644 index 00000000..2ca8e072 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/ActivityBudgetQueryStatisticsService.java @@ -0,0 +1,11 @@ +package com.budwk.app.zhgh.outlay.activityBudget.service; + +import com.budwk.app.base.service.BaseService; +import org.nutz.lang.util.NutMap; + +import java.util.List; + +public interface ActivityBudgetQueryStatisticsService extends BaseService { + + List getDataByBudgetTypeCode(Integer year, String clubId, String unionId, String outlayManageSource); +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/ActivityBudgetService.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/ActivityBudgetService.java new file mode 100644 index 00000000..0b9f66f7 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/ActivityBudgetService.java @@ -0,0 +1,28 @@ +package com.budwk.app.zhgh.outlay.activityBudget.service; + +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.outlay.activityBudget.models.ActivityBudget; +import org.nutz.dao.Cnd; +import org.nutz.dao.sql.Sql; + +import javax.servlet.http.HttpServletResponse; + +public interface ActivityBudgetService extends BaseService { + + + Sql getSqlByApplyList(PageForm pageForm, Integer year, String activityMatter, Cnd cnd); + + /** + * 提交年度预算申报 + * @param activityBudget + * @param flag + */ + Result doSubmit(ActivityBudget activityBudget, Boolean flag); + + ActivityBudget findOne(String id); + + + void doExport(Integer year, String activityMatter, HttpServletResponse response); +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/impl/ActivityBudgetApplyStatisticsServiceImpl.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/impl/ActivityBudgetApplyStatisticsServiceImpl.java new file mode 100644 index 00000000..0ceb9d56 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/impl/ActivityBudgetApplyStatisticsServiceImpl.java @@ -0,0 +1,100 @@ +package com.budwk.app.zhgh.outlay.activityBudget.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.flow.entity.ProcessInstance; +import com.budwk.app.flow.entity.ProcessTask; +import com.budwk.app.flow.entity.ProcessTaskActor; +import com.budwk.app.zhgh.outlay.activityBudget.models.ActivityBudget; +import com.budwk.app.zhgh.outlay.activityBudget.service.ActivityBudgetApplyStatisticsService; +import com.budwk.app.zhgh.outlay.outlayManage.school.model.OutlayManageSchool; +import com.budwk.app.zhgh.outlay.outlayManage.union.model.OutlayManageUnion; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.IocBean; + +import java.util.List; + +/** + * @ClassName ActivityBudgetApplyStatisticsServiceImpl + * @Description TODO + * @Author zhf + * @Date 2025/3/5 下午8:21 + */ +@IocBean(args = {"refer:dao"}) +public class ActivityBudgetApplyStatisticsServiceImpl extends BaseServiceImpl implements ActivityBudgetApplyStatisticsService { + public ActivityBudgetApplyStatisticsServiceImpl(Dao dao) { + super(dao); + } + + @Override + public Sql getsql(Integer year, String unionId, String clubId, String outlayManageSource, String activityMatter) { + Sql sql = Sqls.create(""" + SELECT + YEAR(ab.applyDate) year, + ab.*, + ins.id AS instanceId, + ins.businessNo + FROM + activity_budget ab + LEFT JOIN wf_process_instance ins ON ins.businessNo = ab.id + $condition + """); + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(activityMatter)) { + cnd.andEX("ab.activityMatter", "like", "%" + activityMatter + "%"); + } + cnd.andEX("YEAR(ab.applyDate)", "=", year); + cnd.andEX("ab.unionId", "=", unionId); + /* if (outlayManageSource.equals("ACTIVITY_BUDGET_TYPE_TWO")) { + cnd.andEX("ab.isSchoolBudget", "=", 0); + }*/ + cnd.andEX("ab.clubId", "=", clubId); + cnd.andEX("ab.outlayManageSource", "=", outlayManageSource); + cnd.andEX("ins.state", "=", 20); + cnd.desc("ab.applyDate"); + sql.setCondition(cnd); + return sql; + } + + @Override + public void doDelete(String id) { + ActivityBudget budget = dao().fetch(ActivityBudget.class, id); + if (budget.getOutlayManageSource().equals("ACTIVITY_BUDGET_TYPE_ONE")) { + OutlayManageSchool school = dao().fetch(OutlayManageSchool.class, Cnd.where("year", "=", DateUtil.thisYear())); + if (ObjectUtil.isNotEmpty(school)) { + school.setTotalQuota(school.getTotalQuota().subtract(budget.getTotalBudgetMoney())); + updateIgnoreNull(school); + } + } else if (budget.getOutlayManageSource().equals("ACTIVITY_BUDGET_TYPE_TWO")) { + // 更新分工会活动经费表 + OutlayManageUnion union = dao().fetch(OutlayManageUnion.class, Cnd.where("year", "=", DateUtil.thisYear()) + .and("unionId", "=", budget.getUnionId())); + if (ObjectUtil.isNotEmpty(union)) { + union.setTotalQuota(union.getTotalQuota().subtract(budget.getTotalBudgetMoney())); + updateIgnoreNull(union); + } + } + //查出流程实例 + ProcessInstance instance = dao().fetch(ProcessInstance.class, Cnd.where("businessNo", "=", id)); + if (ObjectUtil.isNotEmpty(instance)) { + //查询流程任务 + List taskList = dao().query(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "=", instance.getId())); + List taskIds = taskList.stream().map(ProcessTask::getId).toList(); + //删除流程任务下面所有的人员 + dao().clear(ProcessTask.class, Cnd.where(ProcessTaskActor::getProcessTaskId, "in", taskIds)); + //删除流程任务 + dao().clear(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "=", instance.getId())); + //删除流程实例 + dao().delete(ProcessInstance.class, instance.getId()); + //删除预算 + dao().delete(ActivityBudget.class, id); + } + + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/impl/ActivityBudgetQueryStatisticsServiceImpl.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/impl/ActivityBudgetQueryStatisticsServiceImpl.java new file mode 100644 index 00000000..dbaba73e --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/impl/ActivityBudgetQueryStatisticsServiceImpl.java @@ -0,0 +1,90 @@ +package com.budwk.app.zhgh.outlay.activityBudget.service.impl; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.outlay.activityBudget.service.ActivityBudgetQueryStatisticsService; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; + +import java.util.ArrayList; +import java.util.List; + +@IocBean(args = {"refer:dao"}) +public class ActivityBudgetQueryStatisticsServiceImpl extends BaseServiceImpl implements ActivityBudgetQueryStatisticsService { + public ActivityBudgetQueryStatisticsServiceImpl(Dao dao) { + super(dao); + } + + @Override + public List getDataByBudgetTypeCode(Integer year, String clubId, String unionId, String outlayManageSource) { + if (List.of("ACTIVITY_BUDGET_TYPE_ONE").contains(outlayManageSource)) { + Sql sql = Sqls.create(""" + SELECT + @year `year`, + ab.activityMatter, + ab.totalBudgetMoney + FROM + activity_budget ab + LEFT JOIN wf_process_instance wpi ON wpi.businessNo = ab.id + $condition + """).setParam("year", year); + Cnd cnd = Cnd.NEW(); + cnd.andEX("YEAR(ab.applyDate)", "=", year); + cnd.andEX("ab.outlayManageSource", "=", outlayManageSource); + cnd.andEX("wpi.state", "=", 20); + sql.setCondition(cnd); + return listMap(sql); + } else if (outlayManageSource.equals("ACTIVITY_BUDGET_TYPE_TWO")) { + //分工会 + Sql sql = Sqls.create(""" + SELECT + @year `year`, + un.unionCode, + un.name AS unionName, + ab.unionId, + COALESCE ( SUM( ab.totalBudgetMoney ), 0 ) AS totalBudgetMoney + FROM + activity_budget ab + LEFT JOIN sys_union un ON ab.unionId = un.id + LEFT JOIN wf_process_instance wpi ON wpi.businessNo = ab.id + $condition + """).setParam("year", year); + Cnd cnd = Cnd.NEW(); + cnd.andEX("ab.unionId", "=", unionId); + cnd.andEX("ab.isSchoolBudget", "=", 0); + cnd.andEX("ab.outlayManageSource", "=", "ACTIVITY_BUDGET_TYPE_TWO"); + cnd.andEX("wpi.state", "=", 20); + cnd.andEX("YEAR(ab.applyDate)", "=", year); + cnd.groupBy("ab.unionId"); + cnd.asc("un.unionCode"); + sql.setCondition(cnd); + return listMap(sql); + + } else if (outlayManageSource.equals("ACTIVITY_BUDGET_TYPE_THREE")) { + /* Sql sql = Sqls.create(""" + SELECT + @year `year`, + sc.`code` AS clubCode, + sc.`name` AS clubName, + COALESCE ( SUM( ab.totalBudgetMoney ), 0 ) AS totalBudgetMoney + FROM + sys_club sc + LEFT JOIN activity_budget ab ON ab.clubId = sc.id + AND ab.outlayManageSource = 'ACTIVITY_BUDGET_TYPE_THREE' + AND ab.auditState = 4 + AND YEAR(ab.applyDate)=@year + $condition + """).setParam("year", year); + Cnd cnd = Cnd.NEW(); + cnd.andEX("sc.id", "=", clubId); + cnd.groupBy("sc.id"); + cnd.asc("sc.`code`"); + sql.setCondition(cnd); + return listMap(sql);*/ + } + return new ArrayList<>(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/impl/ActivityBudgetServiceImpl.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/impl/ActivityBudgetServiceImpl.java new file mode 100644 index 00000000..b3daa80a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/service/impl/ActivityBudgetServiceImpl.java @@ -0,0 +1,249 @@ +package com.budwk.app.zhgh.outlay.activityBudget.service.impl; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.model.Audit; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.sys.models.Sys_dict; +import com.budwk.app.sys.services.SysDictService; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.outlay.activityBudget.models.ActivityBudget; +import com.budwk.app.zhgh.outlay.activityBudget.models.ActivityBudgetDetails; +import com.budwk.app.zhgh.outlay.activityBudget.service.ActivityBudgetService; +import com.budwk.app.zhgh.outlay.outlayManage.school.model.OutlayManageSchool; +import com.budwk.app.zhgh.outlay.outlayManage.union.model.OutlayManageUnion; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; + +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.List; + +/** + * @author zhf + * @date 2025/7/21 11:32 + * @description + */ +@IocBean(args = {"refer:dao"}) +public class ActivityBudgetServiceImpl extends BaseServiceImpl implements ActivityBudgetService { + public ActivityBudgetServiceImpl(Dao dao) { + super(dao); + } + + @Inject + private SysDictService sysDictService; + + @Override + public Sql getSqlByApplyList(PageForm pageForm, Integer year, String activityMatter,Cnd cnd) { + + Sql sql = Sqls.create(""" + SELECT + info.*, + YEAR(info.applyDate) year, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariale, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariale + FROM + activity_budget info + LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id + LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id + AND t.taskState = 10 + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + $condition + """); + if (StrUtil.isNotBlank(activityMatter)) { + cnd.andEX("info.activityMatter", "like", "%" + activityMatter + "%"); + } + SqlExpressionGroup group = new SqlExpressionGroup(); + if (AuthUtil.hasRoleOr(RoleConstant.BRANCH_UNION_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_ADMIN.name())) { + SqlExpressionGroup group1 = new SqlExpressionGroup(); + group1.or("info.outlayManageSource", "=", "ACTIVITY_BUDGET_TYPE_TWO"); + group1.and("info.unionId", "=", SecurityUtil.getUnionId()); + group.or(group1); + } + /*if (ShiroUtil.hasAnyRoles("club01,club05")) { + SqlExpressionGroup group1 = new SqlExpressionGroup(); + SqlExpressionGroup group2 = new SqlExpressionGroup(); + group2.or("ab.outlayManageSource", "=", "ACTIVITY_BUDGET_TYPE_THREE"); + group2.or("ab.outlayManageSource", "=", "ACTIVITY_BUDGET_TYPE_FOUR"); + List clubIds = this.getClubsByRole().stream().map(v -> v.getString("id")).toList(); + group1.and("ab.clubId", "in", clubIds); + group1.and(group2); + group.or(group1); + }*/ + if (AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + SqlExpressionGroup group1 = new SqlExpressionGroup(); + group1.and("info.outlayManageSource", "=", "ACTIVITY_BUDGET_TYPE_ONE"); + group1.or("info.loginName", "=", SecurityUtil.getUserLoginname()); + group.or(group1); + } + cnd.and(group); + cnd.andEX("YEAR(info.applyDate)", "=", year); + cnd.desc("info.applyDate"); + sql.setCondition(cnd); + return sql; + } + + @Override + public Result doSubmit(ActivityBudget activityBudget, Boolean flag) { + if (flag) { + activityBudget.setAuditState(1); + } + + if (StrUtil.isEmpty(activityBudget.getId())) { + activityBudget.setUserId(SecurityUtil.getUserId()); + activityBudget.setLoginName(SecurityUtil.getUserLoginname()); + activityBudget.setUserName(SecurityUtil.getUserUsername()); + //查询分工会这个项目有没有申报过 + if (List.of("ACTIVITY_BUDGET_TYPE_TWO").contains(activityBudget.getOutlayManageSource())) { + int activityMatterCount = count(Cnd.where("activityMatter", "=", + activityBudget.getActivityMatter()).and("unionId", "=", SecurityUtil.getUnionId())); + if (flag && activityMatterCount > 0) { + return Result.error(activityBudget.getActivityMatter() + "已填写申请!"); + } + } + } + //删除预算详情表 + if (StrUtil.isNotBlank(activityBudget.getId()) ) { + dao().clear(ActivityBudgetDetails.class, Cnd.where("budgetId", "=", activityBudget.getId())); + } + + if (List.of("superadmin").contains(SecurityUtil.getUserLoginname())) { + //如果是超级管理员就可以直接提交不用审核 + if (flag) { + activityBudget.setAuditState(4); + activityBudget.setTotalBudgetMoney(activityBudget.getDeclareTotalBudgetMoney()); + ActivityBudget budget = null; + if (StrUtil.isNotBlank(activityBudget.getId())) { + budget = fetch(activityBudget.getId()); + } + //如果申报的是校工会预算 + if (activityBudget.getOutlayManageSource().equals("ACTIVITY_BUDGET_TYPE_ONE")) { + OutlayManageSchool outlayManageSchool = dao().fetch(OutlayManageSchool.class, Cnd.where("year", "=", DateUtil.thisYear())); + if (ObjectUtil.isNotEmpty(outlayManageSchool)) { + if (StrUtil.isNotBlank(activityBudget.getId())) { + //如果传过来有预算Id,代表是修改的,那么就减去原来的金额 + outlayManageSchool.setTotalQuota(outlayManageSchool.getTotalQuota().subtract(budget.getTotalBudgetMoney())); + } + //直接修改为现在传过来的金额 + outlayManageSchool.setTotalQuota(outlayManageSchool.getTotalQuota().add(activityBudget.getTotalBudgetMoney())); + updateIgnoreNull(outlayManageSchool); + } + } else if (activityBudget.getOutlayManageSource().equals("ACTIVITY_BUDGET_TYPE_TWO")) { + //如果申报的是分工会预算 + OutlayManageUnion outlayManageUnion = dao().fetch(OutlayManageUnion.class, + Cnd.where("year", "=", DateUtil.thisYear()) + .and("unionId", "=", activityBudget.getUnionId())); + if (ObjectUtil.isNotEmpty(outlayManageUnion)) { + if (StrUtil.isNotBlank(activityBudget.getId())) { + outlayManageUnion.setTotalQuota(outlayManageUnion.getTotalQuota().subtract(budget.getTotalBudgetMoney())); + } + outlayManageUnion.setTotalQuota(outlayManageUnion.getTotalQuota().add(activityBudget.getTotalBudgetMoney())); + updateIgnoreNull(outlayManageUnion); + } + } else if (activityBudget.getOutlayManageSource().equals("ACTIVITY_BUDGET_TYPE_THREE")) { + //如果不等于校工会预算才往表里面加预算 + //代表协会可能用的是校工会的预算 + if (!activityBudget.getIsSchoolBudget()) { + /* jf_club jfClub = dao.fetch(jf_club.class, Cnd.where("year", "=", DateUtil.getYear()) + .and("club_id", "=", activityBudget.getClubId())); + if (ObjectUtil.isNotEmpty(jfClub)) { + if (StrUtil.isNotBlank(activityBudget.getId())) { + jfClub.setTotalQuota(jfClub.getTotalQuota().subtract(budget.getTotalBudgetMoney())); + } + jfClub.setTotalQuota(jfClub.getTotalQuota().add(activityBudget.getTotalBudgetMoney())); + dao.updateIgnoreNull(jfClub); + }*/ + } + } else if (activityBudget.getOutlayManageSource().equals("ACTIVITY_BUDGET_TYPE_FOUR")) { + // 更新其他经费表 + /*JfOther jfOther = dao.fetch(JfOther.class, Cnd.where("year", "=", DateUtil.getYear())); + if (ObjectUtil.isNotEmpty(jfOther)) { + if (StrUtil.isNotBlank(activityBudget.getId())) { + jfOther.setTotalQuota(jfOther.getTotalQuota().subtract(budget.getTotalBudgetMoney())); + } + jfOther.setTotalQuota(jfOther.getTotalQuota().add(activityBudget.getTotalBudgetMoney())); + dao.updateIgnoreNull(jfOther); + }*/ + } + } + } + + + insertOrUpdate(activityBudget); + for (ActivityBudgetDetails details : activityBudget.getBudgetDetails()) { + details.setBudgetId(activityBudget.getId()); + } + //添加预算详情表 + insert(activityBudget.getBudgetDetails()); + + return Result.success(); + } + + @Override + public ActivityBudget findOne(String id) { + ActivityBudget activityBudget = fetchLinks(fetch(id), "budgetDetails", Cnd.NEW().asc("detailsOrder")); + activityBudget.setSchoolAudit(dao().fetch(Audit.class, Cnd.where("id", "=", activityBudget.getSchoolAuditId()))); +// activityBudget.setAllocationEditAuditList(dao().query(Audit.class, Cnd.where("parentId", "=", activityBudget.getId()))); + return activityBudget; + } + + @Override + public void doExport(Integer year, String activityMatter, HttpServletResponse response) { + + Sql sql = getSqlByApplyList(null, year, activityMatter,Cnd.NEW()); + List mapList = listMap(sql); + List dictList = sysDictService.getSubListByCode("ACTIVITY_BUDGET_TYPE"); + mapList.forEach(map -> { + Sys_dict dict = dictList.stream().filter(d -> d.getCode().equals(map.getString("outlayManageSource"))).findFirst().orElse(null); + map.put("outlayManageSource", dict.getName()); + }); + List entities = new ArrayList<>(); + entities.add(new ExcelExportEntity("年度", "year", 20)); + entities.add(new ExcelExportEntity("申报人姓名", "userName", 20)); + entities.add(new ExcelExportEntity("申报人工号", "loginName", 20)); + entities.add(new ExcelExportEntity("联系方式", "mobile", 20)); + entities.add(new ExcelExportEntity("申报类型", "outlayManageSource", 20)); + entities.add(new ExcelExportEntity("申报单位", "helpUnitName", 20)); + entities.add(new ExcelExportEntity("事项", "activityMatter", 20)); + ExcelExportEntity draftCodeEntity = new ExcelExportEntity("申报预算金额", "declareTotalBudgetMoney", 20); + draftCodeEntity.setType(10); + entities.add(draftCodeEntity); + ExcelExportEntity draftCodeEntity2 = new ExcelExportEntity("审核预算金额", "totalBudgetMoney", 20); + draftCodeEntity2.setType(10); + entities.add(draftCodeEntity2); + entities.add(new ExcelExportEntity("申报时间", "applyDate", 20)); + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, mapList); + CommonDownloadUtil.download("预算申报汇总表.xlsx", workbook, response); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/template/ActivityBudgetTemp.java b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/template/ActivityBudgetTemp.java new file mode 100644 index 00000000..97ea8728 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/activityBudget/template/ActivityBudgetTemp.java @@ -0,0 +1,55 @@ +package com.budwk.app.zhgh.outlay.activityBudget.template; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.alibaba.excel.annotation.write.style.ContentRowHeight; +import com.alibaba.excel.annotation.write.style.HeadRowHeight; +import com.budwk.app.base.model.ExcelImportError; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @ClassName ActivityBudgetTemp + * @Description TODO + * @Author zhf + * @Date 2025/3/12 上午11:13 + */ +@Data +@EqualsAndHashCode +@ContentRowHeight(20) // 内容行高 +@HeadRowHeight(20) // 表头行高 +@ColumnWidth(25) +public class ActivityBudgetTemp extends ExcelImportError { + + + @ExcelProperty("活动时间") + private String activityDate; + + @ExcelProperty("活动项目名称") + private String activityMatter; + + @ExcelProperty("活动内容概述") + private String activityContent; + + @ExcelProperty("联系方式") + private String mobile; + + @ExcelProperty("预算类型(请在下拉菜单中选择)") + private String outlayManageSource; + + @ExcelProperty("审核预算") + private String totalBudgetMoney; + + @ExcelProperty("预算金额") + private String declareTotalBudgetMoney; + + @ExcelProperty("审核意见") + private String auditOpinion; + + @ExcelProperty("申报单位(仅社团申报时可在下拉菜单中选择,其他类型不用填写)") + private String helpUnitName; + + + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/model/OutlayUseDetail.java b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/model/OutlayUseDetail.java new file mode 100644 index 00000000..0d6b50f5 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/model/OutlayUseDetail.java @@ -0,0 +1,79 @@ +package com.budwk.app.zhgh.outlay.outlayManage.model; + +import com.budwk.app.base.model.BaseModel; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @author zhf + * @date 2025/7/21 17:36 + * @description 经费使用详情 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("outlay_use_detail") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("经费使用详情") +public class OutlayUseDetail extends BaseModel implements Serializable { + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + @Column + @Comment("预算Id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String outlayManageId; + + @Column + @Comment("项目") + @ColDefine(type = ColType.VARCHAR, width = 255) + private String projectName; + + @Column + @Comment("调整金额") + @Default("0") + @ColDefine(customType = "decimal(10,2)") + private BigDecimal adjustMoney; + + @Column + @Comment("调整事由") + @ColDefine(type = ColType.TEXT) + private String adjustReason; + + @Column + @Comment("调整人") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String adjustUserId; + + @Column + @Comment("调整人姓名") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String adjustUserName; + + @Column + @Comment("调整人姓名") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String adjustLoginName; + + @Column + @Comment("活动人数") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String activityNumber; + + @Column + @Comment("活动时间") + @ColDefine(type = ColType.VARCHAR) + private String activityTime; + + + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/school/controller/OutlayManageSchoolController.java b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/school/controller/OutlayManageSchoolController.java new file mode 100644 index 00000000..1f40f041 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/school/controller/OutlayManageSchoolController.java @@ -0,0 +1,125 @@ +package com.budwk.app.zhgh.outlay.outlayManage.school.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.aspose.slides.internal.og.bas; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.outlay.activityBudget.models.ActivityBudget; +import com.budwk.app.zhgh.outlay.outlayManage.school.model.OutlayManageSchool; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Objects; + +/** + * @author zhf + * @date 2025/7/21 14:37 + * @description 校工会经费预算管理 + */ +@IocBean +@At("/platform/outlay/outlayManage/schoolManage") +@Ok("json:full") +@Slf4j +@Api(tags = "校工会经费预算管理") +public class OutlayManageSchoolController { + + + @Inject + private BaseService baseService; + + @At("") + @Ok("beetl:/platform/zhgh/outlay/outlayManage/school/manage/index.html") + @SaCheckPermission("outlay.outlayManage.school.manage") + public void index() { + } + + + @At + @ApiOperation("分页查询") + @SaCheckPermission("outlay.outlayManage.school.manage") + public Result pageData(PageForm pageForm, Integer year) { + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(""" + SELECT * FROM `outlay_manage_school` $condition + """); + cnd.andEX("year", "=", year); + sql.setCondition(cnd); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + + @At + @ApiOperation("修改预算") + @SaCheckPermission("outlay.outlayManage.school.manage") + @SLog(tag = "校工会预算分配", msg = "修改了预算分配的金额:${args[0]},id:${args[1]}") + public Result doSubmit(String totalQuota, String id) { + OutlayManageSchool outlayManageSchool = baseService.dao().fetch(OutlayManageSchool.class, id); + outlayManageSchool.setTotalQuota(new BigDecimal(totalQuota)); + baseService.updateIgnoreNull(outlayManageSchool); + return Result.success(); + } + + + @At + @ApiOperation("查看是否分配") + @SaCheckPermission("outlay.outlayManage.school.manage") + public Result getIsAllocationOutlay(Integer year) { + int count = baseService.dao().count(OutlayManageSchool.class, Cnd.where("year", "=", year)); + return Result.success(count); + } + + @At + @ApiOperation("重置预算") + @SaCheckPermission("outlay.outlayManage.school.manage") + @SLog(tag = "校工会预算分配", msg = "重置了预算分配的金额:${args[0]}") + public Result resetOutlay(Integer year) { + int count = baseService.dao().clear(OutlayManageSchool.class, Cnd.where("year", "=", year)); + return Result.success(count); + } + + @At + @ApiOperation("下发预算") + @SaCheckPermission("outlay.outlayManage.school.manage") + @SLog(tag = "校工会预算分配", msg = "下发预算的金额:${args[0]}") + public Result issuedOutlay() { + Sql sql = Sqls.create(""" + SELECT + totalBudgetMoney + FROM + activity_budget ab + LEFT JOIN wf_process_instance wpi ON wpi.businessNo = ab.id + WHERE + YEAR(ab.applyDate) = @year + AND ab.outlayManageSource = 'ACTIVITY_BUDGET_TYPE_ONE' + AND wpi.state = 20 + """).setParam("year",DateUtil.thisYear()); + List budgetList = baseService.listMap(sql); + BigDecimal totalBudgetMoney = budgetList.stream() + .map(v->new BigDecimal(v.getString("totalBudgetMoney"))) // 提取 money 属性 + .reduce(BigDecimal.ZERO, BigDecimal::add); + OutlayManageSchool outlayManageSchool = new OutlayManageSchool(); + outlayManageSchool.setYear(DateUtil.thisYear()); + outlayManageSchool.setTotalQuota(totalBudgetMoney); + baseService.insert(outlayManageSchool); + return Result.success(); + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/school/controller/OutlayManageSchoolUseDetailController.java b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/school/controller/OutlayManageSchoolUseDetailController.java new file mode 100644 index 00000000..5e5a7c26 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/school/controller/OutlayManageSchoolUseDetailController.java @@ -0,0 +1,128 @@ +package com.budwk.app.zhgh.outlay.outlayManage.school.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.outlay.outlayManage.model.OutlayUseDetail; +import com.budwk.app.zhgh.outlay.outlayManage.school.model.OutlayManageSchool; +import com.budwk.app.zhgh.outlay.outlayManage.service.OutlayUseDetailService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @author zhf + * @date 2025/7/21 15:59 + * @description 校工会预算使用明细 + */ +@IocBean +@At("/platform/outlay/outlayManage/schoolUseDetail") +@Ok("json:full") +@Slf4j +@Api(tags = "校工会预算使用明细") +public class OutlayManageSchoolUseDetailController { + + + @Inject + private BaseService baseService; + @Inject + private OutlayUseDetailService outlayUseDetailService; + + @At("") + @Ok("beetl:/platform/zhgh/outlay/outlayManage/school/useDetail/index.html") + @SaCheckPermission("outlay.outlayManage.school.useDetail") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("outlay.outlayManage.school.useDetail") + public Result pageData(PageForm pageForm, String outlayManageId,String projectName) { + Sql sql = Sqls.create(""" + select * from outlay_use_detail $condition + """); + Cnd cnd = Cnd.NEW(); + if (Strings.isNotBlank(projectName)) { + cnd.and("projectName", "LIKE", "%" + projectName + "%"); + } + cnd.and("outlayManageId", "=", outlayManageId); + sql.setCondition(cnd); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @ApiOperation("查询校工会所有的预算") + @SaCheckPermission("outlay.outlayManage.school.useDetail") + public Result getOutlayManageList() { + List schoolList = baseService.dao().query(OutlayManageSchool.class, Cnd.NEW().desc("year")); + return Result.success(schoolList); + } + + @At + @ApiOperation("查询报销了有多少钱") + @SaCheckPermission("outlay.outlayManage.school.useDetail") + public Result getApplyMoney(String outlayManageId,String projectName) { + OutlayManageSchool school = baseService.dao().fetch(OutlayManageSchool.class, Cnd.where("id", "=", outlayManageId)); + if (StrUtil.isEmpty(outlayManageId)){ + return Result.success(Map.of("totalMoney", 0, "totalQuota", school.getTotalQuota(), "usedQuota", school.getUsedQuota())); + } + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotEmpty(projectName)){ + cnd.and("projectName", "LIKE", "%" + projectName + "%"); + } + cnd.and("outlayManageId", "=", outlayManageId); + List newList = baseService.dao().query(OutlayUseDetail.class, cnd); + BigDecimal totalMoney = newList.stream() + .map(OutlayUseDetail::getAdjustMoney) + .filter(Objects::nonNull) // 避免 null 值导致计算错误 + .reduce(BigDecimal.ZERO, BigDecimal::add); + return Result.success(Map.of("totalMoney", totalMoney, "totalQuota", school.getTotalQuota(), "usedQuota", school.getUsedQuota())); + } + + @At + @ApiOperation("删除校工会预算详情") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("outlay.outlayManage.school.useDetail") + @SLog(tag = "校工会预算使用详情", msg = "删除了校工会预算使用详情:${args[0]}") + public Result doDeleteDetail(String id) { + outlayUseDetailService.doDeleteDetail(id,"school"); + return Result.success(); + } + + @At + @ApiOperation("编辑校工会预算详情") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("outlay.outlayManage.school.useDetail") + @SLog(tag = "校工会预算使用详情", msg = "编辑了校工会预算使用详情:${args[0]}") + public Result doEditDetail(OutlayUseDetail outlayUseDetail) { + outlayUseDetailService.doEditDetail(outlayUseDetail,"school"); + return Result.success(); + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/school/model/OutlayManageSchool.java b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/school/model/OutlayManageSchool.java new file mode 100644 index 00000000..73313f17 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/school/model/OutlayManageSchool.java @@ -0,0 +1,46 @@ +package com.budwk.app.zhgh.outlay.outlayManage.school.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @author zhf + * @date 2025/7/21 14:31 + * @description 校工会经费管理 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("outlay_manage_school") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("校工会经费管理") +public class OutlayManageSchool extends BaseModel implements Serializable { + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + @Column + @Comment("年份") + @ColDefine(type = ColType.INT) + private Integer year; + + @Column + @Comment("总额度") + @Default("0") + @ColDefine(customType = "decimal(10,2)") + private BigDecimal totalQuota; + + @Column + @Comment("已使用额度") + @Default("0") + @ColDefine(customType = "decimal(10,2)") + private BigDecimal usedQuota; +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/service/OutlayUseDetailService.java b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/service/OutlayUseDetailService.java new file mode 100644 index 00000000..3051054e --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/service/OutlayUseDetailService.java @@ -0,0 +1,16 @@ +package com.budwk.app.zhgh.outlay.outlayManage.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.outlay.outlayManage.model.OutlayUseDetail; + +public interface OutlayUseDetailService extends BaseService { + + + /** + * 删除预算详情表数据 + * @param id 详情的id + * @param outlayType 预算类型/school/union/club等 + */ + void doDeleteDetail(String id,String outlayType); + void doEditDetail(OutlayUseDetail outlayUseDetail,String outlayType); +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/service/impl/OutlayUseDetailServiceImpl.java b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/service/impl/OutlayUseDetailServiceImpl.java new file mode 100644 index 00000000..0d5173e6 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/service/impl/OutlayUseDetailServiceImpl.java @@ -0,0 +1,71 @@ +package com.budwk.app.zhgh.outlay.outlayManage.service.impl; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.outlay.outlayManage.model.OutlayUseDetail; +import com.budwk.app.zhgh.outlay.outlayManage.school.model.OutlayManageSchool; +import com.budwk.app.zhgh.outlay.outlayManage.service.OutlayUseDetailService; +import com.budwk.app.zhgh.outlay.outlayManage.union.model.OutlayManageUnion; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +import java.math.BigDecimal; + +/** + * @author zhf + * @date 2025/7/25 11:30 + * @description + */ +@IocBean(args = {"refer:dao"}) +public class OutlayUseDetailServiceImpl extends BaseServiceImpl implements OutlayUseDetailService { + public OutlayUseDetailServiceImpl(Dao dao) { + super(dao); + } + + @Override + public void doDeleteDetail(String id, String outlayType) { + //更新预算表的金额 + updateOutlayManage(id, null,outlayType,false); + //更新完删除 + delete(id); + } + + @Override + public void doEditDetail(OutlayUseDetail outlayUseDetail,String outlayType) { + updateOutlayManage(outlayUseDetail.getId(), outlayUseDetail,outlayType,true); + update(outlayUseDetail); + + } + + + /** + * 更新预算表 + * + * @param id + * @param outlayType + */ + private void updateOutlayManage(String id, OutlayUseDetail outlayUseDetail,String outlayType,Boolean isEdit) { + //找到是哪一条的预算详情 + OutlayUseDetail detail = fetch(id); + //拿到预算详情的调整金额 + if (outlayType.equals("school")) { + //找到预算分配的记录 + OutlayManageSchool manageSchool = dao().fetch(OutlayManageSchool.class, detail.getOutlayManageId()); + manageSchool.setUsedQuota(manageSchool.getUsedQuota().subtract(detail.getAdjustMoney())); + if (isEdit){ + //如果是修改,就先减去原来的值在加上现在新的值 + manageSchool.setUsedQuota(manageSchool.getUsedQuota().add(outlayUseDetail.getAdjustMoney())); + } + update(manageSchool); + } else if (outlayType.equals("union")) { + OutlayManageUnion manageUnion = dao().fetch(OutlayManageUnion.class, detail.getOutlayManageId()); + manageUnion.setUsedQuota(manageUnion.getUsedQuota().subtract(detail.getAdjustMoney())); + if (isEdit){ + //如果是修改,就先减去原来的值在加上现在新的值 + manageUnion.setUsedQuota(manageUnion.getUsedQuota().add(outlayUseDetail.getAdjustMoney())); + } + update(manageUnion); + } + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/union/controller/OutlayManageUnionController.java b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/union/controller/OutlayManageUnionController.java new file mode 100644 index 00000000..9cce8ed6 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/union/controller/OutlayManageUnionController.java @@ -0,0 +1,143 @@ +package com.budwk.app.zhgh.outlay.outlayManage.union.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.outlay.activityBudget.models.ActivityBudget; +import com.budwk.app.zhgh.outlay.outlayManage.school.model.OutlayManageSchool; +import com.budwk.app.zhgh.outlay.outlayManage.union.model.OutlayManageUnion; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * @author zhf + * @date 2025/7/21 17:17 + * @description 分工会经费预算管理 + */ +@IocBean +@At("/platform/outlay/outlayManage/unionManage") +@Ok("json:full") +@Slf4j +@Api(tags = "分工会经费预算管理") +public class OutlayManageUnionController { + + @Inject + private BaseService baseService; + + @At("") + @Ok("beetl:/platform/zhgh/outlay/outlayManage/union/manage/index.html") + @SaCheckPermission("outlay.outlayManage.union.manage") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("outlay.outlayManage.union.manage") + public Result pageData(PageForm pageForm, Integer year) { + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(""" + SELECT * FROM `outlay_manage_union` $condition + """); + cnd.andEX("year", "=", year); + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.andEX("unionId", "=", SecurityUtil.getUnionId()); + } + cnd.asc("unionCode"); + sql.setCondition(cnd); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + + @At + @ApiOperation("修改预算") + @SaCheckPermission("outlay.outlayManage.union.manage") + @SLog(tag = "分工会预算分配", msg = "修改了预算分配的金额:${args[0]},id:${args[1]}") + public Result doSubmit(String totalQuota, String id) { + OutlayManageUnion outlayManageUnion = baseService.dao().fetch(OutlayManageUnion.class, id); + outlayManageUnion.setTotalQuota(new BigDecimal(totalQuota)); + baseService.updateIgnoreNull(outlayManageUnion); + return Result.success(); + } + + + @At + @ApiOperation("查看是否分配") + @SaCheckPermission("outlay.outlayManage.union.manage") + public Result getIsAllocationOutlay(Integer year) { + int count = baseService.dao().count(OutlayManageUnion.class, Cnd.where("year", "=", year)); + return Result.success(count); + } + + @At + @ApiOperation("重置预算") + @SaCheckPermission("outlay.outlayManage.union.manage") + @SLog(tag = "分工会预算分配", msg = "重置了预算分配的金额:${args[0]}") + public Result resetOutlay(Integer year) { + int count = baseService.dao().clear(OutlayManageUnion.class, Cnd.where("year", "=", year)); + return Result.success(count); + } + + @At + @ApiOperation("下发预算") + @SaCheckPermission("outlay.outlayManage.union.manage") + @SLog(tag = "分工会预算分配", msg = "根据申报的金额修改本年的预算预算") + public Result issuedOutlay() { + Sql sql = Sqls.create(""" + SELECT + unionId, + totalBudgetMoney + FROM + activity_budget ab + LEFT JOIN wf_process_instance wpi ON wpi.businessNo = ab.id + WHERE + YEAR(ab.applyDate) = @year + AND ab.outlayManageSource = 'ACTIVITY_BUDGET_TYPE_TWO' + AND wpi.state = 20 + """).setParam("year", DateUtil.thisYear()); + List budgetList = baseService.listMap(sql); + + List unionList = baseService.dao().query(Sys_union.class, Cnd.NEW()); + + List insertUnionList = new ArrayList<>(); + unionList.forEach(v -> { + BigDecimal totalBudgetMoney = budgetList.stream() + .filter(budget -> budget.getString("unionId").equals(v.getId())) + .map(budget -> new BigDecimal(budget.getString("totalBudgetMoney"))) // 提取 money 属性 + .reduce(BigDecimal.ZERO, BigDecimal::add); + OutlayManageUnion outlayManageUnion = new OutlayManageUnion(); + outlayManageUnion.setYear(DateUtil.thisYear()); + outlayManageUnion.setUnionName(v.getName()); + outlayManageUnion.setUnionCode(v.getUnionCode()); + outlayManageUnion.setUnionId(v.getId()); + outlayManageUnion.setTotalQuota(totalBudgetMoney); + insertUnionList.add(outlayManageUnion); + }); + baseService.insert(insertUnionList); + return Result.success(); + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/union/controller/OutlayManageUnionUseDetailController.java b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/union/controller/OutlayManageUnionUseDetailController.java new file mode 100644 index 00000000..32159c6d --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/union/controller/OutlayManageUnionUseDetailController.java @@ -0,0 +1,117 @@ +package com.budwk.app.zhgh.outlay.outlayManage.union.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.outlay.outlayManage.model.OutlayUseDetail; +import com.budwk.app.zhgh.outlay.outlayManage.service.OutlayUseDetailService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @author zhf + * @date 2025/7/21 17:19 + * @description 分工会预算使用明细 + */ +@IocBean +@At("/platform/outlay/outlayManage/unionUseDetail") +@Ok("json:full") +@Slf4j +@Api(tags = "分工会预算使用明细") +public class OutlayManageUnionUseDetailController { + + @Inject + private BaseService baseService; + @Inject + private OutlayUseDetailService outlayUseDetailService; + + @At("") + @Ok("beetl:/platform/zhgh/outlay/outlayManage/union/useDetail/index.html") + @SaCheckPermission("outlay.outlayManage.union.useDetail") + public void index() { + } + + + @At + @ApiOperation("分页查询") + @SaCheckPermission("outlay.outlayManage.union.useDetail") + public Result pageData(PageForm pageForm, + Integer year, + String unionId) { + Sql sql = Sqls.create(""" + select * from outlay_manage_union $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("totalQuota", "IS NOT", null); + cnd.and("year", "=", year); + + if (AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.andEX("unionId", "=", unionId); + } else { + cnd.and("unionId", "=", SecurityUtil.getUnionId()); + } + + if (Strings.isNotBlank(pageForm.getPageOrderBy()) && Strings.isNotBlank(pageForm.getPageOrderName())) { + cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } else { + cnd.asc("unionCode"); + } + sql.setCondition(cnd); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + + @At + @ApiOperation("某个分工会预算使用详情") + @SaCheckPermission("outlay.outlayManage.union.useDetail") + public Result detailInfo(PageForm pageForm, String outlayManageId) { + Sql sql = Sqls.create(""" + select * from outlay_use_detail where outlayManageId=@outlayManageId + """).setParam("outlayManageId", outlayManageId); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + + @At + @ApiOperation("删除分工会预算详情") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("outlay.outlayManage.union.useDetail") + @SLog(tag = "分工会预算使用详情", msg = "删除了分工会预算使用详情:${args[0]}") + public Result doDeleteDetail(String id) { + outlayUseDetailService.doDeleteDetail(id,"union"); + return Result.success(); + } + + + @At + @ApiOperation("编辑分工会预算详情") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("outlay.outlayManage.union.useDetail") + @SLog(tag = "分工会预算使用详情", msg = "编辑了分工会预算使用详情:${args[0]}") + public Result doEditDetail(OutlayUseDetail outlayUseDetail) { + outlayUseDetailService.doEditDetail(outlayUseDetail,"union"); + return Result.success(); + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/union/model/OutlayManageUnion.java b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/union/model/OutlayManageUnion.java new file mode 100644 index 00000000..658b3771 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/outlayManage/union/model/OutlayManageUnion.java @@ -0,0 +1,62 @@ +package com.budwk.app.zhgh.outlay.outlayManage.union.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @author zhf + * @date 2025/7/21 17:22 + * @description 分工会经费管理 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("outlay_manage_union") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("分工会经费管理") +public class OutlayManageUnion extends BaseModel implements Serializable { + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + @Column + @Comment("年份") + @ColDefine(type = ColType.INT) + private Integer year; + + @Column + @Comment("总额度") + @Default("0") + @ColDefine(customType = "decimal(10,2)") + private BigDecimal totalQuota; + + @Column + @Comment("已使用额度") + @Default("0") + @ColDefine(customType = "decimal(10,2)") + private BigDecimal usedQuota; + + @Column + @Comment("院级工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("院级工会名称") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionName; + + @Column + @Comment("院级工会code") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionCode; + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/controller/OutlayReimburseApplyListController.java b/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/controller/OutlayReimburseApplyListController.java new file mode 100644 index 00000000..a0e31920 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/controller/OutlayReimburseApplyListController.java @@ -0,0 +1,80 @@ +package com.budwk.app.zhgh.outlay.outlayReimburse.controller; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.outlay.outlayReimburse.service.OutlayReimburseApplyListService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @author zhf + * @date 2025/7/30 15:22 + * @description 我的报销 + */ +@IocBean +@At("/platform/outlay/reimburse/apply") +@Ok("json:full") +@Api("我的报销") +public class OutlayReimburseApplyListController { + + @Inject + private OutlayReimburseApplyListService outlayReimburseApplyListService; + + @At("/index") + @Ok("beetl:/platform/zhgh/outlay/outlayReimburse/apply/index.html") + @SaCheckPermission("outlay.reimburse.apply") + public void index() { + + } + + @At("/form") + @Ok("beetl:/platform/zhgh/outlay/outlayReimburse/apply/form.html") + @SaCheckPermission("outlay.reimburse.apply") + public void form() { + } + + @At("/view") + @Ok("beetl:/platform/zhgh/outlay/outlayReimburse/view/index.html") + @SaCheckPermission("outlay.reimburse.apply") + public void view() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("outlay.reimburse.apply") + public Result pageData(PageForm pageForm) { + + + return Result.success(); + } + + + @At + @ApiOperation("获取预算金额或活动") + @SaCheckPermission("outlay.reimburse.apply") + public Result getBudgetMoneyOrActivity(String outlayManageSource, String clubId, String unionId, String id) { + return Result.success(outlayReimburseApplyListService.getBudgetMoneyOrActivity(outlayManageSource, clubId, unionId, id)); + } + + @At + @ApiOperation("查询这个预算已经报销了的金额") + @SaCheckPermission("outlay.reimburse.apply") + public Result getBxMoneyByBudgetId(String budgetId) { + return Result.success(outlayReimburseApplyListService.getBxMoneyByActivityId(budgetId)); + } + + + @At + @ApiOperation("判断这个报销的记录预算是否充足") + @SaCheckPermission("outlay.reimburse.apply") + public Result bxAddValidate(String budgetId, String money, String outlayManageSource,String clubId) { + return outlayReimburseApplyListService.bxAddValidate(budgetId,money, outlayManageSource,clubId); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/interceptor/OutlayReimburseApplyPostInterceptor.java b/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/interceptor/OutlayReimburseApplyPostInterceptor.java new file mode 100644 index 00000000..8d975441 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/interceptor/OutlayReimburseApplyPostInterceptor.java @@ -0,0 +1,34 @@ +package com.budwk.app.zhgh.outlay.outlayReimburse.interceptor; + +import com.budwk.app.flow.constant.FlowConst; +import com.budwk.app.flow.engine.FlowInterceptor; +import com.budwk.app.flow.engine.core.Execution; +import com.budwk.app.flow.engine.core.ServiceContext; +import com.budwk.app.flow.entity.ProcessInstance; +import com.budwk.app.zhgh.democratic.suggestionBox.models.SuggestionBox; +import com.budwk.app.zhgh.outlay.outlayReimburse.model.OutlayReimburse; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.json.Json; + +/** + * @author zhf + * @date 2025/7/30 15:58 + * @description + */ +public class OutlayReimburseApplyPostInterceptor implements FlowInterceptor { + @Override + public void intercept(Execution execution) { + String formDataStr = execution.getArgs().getStr(FlowConst.FORM_DATA); + OutlayReimburse outlayReimburse = Json.fromJson(OutlayReimburse.class, formDataStr); + + Dao dao = ServiceContext.find(Dao.class); + dao.insertOrUpdate(outlayReimburse); + execution.getArgs().set("outlayManageSource", outlayReimburse.getOutlayManageSource()); + execution.getArgs().set(FlowConst.FORM_DATA, Json.toJson(outlayReimburse)); + + int instanceId = execution.getArgs().getInt(FlowConst.PROCESS_INSTANCE_ID_KEY); + dao.update(ProcessInstance.class, Chain.make("businessNo", outlayReimburse.getId()), Cnd.where(ProcessInstance::getId, "=", instanceId)); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/interceptor/OutlayReimburseSchoolZxAuditPostInterceptor.java b/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/interceptor/OutlayReimburseSchoolZxAuditPostInterceptor.java new file mode 100644 index 00000000..cb621f26 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/interceptor/OutlayReimburseSchoolZxAuditPostInterceptor.java @@ -0,0 +1,16 @@ +package com.budwk.app.zhgh.outlay.outlayReimburse.interceptor; + +import com.budwk.app.flow.engine.FlowInterceptor; +import com.budwk.app.flow.engine.core.Execution; + +/** + * @author zhf + * @date 2025/7/30 16:02 + * @description + */ +public class OutlayReimburseSchoolZxAuditPostInterceptor implements FlowInterceptor { + @Override + public void intercept(Execution execution) { + + } +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/model/OutlayReimburse.java b/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/model/OutlayReimburse.java new file mode 100644 index 00000000..0ea7798f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/model/OutlayReimburse.java @@ -0,0 +1,124 @@ +package com.budwk.app.zhgh.outlay.outlayReimburse.model; + +import cn.hutool.json.JSONObject; +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; + +/** + * @author zhf + * @date 2025/7/30 14:53 + * @description 经费报销 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("outlay_reimburse") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("经费报销") +public class OutlayReimburse extends BaseModel implements Serializable { + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + @Column + @Comment("经办人id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String userId; + + @Column + @Comment("经办人姓名") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String userName; + + @Column + @Comment("工号") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String loginName; + + @Column + @Comment("经办人电话") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String mobile; + + @Column + @Comment("单位") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String unitName; + + @Column + @Comment("单位id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("工会") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String unionName; + + @Column + @Comment("工会id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("社团id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String clubId; + + @Column + @Comment("报销经费来源") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String outlayManageSource; + + @Column + @Comment("活动时间") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String activityTime; + + @Column + @Comment("支付内容") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String paymentContent; + + @Column + @Comment("金额") + @ColDefine(customType = "decimal(10,2)") + private BigDecimal money; + + + @Column + @Comment("活动事项") + @ColDefine(type = ColType.VARCHAR, width = 200) + private String activityMatter; + + @Column + @Comment("年度预算id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String budgetId; + + @Column + @Comment("申请时间") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String applyTime; + + @Column + @Comment("附件") + @ColDefine(type = ColType.MYSQL_JSON) + private List files; + + @Column + @Comment("经办人签字") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String userSign; + + +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/service/OutlayReimburseApplyListService.java b/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/service/OutlayReimburseApplyListService.java new file mode 100644 index 00000000..09054156 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/service/OutlayReimburseApplyListService.java @@ -0,0 +1,40 @@ +package com.budwk.app.zhgh.outlay.outlayReimburse.service; + +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.outlay.outlayReimburse.model.OutlayReimburse; +import org.nutz.lang.util.NutMap; + +import java.math.BigDecimal; + +public interface OutlayReimburseApplyListService extends BaseService { + + + /** + * 获取预算金额或活动 + * + * @param outlayManageSource + * @param clubId + * @param unionId + * @param id + * @return + */ + NutMap getBudgetMoneyOrActivity(String outlayManageSource, String clubId, String unionId, String id); + + /** + * 查询这个预算已经报销了的金额 + * @param budgetId + * @return + */ + BigDecimal getBxMoneyByActivityId(String budgetId); + + /** + * 判断这个报销的记录预算是否充足 + * @param budgetId + * @param money + * @param outlayManageSource + * @param clubId + * @return + */ + Result bxAddValidate(String budgetId, String money, String outlayManageSource,String clubId); +} diff --git a/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/service/impl/OutlayReimburseApplyListServiceImpl.java b/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/service/impl/OutlayReimburseApplyListServiceImpl.java new file mode 100644 index 00000000..97433bef --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/outlay/outlayReimburse/service/impl/OutlayReimburseApplyListServiceImpl.java @@ -0,0 +1,260 @@ +package com.budwk.app.zhgh.outlay.outlayReimburse.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.outlay.activityBudget.models.ActivityBudget; +import com.budwk.app.zhgh.outlay.outlayManage.school.model.OutlayManageSchool; +import com.budwk.app.zhgh.outlay.outlayManage.union.model.OutlayManageUnion; +import com.budwk.app.zhgh.outlay.outlayReimburse.model.OutlayReimburse; +import com.budwk.app.zhgh.outlay.outlayReimburse.service.OutlayReimburseApplyListService; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * @author zhf + * @date 2025/7/30 17:38 + * @description + */ +@IocBean(args = {"refer:dao"}) +public class OutlayReimburseApplyListServiceImpl extends BaseServiceImpl implements OutlayReimburseApplyListService { + public OutlayReimburseApplyListServiceImpl(Dao dao) { + super(dao); + } + + @Override + public NutMap getBudgetMoneyOrActivity(String outlayManageSource, String clubId, String unionId, String id) { + + + String sqlStr = """ + SELECT + ab.id, + ab.schoolBudgetId, + ab.totalBudgetMoney, + ab.isRepeatReimburse, + ab.activityMatter + FROM + activity_budget ab + LEFT JOIN wf_process_instance ins ON ins.businessNo = ab.id + $condition + """; + + + //找出可以重复报销的预算,并且是今年的预算 + Sql sql = Sqls.create(sqlStr); + Cnd cnd = Cnd.NEW(); + cnd.and("YEAR(ab.applyDate)", "=", DateUtil.thisYear()); + cnd.and("isRepeatReimburse", "=", true); + cnd.and("ins.state", "=", 20); + sql.setCondition(cnd); + List budgetList = listMap(sql); + List budgetIds = budgetList.stream().map(budget -> budget.getString("id")).toList(); + + //找出已经报销了的年度预算id,排除可以重复报销的预算 + List outlayReimburseList = dao().query(OutlayReimburse.class, + Cnd.NEW().andEX(OutlayReimburse::getId, "!=", id) + .and(OutlayReimburse::getBudgetId, "not in", budgetIds) + .and(OutlayReimburse::getBudgetId, "is not", null)); + List outlayReimburseIds = outlayReimburseList.stream().map(OutlayReimburse::getBudgetId).toList(); + + //找出可以报销的预算 + Sql sql1 = Sqls.create(sqlStr); + Cnd cnd1 = Cnd.NEW(); + cnd1.and("YEAR(ab.applyDate)", "=", DateUtil.thisYear()); + cnd1.and("ab.isRepeatReimburse", "=", true); + cnd1.and("ab.outlayManageSource", "=", outlayManageSource); + cnd1.and("ins.state", "=", 20); + if (outlayManageSource.equals("ACTIVITY_BUDGET_TYPE_TWO")) { + cnd1.and("unionId", "=", StrUtil.isNotBlank(unionId) ? unionId : SecurityUtil.getUnionId()); + } else if (List.of("ACTIVITY_BUDGET_TYPE_THREE").contains(outlayManageSource)) { + cnd1.and("clubId", "=", clubId); + } + cnd1.andEX("ab.id", "not in", outlayReimburseIds); + sql1.setCondition(cnd1); + List canBudgetList = listMap(sql1); + + //查询每个活动预算下面,有没有关联的子活动预算 + canBudgetList.forEach(budget -> { + //找出来这一条活动预算有没有子预算,如果有子预算那么这一条预算肯定是校工会的预算 + List twoLevelBudgetList = budgetList.stream().filter(b -> StrUtil.isNotBlank(b.getString("schoolBudgetId")) + && b.getString("schoolBudgetId").equals(budget.getString("id"))).toList(); + + if (!twoLevelBudgetList.isEmpty()) { + //找出所有子预算的和 + BigDecimal totalBudgetMoney = twoLevelBudgetList.stream().map(twoLevelBudget -> new BigDecimal(twoLevelBudget.getString("totalBudgetMoney"))).reduce(BigDecimal.ZERO, BigDecimal::add); + budget.put("twoLevelTotalBudgetMoney", totalBudgetMoney); + budget.put("twoLevelBudgetList", twoLevelBudgetList); + } else { + budget.put("twoLevelTotalBudgetMoney", 0); + budget.put("twoLevelBudgetList", List.of()); + } + + + }); + + NutMap map = new NutMap(); + + if (outlayManageSource.equals("ACTIVITY_BUDGET_TYPE_ONE")) { + OutlayManageSchool school = dao().fetch(OutlayManageSchool.class, Cnd.where("year", "=", DateUtil.thisYear())); + map.put("budgetMoney", school.getTotalQuota().subtract(school.getUsedQuota())); + } else if (outlayManageSource.equals("ACTIVITY_BUDGET_TYPE_TWO")) { + OutlayManageUnion union = dao().fetch(OutlayManageUnion.class, Cnd.where("year", "=", DateUtil.thisYear()) + .and("unionId", "=", StrUtil.isNotBlank(unionId) ? unionId : SecurityUtil.getUnionId())); + map.put("budgetMoney", ObjectUtil.isNotEmpty(union) ? union.getTotalQuota().subtract(union.getUsedQuota()) : 0); + } else if (outlayManageSource.equals("ACTIVITY_BUDGET_TYPE_THREE")) { + + } + map.put("activityList", canBudgetList); + return map; + } + + @Override + public BigDecimal getBxMoneyByActivityId(String budgetId) { + Sql sql = Sqls.create(""" + SELECT + rei.money + FROM + `outlay_reimburse` rei + LEFT JOIN wf_process_instance ins ON ins.businessNo = rei.id + WHERE + rei.budgetId = @budgetId + AND ins.state = 20 + """).setParam("budgetId", budgetId); + List reiList = listMap(sql); + + BigDecimal totalMoney = reiList.stream() + .map(rei -> new BigDecimal(rei.getString("money"))) + .reduce(BigDecimal.ZERO, BigDecimal::add); + return totalMoney; + } + + @Override + public Result bxAddValidate(String budgetId, String money, String outlayManageSource, String clubId) { + BigDecimal moneyBig = new BigDecimal(money); + if (StrUtil.isAllEmpty(budgetId, outlayManageSource)) { + return Result.error("参数错误"); + } + + if (List.of("ACTIVITY_BUDGET_TYPE_TWO", "ACTIVITY_BUDGET_TYPE_ONE").contains(outlayManageSource)) { + ActivityBudget budget = dao().fetch(ActivityBudget.class, budgetId); + if (outlayManageSource.equals("ACTIVITY_BUDGET_TYPE_TWO")) { + //判断是否可以重复报 + if (budget.getIsRepeatReimburse()) { + //1.查询已经报销了的总金额 + BigDecimal bXMoney = getBxMoneyByActivityId(budgetId); + if (budget.getIsSchoolBudget()) { + //如果是分工会进来并且报销的活动是校会预算 + // 1. 计算本次加上之前的报销总金额 + BigDecimal totalReimbursement = bXMoney.add(moneyBig); + // 2. 判断是否超出预算 + if (totalReimbursement.compareTo(budget.getTotalBudgetMoney()) > 0) { + return Result.error("该活动预算金额不足!"); + } else { + return Result.success(); + } + } else { + //如果是自己的项目就能超20% + //1.算出现在还能报销多少钱 + BigDecimal twentyPercent = budget.getTotalBudgetMoney().multiply(new BigDecimal("20")).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP); + BigDecimal totalBudgetMoney = budget.getTotalBudgetMoney().add(twentyPercent); + // 2. 计算本次加上之前的报销总金额 + BigDecimal totalReimbursement = bXMoney.add(moneyBig); + // 3. 判断是否超出预算的 20% + if (totalReimbursement.compareTo(totalBudgetMoney) > 0) { + return Result.error("该活动预算金额不足!"); + } else { + return Result.success(); + } + } + } else { + //分工会进来报销自己的预算 + //正常判断这个活动是否超出预算 + //算出现在还能报销多少钱 + //判断是否超出预算的 20% + BigDecimal twentyPercent = budget.getTotalBudgetMoney().multiply(new BigDecimal("20")).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP); + BigDecimal totalBudgetMoney = budget.getTotalBudgetMoney().add(twentyPercent); + if (moneyBig.compareTo(totalBudgetMoney) > 0) { + return Result.error("该活动预算金额不足!"); + } else { + return Result.success(); + } + } + } else { + //如果是校工会进来 + + //如果报销的项目是可以重复报销的 + if (budget.getIsRepeatReimburse()) { + //这个预算已经报销了多少钱 + BigDecimal totalMoney = getBxMoneyByActivityId(budgetId); + //查出这个活动有没有跟其他预算关联,如果跟其他预算关联了,代表当前这条预算是分工会也能报校工会也能报, + // schoolBudgetId字段不为空就代表这条预算是使用的校工会的金额 + List budgetList = dao().query(ActivityBudget.class, + Cnd.where("schoolBudgetId", "=", budgetId)); + if (ObjectUtil.isNotEmpty(budgetList) && !budgetList.isEmpty()) { + //如果报销的项目是分工会也能报校工会也能报,就要减去所有已分配分工会的钱在算能报销多少钱。 + + //1.减去分工会可以报的那一部分预算,比如校工会这个预算有1000,分工会可以报100.那么校工会只能报900 + //找出分配给分工会的预算是多少钱 + BigDecimal unionTotalMoney = budgetList.stream() + .map(ActivityBudget::getTotalBudgetMoney) + .filter(Objects::nonNull) // 避免 null 值导致计算错误 + .reduce(BigDecimal.ZERO, BigDecimal::add); + + //找出能报销多少钱,校工会预算1000-分工会可以报的预算unionTotalMoney=校工会目前可以使用的预算 + BigDecimal totalBudgetMoney = budget.getTotalBudgetMoney().subtract(unionTotalMoney); + //已报销加上现在的钱 + BigDecimal totalReimbursement = totalMoney.add(moneyBig); + if (totalReimbursement.compareTo(totalBudgetMoney) > 0) { + return Result.error("该活动预算金额不足!"); + } else { + return Result.success(); + } + } else { + //正常判断这个活动是否超出预算 + //算出现在还能报销多少钱,判断是否超出预算的 20% + + //1.算出现在还能报销多少钱 + BigDecimal twentyPercent = budget.getTotalBudgetMoney().multiply(new BigDecimal("20")).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP); + BigDecimal totalBudgetMoney = budget.getTotalBudgetMoney().add(twentyPercent); + //2. 计算本次加上之前的报销总金额 + BigDecimal totalReimbursement = totalMoney.add(moneyBig); + // 3. 判断是否超出预算的 20% + if (totalReimbursement.compareTo(totalBudgetMoney) > 0) { + return Result.error("该活动预算金额不足!"); + } else { + return Result.success(); + } + } + + } else { + //正常判断这个活动是否超出预算 + //算出现在还能报销多少钱,判断是否超出预算的 20% + BigDecimal twentyPercent = budget.getTotalBudgetMoney().multiply(new BigDecimal("20")).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP); + BigDecimal totalBudgetMoney = budget.getTotalBudgetMoney().add(twentyPercent); + if (moneyBig.compareTo(totalBudgetMoney) > 0) { + return Result.error("该活动预算金额不足!"); + } else { + return Result.success(); + } + } + + + } + } + + + return null; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/thirtyTeach/controller/ThirtyTeachController.java b/src/main/java/com/budwk/app/zhgh/thirtyTeach/controller/ThirtyTeachController.java new file mode 100644 index 00000000..10889de4 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/thirtyTeach/controller/ThirtyTeachController.java @@ -0,0 +1,236 @@ +package com.budwk.app.zhgh.thirtyTeach.controller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.alibaba.excel.EasyExcel; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.base.utils.EasyExcelUtil; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.sys.services.SysUserService; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.integral.controller.IntegralManageController; +import com.budwk.app.zhgh.thirtyTeach.param.ThirtyTeachPageForm; +import com.budwk.app.zhgh.thirtyTeach.service.ThirtyTeachService; +import com.budwk.app.zhgh.thirtyTeach.template.ThirtyTeachTemp; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.formula.functions.T; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.AdaptBy; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; +import org.nutz.mvc.upload.TempFile; +import org.nutz.mvc.upload.UploadAdaptor; + +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author zhf + * @date 2025/7/25 18:27 + * @description 教职工管理 + */ +@IocBean +@Ok("json:full") +@Slf4j +@Api(tags = "三十龄教工-教职工管理") +@At("/platform/thirtyTeach/manage") +public class ThirtyTeachController { + + + @Inject + private ThirtyTeachService thirtyTeachService; + @Inject + private SysUserService sysUserService; + + @At("") + @Ok("beetl:/platform/zhgh/thirtyTeach/manage/index.html") + @SaCheckPermission("thirtyTeach.manage") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("thirtyTeach.manage") + public Result pageData(ThirtyTeachPageForm pageForm) { + Sql sql = thirtyTeachService.getSql(pageForm); + Pagination pagination = thirtyTeachService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + + @At + @ApiOperation("一键设置三十龄教工") + @SaCheckPermission("thirtyTeach.manage") + @SLog(type = "30龄教工-教职工管理", tag = "设置三十龄教工",msg = "设置三十龄教工设置教龄${args[0]}") + public Result setThirtyTeach(Integer setNum, boolean isFlag){ + if (isFlag) { + sysUserService.update(Chain.make("isThirtyTeach", 0), Cnd.NEW()); + } + Cnd cnd = Cnd.NEW(); + cnd.and("arrivalAtSchoolDate", "is not", null); + cnd.and("arrivalAtSchoolDate", "!=", ""); + cnd.and("TIMESTAMPDIFF(YEAR, CONCAT(arrivalAtSchoolDate, '-01'), CURDATE())", ">", setNum); + sysUserService.update(Chain.make("isThirtyTeach", 1), cnd); + return Result.success(); + } + + @At + @ApiOperation("批量删除三十龄教工") + @SaCheckPermission("thirtyTeach.manage") + @SLog(type = "30龄教工-教职工管理", tag = "批量删除三十龄教工",msg = "批量删除三十龄教工${args[0]}") + public Result doBatchDelete(@Param("userIds") String[] userIds) { + List userIdList = Arrays.asList(userIds); + if (Lang.isNotEmpty(userIdList)) { + sysUserService.update(Chain.make("isThirtyTeach", 0), Cnd.where("id", "in", userIdList)); + } + return Result.success(); + } + + + @At + @SaCheckPermission("thirtyTeach.manage") + @Ok("void") + @ApiOperation("导出30教龄教职工名单") + public void doExport(ThirtyTeachPageForm pageForm, HttpServletResponse response){ + + Sql sql = thirtyTeachService.getSql(pageForm); + List list = thirtyTeachService.listMap(sql); + List entityList = new ArrayList<>(); + ExcelExportEntity no = new ExcelExportEntity("序号", "no", 10); + no.setFormat("isAddIndex"); + entityList.add(no); + entityList.add(new ExcelExportEntity("工号", "loginname", 20)); + entityList.add(new ExcelExportEntity("姓名", "username", 20)); + entityList.add(new ExcelExportEntity("性别", "sex", 20)); + entityList.add(new ExcelExportEntity("教龄(年)", "teachNum", 20)); + entityList.add(new ExcelExportEntity("电话", "mobile", 20)); + entityList.add(new ExcelExportEntity("工会", "unionName", 20)); + entityList.add(new ExcelExportEntity("单位", "unitName", 20)); + entityList.add(new ExcelExportEntity("在职状态", "userState", 20)); + entityList.add(new ExcelExportEntity("人员类型", "personType", 20)); + entityList.add(new ExcelExportEntity("荣誉证办理年月", "thirtyCertificateProcessingTime", 20)); + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, list); + CommonDownloadUtil.download("30教龄教职工名单.xlsx", workbook, response); + } + + @At + @Ok("void") + @ApiOperation("下载导入30教龄教职工模版") + @SaCheckPermission("thirtyTeach.manage") + public void downloadImportTemp(HttpServletResponse response) { + try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { + EasyExcel.write(byteArrayOutputStream, ThirtyTeachTemp.class) + .sheet("30教龄教职工模版") + .doWrite(ArrayList::new); + CommonDownloadUtil.download("30教龄教职工模版.xlsx", byteArrayOutputStream.toByteArray(), response); + } catch (Exception e) { + log.error("下载导入模版失败", e); + } + + } + + + + @At + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("thirtyTeach.manage") + @ApiOperation("导入30教龄教职工名单") + @AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"}) + public Result doImport(TempFile file, Boolean isFlag) { + try { + List ts = EasyExcelUtil.syncReadModel(file.getFile(), ThirtyTeachTemp.class, 0, 1); + List teachTempList = JSONUtil.parseArray(JSONUtil.toJsonStr(ts)).toList(ThirtyTeachTemp.class); + + List users = sysUserService.query(); + + List errorInfos = new ArrayList<>(); + List insertUserList = new ArrayList<>(); + + for (ThirtyTeachTemp temp : teachTempList) { + if (StrUtil.isBlank(temp.getUserName())) { + temp.setResult("获取不到该用户的姓名!"); + errorInfos.add(temp); + break; + } else if (StrUtil.isBlank(temp.getLoginName())) { + temp.setResult("获取不到该用户的出生日期!"); + errorInfos.add(temp); + break; + }else if (StrUtil.isBlank(temp.getThirtyCertificateProcessingTime())) { + temp.setResult("获取不到该用户的荣誉证办理时间!"); + errorInfos.add(temp); + break; + } + + List matchUsers = users.stream().filter(u -> u.getLoginname().equals(temp.getLoginName())).map(u -> { + Sys_user user = new Sys_user(); + user.setId(u.getId()); + user.setLoginname(temp.getLoginName()); + user.setIsThirtyTeach(true); + user.setThirtyCertificateProcessingTime(temp.getThirtyCertificateProcessingTime()); + return user; + }).collect(Collectors.toList()); + insertUserList.addAll(matchUsers); + + } + + int i = 0; + if (Lang.isNotEmpty(insertUserList)) { + if (isFlag) { + sysUserService.update(Chain.make("isThirtyTeach", 0), Cnd.NEW()); + } + i = sysUserService.updateIgnoreNull(insertUserList); + } + if (Lang.isNotEmpty(errorInfos)) { + NutMap nutMap = new NutMap(); + nutMap.setv("totalCount", teachTempList.size()); + nutMap.setv("successCount", i); + nutMap.setv("errorCount", errorInfos.size()); + nutMap.setv("errorList", errorInfos.stream().map(v -> { + return NutMap.NEW().addv("工号", v.getLoginName()).addv("姓名", v.getUserName()).addv("错误原因", v.getResult()); + }).collect(Collectors.toList())); + return Result.success(nutMap); + } + return Result.success(); + + }catch (Exception e){ + log.error("导入30教龄教职工名单失败", e); + e.printStackTrace(); + return Result.error(); + } + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/thirtyTeach/controller/ThirtyTeachSummaryController.java b/src/main/java/com/budwk/app/zhgh/thirtyTeach/controller/ThirtyTeachSummaryController.java new file mode 100644 index 00000000..cbd71ffb --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/thirtyTeach/controller/ThirtyTeachSummaryController.java @@ -0,0 +1,131 @@ +package com.budwk.app.zhgh.thirtyTeach.controller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.sys.services.SysUserService; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.thirtyTeach.param.ThirtyTeachPageForm; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.List; + +/** + * @author zhf + * @date 2025/7/25 18:28 + * @description 教职工汇总 + */ +@IocBean +@Ok("json:full") +@Slf4j +@Api(tags = "三十龄教工-教职工汇总") +@At("/platform/thirtyTeach/summary") +public class ThirtyTeachSummaryController { + + @Inject + private SysUserService sysUserService; + + + @At("") + @Ok("beetl:/platform/zhgh/thirtyTeach/summary/index.html") + @SaCheckPermission("thirtyTeach.summary") + public void index() { + } + + + @At + @ApiOperation("分页查询") + @SaCheckPermission("thirtyTeach.summary") + public Result pageData(String unionId,String unitId){ + Sql sql = Sqls.create(""" + SELECT + su.*, + COUNT( u.id ) AS userNum + FROM + sys_union su + LEFT JOIN `vw_user` u ON u.unionid = su.id + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("u.isThirtyTeach", "=", 1); + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.and("u.unionId", "=", SecurityUtil.getUnionId()); + } + cnd.andEX("u.unionId", "=", unionId); + cnd.andEX("u.unitId", "=", unitId); + cnd.groupBy("su.unionCode"); + cnd.asc("su.unionCode"); + sql.setCondition(cnd); + return Result.success(sysUserService.listMap(sql)); + + } + + @At + @SaCheckPermission("thirtyTeach.summary") + @Ok("void") + @ApiOperation("导出工会汇总名单") + public void doExportSummary(String unionId,String unitId, HttpServletResponse response){ + + Sql sql = Sqls.create(""" + SELECT + su.*, + COUNT( u.id ) AS userNum + FROM + sys_union su + LEFT JOIN `vw_user` u ON u.unionid = su.id + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("u.isThirtyTeach", "=", 1); + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.and("u.unionId", "=", SecurityUtil.getUnionId()); + } + cnd.andEX("u.unionId", "=", unionId); + cnd.andEX("u.unitId", "=", unitId); + cnd.groupBy("su.unionCode"); + cnd.asc("su.unionCode"); + sql.setCondition(cnd); + List thirtyTeachList = sysUserService.listMap(sql); + + List entityList = new ArrayList<>(); + ExcelExportEntity no = new ExcelExportEntity("序号", "no", 10); + no.setFormat("isAddIndex"); + entityList.add(no); + entityList.add(new ExcelExportEntity("分工会", "name", 20)); + ExcelExportEntity entity = new ExcelExportEntity("在职人数", "userNum", 20); + entity.setType(10); + entityList.add(entity); + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, thirtyTeachList); + CommonDownloadUtil.download("30教龄教职工在职人员汇总表.xlsx", workbook, response); + + } + + + + +} diff --git a/src/main/java/com/budwk/app/zhgh/thirtyTeach/param/ThirtyTeachPageForm.java b/src/main/java/com/budwk/app/zhgh/thirtyTeach/param/ThirtyTeachPageForm.java new file mode 100644 index 00000000..c6400d6c --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/thirtyTeach/param/ThirtyTeachPageForm.java @@ -0,0 +1,23 @@ +package com.budwk.app.zhgh.thirtyTeach.param; + +import com.budwk.app.base.param.PageForm; +import lombok.Data; + +/** + * @author zhf + * @date 2025/7/28 10:09 + * @description 30龄教工 + */ +@Data +public class ThirtyTeachPageForm extends PageForm { + + private String unionId; + private String unitId; + //进校时长 + private String teachNum; + //办证年月 + private String thirtyCertificateProcessingTime; + private String userState; + private String personType; + +} diff --git a/src/main/java/com/budwk/app/zhgh/thirtyTeach/service/ThirtyTeachService.java b/src/main/java/com/budwk/app/zhgh/thirtyTeach/service/ThirtyTeachService.java new file mode 100644 index 00000000..2e53e6a8 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/thirtyTeach/service/ThirtyTeachService.java @@ -0,0 +1,15 @@ +package com.budwk.app.zhgh.thirtyTeach.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.thirtyTeach.param.ThirtyTeachPageForm; +import org.nutz.dao.sql.Sql; + +/** + * @author zhf + * @date 2025/7/28 11:52 + * @description + */ +public interface ThirtyTeachService extends BaseService { + + Sql getSql(ThirtyTeachPageForm pageForm); +} diff --git a/src/main/java/com/budwk/app/zhgh/thirtyTeach/service/impl/ThirtyTeachServiceImpl.java b/src/main/java/com/budwk/app/zhgh/thirtyTeach/service/impl/ThirtyTeachServiceImpl.java new file mode 100644 index 00000000..c2b70052 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/thirtyTeach/service/impl/ThirtyTeachServiceImpl.java @@ -0,0 +1,77 @@ +package com.budwk.app.zhgh.thirtyTeach.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.thirtyTeach.param.ThirtyTeachPageForm; +import com.budwk.app.zhgh.thirtyTeach.service.ThirtyTeachService; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.IocBean; + +/** + * @author zhf + * @date 2025/7/28 11:53 + * @description + */ +@IocBean(args = {"refer:dao"}) +public class ThirtyTeachServiceImpl extends BaseServiceImpl implements ThirtyTeachService { + public ThirtyTeachServiceImpl(Dao dao) { + super(dao); + } + + @Override + public Sql getSql(ThirtyTeachPageForm pageForm) { + Sql sql = Sqls.create(""" + SELECT + id, + loginname, + username, + sex, + member, + personType, + userState, + unionName, + unitName, + mobile, + birthday, + thirtyCertificateProcessingTime, + TIMESTAMPDIFF(YEAR, CONCAT(arrivalAtSchoolDate, '-01'), CURDATE()) AS teachNum + FROM + `vw_user` + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("isThirtyTeach", "=", 1); + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.orLike("loginname", pageForm.getSearchKeyword()); + seg.orLike("username", pageForm.getSearchKeyword()); + cnd.and(seg); + } + + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.and("unionId", "=", SecurityUtil.getUnionId()); + } + cnd.andEX("TIMESTAMPDIFF(YEAR, CONCAT(arrivalAtSchoolDate, '-01'), CURDATE())", "=", pageForm.getTeachNum()); + cnd.andEX("unionId", "=", pageForm.getUnionId()); + cnd.andEX("unitId", "=", pageForm.getUnitId()); + cnd.andEX("personType", "=", pageForm.getPersonType()); + cnd.andEX("userState", "=", pageForm.getUserState()); + cnd.and(Cnd.likeEX("thirtyCertificateProcessingTime",pageForm.getThirtyCertificateProcessingTime())); + if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.asc("unionCode").asc("unitCode"); + } else { + cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } + + sql.setCondition(cnd); + return sql; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/thirtyTeach/template/ThirtyTeachTemp.java b/src/main/java/com/budwk/app/zhgh/thirtyTeach/template/ThirtyTeachTemp.java new file mode 100644 index 00000000..aef5fa23 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/thirtyTeach/template/ThirtyTeachTemp.java @@ -0,0 +1,31 @@ +package com.budwk.app.zhgh.thirtyTeach.template; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.alibaba.excel.annotation.write.style.ContentRowHeight; +import com.alibaba.excel.annotation.write.style.HeadRowHeight; +import lombok.Data; +import lombok.EqualsAndHashCode; + + +@Data +@EqualsAndHashCode +@ContentRowHeight(20) // 内容行高 +@HeadRowHeight(20) // 表头行高 +@ColumnWidth(25) +public class ThirtyTeachTemp { + + @ExcelProperty("工号") + private String loginName; + + @ExcelProperty("姓名") + private String userName; + + @ExcelProperty("《30年教龄荣誉证》办理年月") + private String thirtyCertificateProcessingTime; + + @ExcelIgnore + private String result; + +} diff --git a/src/main/resources/views/platform/zhgh/activity/qsv/quiz/rank.html b/src/main/resources/views/platform/zhgh/activity/qsv/quiz/rank.html deleted file mode 100644 index 452577ae..00000000 --- a/src/main/resources/views/platform/zhgh/activity/qsv/quiz/rank.html +++ /dev/null @@ -1,111 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 导出xlsx - - - - - - - - - - - - - - -
- - - - diff --git a/src/main/resources/views/platform/zhgh/activity/qsv/survey/index.html b/src/main/resources/views/platform/zhgh/activity/qsv/survey/index.html deleted file mode 100644 index f0f48a32..00000000 --- a/src/main/resources/views/platform/zhgh/activity/qsv/survey/index.html +++ /dev/null @@ -1,70 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/src/main/resources/views/platform/zhgh/asset/category/index.html b/src/main/resources/views/platform/zhgh/asset/category/index.html new file mode 100644 index 00000000..747a4f4e --- /dev/null +++ b/src/main/resources/views/platform/zhgh/asset/category/index.html @@ -0,0 +1,161 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + 关 闭 + 提 交 + + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/asset/common/assetForm.js b/src/main/resources/views/platform/zhgh/asset/common/assetForm.js new file mode 100644 index 00000000..addbeb88 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/asset/common/assetForm.js @@ -0,0 +1,349 @@ +let ASSSET_FORM = { + /*language=HTML*/ + template: ` +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 校工会资产 + + 分工会资产 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 提 交 + +
+
+ `, + store, + mixins: [initTableMixins], + data() { + return { + ruleForm: { + assetName: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetCategoryId: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetSpecs: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetSupplierName: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetFundingSubjectName: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetPurposeName: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetUnitPrice: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetQuantity: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetTypeCode: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetUsedDate: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetRetiredAssetsDate: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetUseUserId: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetUseUnionId: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetStorageLocation: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetUsageStateName: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetInvoiceFiles: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetFiles: [{required: true, message: '必填', trigger: ['blur', 'change']}], + }, + unions: [], + assetCategoryOption: [], + assetUseUserOption: [], + unionList: [], + } + }, + methods: { + open() { + }, + async findOne(id) { + const res = await this.$axios.post("/platform/asset/manage/findOne", {id}) + this.formData = res.data + }, + async openEdit(id) { + await this.findOne(id) + this.searchAssetUseUser(this.formData.assetUseUserId) + }, + assetUseUnionIdChange(val) { + const union = this.unions.find(v => v.id === val) + if (union) { + this.$set(this.formData, "assetUseUnionName", union.name) + } else { + this.$set(this.formData, "assetUseUnionName", null) + } + }, + // 切换资产类型把使用/管理部门清空 + assetTypeCodeChange(val) { + if (val === 1) { + this.$set(this.formData, "assetUseUnionName", "校工会") + } else { + this.$set(this.formData, "assetUseUnionName", null) + this.$set(this.formData, "assetUseUnionId", null) + } + }, + // 点击责任人 + assetUseUserIdChange(val) { + const { + unionname, + unionid + } = this.assetUseUserOption.find(v => v.id === val) + this.formData.assetUseUnionId = unionid + if (this.formData.assetTypeCode === 1) { + this.formData.assetUseUnionName = "校工会" + } else { + + this.formData.assetUseUnionName = unionname + } + }, + // 点击开始使用日期🧄预计报废时间 + assetUsedDateChange(val) { + if (!this.formData.assetCategoryId) { + this.$message.warning('请选择资产所属类别'); + this.$set(this.formData, "assetUsedDate", null) + return + } + const assetCategoryOption = clone(this.assetCategoryOption) + const data = assetCategoryOption.find(v => v.id === this.formData.assetCategoryId) + const depreciationDate = this.$moment(val).add(data.depreciationYear, 'y').format('YYYY-MM-DD') + this.$set(this.formData, "assetRetiredAssetsDate", depreciationDate) + }, + assetCategoryIdChange() { + if (this.formData.assetUsedDate) { + this.assetUsedDateChange(this.formData.assetUsedDate) + } else { + this.$set(this.formData, "assetUsedDate", null); + } + }, + // 查询责任人 + searchAssetUseUser(val) { + $.get("/platform/asset/manage/searchAssetUseUser", {query: val}).then(resp => { + if (resp.code === 0) { + this.assetUseUserOption = resp.data + } + }) + }, + // 查询资产类别 + queryCategory() { + this.$axios.post("/platform/asset/category/queryCategory").then(resp => { + if (resp.code === 0) { + this.assetCategoryOption = resp.data + } + }) + }, + doSubmit() { + this.$refs["AddForm"].validate((valid) => { + if (valid) { + let formData = clone(this.formData) + if (formData.assetInvoiceFiles) { + formData.assetInvoiceFiles = JSON.stringify(formData.assetInvoiceFiles) + } + if (formData.assetFiles) { + formData.assetFiles = JSON.stringify(formData.assetFiles) + } + + this.$axios.post("/platform/asset/manage/" + (formData.id ? "doEdit" : "doAdd"), formData).then(resp => { + if (resp.code === 0) { + this.formData = {} + this.$refs.AddForm.resetFields() + this.$emit("save_success") + this.$message.success(resp.msg); + } else { + this.$message.warning(resp.msg); + } + + }) + } + }) + } + + }, + async created() { + this.queryCategory() + this.$businessTool.listUnion().then((data) => { + this.unionList = data + }) + }, + style: /*language=CSS*/ ` + .table_fixed .el-form-item { + margin-bottom: 0px !important; + } + + ` +} diff --git a/src/main/resources/views/platform/zhgh/asset/common/assetInfo.js b/src/main/resources/views/platform/zhgh/asset/common/assetInfo.js new file mode 100644 index 00000000..7ed075e9 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/asset/common/assetInfo.js @@ -0,0 +1,164 @@ +let ASSSET_INFO = { + /*language=HTML*/ + template: ` +
+ + + + + {{viewData.assetNumber}} + + + {{viewData.assetName}} + + + {{viewData.assetCategoryName}}({{viewData.assetDepreciationYear}}年) + + + {{viewData.assetSpecs}} + + + {{viewData.assetSupplierName}} + + + {{viewData.assetFundingSubjectName}} + + + {{viewData.assetPurposeName}} + + + {{viewData.assetUnitPrice}} + + + {{viewData.assetQuantity}} + + + {{viewData.assetTypeCode===1?'校工会资产':'分工会资产'}} + + + {{$moment(viewData.assetUsedDate).format('YYYY-MM-DD')}} + + + {{$moment(viewData.assetRetiredAssetsDate).format('YYYY-MM-DD')}} + + + {{viewData.assetUseUserName}} + + + {{viewData.assetUseUnionName}} + + + {{viewData.assetStorageLocation}} + + + {{viewData.assetUsageStateName}} + + + + +
{{viewData.assetNotes}}
+
+ + + + + + +
+
+ + + + + + + + + + + + + + + + + + +
+ + + + + + {{tableStocktakingData.oldAssetUseUserName}} + + + {{tableStocktakingData.oldAssetUseUnionName}} + + + {{tableStocktakingData.oldAssetStorageLocation}} + + + {{tableStocktakingData.oldAssetUsageStateName}} + + + {{$moment(tableStocktakingData.createdAt).format('YYYY-MM-DD HH:mm:ss')}} + + + + {{tableStocktakingData.oldAssetNotes}} + + + + + + + 关 闭 + + +
+ + `, store, + mixins: [initTableMixins], + data() { + return { + viewData: {}, + tableStocktakingData: {}, + activeName: "1", + dialogVisible:false + } + }, + methods: { + openView(row){ + this.tableStocktakingData=row + this.dialogVisible=true + + }, + open(id) { + this.$axios.post("/platform/asset/manage/fondOneAsset", {id}).then(res => { + this.viewData = res.data + }) + } + } +} diff --git a/src/main/resources/views/platform/zhgh/asset/common/assetStocktakingForm.js b/src/main/resources/views/platform/zhgh/asset/common/assetStocktakingForm.js new file mode 100644 index 00000000..e5558497 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/asset/common/assetStocktakingForm.js @@ -0,0 +1,146 @@ +let ASSSET_STOCKTAKING_FORM = { + /*language=HTML*/ + template: ` +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 提 交 + +
+
+ `, + store, + mixins: [initTableMixins], + data() { + return { + ruleForm: { + assetUseUserId: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetStorageLocation: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetUsageStateName: [{required: true, message: '必填', trigger: ['blur', 'change']}], + assetFiles: [{required: true, message: '必填', trigger: ['blur', 'change']}], + }, + assetUseUserOption: [], + assetInfo: {} + } + }, + methods: { + open(row) { + this.assetInfo = row + this.$set(this.formData, "assetId", row.id) + this.$set(this.formData, "assetStocktakingPlanId", row.assetStocktakingPlanId) + this.$set(this.formData, "assetNumber", row.assetNumber) + this.$set(this.formData, "assetName", row.assetName) + this.$set(this.formData, "assetUsedDate", row.assetUsedDate) + this.$set(this.formData, "assetStorageLocation", row.assetStorageLocation) + }, + doSubmit(){ + this.$refs["AddForm"].validate((valid) => { + if (valid) { + let formData = clone(this.formData) + if (formData.assetFiles) { + formData.assetFiles = JSON.stringify(formData.assetFiles) + } + + this.$axios.post("/platform/asset/stocktaking/doSubmit", formData).then(resp => { + if (resp.code === 0) { + this.formData = {} + this.$refs.AddForm.resetFields() + this.$emit("save_success") + this.$message.success(resp.msg); + } else { + this.$message.warning(resp.msg); + } + + }) + } + }) + }, + // 查询责任人 + searchAssetUseUser(val) { + $.get("/platform/asset/manage/searchAssetUseUser", {query: val}).then(resp => { + if (resp.code === 0) { + this.assetUseUserOption = resp.data + } + }) + }, + }, + async created() { + + }, + style: /*language=CSS*/ ` + .table_fixed .el-form-item { + margin-bottom: 0px !important; + } + + ` +} diff --git a/src/main/resources/views/platform/zhgh/asset/depreciation/index.html b/src/main/resources/views/platform/zhgh/asset/depreciation/index.html new file mode 100644 index 00000000..2f36cc0d --- /dev/null +++ b/src/main/resources/views/platform/zhgh/asset/depreciation/index.html @@ -0,0 +1,202 @@ + + + +
+ + + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/asset/manage/index.html b/src/main/resources/views/platform/zhgh/asset/manage/index.html new file mode 100644 index 00000000..81e34667 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/asset/manage/index.html @@ -0,0 +1,205 @@ + + + +
+ + + + + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/asset/stocktaking/index.html b/src/main/resources/views/platform/zhgh/asset/stocktaking/index.html new file mode 100644 index 00000000..5577dce5 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/asset/stocktaking/index.html @@ -0,0 +1,232 @@ + + +
+ + + + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/asset/stocktakingPlan/index.html b/src/main/resources/views/platform/zhgh/asset/stocktakingPlan/index.html new file mode 100644 index 00000000..b39a7821 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/asset/stocktakingPlan/index.html @@ -0,0 +1,212 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + 关 闭 + 提 交 + + +
+ + diff --git a/src/main/resources/views/platform/zhgh/activity/qsv/activity/basicForm.js b/src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/basicForm.js similarity index 91% rename from src/main/resources/views/platform/zhgh/activity/qsv/activity/basicForm.js rename to src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/basicForm.js index 434b1079..7420ddc8 100644 --- a/src/main/resources/views/platform/zhgh/activity/qsv/activity/basicForm.js +++ b/src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/basicForm.js @@ -158,6 +158,7 @@ const basicForm = { @@ -170,16 +171,17 @@ const basicForm = { - - - + + + + + + + + + + + @@ -196,12 +198,14 @@ const basicForm = { `, dicts: ["ACTIVITY_QSV_CATEGORY", "ACTIVITY_QSV_MODE", "ACTIVITY_QSV_REPEAT_MODE", "ACTIVITY_QSV_SCORE_MODE"], components: { - "drawer-user-scope": httpVueLoader("/components/module/activity/DrawerUserScope.vue") + "drawer-user-scope": httpVueLoader("/components/plugins/DrawerUserScope.vue") }, data() { return { dialogVisible: false, - formData: {}, + formData: { + category: '' + }, formRules: { category: [{ required: true, message: "请选择类型", trigger: "change" }], title: [{ required: true, message: "请输入标题", trigger: "change" }], @@ -218,7 +222,7 @@ const basicForm = { this.dialogVisible = true this.getActivityGroup() if (id) { - this.$axios.post("/platform/qsv/activity/findOne", { id }).then((res) => { + $.post("/platform/qsv/activity/findOne", { id }).then((res) => { if (res.code === 0) { this.formData = res.data } @@ -230,7 +234,7 @@ const basicForm = { onSubmit() { this.$refs.formRef.validate((valid) => { if (valid) { - this.$axios.post("/platform/qsv/activity/save", this.formData).then((res) => { + $.post("/platform/qsv/activity/save", this.formData).then((res) => { if (res.code === 0) { this.$message.success(res.msg) this.dialogVisible = false @@ -241,7 +245,7 @@ const basicForm = { }) }, getActivityGroup() { - this.$axios.post("/platform/activity/basic/scope/getActivityUserScopeGroup").then((res) => { + $.post("/platform/activity/basic/scope/getActivityUserScopeGroup").then((res) => { if (res.code === 0) { this.activityGroupOptions = res.data } diff --git a/src/main/resources/views/platform/zhgh/activity/qsv/activity/index.html b/src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/index.html similarity index 90% rename from src/main/resources/views/platform/zhgh/activity/qsv/activity/index.html rename to src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/index.html index 4e9dfc1f..4fb537e9 100644 --- a/src/main/resources/views/platform/zhgh/activity/qsv/activity/index.html +++ b/src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/index.html @@ -7,15 +7,17 @@ layout("/layouts/platform.html"){ - + + - - + + 新增 @@ -46,7 +48,6 @@ layout("/layouts/platform.html"){ - + + diff --git a/src/main/resources/views/platform/zhgh/activity/qsv/survey/answer.js b/src/main/resources/views/platform/zhgh/dayofficework/qsv/survey/answer.js similarity index 79% rename from src/main/resources/views/platform/zhgh/activity/qsv/survey/answer.js rename to src/main/resources/views/platform/zhgh/dayofficework/qsv/survey/answer.js index e85ec3da..90f0ef49 100644 --- a/src/main/resources/views/platform/zhgh/activity/qsv/survey/answer.js +++ b/src/main/resources/views/platform/zhgh/dayofficework/qsv/survey/answer.js @@ -1,7 +1,7 @@ const answer = { /*language=HTML*/ template: ` - + 导出xlsx @@ -14,8 +14,10 @@ const answer = { + `, + mixins: [initTableMixins], data() { return { dialogVisible: false, @@ -28,14 +30,16 @@ const answer = { onOpen(activityId) { this.activityId = activityId this.dialogVisible = true - this.list() + this.pageData() }, - list() { - this.$axios.post("/platform/qsv/survey/userAnswer", { activityId: this.activityId }).then((res) => { + pageData() { + this.pageForm.activityId = this.activityId + $.post("/platform/qsv/survey/userAnswer", this.pageForm).then((res) => { if (res.code === 0) { this.tableColumns = res.data.tableColumns - this.tableData = res.data.tableData + this.tableData = res.data.tableData.list + this.pageForm.totalCount = res.data.tableData.totalCount } }) }, @@ -46,7 +50,7 @@ const answer = { cancelButtonText: "取消", type: "warning" }).then(() => { - this.$axios.post("/platform/qsv/survey/deleteUserAnswer", { id }).then((res) => { + $.post("/platform/qsv/survey/deleteUserAnswer", { id }).then((res) => { if (res.code === 0) { this.$message.success(res.msg) this.list() diff --git a/src/main/resources/views/platform/zhgh/dayofficework/qsv/survey/index.html b/src/main/resources/views/platform/zhgh/dayofficework/qsv/survey/index.html new file mode 100644 index 00000000..2dfdc47d --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/qsv/survey/index.html @@ -0,0 +1,74 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/activity/qsv/survey/report.js b/src/main/resources/views/platform/zhgh/dayofficework/qsv/survey/report.js similarity index 88% rename from src/main/resources/views/platform/zhgh/activity/qsv/survey/report.js rename to src/main/resources/views/platform/zhgh/dayofficework/qsv/survey/report.js index a7a8a381..b2199267 100644 --- a/src/main/resources/views/platform/zhgh/activity/qsv/survey/report.js +++ b/src/main/resources/views/platform/zhgh/dayofficework/qsv/survey/report.js @@ -2,6 +2,9 @@ const report = { /*language=HTML*/ template: ` + + 导出xlsx +
@@ -63,7 +66,7 @@ const report = { onOpen(activityId) { this.dialogVisible = true this.activityId = activityId - this.$axios.post("/platform/qsv/survey/report", { activityId }).then((res) => { + $.post("/platform/qsv/survey/report", { activityId }).then((res) => { if (res.code === 0) { this.subjects = res.data } @@ -72,8 +75,7 @@ const report = { openDetail(subjectId, optionId) { console.log(subjectId) console.log(optionId) - this.$axios - .post("/platform/qsv/survey/selectOptionUsers", { + $.post("/platform/qsv/survey/selectOptionUsers", { activityId: this.activityId, subjectId, optionId @@ -84,6 +86,9 @@ const report = { this.optionUsers = res.data } }) + }, + exportReportXlsx(){ + this.$downLoad("/platform/qsv/survey/exportReportXlsx", { activityId: this.activityId }) } }, style: /*language=CSS*/ ` diff --git a/src/main/resources/views/platform/zhgh/healthCheckup/campus/index.html b/src/main/resources/views/platform/zhgh/healthCheckup/campus/index.html new file mode 100644 index 00000000..0258b1e6 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/healthCheckup/campus/index.html @@ -0,0 +1,165 @@ + +
+ + + + + + + + + + + 新增院区 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 取 消 + 确 定 + + + + + + + + + + + + + + 取 消 + 确 定 + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/healthCheckup/listMange/index.html b/src/main/resources/views/platform/zhgh/healthCheckup/listMange/index.html new file mode 100644 index 00000000..b6e77f1f --- /dev/null +++ b/src/main/resources/views/platform/zhgh/healthCheckup/listMange/index.html @@ -0,0 +1,338 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + 取消 + 确定 + + + + + + + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/healthCheckup/projectMange/index.html b/src/main/resources/views/platform/zhgh/healthCheckup/projectMange/index.html new file mode 100644 index 00000000..c820f50a --- /dev/null +++ b/src/main/resources/views/platform/zhgh/healthCheckup/projectMange/index.html @@ -0,0 +1,572 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/healthCheckup/statisticsSingle/index.html b/src/main/resources/views/platform/zhgh/healthCheckup/statisticsSingle/index.html new file mode 100644 index 00000000..f019a961 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/healthCheckup/statisticsSingle/index.html @@ -0,0 +1,460 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + 取消 + 提交 + + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/outlay/activityBudget/apply/form.html b/src/main/resources/views/platform/zhgh/outlay/activityBudget/apply/form.html new file mode 100644 index 00000000..0dea9b51 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/activityBudget/apply/form.html @@ -0,0 +1,337 @@ +
+ + + {{formData.userName}} + {{formData.applyDate}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 属于 + 不属于 + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/src/main/resources/views/platform/zhgh/outlay/activityBudget/applyList/index.html b/src/main/resources/views/platform/zhgh/outlay/activityBudget/applyList/index.html new file mode 100644 index 00000000..9c110598 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/activityBudget/applyList/index.html @@ -0,0 +1,253 @@ + + + +
+ + + + + + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/outlay/activityBudget/applyStatistics/index.html b/src/main/resources/views/platform/zhgh/outlay/activityBudget/applyStatistics/index.html new file mode 100644 index 00000000..87b7d98e --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/activityBudget/applyStatistics/index.html @@ -0,0 +1,224 @@ + + +
+ + + + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/outlay/activityBudget/queryStatistics/index.html b/src/main/resources/views/platform/zhgh/outlay/activityBudget/queryStatistics/index.html new file mode 100644 index 00000000..0038ac88 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/activityBudget/queryStatistics/index.html @@ -0,0 +1,172 @@ + + +
+ + + +
+ + diff --git a/src/main/resources/views/platform/zhgh/outlay/activityBudget/schoolAudit/form.html b/src/main/resources/views/platform/zhgh/outlay/activityBudget/schoolAudit/form.html new file mode 100644 index 00000000..d3bae0c8 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/activityBudget/schoolAudit/form.html @@ -0,0 +1,69 @@ +
+ + + + + + + + + +
+ + diff --git a/src/main/resources/views/platform/zhgh/outlay/activityBudget/schoolAudit/index.html b/src/main/resources/views/platform/zhgh/outlay/activityBudget/schoolAudit/index.html new file mode 100644 index 00000000..67444588 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/activityBudget/schoolAudit/index.html @@ -0,0 +1,121 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + 已审核 + 未审核 + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/outlay/activityBudget/view/index.html b/src/main/resources/views/platform/zhgh/outlay/activityBudget/view/index.html new file mode 100644 index 00000000..0ff25066 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/activityBudget/view/index.html @@ -0,0 +1,110 @@ +
+ + {{viewData.userName}} + {{viewData.loginName}} + {{viewData.mobile}} + + + + {{viewData.helpUnitName}} + {{viewData.activityMatter}} + {{viewData.activityDate}} + {{viewData.declareTotalBudgetMoney}} + {{viewData.totalBudgetMoney}} + {{viewData.applyDate}} + + +
+
+
+ + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/outlay/outlayManage/common/editDetailDialog.js b/src/main/resources/views/platform/zhgh/outlay/outlayManage/common/editDetailDialog.js new file mode 100644 index 00000000..d0b02988 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/outlayManage/common/editDetailDialog.js @@ -0,0 +1,90 @@ +const OUTLAY_MANAGE_EDIT_DETAIL_DIALOG = { + template: /*language=HTML*/ ` + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 关 闭 + 提 交 + + +
+ `, data() { + return { + dialogVisible: false, + formData: {}, + url: "" + } + }, + methods: { + doSubmit() { + this.$confirm('确认提交吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }).then(async () => { + this.$refs.form.validate(async valid => { + if (valid) { + this.$axios.post(this.url, this.formData).then((resp) => { + if (resp.code === 0) { + this.dialogVisible = false + this.$emit("search") + this.$message.success(resp.msg) + } else { + this.$message.error(resp.msg) + } + }) + } + }) + }) + }, + open(row, url) { + this.formData = row + this.url = url + this.dialogVisible = true + } + } +} diff --git a/src/main/resources/views/platform/zhgh/outlay/outlayManage/school/manage/index.html b/src/main/resources/views/platform/zhgh/outlay/outlayManage/school/manage/index.html new file mode 100644 index 00000000..7dace602 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/outlayManage/school/manage/index.html @@ -0,0 +1,183 @@ + + + +
+ + + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/outlay/outlayManage/school/useDetail/index.html b/src/main/resources/views/platform/zhgh/outlay/outlayManage/school/useDetail/index.html new file mode 100644 index 00000000..b75a4bcd --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/outlayManage/school/useDetail/index.html @@ -0,0 +1,155 @@ + + + +
+ + + + + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/outlay/outlayManage/union/manage/index.html b/src/main/resources/views/platform/zhgh/outlay/outlayManage/union/manage/index.html new file mode 100644 index 00000000..59bae9bb --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/outlayManage/union/manage/index.html @@ -0,0 +1,182 @@ + + + +
+ + + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/outlay/outlayManage/union/useDetail/detailInfo.js b/src/main/resources/views/platform/zhgh/outlay/outlayManage/union/useDetail/detailInfo.js new file mode 100644 index 00000000..d8fc40f8 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/outlayManage/union/useDetail/detailInfo.js @@ -0,0 +1,101 @@ + +let OUTLAY_MANAGE_UNION_USE_DETAIL_INFO = { + /*language=HTML*/ + template: ` +
+ + +
+ + `, + store, + mixins: [initTableMixins], + data() { + return { + rowData: {}, + + } + }, + components: { + 'outlay-manage-edit-detail-dialog': OUTLAY_MANAGE_EDIT_DETAIL_DIALOG + }, + methods: { + search(){ + this.doSearch() + this.$emit("search") + }, + openEdit(row) { + this.$refs.editDetailDialog.open(row,"/platform/outlay/outlayManage/unionUseDetail/doEditDetail") + + }, + doDelete(row) { + this.$confirm("确定要删除该详情吗?", "提示", {type: "warning"}).then(async () => { + this.$set(row, "loading", true) + const resp = await this.$axios.post("/platform/outlay/outlayManage/unionUseDetail/doDeleteDetail", {id: row.id}) + if (resp.code === 0) { + this.doSearch() + this.$emit("search") + this.$message.success(resp.msg) + } else { + this.$message.error(resp.msg) + } + }) + }, + pageData() { + this.$axios.post("/platform/outlay/outlayManage/unionUseDetail/detailInfo", this.pageForm).then((resp) => { + this.tableLoading = false + if (resp.code === 0) { + this.tableData = resp.data.list + this.pageForm.totalCount = resp.data.totalCount + } + }) + }, + open(row) { + this.tableLoading = true + this.rowData = row + this.pageForm.outlayManageId = row.id + this.pageData() + } + } +} diff --git a/src/main/resources/views/platform/zhgh/outlay/outlayManage/union/useDetail/index.html b/src/main/resources/views/platform/zhgh/outlay/outlayManage/union/useDetail/index.html new file mode 100644 index 00000000..314b8328 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/outlayManage/union/useDetail/index.html @@ -0,0 +1,125 @@ + + + +
+ + + + + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/outlay/outlayReimburse/apply/form.html b/src/main/resources/views/platform/zhgh/outlay/outlayReimburse/apply/form.html new file mode 100644 index 00000000..c715a077 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/outlayReimburse/apply/form.html @@ -0,0 +1,323 @@ +
+ + + + + + + {{i.name}} + + + + + {{formData.userName}} + {{formData.loginName}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/src/main/resources/views/platform/zhgh/outlay/outlayReimburse/apply/index.html b/src/main/resources/views/platform/zhgh/outlay/outlayReimburse/apply/index.html new file mode 100644 index 00000000..5e0bdfe9 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/outlayReimburse/apply/index.html @@ -0,0 +1,61 @@ + + + +
+ + + + + + + 报销申请 + + + + + + + + + + + + + + + + + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/outlay/outlayReimburse/view/index.html b/src/main/resources/views/platform/zhgh/outlay/outlayReimburse/view/index.html new file mode 100644 index 00000000..e149a394 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/outlay/outlayReimburse/view/index.html @@ -0,0 +1,10 @@ + + + + + Title + + + + + diff --git a/src/main/resources/views/platform/zhgh/thirtyTeach/manage/index.html b/src/main/resources/views/platform/zhgh/thirtyTeach/manage/index.html new file mode 100644 index 00000000..536e296d --- /dev/null +++ b/src/main/resources/views/platform/zhgh/thirtyTeach/manage/index.html @@ -0,0 +1,305 @@ + + +
+ + + + + + + + + + + + + + + + 清空更新 + 追加 + + + + + +
+ + 关 闭 + 确定 + +
+ +
+ +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/thirtyTeach/summary/index.html b/src/main/resources/views/platform/zhgh/thirtyTeach/summary/index.html new file mode 100644 index 00000000..23dae1a0 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/thirtyTeach/summary/index.html @@ -0,0 +1,111 @@ + + +
+ + + +
+ + + + From 1510e28ab0bd6789f7d335c50d445d7846582ce4 Mon Sep 17 00:00:00 2001 From: Paidax Date: Thu, 31 Jul 2025 15:48:46 +0800 Subject: [PATCH 2/2] commit --- pom.xml | 24 + .../app/base/constant/BpmProcessConstant.java | 1 + .../app/base/constant/RedisConstant.java | 3 + .../controller/AlipayClientController.java | 68 + .../alipay/service/AlipayClientConfig.java | 22 + .../payment/alipay/service/AlipayService.java | 15 + .../service/impl/AlipayNewServiceImpl.java | 140 ++ .../base/payment/enums/RefundStateEnum.java | 24 + .../payment/enums/TradingChannelEnum.java | 25 + .../base/payment/enums/TradingStateEnum.java | 24 + .../base/payment/enums/TradingTypeEnum.java | 22 + .../base/payment/enums/WxPayResultCode.java | 30 + .../payment/model/PaymentRefundRecord.java | 61 + .../payment/model/PaymentTransaction.java | 131 ++ .../base/payment/wxpay/bean/WxPayV3Bean.java | 53 + .../controller/WxPayCommonController.java | 44 + .../base/payment/wxpay/pem/apiclient_cert.pem | 25 + .../base/payment/wxpay/pem/apiclient_key.pem | 28 + .../app/base/payment/wxpay/pem/wechatpay.pem | 24 + .../wxpay/service/WxPayCommonService.java | 71 + .../service/impl/WxPayCommonServiceImpl.java | 612 ++++++ .../base/payment/wxpay/util/WeChatUtils.java | 132 ++ .../payment/wxpay/vo/WxPayNeedParamVo.java | 37 + .../app/sys/models/Sys_user_history.java | 206 +- .../impl/SysDataUserAllUpdateServiceImpl.java | 20 - .../com/budwk/app/sys/views/View_user.java | 4 + .../task/services/TaskPlatformService.java | 2 + .../impl/TaskPlatformServiceImpl.java | 19 + .../budwk/app/web/commons/base/Globals.java | 2 + .../ActivityDeclareApplyController.java | 11 + .../declare/models/ActivityDeclareInfo.java | 18 + .../ActivityReimbursementApplyController.java | 11 + .../models/ActivityReimbursementInfo.java | 18 + .../fitnesswalk/contants/Cascader.java | 16 + .../fitnesswalk/contants/FitnessWalkMode.java | 18 + ...ssWalkActivityBindingRecordController.java | 133 ++ .../FitnessWalkActivityManageController.java | 337 +++ .../FitnessWalkCommonController.java | 52 + .../FitnessWalkLoginController.java | 75 + .../FitnessWalkPunchLotteryController.java | 258 +++ .../FitnessWalkPunchStatisticsController.java | 247 +++ .../FitnessWalkStepManageController.java | 403 ++++ .../FitnessWalkStepRaffleController.java | 285 +++ .../FitnessWalkStepRankingController.java | 274 +++ .../FitnessWalkStepStatisticsController.java | 165 ++ .../FitnessWalkStepWiningController.java | 155 ++ .../model/FitnessWalkActivity.java | 235 ++ .../model/FitnessWalkAwardUser.java | 101 + .../model/FitnessWalkPunchLottery.java | 78 + .../model/FitnessWalkRaffleRules.java | 55 + .../model/FitnessWalkRaffleUser.java | 61 + .../fitnesswalk/model/FitnessWalkStep.java | 50 + .../service/FitnessWalkCommonService.java | 86 + .../FitnessWalkPunchStatisticsService.java | 20 + .../service/FitnessWalkStepRaffleService.java | 34 + .../impl/FitnessWalkCommonServiceImpl.java | 492 +++++ ...FitnessWalkPunchStatisticsServiceImpl.java | 247 +++ .../FitnessWalkStepRaffleServiceImpl.java | 360 ++++ .../fitnesswalk/utils/WeAppCloudUtil.java | 170 ++ .../data/WorkersHomeDataRevelController.java | 308 +++ .../data/WorkersHomeDataTypeController.java | 134 ++ ...WorkersHomeDeclarationApplyController.java | 93 + .../WorkersHomeDeclarationMineController.java | 147 ++ ...HomeDeclarationOrganizationController.java | 100 + ...orkersHomeDeclarationSchoolController.java | 119 + ...rsHomeDeclarationStatisticsController.java | 71 + .../info/WorkersHomeApplyController.java | 66 + .../info/WorkersHomeInfoController.java | 60 + .../info/WorkersHomeMineController.java | 97 + .../WorkersHomeSchoolAuditController.java | 102 + .../review/WorkersHomeReviewController.java | 115 + .../WorkersHomeReviewExportController.java | 267 +++ .../WorkersHomeReviewProxyController.java | 64 + .../review/WorkersHomeReviewStatistics.java | 441 ++++ .../WorkersHomeReviewViewController.java | 165 ++ .../MWorkersHomeReviewController.java | 301 +++ .../workershome/model/WorkersHome.java | 130 ++ .../workershome/model/WorkersHomeApply.java | 130 ++ .../model/WorkersHomeDataRevel.java | 95 + .../model/WorkersHomeDataType.java | 43 + .../review/WorkersHomeReviewContent.java | 58 + .../model/review/WorkersHomeReviewExport.java | 49 + .../review/WorkersHomeReviewGrading.java | 66 + .../model/review/WorkersHomeReviewNorm.java | 97 + .../model/review/WorkersHomeReviewPeo.java | 93 + .../model/review/WorkersHomeReviewProxy.java | 96 + .../model/review/WorkersHomeReviewResult.java | 52 + .../service/WorkersHomeApplyService.java | 28 + .../service/WorkersHomeInfoService.java | 7 + .../impl/WorkersHomeApplyServiceImpl.java | 58 + .../impl/WorkersHomeInfoServiceImpl.java | 14 + .../impl/review/CommentBzServiceImpl.java | 20 + .../impl/review/CommentNrServiceImpl.java | 20 + .../impl/review/CommentPeoServiceImpl.java | 64 + .../review/CommentStatisticsServiceImpl.java | 87 + .../impl/review/CommentZbServiceImpl.java | 82 + .../service/review/CommentBzService.java | 8 + .../service/review/CommentNrService.java | 8 + .../service/review/CommentPeoService.java | 16 + .../review/CommentStatisticsService.java | 22 + .../service/review/CommentZbService.java | 13 + .../workershome/vo/WakesHomeVo.java | 34 + .../zhgh/integral/model/IntegralDetail.java | 1 - .../manage/models/goods/dto/GoodsDTO.java | 187 ++ .../manage/models/goods/entity/BrandDO.java | 64 + .../models/goods/entity/CategoryBrandDO.java | 66 + .../models/goods/entity/CategoryDO.java | 151 ++ .../models/goods/entity/CategorySpecDO.java | 63 + .../models/goods/entity/DraftGoodsDO.java | 307 +++ .../goods/entity/DraftGoodsParamsDO.java | 80 + .../models/goods/entity/DraftGoodsSkuDO.java | 106 + .../manage/models/goods/entity/GoodsDO.java | 481 +++++ .../models/goods/entity/GoodsGalleryDO.java | 101 + .../models/goods/entity/GoodsParamsDO.java | 79 + .../models/goods/entity/GoodsSkuDO.java | 225 ++ .../models/goods/entity/ParameterGroupDO.java | 64 + .../models/goods/entity/ParametersDO.java | 113 + .../models/goods/entity/QuantityLog.java | 153 ++ .../models/goods/entity/SpecValuesDO.java | 78 + .../models/goods/entity/SpecificationDO.java | 83 + .../models/goods/entity/TagGoodsDO.java | 64 + .../manage/models/goods/entity/TagsDO.java | 76 + .../models/goods/enums/GoodsOperate.java | 25 + .../manage/models/goods/enums/GoodsType.java | 23 + .../manage/models/goods/enums/Permission.java | 30 + .../models/goods/enums/QuantityLogType.java | 33 + .../models/goods/enums/QuantityType.java | 19 + .../manage/models/goods/enums/StockType.java | 31 + .../manage/models/goods/enums/TagType.java | 38 + .../manage/models/goods/vo/ExchangeVO.java | 48 + .../models/goods/vo/GoodsMobileIntroVO.java | 64 + .../models/goods/vo/GoodsQuantityVO.java | 91 + .../manage/models/goods/vo/GoodsSkuVO.java | 176 ++ .../manage/models/goods/vo/SpecValueVO.java | 95 + .../DifficultHelpApplyController.java | 170 ++ ...cultHelpBranchUnionApprovalController.java | 119 + .../DifficultHelpReadingController.java | 86 + ...cultHelpSchoolUnionApprovalController.java | 119 + .../DifficultHelpViewController.java | 47 + .../DifficultHelpSaveInterceptor.java | 40 + .../models/DifficultHelpInfo.java | 160 ++ .../service/DifficultHelpCommonService.java | 14 + .../impl/DifficultHelpCommonServiceImpl.java | 22 + .../vo/DifficultHelpPageParam.java | 59 + .../member/constant/MemberChangeOrigin.java | 5 +- .../member/constant/MemberChangeType.java | 10 + ...berApplyBranchUnionApprovalController.java | 156 ++ ...MemberApplyBranchUnionAuditController.java | 186 -- .../apply/MemberApplyController.java | 160 +- .../apply/MemberApplyMineController.java | 180 -- ...berApplySchoolUnionApprovalController.java | 174 ++ ...MemberApplySchoolUnionAuditController.java | 181 -- .../apply/MemberApplyViewController.java | 72 + .../MemberBranchUnionAuditController.java | 113 - .../MemberBranchUnionManageController.java | 124 -- .../MemberBranchUnionRecordController.java | 58 - .../MemberBranchUnionAuditController.java | 160 ++ .../change/MemberChangeApplyController.java | 150 ++ .../change/MemberChangeManageController.java | 206 +- .../change/MemberChangeRecordController.java | 28 +- .../change/MemberChangeViewController.java | 89 + .../MemberSchoolUnionAuditController.java | 222 ++ .../MemberSchoolUnionAuditController.java | 128 -- .../MemberSchoolUnionManageController.java | 93 - .../MemberSchoolUnionRecordController.java | 56 - ...mberBranchVerificationCheckController.java | 38 +- .../MemberListVerificationController.java | 10 +- ...mberSchoolVerificationCheckController.java | 60 +- .../MemberApplyBranchApprovalInterceptor.java | 93 + .../MemberApplySaveInterceptor.java | 47 + .../MemberApplySchoolApprovalInterceptor.java | 53 + .../MemberChangeSaveInterceptor.java | 68 + ...MemberChangeSchoolApprovalInterceptor.java | 37 + .../member/models/MemberApplyRecord.java | 62 +- .../member/models/MemberChangeRecord.java | 225 ++ .../param/pageform/MemberApplyPageForm.java | 14 +- .../param/pageform/MemberChangePageForm.java | 62 + .../param/pageform/MemberManagePageForm.java | 6 +- ...eService.java => MemberCommonService.java} | 64 +- .../MemberBranchUnionManageServiceImpl.java | 10 +- .../MemberListVerificationServiceImpl.java | 12 +- .../service/impl/MemberManageServiceImpl.java | 464 ++-- .../MemberSchoolUnionManageServiceImpl.java | 8 +- ...MemberApplyVo.java => MemberCommonVo.java} | 7 +- .../MemberPaymentChartSummaryController.java | 184 ++ .../MemberPaymentConfigController.java | 103 + .../MemberPaymentMineController.java | 187 ++ .../MemberPaymentProjectController.java | 295 +++ .../MemberPaymentRefundController.java | 115 + .../MemberPaymentSummaryController.java | 287 +++ .../MemberPaymentUserController.java | 85 + .../MobileMemberCostListController.java | 97 + .../memberCost/model/MemberPaymentConfig.java | 73 + .../memberCost/model/MemberPaymentInfo.java | 118 + .../model/MemberPaymentProject.java | 68 + .../service/MemberPaymentService.java | 76 + .../impl/MemberPaymentServiceImpl.java | 174 ++ .../template/MemberPaymentTemp.java | 34 + .../SourceChangeManageController.java | 29 +- .../SpecialStaffManageController.java | 45 +- .../specialstaff/model/SpecialStaff.java | 46 +- .../impl/SpecialStaffManageServiceImpl.java | 14 +- .../static/assets/mobile/svg/memberPay/hf.svg | 1 + .../assets/mobile/svg/memberPay/icon_xsgj.svg | 1 + .../assets/mobile/svg/memberPay/money.svg | 1 + .../assets/mobile/svg/memberPay/payFail.png | Bin 0 -> 116813 bytes .../mobile/svg/memberPay/paySuccess.svg | 1 + .../static/assets/mobile/svg/memberPay/wx.svg | 1 + .../assets/mobile/svg/memberPay/wx_img.png | Bin 0 -> 62232 bytes .../assets/mobile/svg/memberPay/yjf.svg | 1 + .../assets/mobile/svg/memberPay/zf_img.png | Bin 0 -> 124448 bytes .../assets/mobile/svg/memberPay/zfb.svg | 1 + .../assets/platform/js/tool/businessTool.js | 12 + .../assets/platform/module/mall/addGoods.css | 530 +++++ .../activity/fitnesswalk/activityManage.html | 1916 +++++++++++++++++ .../activity/fitnesswalk/bindingRecord.html | 266 +++ .../activity/fitnesswalk/punchStatistics.html | 264 +++ .../zhgh/activity/fitnesswalk/stepRaffle.html | 383 ++++ .../activity/fitnesswalk/stepRanking.html | 177 ++ .../activity/fitnesswalk/stepStatistics.html | 202 ++ .../zhgh/activity/fitnesswalk/stepWining.html | 187 ++ .../dayofficework/workershome/data/revel.html | 460 ++++ .../dayofficework/workershome/data/type.html | 207 ++ .../workershome/declaration/apply.html | 222 ++ .../declaration/components/info.js | 66 + .../workershome/declaration/mine.html | 175 ++ .../declaration/organizationAudit.html | 230 ++ .../workershome/declaration/schoolAudit.html | 286 +++ .../workershome/declaration/statistics.html | 177 ++ .../dayofficework/workershome/info/apply.html | 347 +++ .../dayofficework/workershome/info/info.html | 223 ++ .../dayofficework/workershome/info/mine.html | 162 ++ .../workershome/info/schoolAudit.html | 229 ++ .../review/components/addReviewProxy.js | 385 ++++ .../review/components/reviewResult.js | 113 + .../workershome/review/doReview.html | 444 ++++ .../workershome/review/khzb.html | 211 ++ .../workershome/review/statistics.html | 421 ++++ .../workershome/review/xjkhzb.html | 137 ++ .../difficulthelp/apply/form.html | 541 +++++ .../difficulthelp/apply/index.html | 177 ++ .../branchunionapproval/form.html | 45 + .../branchunionapproval/index.html | 141 ++ .../schoolunionapproval/form.html | 49 + .../schoolunionapproval/index.html | 141 ++ .../difficulthelp/view/index.html | 126 ++ .../apply/branchunionapproval/form.html | 45 + .../apply/branchunionapproval/index.html | 126 ++ .../member/apply/branchunionaudit/index.html | 233 -- .../member/apply/common/commonQuery.js | 85 + .../apply/common/memberApplyAuditInfo.js | 127 ++ .../staffmanage/member/apply/mine/index.html | 127 +- .../apply/schoolunionapproval/form.html | 84 + .../apply/schoolunionapproval/index.html | 125 ++ .../member/apply/schoolunionaudit/index.html | 236 -- .../staffmanage/member/apply/submit/form.html | 466 ++++ .../member/apply/submit/index.html | 404 ++-- .../staffmanage/member/apply/view/index.html | 144 ++ .../member/change/branchUnionAudit/form.html | 44 + .../member/change/branchUnionAudit/index.html | 214 ++ .../member/change/common/commonQuery.js | 87 + .../change/common/memberAllChangeInfo.js | 109 + .../member/change/common/memberChange.js | 519 +++++ .../change/common/memberChangeAuditInfo.js | 144 ++ .../member/change/manage/index.html | 37 +- .../staffmanage/member/change/mine/index.html | 148 ++ .../member/change/record/index.html | 235 +- .../member/change/schoolUnionAudit/form.html | 44 + .../member/change/schoolUnionAudit/index.html | 209 ++ .../member/change/submit/form.html | 532 +++++ .../member/change/submit/index.html | 155 ++ .../member/change/submit/oldindex.html | 60 + .../staffmanage/member/change/view/index.html | 165 ++ .../member/common/apply/memberApply.js | 252 --- .../common/audit/memberAuditChangeInfo.js | 158 -- .../member/common/audit/memberAuditRecord.js | 71 - .../member/common/audit/memberAuditTable.js | 201 -- .../member/common/change/memberChange.js | 368 ---- .../member/common/change/memberChangeInfo.js | 108 - .../member/common/info/memberInfo.js | 104 +- .../member/common/record/memberRecord.js | 143 -- .../membercost/chartSummary/index.html | 376 ++++ .../zhgh/staffmanage/membercost/config.html | 370 ++++ .../staffmanage/membercost/mine/index.html | 368 ++++ .../membercost/mine/minePayInfo.js | 125 ++ .../zhgh/staffmanage/membercost/project.html | 410 ++++ .../staffmanage/membercost/refund/index.html | 185 ++ .../zhgh/staffmanage/membercost/summary.html | 483 +++++ .../zhgh/staffmanage/membercost/user.html | 337 +++ .../manage/addOrModifySpecialStaff.js | 235 +- .../specialstaff/manage/index.html | 452 +++- .../memberCost/memberCostList.html | 416 ++++ .../staffmanage/memberCost/paySuccess.html | 134 ++ .../staffmanage/memberCost/summary.html | 198 ++ 294 files changed, 36042 insertions(+), 4361 deletions(-) create mode 100644 src/main/java/com/budwk/app/base/payment/alipay/controller/AlipayClientController.java create mode 100644 src/main/java/com/budwk/app/base/payment/alipay/service/AlipayClientConfig.java create mode 100644 src/main/java/com/budwk/app/base/payment/alipay/service/AlipayService.java create mode 100644 src/main/java/com/budwk/app/base/payment/alipay/service/impl/AlipayNewServiceImpl.java create mode 100644 src/main/java/com/budwk/app/base/payment/enums/RefundStateEnum.java create mode 100644 src/main/java/com/budwk/app/base/payment/enums/TradingChannelEnum.java create mode 100644 src/main/java/com/budwk/app/base/payment/enums/TradingStateEnum.java create mode 100644 src/main/java/com/budwk/app/base/payment/enums/TradingTypeEnum.java create mode 100644 src/main/java/com/budwk/app/base/payment/enums/WxPayResultCode.java create mode 100644 src/main/java/com/budwk/app/base/payment/model/PaymentRefundRecord.java create mode 100644 src/main/java/com/budwk/app/base/payment/model/PaymentTransaction.java create mode 100644 src/main/java/com/budwk/app/base/payment/wxpay/bean/WxPayV3Bean.java create mode 100644 src/main/java/com/budwk/app/base/payment/wxpay/controller/WxPayCommonController.java create mode 100644 src/main/java/com/budwk/app/base/payment/wxpay/pem/apiclient_cert.pem create mode 100644 src/main/java/com/budwk/app/base/payment/wxpay/pem/apiclient_key.pem create mode 100644 src/main/java/com/budwk/app/base/payment/wxpay/pem/wechatpay.pem create mode 100644 src/main/java/com/budwk/app/base/payment/wxpay/service/WxPayCommonService.java create mode 100644 src/main/java/com/budwk/app/base/payment/wxpay/service/impl/WxPayCommonServiceImpl.java create mode 100644 src/main/java/com/budwk/app/base/payment/wxpay/util/WeChatUtils.java create mode 100644 src/main/java/com/budwk/app/base/payment/wxpay/vo/WxPayNeedParamVo.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/declare/controller/ActivityDeclareApplyController.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/declare/models/ActivityDeclareInfo.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/reimbursement/controller/ActivityReimbursementApplyController.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/reimbursement/models/ActivityReimbursementInfo.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/contants/Cascader.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/contants/FitnessWalkMode.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkActivityBindingRecordController.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkActivityManageController.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkCommonController.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkLoginController.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkPunchLotteryController.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkPunchStatisticsController.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepManageController.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepRaffleController.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepRankingController.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepStatisticsController.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepWiningController.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkActivity.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkAwardUser.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkPunchLottery.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkRaffleRules.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkRaffleUser.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkStep.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/FitnessWalkCommonService.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/FitnessWalkPunchStatisticsService.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/FitnessWalkStepRaffleService.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/impl/FitnessWalkCommonServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/impl/FitnessWalkPunchStatisticsServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/impl/FitnessWalkStepRaffleServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/utils/WeAppCloudUtil.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/data/WorkersHomeDataRevelController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/data/WorkersHomeDataTypeController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationApplyController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationMineController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationOrganizationController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationSchoolController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationStatisticsController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeApplyController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeInfoController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeMineController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeSchoolAuditController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewExportController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewProxyController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewStatistics.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewViewController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/h5controller/MWorkersHomeReviewController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHome.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHomeApply.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHomeDataRevel.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHomeDataType.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewContent.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewExport.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewGrading.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewNorm.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewPeo.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewProxy.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewResult.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/WorkersHomeApplyService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/WorkersHomeInfoService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/WorkersHomeApplyServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/WorkersHomeInfoServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentBzServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentNrServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentPeoServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentStatisticsServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentZbServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentBzService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentNrService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentPeoService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentStatisticsService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentZbService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workershome/vo/WakesHomeVo.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/dto/GoodsDTO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/BrandDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/CategoryBrandDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/CategoryDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/CategorySpecDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/DraftGoodsDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/DraftGoodsParamsDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/DraftGoodsSkuDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsGalleryDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsParamsDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsSkuDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/ParameterGroupDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/ParametersDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/QuantityLog.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/SpecValuesDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/SpecificationDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/TagGoodsDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/TagsDO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/GoodsOperate.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/GoodsType.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/Permission.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/QuantityLogType.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/QuantityType.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/StockType.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/TagType.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/ExchangeVO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/GoodsMobileIntroVO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/GoodsQuantityVO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/GoodsSkuVO.java create mode 100644 src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/SpecValueVO.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpApplyController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpBranchUnionApprovalController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpReadingController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpSchoolUnionApprovalController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpViewController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/interceptor/DifficultHelpSaveInterceptor.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/models/DifficultHelpInfo.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/service/DifficultHelpCommonService.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/service/impl/DifficultHelpCommonServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/vo/DifficultHelpPageParam.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyBranchUnionApprovalController.java delete mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyBranchUnionAuditController.java delete mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyMineController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplySchoolUnionApprovalController.java delete mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplySchoolUnionAuditController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyViewController.java delete mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/branch/MemberBranchUnionAuditController.java delete mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/branch/MemberBranchUnionManageController.java delete mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/branch/MemberBranchUnionRecordController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberBranchUnionAuditController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeApplyController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeViewController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberSchoolUnionAuditController.java delete mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/MemberSchoolUnionAuditController.java delete mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/MemberSchoolUnionManageController.java delete mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/MemberSchoolUnionRecordController.java rename src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/{branch => }/verification/MemberBranchVerificationCheckController.java (86%) rename src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/{school => }/verification/MemberListVerificationController.java (94%) rename src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/{school => }/verification/MemberSchoolVerificationCheckController.java (85%) create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberApplyBranchApprovalInterceptor.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberApplySaveInterceptor.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberApplySchoolApprovalInterceptor.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberChangeSaveInterceptor.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberChangeSchoolApprovalInterceptor.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/models/MemberChangeRecord.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/member/param/pageform/MemberChangePageForm.java rename src/main/java/com/budwk/app/zhgh/staffmanage/member/service/{MemberManageService.java => MemberCommonService.java} (55%) rename src/main/java/com/budwk/app/zhgh/staffmanage/member/vo/{MemberApplyVo.java => MemberCommonVo.java} (87%) create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentChartSummaryController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentConfigController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentMineController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentProjectController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentRefundController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentSummaryController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentUserController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/h5controller/MobileMemberCostListController.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/model/MemberPaymentConfig.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/model/MemberPaymentInfo.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/model/MemberPaymentProject.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/service/MemberPaymentService.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/service/impl/MemberPaymentServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/template/MemberPaymentTemp.java create mode 100644 src/main/resources/static/assets/mobile/svg/memberPay/hf.svg create mode 100644 src/main/resources/static/assets/mobile/svg/memberPay/icon_xsgj.svg create mode 100644 src/main/resources/static/assets/mobile/svg/memberPay/money.svg create mode 100644 src/main/resources/static/assets/mobile/svg/memberPay/payFail.png create mode 100644 src/main/resources/static/assets/mobile/svg/memberPay/paySuccess.svg create mode 100644 src/main/resources/static/assets/mobile/svg/memberPay/wx.svg create mode 100644 src/main/resources/static/assets/mobile/svg/memberPay/wx_img.png create mode 100644 src/main/resources/static/assets/mobile/svg/memberPay/yjf.svg create mode 100644 src/main/resources/static/assets/mobile/svg/memberPay/zf_img.png create mode 100644 src/main/resources/static/assets/mobile/svg/memberPay/zfb.svg create mode 100644 src/main/resources/static/assets/platform/module/mall/addGoods.css create mode 100644 src/main/resources/views/platform/zhgh/activity/fitnesswalk/activityManage.html create mode 100644 src/main/resources/views/platform/zhgh/activity/fitnesswalk/bindingRecord.html create mode 100644 src/main/resources/views/platform/zhgh/activity/fitnesswalk/punchStatistics.html create mode 100644 src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepRaffle.html create mode 100644 src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepRanking.html create mode 100644 src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepStatistics.html create mode 100644 src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepWining.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/data/revel.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/data/type.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/apply.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/components/info.js create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/mine.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/organizationAudit.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/schoolAudit.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/statistics.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/info/apply.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/info/info.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/info/mine.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/info/schoolAudit.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/review/components/addReviewProxy.js create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/review/components/reviewResult.js create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/review/doReview.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/review/khzb.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/review/statistics.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workershome/review/xjkhzb.html create mode 100644 src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/apply/form.html create mode 100644 src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/apply/index.html create mode 100644 src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/branchunionapproval/form.html create mode 100644 src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/branchunionapproval/index.html create mode 100644 src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/schoolunionapproval/form.html create mode 100644 src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/schoolunionapproval/index.html create mode 100644 src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/view/index.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/apply/branchunionapproval/form.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/apply/branchunionapproval/index.html delete mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/apply/branchunionaudit/index.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/apply/common/commonQuery.js create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/apply/common/memberApplyAuditInfo.js create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/apply/schoolunionapproval/form.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/apply/schoolunionapproval/index.html delete mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/apply/schoolunionaudit/index.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/apply/submit/form.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/apply/view/index.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/change/branchUnionAudit/form.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/change/branchUnionAudit/index.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/change/common/commonQuery.js create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/change/common/memberAllChangeInfo.js create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/change/common/memberChange.js create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/change/common/memberChangeAuditInfo.js create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/change/mine/index.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/change/schoolUnionAudit/form.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/change/schoolUnionAudit/index.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/change/submit/form.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/change/submit/index.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/change/submit/oldindex.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/change/view/index.html delete mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/common/apply/memberApply.js delete mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/common/audit/memberAuditChangeInfo.js delete mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/common/audit/memberAuditRecord.js delete mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/common/audit/memberAuditTable.js delete mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/common/change/memberChange.js delete mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/common/change/memberChangeInfo.js delete mode 100644 src/main/resources/views/platform/zhgh/staffmanage/member/common/record/memberRecord.js create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/membercost/chartSummary/index.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/membercost/config.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/membercost/mine/index.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/membercost/mine/minePayInfo.js create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/membercost/project.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/membercost/refund/index.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/membercost/summary.html create mode 100644 src/main/resources/views/platform/zhgh/staffmanage/membercost/user.html create mode 100644 src/main/resources/views/platform/zhghh5/staffmanage/memberCost/memberCostList.html create mode 100644 src/main/resources/views/platform/zhghh5/staffmanage/memberCost/paySuccess.html create mode 100644 src/main/resources/views/platform/zhghh5/staffmanage/memberCost/summary.html diff --git a/pom.xml b/pom.xml index ecfefb32..91efa6fa 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,30 @@ UTF-8 + + + com.github.javen205 + IJPay-All + 2.9.10 + + + + com.alibaba + dashscope-sdk-java + 2.14.4 + + + org.slf4j + slf4j-simple + + + + + com.alipay.sdk + alipay-sdk-java + 4.35.37.ALL + + org.apache.axis axis diff --git a/src/main/java/com/budwk/app/base/constant/BpmProcessConstant.java b/src/main/java/com/budwk/app/base/constant/BpmProcessConstant.java index b97b0b75..c023259d 100644 --- a/src/main/java/com/budwk/app/base/constant/BpmProcessConstant.java +++ b/src/main/java/com/budwk/app/base/constant/BpmProcessConstant.java @@ -25,6 +25,7 @@ public enum BpmProcessConstant { GRASSROOTS_CONGRESS_MATERIALS("基层双代会会议资料"), MEMBER_SINGLE_APPLY("会员入会申请"), + MEMBER_CHANGE("会员入会申请"), MEMBER_BRANCH_UNION_CHANGE("会员分工会变更"), diff --git a/src/main/java/com/budwk/app/base/constant/RedisConstant.java b/src/main/java/com/budwk/app/base/constant/RedisConstant.java index e0d67dc7..959e6f7e 100644 --- a/src/main/java/com/budwk/app/base/constant/RedisConstant.java +++ b/src/main/java/com/budwk/app/base/constant/RedisConstant.java @@ -20,6 +20,9 @@ public class RedisConstant { //企业微信token public final static String REDIS_KEY_WX_WORK_TOKEN = PLATFORM_REDIS_PREFIX + "wxwork:token:"; + //健步走小程序TOKEN + public final static String REDIS_KEY_WE_APP_ACCESS_TOKEN = PLATFORM_REDIS_PREFIX + "weapp:token:"; + //图形验证码 public final static String REDIS_CAPTCHA_KEY = PLATFORM_REDIS_PREFIX + "platfrom:captcha:"; diff --git a/src/main/java/com/budwk/app/base/payment/alipay/controller/AlipayClientController.java b/src/main/java/com/budwk/app/base/payment/alipay/controller/AlipayClientController.java new file mode 100644 index 00000000..acae258d --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/alipay/controller/AlipayClientController.java @@ -0,0 +1,68 @@ +package com.budwk.app.base.payment.alipay.controller; + +import com.budwk.app.base.payment.alipay.service.AlipayService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * @ClassName AlipayClientController + * @Description TODO + * @Author zhf + * @Date 2024/1/25 15:36 + */ +@IocBean +@Slf4j +@Ok("json:full") +@At("/mobile/memberCost/AlipayClient") +public class AlipayClientController { + + + @Inject + private AlipayService alipayService; + + + @At("/tradePagePay") + public String tradePagePay(String money, String paymentProjectId) throws Exception { + log.info("统一收单下单并支付接口调用"); + String formStr = alipayService.tradeCreate(money, paymentProjectId); + return formStr; + } + + @At("/tradeNotify") + @Ok("re") + public String tradeNotify(HttpServletRequest request) { + try { + Map params = new HashMap(); + Map requestParams = request.getParameterMap(); + for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) { + String name = (String) iter.next(); + String[] values = (String[]) requestParams.get(name); + String valueStr = ""; + for (int i = 0; i < values.length; i++) { + valueStr = (i == values.length - 1) ? valueStr + values[i] + : valueStr + values[i] + ","; + } + //乱码解决,这段代码在出现乱码时使用 + + valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8"); + + params.put(name, valueStr); + } + log.info("支付通知,正在执行,通知参数:{}"); + return alipayService.tradeNotify(params); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + } + +} diff --git a/src/main/java/com/budwk/app/base/payment/alipay/service/AlipayClientConfig.java b/src/main/java/com/budwk/app/base/payment/alipay/service/AlipayClientConfig.java new file mode 100644 index 00000000..0508909e --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/alipay/service/AlipayClientConfig.java @@ -0,0 +1,22 @@ +package com.budwk.app.base.payment.alipay.service; + +/** + * @ClassName AlipayClientConfig + * @Description TODO + * @Author zhf + * @Date 2024/1/25 15:33 + */ +public interface AlipayClientConfig { + String serverUrl = "https://openapi.alipay.com/gateway.do"; + String appId = "2021004133670087"; + String sellerId = "2088002638762620"; + String privateKey = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCEJBWNlUIY/2Tave1OtjTgvA21GZ5tdvZZD3jFmixIFTkEdZaRUpXCvlKuZ9heoL1IQwpbuOErJ4dM2f2Ju/Oc7QtUOjEOX6CnElR73KK5OSY8d8f5822LUOgp2zg5FHI6C7olYmjN4Nw26G6BGyqQBmWs4/sKzghKelEaH9AqkR8DZ+yOvuYtIg5KEvVixsM27TMhd6/3BuNXDIiQDVH9ZeQVb9IKuynZ6hnUJS0T4MkS41qehS1u8LgplGU5yvrNuUNeQtybADsiGHDNmNkl5lVt0QNh+N/lo56//duf5PJwh8ApDB22eXptiS6p321PSrYowy5VeFpHC07Tref9AgMBAAECggEAPQddXPKegGUT82LcgwnsCg9QVV/rp6rVw/Q9VyYJZZFHsCOO0rdNq4+zKBGWAL5ELWepFQuiEwhCmN/lFQPVU5i3LsNhfL31uLPiiQIxtVILssmvdmVTJpDLaOlyYgprZxubcUCuHsfHbSSURNSDJ9mMg/kXLLpTYfJ0Gpiuz7lkrMuAxncdz88Sp2r0O9k2T+TcnHFpRXHs+C/QAaa15EF18ieDSBLPkY0ti1R8J91LGAzDrjwcP7pNlq4u7TasZ7djv47ZFwQ3yjWoo13d9ab0MBYeQx9Grf5N+JGNf33YLyulQ0IshcuwNyB+RYhyWGjNmjnJdytzKRMOYSpPgQKBgQC6iqMPX+LGunyI+3T9l/AwAVWRJXzEHPflNxDYfQbicB5awlRixxH5T1qyZ46KZb/pBt01qDULXy0bEObVFSjAn1wXPzC9Fwb+BtVZUroYBTKV3tOAMpVCz2AAC34OZwG/3X//sRtW9Sr0Dr+yCcx8ULMiFS1BuCZfhSNXA516NQKBgQC1V+rge1pYKGnjtWqML4qJy4FEIDI4fSpGIizxumYDMxdXoUdNKoG2NHQkznHU4fIHJPVvIN/Tm82mfj2rhH9eFuu1FB8TL2soe5nPgzSJ9AmP7rZ7KBo3/SczvZqUEpii8+PjHu+Gx95BmgTzOFMnYz8xzitb4IBGTEGxVzavqQKBgCL28XFkS6FsOwOB/n+6Bu84kM1P9X7c3yo7lBC//pZa5ZWlbyPEpH3SffGKr5EJWVtYSgZQrQCgqle0Z0/xU14ngJ9q3LvUoR7kMQE5HGB8OOsWhRY2ZPvM2vWnMc2JSS6pWeCXVcSK164/RXcdlxKGHc15oq360lZ9Ig6hQtcxAoGAIYijd2V4HGtEwYXvsQKtlLOcMNPfVZDXu2Zgd0bnzFmrTFoXjE569A2ZGKFQbXRmxClydV1X5pKeIdagYtI6l1SXu8F/yZVwNGk+1R/HHGeTSRl0hyuwRYA7upaqOg2CSkfdcUdsNblKAUmQ9sUIo3T336bnX7MRJW6+iyO8ihkCgYBG8vG1fVUwPmqlRK+QanHxicR1+UyjRAN+aW6dgJUNMlC+tmPeHj21+WGkDdKPdhinHziLihLmzbmpwWSDwuGMMQPNQm8gSjiaqy1tWcP6XKDxjpG5biTzwEyHNuCIY6odS4HTeDOrrU4LvN6PxirN8xKBIpq+A2cgpGo+Mn4x+g=="; + String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjO/QUy+ujNBlToL6Kt8YjvTRGpEwmXjqc9pFe7GIORVkzBXP3F/UC/w5mPiwXhhyymXAe7bUwLANL/QMUZhvpjjCdLENtFWC9bd6hq3m2oHiTu0oicbzqCuaoQkzik2NybrNjuH+aYVi4RU0eNYpdewQoHHW+hbfxkSYUWmx7NF4SuG93edYlpc/G/ImdrweATLE0b6W9il4H/BxVUweCraPrispiOM8r6TN3fiIKUQRP15HKQo8Xsr4pMJzfi37I9aN8AThN/xBf6sual8IZZsH5hC3PS37LrYkXbUjt0dK5tqKl3SsZPjvvHGyz9b9JC225+0q09Y6B8/axOlihwIDAQAB"; + + /* String serverUrl = "https://openapi-sandbox.dl.alipaydev.com/gateway.do"; + String appId = "9021000134641646"; + String privateKey = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCBFTF8qFbK+NiqUbKf1/jWHL/s0hfUXK6cyKwZCEXkEMZH1Lu6kZQl3kQye9Fsasawxn1vLmKz+OKjMiE+TdTytHDu5ULdLlSHN3bY1qf91i8L+RJfmZpb1p+NQOk9zImhhSauuk+itMkTC3bTiwwAkg/utOxkNB7YaynpAb3evhXnlX3LUVTHaMnCQFeV7ithh7CDKx0LPlxOpOvxnkWDBR3nsdcfjDqYNDVHXnUxEk0KQV4Ik6fA40+Gq/HXTByJolCSAaTk0OaH2ULp1RZAklWLqhiNEhytTZAlJUx8cSm36mm0c4jhgSXNdRz0Yi1BlPY9yxQGStpH5ue3+EfvAgMBAAECggEAda/D4Zp9HysIJyi7SZ6XwWaO2TSnAzfI/yq6NUxkpE1i6cSbr7rgrjHaTYiz5DvpkOw3GnHZDarhvtaKlopRl0JKIJSnhI6kBG/eDE6Q9Q4c8LaSONULdaXU6+z9ehmMddW28eDtkDNxi8qM+MuyEqcYnZMYXzdh1ADIQicTXArxo+9fpvlKUMNxOTO5LoOf0DtJg/xE1CD9PtWVc+l2G8S3+C52+RhfZ214YQdxwayMlvJQlWzLTbfzJCp8w4F2up1nJdwp7EY8k8xDUngEnG6BWm8ztWUVTTg7qp/+SC9yMTD2dl86wDkJt1lTtwcKaWxHYh2ZIn8a8+icHFykaQKBgQDgBEWAmuj0pgpny5Q0GRsUYPq42SwpN70u4rmD5UYFCeDHaKb4U3kyvA1V+1Tp0XWzFi7GU855h1n8dnQX64J3Vm4GfhftWwTJgB5ibbY53cZVEoV5nZe0bOO4hxxMdNy3BKjPovkT0REPpCkVas/RRLAFCdnvi6vmDkFxvv9JewKBgQCTgx9NZZCqSzzCJYpLTDOCitooOQmR8kAlgBiDCcHeH2wNVMh5O2Dl/OyTGauKUJFWIOSD8FXVTrNUbOEmx58msnS/+Mc5SnbEka5ptVEDp73gf6ctB+eZAMdO1kLsBT3iKnuyNa7pRyR/D2A692RHOTQZIvRHE1N+kM1r+iBPHQKBgCZRVLocxUAjrp/2eJE4wiMIO5qmuyEJwbhlW6ot634tJF+3jOfpD1AYToeoh+u+wk0xvCp8Z1LuTfwbHtyAkj5rcEJ4Cwu0h+sXmRro/USEpMokcuRMioh4H7OOmM6TJrW/fEiX7dbv6eUtBUH+lTGMeDdEahzJXUvqoFMegnhFAoGAa2eflRUMflIFzT7UMPsszjIXog3VoASJHETmlBK4q+ipHhPLXCoV5Z+BCaI5Op5rFBEjEcYeWQ/Slvgn/7p9cQmi5FxZgqdrTrjcC2/Pqx+pqxqHOMx2nvroI8jyNTOj2VchdaKM1qHMOw+Q+55Bz3IhMuQ2hMHXm2IHkEUw3SkCgYBjcqcWbJcq26L8yYVpU2JFzOvu7iHuV99TpEvF9Ym3cAcSNuoR5kGXzGS0MadYY87cd4HK9HvmXQmthLY14buKYxq27ZFfNbK/Auz8vk0Wbrm1Ym4Z1yMqClQqxKdr4hV29ijn1nPProRqgnVsGH3EtFmNxDfilZoVzh9ERaZe7w=="; + String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArhElUiFMpxqFCs+8zDHa4OVuhdWgKUUGVKgWnfLktPgy9mDZkuGPKk295k8ktWQSUZsnFvT8ikJIKdGYfbSWzlXvCAn6lDDDlsjfOJWMQ6zLmb9xygCih2OjwN5xt9QFIIthnWq8sOXpWvqmoRpIFQHolxxmvvCmUZ/VwK6mwgwU/yVvVypruQ/FGrJA70LAcJ764spWAMy/pWIoIs5UewOlJa3TAcZQIqRnjupL2/sI/TpIWFWF90a/rahwLfBgZ83VH7MA4Tl9uFLc3aeNFLllDF4X7lRdzaHIMYgUUKte9yvlDy5Ihrt+ssjsgdRhqLHvFn00u/g7BCvO5ZmIUwIDAQAB"; +*/ + +} diff --git a/src/main/java/com/budwk/app/base/payment/alipay/service/AlipayService.java b/src/main/java/com/budwk/app/base/payment/alipay/service/AlipayService.java new file mode 100644 index 00000000..fa4486b0 --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/alipay/service/AlipayService.java @@ -0,0 +1,15 @@ +package com.budwk.app.base.payment.alipay.service; + + +import com.budwk.app.base.service.BaseService; + +import java.util.Map; + +public interface AlipayService extends BaseService { + /** + * 支付宝开放平台接收 request请求对象后 + * @return + */ + String tradeCreate( String money, String paymentProjectId) throws Exception; + String tradeNotify(Map params) ; +} diff --git a/src/main/java/com/budwk/app/base/payment/alipay/service/impl/AlipayNewServiceImpl.java b/src/main/java/com/budwk/app/base/payment/alipay/service/impl/AlipayNewServiceImpl.java new file mode 100644 index 00000000..553ac948 --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/alipay/service/impl/AlipayNewServiceImpl.java @@ -0,0 +1,140 @@ +package com.budwk.app.base.payment.alipay.service.impl; + +import com.alipay.api.AlipayApiException; +import com.alipay.api.AlipayConstants; +import com.alipay.api.DefaultAlipayClient; +import com.alipay.api.domain.AlipayTradeWapPayModel; +import com.alipay.api.internal.util.AlipaySignature; +import com.alipay.api.request.AlipayTradeWapPayRequest; +import com.alipay.api.response.AlipayTradeWapPayResponse; +import com.budwk.app.base.payment.alipay.service.AlipayClientConfig; +import com.budwk.app.base.payment.alipay.service.AlipayService; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentInfo; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +import java.util.Date; +import java.util.Map; + +/** + * @ClassName AlipayNewServiceImpl + * @Description TODO + * @Author zhf + * @Date 2024/1/25 15:38 + */ + +@Slf4j +@IocBean(args = {"refer:dao"}) +public class AlipayNewServiceImpl extends BaseServiceImpl implements AlipayService { + public AlipayNewServiceImpl(Dao dao) { + super(dao); + } + + DefaultAlipayClient alipayClient = new DefaultAlipayClient(AlipayClientConfig.serverUrl, + AlipayClientConfig.appId, + AlipayClientConfig.privateKey, + AlipayConstants.FORMAT_JSON, + AlipayConstants.CHARSET_UTF8, + AlipayClientConfig.alipayPublicKey, + AlipayConstants.SIGN_TYPE_RSA2); + + @Override + public String tradeCreate(String money, String paymentProjectId) throws Exception { + String outTradeNo = String.valueOf(new Date().getTime()); + AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest(); + //支付宝公共参数 + request.setReturnUrl("http://sansi.ltd/mobile/memberCost/AlipayClient/tradeNotify"); + + + //面向对象封装业务参数 + AlipayTradeWapPayModel model = new AlipayTradeWapPayModel(); + model.setOutTradeNo(outTradeNo); + model.setTotalAmount(money); + model.setSubject("会员入会会费"); + model.setProductCode("QUICK_WAP_WAY"); + model.setSellerId(AlipayClientConfig.sellerId); + model.setTimeoutExpress("30m"); + model.setQuitUrl("http://sansi.ltd/mobile/memberCost/list"); + + request.setBizModel(model); + + //执行请求,调用支付宝 + AlipayTradeWapPayResponse response = alipayClient.pageExecute(request, "POST"); + if (response.isSuccess()) { + dao().update(MemberPaymentInfo.class, Chain.make("payId", outTradeNo), Cnd.where("paymentProjectId", "=", paymentProjectId) + .and("userId", "=", SecurityUtil.getUserId())); + log.info("调用成功,返回结果:[{}]", response.getBody()); + return response.getBody(); + } else { + log.info("调用失败!!"); + } + return null; + } + + @Override + public String tradeNotify(Map params) { + String total_amount = params.get("total_amount"); + String out_trade_no = params.get("out_trade_no"); + String trade_no = params.get("trade_no"); + +// + String result = "failure"; + try { + //异步通知验签 + boolean signVerified = AlipaySignature.rsaCheckV1(params, + AlipayClientConfig.alipayPublicKey, + AlipayConstants.CHARSET_UTF8, + AlipayConstants.SIGN_TYPE_RSA2); + if (!signVerified) { + // TODO 验签失败则记录异常日志,并在response中返回failure. + log.error("支付成功,异步通知验签失败!"); + return result; + } + log.info("支付成功,异步通知验签成功!"); + //TODO 验签成功后,按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验 + //1.验证out_trade_no 是否为商家系统中创建的订单号 + String outTradeNo = params.get("out_trade_no"); + if (!outTradeNo.equals(out_trade_no)) { + log.error("订单号不一致"); + return result; + } + //2.判断 total_amount 是否确实为该订单的实际金额 + String totalAmount = params.get("total_amount"); + if (!totalAmount.equals(total_amount)) { + log.error("订单的实际金额不一致"); + return result; + } + //3.校验通知中的 seller_id是否为 out_trade_no 这笔单据的对应的操作方 + String sellerId = params.get("seller_id"); + if (!sellerId.equals(AlipayClientConfig.sellerId)) { + log.error("商家PID校验失败"); + return result; + } + //4.验证 app_id 是否为该商家本身 + String appId = params.get("app_id"); + if (!appId.equals(AlipayClientConfig.appId)) { + log.error("app_id校验失败"); + return result; + } + + dao().update(MemberPaymentInfo.class, + Chain.make("isPayment", true) + .add("paymentMoney", total_amount) + .add("paymentTime", new Date()) + .add("tradeNo", trade_no), + Cnd.where("userId", "=", SecurityUtil.getUserId()).and("payId", "=", out_trade_no)); + + //TODO 处理自身业务 + result = "->:/mobile/memberCost/list/paySuccess"; + } catch (AlipayApiException e) { + e.printStackTrace(); + } + + return result; + } +} diff --git a/src/main/java/com/budwk/app/base/payment/enums/RefundStateEnum.java b/src/main/java/com/budwk/app/base/payment/enums/RefundStateEnum.java new file mode 100644 index 00000000..39b33ca3 --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/enums/RefundStateEnum.java @@ -0,0 +1,24 @@ +package com.budwk.app.base.payment.enums; + +import com.budwk.app.base.annotation.DictEnum; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 退款状态枚举 + */ +@Getter +@AllArgsConstructor +@DictEnum(key = "RefundStateEnum", name = "退款状态枚举") +public enum RefundStateEnum { + + INITIATE_REFUND("发起退款"), + REFUNDING("退款中"), + REFUND_SUCCESS("退款成功"), + REFUND_FAILED("退款失败"); + + /** + * 避免和枚举类的name冲突 + */ + public final String refundStateName; +} diff --git a/src/main/java/com/budwk/app/base/payment/enums/TradingChannelEnum.java b/src/main/java/com/budwk/app/base/payment/enums/TradingChannelEnum.java new file mode 100644 index 00000000..c8e0fd3f --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/enums/TradingChannelEnum.java @@ -0,0 +1,25 @@ +package com.budwk.app.base.payment.enums; + +import com.budwk.app.base.annotation.DictEnum; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 交易渠道枚举 + */ +@Getter +@AllArgsConstructor +@DictEnum(key = "TradingChannelEnum", name = "交易渠道枚举") +public enum TradingChannelEnum { + + QQ_PAY("QQ"), + WX_PAY("微信"), + JD_PAY("京东"), + ALI_PAY("支付宝"), + UNION_PAY("云闪付"); + + /** + * 避免和枚举类的name冲突 + */ + public final String tradingChannelName; +} diff --git a/src/main/java/com/budwk/app/base/payment/enums/TradingStateEnum.java b/src/main/java/com/budwk/app/base/payment/enums/TradingStateEnum.java new file mode 100644 index 00000000..8e2c3a63 --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/enums/TradingStateEnum.java @@ -0,0 +1,24 @@ +package com.budwk.app.base.payment.enums; + +import com.budwk.app.base.annotation.DictEnum; +import lombok.AllArgsConstructor; +import lombok.Getter; + + +/** + * 支付状态枚举 + */ +@Getter +@AllArgsConstructor +@DictEnum(key = "TradingStateEnum", name = "支付状态枚举") +public enum TradingStateEnum { + + WAITING_FOR_PAYMENT("等待支付"), + PAY_SUCCESS("支付成功"), + CANCEL_PAYMENT("取消支付"); + + /** + * 避免和枚举类的name冲突 + */ + public final String tradingStateName; +} diff --git a/src/main/java/com/budwk/app/base/payment/enums/TradingTypeEnum.java b/src/main/java/com/budwk/app/base/payment/enums/TradingTypeEnum.java new file mode 100644 index 00000000..b4ba9379 --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/enums/TradingTypeEnum.java @@ -0,0 +1,22 @@ +package com.budwk.app.base.payment.enums; + +import com.budwk.app.base.annotation.DictEnum; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 交易类型枚举 + */ +@Getter +@AllArgsConstructor +@DictEnum(key = "TradingTypeEnum", name = "交易类型枚举") +public enum TradingTypeEnum { + + PAYMENT("付款"), + REFUND("退款"); + + /** + * 避免和枚举类的name冲突 + */ + public final String tradingTypeName; +} diff --git a/src/main/java/com/budwk/app/base/payment/enums/WxPayResultCode.java b/src/main/java/com/budwk/app/base/payment/enums/WxPayResultCode.java new file mode 100644 index 00000000..d8912181 --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/enums/WxPayResultCode.java @@ -0,0 +1,30 @@ +package com.budwk.app.base.payment.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @version 1.0 + * @Author zzr + * @name:WxPayResultCode + * @Date 2025/3/10 10:27 + * @注释 微信支付返回码 + */ +@Getter +@AllArgsConstructor +public enum WxPayResultCode { + + SUCCESS(200, "操作成功"), + APPID_MCHID_NOT_MATCH(400, "商户ID和服务号或企业微信号不匹配"), + INVALID_REQUEST(400, "无效请求"), + MCH_NOT_EXISTS(400, "商户号不存在"), + PARAM_ERROR(400, "参数错误"), + SIGN_ERROR(401, "签名错误"), + NO_AUTH(403, "商户无权限"), + OUT_TRADE_NO_USED(403, "商户订单号重复"), + FREQUENCY_LIMITED(429, "频率超限"), + SYSTEM_ERROR(500, "系统错误"); + + final int code; + final String msg; +} diff --git a/src/main/java/com/budwk/app/base/payment/model/PaymentRefundRecord.java b/src/main/java/com/budwk/app/base/payment/model/PaymentRefundRecord.java new file mode 100644 index 00000000..76bb109a --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/model/PaymentRefundRecord.java @@ -0,0 +1,61 @@ +package com.budwk.app.base.payment.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.math.BigDecimal; + +/** + * 退款记录表 + */ +@Data +@Table +@Comment("退款记录表") +@EqualsAndHashCode(callSuper = true) +public class PaymentRefundRecord extends BaseModel { + + @Column + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("关联系统交易订单表Id") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String paymentTransactionId; + + @Column + @Comment("本次退款订单号") + @ColDefine(type = ColType.VARCHAR,width = 128) + private String outRefundTradeNo; + + @Column + @Comment("第三方支付的退款单号") + @ColDefine(type = ColType.VARCHAR,width = 128) + private String refundNo; + + @Column + @Comment("退款状态") + @ColDefine(type = ColType.VARCHAR,width = 30) + private String refundState; + + @Column + @Comment("本次退款金额") + @ColDefine(type = ColType.INT) + private Integer refundAmount; + + @Column + @Comment("原订单金额") + @ColDefine(type = ColType.INT) + private Integer total; + + @Column + @Comment("交易返回数据") + @ColDefine(type = ColType.MYSQL_JSON) + private String resultJson; +} diff --git a/src/main/java/com/budwk/app/base/payment/model/PaymentTransaction.java b/src/main/java/com/budwk/app/base/payment/model/PaymentTransaction.java new file mode 100644 index 00000000..b1961339 --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/model/PaymentTransaction.java @@ -0,0 +1,131 @@ +package com.budwk.app.base.payment.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.math.BigDecimal; + +/** + * 交易单表 + */ +@Data +@Table +@Comment("交易订单表") +@EqualsAndHashCode(callSuper = true) +public class PaymentTransaction extends BaseModel { + + @Column + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("商户号") + @ColDefine(type = ColType.VARCHAR,width = 128) + private String mchId; + + @Column + @Comment("订单号,传递给交易系统,交易系统订单号") + @ColDefine(type = ColType.VARCHAR,width = 128) + private String outTradeNo; + + @Column + @Comment("交易系统交易号") + @ColDefine(type = ColType.VARCHAR,width = 128) + private String transactionId; + + @Column + @Comment("交易渠道") + @ColDefine(type = ColType.VARCHAR,width = 50) + private String tradingChannel; + + @Column + @Comment("交易类型") + @ColDefine(type = ColType.VARCHAR,width = 30) + private String tradingType; + + @Column + @Comment("交易状态") + @ColDefine(type = ColType.VARCHAR,width = 50) + private String tradingState; + + @Column + @Comment("用户ID") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String userId; + + @Column + @Comment("用户工号") + @ColDefine(type = ColType.VARCHAR,width = 50) + private String loginName; + + @Column + @Comment("用户姓名") + @ColDefine(type = ColType.VARCHAR,width = 50) + private String userName; + + @Column + @Comment("工会id") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String unionId; + + @Column + @Comment("用户工会") + @ColDefine(type = ColType.VARCHAR,width = 50) + private String unionName; + + @Column + @Comment("单位id") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String unitId; + + @Column + @Comment("用户单位") + @ColDefine(type = ColType.VARCHAR,width = 50) + private String unitName; + + @Column + @Comment("交易金额") + @ColDefine(type = ColType.INT) + private Integer tradingAmount; + + @Column + @Comment("是否退款") + @ColDefine(type = ColType.BOOLEAN) + private Boolean isRefund; + + @Column + @Comment("退款金额") + @ColDefine(type = ColType.INT) + private Integer refundAmount; + + @Column + @Comment("订单描述") + @ColDefine(type = ColType.VARCHAR,width = 128) + private String description; + + @Column + @Comment("附加详细描述") + @ColDefine(type = ColType.TEXT) + private String attach; + + @Column + @Comment("微信支付用户openId") + @ColDefine(type = ColType.VARCHAR,width = 50) + private String openId; + + @Column + @Comment("交易返回数据") + @ColDefine(type = ColType.MYSQL_JSON) + private String resultJson; + + @Column + @Comment("交易名单的主键id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String memberPaymentInfoId; +} diff --git a/src/main/java/com/budwk/app/base/payment/wxpay/bean/WxPayV3Bean.java b/src/main/java/com/budwk/app/base/payment/wxpay/bean/WxPayV3Bean.java new file mode 100644 index 00000000..c3ef48be --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/wxpay/bean/WxPayV3Bean.java @@ -0,0 +1,53 @@ +package com.budwk.app.base.payment.wxpay.bean; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @version 1.0 + * @Author zzr + * @name:WxPayV3Bean + * @Date 2025/3/6 9:54 + * @注释 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class WxPayV3Bean { + + /** + * 服务号 + * appid: wxf12fa6175ec7c75f + * app_secret: f65bbb41d3de4a93c8c93d8e2fd50369 + */ + + private String appId; + private String keyPath; + private String publicKeyPath; + private String certPath; + private String certP12Path; + private String platformCertPath; + private String mchId; + private String apiKey; + private String apiKey3; + private String domain; + private String publicKeyId; + + @Override + public String toString() { + return "WxPayV3Bean{" + + "appId='" + appId + '\'' + + ", keyPath='" + keyPath + '\'' + + ", publicKeyPath='" + publicKeyPath + '\'' + + ", certPath='" + certPath + '\'' + + ", certP12Path='" + certP12Path + '\'' + + ", platformCertPath='" + platformCertPath + '\'' + + ", mchId='" + mchId + '\'' + + ", apiKey='" + apiKey + '\'' + + ", apiKey3='" + apiKey3 + '\'' + + ", domain='" + domain + '\'' + + ", publicKeyId='" + publicKeyId + '\'' + + '}'; + } +} diff --git a/src/main/java/com/budwk/app/base/payment/wxpay/controller/WxPayCommonController.java b/src/main/java/com/budwk/app/base/payment/wxpay/controller/WxPayCommonController.java new file mode 100644 index 00000000..598272ec --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/wxpay/controller/WxPayCommonController.java @@ -0,0 +1,44 @@ +package com.budwk.app.base.payment.wxpay.controller; + +import com.budwk.app.base.payment.wxpay.service.WxPayCommonService; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * @version 1.0 + * @Author zzr + * @name:WxPayCommonController + * @Date 2025/3/10 19:28 + * @注释 微信支付回调 + */ +@Slf4j +@IocBean +@Ok("json:full") +@At("/platform/wxPay") +public class WxPayCommonController { + + @Inject + private WxPayCommonService wxPayCommonService; + + + @At + @Ok("void") + @ApiOperation("微信支付-付款回调") + public void payNotify(HttpServletRequest request, HttpServletResponse response){ + wxPayCommonService.payNotify(request, response); + } + + + @At + @Ok("void") + public void refundNotify(HttpServletRequest request, HttpServletResponse response){ + wxPayCommonService.refundNotify(request, response); + } +} diff --git a/src/main/java/com/budwk/app/base/payment/wxpay/pem/apiclient_cert.pem b/src/main/java/com/budwk/app/base/payment/wxpay/pem/apiclient_cert.pem new file mode 100644 index 00000000..ee557fe9 --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/wxpay/pem/apiclient_cert.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEKDCCAxCgAwIBAgIUONYpzvxVfV/RrWnLGPlL6/nb/AcwDQYJKoZIhvcNAQEL +BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT +FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg +Q0EwHhcNMjUwMzA2MTQwNDAzWhcNMzAwMzA1MTQwNDAzWjCBgTETMBEGA1UEAwwK +MTY2NjkzMDk4MDEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMS0wKwYDVQQL +DCTmrabmsYnlnLDlpKfkuInmgJ3np5HmioDmnInpmZDlhazlj7gxCzAJBgNVBAYT +AkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBALlDML+FJEW+m2hXp/qUH1cU6xlwFllLU4LjFusJkxwyzzcZO4nY0mOi +3woz8xIJipvUWj2Y413WYwMkfcJcRgghupZkfYwdQtSyPfUu7xQBUm8TLWGH88Re +kyyVABEB5T+ne6r3LesXS4IuZknm5N/iaa4z9mbbscGqF0GLvMUqZCRNyTkyfK9r +Bkvs/vspi+Jcjx9I7aU++h/vwzsGB6Bf/uB3kLMb+lj/i3xY20sdrrW8JD2sqONQ +NcRIKmNXSp4zsNy+d6kIKWE3P5609ZTta1ogkeGBNdGXMRNNy6vLIudQc7zny/9H +S4LxGsIrsYmZNhGljRng56X+PG3w1CUCAwEAAaOBuTCBtjAJBgNVHRMEAjAAMAsG +A1UdDwQEAwID+DCBmwYDVR0fBIGTMIGQMIGNoIGKoIGHhoGEaHR0cDovL2V2Y2Eu +aXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJDMDRC +MDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyJnNnPUhBQ0M0NzFCNjU0MjJFMTJCMjdB +OUQzM0E4N0FEMUNERjU5MjZFMTQwMzcxMA0GCSqGSIb3DQEBCwUAA4IBAQBQ5e8U +1pQ40gfRoZyO0s+QF16L8pAcVLVwHffo0mmJpIRB4bu8W5IJ9kKhksJ0CzZ0YEwB +Yv7/LTC1qpi7PE73nZ4Ytm9oZeH1Kk5KIlQS+2H3IwOpoV4wucMc34y6MVQJjC7E +u5OnglBPSAopwNP4p+Us9A3ah7Ks48XCw+LCEWpA/setJwo9C13Qq2AQm8qLpogK +pNBwm/oylxb8/kZK1lLPgcXd7geLDhl/Str+aOzBXyd7YSEMxS8zWiZhWozu6rCq +dg10QFKicPGDkDzNQwBz7cDXvlJXSWRDBK5r1li1YgX+QD5WJYPchATo5SlvF4Lr +5/V/dZzI7BJTinr1 +-----END CERTIFICATE----- diff --git a/src/main/java/com/budwk/app/base/payment/wxpay/pem/apiclient_key.pem b/src/main/java/com/budwk/app/base/payment/wxpay/pem/apiclient_key.pem new file mode 100644 index 00000000..36b4b679 --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/wxpay/pem/apiclient_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC5QzC/hSRFvpto +V6f6lB9XFOsZcBZZS1OC4xbrCZMcMs83GTuJ2NJjot8KM/MSCYqb1Fo9mONd1mMD +JH3CXEYIIbqWZH2MHULUsj31Lu8UAVJvEy1hh/PEXpMslQARAeU/p3uq9y3rF0uC +LmZJ5uTf4mmuM/Zm27HBqhdBi7zFKmQkTck5MnyvawZL7P77KYviXI8fSO2lPvof +78M7BgegX/7gd5CzG/pY/4t8WNtLHa61vCQ9rKjjUDXESCpjV0qeM7DcvnepCClh +Nz+etPWU7WtaIJHhgTXRlzETTcuryyLnUHO858v/R0uC8RrCK7GJmTYRpY0Z4Oel +/jxt8NQlAgMBAAECggEBAKGQqTi9Ii741Ysftsze1J4bDhS3HaZt/LyO0vPS+8qB +vRiuFrBWuNRPu/en6nl2fLz9al2Bsfep+dtJvar80c5Rq+lwZdUFx7y6XTIv5iwq +IvvfW5pM+Bfu6qbcopwybP0gUMd+nTsCq8UyNd6JUFy3lbZodqCpQ9JDRdjRxqSi +oMonve36Q9kJyDs0mS2F0w+Y9oYFtpE9WvGMBthwT7VfzWuDa+YC/Gh0RhT2V9OG +uDC8kxmfaIbk0IITDVFWVMMhScXiqmJL1II9yQWsCHH73dZS+dDxwwH0ObRD3kOx +hHptxpRzhtuNxLjCOZDGhneyvUHIftpqf4wdOgQ8iUECgYEA6TDo36s3XDFIs8SH +lpVYrhie0nmaNET50CtOc5C2M1OotrkMUrQTMoa4F263UloJfqweW9AKZX11wPp2 +8h7af2sZsGawjuwv7mMthZJoi0fc5J2+z6BnVGgFo7uZbcs1Y/+B0tNrDKIHVrqb +Lywmh18iKDXrMiMDMRp8mtiNyU0CgYEAy2Im0oGb1rmAh9gPvQIENmNEgRsyIU4x +WPAFb5KO7jnseO9KrC9uiRSO5JuwZu/QNGlga2w77Gu7n+Q4HfSU2KFlNhR6pKjb +mqXzPq1quryzbtWay520VsRKz3F/Tfp1FUpIuZvj8x7FrL8z8vjbLkbW4p+Z7HE4 +heYdmk2KCjkCgYBC6xU48pJtc3swk2pxjSQoucoCDoFxFIY39eWKhnGy4wQcg5gE +t8Z2jnCP0ObszAfDgTMpF9eT7l/3ZCj0LGR5gkuZ8q4iJadPmsh6d1xm89VxCc+z +F43vi/ZqWTCbcGA+9RjVXnRu6KSAgAZ+kAXyfRt5PJflCGUnFznA2fo+VQKBgG6s +n7Gno/UKBv5lPdM9mKs8A5g6A2KKWWIrYtnfJ/ZNAPiiRsFCImVoEYYnjqvFTkhn +G3f5cvZpfbU5jKwIX0MvOJNgO4kE9lPGgIKX/d9WNlJW3KB21h7tPER8X6lAZJxM +SxztzvKKyUkC1zMd5q/dDqxN64X16qs6mNtR3I9JAoGBAJbqQtg59Szi2m4jZ9Xo +0cKvP7+PSKgysdWsemTkU0ji1rcMpGRTtcUGRWlawLjRSInQS+xNdL6GVU5mHZWe +gNwXIXEpape4IJta0B1PYAhNcIvOSh5CzcUnVTeo6q0CTSVQPdsivlrObLKZ4uGQ +eewDw82Ej6YoSgczjf99ug0x +-----END PRIVATE KEY----- diff --git a/src/main/java/com/budwk/app/base/payment/wxpay/pem/wechatpay.pem b/src/main/java/com/budwk/app/base/payment/wxpay/pem/wechatpay.pem new file mode 100644 index 00000000..aaa69381 --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/wxpay/pem/wechatpay.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEFDCCAvygAwIBAgIUKN05Gm0Q9n9mLPPltUh8qjKKegQwDQYJKoZIhvcNAQEL +BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT +FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg +Q0EwHhcNMjUwMzA2MTQwNDAzWhcNMzAwMzA1MTQwNDAzWjBuMRgwFgYDVQQDDA9U +ZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl +bnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGEwJDTjERMA8GA1UEBwwIU2hlblpo +ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDbMenF0GNlcUYErPpj +Aj+WOuzRFz+PJcrtgkI81S0WDh8flMtq1A2nwKARNyPXx+UPd9it657nH5G8E9kL +Ea5u5rENpn+JZc4cAIvZqazteSAUg2pfQH9ewW+/CxNOWarjXPNRYa0OjZWf+5F8 +ZBOT/x8sJ2+jou9lxKNe1skha+jzmiQ8m3B2vPXqR87qgL/fyQjjpLvBGpvearh/ +hxTMBEfGeB4F6Fu52Fz3/VCWe38ubxwj8EMcRSPp4xsl2BTaRVMMT525Hul2N49C +vXCSVsCNt3ND8UDffXnb19Zgpir4KqpECTbfqcT7YX+U34P1Av8gcDl6rRm+7Wpj +PY4RAgMBAAGjgbkwgbYwCQYDVR0TBAIwADALBgNVHQ8EBAMCA/gwgZsGA1UdHwSB +kzCBkDCBjaCBiqCBh4aBhGh0dHA6Ly9ldmNhLml0cnVzLmNvbS5jbi9wdWJsaWMv +aXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0QjA2QUQzOTc1NDk4NDZDMDFDM0U4 +RUJEMiZzZz1IQUNDNDcxQjY1NDIyRTEyQjI3QTlEMzNBODdBRDFDREY1OTI2RTE0 +MDM3MTANBgkqhkiG9w0BAQsFAAOCAQEAUAvXCx55ZGmd3ATi28W4mirnUHQb2RAw +X5/0OC2SkuBdzxI5RbY4YAuugP6nQIAU8TXCANzno2oqZ6vmFZ4dBnJmLewVFMoM +qp18A4RWmnsGnmEIgMm6N1kB+RbM11oLCLdy2KK0SvmqDmTBFJyjyUGqEmRshnV/ +QfKn4UUzJ4suDFAolGX4DyDIOtM0D+SCHwwxGI4yf2+nj4IB8XgmmOeschxoSvu9 +T3E6BgQ271YVDwg+3r9CiFVI5JdyftvQagOEQmZJMPINEKgFn5LzrZJW7mH42+N+ +i4RFz04wpGUsrSFDESh3JxYSNhq/HulpMLinntWxEBHFhpkjyyGDGg== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/src/main/java/com/budwk/app/base/payment/wxpay/service/WxPayCommonService.java b/src/main/java/com/budwk/app/base/payment/wxpay/service/WxPayCommonService.java new file mode 100644 index 00000000..0333726b --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/wxpay/service/WxPayCommonService.java @@ -0,0 +1,71 @@ +package com.budwk.app.base.payment.wxpay.service; + + +import com.budwk.app.base.payment.wxpay.vo.WxPayNeedParamVo; +import com.budwk.app.base.result.Result; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * @version 1.0 + * @Author zzr + * @name:WxPayCommonService + * @Date 2025/3/6 11:40 + * @注释 + */ +public interface WxPayCommonService { + + + /** + * 二维码统一下单,返回支付二维码链接 + * @param paramVo 需要传递的信息,请自定义付款金额Amount 和 付款描述Description,其他关键信息请勿修改 + * 注意Amount的总价total是int类型,会自动乘以0.01,例如传递100元,会自动转换为1元 + * @return + */ + Result nativePay(WxPayNeedParamVo paramVo); + + + /** + * JSAPI支付,返回支付参数 + * @param paramVo 需要传递的信息,请自定义付款金额Amount 和 付款描述Description,其他关键信息请勿修改 + * 注意Amount的总价total是int类型,会自动乘以0.01,例如传递100元,会自动转换为1元 + * JsAPI支付,需要传递openId,请自行获取 + * @return + */ + Result jsApiPay(WxPayNeedParamVo paramVo); + + /** + * WAP支付,返回支付参数 + * @param paramVo 需要传递的信息,请自定义付款金额Amount 和 付款描述Description,其他关键信息请勿修改 + * 注意Amount的总价total是int类型,会自动乘以0.01,例如传递100元,会自动转换为1元 + * @return + */ + Result wapPay(WxPayNeedParamVo paramVo); + + + /** + * 支付回调,验证是否支付成功 + * @param request 请求 + * @param response 响应 + */ + void payNotify(HttpServletRequest request, HttpServletResponse response); + + + /** + * 退款 + * @param transactionId 微信订单号 + * @param outTradeNo 商户订单号 + * @return + */ + Result refund(String transactionId, String outTradeNo); + + + /** + * 退款回调 + * @param request 请求 + * @param response 响应 + */ + void refundNotify(HttpServletRequest request, HttpServletResponse response); + +} diff --git a/src/main/java/com/budwk/app/base/payment/wxpay/service/impl/WxPayCommonServiceImpl.java b/src/main/java/com/budwk/app/base/payment/wxpay/service/impl/WxPayCommonServiceImpl.java new file mode 100644 index 00000000..0b3cd689 --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/wxpay/service/impl/WxPayCommonServiceImpl.java @@ -0,0 +1,612 @@ +package com.budwk.app.base.payment.wxpay.service.impl; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.ContentType; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.payment.enums.*; +import com.budwk.app.base.payment.model.PaymentRefundRecord; +import com.budwk.app.base.payment.model.PaymentTransaction; +import com.budwk.app.base.payment.wxpay.bean.WxPayV3Bean; +import com.budwk.app.base.payment.wxpay.service.WxPayCommonService; +import com.budwk.app.base.payment.wxpay.vo.WxPayNeedParamVo; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.sys.services.SysUserService; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentInfo; +import com.ijpay.core.IJPayHttpResponse; +import com.ijpay.core.enums.AuthTypeEnum; +import com.ijpay.core.enums.RequestMethodEnum; +import com.ijpay.core.kit.AesUtil; +import com.ijpay.core.kit.HttpKit; +import com.ijpay.core.kit.PayKit; +import com.ijpay.core.kit.WxPayKit; +import com.ijpay.wxpay.WxPayApi; +import com.ijpay.wxpay.enums.WxDomainEnum; +import com.ijpay.wxpay.enums.v3.BasePayApiEnum; +import com.ijpay.wxpay.model.v3.*; +import lombok.extern.slf4j.Slf4j; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.random.R; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayInputStream; +import java.io.FileWriter; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.nio.charset.StandardCharsets; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @version 1.0 + * @Author zzr + * @name:WxPayCommonServiceImpl + * @Date 2025/3/6 11:41 + * @注释 + */ +@Slf4j +@IocBean +public class WxPayCommonServiceImpl implements WxPayCommonService { + + // 判断下单接口成功返回码 + private final static int OK = 200; + + // 1666930980 商户号 + // ww3eda050a1b5ad96e 企业微信 + // wxf12fa6175ec7c75f 微信服务号 + // 微信V3必要的支付参数,后期优化 + private final static WxPayV3Bean WX_PAY_V3_BEAN = new WxPayV3Bean( + "wxf12fa6175ec7c75f", + "src/main/java/com/budwk/app/base/payment/wxpay/pem/apiclient_key.pem", + "src/main/java/com/budwk/app/base/payment/wxpay/pem/apiclient_key.pem", + "src/main/java/com/budwk/app/base/payment/wxpay/pem/apiclient_cert.pem", + "src/main/java/com/budwk/app/base/payment/wxpay/pem/apiclient_cert.pem", + "src/main/java/com/budwk/app/base/payment/wxpay/pem/wechatpay.pem", + "1666930980", + "", + "4ebd020883285d698c44ec50939c0967", + "https://schoolhd.top/platform", + ""); + + // 自定义参数,内容是统一的,但会被多次调用,直接声明 + private String serialNo; + private String platSerialNo; + private final String payNotifyUrl = WX_PAY_V3_BEAN.getDomain().concat("/wxPay/payNotify"); + private final String refundNotifyUrl = WX_PAY_V3_BEAN.getDomain().concat("/wxPay/refundNotify"); + + @Inject + private Dao dao; + @Inject + private SysUserService sysUserService; + + /** + * 微信扫描二维码支付 + * @param paramVo 需要传递的信息,请自定义付款金额Amount 和 付款描述Description,其他关键信息请勿修改 + * 注意Amount的总价total是int类型,会自动乘以0.01,例如传递100元,会自动转换为1元 + * @return + */ + @Override + @Aop(TransAop.READ_COMMITTED) + public Result nativePay(WxPayNeedParamVo paramVo) { + try { + // 商户订单号,存储当前用户的订单 + String outTradeNo = PayKit.generateStr(); + + String timeExpire = getNowTimeExpire(); + UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel() + .setAppid(WX_PAY_V3_BEAN.getAppId()) + .setMchid(WX_PAY_V3_BEAN.getMchId()) + // 描述信息 + .setDescription(paramVo.getDescription()) + .setOut_trade_no(outTradeNo) + .setTime_expire(timeExpire) + .setAttach(paramVo.getAttach()) + .setNotify_url(payNotifyUrl) + // 订单金额 + .setAmount(paramVo.getAmount()); + + log.info("二维码支付统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.NATIVE_PAY.toString(), + WX_PAY_V3_BEAN.getMchId(), + getSerialNumber(), + null, + WX_PAY_V3_BEAN.getKeyPath(), + JSONUtil.toJsonStr(unifiedOrderModel), + AuthTypeEnum.RSA.getCode() + ); + log.info("统一下单响应 {}", response); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, WX_PAY_V3_BEAN.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + // 下单返回数据 + String result = response.getBody(); + + JSONObject jsonObject = JSONUtil.parseObj(result); + + if (response.getStatus() == OK) { + // 统一下单成功,向数据库插入订单记录 + insertTradingOrder(paramVo, outTradeNo, result); + return Result.success("请在三分钟内完成支付,超时将自动取消订单").addData(result); + } else { + WxPayResultCode code = WxPayResultCode.valueOf(WxPayResultCode.class, jsonObject.getStr("code")); + return Result.error(code.getMsg()); + } + } catch (Exception e) { + log.error("系统异常", e); + return Result.error(e.getMessage()); + } + } + + + @Override + @Aop(TransAop.READ_COMMITTED) + public Result jsApiPay(WxPayNeedParamVo paramVo) { + try { + Sys_user user = dao.fetch(Sys_user.class, SecurityUtil.getUserId()); + if (StrUtil.isBlank(user.getOpenId())) { + return Result.error("未获取到当前用户的openid,请重新登录"); + } + // 商户订单号,存储当前用户的订单 + String outTradeNo = PayKit.generateStr(); + // 订单关闭时间 + String timeExpire = getNowTimeExpire(); + UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel() + .setAppid(WX_PAY_V3_BEAN.getAppId()) + .setMchid(WX_PAY_V3_BEAN.getMchId()) + .setDescription(paramVo.getDescription()) + .setOut_trade_no(outTradeNo) + .setTime_expire(timeExpire) + .setAttach(paramVo.getAttach()) + .setNotify_url(payNotifyUrl) + .setAmount(paramVo.getAmount()) + .setPayer(new Payer().setOpenid(user.getOpenId())); + + log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.JS_API_PAY.toString(), + WX_PAY_V3_BEAN.getMchId(), + getSerialNumber(), + null, + WX_PAY_V3_BEAN.getKeyPath(), + JSONUtil.toJsonStr(unifiedOrderModel) + ); + log.info("统一下单响应 {}", response); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, WX_PAY_V3_BEAN.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + if (response.getStatus() == OK && verifySignature) { + String body = response.getBody(); + JSONObject jsonObject = JSONUtil.parseObj(body); + String prepayId = jsonObject.getStr("prepay_id"); + Map map = WxPayKit.jsApiCreateSign(WX_PAY_V3_BEAN.getAppId(), prepayId, WX_PAY_V3_BEAN.getKeyPath()); + log.info("唤起支付参数:{}", map); + // 唤起支付成功,向数据库插入订单参数 + insertTradingOrder(paramVo, outTradeNo, body); + return Result.success().addData(JSONUtil.toJsonStr(map)); + } +// return JSONUtil.toJsonStr(response); + return Result.error("唤起支付失败"); + } catch (Exception e) { + log.error("系统异常", e); + return Result.error(e.getMessage()); + } + } + + + @Override + @Aop(TransAop.READ_COMMITTED) + public Result wapPay(WxPayNeedParamVo paramVo) { + try { + // 商户订单号,存储当前用户的订单 + String outTradeNo = PayKit.generateStr(); + // 订单关闭时间 + String timeExpire = getNowTimeExpire(); + UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel() + .setAppid(WX_PAY_V3_BEAN.getAppId()) + .setMchid(WX_PAY_V3_BEAN.getMchId()) + .setDescription(paramVo.getDescription()) + .setOut_trade_no(outTradeNo) + .setTime_expire(timeExpire) + .setAttach(paramVo.getAttach()) + .setNotify_url(payNotifyUrl) + .setAmount(paramVo.getAmount()) + .setScene_info( + new SceneInfo() + .setPayer_client_ip(""). + setH5_info(new H5Info() + .setType("Wap"))); + + log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.H5_PAY.toString(), + WX_PAY_V3_BEAN.getMchId(), + getSerialNumber(), + null, + WX_PAY_V3_BEAN.getKeyPath(), + JSONUtil.toJsonStr(unifiedOrderModel) + ); + log.info("统一下单响应 {}", response); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, WX_PAY_V3_BEAN.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + if (response.getStatus() == OK && verifySignature) { + String body = response.getBody(); + insertTradingOrder(paramVo, outTradeNo, body); + return Result.success(JSONUtil.toJsonStr(body)); + } +// return JSONUtil.toJsonStr(response); + return Result.error(); + } catch (Exception e) { + log.error("系统异常", e); + return Result.error(e.getMessage()); + } + } + + + /** + * 支付回调 + * @param request + * @param response + */ + @Override + public void payNotify(HttpServletRequest request, HttpServletResponse response) { + Map map = new HashMap<>(12); + try { + String timestamp = request.getHeader("Wechatpay-Timestamp"); + String nonce = request.getHeader("Wechatpay-Nonce"); + String serialNo = request.getHeader("Wechatpay-Serial"); + String signature = request.getHeader("Wechatpay-Signature"); + + log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature); + String result = HttpKit.readData(request); + log.info("支付通知密文 {}", result); +// String plainText = null; + // 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号 + String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, + WX_PAY_V3_BEAN.getApiKey3(), WX_PAY_V3_BEAN.getPlatformCertPath()); + // 微信公钥验证签名并解密 +// if (ObjectUtil.equals(serialNo, WX_PAY_V3_BEAN.getPublicKeyId())) { +// plainText = WxPayKit.verifyPublicKeyNotify(result, signature, nonce, timestamp, +// WX_PAY_V3_BEAN.getApiKey3(), WX_PAY_V3_BEAN.getPlatformCertPath()); +// } + log.info("支付通知明文 {}", plainText); + if (StrUtil.isNotEmpty(plainText)) { + // 支付结果 + JSONObject jsonResult = JSONUtil.parseObj(plainText); + // 获取缴费记录,并修改缴费结果 + PaymentTransaction transaction = sysUserService.dao().fetch(PaymentTransaction.class, Cnd.where("outTradeNo", "=", jsonResult.getStr("out_trade_no"))); + transaction.setTradingState(TradingStateEnum.PAY_SUCCESS.name()); + transaction.setTransactionId(jsonResult.getStr("transaction_id")); + sysUserService.dao().update(transaction); + + sysUserService.dao().update(MemberPaymentInfo.class, + Chain.make("isPayment", true).add("paymentTime", DateUtil.date()) + .add("paymentMoney", transaction.getTradingAmount()), + Cnd.where("id", "=", transaction.getMemberPaymentInfoId()) + ); + + response.setStatus(200); + map.put("code", "SUCCESS"); + map.put("message", "SUCCESS"); + } else { + response.setStatus(500); + map.put("code", "ERROR"); + map.put("message", "签名错误"); + log.error("签名错误"); + } + + // 支付回调,返回给微信,自己也接收不到结果,这里的返回没用 + response.setHeader("Content-type", ContentType.JSON.toString()); + response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8)); + response.flushBuffer(); + } catch (Exception e) { + log.error("系统异常", e); + } + } + + + /** + * 退款 + * @param transactionId 微信订单号 + * @param outTradeNo 商户订单号 + * @return + */ + @Override + public Result refund(String transactionId, String outTradeNo) { + try { + // 查询商户订单 + PaymentTransaction transaction = sysUserService.dao().fetch(PaymentTransaction.class, Cnd.where("outTradeNo", "=", outTradeNo)); + Integer tradingAmount = transaction.getTradingAmount(); + String outRefundNo = PayKit.generateStr(); + log.info("商户退款单号: {}", outRefundNo); + + // 没用 +// List list = new ArrayList<>(); +// RefundGoodsDetail refundGoodsDetail = new RefundGoodsDetail() +// .setMerchant_goods_id("123") +// .setGoods_name("测试") +// .setUnit_price(1) +// .setRefund_amount(1) +// .setRefund_quantity(1); +// list.add(refundGoodsDetail); + + RefundModel refundModel = new RefundModel() + .setOut_refund_no(outRefundNo) + .setReason(transaction.getDescription() + "退款") + .setNotify_url(refundNotifyUrl) + .setAmount(new RefundAmount().setRefund(tradingAmount).setTotal(tradingAmount).setCurrency("CNY")); +// .setGoods_detail(list); + + if (StrUtil.isNotEmpty(transactionId)) { + refundModel.setTransaction_id(transactionId); + } + if (StrUtil.isNotEmpty(outTradeNo)) { + refundModel.setOut_trade_no(outTradeNo); + } + log.info("退款参数 {}", JSONUtil.toJsonStr(refundModel)); + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.REFUND.toString(), + WX_PAY_V3_BEAN.getMchId(), + getSerialNumber(), + null, + WX_PAY_V3_BEAN.getKeyPath(), + JSONUtil.toJsonStr(refundModel) + ); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, WX_PAY_V3_BEAN.getPlatformCertPath()); + // 微信支付公钥验证签名 +// boolean verifySignature = WxPayKit.verifyPublicKeySignature(response, WX_PAY_V3_BEAN.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + log.info("退款响应 {}", response); + + if (verifySignature) { + // 用户发起退款,存一个退款记录 + PaymentRefundRecord record = new PaymentRefundRecord(); + record.setId(R.UU32()); + record.setPaymentTransactionId(transaction.getId()); + record.setOutRefundTradeNo(outRefundNo); + record.setRefundNo(null); + record.setRefundState(RefundStateEnum.REFUNDING.name()); + record.setRefundAmount(tradingAmount); + record.setTotal(tradingAmount); + record.setResultJson(response.getBody()); + dao.insert(record); + + dao.update(MemberPaymentInfo.class, Chain.make("isRefund", true) + .add("refundState", RefundStateEnum.REFUNDING.name()), + Cnd.where("id", "=", transaction.getMemberPaymentInfoId())); + + // 返回退款下单结果 + return Result.success(); + } + return Result.error("退款失败"); + } catch (Exception e) { + log.error("系统异常", e); + return Result.error(e.getMessage()); + } + } + + + /** + * 退款回调 + * @param request + * @param response + */ + @Override + @Aop(TransAop.READ_COMMITTED) + public void refundNotify(HttpServletRequest request, HttpServletResponse response) { + Map map = new HashMap<>(12); + try { + String timestamp = request.getHeader("Wechatpay-Timestamp"); + String nonce = request.getHeader("Wechatpay-Nonce"); + String serialNo = request.getHeader("Wechatpay-Serial"); + String signature = request.getHeader("Wechatpay-Signature"); + + log.info("退款通知 timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature); + String result = HttpKit.readData(request); + log.info("退款通知密文 {}", result); +// String plainText = null; + // 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号 + String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, + WX_PAY_V3_BEAN.getApiKey3(), WX_PAY_V3_BEAN.getPlatformCertPath()); + // 微信公钥验证签名并解密 +// if (ObjectUtil.equals(serialNo, WX_PAY_V3_BEAN.getPublicKeyId())) { +// plainText = WxPayKit.verifyPublicKeyNotify(result, signature, nonce, timestamp, +// WX_PAY_V3_BEAN.getApiKey3(), WX_PAY_V3_BEAN.getPlatformCertPath()); +// } + log.info("退款通知明文 {}", plainText); + + if (StrUtil.isNotEmpty(plainText)) { + // 取出明文,修改退款的结果 + JSONObject jsonObject = JSONUtil.parseObj(plainText); + // 查询出退款记录,存储关键信息并修改 + PaymentRefundRecord record = dao.fetch(PaymentRefundRecord.class, Cnd.where("outRefundTradeNo", "=", jsonObject.getStr("out_refund_no"))); + record.setRefundNo(jsonObject.getStr("refund_id")); + record.setRefundState(RefundStateEnum.REFUND_SUCCESS.name()); + // 到此是退款成功了,还要去修改订单表的数据 + PaymentTransaction transaction = dao.fetch(PaymentTransaction.class, record.getPaymentTransactionId()); + dao.update(PaymentTransaction.class, Chain.make("isRefund", true) + .add("refundAmount", record.getRefundAmount()), + Cnd.where("id", "=", record.getPaymentTransactionId())); + dao.update(MemberPaymentInfo.class, Chain.make("isPayment", null).add("paymentMoney", null) + .add("refundState", RefundStateEnum.REFUND_SUCCESS.name()), + Cnd.where("id", "=", transaction.getMemberPaymentInfoId())); + + dao.update(record); + response.setStatus(200); + map.put("code", "SUCCESS"); + map.put("message", "SUCCESS"); + } else { + response.setStatus(500); + map.put("code", "ERROR"); + map.put("message", "签名错误"); + } + // 没用 + response.setHeader("Content-type", ContentType.JSON.toString()); + response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8)); + response.flushBuffer(); + } catch (Exception e) { + log.error("系统异常", e); + } + } + + + /** + * 公共方法,获取证书序列号 + * @return + */ + private String getSerialNumber() { + if (StrUtil.isEmpty(serialNo)) { + // 获取证书序列号 + X509Certificate certificate = PayKit.getCertificate(WX_PAY_V3_BEAN.getCertPath()); + if (null != certificate) { + serialNo = certificate.getSerialNumber().toString(16).toUpperCase(); + // 提前两天检查证书是否有效 + boolean isValid = PayKit.checkCertificateIsValid(certificate, WX_PAY_V3_BEAN.getMchId(), -2); + log.info("证书是否可用 {} 证书有效期为 {}", isValid, DateUtil.format(certificate.getNotAfter(), DatePattern.NORM_DATETIME_PATTERN)); + } +// System.out.println("输出证书信息:\n" + certificate.toString()); +// // 输出关键信息,截取部分并进行标记 +// System.out.println("证书序列号:" + certificate.getSerialNumber().toString(16)); +// System.out.println("版本号:" + certificate.getVersion()); +// System.out.println("签发者:" + certificate.getIssuerDN()); +// System.out.println("有效起始日期:" + certificate.getNotBefore()); +// System.out.println("有效终止日期:" + certificate.getNotAfter()); +// System.out.println("主体名:" + certificate.getSubjectDN()); +// System.out.println("签名算法:" + certificate.getSigAlgName()); +// System.out.println("签名:" + certificate.getSignature().toString()); + } + System.out.println("serialNo:" + serialNo); + return serialNo; + } + + + /** + * 公共方法,获取平台证书序列号 + * @return + */ + private String getPlatSerialNumber() { + if (StrUtil.isEmpty(platSerialNo)) { + // 获取平台证书序列号 + X509Certificate certificate = PayKit.getCertificate(FileUtil.getInputStream(WX_PAY_V3_BEAN.getPlatformCertPath())); + platSerialNo = certificate.getSerialNumber().toString(16).toUpperCase(); + } + System.out.println("platSerialNo:" + platSerialNo); + return platSerialNo; + } + + + /** + * 公共方法,保存平台证书 + * @param associatedData + * @param nonce + * @param cipherText + * @param algorithm + * @param certPath + * @return + */ + private String savePlatformCert(String associatedData, String nonce, String cipherText, String algorithm, String certPath) { + try { + String key3 = WX_PAY_V3_BEAN.getApiKey3(); + String publicKey; + if (StrUtil.equals(algorithm, AuthTypeEnum.SM2.getPlatformCertAlgorithm())) { + publicKey = PayKit.sm4DecryptToString(key3, cipherText, nonce, associatedData); + } else { + AesUtil aesUtil = new AesUtil(WX_PAY_V3_BEAN.getApiKey3().getBytes(StandardCharsets.UTF_8)); + // 平台证书密文解密 + // encrypt_certificate 中的 associated_data nonce ciphertext + publicKey = aesUtil.decryptToString( + associatedData.getBytes(StandardCharsets.UTF_8), + nonce.getBytes(StandardCharsets.UTF_8), + cipherText + ); + } + if (StrUtil.isNotEmpty(publicKey)) { + // 保存证书 + FileWriter writer = new FileWriter(certPath); + writer.write(publicKey); + // 获取平台证书序列号 + X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes())); + return certificate.getSerialNumber().toString(16).toUpperCase(); + } + return ""; + } catch (Exception e) { + log.error("保存平台证书异常", e); + return e.getMessage(); + } + } + + + /** + * 公共方法,构建订单关闭时间,默认3分钟 + * @return + */ + private String getNowTimeExpire() { + long currentTimeMillis = System.currentTimeMillis() + 1000 * 60 * 3; + // 将时间戳转换为 DateTime 对象 + DateTime dateTime = DateUtil.date(currentTimeMillis); + return DateUtil.format(dateTime, "yyyy-MM-dd'T'HH:mm:ssXXX"); + } + + + /** + * 公共方法,插入交易订单 + * @param paramVo 交易必填参数Vo + * @param outTradeNo 商户交易号 + * @param result 下单返回结构 + */ + private void insertTradingOrder(WxPayNeedParamVo paramVo, String outTradeNo, String result){ + View_user user = sysUserService.dao().fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId())); + PaymentTransaction transaction = new PaymentTransaction(); + transaction.setId(R.UU32()); + transaction.setMchId(WX_PAY_V3_BEAN.getMchId()); + transaction.setOutTradeNo(outTradeNo); + transaction.setTransactionId(null); + transaction.setTradingChannel(TradingChannelEnum.WX_PAY.name()); + transaction.setTradingType(TradingTypeEnum.PAYMENT.name()); + transaction.setUserId(user.getId()); + transaction.setLoginName(user.getLoginname()); + transaction.setUserName(user.getUsername()); + transaction.setUnitId(user.getUnitId()); + transaction.setUnitName(user.getUnitName()); + transaction.setUnionId(user.getUnionId()); + transaction.setUnionName(user.getUnionName()); + transaction.setTradingState(TradingStateEnum.WAITING_FOR_PAYMENT.name()); + // 获取订单金额 + transaction.setTradingAmount(paramVo.getAmount().getTotal()); + transaction.setIsRefund(false); + transaction.setRefundAmount(null); + transaction.setDescription(paramVo.getDescription()); + transaction.setAttach(paramVo.getAttach()); + transaction.setOpenId(null); + transaction.setResultJson(result); + transaction.setMemberPaymentInfoId(paramVo.getMemberPaymentInfoId()); + sysUserService.dao().insert(transaction); + } +} diff --git a/src/main/java/com/budwk/app/base/payment/wxpay/util/WeChatUtils.java b/src/main/java/com/budwk/app/base/payment/wxpay/util/WeChatUtils.java new file mode 100644 index 00000000..2137a285 --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/wxpay/util/WeChatUtils.java @@ -0,0 +1,132 @@ +package com.budwk.app.base.payment.wxpay.util; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.constant.RedisConstant; +import lombok.extern.slf4j.Slf4j; +import org.nutz.http.Http; +import org.nutz.integration.jedis.RedisService; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.json.Json; +import org.nutz.lang.util.NutMap; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.net.URLEncoder; +import java.util.Base64; + +/** + * @version 1.0 + * @Author zzr + * @name:WeChatUtils + * @Date 2025/3/10 14:13 + * @注释 + */ +@Slf4j +@IocBean +public class WeChatUtils { + + private static final String ALGORITHM = "AES"; + private static final String KEY = "4eXvXq1ZJmZj8z5z6yXvXq1ZJmZj8z5z"; + + @Inject + private RedisService redisService; + + public static final String APPID = "wxf12fa6175ec7c75f"; + + public static final String SECRET = "f65bbb41d3de4a93c8c93d8e2fd50369"; + + // 获取code + public final static String CODE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"; + + //获取网页access_token的接口地址 + public final static String WEB_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=APPSECRET&code=CODE&grant_type=authorization_code"; + + + //获取用户信息地址 + public final static String USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN"; + + // 获取access_token的接口地址(GET) 限2000(次/天) + public final static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; + // 发送模板消息 + public static final String SEND_MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN"; + + + /** + * 生成获取code的url + * + * @param redirectUrl + * @return + */ + public String getCodeUrl(String redirectUrl, String state) { + String requestUrl = null; + state = state == null ? "" : state; + try { + requestUrl = CODE_URL.replace("APPID", APPID).replace("REDIRECT_URI", URLEncoder.encode(redirectUrl, "UTF-8")).replace("STATE", state); + } catch (Exception e) { + e.printStackTrace(); + } + return requestUrl; + } + + /** + * 获取微信网页access_token 和 openid + * + * @param code + * @return + */ + public JSONObject getWebAccessTokenAndOpenid(String code) { + String requestUrl = WEB_ACCESS_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", SECRET).replace("CODE", code); + return JSONUtil.parseObj(HttpUtil.post(requestUrl, new JSONObject())); + } + + /** + * 网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息了 + * ... + * + * @param webAccessToken + * @param openid + * @return + */ + public JSONObject getUserInfo(String webAccessToken, String openid) { + String requestUrl = USERINFO_URL.replace("ACCESS_TOKEN", webAccessToken).replace("OPENID", openid); + return JSONUtil.parseObj(HttpUtil.post(requestUrl, new JSONObject())); + } + + /** + * 获取access_token 先从Redis获取,如果没有再调微信获取并存Redis + * + * @return + */ + public String getAccessToken() { + String token = redisService.get(RedisConstant.REDIS_KEY_WX_TOKEN); + if (StrUtil.isNotBlank(token)) { + return token; + } + String accessTokenUrl = ACCESS_TOKEN_URL.formatted(APPID, SECRET); + String accessToken = Json.fromJson(NutMap.class, Http.get(accessTokenUrl).getContent()).getString("access_token"); + redisService.setex(RedisConstant.REDIS_KEY_WX_TOKEN, 60 * 60 * 2, accessToken); + return accessToken; + } + + + public String encrypt(String data) throws Exception { + SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), ALGORITHM); + Cipher cipher = Cipher.getInstance(ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, keySpec); + byte[] encryptedBytes = cipher.doFinal(data.getBytes()); + return Base64.getEncoder().encodeToString(encryptedBytes); + } + + public String decrypt(String encryptedData) throws Exception { + SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), ALGORITHM); + Cipher cipher = Cipher.getInstance(ALGORITHM); + cipher.init(Cipher.DECRYPT_MODE, keySpec); + byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedData)); + return new String(decryptedBytes); + } + +} diff --git a/src/main/java/com/budwk/app/base/payment/wxpay/vo/WxPayNeedParamVo.java b/src/main/java/com/budwk/app/base/payment/wxpay/vo/WxPayNeedParamVo.java new file mode 100644 index 00000000..5131aa6d --- /dev/null +++ b/src/main/java/com/budwk/app/base/payment/wxpay/vo/WxPayNeedParamVo.java @@ -0,0 +1,37 @@ +package com.budwk.app.base.payment.wxpay.vo; + +import com.ijpay.wxpay.model.v3.Amount; +import com.ijpay.wxpay.model.v3.Payer; +import lombok.Data; + +/** + * @version 1.0 + * @Author zzr + * @name:WxPayNeedParamVo + * @Date 2025/3/7 18:43 + * @注释 + */ +@Data +public class WxPayNeedParamVo { + + /** + * 订单描述,会显示在支付界面的标题,最大长度127,必填 + */ + private String description; + + /** + * 附加数据,订单的详细描述信息,不必填 + */ + private String attach; + + /** + * 金额对象,对象中的 total 是金额,必填; + * 其余参数可不传递也可不填 + */ + private Amount amount; + + /** + * 会员支付信息ID,必填 + */ + private String memberPaymentInfoId; +} diff --git a/src/main/java/com/budwk/app/sys/models/Sys_user_history.java b/src/main/java/com/budwk/app/sys/models/Sys_user_history.java index f82977df..f0b60c5e 100644 --- a/src/main/java/com/budwk/app/sys/models/Sys_user_history.java +++ b/src/main/java/com/budwk/app/sys/models/Sys_user_history.java @@ -1,196 +1,61 @@ package com.budwk.app.sys.models; -import cn.hutool.json.JSONObject; -import com.budwk.app.base.model.BaseModel; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; import org.nutz.dao.entity.annotation.*; import org.nutz.dao.interceptor.annotation.PrevInsert; import org.nutz.lang.util.NutMap; -import java.io.Serializable; import java.util.Date; import java.util.List; @Data +@Accessors(chain = true) @EqualsAndHashCode(callSuper = true) @Table("sys_user_history") @TableMeta("{'mysql-charset':'utf8mb4'}") -@TableIndexes({@Index(name = "INDEX_SYS_USER_HISTORY_LOGINNAMAE", fields = {"loginname"}, unique = false)}) +@TableIndexes({ + @Index(name = "INDEX_HISTORY_USER_LOGINNAMAE", fields = {"loginname"}, unique = false), + @Index(name = "INDEX_HISTORY_USER_UNIT", fields = {"unitId"}, unique = false), +}) @Comment("用户历史记录") -public class Sys_user_history extends BaseModel implements Serializable { - +public class Sys_user_history extends Sys_user { @Name + @Column @Comment("ID") - @ColDefine(type = ColType.VARCHAR, width = 32) @PrevInsert(uu32 = true) + @ColDefine(type = ColType.VARCHAR, width = 32) private String id; @Column - @Comment("用户名") - @ColDefine(type = ColType.VARCHAR, width = 120) - private String loginname; + @Comment("更新时间") + @ColDefine(type = ColType.DATETIME) + private Date changeTime; + /** + * @see com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType + */ @Column - @Comment("姓名") - @ColDefine(type = ColType.VARCHAR, width = 100) - private String username; - - @Column - @Comment("性别") - @ColDefine(type = ColType.VARCHAR, width = 20) - private String sex; - - @Column - @Comment("电子邮箱") - @ColDefine(type = ColType.VARCHAR, width = 255) - private String email; - - @Column - @Comment("手机号码") - @ColDefine(type = ColType.VARCHAR, width = 32) - private String mobile; - - @Column - @Comment("工会ID") - @ColDefine(type = ColType.VARCHAR, width = 32) - private String unionId; - - @Column - @Comment("工会名称") - @ColDefine(type = ColType.VARCHAR, width = 200) - private String unionName; - - @Column - @Comment("单位ID") - @ColDefine(type = ColType.VARCHAR, width = 32) - private String unitId; - - @Column - @Comment("单位名称") - @ColDefine(type = ColType.VARCHAR, width = 200) - private String unitName; - - @Column - @Comment("在职状态") - @ColDefine(type = ColType.VARCHAR, width = 20) - private String userState; - - @Column - @Comment("人事编制") - @ColDefine(type = ColType.VARCHAR, width = 30) - private String preparedBy; - - @Column - @Comment("人员类型") - @ColDefine(type = ColType.VARCHAR, width = 20) - private String personType; - - @Column - @Comment("来校年月") - @ColDefine(type = ColType.VARCHAR, width = 30) - private String comeSchoolDate; - - @Column - @Comment("出生日期") - @ColDefine(type = ColType.DATE) - private Date birthday; - - @Column - @Comment("党政职务") - @ColDefine(type = ColType.VARCHAR, width = 50) - private String governmentPosition; - - @Column - @Comment("技术职称") - @ColDefine(type = ColType.VARCHAR, width = 30) - private String technicalTitle; - - @Column - @Comment("民族") - @ColDefine(type = ColType.VARCHAR, width = 15) - private String nation; - - @Column - @Comment("国籍") - @ColDefine(type = ColType.VARCHAR, width = 30) - private String nationality; - - @Column - @Comment("证件类型") - @ColDefine(type = ColType.VARCHAR, width = 30) - private String icCardType; - - @Column - @Comment("证件号码") - @ColDefine(type = ColType.VARCHAR, width = 30) - private String idCard; - - @Column - @Comment("政治面貌") - @ColDefine(type = ColType.VARCHAR, width = 20) - private String political; - - @Column - @Comment("学历") - @ColDefine(type = ColType.VARCHAR, width = 50) - private String education; - - @Column - @Comment("学位") - @ColDefine(type = ColType.VARCHAR, width = 50) - private String academicDegree; - - @Column - @Comment("个人简况") - @ColDefine(type = ColType.VARCHAR, customType = "text") - private String personalData; - - @Column - @Comment("是否双肩挑") - @ColDefine(type = ColType.BOOLEAN) - private Boolean manyUnit; - - @Column - @Comment("是否会员") - @ColDefine(type = ColType.AUTO) - private Boolean member; - - @Column - @Comment("是否愿意加入重大疾病爱心基金互助会") - @ColDefine(type = ColType.BOOLEAN) - private Boolean wantJoinLoveMutualAidAssociation; - - @Column - @Comment("是否福利会员") - @ColDefine(type = ColType.AUTO) - private Boolean welfareMember; - - @Column - @Comment("异动类型") + @Comment("变更类型(多种)") @ColDefine(type = ColType.MYSQL_JSON) private List changeTypes; @Column - @Comment("家庭成员") - @ColDefine(type = ColType.MYSQL_JSON) - private List families; - - @Column - @Comment("博士后进站时间") - @ColDefine(type = ColType.DATE) - private Date postDoctoralJoinDate; - - @Column - @Comment("异动时间") - @ColDefine(type = ColType.DATETIME) - private Date changeTime; - - @Column - @Comment("异动来源") - @ColDefine(type = ColType.VARCHAR, width = 20) + @Comment("变更来源") + @ColDefine(type = ColType.VARCHAR, width = 50) private String changeOrigin; + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("变更原因") + private String changeReason; + + @Column + @Comment("会员变更表记录id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String recordId; + @Column @Comment("详细变更记录,用于查询、列表展示") @ColDefine(type = ColType.MYSQL_JSON) @@ -200,19 +65,4 @@ public class Sys_user_history extends BaseModel implements Serializable { @Comment("详细变更记录,文本类型,可用于导出") @ColDefine(type = ColType.TEXT) private String changeInfosStr; - - @Column - @Comment("变更原因") - @ColDefine(type = ColType.VARCHAR, width = 100) - private String changeReason; - - @Column - @Comment("会员变更记录表") - @ColDefine(type = ColType.VARCHAR, width = 32) - private String recordId; - - @Column - @Comment("变更说明") - @ColDefine(type = ColType.TEXT) - private String remark; } diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java index 256dc7c0..09d26758 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java @@ -1,23 +1,13 @@ package com.budwk.app.sys.services.impl; -import cn.afterturn.easypoi.excel.ExcelImportUtil; -import cn.afterturn.easypoi.excel.entity.ImportParams; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.convert.Convert; import cn.hutool.core.date.DateField; -import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; -import cn.hutool.core.thread.AsyncUtil; -import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; import cn.hutool.http.HtmlUtil; import com.budwk.app.base.constant.RoleConstant; -import com.budwk.app.base.event.user.SysUserEvent; -import com.budwk.app.base.event.user.SysUserPublisher; import com.budwk.app.base.utils.ConditionGroupUtil; -import com.budwk.app.base.utils.ManyAddOrRenewUtil; import com.budwk.app.base.utils.PwdUtil; import com.budwk.app.sys.annotation.DataCenterColumn; import com.budwk.app.sys.models.*; @@ -28,33 +18,23 @@ import com.budwk.app.sys.services.SysRoleService; import com.budwk.app.sys.services.SysUserService; import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin; import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType; -import com.budwk.app.zhgh.staffmanage.member.service.MemberManageService; -import com.budwk.app.zhgh.staffmanage.specialstaff.model.SpecialStaff; import lombok.extern.slf4j.Slf4j; import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.dao.Chain; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; -import org.nutz.dao.Sqls; -import org.nutz.dao.sql.Sql; -import org.nutz.dao.util.cri.SqlExpressionGroup; import org.nutz.ioc.aop.Aop; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.lang.Lang; import org.nutz.lang.random.R; import org.nutz.lang.util.NutMap; -import org.nutz.mvc.Mvcs; import org.springframework.beans.BeanUtils; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import java.io.File; import java.lang.reflect.Field; import java.util.*; import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; /** diff --git a/src/main/java/com/budwk/app/sys/views/View_user.java b/src/main/java/com/budwk/app/sys/views/View_user.java index f1570a5e..5f11ec3a 100644 --- a/src/main/java/com/budwk/app/sys/views/View_user.java +++ b/src/main/java/com/budwk/app/sys/views/View_user.java @@ -170,4 +170,8 @@ public class View_user { @Column private Date postDoctoralJoinDate; + + // 福利享受截止日期 + @Column + private Date welfareStopDate; } diff --git a/src/main/java/com/budwk/app/task/services/TaskPlatformService.java b/src/main/java/com/budwk/app/task/services/TaskPlatformService.java index 2ce4dd75..9a05533a 100644 --- a/src/main/java/com/budwk/app/task/services/TaskPlatformService.java +++ b/src/main/java/com/budwk/app/task/services/TaskPlatformService.java @@ -48,4 +48,6 @@ public interface TaskPlatformService { * @return */ List getCronExeTimes(String cronExpression) throws Exception; + + List getCronExeTimesPlus(String cronExpression) throws Exception; } diff --git a/src/main/java/com/budwk/app/task/services/impl/TaskPlatformServiceImpl.java b/src/main/java/com/budwk/app/task/services/impl/TaskPlatformServiceImpl.java index 9330d53b..d1baedaa 100644 --- a/src/main/java/com/budwk/app/task/services/impl/TaskPlatformServiceImpl.java +++ b/src/main/java/com/budwk/app/task/services/impl/TaskPlatformServiceImpl.java @@ -5,6 +5,7 @@ import org.nutz.integration.quartz.QuartzJob; import org.nutz.integration.quartz.QuartzManager; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; +import org.quartz.CronExpression; import org.quartz.JobKey; import org.quartz.TriggerUtils; import org.quartz.impl.triggers.CronTriggerImpl; @@ -96,4 +97,22 @@ public class TaskPlatformServiceImpl implements TaskPlatformService { } return list; } + + + @Override + public List getCronExeTimesPlus(String cronExpression) throws Exception { + // 创建一个列表来存储执行时间 + List executionTimes = new ArrayList<>(); + // 创建 CronTriggerImpl 对象,并设置 cron 表达式 + CronTriggerImpl cronTrigger = new CronTriggerImpl(); + cronTrigger.setCronExpression(new CronExpression(cronExpression)); + // 计算未来的执行时间 + List nextExecutionTimes = TriggerUtils.computeFireTimes(cronTrigger, null, 5); + // 格式化日期并添加到执行时间列表中 + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + for (Date date : nextExecutionTimes) { + executionTimes.add(dateFormat.format(date)); + } + return executionTimes; + } } diff --git a/src/main/java/com/budwk/app/web/commons/base/Globals.java b/src/main/java/com/budwk/app/web/commons/base/Globals.java index bf67c7b4..02dbf1fd 100644 --- a/src/main/java/com/budwk/app/web/commons/base/Globals.java +++ b/src/main/java/com/budwk/app/web/commons/base/Globals.java @@ -37,6 +37,8 @@ public class Globals { public static String AppDomain = "http://127.0.0.1"; //文件访问域名 public static String AppFileDomain = ""; + //学校代码 + public static String SchoolCode = "HMC"; //系统自定义参数 public static NutMap MyConfig = NutMap.NEW(); //自定义路由 diff --git a/src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/declare/controller/ActivityDeclareApplyController.java b/src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/declare/controller/ActivityDeclareApplyController.java new file mode 100644 index 00000000..535d886d --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/declare/controller/ActivityDeclareApplyController.java @@ -0,0 +1,11 @@ +package com.budwk.app.zhgh.activity.declarereimbursement.declare.controller; + +/** + * @version 1.0 + * @Author zzr + * @name:ActivityDeclareApplyController + * @Date 2025/7/31 15:46 + * @注释 + */ +public class ActivityDeclareApplyController { +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/declare/models/ActivityDeclareInfo.java b/src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/declare/models/ActivityDeclareInfo.java new file mode 100644 index 00000000..7aac3faa --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/declare/models/ActivityDeclareInfo.java @@ -0,0 +1,18 @@ +package com.budwk.app.zhgh.activity.declarereimbursement.declare.models; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.Table; + +/** + * @version 1.0 + * @Author zzr + * @name:ActivityDeclareInfo + * @Date 2025/7/31 15:38 + * @注释 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ActivityDeclareInfo extends BaseModel { +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/reimbursement/controller/ActivityReimbursementApplyController.java b/src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/reimbursement/controller/ActivityReimbursementApplyController.java new file mode 100644 index 00000000..b36571e5 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/reimbursement/controller/ActivityReimbursementApplyController.java @@ -0,0 +1,11 @@ +package com.budwk.app.zhgh.activity.declarereimbursement.reimbursement.controller; + +/** + * @version 1.0 + * @Author zzr + * @name:ActivityReimbursementApplyController + * @Date 2025/7/31 15:47 + * @注释 + */ +public class ActivityReimbursementApplyController { +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/reimbursement/models/ActivityReimbursementInfo.java b/src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/reimbursement/models/ActivityReimbursementInfo.java new file mode 100644 index 00000000..bfed79bb --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/declarereimbursement/reimbursement/models/ActivityReimbursementInfo.java @@ -0,0 +1,18 @@ +package com.budwk.app.zhgh.activity.declarereimbursement.reimbursement.models; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.Table; + +/** + * @version 1.0 + * @Author zzr + * @name:ActivityReimbursement + * @Date 2025/7/31 15:43 + * @注释 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ActivityReimbursementInfo extends BaseModel { +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/contants/Cascader.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/contants/Cascader.java new file mode 100644 index 00000000..2e22f541 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/contants/Cascader.java @@ -0,0 +1,16 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.contants; + +import lombok.Data; + +import java.util.List; + +/** + * 获取活动的树形结构 + */ +@Data +public class Cascader { + + private String value; + private String label; + private List children; +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/contants/FitnessWalkMode.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/contants/FitnessWalkMode.java new file mode 100644 index 00000000..ad699815 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/contants/FitnessWalkMode.java @@ -0,0 +1,18 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.contants; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum FitnessWalkMode { + + PUNCH("punch", "打卡"), + STEP_COUNT("stepCount", "计步"), + GPS("gps", "GPS"); + + + private final String value; + private final String desc; + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkActivityBindingRecordController.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkActivityBindingRecordController.java new file mode 100644 index 00000000..8bb51c65 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkActivityBindingRecordController.java @@ -0,0 +1,133 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.fitnesswalk.utils.WeAppCloudUtil; +import io.swagger.annotations.ApiOperation; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.json.Json; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +@IocBean +@Ok("json") +@ApiOperation("健步走-同步绑定记录") +@At("/platform/fitnessWalk/bindingRecord") +public class FitnessWalkActivityBindingRecordController { + + @Inject + private WeAppCloudUtil weAppCloudUtil; + + @At("") + @Ok("beetl:/platform/zhgh/activity/fitnesswalk/bindingRecord.html") + @SaCheckPermission("fitnessWalk.bindingRecord") + public void index() { + } + + /** + * 获取用户绑定记录 + * @param keyWord + * @param unionId + * @param searchName + * @param searchKeyword + * @param pageNumber + * @param pageSize + * @param pageOrderName + * @param pageOrderBy + * @return + * @throws IOException + */ + @At + @ApiOperation("获取用户绑定记录") + @SaCheckPermission("fitnessWalk.bindingRecord") + public Result pageData(@Param("keyWord") String keyWord, + @Param("unionId") String unionId, + @Param("searchName") String searchName, + @Param("searchKeyword") String searchKeyword, + @Param("pageNumber") int pageNumber, @Param("pageSize") int pageSize, + @Param("pageOrderName") String pageOrderName, + @Param("pageOrderBy") String pageOrderBy) { + int skip = (pageNumber == 1 ? 0 : (pageNumber - 1)) * pageSize; + + StringBuilder sql = new StringBuilder("db.collection('login_record')"); + if (StrUtil.isNotBlank(keyWord)) { + sql.append(".where("); + sql.append("_.or(["); + sql.append("{loginname:{$regex:'").append(keyWord).append("',$options:'i'}},"); + sql.append("{username:{$regex:'").append(keyWord).append("',$options:'i'}}"); + sql.append("])"); + sql.append(")"); + } + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + sql.append(".where({'data.unionid':'").append(SecurityUtil.getUnionId()).append("'})"); + } else { + if (Strings.isNotBlank(unionId)) { + sql.append(".where({'data.unionid':'").append(unionId).append("'})"); + } + } + sql.append(".field({ data: false })"); + sql.append(".skip(").append(skip).append(")"); + sql.append(".limit(").append(pageSize).append(")"); + sql.append(".get()"); + + try { + JSONObject jsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.QUERY, sql.toString()); + List data = jsonObject.getJSONArray("data").stream() + .map(v -> JSONUtil.toBean((String) v, NutMap.class)) + .collect(Collectors.toList()); + JSONObject pager = jsonObject.getJSONObject("pager"); + Pagination pagination = new Pagination(pageNumber, pageSize, pager.getInt("Total"), data); + return Result.success().addData(pagination); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + + /** + * 删除绑定记录 + * @param ids + * @return + */ + @At + @ApiOperation("删除绑定记录") + @SLog(tag = "健步走-同步绑定记录", msg = "删除绑定记录") + @SaCheckPermission("fitnessWalk.bindingRecord") + public Result delete(String[] ids) { + String sql = "db.collection('login_record').where({_id:_.in(" + Json.toJson(ids) + ")}).remove()"; + weAppCloudUtil.request(WeAppCloudUtil.CRUD.DELETE, sql); + return Result.success(); + } + + /** + * 删除所有绑定记录 + * @return + */ + @At + @ApiOperation("删除所有绑定记录") + @SLog(tag = "健步走-同步绑定记录", msg = "删除所有绑定记录") + @SaCheckPermission("fitnessWalk.bindingRecord") + public Result deleteAll() { + String sql = "db.collection('login_record').where({_id: _.neq('0')}).remove()"; + weAppCloudUtil.request(WeAppCloudUtil.CRUD.DELETE, sql); + return Result.success(); + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkActivityManageController.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkActivityManageController.java new file mode 100644 index 00000000..81a3cd25 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkActivityManageController.java @@ -0,0 +1,337 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_task; +import com.budwk.app.sys.services.SysTaskService; +import com.budwk.app.sys.services.SysUserService; +import com.budwk.app.task.services.TaskPlatformService; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkActivity; +import com.budwk.app.zhgh.activity.fitnesswalk.service.FitnessWalkCommonService; +import com.budwk.app.zhgh.activity.fitnesswalk.utils.WeAppCloudUtil; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Cnd; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.json.Json; +import org.nutz.lang.Lang; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.AdaptBy; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; +import org.nutz.mvc.upload.TempFile; +import org.nutz.mvc.upload.UploadAdaptor; + +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; + + +@IocBean +@Ok("json") +@ApiOperation("健步走-活动管理") +@At("/platform/fitnessWalk/activityManage") +public class FitnessWalkActivityManageController { + @Inject + private WeAppCloudUtil weAppCloudUtil; + @Inject + private SysTaskService sysTaskService; + @Inject + private SysUserService sysUserService; + @Inject + private TaskPlatformService taskPlatformService; + @Inject + private FitnessWalkCommonService fitnessWalkCommonService; + + @At("") + @Ok("beetl:/platform/zhgh/activity/fitnesswalk/activityManage.html") + @SaCheckPermission("fitnessWalk.activityManage") + public void index() { + } + + @At + @ApiOperation("获取活动数据") + @SaCheckPermission("fitnessWalk.activityManage") + public Result pageData(@Param("year") Integer year, @Param("unionId") String unionId, @Param("searchName") String searchName, + @Param("searchKeyword") String searchKeyword, @Param("pageNumber") int pageNumber, + @Param("pageSize") int pageSize, @Param("pageOrderName") String pageOrderName, + @Param("pageOrderBy") String pageOrderBy) { + + int skip = (pageNumber == 1 ? 0 : (pageNumber - 1)) * pageSize; + + StringBuilder sql = new StringBuilder("db.collection('activity')"); + if (Strings.isNotBlank(searchName) && Strings.isNotBlank(searchKeyword)) { + sql.append("where("); + sql.append("_.or(["); + sql.append("{name:{$regex:'").append(searchKeyword).append("',$options:'i'}}"); + sql.append("{tag:{$regex:'").append(searchKeyword).append("',$options:'i'}}"); + sql.append("])"); + sql.append(")"); + } + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + sql.append(".where({unionId:'").append(SecurityUtil.getUnionId()).append("'})"); + } else if (StrUtil.isNotBlank(unionId)) { + sql.append(".where({unionId:'").append(unionId).append("'})"); + } + sql.append(".skip(").append(skip).append(")"); + sql.append(".limit(").append(pageSize).append(")"); + sql.append(".get()"); + try { + JSONObject jsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.QUERY, sql.toString()); + List data = jsonObject.getJSONArray("data").stream() + .map(v -> JSONUtil.toBean((String) v, FitnessWalkActivity.class)) + .collect(Collectors.toList()); + JSONObject pager = jsonObject.getJSONObject("pager"); + Pagination pagination = new Pagination(pageNumber, pageSize, pager.getInt("Total"), data); + return Result.success().addData(pagination); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + + } + + + @At + @ApiOperation("添加活动") + @SLog(tag = "健步走-活动管理", msg = "添加活动") + @SaCheckPermission("fitnessWalk.activityManage") + @AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"}) + public Result doAdd(@Param("fitnessWalkActivity") FitnessWalkActivity fitnessWalkActivity, + @Param("file") TempFile tempFile, + @Param("stepFiles") TempFile[] stepFiles, + @Param("certificateFile") TempFile certificateTempFile) { + try { + //设置时间 + if ("punch".equals(fitnessWalkActivity.getActivityModel())) { + fitnessWalkActivity.setApplyStartTime(fitnessWalkActivity.getApplyTime()[0]); + fitnessWalkActivity.setApplyEndTime(fitnessWalkActivity.getApplyTime()[1]); + } + fitnessWalkActivity.setStartTime(fitnessWalkActivity.getTime()[0]); + fitnessWalkActivity.setEndTime(fitnessWalkActivity.getTime()[1]); + + if (tempFile != null) { + String fileId = weAppCloudUtil.uploadFile("activity/", tempFile.getFile()); + fitnessWalkActivity.setCover(fileId); + } + + if (Lang.isNotEmpty(stepFiles)) { + List stepFileIdList = new ArrayList<>(); + for (TempFile file : stepFiles) { + String fileId = weAppCloudUtil.uploadFile("activity/", file.getFile()); + stepFileIdList.add(fileId); + } + fitnessWalkActivity.setRandomPics(stepFileIdList); + } + + if (certificateTempFile != null) { + String fileId = weAppCloudUtil.uploadFile("activity/", certificateTempFile.getFile()); + fitnessWalkActivity.setCompletionCertificateCover(fileId); + } + + if (AuthUtil.hasRoleOr(RoleConstant.BRANCH_UNION_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_OPERATOR.name(), RoleConstant.BRANCH_UNION_ADMIN.name()) + && !AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + fitnessWalkActivity.setUnionId(SecurityUtil.getUnionId()); + } else { + fitnessWalkActivity.setUnionId(""); + } + + fitnessWalkActivity.setNote(fitnessWalkActivity.getNote().replace("\"", "'")); + StringBuilder sql = new StringBuilder(); + sql.append("db.collection('activity').add({data:").append(Json.toJson(fitnessWalkActivity)).append("})"); + + try { + JSONObject jsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.INSERT, sql.toString()); + fitnessWalkCommonService.addLotteryTask(fitnessWalkActivity); + fitnessWalkCommonService.addOrEditDoSaveRedis(fitnessWalkActivity); + return Result.success(); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } catch (Exception e) { + e.printStackTrace(); + return Result.error(); + } + } + + + @At + @Ok("json:full") + @ApiOperation("根据Id获取健步走活动") + @SaCheckPermission("fitnessWalk.activityManage") + public Result findOne(String id) { + return Result.success(fitnessWalkCommonService.getActivity(id)); + } + + @At + @Ok("json") + @ApiOperation("获取附件") + @SaCheckPermission("fitnessWalk.activityManage") + public Result getFile(String pic) { + try { + NutMap res = NutMap.NEW(); + String imgurl = weAppCloudUtil.httpFile(pic); + HashMap imgmap = new HashMap<>(); + imgmap.put("status", "success"); + imgmap.put("name", imgurl.substring(imgurl.lastIndexOf("/") + 1)); + imgmap.put("id", imgurl); + imgmap.put("url", imgurl); + res.setv("img", imgmap); + return Result.success().addData(res); + } catch (Exception e) { + return Result.error(); + } + } + + + @At + @ApiOperation("修改健步走活动") + @SaCheckPermission("fitnessWalk.activityManage") + @AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"}) + public Result doEdit(@Param("fitnessWalkActivity") FitnessWalkActivity fitnessWalkActivity, + @Param("file") TempFile tempFile, + @Param("stepFiles") TempFile[] stepFiles, + @Param("certificateFile") TempFile certificateTempFile) { + //设置时间 + if ("punch".equals(fitnessWalkActivity.getActivityModel())) { + fitnessWalkActivity.setApplyStartTime(fitnessWalkActivity.getApplyTime()[0]); + fitnessWalkActivity.setApplyEndTime(fitnessWalkActivity.getApplyTime()[1]); + } + fitnessWalkActivity.setStartTime(fitnessWalkActivity.getTime()[0]); + fitnessWalkActivity.setEndTime(fitnessWalkActivity.getTime()[1]); + + if (tempFile != null) { + String fileId = weAppCloudUtil.uploadFile("activity/", tempFile.getFile()); + fitnessWalkActivity.setCover(fileId); + } + + if (Lang.isNotEmpty(stepFiles)) { + List stepFileIdList = new ArrayList<>(); + for (TempFile file : stepFiles) { + String fileId = weAppCloudUtil.uploadFile("activity/", file.getFile()); + stepFileIdList.add(fileId); + } + fitnessWalkActivity.setRandomPics(stepFileIdList); + } + + if (certificateTempFile != null) { + String fileId = weAppCloudUtil.uploadFile("activity/", certificateTempFile.getFile()); + fitnessWalkActivity.setCompletionCertificateCover(fileId); + } + + + if (AuthUtil.hasRoleOr(RoleConstant.BRANCH_UNION_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_OPERATOR.name(), RoleConstant.BRANCH_UNION_ADMIN.name()) + && !AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + fitnessWalkActivity.setUnionId(SecurityUtil.getUnionId()); + } else { + fitnessWalkActivity.setUnionId(""); + } + + fitnessWalkActivity.setNote(fitnessWalkActivity.getNote().replace("\"", "'")); + + StringBuilder sql = new StringBuilder(); + sql.append("db.collection('activity').doc('") + .append(fitnessWalkActivity.get_id()) + .append("').update({data:").append(Json.toJson(fitnessWalkActivity)).append("})"); + + try { + JSONObject jsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.UPDATE, sql.toString()); + fitnessWalkCommonService.addLotteryTask(fitnessWalkActivity); + fitnessWalkCommonService.addOrEditDoSaveRedis(fitnessWalkActivity); + return Result.success(); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + + @At + @ApiOperation("删除健步走活动") + @SLog(tag = "健步走-活动管理", msg = "删除活动") + @SaCheckPermission("fitnessWalk.activityManage") + public Result delete(String id) { + try { + weAppCloudUtil.request(WeAppCloudUtil.CRUD.DELETE, "db.collection('activity').doc('" + id + "').remove()"); + weAppCloudUtil.request(WeAppCloudUtil.CRUD.DELETE, "db.collection('register').where({activity_id:'" + id + "'}).remove()"); + weAppCloudUtil.request(WeAppCloudUtil.CRUD.DELETE, "db.collection('sign').where({activity_id:'" + id + "'}).remove()"); + weAppCloudUtil.request(WeAppCloudUtil.CRUD.DELETE, "db.collection('gift_voucher').where({activity_id:'" + id + "'}).remove()"); + + List sys_tasks = sysTaskService.query(Cnd.where("note", "=", id)); + if (sys_tasks != null) { + sys_tasks.forEach(v -> { + taskPlatformService.delete(v.getId(), v.getId()); + sysTaskService.delete(v.getId()); + }); + + } + return Result.success(); + } catch (Exception e) { + return Result.error(); + } + } + + /** + * 健身走健步模式通知提醒 + * + * @param map + */ + private void addNotifyTask(NutMap map) { + if (map.getBoolean("sendNotify")) { + String id = map.getString("_id"); + String name = map.getString("name"); + String groupId = map.getString("groupId"); + + //提醒频率 + int notifyGap = 10; + + List sys_tasks = sysTaskService.query(Cnd.where("note", "=", id)); + if (Lang.isNotEmpty(sys_tasks)) { + sys_tasks.forEach(v -> { + taskPlatformService.delete(v.getId(), v.getId()); + sysTaskService.delete(v.getId()); + }); + } + + DateTime startTime = DateUtil.date(map.getLong("start_time")); + DateTime endTime = DateUtil.date(map.getLong("end_time")); + + Set result = new HashSet<>(); + DateTime offsetDay = DateUtil.offsetDay(startTime, notifyGap); + while (offsetDay.isBefore(endTime) && offsetDay.isAfter(new Date())) { + result.add(offsetDay); + offsetDay = DateUtil.offsetDay(offsetDay, notifyGap); + } + //活动结束前一天再添加一个日期提醒 + result.add(DateUtil.offsetDay(endTime, -1)); + + for (DateTime dateTime : result) { + Sys_task sys_task = new Sys_task(); + sys_task.setName(name); + sys_task.setNote(id); + sys_task.setJobClass("io.v.nutz.task.job.walking.WalkingNotifyJob"); + sys_task.setData(Json.toJson(Map.of("groupId", groupId))); + sys_task.setDisabled(false); + + String dateFormat = "ss mm HH dd MM ? yyyy"; + SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); + String corn = sdf.format(dateTime); + sys_task.setCron(corn); + + sysTaskService.insert(sys_task); + + taskPlatformService.add(sys_task.getId(), sys_task.getId(), sys_task.getJobClass(), sys_task.getCron(), sys_task.getNote(), sys_task.getData()); + } + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkCommonController.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkCommonController.java new file mode 100644 index 00000000..ae74afdf --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkCommonController.java @@ -0,0 +1,52 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.controller; + +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * 健身走公共答题 + */ +@IocBean +@At("/platform/fitnessWalk/common") +@Ok("json:full") +public class FitnessWalkCommonController { + +// @Inject +// private QuestionService questionService; +// +// @Inject +// private QuestionIssueService questionIssueService; +// +// @Inject +// private QuestionWorService questionWorService; +// +// @Inject +// private QuestionReplyService questionReplyService; +// +// @At +// public Object getQuestion() { +// return questionService.query(Cnd.where("qflag", "=", 2)); +// } +// +// @At +// public Object getIssueById(String id) { +// List questionIssues = questionIssueService.query(Cnd.where("iqid", "=", id).asc("ipxbh")); +// questionIssues.forEach(issue -> { +// issue.setWors(questionWorService.query(Cnd.where("wiid", "=", issue.getIid()).asc("wpxbh"))); +// }); +// return questionIssues; +// } +// +// @At +// public Object saveAnswer(@Param("reply") Question_reply[] replys) { +// for (Question_reply reply : replys) { +// reply.setSave(false); +// reply.setRidentity(R.UU32()); +// reply.setRtime(DateUtil.getDate()); +// questionReplyService.insert(reply); +// } +// return null; +// } + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkLoginController.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkLoginController.java new file mode 100644 index 00000000..0aa14a13 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkLoginController.java @@ -0,0 +1,75 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.controller; + +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.services.SysUserService; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @author: Aaron + * @create: 2020-09-11 13:50 + * @description: 小程序登录 + **/ +@At("/platform/fitnessWalk/login") +@Ok("json:full") +@IocBean +public class FitnessWalkLoginController { + + @Inject + private SysUserService sysUserService; + + @At("/") + public Object index(String username, String loginname) { + try { + Sql sql = Sqls.create(""" + SELECT + u.id userid, + u.username, + u.loginname, + u.sex, + u.mobile, + u.birthday, + unit.`name` unitname, + u.unitid, + u.member, + unit.unionid, + un.unionname, + group_concat(sr.`code`) roles + FROM + sys_user u + LEFT JOIN sys_unit unit ON u.unitid = unit.id + LEFT JOIN sys_union un ON unit.unionid = un.id + LEFT JOIN sys_user_role sur ON sur.userId = u.id + LEFT JOIN sys_role sr ON sr.id = sur.roleId + $condition + """).setParam("loginname", loginname).setParam("username", username); + + Cnd cnd = Cnd.NEW(); + cnd.and("LOWER(u.loginname)", "=", loginname.trim().toLowerCase()); + cnd.and("LOWER(u.username)", "=", username.trim().toLowerCase()); + sql.setCondition(cnd); + sql.setCallback(Sqls.callback.map()); + sysUserService.dao().execute(sql); + NutMap user = (NutMap) sql.getResult(); + if (StrUtil.isBlank(user.getString("userid"))) { + return Result.error().addMsg("系统查询不到您的信息,请与工会管理员联系!"); + } +// if(user.getInt("member",0)==0){ +// return Result.error().addMsg("您没有权限参加本次健步行,请与工会管理员联系!"); +// } + /*if (user.getInt("member", 0) != 1 && !user.getString("sex", "").equals("女")) { + return Result.error().addMsg("您没有权限参加本次健步行,请与工会管理员联系!"); + }*/ + return Result.success().addData(user); + } catch (Exception e) { + return Result.error(); + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkPunchLotteryController.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkPunchLotteryController.java new file mode 100644 index 00000000..d1fbebd6 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkPunchLotteryController.java @@ -0,0 +1,258 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.controller; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkActivity; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkPunchLottery; +import com.budwk.app.zhgh.activity.fitnesswalk.service.FitnessWalkCommonService; +import com.budwk.app.zhgh.activity.fitnesswalk.utils.WeAppCloudUtil; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.integration.jedis.RedisService; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.random.R; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.util.*; +import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Collectors; + +/** + * 打卡抽奖 + */ +@IocBean +@Ok("json") +@ApiOperation("健步走打卡抽奖") +@At("/platform/fitnessWalk/punchLottery") +public class FitnessWalkPunchLotteryController { + + private final ReentrantLock lock = new ReentrantLock(true); + + @Inject + private FitnessWalkCommonService fitnessWalkCommonService; + + @Inject + private WeAppCloudUtil weAppCloudUtil; + + @Inject + private RedisService redisService; + + @At("") + @Ok("beetl:/platform/zhgh/activity/fitnesswalk/punchLottery.html") + public void index() { + } + + + /** + * 打卡完成之后抽奖 + * + * @param activityId 活动Id + * @param userId 用户Id + * @return + */ + @At + @ApiOperation("打卡模式的抽奖") + public Result judgeWinningToPunch(String activityId, String userId) { + try { + if (StrUtil.isBlank(activityId) && StrUtil.isBlank(userId)) { + return Result.error("参数错误"); + } + + lock.lock(); + int winingCount = fitnessWalkCommonService.dao().count(FitnessWalkPunchLottery.class, Cnd.where("activityId", "=", activityId).and("userId", "=", userId)); + if (winingCount > 0) { + return null; + } + + // 把中奖的用户直接存到redis里面去 + String redisKey = this.getClass().getName() + "#judgeWinningToPunch#activityid:" + activityId + "#PRIZELIST:"; + String getPrizeIndexesKey = this.getClass().getName() + "#judgeWinningToPunch#activityid:" + activityId + "#GETPRIZEINDEXES:"; + +// redisService.del(getPrizeIndexesKey); + // 获取奖品列表 + List punchLotteryPrizes = new ArrayList<>(); + String punchLotteryPrizesJson = redisService.get(redisKey); + if (StrUtil.isNotBlank(punchLotteryPrizesJson)) { + punchLotteryPrizes = JSONUtil.toList(punchLotteryPrizesJson, FitnessWalkActivity.PunchLotteryPrize.class); + } else { + JSONObject prizeJsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.QUERY, "db.collection('activity').doc('%s').field({punchLotteryPrizes: true}).get()".formatted(activityId)); + List prizeList = JSONUtil.parseObj((String) prizeJsonObject.getJSONArray("data").get(0)).getJSONArray("punchLotteryPrizes").toList(FitnessWalkActivity.PunchLotteryPrize.class); + redisService.set(redisKey, JSONUtil.toJsonStr(prizeList)); + punchLotteryPrizes = prizeList; + } + + List winningUserIndexList = null; + //奖项,抽取多少个 + int sum = punchLotteryPrizes.stream().mapToInt(v -> Integer.parseInt(v.getNum())).sum(); + //判断是否有key,可以获得奖项的下标数组 + if (!redisService.exists(getPrizeIndexesKey)) { + JSONObject jsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.QUERY, "db.collection('register').where({activity_id:'%s'}).count()".formatted(activityId)); + JSONObject pager = jsonObject.getJSONObject("pager"); + String total = pager.getStr("Total"); + //报名人数的一半,从这里的人中取数(最多抽取人数) + Integer lotteryNum = (int) Math.ceil(Double.parseDouble(total) / 2); + winningUserIndexList = generateRandomNumber(1, lotteryNum, sum); + redisService.set(getPrizeIndexesKey, JSONUtil.toJsonStr(winningUserIndexList)); + } else { + String data = redisService.get(getPrizeIndexesKey); + winningUserIndexList = JSONUtil.toList(data, Integer.class); + } + + List punchLotteryList = fitnessWalkCommonService.dao().query(FitnessWalkPunchLottery.class, Cnd.where("activityId", "=", activityId)); + + Sys_user user = fitnessWalkCommonService.dao().fetch(Sys_user.class, Cnd.where("id", "=", userId)); + + FitnessWalkPunchLottery punchLottery = new FitnessWalkPunchLottery(); + punchLottery.setId(R.UU32()); + punchLottery.setActivityId(activityId); + punchLottery.setUserId(userId); + punchLottery.setLoginName(user.getLoginname()); + punchLottery.setUserName(user.getUsername()); + punchLottery.setWinDate(new Date()); + punchLottery.setIsRead(false); + punchLottery.setIsWin(false); + punchLottery.setIsExchange(false); + + if (winningUserIndexList.contains((punchLotteryList.size()))) { + + //奖项map + Map prizeMap = punchLotteryPrizes.stream().collect(Collectors.toMap(FitnessWalkActivity.PunchLotteryPrize::getValue, FitnessWalkActivity.PunchLotteryPrize::getName)); + + //奖项池 + List prizeIdList = new ArrayList<>(); + + punchLotteryPrizes.forEach(v -> { + for (int i = 0; i < Integer.parseInt(v.getNum()); i++) { + prizeIdList.add(v.getValue()); + } + }); + + //已经中奖的奖项ID集合 + List winPrizeIdList = punchLotteryList.stream().filter(FitnessWalkPunchLottery::getIsWin).map(FitnessWalkPunchLottery::getPrizeId).toList(); + winPrizeIdList.forEach(prizeIdList::remove); + + Random random = new Random(); + if (Lang.isNotEmpty(prizeIdList.size())) { + int index = random.nextInt(prizeIdList.size()); + + // 获取随机元素 + String winingPrizeId = prizeIdList.get(index); + String winingPrizeName = prizeMap.get(winingPrizeId); + punchLottery.setPrizeName(winingPrizeName); + punchLottery.setPrizeId(winingPrizeId); + punchLottery.setIsWin(true); + + } + + } + + fitnessWalkCommonService.dao().insert(punchLottery); + if (punchLottery.getIsWin()) { + return Result.success().addData(punchLottery.getPrizeId()); + } else { + return Result.success().addData(null); + } + } catch (Exception e) { + e.printStackTrace(); + return null; + } finally { + if (lock.isLocked()) { + lock.unlock(); + } + } + } + + @At + @ApiOperation("获取中奖记录") + public Result getLotteryRecord(String activityId, String userId) { + List list = fitnessWalkCommonService.dao().query(FitnessWalkPunchLottery.class, Cnd.where("activityId", "=", activityId) + .and("userId", "=", userId)); + return Result.success(list); + } + + + /** + * 兑奖 + * + * @param id + * @return + */ + @At + @ApiOperation("兑奖") + public Result doExchange(String id) { + + int count = fitnessWalkCommonService.dao().count(FitnessWalkPunchLottery.class, Cnd.where("id", "=", id).and("isExchange", "=", 1)); + //返回2 "该二维码已兑奖!" + if (count > 0) { + return Result.success(2); + } + + int update = fitnessWalkCommonService.dao().update(FitnessWalkPunchLottery.class, + Chain.make("isExchange", 1).add("exchangeDate", new Date()), + Cnd.where("id", "=", id)); + return update > 0 ? Result.success() : Result.error(); + } + + + /** + * 改为已读 + * + * @param activityId + * @param userId + * @return + */ + @At + @ApiOperation("改为已读") + public Result doReadLottery(String activityId, String userId) { + fitnessWalkCommonService.dao().update(FitnessWalkPunchLottery.class, Chain.make("isRead", 1), + Cnd.where("userId", "=", userId).and("activityId", "=", activityId)); + return Result.success(); + } + + + /** + * 查看获奖人员 + * + * @return + */ + @At + @ApiOperation("查看获奖人员") + public Result getPunchWining(String activityId) { + List punchLotteryList = fitnessWalkCommonService.dao().query(FitnessWalkPunchLottery.class, + Cnd.where("isWin", "=", 1).and("activityId", "=", activityId)); + return Result.success(punchLotteryList); + } + + + /** + * 抽奖方法的工具类,生成随机数,该随机数为中奖人 + * + * @param minNum 最小值 + * @param maxNum 最多抽取多少人 + * @param count 抽几个 + * @return + */ + public List generateRandomNumber(Integer minNum, Integer maxNum, Integer count) { + Set randomNumbers = new HashSet<>(); + Random rand = new Random(); + //如果是 抽奖人数小于了 奖品数量,会陷入死循环 + if (maxNum <= count) { + for (int i = 0; i <= maxNum; i++) { + randomNumbers.add(i + 1); + } + } else { + while (randomNumbers.size() < count) { + int randomNum = rand.nextInt(maxNum - minNum + 1) + minNum; + randomNumbers.add(randomNum); + } + } + return new ArrayList<>(randomNumbers); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkPunchStatisticsController.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkPunchStatisticsController.java new file mode 100644 index 00000000..a26ffc63 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkPunchStatisticsController.java @@ -0,0 +1,247 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.controller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.json.JSONObject; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.zhgh.activity.fitnesswalk.contants.FitnessWalkMode; +import com.budwk.app.zhgh.activity.fitnesswalk.service.FitnessWalkCommonService; +import com.budwk.app.zhgh.activity.fitnesswalk.service.FitnessWalkPunchStatisticsService; +import com.budwk.app.zhgh.activity.fitnesswalk.utils.WeAppCloudUtil; +import io.swagger.annotations.ApiOperation; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * 打卡统计 + */ +@IocBean +@Ok("json") +@ApiOperation("健步走打卡统计") +@At("/platform/fitnessWalk/punchStatistics") +public class FitnessWalkPunchStatisticsController { + + @Inject + private Dao dao; + + @Inject + private BaseService baseService; + + @Inject + private FitnessWalkCommonService fitnessWalkCommonService; + + @Inject + private WeAppCloudUtil weAppCloudUtil; + + @Inject + private FitnessWalkPunchStatisticsService fitnessWalkPunchStatisticsService; + + @At("") + @Ok("beetl:/platform/zhgh/activity/fitnesswalk/punchStatistics.html") + @SaCheckPermission("fitnessWalk.punchStatistics") + public void index() { + } + + /** + * 分工会统计 + * + * @param activityId + * @param unionId + * @return + */ + @At + @Ok("json:full") + @ApiOperation("打卡记录统计") + @SaCheckPermission("fitnessWalk.punchStatistics") + public Result pageData(String activityId, String unionId) { + List list = fitnessWalkPunchStatisticsService.unionRegCheckInNum(activityId, unionId); + return Result.success(list); + } + + @At + @ApiOperation("获取活动列表") + @SaCheckPermission("fitnessWalk.punchStatistics") + public Result getCascadersActivity(@Param("year") int year) { + return Result.success().addData(fitnessWalkCommonService.cascaderActivity(year, FitnessWalkMode.PUNCH)); + } + + @At + @Ok("json:full") + @ApiOperation("根据工会查询获取报名人员") + @SaCheckPermission("fitnessWalk.punchStatistics") + public Result unionRegistrationData(String activityId, String unionId) { + List list = fitnessWalkPunchStatisticsService.unionRegistrationData(activityId, unionId); + return Result.success(list); + } + + @At + @Ok("json:full") + @ApiOperation("根据工会查询获取打卡人员") + @SaCheckPermission("fitnessWalk.punchStatistics") + public Result unionCheckInData(String activityId, String unionId) { + List list = fitnessWalkPunchStatisticsService.unionCheckInData(activityId, unionId); + return Result.success(list); + } + + + @At + @Ok("void") + @ApiOperation("导出各分工会报名人数、打卡人数") + @SaCheckPermission("fitnessWalk.punchStatistics") + public void exportUnionRegCheckInNum(HttpServletResponse response, String activityId) { + List list = fitnessWalkPunchStatisticsService.unionRegCheckInNum(activityId, null); + List entities = new ArrayList<>(); + entities.add(new ExcelExportEntity("分工会", "unionname", 20)); + entities.add(new ExcelExportEntity("报名人数", "regCount", 20)); + entities.add(new ExcelExportEntity("打卡人数", "checkInCount", 20)); + + try { + Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), entities, list); + workbook.write(response.getOutputStream()); + + CommonDownloadUtil.download("各分工会统计人数.xlsx", workbook, response); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + @At + @Ok("void") + @ApiOperation("导出某个分工会的报名人员") + @SaCheckPermission("fitnessWalk.punchStatistics") + public void exportRegUsers(HttpServletResponse response, String activityId, String unionId) { + Sys_union union = dao.fetch(Sys_union.class, unionId); + String unionName = Optional.ofNullable(union).map(Sys_union::getName).orElse(null); + + List list = fitnessWalkPunchStatisticsService.unionRegistrationData(activityId, unionId); + List entities = new ArrayList<>(); + entities.add(new ExcelExportEntity("工号", "loginname", 20)); + entities.add(new ExcelExportEntity("姓名", "username", 20)); + entities.add(new ExcelExportEntity("单位", "unitname", 20)); + entities.add(new ExcelExportEntity("手机号", "mobile", 20)); + entities.add(new ExcelExportEntity("报名时间", "register_time_str", 20)); + + try { + Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), entities, list); + workbook.write(response.getOutputStream()); + CommonDownloadUtil.download("分工会报名人员.xlsx", workbook, response); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + @At + @Ok("void") + @ApiOperation("导出某个分工会的打卡人员") + @SaCheckPermission("fitnessWalk.punchStatistics") + public void exportCheckInUsers(HttpServletResponse response, String activityId, String unionId) { + Sys_union union = dao.fetch(Sys_union.class, unionId); + String unionName = Optional.ofNullable(union).map(Sys_union::getName).orElse(null); + + List list = fitnessWalkPunchStatisticsService.unionCheckInData(activityId, unionId); + + for (JSONObject jsonObject : list) { + Boolean used = jsonObject.getBool("used"); + if (used == null) { + jsonObject.put("used", "未取得"); + } else if (used) { + jsonObject.put("used", "已领取"); + } else { + jsonObject.put("used", "未领取"); + } + } + + List entities = new ArrayList<>(); + entities.add(new ExcelExportEntity("工号", "loginname", 20)); + entities.add(new ExcelExportEntity("姓名", "username", 20)); + entities.add(new ExcelExportEntity("单位", "unitname", 20)); + entities.add(new ExcelExportEntity("手机号", "mobile", 20)); + entities.add(new ExcelExportEntity("点位总数", "pts_size", 20)); + entities.add(new ExcelExportEntity("已打卡点位数", "sign_size", 20)); + entities.add(new ExcelExportEntity("礼品券", "used", 20)); + + try { + Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), entities, list); + workbook.write(response.getOutputStream()); + CommonDownloadUtil.download(unionName + "分工会报名人员.xlsx", workbook, response); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +// /** +// * 导出礼品领取情况 +// * @param response +// * @param activityId +// * @param unionId 工会id +// * @param used +// */ +// @At +// @Ok("void") +// public void exportGiftInfo(HttpServletResponse response, String activityId, String unionId, boolean used) { +// +// +// +// } + + + @At + @Ok("void") + @ApiOperation("导出未领取得奖品券用户") + @SaCheckPermission("fitnessWalk.punchStatistics") + public void exportNotGetGiftVoucherUsers(HttpServletResponse response, String activityId) { + List list = fitnessWalkPunchStatisticsService.exportNotGetGiftVoucherUsers(activityId); + List entities = new ArrayList<>(); + entities.add(new ExcelExportEntity("工号", "loginname", 20)); + entities.add(new ExcelExportEntity("姓名", "username", 20)); + entities.add(new ExcelExportEntity("单位", "unitname", 20)); + entities.add(new ExcelExportEntity("手机号", "mobile", 20)); + try { + Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), entities, list); + workbook.write(response.getOutputStream()); + CommonDownloadUtil.download("未领取得奖品券人员.xlsx", workbook, response); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @At + @Ok("void") + @ApiOperation("导出未使用奖品券用户") + @SaCheckPermission("fitnessWalk.punchStatistics") + public void exportNotUseGiftVoucherUsers(HttpServletResponse response, String activityId) { + List list = fitnessWalkPunchStatisticsService.exportNotUseGiftVoucherUsers(activityId); + List entities = new ArrayList<>(); + entities.add(new ExcelExportEntity("工号", "loginname", 20)); + entities.add(new ExcelExportEntity("姓名", "username", 20)); + entities.add(new ExcelExportEntity("单位", "unitname", 20)); + entities.add(new ExcelExportEntity("手机号", "mobile", 20)); + try { + Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), entities, list); + workbook.write(response.getOutputStream()); + CommonDownloadUtil.download("导出未使用礼品券用户.xlsx", workbook, response); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepManageController.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepManageController.java new file mode 100644 index 00000000..fd00ffea --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepManageController.java @@ -0,0 +1,403 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.controller; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkActivity; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkStep; +import com.budwk.app.zhgh.activity.fitnesswalk.service.FitnessWalkCommonService; +import com.budwk.app.zhgh.activity.fitnesswalk.utils.WeAppCloudUtil; +import com.budwk.app.zhgh.integral.model.IntegralDetail; +import io.swagger.annotations.ApiOperation; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.integration.jedis.RedisService; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.json.Json; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.util.*; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collectors; + +@IocBean +@Ok("json") +@ApiOperation("健步走步数管理") +@At("/platform/fitnessWalk/stepManage") +public class FitnessWalkStepManageController { + + @Inject + private Dao dao; + @Inject + private BaseService baseService; + @Inject + private RedisService redisService; + @Inject + private WeAppCloudUtil weAppCloudUtil; + @Inject + private FitnessWalkCommonService fitnessWalkCommonService; + + + /** + * 用户上传一个近31天的步数 + * + * @param activityId 活动id + * @param userId 用户id + * @param monthSteps 步数(当天往前推30天) + * @return + */ + @At + @Ok("json:full") + @Aop(TransAop.READ_COMMITTED) + @SLog(tag = "健步走步数管理", msg = "微信步数上传") + @ApiOperation("上传微信步数,再根据是否开启了积分,自动将步数转化成积分") + public Result updateStepMonth(String activityId, String userId, String monthSteps) { + try { + if (StrUtil.isBlank(userId) || StrUtil.isBlank(monthSteps) || StrUtil.isBlank(activityId)) { + return Result.error("必要参数未传递"); + } + + // 健步走的活动数据 + FitnessWalkActivity activity = fitnessWalkCommonService.getActivity(activityId); + // 是否启用了积分 + boolean isPoints = activity.getIsPoints() != null && activity.getIsPoints(); + + // 使用对象解构获取活动参数 + final Integer standSteps = activity.getLotteryQualificationSteps(); + final Integer standPoints = activity.getLotteryQualificationPoints(); + final Integer otherSteps = activity.getOtherSteps(); + final Integer otherPoints = activity.getOtherPoints(); + final Integer maxPoints = activity.getMaxPoints(); + + String integralNotes = activity.getMasterActivityName() + "所获积分"; + + // 获取到的用户的步数数据 + List steps = Json.fromJsonAsList(NutMap.class, monthSteps); + + //判断数据是否完整 微信运动会在晚上10点多进行步数的更新 会导致31天前的步数获取变为0 所以这里去除掉第一个元素 即为31天前的数据 每次只保存最近30天的数据 + if (Lang.isNotEmpty(steps) && steps.size() == 31) { + steps.remove(0); + } + + // 传递过来的步数数据 + List wxSteps = steps.stream().map(v -> { + FitnessWalkStep step = new FitnessWalkStep(); + step.setActivityId(activityId); + step.setUserId(userId); + step.setStep(v.getInt("step")); + // 计算积分,判断有没有设置,超过达标步数后,每达标XX步数,获得XX积分 + int calculatedPoints = calculatePoints(isPoints, standSteps, standPoints, otherSteps, otherPoints, maxPoints, step.getStep()); + step.setPoints(calculatedPoints); + DateTime date = DateUtil.parse(DateUtil.format(DateUtil.date(v.getLong("timestamp") * 1000), "yyyy-MM-dd"), "yyyy-MM-dd"); + step.setApplyDate(date); + return step; + }).toList(); + + // 传递过来的所有日期的集合 + List dateList = wxSteps.stream().map(FitnessWalkStep::getApplyDate).collect(Collectors.toList()); + + // 去数据库查询日期,这个玩意还要保证插入到数据库的单个日期只有一条,并且这个日期数据库之前有步数,传过来没步数那就要保留数据库的步数 + // 上面日期集合数据库的步数 + List stepList = dao.query(FitnessWalkStep.class, Cnd.where("activityId", "=", activityId) + .and("userId", "=", userId).and("applyDate", "in", dateList)); + + // 这就是保留每天最大步数的集合,那这个集合里面applyDate就是唯一的了 + List dupStepList = new ArrayList<>(stepList.stream() + .collect(Collectors.toMap(FitnessWalkStep::getApplyDate, Function.identity(), + BinaryOperator.maxBy(Comparator.comparing(FitnessWalkStep::getStep)))) + .values()); + + // 这是过滤的相同的applyDate的集合,这些数据要删除 + List delStepIds = stepList.stream() + .filter(step -> !dupStepList.contains(step)) + .map(FitnessWalkStep::getId) + .collect(Collectors.toList()); + + // 数据库的数据 这个map就用于判断数据库的日期和传递过来日期的步数,两个是不是相等的,保留步数多的数据 + Map dateStepMap = dupStepList.stream().collect(Collectors.toMap(FitnessWalkStep::getApplyDate, v -> v)); + + List resultStepList = new ArrayList<>(); + // 这里循环就是,循环的传递过来的数据 + for (FitnessWalkStep step : wxSteps) { + // 数据库存储的步数 + FitnessWalkStep walkStep = dateStepMap.get(step.getApplyDate()); + // 如果数据库没有,那就要新增 + if (Lang.isEmpty(walkStep)) { + resultStepList.add(step); + } else { + // 如果数据库有,那就要保留步数多的 + if (walkStep.getStep() < step.getStep()) { + walkStep.setStep(step.getStep()); + resultStepList.add(walkStep); + } + } + } + + // 最后删除重复日期,更新步数数据 + if (Lang.isNotEmpty(delStepIds)) { + dao.clear(FitnessWalkStep.class, Cnd.where("id", "in", delStepIds)); + if (standSteps != null && standSteps > 0) { + // 删除积分明细 + dao.clear(IntegralDetail.class, Cnd.where("id", "in", delStepIds)); + } + } + if (Lang.isNotEmpty(resultStepList)) { + dao.insertOrUpdate(resultStepList); + if (standSteps != null && standSteps > 0) { + // 增加积分明细 + int year = DateUtil.thisYear(); + List integralDetailList = resultStepList.stream().map(v -> { + IntegralDetail detail = new IntegralDetail(); + detail.setId(v.getId()); + detail.setYear(String.valueOf(year)); + detail.setUserId(userId); + detail.setIntegral(String.valueOf(v.getPoints())); + detail.setIntegralNotes(integralNotes); + detail.setBizId(activityId); + detail.setIntegralTime(v.getApplyDate()); + return detail; + }).toList(); + + List list = integralDetailList.stream().filter(v -> !"0".equals(v.getIntegral())).toList(); + if (Lang.isNotEmpty(list)) { + dao.insertOrUpdate(list); + } + } + } + return Result.success(); + } catch (Exception e){ + e.printStackTrace(); + return Result.error("步数上传失败,请稍后重试,必要时请及时联系管理员"); + } + } + + + /** + * 小程序获取开始时间至今的步数 + * + * @param activityId + * @param userId + * @return + */ + @At + @Ok("json:full") + @ApiOperation("小程序获取开始时间至今的步数") + public Result getActivityDateStep(String activityId, String userId) { + try { + Cnd cnd = Cnd.NEW(); + + FitnessWalkActivity activity = fitnessWalkCommonService.getActivity(activityId); + DateTime startTime = DateUtil.date(activity.getStartTime()); + DateTime endTime = DateUtil.date(activity.getEndTime()); + + cnd.and("activityId", "=", activityId); + cnd.and("userId", "=", userId); + cnd.and("applyDate", ">=", startTime); + cnd.and("applyDate", "<=", endTime); + cnd.asc("applyDate"); + cnd.groupBy("applyDate"); + List stepList = baseService.dao().query(FitnessWalkStep.class, cnd); + + List> collect = stepList.stream().map(v -> { + return Map.of("step", v.getStep(), "timestamp", v.getApplyDate().getTime()); + }).collect(Collectors.toList()); + + return Result.success().addData(collect); + + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + @At + @Ok("json:full") + @ApiOperation("获取活动达标的进度条") + public Result getActivityQualifyProgressBar(String activityId, String userId) { + NutMap resultMap = NutMap.NEW(); + + FitnessWalkActivity activity = fitnessWalkCommonService.getActivity(activityId); + //计步的抽奖模式 everyday custom + String lotteryMode = activity.getLotteryMode(); + if ("everyday".equals(lotteryMode)) { + FitnessWalkActivity.DayLotteryRule dayLotteryRule = activity.getDayLotteryRule(); + //每日抽奖资格步数 + Integer lotteryQualificationStep = dayLotteryRule.getLotteryQualificationStep(); + + FitnessWalkStep userWalkStep = baseService.dao().fetch(FitnessWalkStep.class, Cnd.where("userId", "=", userId) + .and("DATE( applyDate )", "=", DateUtil.today()).and("activityId", "=", activityId)); + + int complianceDay = baseService.dao().count(FitnessWalkStep.class, Cnd.where("userId", "=", userId) + .and("DATE( applyDate )", "=", DateUtil.today()).and("activityId", "=", activityId) + .and("step", ">", lotteryQualificationStep)); + + // 今天的步数 + Integer thisDayStep = userWalkStep.getStep(); + + // 去计算达标的百分比 + BigDecimal lotteryQualificationStepBig = new BigDecimal(lotteryQualificationStep); + BigDecimal thisDayStepBig = new BigDecimal(thisDayStep); + //达标的小数,保留四位 + BigDecimal divide = thisDayStepBig.divide(lotteryQualificationStepBig, 4, RoundingMode.HALF_UP); + BigDecimal percentValue = divide.multiply(new BigDecimal("100")); + // 格式化为两位小数 + DecimalFormat decimalFormat = new DecimalFormat("#.##"); + //百分数 + String formattedPercent = decimalFormat.format(percentValue); + + long betweenDay = DateUtil.date(activity.getStartTime()).between(DateUtil.date(activity.getEndTime()), DateUnit.DAY); + NutMap map = new NutMap(); + map.setv("mode", "everyDayLottery"); + //当前达标步数 + map.setv("userStep", thisDayStep); + //达标总步数 + map.setv("complianceSumStep", lotteryQualificationStep); + //达标比例 + map.setv("complianceProportion", Integer.parseInt(formattedPercent)); + //活动天数 + map.setv("betweenDay", betweenDay); + //达标天数 + map.setv("complianceDay", complianceDay); + resultMap.addv("everyDayLotteryMode", map); + } else if ("custom".equals(lotteryMode)) { + List customLotteryRules = activity.getCustomLotteryRules(); + List userWalkSteps = baseService.dao(). + query(FitnessWalkStep.class, Cnd.where("userId", "=", userId) + .and("activityId", "=", activityId) + .and("DATE(applyDate)", ">=", DateUtil.format(DateUtil.date(activity.getStartTime()), "yyyy-MM-dd")) + .and("DATE(applyDate)", "<=", DateUtil.format(DateUtil.date(activity.getEndTime()), "yyyy-MM-dd")) + ); + + List result = new ArrayList<>(); + + for (FitnessWalkActivity.CustomLotteryRule rule : customLotteryRules) { + NutMap nutMap = NutMap.NEW(); + + List partSteps = userWalkSteps.stream() + .filter(s -> (DateUtil.compare(s.getApplyDate(), rule.getStartDate()) >= 0 && DateUtil.compare(s.getApplyDate(), rule.getEndDate()) <= 0)) + .toList(); + + Integer lotteryQualificationDay = rule.getLotteryQualificationDay(); + Integer lotteryQualificationStep = rule.getLotteryQualificationStep(); + + if (lotteryQualificationDay != null && lotteryQualificationStep != null) { + //每天步数 + nutMap.put("mode", "customLotteryEveryDayStepMode"); + //用户总达标步数 + nutMap.put("userSumStep", partSteps.stream().filter(s -> DateUtil.compare(s.getApplyDate(), new Date(), "yyyy-MM-dd") == 0).findFirst().map(s -> s.getStep()).orElse(0)); + //今天达标步数 + nutMap.put("complianceStep", lotteryQualificationStep); + //总达标步数 + nutMap.put("complianceSumStep", lotteryQualificationDay * lotteryQualificationStep); + //用户当前达标总天数 + nutMap.put("userComplianceSumDay", partSteps.stream().filter(s -> s.getStep() > lotteryQualificationStep).count()); + //总达标天数 + nutMap.put("complianceSumDay", lotteryQualificationDay); + } else if (lotteryQualificationDay == null && lotteryQualificationStep != null) { + //总步数 + nutMap.put("mode", "customLotterySumStepMode"); + //用户总达标步数 + nutMap.put("userSumStep", partSteps.stream().mapToInt(FitnessWalkStep::getStep).sum()); + //总达标步数 + nutMap.put("complianceSumStep", lotteryQualificationStep); + + nutMap.put("title", DateUtil.format(rule.getStartDate(), "MM月dd日") + "至" + DateUtil.format(rule.getEndDate(), "MM月dd日")); + + } + result.add(nutMap); + } + resultMap.addv("customLotteryMode", result); + } + return Result.success().addData(resultMap); + } + + /** + * 获取用户未读的奖 + * + * @param activityId + * @param userId + * @return + */ + @At + @Ok("json:full") + @ApiOperation("获取用户未读的奖") + public Result winningRecord(String activityId, String userId) { + Sql sql = Sqls.create(""" + select awardName,startDate,endDate from fitness_walk_award_user where activityId=@activityId and userId=@userId and isRead=@isRead + """).setParam("activityId",activityId).setParam("userId", userId).setParam("isRead",true); + + /* List awardUsers = baseService.dao().query(FitnessWalkAwardUser.class, + Cnd.where("activityId", "=", activityId) + .and("userId", "=", userId).and("isRead", "=", true));*/ + return Result.success(baseService.listMap(sql)); + } + + + + /** + * 计算积分 + * @param isPointsEnabled + * @param standSteps + * @param standPoints + * @param otherSteps + * @param otherPoints + * @param maxPoints + * @param actualSteps + * @return + */ + private int calculatePoints(boolean isPointsEnabled, + Integer standSteps, Integer standPoints, + Integer otherSteps, Integer otherPoints, + Integer maxPoints, int actualSteps) { + // 基础条件检查 + if (!isPointsEnabled || standSteps == null || standPoints == null || actualSteps < standSteps) { + return 0; + } + + // 计算基础积分 + int totalPoints = standPoints; + + // 计算额外积分 + if (hasExtraPoints(otherSteps, otherPoints)) { + int extraSteps = actualSteps - standSteps; + int extraPoints = (extraSteps / otherSteps) * otherPoints; + totalPoints += extraPoints; + } + + // 应用积分上限 + if (hasMaxPointsLimit(maxPoints)) { + return Math.min(totalPoints, maxPoints); + } + + return totalPoints; + } + + /** + * 检查是否有额外积分规则 + */ + private boolean hasExtraPoints(Integer otherSteps, Integer otherPoints) { + return otherSteps != null && otherPoints != null && otherSteps > 0 && otherPoints > 0; + } + + /** + * 检查是否有积分上限 + */ + private boolean hasMaxPointsLimit(Integer maxPoints) { + return maxPoints != null && maxPoints > 0; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepRaffleController.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepRaffleController.java new file mode 100644 index 00000000..8e5ce2e9 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepRaffleController.java @@ -0,0 +1,285 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.controller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.zhgh.activity.fitnesswalk.contants.FitnessWalkMode; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkAwardUser; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkRaffleRules; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkRaffleUser; +import com.budwk.app.zhgh.activity.fitnesswalk.service.FitnessWalkCommonService; +import com.budwk.app.zhgh.activity.fitnesswalk.service.FitnessWalkStepRaffleService; +import com.budwk.app.zhgh.integral.model.IntegralDetail; +import io.swagger.annotations.ApiOperation; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.List; + +/** + * @version 1.0 + * @Author zzr + * @name:FitnessWalkStepRaffleController + * @Date 2024/12/27 14:43 + * @注释 健步走抽奖控制器 + */ +@IocBean +@Ok("json") +@ApiOperation("健步走手动抽奖") +@At("/platform/fitnessWalk/stepRaffle") +public class FitnessWalkStepRaffleController { + + @Inject + private Dao dao; + @Inject + private BaseService baseService; + @Inject + private FitnessWalkCommonService fitnessWalkCommonService; + @Inject + private FitnessWalkStepRaffleService fitnessWalkStepRaffleService; + + + @At("") + @Ok("beetl:/platform/zhgh/activity/fitnesswalk/stepRaffle.html") + @SaCheckPermission("fitnessWalk.stepRaffle") + public void index() { + } + + + @At + @ApiOperation("获取抽奖列表") + @SaCheckPermission("fitnessWalk.stepRaffle") + public Result pageData(PageForm pageForm, + @Param("activityId") String activityId, + @Param("unionId") String unionId, + @Param("unitId") String unitId){ + Sql sql = fitnessWalkStepRaffleService.getRaffleSql(pageForm, activityId, unionId, unitId); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + @At + @ApiOperation("获取活动级联数据") + @SaCheckPermission("fitnessWalk.stepRaffle") + public Result getCascadersActivity(@Param("year") int year) { + return Result.success().addData(fitnessWalkCommonService.cascaderActivity(year, FitnessWalkMode.STEP_COUNT)); + } + + + @At + @Aop(TransAop.READ_COMMITTED) + @ApiOperation("设置抽奖规则,并抽奖") + @SLog(tag = "健步走手动抽奖", msg = "设置抽奖规则并抽奖") + @SaCheckPermission("fitnessWalk.stepRaffle") + public Result saveRaffle(FitnessWalkRaffleRules fitnessWalkRaffleRules){ + baseService.dao().insertOrUpdate(fitnessWalkRaffleRules); + fitnessWalkStepRaffleService.manualLottery(fitnessWalkRaffleRules.getActivityId()); + return null; + } + + + @At + @ApiOperation("获取抽奖规则") + @SaCheckPermission("fitnessWalk.stepRaffle") + public Result getRaffle(String activityId){ + FitnessWalkRaffleRules raffleRules = baseService.dao().fetch(FitnessWalkRaffleRules.class, Cnd.where("activityId", "=", activityId)); + return Result.success().addData(raffleRules); + } + + + /** + * 小程序获取奖项信息 + * @param activityId + * @return + */ + @At + @ApiOperation("小程序获取奖项信息") + public Result getAwardList(String activityId){ + List activityAwardList = fitnessWalkStepRaffleService.getActivityAwardList(activityId); + return Result.success().addData(activityAwardList); + } + + + /** + * 小程序获取自己的中奖信息 + * @return + */ + @At + @ApiOperation("小程序获取自己的中奖信息") + public Result getAwardInfo(String activityId, String userId){ + Dao dao = fitnessWalkStepRaffleService.dao(); + FitnessWalkAwardUser awardUser = dao.fetch(FitnessWalkAwardUser.class, Cnd.where("activityId", "=", activityId).and("userId", "=", userId)); + FitnessWalkRaffleUser raffleUser = dao.fetch(FitnessWalkRaffleUser.class, Cnd.where("activityId", "=", activityId).and("userId", "=", userId)); + + NutMap map = NutMap.NEW(); + if (Lang.isNotEmpty(raffleUser) && !raffleUser.getIsRaffle()) { + if (Lang.isNotEmpty(awardUser)) { + map.put("awardName", awardUser.getAwardName()); + } else { + map.put("awardName", "没有中奖"); + } + map.put("raffleNum", 1); + } else { + map.put("raffleNum", 0); + } + return Result.success().addData(map); + } + + + /** + * 小程序获取查询是否可以抽奖 + * @return + */ + @At + @ApiOperation("小程序获取查询是否可以抽奖") + public Result checkRaffle(String activityId, String userId){ + Dao dao = fitnessWalkStepRaffleService.dao(); + FitnessWalkRaffleUser raffleUser = dao.fetch(FitnessWalkRaffleUser.class, + Cnd.where("activityId", "=", activityId) + .and("userId", "=", userId)); + if (Lang.isNotEmpty(raffleUser)) { + return raffleUser.getIsRaffle() ? Result.error() : Result.success(); + } else { + return Result.error(); + } + } + + + /** + * 抽奖成功后,修改数据库状态 + * @param activityId + * @param userId + * @return + */ + @At + @Aop(TransAop.READ_COMMITTED) + @ApiOperation("抽奖成功后,修改数据库状态") + @SLog(tag = "健步走手动抽奖", msg = "抽奖成功后,修改数据库状态") + public Result updateUserAward(String activityId, String userId) { + fitnessWalkStepRaffleService.dao().update(FitnessWalkAwardUser.class, + Chain.make("isRead", true).add("applyDate", DateUtil.date()), + Cnd.where("activityId", "=", activityId).and("userId", "=", userId)); + + fitnessWalkStepRaffleService.dao().update(FitnessWalkRaffleUser.class, + Chain.make("isRaffle", true), + Cnd.where("activityId", "=", activityId).and("userId", "=", userId)); + // 增加积分 + FitnessWalkAwardUser awardUser = dao.fetch(FitnessWalkAwardUser.class, Cnd.where("activityId", "=", activityId).and("userId", "=", userId)); + IntegralDetail detail = new IntegralDetail(); + detail.setId(awardUser.getId()); + detail.setYear(String.valueOf(DateUtil.thisYear())); + detail.setUserId(awardUser.getUserId()); + detail.setIntegral(String.valueOf(awardUser.getPoints())); + detail.setIntegralNotes(awardUser.getAwardName()); + detail.setBizId(awardUser.getId()); + detail.setIntegralTime(DateUtil.date()); + dao.insert(detail); + return null; + } + + + @At + @Ok("void") + @ApiOperation("导出中奖名单") + @SaCheckPermission("fitnessWalk.stepRaffle") + public void exportAwardExcel(String searchKeyword, String activityId, + String lotteryTime, HttpServletResponse response) { + Cnd cnd = Cnd.NEW(); + cnd.andEX("activityId", "=", activityId); + cnd.andEX("awardName", "=", lotteryTime); + if (StrUtil.isNotBlank(searchKeyword)) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.orLike("username", searchKeyword); + seg.orLike("loginName", searchKeyword); + cnd.and(seg); + } + cnd.and("isRead", "=", true); + List list = fitnessWalkCommonService.dao().query(FitnessWalkAwardUser.class, cnd); + + for (FitnessWalkAwardUser awardUser : list) { + awardUser.setApplyDate(awardUser.getApplyDate()); + } + + List entityList = new ArrayList<>(); + ExcelExportEntity no = new ExcelExportEntity("序号", "no", 10); + no.setFormat("isAddIndex"); + entityList.add(no); + entityList.add(new ExcelExportEntity("工号", "loginName", 20)); + entityList.add(new ExcelExportEntity("姓名", "username", 20)); + entityList.add(new ExcelExportEntity("分工会", "unionName", 20)); + entityList.add(new ExcelExportEntity("单位", "unitName", 40)); + entityList.add(new ExcelExportEntity("奖项名称", "awardName", 20)); + entityList.add(new ExcelExportEntity("中奖时间", "applyDate2", 20)); + + try { + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, list); + workbook.write(response.getOutputStream()); + CommonDownloadUtil.download("健步走中奖人员名单.xlsx", workbook, response); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + @At + @Ok("void") + @ApiOperation("导出健步走达标人员名单") + @SaCheckPermission("fitnessWalk.stepRaffle") + public void exportExcel(String searchKeyword, String activityId, String unionId, + String unitId, HttpServletResponse response) { + PageForm pageForm = new PageForm(); + pageForm.setSearchKeyword(searchKeyword); + Sql sql = fitnessWalkStepRaffleService.getRaffleSql(pageForm, activityId, unionId, unitId); + + List list = fitnessWalkStepRaffleService.listMap(sql); + + List entityList = new ArrayList<>(); + ExcelExportEntity no = new ExcelExportEntity("序号", "no", 10); + no.setFormat("isAddIndex"); + entityList.add(no); + entityList.add(new ExcelExportEntity("工号", "loginname", 20)); + entityList.add(new ExcelExportEntity("姓名", "username", 20)); + entityList.add(new ExcelExportEntity("分工会", "unionname", 20)); + entityList.add(new ExcelExportEntity("单位", "unitname", 40)); + entityList.add(new ExcelExportEntity("达标天数", "standardsDays", 20)); + entityList.add(new ExcelExportEntity("步数", "total_steps", 20)); + + try { + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, list); + workbook.write(response.getOutputStream()); + CommonDownloadUtil.download("健步走达标人员名单.xlsx", workbook, response); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepRankingController.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepRankingController.java new file mode 100644 index 00000000..4afc3fe3 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepRankingController.java @@ -0,0 +1,274 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.controller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.zhgh.activity.fitnesswalk.contants.FitnessWalkMode; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkActivity; +import com.budwk.app.zhgh.activity.fitnesswalk.service.FitnessWalkCommonService; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * 步数排行榜 + */ +@Slf4j +@IocBean +@Ok("json") +@ApiOperation("健步走步数排行榜") +@At("/platform/fitnessWalk/stepRanking") +public class FitnessWalkStepRankingController { + + @Inject + private BaseService baseService; + + @Inject + private FitnessWalkCommonService fitnessWalkCommonService; + + @At("") + @Ok("beetl:/platform/zhgh/activity/fitnesswalk/stepRanking.html") + @SaCheckPermission("fitnessWalk.stepRanking") + public void index() { + } + + @At + @ApiOperation("获取步数排行榜") + @SaCheckPermission("fitnessWalk.stepRanking") + public Result pageData(PageForm pageForm, + @Param("activityId") String activityId, + @Param("unionId") String unionId, + @Param("unitId") String unitId, + @Param("mode") String mode) { + Pagination pagination = fitnessWalkCommonService.getStepRankingPagination(pageForm, activityId, unionId, unitId, mode); + return Result.success().addData(pagination); + } + + + /** + * 获取所有教工 今天的步数及活动时间范围内的步数 + * + * @param activityId + * @param mode day:今天 all:所有 + * @return {@link Object} + */ + @At + @Ok("json:full") + @ApiOperation("获取今日步数及活动范围内步数") + @SLog(type = "校工会特色活动", tag = "健身走-计步步数排行榜", msg = "小程序接口(获取今日步数及活动范围内步数)") + public Result getUserStepRanking(String activityId, String mode, Integer pageNumber, Integer pageSize) { + if ("day".equals(mode)) { + Sql sql = Sqls.create(""" + SELECT + t.step, + t.applyDate, + u.username + FROM + `fitness_walk_step` t + LEFT JOIN sys_user u ON u.id = t.userId + WHERE + t.activityId = @activityId + AND t.applyDate = @today + GROUP BY u.id + ORDER BY t.step DESC + """); + sql.setParam("activityId", activityId); + sql.setParam("today", DateUtil.today()); + Pagination pagination = baseService.listPageMap(pageNumber, 50, sql); + return Result.success().addData(pagination); + } else if ("week".equals(mode)) { + // 周榜 + Date startOfWeek = DateUtil.beginOfWeek(new Date()); + Date endOfWeek = DateUtil.endOfWeek(new Date()); + + Sql sql = Sqls.create(""" + SELECT + t.userId, + sum( t.step ) AS step, + u.username + FROM + `fitness_walk_step` t + LEFT JOIN sys_user u ON u.id = t.userId + WHERE + t.activityId = @activityId + AND t.applyDate >= @startTime + AND t.applyDate <= @endTime + GROUP BY + t.userId + ORDER BY + step DESC + """); + sql.setParam("activityId", activityId); + sql.setParam("startTime", startOfWeek); + sql.setParam("endTime", endOfWeek); + Pagination pagination = baseService.listPageMap(pageNumber, 50, sql); + return Result.success().addData(pagination); + } else if ("month".equals(mode)) { + // 月榜 + Date firstDayOfMonth = DateUtil.beginOfMonth(new Date()); + Date lastDayOfMonth = DateUtil.endOfMonth(new Date()); + Sql sql = Sqls.create(""" + SELECT + t.userId, + sum( t.step ) AS step, + u.username + FROM + `fitness_walk_step` t + LEFT JOIN sys_user u ON u.id = t.userId + WHERE + t.activityId = @activityId + AND t.applyDate >= @startTime + AND t.applyDate <= @endTime + GROUP BY + t.userId + ORDER BY + step DESC + """); + sql.setParam("activityId", activityId); + sql.setParam("startTime", firstDayOfMonth); + sql.setParam("endTime", lastDayOfMonth); + Pagination pagination = baseService.listPageMap(pageNumber, 50, sql); + return Result.success().addData(pagination); + } else if ("all".equals(mode)) { + // 总达标榜 + FitnessWalkActivity activity = fitnessWalkCommonService.getActivity(activityId); + DateTime startTime = DateUtil.date(activity.getStartTime()); + DateTime endTime = DateUtil.date(activity.getEndTime()); + Sql sql = Sqls.create(""" + SELECT + SUM(sub.max_step) AS step, + u.username + FROM ( + SELECT + userId, + activityId, + applyDate, + MAX(step) AS max_step + FROM + fitness_walk_step + WHERE + activityId = @activityId + AND applyDate >= @startTime AND applyDate <= @endTime + GROUP BY + userId, + activityId, + applyDate + ) sub + left join `user` u ON u.id = sub.userId + GROUP BY + userId + ORDER BY + step desc + """); + sql.setParam("activityId", activityId); + sql.setParam("startTime", startTime); + sql.setParam("endTime", endTime); + Pagination pagination = baseService.listPageMap(pageNumber, 50, sql); + return Result.success().addData(pagination); + } else if ("points".equals(mode)) { + // 积分榜 + FitnessWalkActivity activity = fitnessWalkCommonService.getActivity(activityId); + DateTime startTime = DateUtil.date(activity.getStartTime()); + DateTime endTime = DateUtil.date(activity.getEndTime()); + Sql sql = Sqls.create(""" + SELECT + SUM(sub.max_step) AS step, + u.username + FROM ( + SELECT + userId, + activityId, + applyDate, + MAX(points) AS max_step + FROM + fitness_walk_step + WHERE + activityId = @activityId + AND applyDate >= @startTime AND applyDate <= @endTime + GROUP BY + userId, + activityId, + applyDate + ) sub + left join `user` u ON u.id = sub.userId + GROUP BY + userId + ORDER BY + step desc + """); + sql.setParam("activityId", activityId); + sql.setParam("startTime", startTime); + sql.setParam("endTime", endTime); + Pagination pagination = baseService.listPageMap(pageNumber, 50, sql); + return Result.success().addData(pagination); + } else { + return null; + } + } + + + @At + @Ok("void") + @ApiOperation("步数排行榜导出") + @SaCheckPermission("fitnessWalk.stepRanking") + @SLog(type = "校工会特色活动", tag = "健身走-计步步数排行榜", msg = "步数排行榜导出", param = true, result = true) + public void exportExcel(@Param("searchName") String searchName, + @Param("searchKeyword") String searchKeyword, + @Param("activityId") String activityId, + @Param("unionId") String unionId, + @Param("unitId") String unitId, + @Param("mode") String mode, + HttpServletResponse response) { + List stepRankingList = fitnessWalkCommonService.getStepRankingList(searchName, searchKeyword, activityId, unionId, unitId, mode); + + List entityList = new ArrayList<>(); + ExcelExportEntity no = new ExcelExportEntity("序号", "no", 10); + no.setFormat("isAddIndex"); + entityList.add(no); + entityList.add(new ExcelExportEntity("姓名", "username", 20)); + entityList.add(new ExcelExportEntity("工号", "loginname", 20)); + entityList.add(new ExcelExportEntity("分工会", "unionname", 20)); + entityList.add(new ExcelExportEntity("单位", "unitname", 20)); + entityList.add(new ExcelExportEntity("today".equals(mode) ? "今日步数" : "活动期间总步数", "total_steps", 20)); + try { + String title = ("today".equals(mode) ? DateUtil.format(new Date(), "yyyy年MM月dd日") : "活动期间总") + "步数榜.xlsx"; + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, stepRankingList); + workbook.write(response.getOutputStream()); + CommonDownloadUtil.download(title, workbook, response); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @At + @ApiOperation("获取联级活动") + @SaCheckPermission("fitnessWalk.stepRanking") + public Result getCascadersActivity(@Param("year") int year) { + return Result.success().addData(fitnessWalkCommonService.cascaderActivity(year, FitnessWalkMode.STEP_COUNT)); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepStatisticsController.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepStatisticsController.java new file mode 100644 index 00000000..0763ad07 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepStatisticsController.java @@ -0,0 +1,165 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.controller; + + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.zhgh.activity.fitnesswalk.contants.FitnessWalkMode; +import com.budwk.app.zhgh.activity.fitnesswalk.service.FitnessWalkCommonService; +import com.budwk.app.zhgh.activity.fitnesswalk.utils.WeAppCloudUtil; +import io.swagger.annotations.ApiOperation; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.integration.jedis.RedisService; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.List; + +@IocBean +@Ok("json") +@ApiOperation("计步步数统计") +@At("/platform/fitnessWalk/stepStatistics") +public class FitnessWalkStepStatisticsController { + + @Inject + private BaseService baseService; + @Inject + private RedisService redisService; + @Inject + private WeAppCloudUtil weAppCloudUtil; + @Inject + private FitnessWalkCommonService fitnessWalkCommonService; + + @At("") + @Ok("beetl:/platform/zhgh/activity/fitnesswalk/stepStatistics.html") + @SaCheckPermission("fitnessWalk.stepStatistics") + public void index() { + } + + /** + * 公共sql + * @return + */ + private String getSql() { + return """ + SELECT + u.loginname, + u.username, + u.unionName AS unionname, + u.unitName AS unitname, + al.applyDate, + al.step, + date_format(al.applyDate,'%Y-%m-%d') as prizeData + FROM + `fitness_walk_step` al + LEFT JOIN `vw_user` u ON u.id = al.userId + $condition + """; + } + + @At + @Ok("json:full") + @ApiOperation("计步步数统计") + @SaCheckPermission("fitnessWalk.stepStatistics") + public Result pageData(PageForm pageForm, + @Param("year") Integer year, + @Param("activityId") String activityId, + @Param("activityDate") String[] activityDate, + @Param("unionId") String unionId, + @Param("unitId") String unitId) { + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(getSql()); + if (Lang.isNotEmpty(activityDate)) { + cnd.and("date_format(al.applyDate,'%Y-%m-%d')", ">=", activityDate[0]); + cnd.and("date_format(al.applyDate,'%Y-%m-%d')", "<=", activityDate[1]); + } + if(StrUtil.isNotBlank(pageForm.getSearchKeyword())){ + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.orLike("u.username",pageForm.getSearchKeyword()); + seg.orLike("u.loginname",pageForm.getSearchKeyword()); + cnd.and(seg); + } + cnd.andEX("YEAR(al.applyDate)", "=", year); + cnd.andEX("al.activityId", "=", activityId); + cnd.andEX("u.unionid", "=", unionId); + cnd.andEX("u.unitId", "=", unitId); + cnd.desc("al.applyDate"); + cnd.desc("u.unioncode"); + cnd.groupBy("al.applyDate", "al.userId"); + + sql.setCondition(cnd); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + @At + @ApiOperation("获取联级活动") + @SaCheckPermission("fitnessWalk.stepStatistics") + public Result getCascadersActivity(@Param("year") int year) { + return Result.success().addData(fitnessWalkCommonService.cascaderActivity(year, FitnessWalkMode.STEP_COUNT)); + } + + + @Ok("void") + @At("/exportExcel") + @ApiOperation("计步步数统计表导出") + @SaCheckPermission("fitnessWalk.stepStatistics") + public void exportExcel(@Param("activityId") String activityId, + @Param("activityDate") String[] activityDate, + @Param("unionId") String unionId, + @Param("unitId") String unitId, HttpServletResponse response) { + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(getSql()); + if (activityDate.length > 0) { + cnd.and("date_format(al.applyDate,'%Y-%m-%d')", ">=", activityDate[0]); + cnd.and("date_format(al.applyDate,'%Y-%m-%d')", "<=", activityDate[1]); + } + cnd.andEX("al.activityId", "=", activityId); + cnd.andEX("u.unionid", "=", unionId); + cnd.andEX("u.unitId", "=", unitId); + cnd.desc("al.applyDate"); + cnd.desc("u.unioncode"); + sql.setCondition(cnd); + + List exportList = baseService.listMap(sql); + + List entityList = new ArrayList<>() {{ + add(new ExcelExportEntity("姓名", "username", 20)); + add(new ExcelExportEntity("工号", "loginname", 20)); + add(new ExcelExportEntity("单位", "unitname", 20)); + add(new ExcelExportEntity("分工会", "unionname", 20)); + add(new ExcelExportEntity("当前步数", "step", 20)); + add(new ExcelExportEntity("日期", "prizeData", 20)); + }}; + + try { + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, exportList); + workbook.write(response.getOutputStream()); + CommonDownloadUtil.download("计步步数统计表.xlsx", workbook, response); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepWiningController.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepWiningController.java new file mode 100644 index 00000000..5ca384d5 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/controller/FitnessWalkStepWiningController.java @@ -0,0 +1,155 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.controller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.activity.fitnesswalk.contants.FitnessWalkMode; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkAwardUser; +import com.budwk.app.zhgh.activity.fitnesswalk.service.FitnessWalkCommonService; +import io.swagger.annotations.ApiOperation; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.dao.Cnd; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedOutputStream; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/** + * 用户中奖榜 + */ +@IocBean +@Ok("json") +@ApiOperation("小程序计步步数中奖榜") +@At("/platform/fitnessWalk/stepWining") +public class FitnessWalkStepWiningController { + + @Inject + private BaseService baseService; + + @Inject + private FitnessWalkCommonService fitnessWalkCommonService; + + + @At("") + @Ok("beetl:/platform/zhgh/activity/fitnesswalk/stepWining.html") + @SaCheckPermission("fitnessWalk.stepWining") + public void index() { + } + + + /** + * 获取中奖榜 + * + * @param activityId + * @return {@link Object} + */ + @At + @Ok("json:full") + @ApiOperation("小程序获取中奖榜") + @SLog(type = "校工会特色活动",tag = "健身走-计步步数中奖榜",msg = "获取中奖榜") + public Result getUserStepWining(String activityId) { + return Result.success().addData(fitnessWalkCommonService.getWiningRankingUserList(activityId)); + } + + @At + @ApiOperation("获取联级活动") + @SaCheckPermission("fitnessWalk.stepWining") + public Result getCascadersActivity(@Param("year") int year) { + return Result.success().addData(fitnessWalkCommonService.cascaderActivity(year, FitnessWalkMode.STEP_COUNT)); + } + + + @At + @Ok("void") + @ApiOperation("小程序中奖榜导出") + @SaCheckPermission("fitnessWalk.stepWining") + @SLog(type = "校工会特色活动",tag = "健身走-计步步数中奖榜",msg = "导出中奖榜") + public void exportUserStepWining(String activityId, HttpServletResponse response){ + List winingRankingUserList = fitnessWalkCommonService.getWiningRankingUserList(activityId); + List entityList = new ArrayList<>(); + ExcelExportEntity no = new ExcelExportEntity("序号", "no", 10); + no.setFormat("isAddIndex"); + entityList.add(no); + entityList.add(new ExcelExportEntity("工号", "loginName", 20)); + entityList.add(new ExcelExportEntity("姓名", "username", 20)); + entityList.add(new ExcelExportEntity("分工会", "unionName", 20)); + entityList.add(new ExcelExportEntity("单位", "unitName", 40)); + entityList.add(new ExcelExportEntity("奖项名称", "awardName", 20)); + entityList.add(new ExcelExportEntity("步数", "awardSteps", 20)); + entityList.add(new ExcelExportEntity("中奖时间", "applyDate", 20)); + try { + response.setContentType("application/octet-stream"); + response.setHeader("content-disposition", "attachment;filename=" + + URLEncoder.encode("中奖明细.zip", "UTF-8")); + ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream())); + for (NutMap map : winingRankingUserList) { + List awardList = map.getAsList("awardList", NutMap.class); + awardList.forEach(v->v.setv("applyDate",DateUtil.format(v.getTime("applyDate"),"yyyy-MM-dd"))); + zipOutputStream.putNextEntry(new ZipEntry(map.getString("title") + ".xlsx")); + Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), entityList, awardList); + workbook.write(zipOutputStream); + zipOutputStream.closeEntry(); + } + zipOutputStream.flush(); + zipOutputStream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + + /** + * 中奖奖项列表 + * + * @param activityId + * @return + */ + @At + @ApiOperation("小程序获取中奖奖项列表") + public Result prizeOption(String activityId) { + List list = fitnessWalkCommonService.prizeOption(activityId); + return Result.success(list); + } + + /** + * 中奖用户 + * @param lotteryTime + * @param activityId + * @return + */ + @At + @ApiOperation("小程序获取中奖用户") + public Result prizeUsers(String lotteryTime, String activityId, String searchKeyword) { + Cnd cnd = Cnd.NEW(); + cnd.andEX("activityId", "=", activityId); + cnd.andEX("awardName", "=", lotteryTime); + if (StrUtil.isNotBlank(searchKeyword)) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.orLike("username", searchKeyword); + seg.orLike("loginName", searchKeyword); + cnd.and(seg); + } + cnd.and("isRead", "=", true); + List awardUserList = fitnessWalkCommonService.dao().query(FitnessWalkAwardUser.class, cnd); + return Result.success(awardUserList); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkActivity.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkActivity.java new file mode 100644 index 00000000..6b4823de --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkActivity.java @@ -0,0 +1,235 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.model; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +@Data +public class FitnessWalkActivity { + + @ApiModelProperty(value = "小程序活动Id") + private String _id; + // 主活动名称 + @ApiModelProperty(value = "主活动名称") + private String masterActivityName; + // 分支活动名称 + @ApiModelProperty(value = "分支活动名称") + private String branchActivityName; + // 活动地址 + @ApiModelProperty(value = "活动地址") + private String address; + + @ApiModelProperty(value = "活动礼品") + private String giftName; + + @ApiModelProperty(value = "活动分组Id") + private String groupId; + + @ApiModelProperty(value = "创建分工会Id") + private String unionId; + + @ApiModelProperty(value = "活动模式") + private String activityModel; + + @ApiModelProperty(value = "活动报名时间范围,时间戳模式") + private Long[] applyTime; + + @ApiModelProperty(value = "活动报名开始时间") + private Long applyStartTime; + + @ApiModelProperty(value = "活动报名结束时间") + private Long applyEndTime; + + @ApiModelProperty(value = "活动时间范围,时间戳模式") + private Long[] time; + + @ApiModelProperty(value = "活动开始时间") + private Long startTime; + + @ApiModelProperty(value = "活动结束时间") + private Long endTime; + + @ApiModelProperty(value = "活动描述") + private String note; + + @ApiModelProperty(value = "活动封面") + private String cover; + + @ApiModelProperty(value = "活动临时封面") + private String tempCover; + + @ApiModelProperty(value = "是否需要答题") + private Boolean isQuestion; + + @ApiModelProperty(value = "答题活动Id") + private String questionId; + + @ApiModelProperty(value = "步数模式") + private String speedControlMode; + + //打卡完成之后 gift_voucher:礼品券 cert:完赛证书 null啥也不干 + @ApiModelProperty(value = "打卡完成之后操作") + private String punchFinishAfter; + + //完赛证书 + @ApiModelProperty(value = "完赛证书") + private String completionCertificateCover; + + //完赛证书临时url + @ApiModelProperty(value = "完赛证书临时url") + private String tempCompletionCertificateCover; + + //是否抽奖 + @ApiModelProperty(value = "是否抽奖") + private Boolean isLottery; + + //打卡模式奖品列表 + @ApiModelProperty(value = "打卡完成之后抽奖信息") + private List punchLotteryPrizes; + + @ApiModelProperty(value = "是否显示礼品券") + private Boolean showGiftTicket; + + @ApiModelProperty(value = "知识卡的图片") + private List pts; + + @ApiModelProperty(value = "打开点位,线路") + private List linePoints; + + @ApiModelProperty(value = "打开点位,线路2") + private List linePoints2; + + //是否按顺序签到 + @ApiModelProperty(value = "是否按顺序签到") + private Boolean isOrderSignIn; + + //是否多条线路 + @ApiModelProperty(value = "是否多条线路") + private Boolean isMultipleLines; + + //抽奖模式 none无 everyday每天 monthly每月 custom自定义 + @ApiModelProperty(value = "抽奖模式") + private String lotteryMode; + + //每月抽奖模式抽奖时间 + @ApiModelProperty(value = "每月抽奖模式抽奖时间") + private List everyMonthLotteryTime; + + @ApiModelProperty(value = "自定义模式抽奖抽奖时间规则") + private List customLotteryRules; + + @ApiModelProperty(value = "每日模式抽奖抽奖时间规则") + private DayLotteryRule dayLotteryRule; + + @ApiModelProperty(value = "随机图片数组") + private List randomPics; + + @ApiModelProperty(value = "模板随机图片数组") + private List templateRandomPics; + + @ApiModelProperty(value = "外链地址") + private String externalLinkAddress; + + @ApiModelProperty(value = "是否开启距离限制") + private Boolean enableDistance; + + @ApiModelProperty(value = "签到几个点位算完成") + private Integer finishPointNum; + + @ApiModelProperty(value = "是否自动抽奖") + private Boolean isAutoLottery; + + @ApiModelProperty(value = "手动抽奖,抽奖资格天数") + private Integer lotteryQualificationDays; + + @ApiModelProperty(value = "手动抽奖,抽奖资格步数") + private Integer lotteryQualificationSteps; + + @ApiModelProperty(value = "是否启用积分") + private Boolean isPoints; + + @ApiModelProperty(value = "达标获得积分") + private Integer lotteryQualificationPoints; + + @ApiModelProperty(value = "额外积分的达标步数") + private Integer otherSteps; + + @ApiModelProperty(value = "根据额外步数来计算的额外积分") + private Integer otherPoints; + + @ApiModelProperty(value = "封顶积分") + private Integer maxPoints; + + @Data + public static class Point implements Serializable { + private String type; + private Double[] coordinates; + } + + @Data + public static class Pts implements Serializable { + private int code; + private String name; + private int interval; + private List issueIds; + private Point location; + private int radius; + private String tip; + } + + /** + * 自定义抽奖规则 + */ + @Data + public static class CustomLotteryRule implements Serializable { + //抽奖时间 + private Date lotteryTime; + //抽奖从那天开始计算 + private Date startDate; + //抽奖截至到哪天 + private Date endDate; + //奖项名称 + private String awardName; + //抽奖人数 + private Integer lotteryUserNum; + //抽奖资格步数 + private Integer lotteryQualificationStep; + //抽奖资格天数 + private Integer lotteryQualificationDay; + } + + /** + * 每日抽奖规则 + */ + @Data + public static class DayLotteryRule implements Serializable { + //抽奖资格步数 + private Integer lotteryQualificationStep; + //抽奖资格天数 + private Integer lotteryQualificationDay; + //抽奖人数 + private Integer lotteryUserNum; + //是否可以重复抽奖 + private Boolean repeatLottery; + //是否可以增加抽奖机会 + private Boolean addLotteryChance; + //每日抽奖模式抽奖时间 + private String everyDayLotteryTime; + } + + /** + * 打卡抽奖奖品列表 + */ + @Data + public static class PunchLotteryPrize implements Serializable{ + private String name; + private String value; + private String url; + //份数 + private String num; + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkAwardUser.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkAwardUser.java new file mode 100644 index 00000000..20c86852 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkAwardUser.java @@ -0,0 +1,101 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.util.Date; + +@Data +@Table +@EqualsAndHashCode(callSuper = true) +public class FitnessWalkAwardUser extends BaseModel { + + @Column + @Name + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR) + @Comment("活动") + private String activityId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("用户Id") + private String userId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("工号") + private String loginName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("姓名") + private String username; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("奖项名称") + private String awardName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("工会id") + private String unionId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 50) + @Comment("工会名称") + private String unionName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("单位id") + private String unitId; + + @Column + @ColDefine(type = ColType.INT) + @Comment("达标天数") + private Integer standardsDays; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 20) + @Comment("中奖步数") + private String awardSteps; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 50) + @Comment("单位名称") + private String unitName; + + @Column + @ColDefine(type = ColType.DATETIME) + @Comment("中奖时间") + private Date applyDate; + + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("是否已读") + private Boolean isRead; + + @Column + @ColDefine(type = ColType.DATE) + @Comment("开始时间") + private Date startDate; + + @Column + @ColDefine(type = ColType.DATE) + @Comment("结束时间") + private Date endDate; + + @Column + @ColDefine(type = ColType.INT) + @Comment("积分") + private Integer points; +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkPunchLottery.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkPunchLottery.java new file mode 100644 index 00000000..bfaac069 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkPunchLottery.java @@ -0,0 +1,78 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.util.Date; + +@EqualsAndHashCode(callSuper = true) +@Table +@Data +@Comment("打卡模式抽奖记录") +public class FitnessWalkPunchLottery extends BaseModel { + + @Column + @Name + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("活动Id") + private String activityId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("用户Id") + private String userId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 50) + @Comment("用户工号") + private String loginName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 50) + @Comment("中奖用户") + private String userName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 20) + @Comment("奖品名称") + private String prizeName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("奖品") + private String prizeId; + + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("是否中奖") + private Boolean isWin; + + @Column + @ColDefine(type = ColType.DATETIME) + @Comment("中奖时间") + private Date winDate; + + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("是否已读") + private Boolean isRead; + + @Column + @ColDefine(type = ColType.DATETIME) + @Comment("兑奖时间") + private Date exchangeDate; + + + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("是否兑换") + private Boolean isExchange; +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkRaffleRules.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkRaffleRules.java new file mode 100644 index 00000000..4898652f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkRaffleRules.java @@ -0,0 +1,55 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serializable; +import java.util.List; + +/** + * @version 1.0 + * @Author zzr + * @name:FitenssWalkRaffleRules + * @Date 2024/12/28 10:05 + * @注释 + */ +@Data +@Table +@EqualsAndHashCode(callSuper = true) +public class FitnessWalkRaffleRules extends BaseModel { + + @Column + @Name + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR) + @Comment("活动id") + private String activityId; + + @Column + @ColDefine(type = ColType.MYSQL_JSON) + @Comment("手动抽奖规则") + private List manualLotteryRules; + + @Data + public static class ManualLotteryRules implements Serializable { + // 奖项名称 + private String awardName; + // 奖项积分 + private Integer points; + // 抽奖人数 + private Integer lotteryUserNum; + // 抽奖类型 + private String raffleType; + // 排名位次 + private Integer rankingPosition; + // 是否兼得 + private Boolean isSimultaneously; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkRaffleUser.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkRaffleUser.java new file mode 100644 index 00000000..19e92103 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkRaffleUser.java @@ -0,0 +1,61 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +/** + * @version 1.0 + * @Author zzr + * @name:FitnessWalkRaffleUser + * @Date 2024/12/28 17:10 + * @注释 + */ +@Data +@Table +@EqualsAndHashCode(callSuper = true) +public class FitnessWalkRaffleUser extends BaseModel { + + @Column + @Name + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("活动id") + private String activityId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("用户id") + private String userId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 50) + @Comment("用户工号") + private String loginName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 50) + @Comment("用户姓名") + private String username; + + @Column + @ColDefine(type = ColType.INT) + @Comment("达标天数") + private Integer standardsDays; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 20) + @Comment("中奖步数") + private String awardSteps; + + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("是否已抽奖") + private Boolean isRaffle; +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkStep.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkStep.java new file mode 100644 index 00000000..a941f73c --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/model/FitnessWalkStep.java @@ -0,0 +1,50 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serializable; +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +//@Table("fitness_walk_step_${month}") +@Table +public class FitnessWalkStep extends BaseModel implements Serializable { + + private static final long serialVersionUID = 1L; + + @Column + @Name + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR) + @Comment("活动id") + private String activityId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("姓名Id") + private String userId; + + @Column + @ColDefine(customType = "int") + @Comment("步数") + private Integer step; + + @Column + @ColDefine(type = ColType.INT) + @Comment("积分") + private Integer points; + + @Column + @ColDefine(type = ColType.DATE) + @Comment("时间") + private Date applyDate; +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/FitnessWalkCommonService.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/FitnessWalkCommonService.java new file mode 100644 index 00000000..30e03419 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/FitnessWalkCommonService.java @@ -0,0 +1,86 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.service; + +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.activity.fitnesswalk.contants.Cascader; +import com.budwk.app.zhgh.activity.fitnesswalk.contants.FitnessWalkMode; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkActivity; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkAwardUser; +import org.nutz.lang.util.NutMap; + +import java.util.List; + +public interface FitnessWalkCommonService extends BaseService { + + //活动缓存时间 + int CACHE_TIME = 7200; + + /** + * 活动,从Redis中取 + * + * @param activityId 活动id + * @return + */ + FitnessWalkActivity getActivity(String activityId); + + + /** + * 获取所有活动 + * + * @return + */ + List getAllActivity(); + + /** + * 级联活动 + */ + List cascaderActivity(int year, FitnessWalkMode mode); + + + /** + * 添加活动或修改活动,存放至redis + * + * @param activity 活动 + */ + void addOrEditDoSaveRedis(FitnessWalkActivity activity); + + + /** + * 健身走抽奖模式添加定时抽奖任务 + * + * @param fitnessWalkActivity 活动 + */ + void addLotteryTask(FitnessWalkActivity fitnessWalkActivity); + + + /** + * 获取步数排行榜 + * + * @param activityId 活动id + * @param unionId 工会id + * @param unitId 单位id + * @param mode today all + * @return + */ + Pagination getStepRankingPagination(PageForm pageForm, String activityId, String unionId, String unitId, String mode); + + List getStepRankingList(String searchName, String searchKeyword, String activityId, String unionId, String unitId, String mode); + + + /** + * 获取中奖榜 + * + * @param activityId 活动id + * @return + */ + List getWiningRankingUserList(String activityId); + + /** + * 中奖奖项列表 + * @param activityId + * @return + */ + List prizeOption(String activityId); + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/FitnessWalkPunchStatisticsService.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/FitnessWalkPunchStatisticsService.java new file mode 100644 index 00000000..8e626fad --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/FitnessWalkPunchStatisticsService.java @@ -0,0 +1,20 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.service; + +import cn.hutool.json.JSONObject; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkAwardUser; +import org.nutz.lang.util.NutMap; + +import java.util.List; + +public interface FitnessWalkPunchStatisticsService extends BaseService { + + List unionRegCheckInNum(String activityId, String unionId); + + List unionRegistrationData(String activityId, String unionId); + + List unionCheckInData(String activityId, String unionId); + + List exportNotGetGiftVoucherUsers(String activityId); + List exportNotUseGiftVoucherUsers(String activityId); +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/FitnessWalkStepRaffleService.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/FitnessWalkStepRaffleService.java new file mode 100644 index 00000000..f3d24fbc --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/FitnessWalkStepRaffleService.java @@ -0,0 +1,34 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.service; + +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkRaffleRules; +import org.nutz.dao.sql.Sql; +import org.nutz.lang.util.NutMap; + +import java.util.List; + +/** + * @version 1.0 + * @Author zzr + * @name:FitnessWalkStepRaffleService + * @Date 2024/12/28 11:13 + * @注释 + */ +public interface FitnessWalkStepRaffleService extends BaseService { + + Sql getRaffleSql(PageForm pageForm, String activityId, String unionId, String unitId); + + /** + * 获取活动的奖项 + * @param activityId + * @return + */ + List getActivityAwardList(String activityId); + + /** + * 手动抽奖 + * @param activityId 活动id + */ + void manualLottery(String activityId); +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/impl/FitnessWalkCommonServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/impl/FitnessWalkCommonServiceImpl.java new file mode 100644 index 00000000..3384be2b --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/impl/FitnessWalkCommonServiceImpl.java @@ -0,0 +1,492 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.exception.BaseException; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.sys.models.Sys_task; +import com.budwk.app.sys.services.SysTaskService; +import com.budwk.app.task.services.TaskPlatformService; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.fitnesswalk.contants.Cascader; +import com.budwk.app.zhgh.activity.fitnesswalk.contants.FitnessWalkMode; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkActivity; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkAwardUser; +import com.budwk.app.zhgh.activity.fitnesswalk.service.FitnessWalkCommonService; +import com.budwk.app.zhgh.activity.fitnesswalk.utils.WeAppCloudUtil; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.Static; +import org.nutz.integration.jedis.RedisService; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.json.Json; +import org.nutz.lang.Lang; +import org.nutz.lang.Strings; +import org.nutz.lang.random.R; +import org.nutz.lang.util.NutMap; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; + +@IocBean(args = {"refer:dao"}) +public class FitnessWalkCommonServiceImpl extends BaseServiceImpl implements FitnessWalkCommonService { + + @Inject + private RedisService redisService; + + @Inject + private WeAppCloudUtil weAppCloudUtil; + + @Inject + private SysTaskService sysTaskService; + + @Inject + private TaskPlatformService taskPlatformService; + + + public FitnessWalkCommonServiceImpl(Dao dao) { + super(dao); + } + + + /** + * 活动,从Redis中取 + * + * @param activityId 活动id + * @return + */ + @Override + public FitnessWalkActivity getActivity(String activityId) { + if (StrUtil.isBlank(activityId)) { + throw new BaseException("请传递活动"); + } + String redisKey = "FitnessWalk:" + activityId; + Boolean exists = redisService.exists("FitnessWalk:" + activityId); + FitnessWalkActivity activity = null; + exists = false; + if (exists) { + String string = redisService.get(redisKey); + activity = JSONUtil.toBean(string, FitnessWalkActivity.class); + if (Lang.isNotEmpty(activity.getRandomPics())) { + List urlStr = new ArrayList<>(); + for (String url : activity.getRandomPics()) { + String tempUrl = weAppCloudUtil.httpFile(url); + urlStr.add(tempUrl); + } + activity.setTemplateRandomPics(urlStr); + redisService.set(redisKey, JSONUtil.toJsonStr(activity)); + } + + if (Strings.isNotBlank(activity.getCover())) { + String tempUrl = weAppCloudUtil.httpFile(activity.getCover()); + activity.setTempCover(tempUrl); + } + + if(Strings.isNotBlank(activity.getCompletionCertificateCover())){ + String tempUrl = weAppCloudUtil.httpFile(activity.getCompletionCertificateCover()); + activity.setTempCompletionCertificateCover(tempUrl); + } + + } else { + StringBuilder sql = new StringBuilder(); + sql.append("db.collection('activity').doc('").append(activityId).append("').get()"); + try { + JSONObject jsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.QUERY, sql.toString()); + activity = jsonObject.getJSONArray("data").stream() + .map(v -> JSONUtil.toBean((String) v, FitnessWalkActivity.class)) + .findFirst().orElse(null); + if (Lang.isNotEmpty(activity.getRandomPics())) { + List urlStr = new ArrayList<>(); + for (String url : activity.getRandomPics()) { + String tempUrl = weAppCloudUtil.httpFile(url); + urlStr.add(tempUrl); + } + activity.setTemplateRandomPics(urlStr); + } + if (Strings.isNotBlank(activity.getCover())) { + String tempCover = weAppCloudUtil.httpFile(activity.getCover()); + activity.setTempCover(tempCover); + } + + if(Strings.isNotBlank(activity.getCompletionCertificateCover())){ + String tempUrl = weAppCloudUtil.httpFile(activity.getCompletionCertificateCover()); + activity.setTempCompletionCertificateCover(tempUrl); + } + + redisService.setex(redisKey, CACHE_TIME, JSONUtil.toJsonStr(activity)); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("获取数据异常!"); + } + } + + if (AuthUtil.hasRoleOr(RoleConstant.BRANCH_UNION_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_OPERATOR.name(), RoleConstant.BRANCH_UNION_ADMIN.name()) + && !AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + return SecurityUtil.getUnionId().equals(activity.getUnionId()) ? activity : null; + } + return activity; + } + + + @Override + public List getAllActivity() { + List fitnessWalkActivities; + if (redisService.exists("FitnessWalk:ActivityList")) { + String dataString = redisService.get("FitnessWalk:ActivityList"); + fitnessWalkActivities = JSONUtil.toList(dataString, FitnessWalkActivity.class); + } else { + StringBuilder sql = new StringBuilder(); + sql.append("db.collection('activity').field({") + .append("masterActivityName:true,") + .append("branchActivityName:true,") + .append("activityModel:true,") + .append("endTime:true,") + .append("startTime:true,") + .append("unionId:true") + .append("}).orderBy('startTime', 'desc').get()"); + JSONObject jsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.QUERY, sql.toString()); + fitnessWalkActivities = jsonObject.getJSONArray("data").stream() + .map(v -> JSONUtil.toBean((String) v, FitnessWalkActivity.class)).collect(Collectors.toList()); + } + + if (AuthUtil.hasRoleOr(RoleConstant.BRANCH_UNION_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_OPERATOR.name(), RoleConstant.BRANCH_UNION_ADMIN.name()) + && !AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + fitnessWalkActivities = fitnessWalkActivities.stream() + .filter(v -> SecurityUtil.getUnionId().equals(v.getUnionId())) + .collect(Collectors.toList()); + } + redisService.set("FitnessWalk:ActivityList", JSONUtil.toJsonStr(fitnessWalkActivities)); + return fitnessWalkActivities; + } + + + @Override + public List cascaderActivity(int year, FitnessWalkMode mode) { + + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.YEAR, year); + + long startTs = DateUtil.beginOfYear(calendar.getTime()).getTime(); + long endTs = DateUtil.endOfYear(calendar.getTime()).getTime(); + + List cascaders = this.getAllActivity().stream() + .filter(v -> v.getActivityModel().equals(mode.getValue()) && v.getStartTime() >= startTs && v.getStartTime() <= endTs) + .collect(Collectors.groupingBy(FitnessWalkActivity::getMasterActivityName)) + .entrySet().stream() + .map(entry -> { + Cascader cascader = new Cascader(); + cascader.setValue(entry.getValue().stream().findFirst().map(FitnessWalkActivity::get_id).orElse(null)); + cascader.setLabel(entry.getKey()); + if (entry.getValue().size() > 1) { + List children = entry.getValue().stream().map(z -> { + Cascader cascader2 = new Cascader(); + cascader2.setLabel(z.getBranchActivityName()); + cascader2.setValue(z.get_id()); + return cascader2; + }).collect(Collectors.toList()); + cascader.setChildren(children); + } + return cascader; + }) + .collect(Collectors.toList()); + + return cascaders; + } + + @Override + public void addOrEditDoSaveRedis(FitnessWalkActivity activity) { + redisService.del("FitnessWalk:" + activity.get_id()); + redisService.del("FitnessWalk:ActivityList"); + redisService.set("FitnessWalk:" + activity.get_id(), JSONUtil.toJsonStr(activity)); + } + + @Override + public void addLotteryTask(FitnessWalkActivity fitnessWalkActivity) { + //删除和该活动关联的定时任务 + List oldTasks = sysTaskService.dao().query(Sys_task.class, Cnd.where("data", "like", "%" + fitnessWalkActivity.get_id() + "%")); + for (Sys_task task : oldTasks) { + taskPlatformService.delete(task.getId(), task.getId()); + sysTaskService.delete(task.getId()); + } + + + if ("everyday".equals(fitnessWalkActivity.getLotteryMode())) { + FitnessWalkActivity.DayLotteryRule dayLotteryRule = fitnessWalkActivity.getDayLotteryRule(); + if (Lang.isNotEmpty(dayLotteryRule)) { + //每日抽奖时间 + String lotteryTime = dayLotteryRule.getEveryDayLotteryTime(); + SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss"); + Date timeDate = null; + try { + timeDate = timeFormat.parse(lotteryTime); + } catch (ParseException e) { + throw new RuntimeException(e); + } + String cron = timeDate.getSeconds() + " " + timeDate.getMinutes() + " " + timeDate.getHours() + " * * ?"; + try { + List cronExeTimes = taskPlatformService.getCronExeTimesPlus(cron); + + if (CollectionUtil.isNotEmpty(cronExeTimes)) { + //调用类 + String jobClass = "io.v.nutz.task.job.fitnessWalk.FitnessWalkLotteryJob"; + HashMap map = new HashMap<>(5); + map.put("id", fitnessWalkActivity.get_id()); + // 唯一标识的删除id,用于执行定时任务完成后,将此定时任务禁用 + map.put("deleteId", R.UU32()); + //每天抽奖达标步数 + map.put("lotteryQualificationStep", dayLotteryRule.getLotteryQualificationStep().toString()); + //每天抽奖人数 + map.put("lotteryUserNum", dayLotteryRule.getLotteryUserNum().toString()); + //抽奖模式 + map.put("mode", "everyday"); + + // 设置定时任务 + Sys_task task = new Sys_task(); + task.setName(fitnessWalkActivity.getMasterActivityName() + "健步走计步模式每日抽奖任务"); + task.setJobClass(jobClass); + task.setNote("健步走计步模式每日抽奖任务"); + task.setCron(cron); + task.setData(Json.toJson(map)); + task.setDisabled(false); + sysTaskService.insert(task); + taskPlatformService.add(task.getId(), task.getId(), task.getJobClass(), task.getCron(), task.getNote(), task.getData()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } else if ("custom".equals(fitnessWalkActivity.getLotteryMode())) { + List customLotteryRules = fitnessWalkActivity.getCustomLotteryRules(); + customLotteryRules.removeIf(Lang::isEmpty); + + for (FitnessWalkActivity.CustomLotteryRule rule : customLotteryRules) { + Date lotteryTime = rule.getLotteryTime(); + SimpleDateFormat dateFormatCron = new SimpleDateFormat("ss mm HH dd MM ? yyyy"); + // 设置定时任务执行时间 + String cron = dateFormatCron.format(lotteryTime); + try { + //调用类 + String jobClass = "io.v.nutz.task.job.fitnessWalk.FitnessWalkLotteryJob"; + HashMap map = new HashMap<>(8); + map.put("id", fitnessWalkActivity.get_id()); + // 唯一标识的删除id,用于执行定时任务完成后,将此定时任务禁用 + map.put("deleteId", R.UU32()); + //月抽奖达标步数 + map.put("lotteryQualificationStep", rule.getLotteryQualificationStep().toString()); + //月抽奖人数 + map.put("lotteryUserNum", rule.getLotteryUserNum().toString()); + //查询开始时间 + map.put("startDate", rule.getStartDate()); + //查询结束时间 + map.put("endDate", rule.getEndDate()); + //抽奖天数 + map.put("lotteryQualificationDay", rule.getLotteryQualificationDay()); + //获奖名称 + map.put("awardName", rule.getAwardName()); + //抽奖模式 + map.put("mode", "custom"); + + Sys_task task = new Sys_task(); + task.setName(fitnessWalkActivity.getMasterActivityName() + "健步走计步模式自定义抽奖任务"); + task.setJobClass(jobClass); + task.setNote("健步走计步模式自定义抽奖任务"); + task.setCron(cron); + task.setData(Json.toJson(map)); + task.setDisabled(false); + sysTaskService.insert(task); + taskPlatformService.add(task.getId(), task.getId(), task.getJobClass(), task.getCron(), task.getNote(), task.getData()); + } catch (Exception e) { + e.printStackTrace(); + return; + } + } + } + } + + + @Override + public Pagination getStepRankingPagination(PageForm pageForm, String activityId, String unionId, String unitId, String mode) { + Sql sql = rankingListSql(pageForm.getSearchName(), pageForm.getSearchKeyword(), activityId, unionId, unitId, mode); + return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + } + + @Override + public List getStepRankingList(String searchName, String searchKeyword, String activityId, String unionId, String unitId, String mode) { + Sql sql = rankingListSql(searchName, searchKeyword, activityId, unionId, unitId, mode); + return listMap(sql); + } + + + /** + * 获取中奖榜 + * + * @param activityId 活动id + * @return + */ + @Override + public List getWiningRankingUserList(String activityId) { + FitnessWalkActivity activity = getActivity(activityId); + List resultMapList = new ArrayList<>(); + if ("everyday".equals(activity.getLotteryMode())) { + String lastDayFormat = DateUtil.format(DateUtil.offsetDay(new Date(), -1), "yyyy-MM-dd"); + List awardUserList = dao().query(FitnessWalkAwardUser.class, Cnd.where("activityId", "=", activityId) + .and("DATE( applyDate )", ">=", lastDayFormat)); + + //昨天的中奖榜 + List lastDayAwardUserList = awardUserList.stream().filter(v -> DateUtil.compare(v.getApplyDate(), + DateUtil.offsetDay(new Date(), -1), "yyyy-MM-dd") == 0).collect(Collectors.toList()); + NutMap lastDayAwardMap = new NutMap(); + //昨日中奖时间 + lastDayAwardMap.put("title", "昨日中奖榜"); + lastDayAwardMap.put("lotteryTime", lastDayFormat); + lastDayAwardMap.put("awardName", "幸运奖"); + lastDayAwardMap.put("awardList", lastDayAwardUserList); + resultMapList.add(lastDayAwardMap); + + //今天的中奖榜 + List thisDayAwardUserList = (List) CollectionUtil.subtract(awardUserList, lastDayAwardUserList); + NutMap thisDayAwardMap = new NutMap(); + //今日中奖时间 + lastDayAwardMap.put("title", "今日中奖榜"); + thisDayAwardMap.put("lotteryTime", DateUtil.today()); + thisDayAwardMap.put("awardName", "幸运奖"); + thisDayAwardMap.put("awardList", thisDayAwardUserList); + resultMapList.add(thisDayAwardMap); + + } else if ("custom".equals(activity.getLotteryMode())) { + List customLotteryRules = activity.getCustomLotteryRules(); + //当前活动中奖榜单 + List awardUserList = dao().query(FitnessWalkAwardUser.class, Cnd.where("activityId", "=", activityId)); + + for (FitnessWalkActivity.CustomLotteryRule rule : customLotteryRules) { + NutMap map = new NutMap(); + List customAwardList = awardUserList.stream().filter(v -> DateUtil.compare(v.getApplyDate(), DateUtil.date(rule.getLotteryTime()), "yyyy-MM-dd") == 0).collect(Collectors.toList()); + //自定义抽奖时间范围 + map.put("title", DateUtil.format(DateUtil.date(rule.getStartDate()), "MM-dd") + "至" + DateUtil.format(DateUtil.date(rule.getEndDate()), "MM-dd") + rule.getAwardName() + "中奖榜"); +// map.put("customTimeRange", DateUtil.format(DateUtil.date(rule.getStartDate()), "yyyy-MM-dd") + "——" + DateUtil.format(DateUtil.date(rule.getEndDate()), "yyyy-MM-dd")); + //抽奖时间 + map.put("lotteryTime", DateUtil.format(rule.getLotteryTime(), "yyyy-MM-dd")); + //奖项名称 + map.put("awardName", rule.getAwardName()); + //中奖人员 + map.put("awardList", customAwardList); + resultMapList.add(map); + } + } + return resultMapList; + } + + @Override + public List prizeOption(String activityId) { + List list = dao().query(FitnessWalkAwardUser.class, + Cnd.where("activityId", "=", activityId).groupBy("awardName").asc("awardName")); + + List collect = list.stream().map(v -> { + NutMap map = new NutMap(); + map.put("text", v.getAwardName()); + map.put("value", v.getAwardName()); + return map; + }).collect(Collectors.toList()); + + +// FitnessWalkActivity activity = getActivity(activityId); +// if ("custom".equals(activity.getLotteryMode())) { +// List customLotteryRules = activity.getCustomLotteryRules(); +// return customLotteryRules.stream().map(rule -> { +// NutMap map = new NutMap(); +// map.put("text", DateUtil.format(DateUtil.date(rule.getStartDate()), "MM-dd") + "至" + DateUtil.format(DateUtil.date(rule.getEndDate()), "MM-dd") + rule.getAwardName() + "中奖榜"); +// map.put("value", rule.getLotteryTime()); +// return map; +// }).collect(Collectors.toList()); +// } + return collect; + } + + + private Sql rankingListSql(String searchName, String searchKeyword, String activityId, String unionId, String unitId, String mode) { + FitnessWalkActivity activity = getActivity(activityId); + Cnd cnd = Cnd.NEW(); + + Sql sql = Sqls.create(""" + SELECT + u.id, + COALESCE(SUM(sub.step), 0) AS total_steps, + u.username, + u.loginname, + u.unionName, + u.unitName, + over3k.standardsDays + FROM + `vw_user` u + LEFT JOIN ( + SELECT + userId, + applyDate, + step + FROM + `fitness_walk_step` + WHERE + step >= @step + AND activityId=@activityId + AND $dateSql + GROUP BY + userId, + applyDate + ) AS sub ON u.id = sub.userId + LEFT JOIN ( + SELECT + userId, + COUNT(DISTINCT DATE(applyDate)) AS standardsDays + FROM + `fitness_walk_step` + WHERE + step >= @step + AND activityId=@activityId + AND $dateSql + GROUP BY + userId + ) AS over3k ON u.id = over3k.userId + $condition + """).setParam("activityId",activityId).setParam("step",0); + + if ("today".equals(mode)) { + sql.setVar("dateSql",new Static("DATE(applyDate) = '"+DateUtil.today()+"'")); +// cnd.and("DATE( s.applyDate )", "=", DateUtil.today()); + } else { + sql.setVar("dateSql",new Static("DATE(applyDate) >= '" + +DateUtil.format(DateUtil.date(activity.getStartTime()), "yyyy-MM-dd")+"' and DATE(applyDate) <= '" + +DateUtil.format(DateUtil.date(activity.getEndTime()), "yyyy-MM-dd")+"'")); +// cnd.and("DATE( s.applyDate )", ">=", DateUtil.format(DateUtil.date(activity.getStartTime()), "yyyy-MM-dd")); +// cnd.and("DATE( s.applyDate )", "<=", DateUtil.format(DateUtil.date(activity.getEndTime()), "yyyy-MM-dd")); + } + + if (Strings.isNotBlank(unitId)) { + cnd.and("u.unitId", "=", unitId); + } + if (Strings.isNotBlank(unionId)) { + cnd.and("u.unionId", "=", unionId); + } + + if (Strings.isNotBlank(searchName) && Strings.isNotBlank(searchKeyword)) { + cnd.and(searchName, "LIKE", "%" + searchKeyword + "%"); + } +// cnd.and("u.id","in",Sqls.create("select userId from activity_user_scope where groupId = @groupId").setParam("groupId",activity.getGroupId())); + cnd.groupBy("u.id","u.username","u.loginname","u.unionName","u.unitName","over3k.standardsDays"); + cnd.desc("total_steps"); + cnd.having(Cnd.NEW().and("COALESCE(SUM(sub.step), 0)",">",0)); + sql.setCondition(cnd); + return sql; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/impl/FitnessWalkPunchStatisticsServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/impl/FitnessWalkPunchStatisticsServiceImpl.java new file mode 100644 index 00000000..f80351b1 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/impl/FitnessWalkPunchStatisticsServiceImpl.java @@ -0,0 +1,247 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.service.impl; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkAwardUser; +import com.budwk.app.zhgh.activity.fitnesswalk.service.FitnessWalkPunchStatisticsService; +import com.budwk.app.zhgh.activity.fitnesswalk.utils.WeAppCloudUtil; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@IocBean(args = {"refer:dao"}) +public class FitnessWalkPunchStatisticsServiceImpl extends BaseServiceImpl implements FitnessWalkPunchStatisticsService { + public FitnessWalkPunchStatisticsServiceImpl(Dao dao) { + super(dao); + } + + @Inject + private WeAppCloudUtil weAppCloudUtil; + + @Override + public List unionRegCheckInNum(String activityId, String unionId) { + List unions = dao().query(Sys_union.class, Cnd.NEW().desc("unioncode")); + //查询报名的数据 + StringBuffer regCountSql = new StringBuffer(); + regCountSql.append("db.collection('register').aggregate()"); + regCountSql.append(".match({"); + regCountSql.append("activity_id:'").append(activityId).append("'"); + if (StrUtil.isNotBlank(unionId)) { + regCountSql.append(",unionid:'").append(unionId).append("'"); + } + regCountSql.append("})"); + regCountSql.append(".group({_id:'$unionid',count:$.sum(1)}).end()"); + + JSONObject regCountJsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.AGGREGATE, regCountSql.toString()); + Map regCountData = regCountJsonObject.getJSONArray("data").stream().map(v -> { + JSONObject rowData = JSONUtil.parseObj((String) v); + String id = rowData.getStr("_id"); + int count = rowData.getJSONObject("count").getInt("$numberInt"); + return NutMap.NEW().addv("id", id).addv("count", count); + }).collect(Collectors.toMap(v -> v.getString("id"), v -> v.getInt("count"))); + + //查询打卡的数据 + StringBuffer checkInCountSql = new StringBuffer(); + checkInCountSql.append("db.collection('sign').aggregate()"); + checkInCountSql.append(".match({"); + checkInCountSql.append("activity_id:'").append(activityId).append("'"); + if (StrUtil.isNotBlank(unionId)) { + checkInCountSql.append(",unionid:'").append(unionId).append("'"); + } + checkInCountSql.append("})"); + checkInCountSql.append(".group({_id:'$unionid',count: $.addToSet('$userid')})"); + checkInCountSql.append(".project({_id: 0,unionid:'$_id',count:$.size('$count')})"); + checkInCountSql.append(".end()"); + + JSONObject checkInCountJsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.AGGREGATE, checkInCountSql.toString()); + Map checkInCountData = checkInCountJsonObject.getJSONArray("data").stream().map(v -> { + JSONObject rowData = JSONUtil.parseObj((String) v); + String id = rowData.getStr("unionid"); + int count = rowData.getJSONObject("count").getInt("$numberInt"); + return NutMap.NEW().addv("id", id).addv("count", count); + }).collect(Collectors.toMap(v -> v.getString("id"), v -> v.getInt("count"))); + + List list = unions.stream().map(v -> { + String id = v.getId(); + String unionname = v.getName(); + String unioncode = v.getUnionCode(); + + NutMap map = NutMap.NEW(); + map.put("id", id); + map.put("unionname", unionname); + map.put("unioncode", unioncode); + map.put("regCount", regCountData.getOrDefault(id, 0)); + map.put("checkInCount", checkInCountData.getOrDefault(id, 0)); + + return map; + }).collect(Collectors.toList()); + return list; + } + + @Override + public List unionRegistrationData(String activityId, String unionId) { + StringBuffer sql = new StringBuffer("db.collection('register').aggregate()"); + sql.append(".match({"); + sql.append("activity_id:'").append(activityId).append("',unionid:'").append(unionId).append("'"); + sql.append("})"); + sql.append(".addFields({register_time_date:$.toDate('$register_time')})"); + sql.append(""" + .project({ + _id:true, + loginname:true, + username:true, + unitname:true, + mobile:true, + sex:true, + register_time:true, + register_time_str: $.dateToString({ + date: '$register_time_date', + format: '%Y-%m-%d %H:%M:%S', + timezone: 'Asia/Shanghai' + }) + }) + .sort({ unitname: 1 }) + .end() + """); + + JSONObject jsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.AGGREGATE, sql.toString()); + List list = jsonObject.getJSONArray("data").stream().map(v -> JSONUtil.parseObj((String) v)).collect(Collectors.toList()); + return list; + } + + @Override + public List unionCheckInData(String activityId, String unionId) { + // 查询打卡的数据,根据分工会来 + String sql = """ + db.collection('sign').aggregate() + .match({ + activity_id: '%s', + unionid: '%s' + }) + .lookup({ + from: 'activity', + localField: 'activity_id', + foreignField: '_id', + as: 'activity' + }) + .lookup({ + from: 'gift_voucher', + let: { + signActivityId: '$activity_id', + signLoginName: '$loginname' + }, + pipeline: $.pipeline() + .match({ + $expr: { + $and: [ + { $eq: ['$activity_id', '$$signActivityId'] }, + { $eq: ['$loginname', '$$signLoginName'] } + ] + } + }) + .project({ + used: 1, + _id: 0 + }) + .done(), + as: 'gift_voucher' + }) + .addFields({ + used: { $arrayElemAt: ['$gift_voucher.used', 0] }, + masterActivityName: { $arrayElemAt: ['$activity.masterActivityName', 0] }, + pts: { $arrayElemAt: ['$activity.pts', 0] }, + }) + .group({ + _id: { + activity_id: '$activity_id', + loginname: '$loginname' + }, + loginname: { $first: '$loginname' }, + sex: { $first: '$sex' }, + username: { $first: '$username' }, + unitname: { $first: '$unitname' }, + unionname: { $first: '$unionname' }, + used: { $first: '$used' }, + sign_size: { $sum: 1 }, + masterActivityName: { $first: '$masterActivityName' }, + pts_size: { $first: { $size: '$pts' } }, + }) + .project({ + _id: 0, + loginname: 1, + sex: 1, + username: 1, + unitname: 1, + unionname: 1, + used: 1, + sign_size: { $toString: '$sign_size' }, + masterActivityName: 1, + pts_size: { $toString: '$pts_size' } + }) + .sort({ unitname: 1 }) + .end() + """; + sql = sql.formatted(activityId, unionId); + JSONObject jsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.AGGREGATE, sql); + List list = jsonObject.getJSONArray("data").stream().map(v -> { + JSONObject jo = JSONUtil.parseObj((String) v); + if (jo.getInt("sign_size") > jo.getInt("pts_size")) { + jo.put("sign_size", jo.getInt("pts_size")); + } + return jo; + }).collect(Collectors.toList()); + return list; + } + + @Override + public List exportNotGetGiftVoucherUsers(String activityId) { + //查询报名的人员 + JSONObject regJsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.AGGREGATE, """ + db.collection('register').aggregate([ + { $match: { activity_id: '%s' } } + ]) + .sort({ unitname: 1 }) + .end() + """.formatted(activityId)); + //查询打完卡获得礼品券的人员 + JSONObject giftUserJsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.AGGREGATE, """ + db.collection('gift_voucher').aggregate() + .match({ activity_id: '%s' }) + .group({ _id: '$loginname' }) + .project({ _id: 0, loginname: '$_id' }) + .end() + """.formatted(activityId)); + + List giftUserLoginNames = giftUserJsonObject.getJSONArray("data").stream().map(v -> { + JSONObject jo = JSONUtil.parseObj((String) v); + return jo.getStr("loginname"); + }).toList(); + + List list = regJsonObject.getJSONArray("data").stream() + .map(v -> JSONUtil.parseObj((String) v)) + .filter(v -> !giftUserLoginNames.contains(v.getStr("loginname"))).collect(Collectors.toList()); + return list; + } + + @Override + public List exportNotUseGiftVoucherUsers(String activityId) { + //查询未使用礼品券的人员 + JSONObject jsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.AGGREGATE, """ + db.collection('gift_voucher').aggregate() + .match({ activity_id: '%s', used: false }) + .sort({ unitname: 1 }) + .end() + """.formatted(activityId)); + return jsonObject.getJSONArray("data").stream() + .map(v -> JSONUtil.parseObj((String) v)).collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/impl/FitnessWalkStepRaffleServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/impl/FitnessWalkStepRaffleServiceImpl.java new file mode 100644 index 00000000..13e9be54 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/service/impl/FitnessWalkStepRaffleServiceImpl.java @@ -0,0 +1,360 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.service.impl; + +import cn.hutool.core.date.DateUtil; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkActivity; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkAwardUser; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkRaffleRules; +import com.budwk.app.zhgh.activity.fitnesswalk.model.FitnessWalkRaffleUser; +import com.budwk.app.zhgh.activity.fitnesswalk.service.FitnessWalkCommonService; +import com.budwk.app.zhgh.activity.fitnesswalk.service.FitnessWalkStepRaffleService; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.dao.util.cri.Static; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.lang.random.R; +import org.nutz.lang.util.NutMap; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * @version 1.0 + * @Author zzr + * @name:FitnessWalkStepRaffleServiceImpl + * @Date 2024/12/28 11:17 + * @注释 + */ +@IocBean(args = {"refer:dao"}) +public class FitnessWalkStepRaffleServiceImpl extends BaseServiceImpl implements FitnessWalkStepRaffleService { + public FitnessWalkStepRaffleServiceImpl(Dao dao) { + super(dao); + } + + @Inject + private FitnessWalkCommonService fitnessWalkCommonService; + + /** + * 获取可抽奖用户,那就是达标用户 + * @param pageForm + * @param activityId + * @param unionId + * @param unitId + * @return + */ + @Override + public Sql getRaffleSql(PageForm pageForm, String activityId, String unionId, String unitId) { + FitnessWalkActivity activity = fitnessWalkCommonService.getActivity(activityId); + + Integer lotteryQualificationDays = activity.getLotteryQualificationDays(); + Integer lotteryQualificationSteps = activity.getLotteryQualificationSteps(); + Date startDate = DateUtil.parse(DateUtil.format(DateUtil.date(activity.getStartTime()), "yyyy-MM-dd"), "yyyy-MM-dd"); + Date endDate = DateUtil.parse(DateUtil.format(DateUtil.date(activity.getEndTime()), "yyyy-MM-dd"), "yyyy-MM-dd"); + + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(""" + SELECT + u.id, + COALESCE(SUM(sub.step), 0) AS total_steps, + u.loginname, + u.username, + u.unionId, + u.unionName, + u.unitId, + u.unitName, + over3k.standardsDays + FROM + `vw_user` u + LEFT JOIN ( + SELECT + userId, + applyDate, + step + FROM + `fitness_walk_step` + WHERE + activityId = @activityId + AND DATE(applyDate) >= @startDate + AND DATE(applyDate) <= @endDate + $lotteryQualificationDaySql + GROUP BY + userId, + applyDate + ) AS sub ON u.id = sub.userId + LEFT JOIN ( + SELECT + userId, + COUNT(DISTINCT DATE(applyDate)) AS standardsDays + FROM + `fitness_walk_step` + WHERE + activityId = @activityId + AND DATE(applyDate) >= @startDate + AND DATE(applyDate) <= @endDate + $lotteryQualificationDaySql + GROUP BY + userId + ) AS over3k ON u.id = over3k.userId + $condition + """); + if (lotteryQualificationDays != null) { + sql.setVar("lotteryQualificationDaySql", new Static(" AND step >= '%s' ".formatted(lotteryQualificationSteps))); + cnd.having(cnd.and(new Static(" over3k.standardsDays >= '%s' ".formatted(lotteryQualificationDays)))); + +// sql.setVar("stepHavingSql", new Static(" over3k.standardsDays >= '%s' ".formatted(lotteryQualificationDays))); + } else { + cnd.having(cnd.and(new Static(" COALESCE(SUM(sub.step), 0) >= '%s' ".formatted(lotteryQualificationSteps)))); +// sql.setVar("stepHavingSql", new Static(" COALESCE(SUM(sub.step), 0) >= '%s' ".formatted(lotteryQualificationSteps))); + } + sql.setParam("activityId", activityId); + sql.setParam("step", lotteryQualificationSteps); + sql.setParam("startDate", startDate); + sql.setParam("endDate", endDate); + + if (Strings.isNotBlank(unitId)) { + cnd.and("u.unitId", "=", unitId); + } + if (Strings.isNotBlank(unionId)) { + cnd.and("u.unionId", "=", unionId); + } + + if (pageForm != null && Strings.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.orLike("u.loginname", pageForm.getSearchKeyword()); + seg.orLike("u.username", pageForm.getSearchKeyword()); + cnd.and(seg); + } +// cnd.and("u.id","in",Sqls.create("select userId from activity_user_scope where groupId = @groupId").setParam("groupId",activity.getGroupId())); + cnd.groupBy("u.id", "u.username", "u.loginname", "u.unionName", "u.unitName"); + cnd.desc("total_steps"); + sql.setCondition(cnd); + return sql; + } + + + /** + * 获取活动的奖项,然后再将奖项去遍历出来 + * @param activityId + * @return { index: 0, name: '奖项名称', type: 0 } + */ + @Override + public List getActivityAwardList(String activityId) { + FitnessWalkRaffleRules rules = fetch(Cnd.where("activityId", "=", activityId)); + List manualLotteryRules = rules.getManualLotteryRules(); + // 存放奖品列表 + List ruleList = new ArrayList<>(); + // 奖品数量 + int size = manualLotteryRules.size(); + if (size == 1) { + String prize = manualLotteryRules.get(0).getAwardName(); + for (int i = 0; i < 8; i++) { + ruleList.add(prize); + if (ruleList.size() < 8) { + ruleList.add("没有中奖"); + } + } + } else if (size == 2) { + for (int i = 0; i < 8; i++) { + String prize = manualLotteryRules.get(i % size).getAwardName(); + ruleList.add(prize); + if (ruleList.size() < 8) { + ruleList.add("没有中奖"); + } + } + } else if (size == 3) { + for (int i = 0; i < 8; ) { + for (int j = 0; j < size && i < 8; j++) { + String prize = manualLotteryRules.get(j).getAwardName(); + ruleList.add(prize); + if (ruleList.size() < 8) { + ruleList.add("没有中奖"); + i += 2; + } + } + } + } else if (size == 4) { + for (int i = 0; i < 8; ) { + for (int j = 0; j < size && i < 8; j++) { + String prize = manualLotteryRules.get(j).getAwardName(); + ruleList.add(prize); + if (ruleList.size() < 8) { + ruleList.add("没有中奖"); + i += 2; + } + } + } + } else if (size == 5) { + ruleList = manualLotteryRules.stream().map(FitnessWalkRaffleRules.ManualLotteryRules::getAwardName).collect(Collectors.toList()); + ruleList.add(2, "没有中奖"); + ruleList.add(4, "没有中奖"); + ruleList.add(7, "没有中奖"); + } else if (size == 6) { + ruleList = manualLotteryRules.stream().map(FitnessWalkRaffleRules.ManualLotteryRules::getAwardName).collect(Collectors.toList()); + ruleList.add(2, "没有中奖"); + ruleList.add(6, "没有中奖"); + } else { + ruleList = manualLotteryRules.stream().map(FitnessWalkRaffleRules.ManualLotteryRules::getAwardName).collect(Collectors.toList()); + ruleList.add("没有中奖"); + } + + List finalRuleList = ruleList; + List awardList = IntStream.range(0, ruleList.size()) + .mapToObj(index -> { + String awardName = finalRuleList.get(index); + NutMap map = NutMap.NEW(); + map.put("index", index); + map.put("name", awardName); + map.put("type", "没有中奖".equals(awardName) ? 1 : 0); + return map; + }).collect(Collectors.toList()); + return awardList; + } + + /** + * 手动抽奖 + * + * @param activityId 活动id + */ + @Override + @Aop(TransAop.READ_COMMITTED) + public void manualLottery(String activityId) { + // 删除此活动下的获奖记录 + dao().clear(FitnessWalkAwardUser.class, Cnd.where("activityId", "=", activityId)); + dao().clear(FitnessWalkRaffleUser.class, Cnd.where("activityId", "=", activityId)); + + FitnessWalkActivity activity = fitnessWalkCommonService.getActivity(activityId); + Date startDate = DateUtil.parse(DateUtil.format(DateUtil.date(activity.getStartTime()), "yyyy-MM-dd"), "yyyy-MM-dd"); + Date endDate = DateUtil.parse(DateUtil.format(DateUtil.date(activity.getEndTime()), "yyyy-MM-dd"), "yyyy-MM-dd"); + + // 获取达标的所有人,按照步数倒序 + Sql sql = getRaffleSql(null, activityId, null, null); + List list = listMap(sql); + + List raffleUserList = list.stream().map(v -> { + FitnessWalkRaffleUser raffleUser = new FitnessWalkRaffleUser(); + raffleUser.setId(R.UU32()); + raffleUser.setActivityId(activityId); + raffleUser.setUserId(v.getString("id")); + raffleUser.setLoginName(v.getString("loginname")); + raffleUser.setUsername(v.getString("username")); + raffleUser.setAwardSteps(v.getString("total_steps")); + raffleUser.setStandardsDays(v.getInt("standardsDays")); + raffleUser.setIsRaffle(false); + return raffleUser; + }).collect(Collectors.toList()); + dao().fastInsert(raffleUserList); + + Set winningRankLoginNames = new HashSet<>(); + + // 获奖人员 + List winningUsers = new ArrayList<>(); + + // 获取抽奖规则 + FitnessWalkRaffleRules rules = fetch(Cnd.where("activityId", "=", activityId)); + List manualLotteryRules = rules.getManualLotteryRules(); + + // 找出是按照排名来颁奖的奖项 + List ranks = manualLotteryRules.stream().filter(v -> "排名".equals(v.getRaffleType())) + .sorted(Comparator.comparing(FitnessWalkRaffleRules.ManualLotteryRules::getRankingPosition)).toList(); + + for (FitnessWalkRaffleRules.ManualLotteryRules rank : ranks) { + String awardName = rank.getAwardName(); + Integer lotteryUserNum = rank.getLotteryUserNum(); + + // 排除之前获奖的人,再倒序排列 + List canLotteryUsers = list.stream() + .filter(v -> !winningRankLoginNames.contains(v.getString("loginname"))) + .sorted(Comparator.comparingInt((NutMap v) -> v.getInt("total_steps")).reversed()) + .toList(); + + // 截取当前奖项的中奖人员 + List rankNutMaps = canLotteryUsers.subList(0, lotteryUserNum); + // 收集成中奖人员存储 + List collect = rankNutMaps.stream().map(v -> { + FitnessWalkAwardUser awardUser = new FitnessWalkAwardUser(); + awardUser.setId(R.UU32()); + awardUser.setActivityId(activityId); + awardUser.setUserId(v.getString("id")); + awardUser.setLoginName(v.getString("loginname")); + awardUser.setUsername(v.getString("username")); + awardUser.setAwardName(awardName); + awardUser.setStartDate(startDate); + awardUser.setEndDate(endDate); + awardUser.setUnionId(v.getString("unionid")); + awardUser.setUnionName(v.getString("unionName")); + awardUser.setUnitId(v.getString("unitId")); + awardUser.setUnitName(v.getString("unitName")); + awardUser.setStandardsDays(v.getInt("standardsDays")); + awardUser.setAwardSteps(v.getString("total_steps")); + awardUser.setPoints(rank.getPoints()); + return awardUser; + }).toList(); + + winningRankLoginNames.addAll(collect.stream().map(FitnessWalkAwardUser::getLoginName).toList()); + + winningUsers.addAll(collect); + } + + + List reachList = manualLotteryRules.stream().filter(v -> "达标".equals(v.getRaffleType())) + .sorted(Comparator.comparing(FitnessWalkRaffleRules.ManualLotteryRules::getRankingPosition)).toList(); + + for (FitnessWalkRaffleRules.ManualLotteryRules reach : reachList) { + List nutMaps; + if (reach.getIsSimultaneously() != null && reach.getIsSimultaneously()) { + // 可以兼得, 达标了的抽奖就是全部达标的人 + nutMaps = list; + } else { + // 不可兼得, 这里要排除其他奖项的中奖人员 + nutMaps = list.stream().filter(v -> !winningRankLoginNames.contains(v.getString("loginname"))).collect(Collectors.toList()); + } + + // 抽奖人数 + Integer lotteryUserNum = reach.getLotteryUserNum(); + // 奖项名称 + String awardName = reach.getAwardName(); + + // 这里是随机打乱了再去抽奖 + List reachNutMaps = nutMaps.stream().collect(Collectors.collectingAndThen(Collectors.toList(), collected -> { + int size = Math.min(lotteryUserNum, collected.size()); + Collections.shuffle(collected); + return collected.subList(0, size); + })); + + List collect = reachNutMaps.stream().map(v -> { + FitnessWalkAwardUser awardUser = new FitnessWalkAwardUser(); + awardUser.setId(R.UU32()); + awardUser.setActivityId(activityId); + awardUser.setUserId(v.getString("id")); + awardUser.setLoginName(v.getString("loginname")); + awardUser.setUsername(v.getString("username")); + awardUser.setAwardName(awardName); + awardUser.setStartDate(startDate); + awardUser.setEndDate(endDate); + awardUser.setUnionId(v.getString("unionid")); + awardUser.setUnionName(v.getString("unionName")); + awardUser.setUnitId(v.getString("unitId")); + awardUser.setUnitName(v.getString("unitName")); + awardUser.setStandardsDays(v.getInt("standardsDays")); + awardUser.setAwardSteps(v.getString("total_steps")); + awardUser.setPoints(reach.getPoints()); + return awardUser; + }).toList(); + + winningRankLoginNames.addAll(collect.stream().map(FitnessWalkAwardUser::getLoginName).toList()); + + winningUsers.addAll(collect); + } + + dao().fastInsert(winningUsers); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/utils/WeAppCloudUtil.java b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/utils/WeAppCloudUtil.java new file mode 100644 index 00000000..84e0b52d --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/fitnesswalk/utils/WeAppCloudUtil.java @@ -0,0 +1,170 @@ +package com.budwk.app.zhgh.activity.fitnesswalk.utils; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.constant.RedisConstant; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import org.nutz.integration.jedis.RedisService; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +/** + * 微信小程序云开发工具类 + */ +@IocBean +public class WeAppCloudUtil { + public static String ENV = "zufe-6guuuwl17ba1b011"; + + private static final String APPID = "wx093225a38487550f"; + + private static final String APP_SECRET = "23e506ca150f342e9afdcd772cced34a"; + + @Inject + public RedisService redisService; + + public JSONObject request(CRUD crud, String sql) { + String url = crud.url.replace("ACCESS_TOKEN", getAccessToken()); + String responseJson = HttpUtil.createPost(url).header("Content-Type", "application/json") + .body(JSONUtil.toJsonStr(Map.of("env", ENV, "query", sql))).execute().body(); + JSONObject response = JSONUtil.parseObj(responseJson); + if (response.getInt("errcode") == 42001) { + redisService.del(RedisConstant.REDIS_KEY_WE_APP_ACCESS_TOKEN); +// request(crud, sql); + } else if (response.getInt("errcode") == 40001) { + redisService.del(RedisConstant.REDIS_KEY_WE_APP_ACCESS_TOKEN); + } else if (response.getInt("errcode") != 0) { + throw new RuntimeException("小程序云函数接口调用失败,errcode:" + response.getStr("errcode") + ",errmsg:" + response.getStr("errmsg")); + } + return response; + } + + /** + * 获取token + * + * @return + */ + private String getAccessToken() { + String token = redisService.get(RedisConstant.REDIS_KEY_WE_APP_ACCESS_TOKEN); + if (StrUtil.isNotBlank(token)) { + return token; + } + String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET".replace("APPID", APPID).replace("APPSECRET", APP_SECRET); + String responseJson = HttpUtil.createGet(url).execute().body(); + + TokenResponse tokenResponse = JSONUtil.toBean(responseJson, TokenResponse.class); + // 微信的Access_token,两个小时过期,也就是7200秒 + redisService.setex(RedisConstant.REDIS_KEY_WE_APP_ACCESS_TOKEN, 7000, tokenResponse.getAccess_token()); + return tokenResponse.getAccess_token(); + + /*String result = Http.get(url).getContent(); + HashMap tokenObject = Json.fromJson(HashMap.class, result); + if (tokenObject.containsKey("errcode")) { + log.error("获取token失败------" + tokenObject.get("errmsg")); + throw new RuntimeException("获取token失败------" + tokenObject.get("errmsg")); + } + redisService.setex(RedisConstant.REDIS_KEY_WE_APP_ACCESS_TOKEN, 7200 - 200, (String) tokenObject.get("access_token")); + return (String) tokenObject.get("access_token"); + return null;*/ + } + + @Getter + @AllArgsConstructor + public enum CRUD { + INSERT("https://api.weixin.qq.com/tcb/databaseadd?access_token=ACCESS_TOKEN"), + QUERY("https://api.weixin.qq.com/tcb/databasequery?access_token=ACCESS_TOKEN"), + DELETE("https://api.weixin.qq.com/tcb/databasedelete?access_token=ACCESS_TOKEN"), + UPDATE("https://api.weixin.qq.com/tcb/databaseupdate?access_token=ACCESS_TOKEN"), + AGGREGATE("https://api.weixin.qq.com/tcb/databaseaggregate?access_token=ACCESS_TOKEN"), + COUNT("https://api.weixin.qq.com/tcb/databasecount?access_token=ACCESS_TOKEN"); + private final String url; + } + + @Data + public static class Response { + private int errcode; + private String erremsg; + } + + @EqualsAndHashCode(callSuper = true) + @Data + public static class TokenResponse extends Response { + private int expires_in; + private String access_token; + } + + /** + * 上传文件返回cloud—url + * + * @param rootPath + * @param file + * @return + */ + public String uploadFile(String rootPath, File file) { + String path = rootPath + file.getName(); + String url = "https://api.weixin.qq.com/tcb/uploadfile?access_token=ACCESS_TOKEN".replace("ACCESS_TOKEN", getAccessToken()); + String responseJson = HttpUtil.createPost(url).header("Content-Type", "application/json") + .body(JSONUtil.toJsonStr(Map.of("env", ENV, "path", path))).execute().body(); + JSONObject jsonObject = JSONUtil.parseObj(responseJson); + if (jsonObject.getInt("errcode") != 0) { + throw new RuntimeException(jsonObject.getStr("errmsg")); + } + try{ + HttpUtil.createPost(jsonObject.getStr("url")) + .form("key", path) + .form("Signature", jsonObject.getStr("authorization")) + .form("x-cos-security-token", jsonObject.getStr("token")) + .form("x-cos-meta-fileid", jsonObject.getStr("cos_file_id")) + .form("file", file) + .execute().body(); + return jsonObject.getStr("file_id"); + }catch (Exception e){ + return jsonObject.getStr("file_id"); + } + } + + public String httpFile(String fileId) { + String url = "https://api.weixin.qq.com/tcb/batchdownloadfile?access_token=ACCESS_TOKEN".replace("ACCESS_TOKEN", getAccessToken()); + + HashMap body = new HashMap<>(2) {{ + put("env", ENV); + put("file_list", new ArrayList<>() {{ + add(new HashMap<>() {{ + put("fileid", fileId); + put("max_age", 7200); + }}); + }}); + }}; + + Map mf = new HashMap(); + mf.put("fileid", fileId); + mf.put("max_age", 7200); + ArrayList fm = new ArrayList<>(); + fm.add(mf); + + body.put("file_list", fm); + + + String responseJson = HttpUtil.createPost(url) + .header("Content-Type", "application/json") + .body(JSONUtil.toJsonStr(body)) + .execute().body(); + System.out.println(JSONUtil.toJsonStr(body)); + JSONObject jsonObject = JSONUtil.parseObj(responseJson); + if (jsonObject.getInt("errcode") != 0) { + throw new RuntimeException(jsonObject.getStr("errmsg")); + } + return jsonObject.getJSONArray("file_list").toList(JSONObject.class).get(0).getStr("download_url"); + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/data/WorkersHomeDataRevelController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/data/WorkersHomeDataRevelController.java new file mode 100644 index 00000000..ddc7903a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/data/WorkersHomeDataRevelController.java @@ -0,0 +1,308 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.data; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_file; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.workershome.model.WorkersHomeDataRevel; +import com.budwk.app.zhgh.dayofficework.workershome.service.WorkersHomeInfoService; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.boot.starter.ftp.FtpService; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Criteria; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.random.R; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileInputStream; +import java.net.URLEncoder; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @version 1.0 + * @Author zzr + * @name:WorkersHomeDataRevelController + * @Date 2024/7/30 15:48 + * @注释 职工建家资料管理 + */ +@IocBean +@Ok("json:full") +@ApiOperation("职工建家资料管理") +@At("/platform/workershome/data/revel") +public class WorkersHomeDataRevelController { + + @Inject + private Dao dao; + @Inject + private FtpService ftpsService; + @Inject + private WorkersHomeInfoService workersHomeInfoService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workershome/data/revel.html") + @SaCheckPermission("workershome.data.revel") + public void index() { + } + + + @At + @ApiOperation("获取职工小家的树形数据,按分工会展示") + @SaCheckPermission("workershome.data.revel") + public Result getTreeData(@Param("year") String year, + @Param("revelName") String revelName, + @Param("typeId") String typeId) { + NutMap nutMap = NutMap.NEW(); + nutMap.setv("unionname", "工会委员会"); + Sql sql = Sqls.create(""" + select + un.*, + un.name AS unionname, + (select count(*) from workers_home_data_revel whdr where whdr.belongToUnionId = un.id $revelCount) as revelCount + from + sys_union un + $condition + """); + Criteria criteria = Cnd.cri(); + criteria.where().setTop(false); + if (StringUtils.isNotBlank(year)) { + criteria.where().and("year(whdr.time)", "=", year); + } + if (StringUtils.isNotBlank(revelName)) { + criteria.where().and(Cnd.likeEX("whdr.revelName", revelName)); + } + if (StringUtils.isNotBlank(typeId)) { + criteria.where().and("whdr.typeId", "=", typeId); + } + if (!criteria.where().isEmpty()) { + sql.vars().set("revelCount", "and " + criteria.toSql(null)); + } + + Cnd cnd = Cnd.NEW(); + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.and("un.id", "=", SecurityUtil.getUnionId()); + } + cnd.asc("un.unioncode"); + sql.setCondition(cnd); + nutMap.setv("child", workersHomeInfoService.listMap(sql)); + return Result.success().addData(List.of(nutMap)); + } + + + @At + @ApiOperation("按照工会查询职工小家资料列表") + @SaCheckPermission("workershome.data.revel") + public Object pageData(PageForm pageForm, + @Param("year") String year, + @Param("revelName") String revelName, + @Param("typeId") String typeId, + @Param("unionId") String unionId) { + try { + Sql sql = Sqls.create(""" + SELECT + whdr.*, + whdt.typeName + FROM + workers_home_data_revel whdr + LEFT JOIN workers_home_data_type whdt ON whdr.typeId = whdt.id + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("year(whdr.time)", "=", year); + if (StrUtil.isNotBlank(revelName)) { + cnd.and(Cnd.likeEX("whdr.revelName", revelName)); + } + cnd.andEX("whdr.typeId", "=", typeId); + cnd.andEX("whdr.unionId", "=", unionId); + cnd.desc("whdr.time"); + sql.setCondition(cnd); + Pagination pagination = workersHomeInfoService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } catch (Exception e) { + e.printStackTrace(); + return Result.error(); + } + } + + + @At + @ApiOperation("职工小家资料添加") + @SaCheckPermission("workershome.data.revel") + @SLog(tag = "职工小家资料添加", msg = "职工小家资料名称: ${args[0].revelName}") + public Result doAdd(WorkersHomeDataRevel workersHomeDataRevel) { + View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId())); + workersHomeDataRevel.setId(R.UU32()); + workersHomeDataRevel.setUserId(user.getId()); + workersHomeDataRevel.setUsername(user.getUsername()); + workersHomeDataRevel.setLoginName(user.getLoginname()); + workersHomeDataRevel.setUnitId(user.getUnitId()); + workersHomeDataRevel.setUnitName(user.getUnitName()); + workersHomeDataRevel.setUnionId(user.getUnionId()); + workersHomeDataRevel.setUnionName(user.getUnionName()); + workersHomeDataRevel.setTime(DateUtil.now()); + if (StrUtil.isNotBlank(workersHomeDataRevel.getBelongToUnionId())) { + Sys_union union = dao.fetch(Sys_union.class, workersHomeDataRevel.getBelongToUnionId()); + workersHomeDataRevel.setBelongToUnionName(union.getName()); + } else { + workersHomeDataRevel.setBelongToUnionId(user.getUnionId()); + workersHomeDataRevel.setBelongToUnionName(user.getUnionName()); + } + dao.fastInsert(workersHomeDataRevel); + return Result.success(); + } + + + @At + @ApiOperation("职工小家资料修改") + @SaCheckPermission("workershome.data.revel") + @SLog(tag = "职工小家资料修改", msg = "职工小家资料名称: ${args[0].revelName}") + public Result doEdit(WorkersHomeDataRevel workersHomeDataRevel) { + dao.update(workersHomeDataRevel); + return Result.success(); + } + + + @At + @Aop(TransAop.READ_COMMITTED) + @ApiOperation("职工小家资料删除") + @SaCheckPermission("workershome.data.revel") + @SLog(tag = "职工小家资料删除", msg = "职工小家资料id: ${args[0]}") + public Result doDelete(String id) { + WorkersHomeDataRevel revel = dao.fetch(WorkersHomeDataRevel.class, id); + if (revel != null) { + if (revel.getFiles() != null && !revel.getFiles().isEmpty()) { + Set fileIds = revel.getFiles().stream().map(Sys_file::getId).collect(Collectors.toSet()); + dao.clear(Sys_file.class, Cnd.where("id", "in", fileIds)); + } + dao.clear(WorkersHomeDataRevel.class, Cnd.where("id", "=", id)); + } + return Result.success(); + } + + + @At + @Ok("void") + @ApiOperation("按工会导出所有资料") + @SaCheckPermission("workershome.data.revel") + public void exportAllFileByUnionId(String unionId, String unionName, HttpServletResponse response) { + response.reset(); + response.setContentType("application/x-msdownload;charset=utf-8"); + + // 创建临时文件夹 + String tmpPath = "tmp/" + R.UU32(); + File tmpDir = new File(tmpPath + "/" + unionName + "附件汇总"); + tmpDir.mkdirs(); + + List query = dao.query(WorkersHomeDataRevel.class, Cnd.where("belongToUnionId", "=", unionId)); + + try { + if (Lang.isNotEmpty(query)) { + for (WorkersHomeDataRevel revel : query) { + // 创建资料名称的文件夹 + String fileName = revel.getRevelName(); + + File tDir = new File(tmpDir + "/" + fileName); + tDir.mkdirs(); + +// if (Lang.isNotEmpty(revel.getFiles())) { +// for (Sys_file file : revel.getFiles()) { +// FileOutputStream outputStream = new FileOutputStream(tDir.getPath() + "/" + file.getFilename()); +// ftpsService.download(file.getFilepath(), outputStream); +// outputStream.close(); +// } +// } + } + + String aimsDir = "zipTmp/" + R.UU32(); + String aimsName = unionName + "附件汇总.zip"; + String aimsPath = aimsDir + "/" + aimsName; +// FileUtil.compressToZip(tmpDir.getPath(), aimsDir, aimsName); + + response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(aimsName, "UTF-8")); + + File aimsFile = new File(aimsPath); + FileInputStream inputStream = new FileInputStream(aimsFile); + IOUtils.copy(inputStream, response.getOutputStream()); + inputStream.close(); + aimsFile.delete(); + +// FileUtil.deleteDir(new File(tmpPath)); +// FileUtil.deleteDir(new File(aimsDir)); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + + @At + @Ok("void") + @ApiOperation("导出单个资料") + @SaCheckPermission("workershome.data.revel") + public void exportAllFileById(String id, HttpServletResponse response) { + response.reset(); + response.setContentType("application/x-msdownload;charset=utf-8"); + + WorkersHomeDataRevel dataRevel = dao.fetch(WorkersHomeDataRevel.class, Cnd.where("id", "=", id)); + + // 创建临时文件夹 + String tmpPath = "tmp/" + R.UU32(); + File tmpDir = new File(tmpPath + "/" + dataRevel.getBelongToUnionName() + dataRevel.getRevelName() + "附件汇总"); + tmpDir.mkdirs(); + + try { + + if (Lang.isNotEmpty(dataRevel.getFiles())) { +// for (Sys_file file : dataRevel.getFiles()) { +// FileOutputStream outputStream = new FileOutputStream(tmpDir.getPath() + "/" + file.getFilename()); +// ftpsService.download(file.getFilepath(), outputStream); +// outputStream.close(); +// } + } + + String aimsDir = "zipTmp/" + R.UU32(); + String aimsName = dataRevel.getBelongToUnionName() + dataRevel.getRevelName() + "附件汇总.zip"; + String aimsPath = aimsDir + "/" + aimsName; +// FileUtil.compressToZip(tmpDir.getPath(), aimsDir, aimsName); + + response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(aimsName, "UTF-8")); + + File aimsFile = new File(aimsPath); + FileInputStream inputStream = new FileInputStream(aimsFile); + IOUtils.copy(inputStream, response.getOutputStream()); + inputStream.close(); + aimsFile.delete(); + +// FileUtil.deleteDir(new File(tmpPath)); +// FileUtil.deleteDir(new File(aimsDir)); + + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/data/WorkersHomeDataTypeController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/data/WorkersHomeDataTypeController.java new file mode 100644 index 00000000..d7ac58ea --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/data/WorkersHomeDataTypeController.java @@ -0,0 +1,134 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.data; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.dayofficework.workershome.model.WorkersHomeDataType; +import com.budwk.app.zhgh.dayofficework.workershome.service.WorkersHomeInfoService; +import io.swagger.annotations.ApiOperation; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.random.R; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @version 1.0 + * @Author zzr + * @name:WorkersHomeDataTypeController + * @Date 2024/7/30 15:48 + * @注释 + */ +@IocBean +@Ok("json:full") +@ApiOperation("职工建家资料类型管理") +@At("/platform/workershome/data/type") +public class WorkersHomeDataTypeController { + + @Inject + private WorkersHomeInfoService workersHomeInfoService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workershome/data/type.html") + @SaCheckPermission("workershome.data.type") + public void index() { + } + + + @At + @ApiOperation("资料类型数据展示") + @SaCheckPermission("workershome.data.type") + public Result pageData(PageForm pageForm, + @Param("typeName") String typeName) { + Sql sql = Sqls.create("select * from workers_home_data_type $condition"); + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(typeName)) { + cnd.and(Cnd.likeEX("typeName", typeName)); + } + cnd.asc("serialNum"); + sql.setCondition(cnd); + Pagination pagination = workersHomeInfoService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + @At + @ApiOperation("新增资料类型") + @SaCheckPermission("workershome.data.type") + @SLog(tag = "职工小家资料类型添加", msg = "职工小家资料类型名称: ${args[0].typeName}") + public Result doAdd(WorkersHomeDataType workersHomeDataType) { + int count = workersHomeInfoService.dao().count("workers_home_data_type", Cnd.where("code", "=", workersHomeDataType.getCode())); + if (count > 0) { + return Result.error("编码重复"); + } + workersHomeDataType.setId(R.UU32()); + int totalCount = workersHomeInfoService.count("workers_home_data_type"); + workersHomeDataType.setSerialNum(totalCount + 1); + workersHomeInfoService.insert("workers_home_data_type", Chain.from(workersHomeDataType)); + return Result.success(); + } + + + @At + @ApiOperation("修改资料类型") + @SaCheckPermission("workershome.data.type") + @SLog(tag = "职工小家资料类型修改", msg = "职工小家资料类型名称: ${args[0].typeName}") + public Result doEdit(WorkersHomeDataType workersHomeDataType) { + int count = workersHomeInfoService.count("workers_home_data_type", Cnd.where("code", "=", workersHomeDataType.getCode()).and("id", "!=", workersHomeDataType.getId())); + if (count > 0) { + return Result.error("编码重复"); + } + workersHomeInfoService.update("workers_home_data_type", Chain.from(workersHomeDataType), Cnd.where("id", "=", workersHomeDataType.getId())); + return Result.success(); + } + + @At + @ApiOperation("删除资料类型") + @SaCheckPermission("workershome.data.type") + @SLog(tag = "职工小家资料类型删除", msg = "职工小家资料类型id: ${args[0]}") + public Result doDelete(String id) { + workersHomeInfoService.dao().clear(WorkersHomeDataType.class, Cnd.where("id", "=", id)); + return Result.success(); + } + + + @At + @ApiOperation("获取所有资料类型") + @SaCheckPermission("workershome.data.type") + public Result getAllWakesHomeDataType() { + List list = workersHomeInfoService.dao().query(WorkersHomeDataType.class, Cnd.NEW().asc("serialNum")); + return Result.success().addData(list); + } + + + @At + @ApiOperation("资料类型排序") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("workershome.data.type") + public Result serialNumChange(String id, Integer serialNum, boolean toDown) { + if (toDown) { + WorkersHomeDataType next = workersHomeInfoService.dao().fetch(WorkersHomeDataType.class, Cnd.where("serialNum", "=", serialNum + 1)); + next.setSerialNum(serialNum - 1); + workersHomeInfoService.dao().update(next); + workersHomeInfoService.dao().update(WorkersHomeDataType.class, Chain.make("serialNum", serialNum + 1), Cnd.where("id", "=", id)); + } else { + WorkersHomeDataType pre = workersHomeInfoService.dao().fetch(WorkersHomeDataType.class, Cnd.where("serialNum", "=", serialNum - 1)); + pre.setSerialNum(serialNum + 1); + workersHomeInfoService.dao().update(pre); + workersHomeInfoService.dao().update(WorkersHomeDataType.class, Chain.make("serialNum", serialNum - 1), Cnd.where("id", "=", id)); + } + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationApplyController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationApplyController.java new file mode 100644 index 00000000..3be4a9de --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationApplyController.java @@ -0,0 +1,93 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.declaration; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.result.Result; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.workershome.model.WorkersHomeApply; +import com.budwk.app.zhgh.dayofficework.workershome.service.WorkersHomeApplyService; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Cnd; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.random.R; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @version 1.0 + * @Author zzr + * @name:WorkersHomeDeclarationApplyController + * @Date 2024/7/30 14:06 + * @注释 职工建家申报 + */ +@IocBean +@Ok("json:full") +@ApiOperation("职工建家申报") +@At("/platform/workershome/declaration/apply") +public class WorkersHomeDeclarationApplyController { + + @Inject + private WorkersHomeApplyService workersHomeApplyService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workershome/declaration/apply.html") + @SaCheckPermission("workershome.declaration.apply") + public void index() {} + + + @At + @ApiOperation("职工建家申报保存") + @SLog(tag = "职工建家申报保存", msg = "职工建家申报信息") + @SaCheckPermission("workershome.declaration.apply") + public Result doSave(WorkersHomeApply workersHomeApply) { + workersHomeApply.setState("10000"); + if (StrUtil.isNotBlank(workersHomeApply.getId())) { + workersHomeApplyService.update(workersHomeApply); + } else { + workersHomeApplyService.setParams(workersHomeApply); + workersHomeApplyService.fastInsert(workersHomeApply); + } + return Result.success(); + } + + + @At + @ApiOperation("职工建家申报提交") + @SLog(tag = "职工建家申报提交", msg = "职工建家申报信息") + @SaCheckPermission("workershome.declaration.apply") + public Result doSubmit(WorkersHomeApply workersHomeApply) { + workersHomeApply.setState("10020"); + if (StrUtil.isNotBlank(workersHomeApply.getId())) { + workersHomeApplyService.update(workersHomeApply); + } else { + workersHomeApply.setId(R.UU32()); + workersHomeApplyService.setParams(workersHomeApply); + workersHomeApplyService.fastInsert(workersHomeApply); + } + return Result.success(); + } + + + @At + @ApiOperation("职工建家申报信息查询") + @SaCheckPermission(value = {"workershome.declaration.apply","workershome.declaration.mine", + "workershome.declaration.organization", "workershome.declaration.school", + "workershome.declaration.statistics"}, mode = SaMode.OR) + public Result getInfoById(String id){ + NutMap map = workersHomeApplyService.findById(id); + return Result.success().addData(map); + } + + + @At + @ApiOperation("职工建家申报工会信息查询") + @SaCheckPermission("workershome.declaration.apply") + public Result getWakesHomeUnitInfo() { + WorkersHomeApply apply = workersHomeApplyService.fetch(Cnd.where("unionId", "=", SecurityUtil.getUnionId())); + return Result.success().addData(apply); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationMineController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationMineController.java new file mode 100644 index 00000000..40f1dada --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationMineController.java @@ -0,0 +1,147 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.declaration; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.model.Audit; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.workershome.model.WorkersHomeApply; +import com.budwk.app.zhgh.dayofficework.workershome.service.WorkersHomeApplyService; +import io.swagger.annotations.ApiOperation; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletResponse; + +/** + * @version 1.0 + * @Author zzr + * @name:WorkersHomeDeclarationMineController + * @Date 2024/7/30 14:06 + * @注释 我的建家申报 + */ +@IocBean +@Ok("json:full") +@ApiOperation("职工建家我的申报") +@At("/platform/workershome/declaration/mine") +public class WorkersHomeDeclarationMineController { + + @Inject + private WorkersHomeApplyService workersHomeApplyService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workershome/declaration/mine.html") + @SaCheckPermission("workershome.declaration.mine") + public void index() { + } + + + @At + @ApiOperation("获取职工建家我的申报列表") + @SaCheckPermission("workershome.declaration.mine") + public Result pageData(PageForm pageForm, + @Param("year") Integer year, + @Param("unionId") String unionId) { + Sql sql = Sqls.create(""" + SELECT + wh.*, + audit.stateName + FROM + `workers_home_apply` wh + LEFT JOIN audit_state audit ON wh.state = audit.stateId + AND audit.module = 'workershome' + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("YEAR(wh.applyDate)", "=", year); + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.and("unionId", "=", SecurityUtil.getUnionId()); + } else { + cnd.andEX("unionId", "=", unionId); + } + sql.setCondition(cnd); + Pagination pagination = workersHomeApplyService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + @At + @Aop(TransAop.READ_COMMITTED) + @ApiOperation("职工建家我的申报删除") + @SLog(tag = "职工建家我的申报删除", msg = "职工建家我的申报id: ${args[0]}") + @SaCheckPermission(value = {"workershome.declaration.apply", "workershome.declaration.mine"}, mode = SaMode.OR) + public Result doDelete(String id) { + WorkersHomeApply apply = workersHomeApplyService.fetch(id); + if (StrUtil.isNotBlank(apply.getOrganizationAuditId())) { + workersHomeApplyService.dao().delete(Audit.class, apply.getOrganizationAuditId()); + } + if (StrUtil.isNotBlank(apply.getSchoolAuditId())) { + workersHomeApplyService.dao().delete(Audit.class, apply.getSchoolAuditId()); + } + workersHomeApplyService.delete(id); + return Result.success(); + } + + @At + @Ok("void") + public void openExport(String id, HttpServletResponse response) { +// try { +// NutMap nutMap = workersHomeApplyService.findById(id); +// +// HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy(); +// HtmlRenderPolicy htmlRenderPolicy = new HtmlRenderPolicy(); +// htmlRenderPolicy.getConfig().setShowDefaultTableBorderInTableCell(true); +// +// Configure config = Configure.newBuilder() +// .bind("basicInformation", htmlRenderPolicy) +// .bind("constructionPlan", htmlRenderPolicy).build(); +// HashMap map = new HashMap<>(); +// String fileName = Globals.schoolName + "“教工小家”建设计划书"; +// map.put("fileName", fileName); +// map.put("schoolName", Globals.schoolName); +// map.put("unionName", nutMap.getString("unionName")); +// map.put("applyDate", nutMap.getString("applyDate")); +// map.put("username", nutMap.getString("username")); +// map.put("mobile", nutMap.getString("mobile")); +// map.put("basicInformation", nutMap.getString("basicInformation")); +// map.put("constructionPlan", nutMap.getString("constructionPlan")); +// NutMap schoolAudit = nutMap.getAs("schoolAudit", NutMap.class); +// if (Lang.isNotEmpty(schoolAudit)){ +// schoolAudit.setv("auditTime", DateUtil.formatDate(schoolAudit.getTime("auditTime"))); +// schoolAudit.setv("auditSign", Vi.getImg(schoolAudit.getString("auditSign"))); +// map.put("schoolAudit", schoolAudit); +// } +// NutMap organizationAudit = nutMap.getAs("organizationAudit", NutMap.class); +// if (Lang.isNotEmpty(organizationAudit)){ +// organizationAudit.setv("auditTime", DateUtil.formatDate(organizationAudit.getTime("auditTime"))); +// organizationAudit.setv("auditSign", Vi.getImg(organizationAudit.getString("auditSign"))); +// map.put("organizationAudit", organizationAudit); +// } +// +// +// +// +// response.addHeader("Content-Type", "application/octet-stream"); +// response.addHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1") + "\".docx"); +// InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("docTemplate/workershome/workershome.docx"); +// XWPFTemplate.compile(inputStream, config).render(map, response.getOutputStream()); +// inputStream.close(); +// } catch (Exception e) { +// e.printStackTrace(); +// } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationOrganizationController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationOrganizationController.java new file mode 100644 index 00000000..b6f08ca7 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationOrganizationController.java @@ -0,0 +1,100 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.declaration; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.model.Audit; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.workershome.model.WorkersHomeApply; +import com.budwk.app.zhgh.dayofficework.workershome.service.WorkersHomeApplyService; +import io.swagger.annotations.ApiOperation; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +/** + * @version 1.0 + * @Author zzr + * @name:WakesHomeDeclarationOrganization + * @Date 2024/7/30 14:07 + * @注释 建家申报党组织审核 + */ +@IocBean +@Ok("json:full") +@ApiOperation("职工建家申报党组织审核") +@At("/platform/workershome/declaration/organization") +public class WorkersHomeDeclarationOrganizationController { + + @Inject + private WorkersHomeApplyService workersHomeApplyService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workershome/declaration/organizationAudit.html") + @SaCheckPermission("workershome.declaration.organization") + public void index() { + } + + + @At + @ApiOperation("职工建家申报党组织审核") + @SaCheckPermission("workershome.declaration.organization") + public Result pageData(PageForm pageForm, @Param("year") Integer year, + @Param("unionId") String unionId, @Param("isAudit") String isAudit) { + Sql sql = Sqls.create(""" + SELECT + wh.*, + audit.stateName + FROM + `workers_home_apply` wh + LEFT JOIN audit_state audit ON wh.state = audit.stateId + AND audit.module = 'workershome' + $condition + """); + Cnd cnd = Cnd.NEW(); + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.and("wh.unionId", "=", SecurityUtil.getUnionId()); + } else { + cnd.andEX("wh.unionId", "=", unionId); + } + cnd.andEX("YEAR(wh.applyDate)", "=", year); + cnd.and("wh.state", "true".equals(isAudit) ? ">" : "false".equals(isAudit) ? "=" : ">=", 10010); + sql.setCondition(cnd); + Pagination pagination = workersHomeApplyService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + @At + @Aop(TransAop.READ_COMMITTED) + @ApiOperation("职工建家申报党组织审核") + @SaCheckPermission("workershome.declaration.organization") + public Result doAudit(@Param("audit") Audit audit, String id) { + Boolean auditPass = audit.getAuditPass(); + workersHomeApplyService.dao().insert(audit); + workersHomeApplyService.update(Chain.make("state", auditPass ? 10020 : 10015) + .add("organizationAuditId", audit.getId()), Cnd.where("id", "=", id)); + return Result.success(); + } + + + @At + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("workershome.declaration.organization") + public Result doRollBack(String id){ + WorkersHomeApply workershome = workersHomeApplyService.fetch(id); + workersHomeApplyService.dao().clear(Audit.class,Cnd.where("id","=",workershome.getOrganizationAuditId())); + workersHomeApplyService.update(Chain.make("state",10010).add("organizationAuditId",null),Cnd.where("id","=",id)); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationSchoolController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationSchoolController.java new file mode 100644 index 00000000..b04342da --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationSchoolController.java @@ -0,0 +1,119 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.declaration; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.model.Audit; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.workershome.model.WorkersHomeApply; +import com.budwk.app.zhgh.dayofficework.workershome.service.WorkersHomeApplyService; +import io.swagger.annotations.ApiOperation; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +/** + * @version 1.0 + * @Author zzr + * @name:WorkersHomeDeclarationSchoolController + * @Date 2024/7/30 14:07 + * @注释 建家申报校工会审核 + */ +@IocBean +@Ok("json:full") +@ApiOperation("职工建家校工会审核") +@At("/platform/workershome/declaration/school") +public class WorkersHomeDeclarationSchoolController { + + @Inject + private WorkersHomeApplyService workersHomeApplyService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workershome/declaration/schoolAudit.html") + @SaCheckPermission("workershome.declaration.school") + public void index() { + } + + + @At + @ApiOperation("获取职工建家校工会审核列表") + @SaCheckPermission("workershome.declaration.school") + public Result pageData(PageForm pageForm, + @Param("year") Integer year, + @Param("unionId") String unionId, + @Param("isAudit") String isAudit) { + Sql sql = Sqls.create(""" + SELECT + wh.*, + audit.stateName + FROM + `workers_home_apply` wh + LEFT JOIN audit_state audit ON wh.state = audit.stateId + AND audit.module = 'workershome' + $condition + """); + Cnd cnd = Cnd.NEW(); + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.and("wh.unionId", "=", SecurityUtil.getUnionId()); + } else { + cnd.andEX("wh.unionId", "=", unionId); + } + cnd.andEX("YEAR(wh.applyDate)", "=", year); + cnd.and("wh.state", "true".equals(isAudit) ? ">" : "false".equals(isAudit) ? "=" : ">=", 10020); + sql.setCondition(cnd); + Pagination pagination = workersHomeApplyService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + @At + @Aop(TransAop.READ_COMMITTED) + @ApiOperation("职工建家校工会审核") + @SaCheckPermission("workershome.declaration.school") + @SLog(tag = "职工建家校工会审核", msg = "职工建家校工会审核id: ${args[1]}") + public Result doAudit(@Param("audit") Audit audit, String id) { + Boolean auditPass = audit.getAuditPass(); + workersHomeApplyService.dao().insert(audit); + workersHomeApplyService.update(Chain.make("state", auditPass ? 10030 : 10025) + .add("schoolAuditId", audit.getId()), Cnd.where("id", "=", id)); + return Result.success(); + } + + + @At + @Aop(TransAop.READ_COMMITTED) + @ApiOperation("职工建家校工会审核撤回") + @SaCheckPermission("workershome.declaration.school") + @SLog(tag = "职工建家校工会审核撤回", msg = "职工建家校工会审核撤回id: ${args[0]}") + public Result doRollBack(String id) { + WorkersHomeApply workersHome = workersHomeApplyService.fetch(id); + workersHomeApplyService.dao().clear(Audit.class, Cnd.where("id", "=", workersHome.getSchoolAuditId())); + workersHomeApplyService.update(Chain.make("state", 10020).add("schoolAuditId", null), Cnd.where("id", "=", id)); + return Result.success(); + } + + @At + @ApiOperation("职工建家校工会审核文件上传") + @SaCheckPermission("workershome.declaration.school") + public Result doFiles(String id, String files) { + WorkersHomeApply wakesHomeApply = new WorkersHomeApply(); + wakesHomeApply.setId(id); + wakesHomeApply.setFiles(JSONUtil.toList(files, JSONObject.class)); + workersHomeApplyService.updateIgnoreNull(wakesHomeApply); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationStatisticsController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationStatisticsController.java new file mode 100644 index 00000000..1531d6c9 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/declaration/WorkersHomeDeclarationStatisticsController.java @@ -0,0 +1,71 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.declaration; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.workershome.service.WorkersHomeApplyService; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +/** + * @version 1.0 + * @Author zzr + * @name:WorkersHomeDeclarationStatisticsController + * @Date 2024/8/2 15:00 + * @注释 申报,查询统计 + */ +@IocBean +@Ok("json:full") +@ApiOperation("职工建家统计") +@At("/platform/workershome/declaration/statistics") +public class WorkersHomeDeclarationStatisticsController { + + @Inject + private WorkersHomeApplyService workersHomeApplyService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workershome/declaration/statistics.html") + @SaCheckPermission("workershome.declaration.statistics") + public void index() {} + + + @At + @ApiOperation("获取职工建家统计列表") + @SaCheckPermission("workershome.declaration.statistics") + public Result pageData(PageForm pageForm, + @Param("year") Integer year, + @Param("unionId") String unionId){ + Sql sql = Sqls.create(""" + SELECT + wh.*, + audit.stateName + FROM + `workers_home_apply` wh + LEFT JOIN audit_state audit ON wh.state = audit.stateId + AND audit.module = 'workershome' + $condition + """); + Cnd cnd = Cnd.NEW(); + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.and("wh.unionId", "=", SecurityUtil.getUnionId()); + } else { + cnd.andEX("wh.unionId", "=", unionId); + } + cnd.andEX("YEAR(wh.applyDate)", "=", year); + cnd.and("wh.state", "=" , 10030); + sql.setCondition(cnd); + Pagination pagination = workersHomeApplyService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeApplyController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeApplyController.java new file mode 100644 index 00000000..b1fa5e09 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeApplyController.java @@ -0,0 +1,66 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.info; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.result.Result; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.workershome.model.WorkersHome; +import com.budwk.app.zhgh.dayofficework.workershome.model.WorkersHomeApply; +import com.budwk.app.zhgh.dayofficework.workershome.service.WorkersHomeInfoService; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Cnd; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +@IocBean +@Ok("json:full") +@ApiOperation("职工建家信息填报") +@At("/platform/workershome/info/apply") +public class WorkersHomeApplyController { + + @Inject + private WorkersHomeInfoService workersHomeInfoService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workershome/info/apply.html") + @SaCheckPermission("workershome.info.apply") + public void index() {} + + + @At + @SaCheckPermission("workershome.info.apply") + public Result doAdd(WorkersHome workershome, Boolean isSubmit){ + if (isSubmit){ + workershome.setState(8120); + } else { + workershome.setState(8100); + } + if (!"校工会".equals(workershome.getCategory())){ + workershome.setUnionId(SecurityUtil.getUnionId()); + } + workersHomeInfoService.insert(workershome); + return Result.success(); + } + + + @At + @SaCheckPermission("workershome.info.apply") + public Result doEdit(WorkersHome workershome,Boolean isSubmit){ + if (isSubmit){ + workershome.setState(8120); + } + workersHomeInfoService.updateIgnoreNull(workershome); + return Result.success(); + } + + + @At + @SaCheckPermission("workershome.info.apply") + public Result validateApply(){ + int count = workersHomeInfoService.dao().count(WorkersHomeApply.class, + Cnd.where("state", "=", "10030") + .and("unionId", "=", SecurityUtil.getUnionId())); + return (count > 0) ? Result.success() : Result.error(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeInfoController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeInfoController.java new file mode 100644 index 00000000..07ef4d31 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeInfoController.java @@ -0,0 +1,60 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.info; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.dayofficework.workershome.service.WorkersHomeInfoService; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +@IocBean +@Ok("json:full") +@ApiOperation("职工建家信息查询") +@At("/platform/workershome/info/info") +public class WorkersHomeInfoController { + + @Inject + private WorkersHomeInfoService workersHomeInfoService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workershome/info/info.html") + @SaCheckPermission("workershome.info.info") + public void index() {} + + + @At + @ApiOperation("职工建家信息查询") + @SaCheckPermission("workershome.info.info") + public Result pageData(PageForm pageForm, @Param("year") Integer year, @Param("unionId") String unionId){ + Sql sql = Sqls.create(""" + SELECT + wh.* + FROM + `workers_home` wh + LEFT JOIN sys_union su ON su.id = wh.unionId + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("YEAR(applyTime)","=",year); + if ("校工会".equals(unionId)){ + cnd.and("wh.category","=","校工会"); + } else { + cnd.andEX("wh.unionId","=",unionId); + } + cnd.and("wh.state","=",8130); + cnd.asc("su.unioncode"); + sql.setCondition(cnd); + List list = workersHomeInfoService.listMap(sql); + return Result.success().addData(list); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeMineController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeMineController.java new file mode 100644 index 00000000..dc1a30c7 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeMineController.java @@ -0,0 +1,97 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.info; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.model.Audit; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.workershome.model.WorkersHome; +import com.budwk.app.zhgh.dayofficework.workershome.service.WorkersHomeInfoService; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + + +@IocBean +@Ok("json:full") +@ApiOperation("职工建家信息我的填报") +@At("/platform/workershome/info/mine") +public class WorkersHomeMineController { + + @Inject + private WorkersHomeInfoService workersHomeInfoService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workershome/info/mine.html") + @SaCheckPermission("workershome.info.mine") + public void index() {} + + + @At + @ApiOperation("职工建家信息我的填报列表") + @SaCheckPermission("workershome.info.mine") + public Result pageData(PageForm pageForm, @Param("year") Integer year, @Param("unionId")String unionId){ + Sql sql = Sqls.create(""" + SELECT + wh.*, + audit.stateName + FROM + `workers_home` wh + LEFT JOIN audit_state audit ON wh.state = audit.stateId + AND audit.module = 'workershome' + $condition + """); + + Cnd cnd = Cnd.NEW(); + cnd.andEX("YEAR(applyTime)","=",year); + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())){ + cnd.and("unionId","=", SecurityUtil.getUnionId()); + } else { + if ("校工会".equals(unionId)){ + cnd.and("wh.category","=","校工会"); + } else { + cnd.andEX("unionId", "=", unionId); + } + } + sql.setCondition(cnd); + Pagination pagination = workersHomeInfoService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + + + @At + @ApiOperation("职工建家信息我的填报详情") + @SaCheckPermission(value = {"workershome.info.mine","workershome.info.apply"}, mode = SaMode.OR) + public Result getInfoById(String id){ + WorkersHome workersHome = workersHomeInfoService.fetch(id); + NutMap nutMap = Lang.obj2nutmap(workersHome); + Audit audit = workersHomeInfoService.dao().fetch(Audit.class, Cnd.where("id", "=", workersHome.getSchoolAuditId())); + if (Lang.isNotEmpty(audit)){ + nutMap.setv("schoolAudit",audit); + } + return Result.success().addData(nutMap); + } + + @At + @ApiOperation("职工建家信息我的填报删除") + @SaCheckPermission("workershome.info.mine") + @SLog(tag = "职工建家信息", msg = "职工建家信息删除id: ${args[0]}") + public Result doRemove(String id){ + workersHomeInfoService.delete(id); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeSchoolAuditController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeSchoolAuditController.java new file mode 100644 index 00000000..7f27b5e4 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/info/WorkersHomeSchoolAuditController.java @@ -0,0 +1,102 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.info; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.model.Audit; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.workershome.model.WorkersHome; +import com.budwk.app.zhgh.dayofficework.workershome.service.WorkersHomeInfoService; +import io.swagger.annotations.ApiOperation; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + + +@IocBean +@Ok("json:full") +@ApiOperation("职工建家信息校工会审核") +@At("/platform/workershome/info/schoolaudit") +public class WorkersHomeSchoolAuditController { + + @Inject + private WorkersHomeInfoService workersHomeInfoService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workershome/info/schoolAudit.html") + @SaCheckPermission("workershome.info.schoolaudit") + public void index() {} + + + @At + @ApiOperation("职工建家信息校工会审核列表") + @SaCheckPermission("workershome.info.schoolaudit") + public Result pageData(PageForm pageForm, @Param("year") Integer year, + @Param("unionId")String unionId, @Param("isAudit") String isAudit){ + Sql sql = Sqls.create(""" + SELECT + wh.*, + audit.stateName + FROM + `workers_home` wh + LEFT JOIN audit_state audit ON wh.state = audit.stateId + AND audit.module = 'workershome' + $condition + """); + + Cnd cnd = Cnd.NEW(); + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())){ + cnd.and("unionId", "=" , SecurityUtil.getUnionId()); + } else { + if ("校工会".equals(unionId)){ + cnd.and("wh.category","=","校工会"); + } else { + cnd.andEX("unionId", "=", unionId); + } + } + cnd.andEX("YEAR(applyTime)","=",year); + cnd.and("wh.state", "true".equals(isAudit) ? ">" : "false".equals(isAudit) ? "=" : ">=", 8120); + sql.setCondition(cnd); + Pagination pagination = workersHomeInfoService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + @At + @Aop(TransAop.READ_COMMITTED) + @ApiOperation("职工建家信息校工会审核") + @SaCheckPermission("workershome.info.schoolaudit") + @SLog(tag = "职工建家信息校工会审核", msg = "职工建家信息校工会审核id: ${args[1]}") + public Result doAudit(@Param("audit") Audit audit, String id, String isPass){ + workersHomeInfoService.dao().insert(audit); + workersHomeInfoService.update(Chain.make("state","1".equals(isPass) ? 8130 : 8125) + .add("schoolAuditId",audit.getId()), Cnd.where("id","=",id)); + return Result.success(); + } + + + @At + @Aop(TransAop.READ_COMMITTED) + @ApiOperation("职工建家信息校工会审核撤回") + @SaCheckPermission("workershome.info.schoolaudit") + @SLog(tag = "职工建家信息校工会审核撤回", msg = "职工建家信息校工会审核撤回id: ${args[0]}") + public Object doRollBack(String id){ + WorkersHome workersHome = workersHomeInfoService.fetch(id); + workersHomeInfoService.dao().clear(Audit.class,Cnd.where("id","=",workersHome.getSchoolAuditId())); + workersHomeInfoService.update(Chain.make("state",8120).add("schoolAuditId",null),Cnd.where("id","=",id)); + return null; + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewController.java new file mode 100644 index 00000000..b26bf0d7 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewController.java @@ -0,0 +1,115 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.review; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewPeo; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentZbService; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @version 1.0 + * @Author zzr + * @name:WorkersHomeReviewController + * @Date 2024/8/1 16:47 + * @注释 pc端职工评议 + */ +@IocBean +@Ok("json:full") +@ApiOperation("电脑端的职工评议") +@At("/platform/workershome/review/doReview") +public class WorkersHomeReviewController { + + @Inject + private CommentZbService commentZbService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workershome/review/doReview.html") + @SaCheckPermission("workershome.review.doReview") + public void index() { + } + + @At + @ApiOperation("职工评议分页数据") + @SaCheckPermission("workershome.review.doReview") + public Result pageData(PageForm pageForm, + @Param("annual") String annual, + @Param("assessment") String assessment){ + Sql sql = Sqls.create(""" + SELECT + zb.* , + if((select count(1) from comment_peo peo where peo.zbId = zb.id and peo.userId = @userId) > 0,true,false) as isReview + FROM + `comment_zb` zb + $condition + """).setParam("userId", SecurityUtil.getUserId()); + Cnd cnd = Cnd.NEW(); + if (Strings.isNotBlank(annual) && Strings.isNotBlank(annual)) { + cnd.and("zb.annual", "=", annual); + } + if (Strings.isNotBlank(assessment) && Strings.isNotBlank(assessment)) { + cnd.where().andLike("zb.assessment", assessment); + } else { + cnd.desc("zb.annual"); + } + sql.setCondition(cnd); + Pagination pagination = commentZbService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + List list = pagination.getList(); + List unionList = commentZbService.dao().query(Sys_union.class, Cnd.NEW()); + list.forEach(v -> { + //自评模式 + boolean reviewMode = v.getInt("reviewMode") == 1; + if (reviewMode && v.getInt("commentTarget") == 1) { + //校工会自评,判断有没有校工会管理员的权限 + v.put("canJoin", AuthUtil.hasRole(RoleConstant.SCHOOL_UNION_ADMIN.name())); + } else if (reviewMode && v.getInt("commentTarget") == 2){ + //分工会自评,判断有没有分工会管理员 + v.put("canJoin", AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())); + } + + //自选分工会的模式 + if (StrUtil.isNotBlank(v.getString("unionIds"))) { + List unionIdList = JSONUtil.parseArray(v.getString("unionIds")).toList(String.class); + String string = unionList.stream().filter(item -> unionIdList.contains(item.getId())) + .map(Sys_union::getName).collect(Collectors.joining(",")); + v.put("unionNames", string); + //如果是自评,只有分工会主席才能自评 + if (reviewMode) { + v.put("canJoin", (unionIdList.contains(SecurityUtil.getUnionId()) && AuthUtil.hasRole(RoleConstant.BRANCH_UNION_ADMIN.name()))); + } else { + v.put("canJoin", unionIdList.contains(SecurityUtil.getUnionId())); + } + } + }); + return Result.success().addData(pagination); + } + + + @At + @ApiOperation("判断当前用户是否已经评价") + @SaCheckPermission("workershome.review.doReview") + public Object getPeoId(String id){ + WorkersHomeReviewPeo peo = commentZbService.dao().fetch(WorkersHomeReviewPeo.class, Cnd.where("zbId", "=", id).and("userId", "=", SecurityUtil.getUserId())); + return Result.success().addData(peo.getId()); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewExportController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewExportController.java new file mode 100644 index 00000000..1e852ee2 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewExportController.java @@ -0,0 +1,267 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.review; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.ZipUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewExport; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewProxy; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentZbService; +import io.swagger.annotations.ApiOperation; +import org.apache.poi.util.IOUtils; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.net.URLEncoder; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @ClassName exportZpController + * @Description TODO + * @Author zhf + * @Date 2023/9/6 17:09 + */ +@IocBean +@Ok("json:full") +@ApiOperation("职工评议-导出") +@At("/platform/workershome/review/export") +public class WorkersHomeReviewExportController { + + +// @Inject +// private OfficeTemplateUtil officeTemplateUtil; + + @Inject + private Dao dao; + @Inject + private CommentZbService zbService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/unionComment/exportZp.html") + @SaCheckPermission("workerhome.review.export") + public void index() {} + + + @At + @ApiOperation("获取列表") + @SaCheckPermission("workerhome.review.export") + public Result pageData(@Param("annual") Integer annual, + int pageNumber, int pageSize) { + Sql sql = Sqls.create("SELECT YEAR(e.createTime) annual,e.* FROM `comment_export` e $condition"); + Cnd cnd = Cnd.NEW(); + cnd.andEX("YEAR(e.createTime)", "=", annual); + sql.setCondition(cnd); + Pagination pagination = zbService.listPageMap(pageNumber, pageSize, sql); + return Result.success().addData(pagination); + } + + + @At + @ApiOperation("获取指标列表") + @SaCheckPermission("workerhome.review.export") + public Result getZbData(@Param("annual") String annual, @Param("assessment") String assessment) { + Sql sql = Sqls.create("SELECT * FROM `comment_zb` $condition"); + Cnd cnd = Cnd.NEW(); + if (Strings.isNotBlank(annual) && Strings.isNotBlank(annual)) { + cnd.and("annual", "=", annual); + } + if (Strings.isNotBlank(assessment) && Strings.isNotBlank(assessment)) { + cnd.where().andLike("assessment", assessment); + } else { + cnd.desc("annual"); + } + sql.setCondition(cnd); + List list = zbService.listMap(sql); + return Result.success().addData(list); + } + + @At + @ApiOperation("添加导出内容") + @SaCheckPermission("workerhome.review.export") + public Result doAddExport(@Param("export") WorkersHomeReviewExport export) { + export.setCreateTime(DateUtil.now()); + if (StrUtil.isNotBlank(export.getId())) { + zbService.updateIgnoreNull(export); + } else { + zbService.insert(export); + } + return null; + } + + @At + @ApiOperation("删除导出内容") + @SaCheckPermission("workerhome.review.export") + @SLog(tag = "删除导出内容", msg = "删除到处内容id: ${args[0]}") + public Result doDelete(String id) { + zbService.dao().delete(WorkersHomeReviewExport.class, id); + return Result.success(); + } + + @At + @ApiOperation("获取导出内容") + @SaCheckPermission("workerhome.review.export") + public Result findOne(String id) { + WorkersHomeReviewExport export = zbService.dao().fetch(WorkersHomeReviewExport.class, id); + List zbList = zbService.query(Cnd.NEW().and("id", "in", export.getProxyIds()).asc("assessmentMode")); + Map data = Map.of("export", export, "zbList", zbList); + return Result.success().addData(data); + } + + + @At + @Ok("void") + @ApiOperation("导出") + @SaCheckPermission("workerhome.review.export") + public void doExport(String id, HttpServletResponse response) throws Exception { + WorkersHomeReviewExport export = zbService.dao().fetch(WorkersHomeReviewExport.class, id); + //查询测评有那几个工会测评过 + Sql sql = Sqls.create(""" + SELECT + un.id, + un.unionname unionName, + count( peo.id ) num + FROM + sys_union un + LEFT JOIN `user` u ON u.unionId = un.id + LEFT JOIN comment_peo peo ON peo.userId = u.id + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("peo.zbId", "in", export.getProxyIds()); + cnd.groupBy("un.id"); + cnd.desc("count( peo.id )"); + sql.setCondition(cnd); + List unionMap = zbService.listMap(sql); + + + List zbs = zbService.query(Cnd.NEW().and("id", "in", export.getProxyIds()).asc("assessmentMode")); + + //创建临时文件夹 + Path templateDir = Files.createTempDirectory("评测结果文件夹"); + + //循环分工会 + for (NutMap un : unionMap) { + List users = zbService.dao().query(View_user.class, Cnd.where("unionId", "=", un.getString("id"))); + + FileOutputStream outputStream = new FileOutputStream(templateDir.toString() + "/" + un.getString("unionName") + "基层工会会员评家民主测评结果报告表.docx"); + + List zpxxList = new ArrayList<>(); + for (WorkersHomeReviewProxy zb : zbs) { + + Sql sqlps = Sqls.create(""" + SELECT + SUM( CASE WHEN cp.reviewResult = '不满意' THEN 1 ELSE 0 END ) AS bmy, + SUM( CASE WHEN cp.reviewResult = '基本满意' THEN 1 ELSE 0 END ) AS jbmy, + SUM( CASE WHEN cp.reviewResult = '满意' THEN 1 ELSE 0 END ) AS my + FROM + comment_peo cp + LEFT JOIN `user` u ON u.id = cp.userId + $condition + """); + Cnd cndPs = Cnd.NEW(); + cndPs.and("u.unionId", "=", un.getString("id")); + cndPs.and("cp.zbId", "=", zb.getId()); + + sqlps.setCondition(cndPs); + if (zb.getAssessmentMode() == 1) { + NutMap zpxx = new NutMap(); + + sqlps.setCallback(Sqls.callback.map()); + dao.execute(sqlps); + NutMap psMap = (NutMap) sqlps.getResult(); + zpxx.setv("pcdx", "工会工作及职工之家建设情况测评"); + zpxx.setv("my", psMap.getInt("my")); + zpxx.setv("jbmy", psMap.getInt("jbmy")); + zpxx.setv("bmy", psMap.getInt("bmy")); + zpxxList.add(zpxx); + } else { + NutMap zpxxZx = new NutMap(); + Cnd clone = cndPs.clone(); + sqlps.setCondition(clone); + clone.and("cp.evaluatedPersonType", "=", "分工会主席"); + + sqlps.setCallback(Sqls.callback.map()); + dao.execute(sqlps); + NutMap psMap = (NutMap) sqlps.getResult(); + zpxxZx.setv("pcdx", "工会主席履职情况测评"); + zpxxZx.setv("my", psMap.getInt("my")); + zpxxZx.setv("jbmy", psMap.getInt("jbmy")); + zpxxZx.setv("bmy", psMap.getInt("bmy")); + zpxxList.add(zpxxZx); + + + NutMap zpxxFzx = new NutMap(); + Cnd clone2 = cndPs.clone(); + clone2.and("cp.evaluatedPersonType", "=", "分工会副主席"); + sqlps.setCondition(clone2); + + sqlps.setCallback(Sqls.callback.map()); + dao.execute(sqlps); + NutMap psMap2 = (NutMap) sqlps.getResult(); + zpxxFzx.setv("pcdx", "工会副主席履职情况测评"); + zpxxFzx.setv("my", psMap2.getInt("my")); + zpxxFzx.setv("jbmy", psMap2.getInt("jbmy")); + zpxxFzx.setv("bmy", psMap2.getInt("bmy")); + zpxxList.add(zpxxFzx); + } + + + } +// HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy(); +// HtmlRenderPolicy htmlRenderPolicy = new HtmlRenderPolicy(); +// htmlRenderPolicy.getConfig().setShowDefaultTableBorderInTableCell(true); +// +// Configure config = Configure.newBuilder().bind("zpxxList", policy).build(); + HashMap map = new HashMap<>(); + + map.put("zpxxList", zpxxList); + map.put("unionName", un.getString("unionName")); + map.put("num", users.size()); + map.put("memberNum", users.stream().filter(v -> v.getMember() == 1).collect(Collectors.toList()).size()); +// XWPFTemplate.compile(officeTemplateUtil.getPath("unionComment"), config).render(map).writeAndClose(outputStream); + + outputStream.close(); + } + + //压缩 + File zipFile = ZipUtil.zip(templateDir.toString()); + response.setHeader("content-disposition", "attachment;filename=" + + URLEncoder.encode(zipFile.getName(), "UTF-8")); + try (ServletOutputStream outputStream = response.getOutputStream(); + FileInputStream zipFis = new FileInputStream(zipFile);) { + IOUtils.copy(zipFis, outputStream); + } catch (Exception e) { + e.printStackTrace(); + } finally { + FileUtil.del(templateDir); + FileUtil.del(zipFile); + } + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewProxyController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewProxyController.java new file mode 100644 index 00000000..d1d830d8 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewProxyController.java @@ -0,0 +1,64 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.review; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewContent; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewProxy; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentZbService; +import io.swagger.annotations.ApiOperation; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @ClassName addZbController + * @Description TODO + * @Author zhf + * @Date 2023/9/4 15:42 + */ +@IocBean +@Ok("json:full") +@ApiOperation("职工评议-添加考核指标") +@At("/platform/workershome/review/proxy") +public class WorkersHomeReviewProxyController { + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workershome/review/xjkhzb.html") + @SaCheckPermission("workershome.review.proxy") + public void index() { + } + + @Inject + private CommentZbService commentZbService; + + @At + @ApiOperation("添加指标") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("workershome.review.proxy") + public Result doAdd(@Param("kh_zb") WorkersHomeReviewProxy commentZb) { + WorkersHomeReviewProxy zb = commentZbService.insert(commentZb); + for (WorkersHomeReviewContent nr : commentZb.getReviewContents()) { + nr.setProxyId(zb.getId()); + nr.getReviewNorms().forEach(v->v.setProxyId(zb.getId())); + commentZbService.insertWith(nr, "bzs"); + } + commentZbService.setGrading(zb); + return Result.success(); + + } + + @At + @ApiOperation("获取指标列表") + public Result getZbList(Integer year) { + List annual = commentZbService.query(Cnd.NEW().andEX("annual", "=", year)); + return Result.success(annual); + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewStatistics.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewStatistics.java new file mode 100644 index 00000000..d738c71b --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewStatistics.java @@ -0,0 +1,441 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.review; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_file; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewPeo; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewGrading; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewProxy; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentPeoService; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentStatisticsService; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentZbService; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.io.IOUtils; +import org.nutz.boot.starter.ftp.FtpService; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.random.R; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.net.URLEncoder; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/** + * @ClassName statisticsController + * @Description TODO + * @Author zhf + * @Date 2023/9/5 15:58 + */ +@IocBean +@Ok("json:full") +@ApiOperation("职工评议-统计") +@At("/platform/workershome/review/statistics") +public class WorkersHomeReviewStatistics { + + @Inject + private Dao dao; + @Inject + private FtpService ftpService; + @Inject + private CommentZbService commentZbService; + @Inject + private CommentPeoService commentPeoService; + @Inject + private CommentStatisticsService commentStatisticsService; + + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workershome/review/statistics.html") + @SaCheckPermission("workershome.review.statistics") + public void index() { + } + + @At + @ApiOperation("获取列表") + @SaCheckPermission("workershome.review.statistics") + public Result pageData(PageForm page, + @Param("zbId") String zbId, + @Param("unionId") String unionId) { + + WorkersHomeReviewProxy zb = commentPeoService.dao().fetch(WorkersHomeReviewProxy.class, Cnd.where("id", "=", zbId)); + Sql sql = Sqls.create(""" + SELECT + un.id, + un.unionname unionName, + IFNULL(grading.gradingName,'未定级') AS gradingName, + grading.isGrading, + count( peo.id ) num + FROM + sys_union un + LEFT JOIN `user` u ON u.unionId = un.id + LEFT JOIN comment_peo peo ON peo.userId = u.id AND peo.zbId = @zbId + LEFT JOIN comment_union_grading grading on un.id = grading.unionId AND grading.zbId = @zbId + $condition + """).setParam("zbId", zbId); + Cnd cnd = Cnd.NEW(); + + if (Lang.isNotEmpty(zb.getUnionIds())) { + cnd.and("un.id", "in", zb.getUnionIds()); + } else { + if (AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.andEX("un.id", "=", unionId); + } else { + cnd.and("un.id", "=", SecurityUtil.getUnionId()); + } + } + + cnd.groupBy("un.id"); + cnd.desc("count( peo.id )"); + sql.setCondition(cnd); + Pagination pagination = commentZbService.listPageMap(page.getPageNumber(), page.getPageSize(), sql); + return Result.success(pagination); + } + + + @At + @ApiOperation("获取个人评议或工会评议列表") + @SaCheckPermission("workershome.review.statistics") + public Result getUserPeoByZbIdOrUnionId(PageForm page, + @Param("zbId") String zbId, + @Param("unionId") String unionId, + @Param("reviewResult") String reviewResult) { + Sql sql = Sqls.create(""" + SELECT + peo.*, + u.loginname loginName, + unitname unitName + FROM + comment_peo peo + LEFT JOIN `user` u ON u.id = peo.userId + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("peo.zbId", "=", zbId); + cnd.andEX("u.unionId", "=", unionId); + cnd.andEX("peo.reviewResult", "=", reviewResult); + if (StrUtil.isNotBlank(page.getSearchKeyword())) { + SqlExpressionGroup sqlExpressionGroup = new SqlExpressionGroup(); + sqlExpressionGroup.orLike("u.loginname", page.getSearchKeyword()); + sqlExpressionGroup.orLike("u.username", page.getSearchKeyword()); + cnd.and(sqlExpressionGroup); + } + sql.setCondition(cnd); + Pagination pagination = commentZbService.listPageMap(page.getPageNumber(), page.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @ApiOperation("根据id获取评测内容") + @SaCheckPermission("workershome.review.statistics") + public Result getBzById(String peoId) { + NutMap map = commentPeoService.getBzById(peoId); + return Result.success(map); + + } + + @At + @ApiOperation("获取评价结果数量") + @SaCheckPermission("workershome.review.statistics") + public Result getReviewResultNum(@Param("zbId") String zbId, + @Param("unionId") String unionId) { + Sql sql = Sqls.create(""" + SELECT + SUM( CASE WHEN cp.reviewResult = '非常满意' THEN 1 ELSE 0 END ) AS fcmy, + SUM( CASE WHEN cp.reviewResult = '满意' THEN 1 ELSE 0 END ) AS my, + SUM( CASE WHEN cp.reviewResult = '良好' THEN 1 ELSE 0 END ) AS lh, + SUM( CASE WHEN cp.reviewResult = '一般' THEN 1 ELSE 0 END ) AS yb + FROM + comment_peo cp + LEFT JOIN `user` u ON u.id = cp.userId + WHERE + cp.zbId = @zbId + AND u.unionId = @unionId + """).setParam("zbId", zbId).setParam("unionId", unionId); + sql.setCallback(Sqls.callback.map()); + dao.execute(sql); + NutMap mapList = (NutMap) sql.getResult(); + return Result.success(mapList); + } + + + /** + * 分工会自评导出(单个) + * + * @param zbId + * @param unionId + * @param response + */ + @At + @Ok("void") + @ApiOperation("分工会自评导出(单个)") + @SaCheckPermission("workershome.review.statistics") + public void doDownLoadSingleByUnionId(String zbId, String unionId, HttpServletResponse response) { + WorkersHomeReviewPeo peo = commentZbService.dao().fetch(WorkersHomeReviewPeo.class, Cnd.where("unionId", "=", unionId).and("zbId", "=", zbId)); + + String fileName = peo.getUnionName() + "(" + peo.getUserName() + ")“模范教工小家”评议结果"; + try { + response.addHeader("Content-Type", "application/octet-stream"); + response.addHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1") + "\".docx"); + commentStatisticsService.exportWord(peo, response.getOutputStream()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + /** + * 分工会下所有测评结果导出(多个)压缩包 + * + * @param zbId + * @param unionId + * @param response + */ + @At + @Ok("void") + @ApiOperation("分工会下所有测评结果导出(多个)压缩包") + @SaCheckPermission("workershome.review.statistics") + public void doDownLoadZipByUnionId(String zbId, String unionId, HttpServletResponse response) { + try { + List peoList = commentPeoService.dao().query(WorkersHomeReviewPeo.class, Cnd.where("unionId", "=", unionId).and("zbId", "=", zbId)); + WorkersHomeReviewPeo commentPeo = peoList.stream().findFirst().orElse(new WorkersHomeReviewPeo()); + String zipName = commentPeo.getUnionName() + "评议结果.zip"; + response.setContentType("application/octet-stream"); + response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(zipName, "UTF-8")); + + ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream())); + for (WorkersHomeReviewPeo peo : peoList) { + String fileName = peo.getUnionName() + "(" + peo.getUserName() + ")“模范教工小家”评议结果.docx"; + zipOutputStream.putNextEntry(new ZipEntry(fileName)); + commentStatisticsService.exportWord(peo, zipOutputStream); + zipOutputStream.closeEntry(); + response.flushBuffer(); + } + zipOutputStream.flush(); + zipOutputStream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + /** + * 校验是否有附件 + * + * @param peoId 测评结果Id + * @param zbId 指标Id + * @param unionId 分工会Id + * @return + */ + @At + @ApiOperation("校验是否有附件") + @SaCheckPermission("workershome.review.statistics") + public Result validateHasFiles(@Param("peoId") String peoId, + @Param("zbId") String zbId, + @Param("unionId") String unionId) { + Cnd cnd = Cnd.NEW(); + cnd.andEX("id", "=", peoId); + cnd.andEX("zbId", "=", zbId); + cnd.andEX("unionId", "=", unionId); + List peoList = commentPeoService.dao().query(WorkersHomeReviewPeo.class, cnd); + List files; + try { + files = peoList.stream().flatMap(v -> v.getFiles().stream()).toList(); + } catch (NullPointerException e) { + return Result.error(); + } + if (Lang.isEmpty(files)) { + return Result.error(); + } else { + return Result.success(); + } + } + + + /** + * 分工会导出附件 + * + * @param zbId + * @param unionId + * @param response + */ + @At + @Ok("void") + @ApiOperation("分工会导出附件") + @SaCheckPermission("workershome.review.statistics") + public void exportFilesByUnionId(String zbId, String unionId, HttpServletResponse response) { + List peoList = commentPeoService.dao().query(WorkersHomeReviewPeo.class, Cnd.where("unionId", "=", unionId).and("zbId", "=", zbId)); + WorkersHomeReviewPeo commentPeo = peoList.stream().findFirst().orElse(new WorkersHomeReviewPeo()); + response.reset(); + response.setContentType("application/x-msdownload;charset=utf-8"); + + String tmpPath = "tmp/" + R.UU32(); + File tmpDir = new File(tmpPath + "/附件信息"); + tmpDir.mkdirs(); + + try { + for (WorkersHomeReviewPeo peo : peoList) { + String fileName = peo.getUnionName() + "(" + peo.getUserName() + ")"; + List files = peo.getFiles(); + + File tDir = new File(tmpDir + "/" + fileName); + tDir.mkdirs(); + + if (Lang.isNotEmpty(files)) { +// for (Sys_file file : files) { +// if (Lang.isNotEmpty(file)) { +// FileOutputStream outputStream = new FileOutputStream(tDir.getPath() + "/" + file.getFilename()); +// ftpService.download(file.getFilepath(), outputStream); +// outputStream.close(); +// } +// } + } + } + + String aimsDir = "zipTmp/" + R.UU32(); + String aimsName = commentPeo.getUnionName() + "评议信息.zip"; + String aimsPath = aimsDir + "/" + aimsName; +// FileUtil.compressToZip(tmpDir.getPath(), aimsDir, aimsName); + + response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(aimsName, "UTF-8")); + + File aimsFile = new File(aimsPath); + FileInputStream inputStream = new FileInputStream(aimsFile); + IOUtils.copy(inputStream, response.getOutputStream()); + inputStream.close(); + aimsFile.delete(); + +// FileUtil.deleteDir(new File(tmpPath)); +// FileUtil.deleteDir(new File(aimsDir)); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + + /** + * 个人上传附件导出 + * + * @param peoId + * @param response + */ + @At + @Ok("void") + @ApiOperation("个人上传附件导出") + @SaCheckPermission("workershome.review.statistics") + public void exportFilesByPeoId(String peoId, HttpServletResponse response) { + WorkersHomeReviewPeo peo = commentPeoService.dao().fetch(WorkersHomeReviewPeo.class, peoId); + List files = peo.getFiles(); + + response.reset(); + response.setContentType("application/x-msdownload;charset=utf-8"); + + String tmpPath = "tmp/" + R.UU32(); + File tmpDir = new File(tmpPath + "/个人附件信息"); + tmpDir.mkdirs(); + + try { + for (Sys_file file : files) { +// if (Lang.isNotEmpty(files)) { +// FileOutputStream out = new FileOutputStream(tmpDir.getPath() + "/" + file.getFilename()); +// ftpService.download(file.getFilepath(), out); +// out.close(); +// } + } + String aimsDir = "zipTmp/" + R.UU32(); + String aimsName = peo.getUnionName() + "(" + peo.getUserName() + ")个人附件信息.zip"; + String aimsPath = aimsDir + "/" + aimsName; +// FileUtil.compressToZip(tmpDir.getPath(), aimsDir, aimsName); + + response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(aimsName, "UTF-8")); + + File aimsFile = new File(aimsPath); + FileInputStream inputStream = new FileInputStream(aimsFile); + IOUtils.copy(inputStream, response.getOutputStream()); + inputStream.close(); + aimsFile.delete(); + +// FileUtil.deleteDir(new File(tmpPath)); +// FileUtil.deleteDir(new File(aimsDir)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + /** + * 个人评议结果导出(得分) + * + * @param peoId + * @param response + */ + @At + @Ok("void") + @ApiOperation("个人评议结果导出(得分)") + @SaCheckPermission("workershome.review.statistics") + public void exportByPeoId(String peoId, HttpServletResponse response) { + WorkersHomeReviewPeo peo = commentPeoService.dao().fetch(WorkersHomeReviewPeo.class, peoId); + + String fileName = peo.getUnionName() + "(" + peo.getUserName() + ")“模范教工小家”评议结果"; + try { + response.addHeader("Content-Type", "application/octet-stream"); + response.addHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1") + "\".docx"); + commentStatisticsService.exportWord(peo, response.getOutputStream()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + /** + * 导出所有分工会评议结果和附件信息 + * + * @param zbId + * @param response + */ + @At + @Ok("void") + @SaCheckPermission("workershome.review.statistics") + public void exportAllUnions(String zbId, HttpServletResponse response) { +// List peoList = commentPeoService.dao().query(CommentPeo.class, Cnd.where("zbId", "=", zbId)); + +// Map> collect = peoList.stream().collect(Collectors.groupingBy(CommentPeo::getUnionId)); + } + + + @At + @ApiOperation("评级") + @SaCheckPermission("workershome.review.statistics") + public Result doGrading(WorkersHomeReviewGrading grading){ + if (StrUtil.isAllBlank(grading.getProxyId(),grading.getUnionId(),grading.getGradingName())) { + return Result.error("必要参数为空"); + } + commentPeoService.dao().update(WorkersHomeReviewGrading.class, + Chain.make("isGrading",true).add("gradingName",grading.getGradingName()).add("gradingTime", DateUtil.now()), + Cnd.where("zbId","=",grading.getProxyId()).and("unionId","=",grading.getUnionId())); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewViewController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewViewController.java new file mode 100644 index 00000000..6d20d770 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/controller/review/WorkersHomeReviewViewController.java @@ -0,0 +1,165 @@ +package com.budwk.app.zhgh.dayofficework.workershome.controller.review; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewNorm; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewContent; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewProxy; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentBzService; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentNrService; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentZbService; +import io.swagger.annotations.ApiOperation; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.Strings; +import org.nutz.lang.random.R; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @ClassName viewZbController + * @Description TODO + * @Author zhf + * @Date 2023/9/4 16:00 + */ +@IocBean +@Ok("json:full") +@ApiOperation("指标查看") +@At("/platform/workershome/review/view") +public class WorkersHomeReviewViewController { + + + @Inject + private CommentZbService commentZbService; + + @Inject + private CommentNrService commentNrService; + + @Inject + private CommentBzService commentBzService; + + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workershome/review/khzb.html") + @SaCheckPermission("workerhome.review.view") + public void index() { + + } + + @At + @ApiOperation("指标查看分页数据") + @SaCheckPermission("workerhome.review.view") + public Result pageData(@Param("annual") String annual, + @Param("assessment") String assessment, + int pageNumber, int pageSize) { + Sql sql = Sqls.create("SELECT * FROM `comment_zb` $condition"); + Cnd cnd = Cnd.NEW(); + if (Strings.isNotBlank(annual) && Strings.isNotBlank(annual)) { + cnd.and("annual", "=", annual); + } + if (Strings.isNotBlank(assessment) && Strings.isNotBlank(assessment)) { + cnd.where().andLike("assessment", assessment); + } else { + cnd.desc("annual"); + } + sql.setCondition(cnd); + Pagination pagination = commentZbService.listPageMap(pageNumber, pageSize, sql); + return Result.success().addData(pagination); + } + + + @At + @ApiOperation("指标删除") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("workerhome.review.view") + @SLog(tag = "指标删除", msg = "指标删除id: ${args[0]}") + public Result delete(String id) { + commentZbService.delete(id); + List query = commentNrService.query(Cnd.where("zb_id", "=", id)); + + if (Lang.isNotEmpty(query)) { + List nrIds = query.stream().map(WorkersHomeReviewContent::getId).toList(); + commentBzService.clear(Cnd.where("nr_id", "in", nrIds)); + } + commentNrService.clear(Cnd.where("zb_id", "=", id)); + return Result.success(); + } + + + @At + @ApiOperation("获取编辑内容") + @SaCheckPermission("workerhome.review.view") + @SLog(tag = "获取编辑内容", msg = "编辑内容id: ${args[0]}") + public Result edit(String id) { + WorkersHomeReviewProxy khzb = commentZbService.khzb(id); + return Result.success().addData(khzb); + } + + + @At + @ApiOperation("指标编辑") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("workerhome.review.view") + @SLog(tag = "指标编辑", msg = "指标编辑id: ${args[0]}") + public Result doEdit(@Param("kh_zb") WorkersHomeReviewProxy commentZb) { + commentZbService.updateIgnoreNull(commentZb); + + List query = commentNrService.query(Cnd.where("zb_id", "=", commentZb.getId())); + + if (Lang.isNotEmpty(query)) { + List nrIds = query.stream().map(WorkersHomeReviewContent::getId).toList(); + commentBzService.clear(Cnd.where("nr_id", "in", nrIds)); + } + + commentNrService.clear(Cnd.where("zb_id", "=", commentZb.getId())); + List nrs = commentZb.getReviewContents(); + if (Lang.isNotEmpty(nrs)){ + nrs.forEach(v->{ + if (v.getId() == null) { + v.setId(R.UU32()); + } + Chain chain = Chain.make("id", v.getId()); + chain.add("zb_id",commentZb.getId()); + chain.add("content",v.getContent()); + chain.add("contentNumber",v.getContentNumber()); + chain.add("remark",v.getRemark()); + commentNrService.dao().insert(WorkersHomeReviewContent.class, chain); + + List bzs = v.getReviewNorms(); + bzs.forEach(b->{ + if (b.getId() == null) { + b.setId(R.UU32()); + } + Chain bzChain = Chain.make("id", b.getId()); + bzChain.add("nr_id",v.getId()); + bzChain.add("inspection",b.getInspection()); + bzChain.add("score",b.getScore()); + bzChain.add("single_score",b.getSingleScore()); + bzChain.add("zb_id",commentZb.getId()); + bzChain.add("contentNumber",b.getContentNumber()); + commentNrService.dao().insert(WorkersHomeReviewNorm.class, bzChain); + + }); + + + }); + + } + commentZbService.setGrading(commentZb); + return Result.success(); + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/h5controller/MWorkersHomeReviewController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/h5controller/MWorkersHomeReviewController.java new file mode 100644 index 00000000..c3cbde94 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/h5controller/MWorkersHomeReviewController.java @@ -0,0 +1,301 @@ +package com.budwk.app.zhgh.dayofficework.workershome.h5controller; + + +import cn.dev33.satoken.annotation.SaCheckLogin; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewNorm; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewPeo; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewResult; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentPeoService; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentZbService; +import com.budwk.app.zhgh.dayofficework.workershome.vo.WakesHomeVo; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.Static; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@IocBean +@At("/mobile/workershome/review/appraisal") +@Ok("json:full") +public class MWorkersHomeReviewController { + + @Inject + private CommentZbService commentZbService; + + @Inject + private BaseService baseService; + + @Inject + private CommentPeoService commentPeoService; + + @At + @Ok("beetl:/mobile/workershome/review/appraisal.html") + @SaCheckLogin + public void index() { + } + + @At + @Ok("beetl:/mobile/workershome/review/commentator.html") + @SaCheckLogin + public void commentator() { + } + + + @At + @Ok("beetl:/mobile/workershome/review/mine.html") + @SaCheckLogin + public void mine() { + } + + + /** + * 民主测评首页展示 + * + * @param pageForm + * @param annual + * @return + */ + @At + @SaCheckPermission + public Object pageData(PageForm pageForm, + @Param("annual") String annual, + @Param("type") Integer type) { + Sql sql = Sqls.create("SELECT * FROM `comment_zb` $condition"); + Cnd cnd = Cnd.NEW(); + if (Strings.isNotBlank(annual) && Strings.isNotBlank(annual)) { + cnd.and("annual", "=", annual); + } + switch (type) { + //进行中 + case 2 -> cnd.and(new Static("now() >= startTime and now() <= endTime")); + //已结束 + case 3 -> cnd.and(new Static("now() > endTime")); + //未开始 + case 4 -> cnd.and(new Static("now() < startTime")); + } + sql.setCondition(cnd); + Pagination pagination = commentZbService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + List list = pagination.getList(); + List unionList = commentZbService.dao().query(Sys_union.class, Cnd.NEW()); + list.forEach(v -> { + //自评模式 + boolean reviewMode = v.getInt("reviewMode") == 1; + if (reviewMode && v.getInt("commentTarget") == 1) { + //校工会自评,判断有没有校工会管理员的权限 + v.put("canJoin", AuthUtil.hasRole(RoleConstant.SCHOOL_UNION_ADMIN.name())); + } else if (reviewMode && v.getInt("commentTarget") == 2) { + //分工会自评,判断有没有分工会管理员 + v.put("canJoin", AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())); + } + + //自选分工会的模式 + if (StrUtil.isNotBlank(v.getString("unionIds"))) { + List unionIdList = JSONUtil.parseArray(v.getString("unionIds")).toList(String.class); + String string = unionList.stream().filter(item -> unionIdList.contains(item.getId())) + .map(Sys_union::getName).collect(Collectors.joining(",")); + v.put("unionNames", string); + //如果是自评,只有分工会主席才能自评 + if (reviewMode) { + v.put("canJoin", (unionIdList.contains(SecurityUtil.getUnionId()) && AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name()))); + } else { + v.put("canJoin", unionIdList.contains(SecurityUtil.getUnionId())); + } + } + }); + return pagination; + } + + + /** + * 根据id获取测评内容 + * + * @param id + * @return + */ + @At + @SaCheckPermission + public Object getById(String id) { + return commentZbService.khzb(id); + } + + + @At + @Aop(TransAop.READ_COMMITTED) + public Object doSubmit(WakesHomeVo wakesHomeVo) { + try { + View_user user = baseService.dao().fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId())); + WorkersHomeReviewPeo peo = new WorkersHomeReviewPeo(); + if (Strings.isNotBlank(wakesHomeVo.getEvaluatedPersonId())) { + peo.setEvaluatedPersonId(wakesHomeVo.getEvaluatedPersonId()); + peo.setEvaluatedPersonName(wakesHomeVo.getEvaluatedPersonName()); + peo.setEvaluatedPersonType(wakesHomeVo.getEvaluatedPersonType()); + } + peo.setReviewResult(wakesHomeVo.getReviewResult()); + peo.setProxyId(wakesHomeVo.getId()); + peo.setReviewTime(DateUtil.now()); +// peo.setFiles(wakesHomeVo.getFiles()); + peo.setUserId(user.getId()); + peo.setUserName(user.getUsername()); + peo.setUnionId(user.getUnionId()); + peo.setUnionName(user.getUnionName()); + if (Strings.isNotBlank(wakesHomeVo.getPresidentOpinions())) { + peo.setPresidentOpinions(wakesHomeVo.getPresidentOpinions()); + } + baseService.dao().insert(peo); + List commentResults = new ArrayList<>(); + for (WorkersHomeReviewNorm v : wakesHomeVo.getBzList()) { + WorkersHomeReviewResult result = new WorkersHomeReviewResult(); + result.setProxyId(v.getId()); + result.setAssessResult(v.getResultScore()); + result.setRecommendation(v.getOptions() != null ? v.getOptions() : null); + result.setPeoId(peo.getId()); + commentResults.add(result); + } + baseService.dao().insert(commentResults); + return Result.success(); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(); + } + } + + + /** + * 判断是否测评过 + * + * @param id 指标id + * @param evaluatedPersonId 被测评人id + * @return + */ + @At + public Object isAssess(@Param("id") String id, + @Param("evaluatedPersonId") String evaluatedPersonId) { + //主席测评 + if (Strings.isNotBlank(evaluatedPersonId)) { + Cnd cnd = Cnd.NEW(); + cnd.and("evaluatedPersonId", "=", evaluatedPersonId); + cnd.and("userId", "=", SecurityUtil.getUserId()); + cnd.and("zbId", "=", id); + return Result.success().addData(baseService.dao().count(WorkersHomeReviewPeo.class, cnd)); + } else {//会员评家测评 + Sql sql = Sqls.create(""" + SELECT + cp.*, + cz.annual, + cz.assessment, + cz.assessmentMode, + cz.scoringMode, + cz.commentTarget + FROM + `comment_peo` cp + LEFT JOIN `comment_zb` cz ON cz.id = cp.zbId + where cp.zbId=@zbId and cp.userId=@userId + """).setParam("zbId", id).setParam("userId", SecurityUtil.getUserId()); + List list = baseService.listMap(sql); + NutMap nutMap = list.stream().findFirst().orElse(null); + if (nutMap != null && Strings.isNotBlank(nutMap.getString("commentTarget")) && "1".equals(nutMap.getString("assessmentMode"))) { + return Result.success().addData(1); + } else { + return Result.success().addData(0); + } + } + } + + + /** + * 我的测评页面展示 + * + * @param pageForm + * @param annual + * @return + */ + @At + public Object onLoad(PageForm pageForm, + @Param("annual") String annual) { + Sql sql = Sqls.create(""" + SELECT + cp.*, + cz.annual, + cz.assessment, + cz.assessmentMode, + cz.scoringMode, + cz.commentTarget + FROM + `comment_peo` cp + LEFT JOIN `comment_zb` cz ON cz.id = cp.zbId + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("cz.annual", "=", annual); + cnd.and("cp.userId", "=", SecurityUtil.getUserId()); + cnd.desc("cp.reviewTime"); + sql.setCondition(cnd); + return baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + } + + + /** + * 获取测评结果信息 + * + * @param peoId + * @return + */ + @At + public Object getBzById(@Param("peoId") String peoId) { + return commentPeoService.getBzById(peoId); + } + + /** + * 获取分工会主席和副主席 + * + * @return + */ + @At + public Object getPresidents() { + Sql sql = Sqls.create(""" + SELECT + u.id, + u.loginname, + u.username, + sr.`name` evaluatedPersonType, + GROUP_CONCAT( DISTINCT u.username, '(', sr.`name`, ')' ) presidents + FROM + `user` u + LEFT JOIN `sys_user_role` sur ON u.id = sur.userId + LEFT JOIN `sys_role` sr ON sur.roleId = sr.id + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("sr.`code`", "in", List.of(RoleConstant.BRANCH_UNION_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_VICE_CHAIRMAN.name())); + cnd.and("u.unionid", "=", SecurityUtil.getUnionId()); + cnd.groupBy("u.id"); + cnd.asc("u.loginname"); + sql.setCondition(cnd); + return baseService.listMap(sql); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHome.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHome.java new file mode 100644 index 00000000..7e73320e --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHome.java @@ -0,0 +1,130 @@ +package com.budwk.app.zhgh.dayofficework.workershome.model; + +import cn.hutool.json.JSONObject; +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serializable; +import java.util.List; + +/** + * @author mayn + */ +@Data +@Table +@Comment("职工小家-职工小家表") +@EqualsAndHashCode(callSuper = true) +public class WorkersHome extends BaseModel { + + @Name + @Column + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("填报人") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String username; + + @Column + @Comment("联系方式") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String mobile; + + @Column + @Comment("所属工会id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("工会名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionName; + + @Column + @Comment("填报时间") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String applyTime; + + @Column + @Comment("填报类别(校工会/分工会)") + @ColDefine(type = ColType.VARCHAR, width = 10) + private String category; + + @Column + @Comment("创办时间") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String foundTime; + + @Column + @Comment("单位位置") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String position; + + @Column + @Comment("单位面积") + @ColDefine(type = ColType.VARCHAR, width = 10) + private String area; + + @Column + @Comment("单位信息") + @ColDefine(type = ColType.TEXT) + private String details; + + @Column + @Comment("获奖情况") + @ColDefine(type = ColType.MYSQL_JSON) + private List awardInfo; + + @Column + @Comment("图片文件") + @ColDefine(type = ColType.MYSQL_JSON) + private List picFiles; + + @Column + @Comment("附件") + @ColDefine(type = ColType.MYSQL_JSON) + private List files; + + @Column + @Comment("分工会审核id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionAuditId; + + @Column + @Comment("校工会审核id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String schoolAuditId; + + @Column + @Comment("状态") + @ColDefine(type = ColType.INT) + private Integer state; + + + @Data + public static class AwardInfo implements Serializable { + /** + * 获奖日期 + */ + private String awardTime; + /** + * 获奖单位 + */ + private String awardUnit; + /** + * 奖项名称 + */ + private String awardName; + /** + * 奖项照片 + */ + private String awardPic; + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHomeApply.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHomeApply.java new file mode 100644 index 00000000..7ac1ceda --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHomeApply.java @@ -0,0 +1,130 @@ +package com.budwk.app.zhgh.dayofficework.workershome.model; + +import cn.hutool.json.JSONObject; +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serializable; +import java.util.List; + +/** + * @version 1.0 + * @Author zzr + * @name:WakesHomeApply + * @Date 2024/7/31 10:47 + * @注释 职工之家申报 + */ +@Data +@Table +@Comment("职工之家申报") +@EqualsAndHashCode(callSuper = true) +public class WorkersHomeApply extends BaseModel implements Serializable { + + private static final long serialVersionUID = 1L; + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("申报人id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String userId; + + @Column + @Comment("申报人工号") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String loginName; + + @Column + @Comment("申报人姓名") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String username; + + @Column + @Comment("申报人单位id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("申报人单位名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unitName; + + @Column + @Comment("申报人工会Id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("申报人工会名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionName; + + @Column + @Comment("联系电话") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String mobile; + + @Column + @Comment("基本情况简介(500字内)") + @ColDefine(type = ColType.TEXT) + private String basicInformation; + + @Column + @Comment("建设方案") + @ColDefine(type = ColType.TEXT) + private String constructionPlan; + + @Column + @Comment("基层党组织审核Id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String organizationAuditId; + + @Column + @Comment("校工会审核Id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String schoolAuditId; + + //10000待提交;10010待基层党组织审核;10020待校工会审核;10030审核通过 + @Column + @Comment("当前状态") + @ColDefine(type = ColType.VARCHAR, width = 10) + private String state; + + @Column + @Comment("申报时间") + @ColDefine(type = ColType.DATE) + private String applyDate; + + @Column + @Comment("创办时间") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String foundTime; + + @Column + @Comment("单位位置") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String position; + + @Column + @Comment("单位面积") + @ColDefine(type = ColType.VARCHAR, width = 10) + private String area; + + @Column + @Comment("单位信息") + @ColDefine(type = ColType.TEXT) + private String details; + + @Column + @Comment("附件") + @ColDefine(type = ColType.MYSQL_JSON) + private List files; +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHomeDataRevel.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHomeDataRevel.java new file mode 100644 index 00000000..058b08a7 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHomeDataRevel.java @@ -0,0 +1,95 @@ +package com.budwk.app.zhgh.dayofficework.workershome.model; + +import com.budwk.app.base.model.BaseModel; +import com.budwk.app.sys.models.Sys_file; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.util.List; + +/** + * @version 1.0 + * @Author zzr + * @name:WakesHomeDataRevel + * @Date 2024/7/30 15:29 + * @注释 职工建家资料管理 + */ +@Data +@Table +@Comment("职工建家资料管理") +@EqualsAndHashCode(callSuper = true) +public class WorkersHomeDataRevel extends BaseModel { + + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("资料名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String revelName; + + @Column + @Comment("上传人id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String userId; + + @Column + @Comment("上传人工号") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String loginName; + + @Column + @Comment("上传人姓名") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String username; + + @Column + @Comment("上传人单位id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("上传人单位名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String unitName; + + @Column + @Comment("上传人工会id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("上传人工会名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String unionName; + + @Column + @Comment("资料归属分工会id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String belongToUnionId; + + @Column + @Comment("资料归属分工会名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String belongToUnionName; + + @Column + @Comment("上传时间") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String time; + + @Column + @Comment("类型Id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String typeId; + + @Column + @Comment("附件") + @ColDefine(type = ColType.MYSQL_JSON) + private List files; +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHomeDataType.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHomeDataType.java new file mode 100644 index 00000000..f278f41a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/WorkersHomeDataType.java @@ -0,0 +1,43 @@ +package com.budwk.app.zhgh.dayofficework.workershome.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +/** + * @version 1.0 + * @Author zzr + * @name:WakesHomeDataType + * @Date 2024/7/30 15:29 + * @注释 职工建家资料类型管理 + */ +@Data +@Table +@Comment("职工建家资料类型管理") +@EqualsAndHashCode(callSuper = true) +public class WorkersHomeDataType extends BaseModel { + + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("类型编码") + @ColDefine(type = ColType.VARCHAR, width = 10) + private String code; + + @Column + @Comment("工作资料类型名称") + @ColDefine(type = ColType.VARCHAR, width = 80) + private String typeName; + + @Column + @Comment("序号") + @ColDefine(type = ColType.INT) + private Integer serialNum; + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewContent.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewContent.java new file mode 100644 index 00000000..700e07e7 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewContent.java @@ -0,0 +1,58 @@ +package com.budwk.app.zhgh.dayofficework.workershome.model.review; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +import java.util.List; + +/** + * @ClassName CommentNr + * @Description TODO + * @Author zhf + * @Date 2023/9/4 16:13 + */ +@Data +@Table +@Comment("职工小家-评议内容") +@EqualsAndHashCode(callSuper = true) +public class WorkersHomeReviewContent extends BaseModel { + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + @Column + @Comment("考核内容") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String content; + + @Column + @Comment("题号") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String contentNumber; + + @Column + @Comment("指标id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String proxyId; + + @One(field = "proxyId",key = "id") + private WorkersHomeReviewProxy reviewProxy; + + @Many(field = "contentId") + private List reviewNorms; + + @Column + @Comment("排序字段") + private Integer location; + + @Column + @Comment("备注") + @ColDefine(type = ColType.TEXT) + private String remark; +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewExport.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewExport.java new file mode 100644 index 00000000..bceb0eef --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewExport.java @@ -0,0 +1,49 @@ +package com.budwk.app.zhgh.dayofficework.workershome.model.review; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +import java.util.List; + +/** + * @ClassName CommentExport + * @Description TODO + * @Author zhf + * @Date 2023/9/7 15:19 + */ +@Data +@Table +@Comment("职工小家-评议导出") +@EqualsAndHashCode(callSuper = true) +public class WorkersHomeReviewExport extends BaseModel { + + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + + @Column + @Comment("导出的名称") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String exportName; + + // 指标id + @Column + @Comment("proxyIds") + @ColDefine(type = ColType.MYSQL_JSON) + private List proxyIds; + + + @Column + @Comment("创建时间") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String createTime; + + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewGrading.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewGrading.java new file mode 100644 index 00000000..dfa3f71f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewGrading.java @@ -0,0 +1,66 @@ +package com.budwk.app.zhgh.dayofficework.workershome.model.review; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +import java.util.Date; + +/** + * @version 1.0 + * @Author zzr + * @name:CommentUnionGrading + * @Date 2024/9/19 8:48 + * @注释 校工会给分工会定级 + */ +@Data +@Table +@Comment("校工会给分工会定级表") +@EqualsAndHashCode(callSuper = true) +public class WorkersHomeReviewGrading extends BaseModel { + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + @Column + @Comment("考核指标id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String proxyId; + + @Column + @Comment("定级的分工会id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("分工会名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionName; + + @Column + @Comment("分工会编码") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionCode; + + @Column + @Comment("定级的名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String gradingName; + + @Column + @Default("0") + @Comment("是否定级") + @ColDefine(type = ColType.BOOLEAN) + private Boolean isGrading; + + @Column + @Comment("定级时间") + @ColDefine(type = ColType.DATETIME) + private Date gradingTime; + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewNorm.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewNorm.java new file mode 100644 index 00000000..8e3c95d6 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewNorm.java @@ -0,0 +1,97 @@ +package com.budwk.app.zhgh.dayofficework.workershome.model.review; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +/** + * @ClassName CommentBz + * @Description TODO + * @Author zhf + * @Date 2023/9/4 16:24 + * 职工小家评议标准 + */ +@Data +@Table +@Comment("职工小家-评议标准") +@EqualsAndHashCode(callSuper = true) +public class WorkersHomeReviewNorm extends BaseModel { + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + + @Column + @Comment("内容id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String contentId; + + + @Column + @Comment("考核标准") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String inspection; + + + @Column + @Comment("是否启用佐证材料") + @ColDefine(type = ColType.BOOLEAN) + private boolean isEvidence; + + @Column + @Comment("标准分") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String score; + + @Column + @Comment("单项得分") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String singleScore; + + @Column + @Comment("自评能否超过最高分") + @ColDefine(type = ColType.BOOLEAN) + private boolean beyondHighestScore; + + @Column + @Comment("关联模块") + @ColDefine(type = ColType.VARCHAR,width = 100) + private String associatedModule; + + @Column + @Comment("标准标识") + @ColDefine(type = ColType.VARCHAR,width = 100) + private String normRelationId; + + @Column + @Comment("指标id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String proxyId; + + + @Column + @Comment("题号") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String contentNumber; + + @Column + @Comment("排序字段") + private Integer location; + + @Column + @Comment("能否删除该项") + @ColDefine(type = ColType.BOOLEAN) + private boolean canDelete; + + @One(field = "contentId", key = "id") + private WorkersHomeReviewContent reviewContent; + + private String resultScore; + + private String options; +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewPeo.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewPeo.java new file mode 100644 index 00000000..468cdb2e --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewPeo.java @@ -0,0 +1,93 @@ +package com.budwk.app.zhgh.dayofficework.workershome.model.review; + + +import com.budwk.app.base.model.BaseModel; +import com.budwk.app.sys.models.Sys_file; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +import java.util.List; + +/** + * @author mayn + */ +@Data +@Table +@Comment("职工小家-测评人记录") +@EqualsAndHashCode(callSuper = true) +public class WorkersHomeReviewPeo extends BaseModel { + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + @Column + @Comment("测评人") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String userId; + + @Column + @Comment("测评人姓名") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String userName; + + @Column + @Comment("测评人工会id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("测评人工会名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionName; + + @Column + @Comment("被测评人id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String evaluatedPersonId; + + @Column + @Comment("被测评人姓名") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String evaluatedPersonName; + + @Column + @Comment("被测评人职务(主席/副主席)") + @ColDefine(type = ColType.VARCHAR, width = 10) + private String evaluatedPersonType; + + + @Column + @Comment("指标id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String proxyId; + + @Column + @Comment("主席测评意见") + @ColDefine(type = ColType.TEXT) + private String presidentOpinions; + + @Column + @Comment("评测结果") + @ColDefine(type = ColType.VARCHAR,width = 10) + private String reviewResult; + + @Column + @Comment("测评时间") + @ColDefine(type = ColType.VARCHAR,width = 20) + private String reviewTime; + + + @Many(field = "peoId") + private List resultList; + + + @Column + @Comment("自我测评的附件") + @ColDefine(type = ColType.MYSQL_JSON) + private List files; +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewProxy.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewProxy.java new file mode 100644 index 00000000..c61ba0b1 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewProxy.java @@ -0,0 +1,96 @@ +package com.budwk.app.zhgh.dayofficework.workershome.model.review; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +import java.util.Date; +import java.util.List; + +/** + * @ClassName CommentZb + * @Description TODO + * @Author zhf + * @Date 2023/9/4 15:39 + * 评议指标 + */ +@Data +@Table +@Comment("职工小家-评议指标") +@EqualsAndHashCode(callSuper = true) +public class WorkersHomeReviewProxy extends BaseModel { + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + @Column + @Comment("年度") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String annual; + + @Column + @Comment("考核名称") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String assessment; + + @Column + @Comment("添加时间") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String addTime; + + @Column + @Comment("评议选项(1.工会评家2.主席评家)") + @ColDefine(type = ColType.INT) + private Integer assessmentMode; + + @Column + @Comment("可报名范围组别") + @ColDefine(type = ColType.VARCHAR, width = 32) + private Integer activityGroupId; + + @Column + @Comment("评议范围(1.校工会 2.全部分工会 3.自选分工会)") + @ColDefine(type = ColType.INT) + private Integer commentTarget; + + @Column + @Comment("打分模式(1.评分模式2.选择满意不满意模式)") + @ColDefine(type = ColType.INT) + private Integer scoringMode; + + + @Many(field = "proxyId") + private List reviewContents; + + @Column + @Comment("排序字段") + private Integer location; + + + @Column + @Comment("自选分工会Id") + @ColDefine(type = ColType.MYSQL_JSON) + private List unionIds; + + @Column + @Comment("评议开始时间") + @ColDefine(type = ColType.DATETIME) + private Date startTime; + + + @Column + @Comment("评议结束时间") + @ColDefine(type = ColType.DATETIME) + private Date endTime; + + + @Column + @Comment("评议模式(1.自评模式 2.教职工评议)") + @ColDefine(type = ColType.INT) + private Integer reviewMode; +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewResult.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewResult.java new file mode 100644 index 00000000..b9e7cba5 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/model/review/WorkersHomeReviewResult.java @@ -0,0 +1,52 @@ +package com.budwk.app.zhgh.dayofficework.workershome.model.review; + + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +/** + * @author mayn + */ +@Data +@Table +@Comment("职工小家-评测结果表") +@EqualsAndHashCode(callSuper = true) +public class WorkersHomeReviewResult extends BaseModel { + + @Column + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Prev(els = {@EL("uuid()")}) + private String id; + + + @Column + @Comment("测评人表id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String peoId; + + + @Column + @Comment("测评标准id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String proxyId; + + + @Column + @Comment("测评分数/满意度") + @ColDefine(type = ColType.VARCHAR, width = 10) + private String assessResult; + + + @Column + @Comment("会员评家意见或建议") + @ColDefine(type = ColType.TEXT) + private String recommendation; + + + @One(field = "peoId",key = "id") + private WorkersHomeReviewPeo reviewPeo; +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/WorkersHomeApplyService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/WorkersHomeApplyService.java new file mode 100644 index 00000000..5b0eb889 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/WorkersHomeApplyService.java @@ -0,0 +1,28 @@ +package com.budwk.app.zhgh.dayofficework.workershome.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.dayofficework.workershome.model.WorkersHomeApply; +import org.nutz.lang.util.NutMap; + +/** + * @version 1.0 + * @Author zzr + * @name:WorkersHomeApplyService + * @Date 2024/7/31 11:09 + * @注释 + */ +public interface WorkersHomeApplyService extends BaseService { + + /** + * 根据id获取信息 + * @param id + * @return + */ + NutMap findById(String id); + + /** + * 设置参数 + * @param wakesHomeApply + */ + void setParams(WorkersHomeApply wakesHomeApply); +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/WorkersHomeInfoService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/WorkersHomeInfoService.java new file mode 100644 index 00000000..dca80ab3 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/WorkersHomeInfoService.java @@ -0,0 +1,7 @@ +package com.budwk.app.zhgh.dayofficework.workershome.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.dayofficework.workershome.model.WorkersHome; + +public interface WorkersHomeInfoService extends BaseService { +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/WorkersHomeApplyServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/WorkersHomeApplyServiceImpl.java new file mode 100644 index 00000000..c62842d5 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/WorkersHomeApplyServiceImpl.java @@ -0,0 +1,58 @@ +package com.budwk.app.zhgh.dayofficework.workershome.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.model.Audit; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.workershome.model.WorkersHomeApply; +import com.budwk.app.zhgh.dayofficework.workershome.service.WorkersHomeApplyService; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.random.R; +import org.nutz.lang.util.NutMap; + +/** + * @version 1.0 + * @Author zzr + * @name:WakesHomeApplyServiceImpl + * @Date 2024/7/31 11:10 + * @注释 + */ +@IocBean(args = {"refer:dao"}) +public class WorkersHomeApplyServiceImpl extends BaseServiceImpl implements WorkersHomeApplyService { + public WorkersHomeApplyServiceImpl(Dao dao) { + super(dao); + } + + + @Override + public NutMap findById(String id) { + WorkersHomeApply apply = fetch(id); + NutMap nutMap = Lang.obj2nutmap(apply); + if (StrUtil.isNotBlank(apply.getOrganizationAuditId())) { + Audit audit = dao().fetch(Audit.class, Cnd.where("id", "=", apply.getOrganizationAuditId())); + nutMap.put("organizationAudit", Lang.obj2nutmap(audit)); + } + if (StrUtil.isNotBlank(apply.getSchoolAuditId())) { + Audit audit = dao().fetch(Audit.class, Cnd.where("id", "=", apply.getSchoolAuditId())); + nutMap.put("schoolAudit", Lang.obj2nutmap(audit)); + } + return nutMap; + } + + + @Override + public void setParams(WorkersHomeApply wakesHomeApply) { + View_user user = dao().fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId())); + wakesHomeApply.setId(R.UU32()); + wakesHomeApply.setApplyDate(DateUtil.today()); + wakesHomeApply.setUnitId(user.getUnitId()); + wakesHomeApply.setUnitName(user.getUnitName()); + wakesHomeApply.setUnionId(user.getUnionId()); + wakesHomeApply.setUnionName(user.getUnionName()); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/WorkersHomeInfoServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/WorkersHomeInfoServiceImpl.java new file mode 100644 index 00000000..9fc20459 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/WorkersHomeInfoServiceImpl.java @@ -0,0 +1,14 @@ +package com.budwk.app.zhgh.dayofficework.workershome.service.impl; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.dayofficework.workershome.model.WorkersHome; +import com.budwk.app.zhgh.dayofficework.workershome.service.WorkersHomeInfoService; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +@IocBean(args = {"refer:dao"}) +public class WorkersHomeInfoServiceImpl extends BaseServiceImpl implements WorkersHomeInfoService { + public WorkersHomeInfoServiceImpl(Dao dao) { + super(dao); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentBzServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentBzServiceImpl.java new file mode 100644 index 00000000..9422d5d6 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentBzServiceImpl.java @@ -0,0 +1,20 @@ +package com.budwk.app.zhgh.dayofficework.workershome.service.impl.review; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewNorm; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentBzService; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +/** + * @ClassName CommentBzServiceImpl + * @Description TODO + * @Author zhf + * @Date 2023/9/4 16:30 + */ +@IocBean(args = {"refer:dao"}) +public class CommentBzServiceImpl extends BaseServiceImpl implements CommentBzService { + public CommentBzServiceImpl(Dao dao) { + super(dao); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentNrServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentNrServiceImpl.java new file mode 100644 index 00000000..0289068f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentNrServiceImpl.java @@ -0,0 +1,20 @@ +package com.budwk.app.zhgh.dayofficework.workershome.service.impl.review; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewContent; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentNrService; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +/** + * @ClassName CommentNrServiceImpl + * @Description TODO + * @Author zhf + * @Date 2023/9/4 16:28 + */ +@IocBean(args = {"refer:dao"}) +public class CommentNrServiceImpl extends BaseServiceImpl implements CommentNrService { + public CommentNrServiceImpl(Dao dao) { + super(dao); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentPeoServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentPeoServiceImpl.java new file mode 100644 index 00000000..28af909e --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentPeoServiceImpl.java @@ -0,0 +1,64 @@ +package com.budwk.app.zhgh.dayofficework.workershome.service.impl.review; + + +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewContent; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewPeo; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewResult; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewProxy; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentPeoService; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentZbService; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@IocBean(args = {"refer:dao"}) +public class CommentPeoServiceImpl extends BaseServiceImpl implements CommentPeoService { + + public CommentPeoServiceImpl(Dao dao) {super(dao);} + + @Inject + private BaseService baseService; + + @Inject + private CommentZbService commentZbService; + + /** + * 获取测评结果信息 + * @param peoId 指标id + * @return + */ + @Override + public NutMap getBzById(String peoId) { + WorkersHomeReviewPeo commentPeo = fetch(peoId); + List query = baseService.dao().query(WorkersHomeReviewResult.class, Cnd.where("peo_id","=",peoId)); + //对测评标准分组 + Map commentResultMap = query.stream().collect(Collectors.toMap(v -> v.getProxyId(), v -> v)); + //获取指标 + WorkersHomeReviewProxy khzb = commentZbService.khzb(commentPeo.getProxyId()); + List nrs = khzb.getReviewContents(); + nrs.forEach(v->{ + v.getReviewNorms().forEach(o->{ + //赋值测评结果 + WorkersHomeReviewResult result = commentResultMap.get(o.getId()); + if (Lang.isNotEmpty(result)){ + o.setOptions(StrUtil.isNotBlank(result.getRecommendation()) ? result.getRecommendation() : "未填写此项"); + o.setResultScore(result.getAssessResult()); + } + }); + }); + NutMap nutMap = new NutMap(); + nutMap.setv("zbxx",khzb); + nutMap.setv("commentPeo",commentPeo); + return nutMap; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentStatisticsServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentStatisticsServiceImpl.java new file mode 100644 index 00000000..0865dbc3 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentStatisticsServiceImpl.java @@ -0,0 +1,87 @@ +package com.budwk.app.zhgh.dayofficework.workershome.service.impl.review; + +import cn.hutool.core.convert.Convert; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewNorm; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewContent; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewPeo; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewProxy; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentPeoService; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentStatisticsService; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; + +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @version 1.0 + * @Author zzr + * @name:CommentStatisticsServiceImpl + * @Date 2024/8/26 9:48 + * @注释 + */ +@IocBean(args = {"refer:dao"}) +public class CommentStatisticsServiceImpl extends BaseServiceImpl implements CommentStatisticsService { + public CommentStatisticsServiceImpl(Dao dao) { + super(dao); + } + + @Inject + private CommentPeoService commentPeoService; + + + @Override + public void exportWord(WorkersHomeReviewPeo peo, OutputStream outputStream) { + NutMap map = commentPeoService.getBzById(peo.getId()); + //最后的导出表 + NutMap resultMap = NutMap.NEW(); + + List list = new ArrayList<>(); +// resultMap.put("schoolName", Globals.schoolName); + + WorkersHomeReviewProxy khzb = map.getAs("zbxx", WorkersHomeReviewProxy.class); + List nrs = khzb.getReviewContents(); + + nrs.forEach(v -> { + NutMap nutMap = NutMap.NEW(); + List bzs = v.getReviewNorms(); + String nr = bzs.stream().sorted(Comparator.comparing(WorkersHomeReviewNorm::getContentNumber)).map(item -> { + return item.getContentNumber() + "." + item.getInspection() + "(" + item.getScore() + "分)"; + }).collect(Collectors.joining("\n")); + + int jf = bzs.stream().mapToInt(item -> Integer.parseInt(item.getScore())).sum(); + int zpf = bzs.stream().mapToInt(item -> Integer.parseInt(item.getResultScore())).sum(); + WorkersHomeReviewNorm commentBz = bzs.stream().findFirst().orElse(new WorkersHomeReviewNorm()); + + nutMap.put("xh", Convert.numberToChinese(Double.parseDouble(v.getContentNumber()), false)); + nutMap.put("zb", v.getContent()); + nutMap.put("nr", nr); + nutMap.put("jf", jf); + nutMap.put("zpf", zpf); + nutMap.put("bz", commentBz.getOptions()); + list.add(nutMap); + }); + +// HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy(); +// HtmlRenderPolicy htmlRenderPolicy = new HtmlRenderPolicy(); +// htmlRenderPolicy.getConfig().setShowDefaultTableBorderInTableCell(true); +// +// Configure config = Configure.newBuilder().bind("list", policy) +// .bind("list.nr", htmlRenderPolicy).build(); + resultMap.put("list", list); + + try { +// InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("docTemplate/workershome.docx"); +// XWPFTemplate.compile(inputStream, config).render(resultMap, outputStream); +// inputStream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentZbServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentZbServiceImpl.java new file mode 100644 index 00000000..c3ac2e18 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/impl/review/CommentZbServiceImpl.java @@ -0,0 +1,82 @@ +package com.budwk.app.zhgh.dayofficework.workershome.service.impl.review; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewNorm; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewContent; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewGrading; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewProxy; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentNrService; +import com.budwk.app.zhgh.dayofficework.workershome.service.review.CommentZbService; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.random.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * @ClassName CommentZbServiceImpl + * @Description TODO + * @Author zhf + * @Date 2023/9/4 15:54 + */ +@IocBean(args = {"refer:dao"}) +public class CommentZbServiceImpl extends BaseServiceImpl implements CommentZbService { + public CommentZbServiceImpl(Dao dao) { + super(dao); + } + + @Inject + private CommentNrService commentNrService; + + + @Override + public WorkersHomeReviewProxy khzb(String zbid) { + if (StrUtil.isBlank(zbid)) { + return null; + } + + WorkersHomeReviewProxy zb = dao().fetchLinks(fetch(zbid), "nrs", Cnd.NEW().asc("contentNumber")); + for (WorkersHomeReviewContent nr : zb.getReviewContents()) { + List query = dao().query(WorkersHomeReviewNorm.class, Cnd.where("zb_id", "=", zbid).and("nr_id", "=", nr.getId()).asc("contentNumber")); + nr.setReviewNorms(query); + } + return zb; + } + + + @Override + public void setGrading(WorkersHomeReviewProxy commentZb) { + int count = dao().count(WorkersHomeReviewGrading.class, Cnd.where("zbId", "=", commentZb.getId())); + if (count > 0) { + dao().clear(WorkersHomeReviewGrading.class, Cnd.where("zbId", "=", commentZb.getId())); + } + + if (ObjectUtil.isNotNull(commentZb.getCommentTarget()) && commentZb.getCommentTarget() != 1) { + List query = new ArrayList<>(); + if (commentZb.getCommentTarget() == 2) { + query = dao().query(Sys_union.class, Cnd.NEW()); + } else if (commentZb.getCommentTarget() == 3) { + query = dao().query(Sys_union.class, Cnd.where("id", "in", commentZb.getUnionIds())); + } + List commentUnionGradings = new ArrayList<>(); + for (Sys_union union : query) { + WorkersHomeReviewGrading unionGrading = new WorkersHomeReviewGrading(); + unionGrading.setId(R.UU32()); + unionGrading.setUnionId(union.getId()); + unionGrading.setProxyId(commentZb.getId()); + unionGrading.setUnionName(union.getName()); + unionGrading.setUnionCode(union.getUnionCode()); + unionGrading.setIsGrading(false); + unionGrading.setGradingTime(null); + commentUnionGradings.add(unionGrading); + } + dao().insert(commentUnionGradings); + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentBzService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentBzService.java new file mode 100644 index 00000000..e5d949a8 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentBzService.java @@ -0,0 +1,8 @@ +package com.budwk.app.zhgh.dayofficework.workershome.service.review; + + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewNorm; + +public interface CommentBzService extends BaseService { +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentNrService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentNrService.java new file mode 100644 index 00000000..7d8b6b6b --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentNrService.java @@ -0,0 +1,8 @@ +package com.budwk.app.zhgh.dayofficework.workershome.service.review; + + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewContent; + +public interface CommentNrService extends BaseService { +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentPeoService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentPeoService.java new file mode 100644 index 00000000..94ccece5 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentPeoService.java @@ -0,0 +1,16 @@ +package com.budwk.app.zhgh.dayofficework.workershome.service.review; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewPeo; +import org.nutz.lang.util.NutMap; + +public interface CommentPeoService extends BaseService { + + /** + * 根据指标id和被测评人id查测评结果 + * @param peoId 指标id + * @return + */ + NutMap getBzById(String peoId); + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentStatisticsService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentStatisticsService.java new file mode 100644 index 00000000..6374b0dc --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentStatisticsService.java @@ -0,0 +1,22 @@ +package com.budwk.app.zhgh.dayofficework.workershome.service.review; + + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewPeo; + +import java.io.OutputStream; + +/** + * @version 1.0 + * @Author zzr + * @name:CommentStatisticsService + * @Date 2024/8/26 9:47 + * @注释 + */ +public interface CommentStatisticsService extends BaseService { + + void exportWord(WorkersHomeReviewPeo peo, OutputStream outputStream); + + + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentZbService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentZbService.java new file mode 100644 index 00000000..d5d67c5a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/service/review/CommentZbService.java @@ -0,0 +1,13 @@ +package com.budwk.app.zhgh.dayofficework.workershome.service.review; + + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewProxy; + +public interface CommentZbService extends BaseService { + + + WorkersHomeReviewProxy khzb(String zbid); + + void setGrading(WorkersHomeReviewProxy zb); +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/vo/WakesHomeVo.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/vo/WakesHomeVo.java new file mode 100644 index 00000000..9cb98d7f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workershome/vo/WakesHomeVo.java @@ -0,0 +1,34 @@ +package com.budwk.app.zhgh.dayofficework.workershome.vo; + +import cn.hutool.json.JSONObject; +import com.budwk.app.zhgh.dayofficework.workershome.model.review.WorkersHomeReviewNorm; +import lombok.Data; + +import java.util.List; + +/** + * @version 1.0 + * @Author zzr + * @name:WakesHomeVo + * @Date 2024/8/1 16:06 + * @注释 职工建家vo + */ +@Data +public class WakesHomeVo { + + private String id; + + private List bzList; + + private String reviewResult; + + private String evaluatedPersonId; + + private String evaluatedPersonName; + + private String evaluatedPersonType; + + private String presidentOpinions; + + private List files; +} diff --git a/src/main/java/com/budwk/app/zhgh/integral/model/IntegralDetail.java b/src/main/java/com/budwk/app/zhgh/integral/model/IntegralDetail.java index 60ba60e4..086aa2b2 100644 --- a/src/main/java/com/budwk/app/zhgh/integral/model/IntegralDetail.java +++ b/src/main/java/com/budwk/app/zhgh/integral/model/IntegralDetail.java @@ -25,7 +25,6 @@ public class IntegralDetail extends BaseModel implements Serializable { @Name @Comment("id") @ColDefine(type = ColType.VARCHAR, width = 32) - @Prev(els = {@EL("uuid()")}) private String id; @Column diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/dto/GoodsDTO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/dto/GoodsDTO.java new file mode 100644 index 00000000..74d6b9e6 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/dto/GoodsDTO.java @@ -0,0 +1,187 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.dto; + +import com.budwk.app.zhgh.mall.manage.models.goods.entity.GoodsGalleryDO; +import com.budwk.app.zhgh.mall.manage.models.goods.entity.GoodsParamsDO; +import com.budwk.app.zhgh.mall.manage.models.goods.vo.ExchangeVO; +import com.budwk.app.zhgh.mall.manage.models.goods.vo.GoodsMobileIntroVO; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.Valid; +import javax.validation.constraints.*; +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +/** + * 商品vo + * + * @author fk + * @version v2.0 + * @since v7.0.0 + * 2018年3月21日 上午11:25:10 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class GoodsDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 3922135264669953741L; + + @ApiModelProperty("商品id") + private Long goodsId; + + @ApiModelProperty("分类id") + private Long categoryId; + + /** + * 用作显示 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + @ApiModelProperty("店铺分类id") + @Min(value = 0, message = "店铺分类值不正确") + private Long shopCatId; + + @ApiModelProperty("品牌id") + private Long brandId; + + @ApiModelProperty("商品名称") + @NotEmpty(message = "商品名称不能为空") + private String goodsName; + + @ApiModelProperty("商品编号") + @Length(max = 30,message = "商品编号太长,不能超过30个字符") + private String sn; + + @ApiModelProperty("商品价格") + @NotNull(message = "商品价格不能为空") + @Min(value = 0, message = "商品价格不能为负数") + @Max(value = 99999999, message = "商品价格不能超过99999999") + private Double price; + + @ApiModelProperty("成本价格") + @NotNull(message = "成本价格不能为空") + @Min(value = 0, message = "成本价格不能为负数") + @Max(value = 99999999, message = "成本价格不能超过99999999") + private Double cost; + + @ApiModelProperty("市场价格") + @NotNull(message = "市场价格不能为空") + @Min(value = 0, message = "市场价格不能为负数") + @Max(value = 99999999, message = "市场价格不能超过99999999") + private Double mktprice; + + @ApiModelProperty("重量") + @NotNull(message = "商品重量不能为空") + @Min(value = 0, message = "重量不能为负数") + @Max(value = 99999999,message = "重量不能超过99999999") + private Double weight; + + @ApiModelProperty("谁承担运费0:买家承担,1:卖家承担") + @NotNull(message = "承担运费不能为空") + @Min(value = 0, message = "承担运费值不正确") + @Max(value = 1, message = "承担运费值不正确") + private Integer goodsTransfeeCharge; + + @ApiModelProperty("详情") + private String intro; + + @ApiModelProperty("是否有规格0没有1有") + private Integer haveSpec; + + @ApiModelProperty("库存") + @Max(value = 99999999, message = "库存不能超过99999999") + private Integer quantity; + + @ApiModelProperty("是否上架,1上架 0下架") + @Min(value = 0, message = "是否上架值不正确") + @Max(value = 1, message = "是否上架值不正确") + private Integer marketEnable; + + @ApiModelProperty("商品参数") + @Valid + private List goodsParamsList; + + @ApiModelProperty("商品相册") + @NotNull(message = "商品相册图片不能为空") + @Size(min = 1,message = "商品相册图片不能为空") + private List goodsGalleryList; + + @ApiModelProperty("积分兑换对象,不是积分兑换商品可以不传") + private ExchangeVO exchange; + + @ApiModelProperty("sku数据变化或者组合变化判断 0:没变化,1:变化") + private Integer hasChanged; + + @ApiModelProperty("seo标题") + private String pageTitle; + + @ApiModelProperty("seo关键字") + private String metaKeywords; + + @ApiModelProperty("seo描述") + private String metaDescription; + + @ApiModelProperty("商品的评论数量") + private Integer commentNum; + + @ApiModelProperty("运费模板id,不需要运费模板时值是0") + private Long templateId; + + @ApiModelProperty("商品是否审核") + private Integer isAuth; + + @ApiModelProperty("可用库存") + private Integer enableQuantity; + + @ApiModelProperty("商品移动端详情数据集合") + private List introList; + + @ApiModelProperty("商品视频") + private String goodsVideo; + + @Override + public String toString() { + return "GoodsDTO{" + + "goodsId=" + goodsId + + ", categoryId=" + categoryId + + ", categoryName='" + categoryName + '\'' + + ", shopCatId=" + shopCatId + + ", brandId=" + brandId + + ", goodsName='" + goodsName + '\'' + + ", sn='" + sn + '\'' + + ", price=" + price + + ", cost=" + cost + + ", mktprice=" + mktprice + + ", weight=" + weight + + ", goodsTransfeeCharge=" + goodsTransfeeCharge + + ", intro='" + intro + '\'' + + ", haveSpec=" + haveSpec + + ", quantity=" + quantity + + ", marketEnable=" + marketEnable + + ", goodsParamsList=" + goodsParamsList + + ", goodsGalleryList=" + goodsGalleryList + + ", exchange=" + exchange + + ", hasChanged=" + hasChanged + + ", pageTitle='" + pageTitle + '\'' + + ", metaKeywords='" + metaKeywords + '\'' + + ", metaDescription='" + metaDescription + '\'' + + ", commentNum=" + commentNum + + ", templateId=" + templateId + + ", isAuth=" + isAuth + + ", enableQuantity=" + enableQuantity + + ", introList=" + introList + + ", goodsVideo='" + goodsVideo + '\'' + + '}'; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/BrandDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/BrandDO.java new file mode 100644 index 00000000..d4f84cfe --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/BrandDO.java @@ -0,0 +1,64 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.Data; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serial; +import java.io.Serializable; + + +/** + * 品牌实体 + * + * @author fky + * + */ +@Data +@Table("mall_brand") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class BrandDO implements Serializable { + + @Serial + private static final long serialVersionUID = 9122931201151887L; + + /** + * 主键 + */ + @Id + @Column + @Comment("id") + @ColDefine(customType = "bigint") + private Long brandId; + + /** + * 品牌名称 + */ + @Column + @Comment("品牌名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String name; + + /** + * 品牌图标 + */ + @Column + @Comment("品牌图标") + @ColDefine(type = ColType.VARCHAR, width = 255) + private String logo; + + /** + * 是否删除,0删除1未删除 + */ + @Column + @Comment("是否删除") + @ColDefine(type = ColType.INT) + private Integer disabled; + + @Override + public String toString() { + return "[brandId=" + brandId + ", name=" + name + ", logo=" + logo + ", disabled=" + disabled + "]"; + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/CategoryBrandDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/CategoryBrandDO.java new file mode 100644 index 00000000..29f544b1 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/CategoryBrandDO.java @@ -0,0 +1,66 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serial; +import java.io.Serializable; + + +/** + * 分类品牌关联表实体 + * + * @author fky + * + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Comment("分类品牌关联表实体") +@Table("mall_category_brand") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class CategoryBrandDO implements Serializable { + + @Serial + private static final long serialVersionUID = 3315719881926878L; + /** + * 分类id + */ + @Id + @Column + @Comment("id") + @ColDefine(customType = "bigint") + private Long id; + + /** + * 分类id + */ + @Column + @Comment("分类id") + @ColDefine(customType = "bigint") + private Long categoryId; + + /** + * 品牌id + */ + @Column + @Comment("品牌id") + @ColDefine(customType = "bigint") + private Long brandId; + + public CategoryBrandDO(Long categoryId, Long brandId) { + super(); + this.categoryId = categoryId; + this.brandId = brandId; + } + + @Override + public String toString() { + return "CategoryBrandDO [categoryId=" + categoryId + ", brandId=" + brandId + "]"; + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/CategoryDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/CategoryDO.java new file mode 100644 index 00000000..f10bbd51 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/CategoryDO.java @@ -0,0 +1,151 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.Data; +import org.nutz.dao.entity.annotation.*; + +import javax.validation.constraints.NotEmpty; +import java.io.Serial; +import java.io.Serializable; +import java.util.Objects; + + +/** + * 商品分类实体 + * + * @author fky + * + */ +@Data +@Comment("商品分类实体") +@Table("mall_category") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class CategoryDO implements Serializable { + + @Serial + private static final long serialVersionUID = 1964321416223565L; + + /** + * 主键 + */ + @Id + @Column + @Comment("id") + @ColDefine(customType = "bigint") + private Long categoryId; + + /** + * 分类名称 + */ + @Column + @Comment("分类名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String name; + + /** + * 分类父id + */ + @Column + @Comment("分类父id,顶级0") + @ColDefine(customType = "bigint") + private Long parentId; + + /** + * 分类父子路径 + */ + @Column + @Comment("分类父子路径") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String categoryPath; + + /** + * 该分类下商品数量 + */ + @Column + @Comment("该分类下商品数量") + @ColDefine(type = ColType.INT) + private Integer goodsCount; + + /** + * 分类排序 + */ + @Column + @Comment("分类排序") + @ColDefine(type = ColType.INT) + private Integer categoryOrder; + + /** + * 分类图标 + */ + @Column + @Comment("分类图标") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String image; + + /** + * 是否显示 YES:是,NO:否 + */ + @Column + @Comment("是否显示 YES:是,NO:否") + @ColDefine(type = ColType.VARCHAR, width = 10) + private String isShow; + + /** + * 分类广告图片 + */ + @Column + @Comment("分类广告图片") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String advImage; + + /** + * 分类广告图片链接 + */ + @Column + @Comment("分类广告图片链接") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String advImageLink; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CategoryDO that = (CategoryDO) o; + return Objects.equals(categoryId, that.categoryId) && + Objects.equals(name, that.name) && + Objects.equals(parentId, that.parentId) && + Objects.equals(categoryPath, that.categoryPath) && + Objects.equals(goodsCount, that.goodsCount) && + Objects.equals(categoryOrder, that.categoryOrder) && + Objects.equals(image, that.image) && + Objects.equals(isShow, that.isShow) && + Objects.equals(advImage, that.advImage) && + Objects.equals(advImageLink, that.advImageLink); + } + + @Override + public int hashCode() { + return Objects.hash(categoryId, name, parentId, categoryPath, goodsCount, categoryOrder, image, isShow, advImage, advImageLink); + } + + @Override + public String toString() { + return "CategoryDO{" + + "categoryId=" + categoryId + + ", name='" + name + '\'' + + ", parentId=" + parentId + + ", categoryPath='" + categoryPath + '\'' + + ", goodsCount=" + goodsCount + + ", categoryOrder=" + categoryOrder + + ", image='" + image + '\'' + + ", isShow='" + isShow + '\'' + + ", advImage='" + advImage + '\'' + + ", advImageLink='" + advImageLink + '\'' + + '}'; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/CategorySpecDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/CategorySpecDO.java new file mode 100644 index 00000000..0c4c2fd5 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/CategorySpecDO.java @@ -0,0 +1,63 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serial; +import java.io.Serializable; + + +/** + * 分类规格关联表实体 + * + * @author fky + * + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Table("mall_category_spec") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class CategorySpecDO implements Serializable { + + @Serial + private static final long serialVersionUID = 3127259064985991L; + + @Id + @Column + @Comment("id") + @ColDefine(customType = "bigint") + private Long id; + + /** + * 分类id + */ + @Column + @Comment("分类id") + @ColDefine(customType = "bigint") + private Long categoryId; + + /** + * 规格id + */ + @Column + @Comment("规格id") + @ColDefine(customType = "bigint") + private Long specId; + + public CategorySpecDO(Long categoryId, Long specId) { + super(); + this.categoryId = categoryId; + this.specId = specId; + } + + @Override + public String toString() { + return "CategorySpecDO [categoryId=" + categoryId + ", specId=" + specId + "]"; + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/DraftGoodsDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/DraftGoodsDO.java new file mode 100644 index 00000000..b49d41e2 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/DraftGoodsDO.java @@ -0,0 +1,307 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import cn.hutool.json.JSONUtil; +import com.budwk.app.zhgh.mall.manage.models.goods.dto.GoodsDTO; +import com.budwk.app.zhgh.mall.manage.models.goods.enums.GoodsType; +import com.budwk.app.zhgh.mall.manage.models.goods.vo.GoodsMobileIntroVO; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; +import java.util.List; + +/** + * 草稿商品实体 + * + * @author fky + * + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Table("mall_draft_goods") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class DraftGoodsDO implements Serializable { + + private static final long serialVersionUID = 7646662730625878L; + + /** + * 草稿商品id + */ + @Id + @Column + @Comment("id") + @ColDefine(customType = "bigint") + private Long draftGoodsId; + /** + * 商品编号 + */ + @Column + @Comment("商品编号") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String sn; + /** + * 商品名称 + */ + @Column + @Comment("商品名称") + @ColDefine(type = ColType.VARCHAR, width = 255) + private String goodsName; + /** + * 商品品牌ID + */ + @Column + @Comment("商品品牌ID") + @ColDefine(customType = "bigint") + private Long brandId; + /** + * 商品分类ID + */ + @Column + @Comment("商品分类ID") + @ColDefine(customType = "bigint") + private Long categoryId; + /** + * 商品重量 + */ + @Column + @Comment("商品重量") + @ColDefine(type = ColType.DOUBLE) + private Double weight; + /** + * 商品详情 + */ + @Column + @Comment("商品详情") + @ColDefine(type = ColType.MYSQL_JSON) + private String intro; + /** + * 商品价格 + */ + @Column + @Comment("商品价格") + @ColDefine(type = ColType.DOUBLE) + private Double price; + /** + * 商品成本价 + */ + @Column + @Comment("商品成本价") + @ColDefine(type = ColType.DOUBLE) + private Double cost; + /** + * 商品市场价 + */ + @Column + @Comment("商品市场价") + @ColDefine(type = ColType.DOUBLE) + private Double mktprice; + /** + * 商品类型 + */ + @Column + @Comment("商品类型") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String goodsType; + /** + * 是否开启规格 + */ + @Column + @Comment("是否开启规格") + @ColDefine(type = ColType.INT) + private Integer haveSpec; + /** + * 商品添加时间 + */ + @Column + @Comment("商品添加时间") + @ColDefine(customType = "bigint") + private Long createTime; + /** + * 商品总库存 + */ + @Column + @Comment("商品总库存") + @ColDefine(type = ColType.INT) + private Integer quantity; + /** + * 商品原始图片 + */ + @Column + @Comment("商品原始图片") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String original; + /** + * 商品所属卖家ID + */ + @Column + @Comment("商品所属卖家ID") + @ColDefine(customType = "bigint") + private Long sellerId; + /** + * 商品所属店铺类目ID + */ + @Column + @Comment("商品所属店铺类目ID") + @ColDefine(customType = "bigint") + private Long shopCatId; + /** + * 商品运费模板ID + */ + @Column + @Comment("商品运费模板ID") + @ColDefine(customType = "bigint") + private Long templateId; + /** + * 是否为买家承担运费 + */ + @Column + @Comment("是否为买家承担运费") + @ColDefine(type = ColType.INT) + private Integer goodsTransfeeCharge; + /** + * 商品所属店铺名称 + */ + @Column + @Comment("商品所属店铺名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String sellerName; + /** + * seo 标题 + */ + @Column + @Comment("seo 标题") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String pageTitle; + /** + * seo关键字 + */ + @Column + @Comment("seo关键字") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String metaKeywords; + /** + * seo描述 + */ + @Column + @Comment("seo描述") + @ColDefine(type = ColType.MYSQL_JSON) + private String metaDescription; + /** + * 积分商品需要的金额 + */ + @Column + @Comment("积分商品需要的金额") + @ColDefine(type = ColType.DOUBLE) + private Double exchangeMoney; + /** + * 积分商品需要的积分 + */ + @Column + @Comment("积分商品需要的积分") + @ColDefine(type = ColType.INT) + private Integer exchangePoint; + /** + * 积分商品的分类id + */ + @Column + @Comment("积分商品的分类id") + @ColDefine(customType = "bigint") + private Long exchangeCategoryId; + + /** + * 商品移动端详情 + */ + @Column + @Comment("商品移动端详情") + @ColDefine(type = ColType.MYSQL_JSON) + private String mobileIntro; + + /** + * 商品视频 + */ + @Column + @Comment("商品视频") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String goodsVideo; + + private List galleryList; + + public DraftGoodsDO(GoodsDTO goodsVO) { + + this.draftGoodsId = goodsVO.getGoodsId(); + this.categoryId = goodsVO.getCategoryId(); + this.shopCatId = goodsVO.getShopCatId(); + this.brandId = goodsVO.getBrandId(); + this.goodsName = goodsVO.getGoodsName(); + this.sn = goodsVO.getSn(); + this.price = goodsVO.getPrice() == null ? 0 : goodsVO.getPrice(); + this.cost = goodsVO.getCost() == null ? 0 : goodsVO.getCost(); + this.mktprice = goodsVO.getMktprice() == null ? 0 : goodsVO.getMktprice(); + this.weight = goodsVO.getWeight() == null ? 0 : goodsVO.getWeight(); + this.goodsTransfeeCharge = goodsVO.getGoodsTransfeeCharge(); + this.intro = goodsVO.getIntro(); + this.haveSpec = goodsVO.getHaveSpec(); + if (goodsVO.getExchange() != null && goodsVO.getExchange().getEnableExchange() == 1) { + this.goodsType = GoodsType.POINT.name(); + this.exchangeMoney = goodsVO.getExchange().getExchangeMoney(); + this.exchangePoint = goodsVO.getExchange().getExchangePoint(); + this.exchangeCategoryId = goodsVO.getExchange().getCategoryId(); + } else { + this.goodsType = GoodsType.NORMAL.name(); + this.exchangeMoney = 0.00; + this.exchangePoint = 0; + this.exchangeCategoryId = 1L; + } + this.pageTitle = goodsVO.getPageTitle(); + this.metaKeywords = goodsVO.getMetaKeywords(); + this.metaDescription = goodsVO.getMetaDescription(); + this.templateId = goodsVO.getTemplateId(); + + List introList = goodsVO.getIntroList(); + if (introList != null && !introList.isEmpty()) { + this.mobileIntro = JSONUtil.toJsonStr(introList); + } + + this.goodsVideo = goodsVO.getGoodsVideo(); + } + + @Override + public String toString() { + return "DraftGoodsDO{" + + "draftGoodsId=" + draftGoodsId + + ", sn='" + sn + '\'' + + ", goodsName='" + goodsName + '\'' + + ", brandId=" + brandId + + ", categoryId=" + categoryId + + ", weight=" + weight + + ", intro='" + intro + '\'' + + ", price=" + price + + ", cost=" + cost + + ", mktprice=" + mktprice + + ", goodsType='" + goodsType + '\'' + + ", haveSpec=" + haveSpec + + ", createTime=" + createTime + + ", quantity=" + quantity + + ", original='" + original + '\'' + + ", sellerId=" + sellerId + + ", shopCatId=" + shopCatId + + ", templateId=" + templateId + + ", goodsTransfeeCharge=" + goodsTransfeeCharge + + ", sellerName='" + sellerName + '\'' + + ", pageTitle='" + pageTitle + '\'' + + ", metaKeywords='" + metaKeywords + '\'' + + ", metaDescription='" + metaDescription + '\'' + + ", exchangeMoney=" + exchangeMoney + + ", exchangePoint=" + exchangePoint + + ", exchangeCategoryId=" + exchangeCategoryId + + ", mobileIntro='" + mobileIntro + '\'' + + ", goodsVideo='" + goodsVideo + '\'' + + ", galleryList=" + galleryList + + '}'; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/DraftGoodsParamsDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/DraftGoodsParamsDO.java new file mode 100644 index 00000000..3995d152 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/DraftGoodsParamsDO.java @@ -0,0 +1,80 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serial; +import java.io.Serializable; + + +/** + * 草稿商品参数表实体 + * + * @author fky + * + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Table("mall_draft_goods_params") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class DraftGoodsParamsDO implements Serializable { + + @Serial + private static final long serialVersionUID = 1137617128769441L; + + /** + * ID + */ + @Id + @Column + @Comment("id") + @ColDefine(customType = "bigint") + private Long id; + /** + * 草稿ID + */ + @Column + @Comment("草稿id") + @ColDefine(customType = "bigint") + private Long draftGoodsId; + /** + * 参数ID + */ + @Column + @Comment("参数id") + @ColDefine(customType = "bigint") + private Long paramId; + /** + * 参数名 + */ + @Column + @Comment("参数名") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String paramName; + /** + * 参数值 + */ + @Column + @Comment("参数值") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String paramValue; + + public DraftGoodsParamsDO(GoodsParamsDO param) { + this.paramId = param.getParamId(); + this.paramName = param.getParamName(); + this.paramValue = param.getParamValue(); + } + + @Override + public String toString() { + return "DraftGoodsParamsDO [id=" + id + ", draftGoodsId=" + draftGoodsId + ", paramId=" + paramId + + ", paramName=" + paramName + ", paramValue=" + paramValue + "]"; + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/DraftGoodsSkuDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/DraftGoodsSkuDO.java new file mode 100644 index 00000000..fee17a1c --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/DraftGoodsSkuDO.java @@ -0,0 +1,106 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import com.budwk.app.zhgh.mall.manage.models.goods.vo.GoodsSkuVO; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.Data; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serial; +import java.io.Serializable; + + +/** + * 草稿商品sku实体 + * + * @author fky + * + */ +@Data +@Table("mall_draft_goods_sku") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class DraftGoodsSkuDO implements Serializable { + + @Serial + private static final long serialVersionUID = 5684194304207265L; + + /** + * 主键ID + */ + @Id + @Column + @Comment("id") + @ColDefine(customType = "bigint") + private Long draftSkuId; + /** + * 草稿id + */ + @Column + @Comment("草稿id") + @ColDefine(customType = "bigint") + private Long draftGoodsId; + /** + * 货号 + */ + @Column + @Comment("货号") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String sn; + /** + * 总库存 + */ + @Column + @Comment("货号") + @ColDefine(type = ColType.VARCHAR, width = 50) + private Integer quantity; + /** + * 价格 + */ + @Column + @Comment("货号") + @ColDefine(type = ColType.VARCHAR, width = 50) + private Double price; + /** + * 规格 + */ + @Column + @Comment("货号") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String specs; + /** + * 成本 + */ + @Column + @Comment("货号") + @ColDefine(type = ColType.VARCHAR, width = 50) + private Double cost; + /** + * 重量 + */ + @Column + @Comment("货号") + @ColDefine(type = ColType.VARCHAR, width = 50) + private Double weight; + + public DraftGoodsSkuDO() { + } + + public DraftGoodsSkuDO(GoodsSkuVO skuVO) { + this.setDraftGoodsId(skuVO.getGoodsId()); + this.setSn(skuVO.getSn()); + this.setPrice(skuVO.getPrice()); + this.setCost(skuVO.getCost()); + this.setWeight(skuVO.getWeight()); + this.setQuantity(skuVO.getQuantity()); + this.setSpecs(skuVO.getSpecs()); + } + + @Override + public String toString() { + return "DraftGoodsSkuDO [draftSkuId=" + draftSkuId + ", draftGoodsId=" + draftGoodsId + ", sn=" + sn + + ", quantity=" + quantity + ", price=" + price + ", specs=" + specs + ", cost=" + cost + ", weight=" + + weight + "]"; + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsDO.java new file mode 100644 index 00000000..ab8ed26b --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsDO.java @@ -0,0 +1,481 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.budwk.app.zhgh.mall.manage.models.goods.dto.GoodsDTO; +import com.budwk.app.zhgh.mall.manage.models.goods.vo.GoodsMobileIntroVO; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; +import java.util.Objects; + +/** + * 商品实体 + * + * @author fky + * + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Table("mall_goods") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class GoodsDO implements Serializable { + + @Serial + private static final long serialVersionUID = 9115135430405642L; + + /** + * 主键 + */ + @Id + @Column + @Comment("id") + @ColDefine(customType = "bigint") + private Long goodsId; + /** + * 商品名称 + */ + @Column + @Comment("商品名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String goodsName; + /** + * 商品编号 + */ + @Column + @Comment("商品编号") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String sn; + /** + * 品牌id + */ + @Column + @Comment("品牌id") + @ColDefine(customType = "bigint") + private Long brandId; + /** + * 分类id + */ + @Column + @Comment("分类id") + @ColDefine(customType = "bigint") + private Long categoryId; + /** + * 商品类型normal普通point积分 + */ + @Column + @Comment("商品类型NORMAL普通POINT积分") + @ColDefine(type = ColType.VARCHAR, width = 120) + private String goodsType; + /** + * 重量 + */ + @Column + @Comment("重量") + @ColDefine(type = ColType.DOUBLE) + private Double weight; + /** + * 上架状态 1上架 0下架 + */ + @Column + @Comment("上架状态 1上架 0下架") + @ColDefine(type = ColType.INT) + private Integer marketEnable; + /** + * 详情 + */ + @Column + @Comment("详情") + @ColDefine(type = ColType.MYSQL_JSON) + private String intro; + /** + * 商品价格 + */ + @Column + @Comment("商品价格") + @ColDefine(type = ColType.DOUBLE) + private Double price; + /** + * 成本价格 + */ + @Column + @Comment("成本价格") + @ColDefine(type = ColType.DOUBLE) + private Double cost; + /** + * 市场价格 + */ + @Column + @Comment("市场价格") + @ColDefine(type = ColType.DOUBLE) + private Double mktprice; + /** + * 是否有规格0没有 1有 + */ + @Column + @Comment("是否有规格0没有 1有") + @ColDefine(type = ColType.INT) + private Integer haveSpec; + /** + * 创建时间 + */ + @Column + @Comment("创建时间") + @ColDefine(customType = "bigint") + private Long createTime; + /** + * 最后修改时间 + */ + @Column + @Comment("最后修改时间") + @ColDefine(customType = "bigint") + private Long lastModify; + /** + * 浏览数量 + */ + @Column + @Comment("浏览数量") + @ColDefine(type = ColType.INT) + private Integer viewCount; + /** + * 购买数量 + */ + @Column + @Comment("购买数量") + @ColDefine(type = ColType.INT) + private Integer buyCount; + /** + * 是否被删除0 删除 1未删除 + */ + @Column + @Comment("是否被删除0 删除 1未删除") + @ColDefine(type = ColType.INT) + private Integer disabled; + /** + * 库存 + */ + @Column + @Comment("库存") + @ColDefine(type = ColType.INT) + private Integer quantity; + /** + * 可用库存 + */ + @Column + @Comment("可用库存") + @ColDefine(type = ColType.INT) + private Integer enableQuantity; + /** + * 如果是积分商品需要使用的积分 + */ + @Column + @Comment("如果是积分商品需要使用的积分") + @ColDefine(type = ColType.INT) + private Integer point; + /** + * seo标题 + */ + @Column + @Comment("seo标题") + @ColDefine(type = ColType.VARCHAR, width = 120) + private String pageTitle; + /** + * seo关键字 + */ + @Column + @Comment("seo关键字") + @ColDefine(type = ColType.VARCHAR, width = 255) + private String metaKeywords; + /** + * seo描述 + */ + @Column + @Comment("seo描述") + @ColDefine(type = ColType.VARCHAR, width = 255) + private String metaDescription; + /** + * 商品好评率 + */ + @Column + @Comment("商品好评率") + @ColDefine(type = ColType.DOUBLE) + private Double grade; + /** + * 缩略图路径 + */ + @Column + @Comment("缩略图路径") + @ColDefine(type = ColType.VARCHAR, width = 120) + private String thumbnail; + /** + * 大图路径 + */ + @Column + @Comment("大图路径") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String big; + /** + * 小图路径 + */ + @Column + @Comment("小图路径") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String small; + /** + * 原图路径 + */ + @Column + @Comment("原图路径") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String original; + /** + * 卖家id + */ + @Column + @Comment("卖家id") + @ColDefine(customType = "bigint") + private Long sellerId; + /** + * 店铺分类id + */ + @Column + @Comment("店铺分类id") + @ColDefine(customType = "bigint") + private Long shopCatId; + /** + * 评论数量 + */ + @Column + @Comment("评论数量") + @ColDefine(type = ColType.INT) + private Integer commentNum; + /** + * 运费模板id + */ + @Column + @Comment("运费模板id") + @ColDefine(customType = "bigint") + private Long templateId; + /** + * 谁承担运费0:买家承担,1:卖家承担 + */ + @Column + @Comment("谁承担运费0:买家承担,1:卖家承担") + @ColDefine(type = ColType.INT) + private Integer goodsTransfeeCharge; + /** + * 卖家名字 + */ + @Column + @Comment("卖家名字") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String sellerName; + /** + * 0 需要审核 并且待审核,1 不需要审核 2需要审核 且审核通过 3 需要审核 且审核未通过 + */ + @Column + @Comment("0 待审核,1 审核通过 2 未通过") + @ColDefine(type = ColType.INT) + private Integer isAuth; + /** + * 审核信息 + */ + @Column + @Comment("审核信息") + @ColDefine(type = ColType.VARCHAR, width = 255) + private String authMessage; + + /** + * 下架原因 + */ + @Column + @Comment("下架原因") + @ColDefine(type = ColType.VARCHAR, width = 255) + private String underMessage; + + @Column + @Comment("是否自营0否 1是") + @ColDefine(type = ColType.INT) + private Integer selfOperated; + + /** + * 商品移动端详情 + */ + @Column + @Comment("商品移动端详情") + @ColDefine(type = ColType.MYSQL_JSON) + private String mobileIntro; + + /** + * 商品视频 + */ + @Column + @Comment("商品视频") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String goodsVideo; + + /** + * 搜索优先级 + */ + @Column + @Comment("搜索优先级") + @ColDefine(type = ColType.INT) + private Integer priority; + + @JsonIgnore + protected String scanRounds; + + public GoodsDO(GoodsDTO goodsVO) { + this.goodsId = goodsVO.getGoodsId(); + this.categoryId = goodsVO.getCategoryId(); + this.shopCatId = goodsVO.getShopCatId(); + this.brandId = goodsVO.getBrandId(); + this.goodsName = goodsVO.getGoodsName(); + this.sn = goodsVO.getSn(); + this.price = goodsVO.getPrice(); + this.cost = goodsVO.getCost(); + this.mktprice = goodsVO.getMktprice(); + this.weight = goodsVO.getWeight(); + this.goodsTransfeeCharge = goodsVO.getGoodsTransfeeCharge(); + this.intro = goodsVO.getIntro(); + this.haveSpec = goodsVO.getHaveSpec(); + this.templateId = goodsVO.getTemplateId(); + this.pageTitle = goodsVO.getPageTitle(); + this.metaKeywords = goodsVO.getMetaKeywords(); + this.metaDescription = goodsVO.getMetaDescription(); + this.marketEnable = goodsVO.getMarketEnable() != 1 ? 0 : 1; + + if (StrUtil.isNotBlank(this.pageTitle)) { + this.pageTitle = goodsVO.getGoodsName(); + } + if (StrUtil.isNotBlank(this.metaKeywords)) { + this.metaKeywords = goodsVO.getGoodsName(); + } + if (StrUtil.isNotBlank(this.metaDescription)) { + this.metaDescription = goodsVO.getGoodsName(); + } + + List introList = goodsVO.getIntroList(); + if (introList != null && introList.size() != 0) { + this.mobileIntro = JSONUtil.toJsonStr(introList); + } else { + this.mobileIntro = ""; + } + + this.goodsVideo = goodsVO.getGoodsVideo(); + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + GoodsDO goodsDO = (GoodsDO) o; + return Objects.equals(goodsId, goodsDO.goodsId) && + Objects.equals(goodsName, goodsDO.goodsName) && + Objects.equals(sn, goodsDO.sn) && + Objects.equals(brandId, goodsDO.brandId) && + Objects.equals(categoryId, goodsDO.categoryId) && + Objects.equals(goodsType, goodsDO.goodsType) && + Objects.equals(weight, goodsDO.weight) && + Objects.equals(marketEnable, goodsDO.marketEnable) && + Objects.equals(intro, goodsDO.intro) && + Objects.equals(price, goodsDO.price) && + Objects.equals(cost, goodsDO.cost) && + Objects.equals(mktprice, goodsDO.mktprice) && + Objects.equals(haveSpec, goodsDO.haveSpec) && + Objects.equals(createTime, goodsDO.createTime) && + Objects.equals(lastModify, goodsDO.lastModify) && + Objects.equals(viewCount, goodsDO.viewCount) && + Objects.equals(buyCount, goodsDO.buyCount) && + Objects.equals(disabled, goodsDO.disabled) && + Objects.equals(quantity, goodsDO.quantity) && + Objects.equals(enableQuantity, goodsDO.enableQuantity) && + Objects.equals(point, goodsDO.point) && + Objects.equals(pageTitle, goodsDO.pageTitle) && + Objects.equals(metaKeywords, goodsDO.metaKeywords) && + Objects.equals(metaDescription, goodsDO.metaDescription) && + Objects.equals(grade, goodsDO.grade) && + Objects.equals(thumbnail, goodsDO.thumbnail) && + Objects.equals(big, goodsDO.big) && + Objects.equals(small, goodsDO.small) && + Objects.equals(original, goodsDO.original) && + Objects.equals(sellerId, goodsDO.sellerId) && + Objects.equals(shopCatId, goodsDO.shopCatId) && + Objects.equals(commentNum, goodsDO.commentNum) && + Objects.equals(templateId, goodsDO.templateId) && + Objects.equals(goodsTransfeeCharge, goodsDO.goodsTransfeeCharge) && + Objects.equals(sellerName, goodsDO.sellerName) && + Objects.equals(isAuth, goodsDO.isAuth) && + Objects.equals(authMessage, goodsDO.authMessage) && + Objects.equals(underMessage, goodsDO.underMessage) && + Objects.equals(selfOperated, goodsDO.selfOperated) && + Objects.equals(mobileIntro, goodsDO.mobileIntro) && + Objects.equals(goodsVideo, goodsDO.goodsVideo); + } + + @Override + public int hashCode() { + return Objects.hash(goodsId, goodsName, sn, brandId, categoryId, goodsType, weight, marketEnable, intro, price, cost, mktprice, haveSpec, createTime, lastModify, viewCount, buyCount, disabled, quantity, enableQuantity, point, pageTitle, metaKeywords, metaDescription, grade, thumbnail, big, small, original, sellerId, shopCatId, commentNum, templateId, goodsTransfeeCharge, sellerName, isAuth, authMessage, underMessage, selfOperated, mobileIntro, goodsVideo); + } + + @Override + public String toString() { + return "GoodsDO{" + + "goodsId=" + goodsId + + ", goodsName='" + goodsName + '\'' + + ", sn='" + sn + '\'' + + ", brandId=" + brandId + + ", categoryId=" + categoryId + + ", goodsType='" + goodsType + '\'' + + ", weight=" + weight + + ", marketEnable=" + marketEnable + + ", intro='" + intro + '\'' + + ", price=" + price + + ", cost=" + cost + + ", mktprice=" + mktprice + + ", haveSpec=" + haveSpec + + ", createTime=" + createTime + + ", lastModify=" + lastModify + + ", viewCount=" + viewCount + + ", buyCount=" + buyCount + + ", disabled=" + disabled + + ", quantity=" + quantity + + ", enableQuantity=" + enableQuantity + + ", point=" + point + + ", pageTitle='" + pageTitle + '\'' + + ", metaKeywords='" + metaKeywords + '\'' + + ", metaDescription='" + metaDescription + '\'' + + ", grade=" + grade + + ", thumbnail='" + thumbnail + '\'' + + ", big='" + big + '\'' + + ", small='" + small + '\'' + + ", original='" + original + '\'' + + ", sellerId=" + sellerId + + ", shopCatId=" + shopCatId + + ", commentNum=" + commentNum + + ", templateId=" + templateId + + ", goodsTransfeeCharge=" + goodsTransfeeCharge + + ", sellerName='" + sellerName + '\'' + + ", isAuth=" + isAuth + + ", authMessage='" + authMessage + '\'' + + ", underMessage='" + underMessage + '\'' + + ", selfOperated=" + selfOperated + + ", mobileIntro='" + mobileIntro + '\'' + + ", goodsVideo='" + goodsVideo + '\'' + + '}'; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsGalleryDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsGalleryDO.java new file mode 100644 index 00000000..90ca2bc1 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsGalleryDO.java @@ -0,0 +1,101 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; + + +/** + * 商品相册实体 + * + * @author fky + * + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Table("mall_goods_gallery") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class GoodsGalleryDO implements Serializable { + + private static final long serialVersionUID = 8150217189133447L; + + /** + * 主键 + */ + @Id + @Column + @Comment("图片的主键id") + @ColDefine(customType = "bigint") + private Long imgId; + /** + * 商品主键 + */ + @Column + @Comment("商品主键") + @ColDefine(customType = "bigint") + private Long goodsId; + /** + * 缩略图路径 + */ + @Column + @Comment("缩略图路径") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String thumbnail; + /** + * 小图路径 + */ + @Column + @Comment("小图路径") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String small; + /** + * 大图路径 + */ + @Column + @Comment("大图路径") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String big; + /** + * 原图路径 + */ + @Column + @Comment("原图路径") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String original; + /** + * 极小图路径 + */ + @Column + @Comment("极小图路径") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String tiny; + /** + * 是否是默认图片1 0没有默认 + */ + @Column + @Comment("是否是默认图片1 0没有默认") + @ColDefine(type = ColType.INT) + private Integer isdefault; + /** + * 排序 + */ + @Column + @Comment("排序") + @ColDefine(type = ColType.INT) + private Integer sort; + + @Override + public String toString() { + return "GoodsGalleryDO [imgId=" + imgId + ", goodsId=" + goodsId + ", thumbnail=" + thumbnail + ", small=" + + small + ", big=" + big + ", original=" + original + ", tiny=" + tiny + ", isdefault=" + isdefault + + ", sort=" + sort + "]"; + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsParamsDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsParamsDO.java new file mode 100644 index 00000000..26edef80 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsParamsDO.java @@ -0,0 +1,79 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import cn.hutool.core.util.StrUtil; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; + + +/** + * 商品关联参数值实体 + * + * @author fky + * + */ +@Data +@Table("mall_goods_params") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class GoodsParamsDO implements Serializable { + + private static final long serialVersionUID = 4134870721776090L; + + /** + * 主键 + */ + @Id + @Column + @Comment("id") + @ColDefine(customType = "bigint") + private Long id; + /** + * 商品id + */ + @Column + @Comment("商品id") + @ColDefine(customType = "bigint") + private Long goodsId; + /** + * 参数id + */ + @Column + @Comment("参数id") + @ColDefine(customType = "bigint") + private Long paramId; + /** + * 参数名字 + */ + @Column + @Comment("参数名字") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String paramName; + /** + * 参数值 + */ + @Column + @Comment("参数值") + @ColDefine(type = ColType.VARCHAR, width = 120) + @Length(max = 100, message = "参数值字符不能大于120") + private String paramValue; + + + public String getParamValue() { + if (StrUtil.isNotBlank(paramValue)) { + return ""; + } + return paramValue; + } + + @Override + public String toString() { + return "GoodsParamsDO [id=" + id + ", goodsId=" + goodsId + ", paramId=" + paramId + ", paramName=" + paramName + + ", paramValue=" + paramValue + "]"; + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsSkuDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsSkuDO.java new file mode 100644 index 00000000..5440724d --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/GoodsSkuDO.java @@ -0,0 +1,225 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import cn.hutool.core.builder.EqualsBuilder; +import cn.hutool.core.builder.HashCodeBuilder; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.nutz.dao.entity.annotation.*; + +import javax.validation.constraints.Max; +import java.io.Serial; +import java.io.Serializable; + + +/** + * 商品sku实体 + * + * @author fky + * + */ +@Data +@Table("mall_goods_sku") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class GoodsSkuDO implements Serializable { + + @Serial + private static final long serialVersionUID = 5102510694003249L; + + /** + * 主键 + */ + @Id + @Column + @Comment("id") + @ColDefine(customType = "bigint") + private Long skuId; + /** + * 商品id + */ + @Column + @Comment("商品id") + @ColDefine(customType = "bigint") + private Long goodsId; + /** + * 商品名称 + */ + @Column + @Comment("商品名称") + @ColDefine(type = ColType.VARCHAR, width = 255) + private String goodsName; + /** + * 商品编号 + */ + @Column + @Comment("商品编号") + @ColDefine(type = ColType.VARCHAR, width = 30) + @Length(max = 30,message = "商品规格编号太长,不能超过30个字符") + private String sn; + + /** + * 库存 + */ + @Column + @Comment("库存") + @ColDefine(type = ColType.INT) + @Max(value = 99999999, message = "库存不能超过99999999") + private Integer quantity; + /** + * 可用库存 + */ + @Column + @Comment("可用库存") + @ColDefine(type = ColType.INT) + private Integer enableQuantity; + /** + * 商品价格 + */ + @Column + @Comment("商品价格") + @ColDefine(type = ColType.DOUBLE) + @Max(value = 99999999, message = "价格不能超过99999999") + private Double price; + /** + * 规格信息json + */ + @Column + @Comment("规格信息json") + @ColDefine(type = ColType.MYSQL_JSON) + private String specs; + /** + * 成本价格 + */ + @Column + @Comment("成本价格") + @ColDefine(type = ColType.DOUBLE) + @Max(value = 99999999, message = "成本价格不能超过99999999") + private Double cost; + /** + * 重量 + */ + @Column + @Comment("重量") + @ColDefine(type = ColType.DOUBLE) + @Max(value = 99999999, message = "重量不能超过99999999") + private Double weight; + /** + * 卖家id + */ + @Column + @Comment("卖家id") + @ColDefine(customType = "bigint") + private Long sellerId; + /** + * 卖家名称 + */ + @Column + @Comment("卖家名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String sellerName; + /** + * 分类id + */ + @Column + @Comment("分类id") + @ColDefine(customType = "bigint") + private Long categoryId; + /** + * 缩略图 + */ + @Column + @Comment("缩略图") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String thumbnail; + + @Column + @Comment("hash_code") + @ColDefine(type = ColType.INT) + private Integer hashCode; + + /** + * 运费模板ID(非数据库字段) + */ + private Long templateId; + + @JsonIgnore + protected String scanRounds; + + @Override + public String toString() { + return "GoodsSkuDO{" + + "skuId=" + skuId + + ", goodsId=" + goodsId + + ", goodsName='" + goodsName + '\'' + + ", sn='" + sn + '\'' + + ", quantity=" + quantity + + ", enableQuantity=" + enableQuantity + + ", price=" + price + + ", specs='" + specs + '\'' + + ", cost=" + cost + + ", weight=" + weight + + ", sellerId=" + sellerId + + ", sellerName='" + sellerName + '\'' + + ", categoryId=" + categoryId + + ", thumbnail='" + thumbnail + '\'' + + ", hashCode=" + hashCode + + ", templateId=" + templateId + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + GoodsSkuDO that = (GoodsSkuDO) o; + + return new EqualsBuilder() + .append(getSkuId(), that.getSkuId()) + .append(getGoodsId(), that.getGoodsId()) + .append(getGoodsName(), that.getGoodsName()) + .append(getSn(), that.getSn()) + .append(getQuantity(), that.getQuantity()) + .append(getEnableQuantity(), that.getEnableQuantity()) + .append(getPrice(), that.getPrice()) + .append(getSpecs(), that.getSpecs()) + .append(getCost(), that.getCost()) + .append(getWeight(), that.getWeight()) + .append(getSellerId(), that.getSellerId()) + .append(getSellerName(), that.getSellerName()) + .append(getCategoryId(), that.getCategoryId()) + .append(getThumbnail(), that.getThumbnail()) + .append(hashCode, that.hashCode) + .append(getTemplateId(), that.getTemplateId()) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(getSkuId()) + .append(getGoodsId()) + .append(getGoodsName()) + .append(getSn()) + .append(getQuantity()) + .append(getEnableQuantity()) + .append(getPrice()) + .append(getSpecs()) + .append(getCost()) + .append(getWeight()) + .append(getSellerId()) + .append(getSellerName()) + .append(getCategoryId()) + .append(getThumbnail()) + .append(hashCode) + .append(getTemplateId()) + .toHashCode(); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/ParameterGroupDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/ParameterGroupDO.java new file mode 100644 index 00000000..b27ac8f1 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/ParameterGroupDO.java @@ -0,0 +1,64 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.nutz.dao.entity.annotation.*; + +import javax.validation.constraints.NotEmpty; +import java.io.Serializable; + + +/** + * 参数组实体 + * + * @author fky + * + */ +@Data +@Table("mall_parameter_group") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class ParameterGroupDO implements Serializable { + + private static final long serialVersionUID = 2394621849767871L; + + /** + * 主键 + */ + @Id + @Column + @Comment("id") + @ColDefine(customType = "bigint") + private Long groupId; + /** + * 参数组名称 + */ + @Column + @Comment("参数组名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + @NotEmpty(message = "参数组名称不能为空") + @Length(max = 50, message = "参数组名称不能超过50字") + private String groupName; + /** + * 关联分类id + */ + @Column + @Comment("关联分类id") + @ColDefine(customType = "bigint") + private Long categoryId; + /** + * 排序 + */ + @Column + @Comment("id") + @ColDefine(type = ColType.INT) + private Integer sort; + + @Override + public String toString() { + return "ParameterGroupDO [groupId=" + groupId + ", groupName=" + groupName + ", categoryId=" + categoryId + + ", sort=" + sort + "]"; + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/ParametersDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/ParametersDO.java new file mode 100644 index 00000000..5f99103b --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/ParametersDO.java @@ -0,0 +1,113 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.nutz.dao.entity.annotation.*; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + + +/** + * 参数实体 + * + * @author fky + * + */ +@Data +@Table("mall_parameters") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class ParametersDO implements Serializable { + + private static final long serialVersionUID = 320610453789555L; + + /** + * 主键 + */ + @Id + @Column + @Comment("id") + @ColDefine(customType = "bigint") + private Long paramId; + /** + * 参数名称 + */ + @Column + @Comment("参数名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + @NotEmpty(message = "参数名称必填") + @Length(max = 50, message = "参数名称不能超过50字") + private String paramName; + /** + * 参数类型1 输入项 2 选择项 + */ + @Column + @Comment("参数类型1 输入项 2 选择项") + @ColDefine(type = ColType.INT) + @NotNull(message = "参数类型必选") + @Min(value = 1,message = "参数类型传值不正确") + @Max(value = 2,message = "参数类型传值不正确") + private Integer paramType; + /** + * 选择值,当参数类型是选择项2时,必填,逗号分隔 + */ + @Column + @Comment("选择值") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String options; + /** + * 是否可索引,0 不显示 1 显示 + */ + @Column + @Comment("是否可索引必选") + @ColDefine(type = ColType.INT) + @NotNull(message = "是否可索引必选") + @Min(value = 0,message = "是否可索引传值不正确") + @Max(value = 1,message = "是否可索引传值不正确") + private Integer isIndex; + /** + * 是否必填是 1 否 0 + */ + @Column + @Comment("是否必填") + @ColDefine(type = ColType.INT) + @NotNull(message = "是否必填必选") + @Min(value = 0,message = "是否必填传值不正确") + @Max(value = 1,message = "是否必填传值不正确") + private Integer required; + /** + * 参数分组id + */ + @Column + @Comment("参数分组id") + @ColDefine(customType = "bigint") + @NotNull(message = "所属参数组不能为空") + private Long groupId; + /** + * 分类id + */ + @Column + @Comment("分类id") + @ColDefine(customType = "bigint") + private Long categoryId; + /** + * 排序 + */ + @Column + @Comment("参数组名称") + @ColDefine(type = ColType.INT) + private Integer sort; + + @Override + public String toString() { + return "ParametersDO [paramId=" + paramId + ", paramName=" + paramName + ", paramType=" + paramType + + ", options=" + options + ", isIndex=" + isIndex + ", required=" + required + ", groupId=" + groupId + + ", categoryId=" + categoryId + ", sort=" + sort + "]"; + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/QuantityLog.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/QuantityLog.java new file mode 100644 index 00000000..8c69d992 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/QuantityLog.java @@ -0,0 +1,153 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import cn.hutool.core.builder.EqualsBuilder; +import cn.hutool.core.builder.HashCodeBuilder; +import com.budwk.app.zhgh.mall.manage.models.goods.vo.GoodsQuantityVO; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.nutz.dao.entity.annotation.*; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotEmpty; +import java.io.Serial; +import java.io.Serializable; + + +/** + * 库存日志表实体 + * + * @author fky + * + */ +@Data +@NoArgsConstructor +@Table("mall_quantity_log") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class QuantityLog implements Serializable { + + @Serial + private static final long serialVersionUID = 6427256120262393L; + + /** + * 日志id + */ + @Id + @Column + @Comment("id") + @ColDefine(customType = "bigint") + private Long logId; + /** + * 订单编号 + */ + @Column + @Comment("订单编号") + @ColDefine(type = ColType.VARCHAR, width = 100) + @NotEmpty(message = "订单编号不能为空") + private String orderSn; + /** + * 商品id + */ + @Column + @Comment("商品id") + @ColDefine(customType = "bigint") + @NotEmpty(message = "商品id不能为空") + private Long goodsId; + /** + * sku id + */ + @Column + @Comment("sku id") + @ColDefine(customType = "bigint") + private Long skuId; + /** + * 库存数 + */ + @Column + @Comment("库存数") + @ColDefine(type = ColType.INT) + @NotEmpty(message = "库存数不能为空") + private Integer quantity; + /** + * 可用库存 + */ + @Column + @Comment("可用库存") + @ColDefine(type = ColType.INT) + @Min(message = "必须为数字", value = 0) + private Integer enableQuantity; + /** + * 操作时间 + */ + @Column + @Comment("操作时间") + @ColDefine(customType = "bigint") + private Long opTime; + + @Column + @Comment("日志类型") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String logType; + + @Column + @Comment("原因") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String reason; + + public QuantityLog(GoodsQuantityVO goodsQuantity) { + this.skuId = goodsQuantity.getSkuId(); + this.quantity = goodsQuantity.getQuantity(); + + this.goodsId = goodsQuantity.getGoodsId(); + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + QuantityLog that = (QuantityLog) o; + + return new EqualsBuilder() + .append(orderSn, that.orderSn) + .append(goodsId, that.goodsId) + .append(skuId, that.skuId) + .append(quantity, that.quantity) + .append(enableQuantity, that.enableQuantity) + .append(logType, that.logType) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(orderSn) + .append(goodsId) + .append(skuId) + .append(quantity) + .append(enableQuantity) + .append(logType) + .toHashCode(); + } + + @Override + public String toString() { + return "QuantityLog{" + + "logId=" + logId + + ", orderSn='" + orderSn + '\'' + + ", goodsId=" + goodsId + + ", skuId=" + skuId + + ", quantity=" + quantity + + ", enableQuantity=" + enableQuantity + + ", opTime=" + opTime + + ", logType='" + logType + '\'' + + '}'; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/SpecValuesDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/SpecValuesDO.java new file mode 100644 index 00000000..10f92e0f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/SpecValuesDO.java @@ -0,0 +1,78 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serializable; + + +/** + * 规格值实体 + * + * @author fky + * + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Table("mall_spec_values") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class SpecValuesDO implements Serializable { + + private static final long serialVersionUID = 5356147177823233L; + + /** + * 主键 + */ + @Id + @Column + @Comment("规格值id") + @ColDefine(customType = "bigint") + private Long specValueId; + /** + * 规格项id + */ + @Column + @Comment("规格项id") + @ColDefine(customType = "bigint") + private Long specId; + /** + * 规格值名字 + */ + @Column + @Comment("规格值名字") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String specValue; + /** + * 所属卖家 + */ + @Column + @Comment("所属卖家") + @ColDefine(customType = "bigint") + private Long sellerId; + + /** + * 规格名称 + */ + @Column + @Comment("规格名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String specName; + + public SpecValuesDO(Long specId, String specValue, Long sellerId) { + super(); + this.specId = specId; + this.specValue = specValue; + this.sellerId = sellerId; + } + + @Override + public String toString() { + return "SpecValuesDO [specValueId=" + specValueId + ", specId=" + specId + ", specValue=" + specValue + + ", sellerId=" + sellerId + "]"; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/SpecificationDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/SpecificationDO.java new file mode 100644 index 00000000..c6ee3d27 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/SpecificationDO.java @@ -0,0 +1,83 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; +import org.nutz.dao.entity.annotation.*; + +import javax.validation.constraints.NotEmpty; +import java.io.Serializable; + + +/** + * 规格项实体 + * + * @author fky + * + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Table("mall_specification") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class SpecificationDO implements Serializable { + + private static final long serialVersionUID = 5111769180376075L; + + /** + * 主键 + */ + @Id + @Column + @Comment("id") + @ColDefine(customType = "bigint") + private Long specId; + /** + * 规格项名称 + */ + @Column + @Comment("规格项名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + @NotEmpty(message = "规格项名称不能为空") + private String specName; + /** + * 是否被删除0 删除 1 没有删除 + */ + @Column + @Comment("参数名称") + @ColDefine(type = ColType.INT) + private Integer disabled; + /** + * 规格描述 + */ + @Column + @Comment("规格描述") + @ColDefine(type = ColType.VARCHAR, width = 50) + @Length(max = 50, message = "规格备注为0到50个字符之间") + private String specMemo; + /** + * 所属卖家 0属于平台 + */ + @Column + @Comment("所属卖家 0属于平台") + @ColDefine(customType = "bigint") + private Long sellerId; + + public SpecificationDO(String specName, Integer disabled, String specMemo, Long sellerId) { + super(); + this.specName = specName; + this.disabled = disabled; + this.specMemo = specMemo; + this.sellerId = sellerId; + } + + @Override + public String toString() { + return "SpecificationDO [specId=" + specId + ", specName=" + specName + ", disabled=" + disabled + ", specMemo=" + + specMemo + ", sellerId=" + sellerId + "]"; + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/TagGoodsDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/TagGoodsDO.java new file mode 100644 index 00000000..723514c8 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/TagGoodsDO.java @@ -0,0 +1,64 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serial; +import java.io.Serializable; + + +/** + * 标签商品关联实体 + * + * @author fky + * + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Table("mall_tag_goods") +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class TagGoodsDO implements Serializable { + + @Serial + private static final long serialVersionUID = 9467335201085494L; + + @Id + @Column + @Comment("规格值id") + @ColDefine(customType = "bigint") + private Long id; + + /** + * 标签id + */ + @Column + @Comment("标签id") + @ColDefine(customType = "bigint") + private Long tagId; + /** + * 商品id + */ + @Column + @Comment("商品id") + @ColDefine(customType = "bigint") + private Long goodsId; + + public TagGoodsDO(Long tagId, Long goodsId) { + super(); + this.tagId = tagId; + this.goodsId = goodsId; + } + + @Override + public String toString() { + return "TagGoodsDO{" + + "tagId=" + tagId + + ", goodsId=" + goodsId + + '}'; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/TagsDO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/TagsDO.java new file mode 100644 index 00000000..a7a82042 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/entity/TagsDO.java @@ -0,0 +1,76 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.entity; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.nutz.dao.entity.annotation.*; + +import java.io.Serial; +import java.io.Serializable; + + +/** + * 商品标签实体 + * + * @author fky + * + */ +@Data +@Table("mall_tags") +@NoArgsConstructor +@AllArgsConstructor +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class TagsDO implements Serializable { + + @Serial + private static final long serialVersionUID = 1899720595535600L; + + /** + * 主键 + */ + @Id + @Column + @Comment("规格值id") + @ColDefine(customType = "bigint") + private Long tagId; + /** + * 标签名字 + */ + @Column + @Comment("标签名字") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String tagName; + /** + * 所属卖家 + */ + @Column + @Comment("所属卖家") + @ColDefine(customType = "bigint") + private Long sellerId; + /** + * 关键字 + */ + @Column + @Comment("关键字") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String mark; + + public TagsDO(String tagName, Long sellerId, String mark) { + super(); + this.tagName = tagName; + this.sellerId = sellerId; + this.mark = mark; + } + + @Override + public String toString() { + return "TagsDO{" + + "tagId=" + tagId + + ", tagName='" + tagName + '\'' + + ", sellerId=" + sellerId + + ", mark='" + mark + '\'' + + '}'; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/GoodsOperate.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/GoodsOperate.java new file mode 100644 index 00000000..a2c44e32 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/GoodsOperate.java @@ -0,0 +1,25 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.enums; + +/** + * 商品操作枚举 + * @author fky + */ +public enum GoodsOperate { + /** + * 下架 + */ + UNDER, + /** + * 还原 + */ + REVRET, + /** + * 放入回收站 + */ + RECYCLE, + /** + * 删除 + */ + DELETE + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/GoodsType.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/GoodsType.java new file mode 100644 index 00000000..702e9695 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/GoodsType.java @@ -0,0 +1,23 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.enums; + +/** + * 商品类型枚举 + * @author fky + */ +public enum GoodsType { + /** + * 正常商品 + */ + NORMAL("正常商品"), + /** + * 积分商品 + */ + POINT("积分商品"); + + private String description; + + GoodsType(String description) { + this.description = description; + + } +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/Permission.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/Permission.java new file mode 100644 index 00000000..b686eae7 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/Permission.java @@ -0,0 +1,30 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.enums; + + +/** + * 权限枚举 + * @author fky + */ +public enum Permission { + + /** + * 卖家权限 + */ + SELLER, + + /** + * 买家权限 + */ + BUYER, + + /** + * 管理员权限 + */ + ADMIN, + + /** + * 不验证权限 + */ + CLIENT + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/QuantityLogType.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/QuantityLogType.java new file mode 100644 index 00000000..1b70a59a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/QuantityLogType.java @@ -0,0 +1,33 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.enums; + +/** + * 库存日志类型 + * @author fky + */ +public enum QuantityLogType { + + /** + * 订单创建扣减库存 + */ + ORDER_CREATE, + + /** + * 订单取消 + */ + ORDER_CANCEL, + + /** + * 库存回滚 + */ + ROLLBACK, + + /** + * 发货 + */ + SHIP, + + /** + * 退货 + */ + RETURN +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/QuantityType.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/QuantityType.java new file mode 100644 index 00000000..b258d9c8 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/QuantityType.java @@ -0,0 +1,19 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.enums; + +/** + * 库存数类型 + * @author fky + */ +public enum QuantityType { + + /** + * 实际的库存,包含了待发货的 + */ + actual, + + /** + * 可以售的库存,不包含待发货的 + */ + enable + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/StockType.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/StockType.java new file mode 100644 index 00000000..171d9759 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/StockType.java @@ -0,0 +1,31 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.enums; + +/** + * 缓存中库存类型 + * 用于更新缓存等操作使用 + * @author fky + */ +public enum StockType { + + + /** + * sku实际的库存,包含了待发货的 + */ + SKU_STOCK_ACTUAL, + + /** + * sku可以售的库存,不包含待发货的 + */ + SKU_STOCK_ENABLE, + + /** + * goods实际的库存,包含了待发货的 + */ + GOODS_STOCK_ACTUAL, + + /** + * goods可以售的库存,不包含待发货的 + */ + GOODS_STOCK_ENABLE, + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/TagType.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/TagType.java new file mode 100644 index 00000000..7c08b02a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/enums/TagType.java @@ -0,0 +1,38 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.enums; + +/** + * 标签类型 + * @author fky + */ +public enum TagType { + + /** + * 热卖排行 + */ + HOT("hot","热卖排行"), + /** + * 新品推荐 + */ + NEW("new","新品推荐"), + /** + * 推荐商品 + */ + RECOMMEND("recommend","推荐商品"); + + private String mark; + private String tagName; + + TagType(String mark,String tagName) { + + this.mark = mark; + this.tagName = tagName; + } + + public String mark(){ + return this.mark; + } + + public String tagName(){ + return this.tagName; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/ExchangeVO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/ExchangeVO.java new file mode 100644 index 00000000..7e3626fa --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/ExchangeVO.java @@ -0,0 +1,48 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.vo; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 商品的积分兑换信息 + * @author fky + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class ExchangeVO implements Serializable{ + + @Serial + private static final long serialVersionUID = 4702156500500693965L; + + /** 是否允许兑换 */ + @ApiModelProperty("是否允许积分兑换") + private Integer enableExchange; + + /** 兑换所需金额 */ + @ApiModelProperty("兑换所需金额") + private Double exchangeMoney; + + /** 商品所属积分分类 */ + @ApiModelProperty("积分兑换所属分类") + private Long categoryId; + + /** 兑换所需积分 */ + @ApiModelProperty("积分兑换使用的积分") + private Integer exchangePoint; + + @Override + public String toString() { + return "ExchangeVO [enableExchange=" + enableExchange + ", exchangeMoney=" + exchangeMoney + ", categoryId=" + + categoryId + ", exchangePoint=" + exchangePoint + "]"; + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/GoodsMobileIntroVO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/GoodsMobileIntroVO.java new file mode 100644 index 00000000..f5869460 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/GoodsMobileIntroVO.java @@ -0,0 +1,64 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.vo; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Objects; + +/** + * 商品移动端详情VO + * @author fky + */ +@Data +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class GoodsMobileIntroVO implements Serializable { + + @Serial + private static final long serialVersionUID = 7556885109369605084L; + + @ApiModelProperty("类型 text:文字,image:图片") + private String type; + + @ApiModelProperty("内容") + private String content; + + @ApiModelProperty("是否选中") + private Boolean checked; + + @ApiModelProperty("是否选中编辑") + private Boolean editChecked; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + GoodsMobileIntroVO that = (GoodsMobileIntroVO) o; + return Objects.equals(type, that.type) && + Objects.equals(content, that.content) && + Objects.equals(checked, that.checked) && + Objects.equals(editChecked, that.editChecked); + } + + @Override + public int hashCode() { + return Objects.hash(type, content, checked, editChecked); + } + + @Override + public String toString() { + return "GoodsMobileIntroVO{" + + "type='" + type + '\'' + + ", content='" + content + '\'' + + ", checked=" + checked + + ", editChecked=" + editChecked + + '}'; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/GoodsQuantityVO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/GoodsQuantityVO.java new file mode 100644 index 00000000..2fab8a39 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/GoodsQuantityVO.java @@ -0,0 +1,91 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.vo; + + +import cn.hutool.core.builder.EqualsBuilder; +import cn.hutool.core.builder.HashCodeBuilder; +import com.budwk.app.zhgh.mall.manage.models.goods.enums.QuantityType; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 商品库存vo + * @author fky + */ +@Data +@NoArgsConstructor +public class GoodsQuantityVO implements Cloneable{ + + private Long goodsId; + + private Long skuId; + + private Integer quantity; + + private QuantityType quantityType; + + + public GoodsQuantityVO(Long goodsId, Long skuId, Integer quantity ) { + super(); + this.goodsId = goodsId; + this.skuId = skuId; + this.quantity = quantity; + + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + + public Integer getQuantity() { + if ( quantity==null){ + return 0; + } + + return quantity; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + GoodsQuantityVO that = (GoodsQuantityVO) o; + + return new EqualsBuilder() + .append(goodsId, that.goodsId) + .append(skuId, that.skuId) + .append(quantity, that.quantity) + .append(quantityType, that.quantityType) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(goodsId) + .append(skuId) + .append(quantity) + .append(quantityType) + .toHashCode(); + } + + @Override + public String toString() { + return "GoodsQuantityVO{" + + "goodsId=" + goodsId + + ", skuId=" + skuId + + ", quantity=" + quantity + + ", quantityType=" + quantityType + + '}'; + } + + +} + diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/GoodsSkuVO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/GoodsSkuVO.java new file mode 100644 index 00000000..e382c316 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/GoodsSkuVO.java @@ -0,0 +1,176 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.vo; + +import cn.hutool.json.JSONUtil; +import com.budwk.app.zhgh.mall.manage.models.goods.entity.DraftGoodsSkuDO; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.Max; +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +/** + * 商品sku + * @author fky + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class GoodsSkuVO implements Serializable { + + @Serial + private static final long serialVersionUID = -666090547834195127L; + + /** + * 主键 + */ + @ApiModelProperty("sku表主键") + private Long skuId; + /** + * 商品id + */ + @ApiModelProperty("商品id") + private Long goodsId; + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String goodsName; + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + @Length(max = 30,message = "商品规格编号太长,不能超过30个字符") + private String sn; + + /** + * 库存 + */ + @ApiModelProperty("库存") + @Max(value = 99999999, message = "库存不能超过99999999") + + private Integer quantity; + /** + * 可用库存 + */ + @ApiModelProperty("可用库存") + + private Integer enableQuantity; + /** + * 商品价格 + */ + @ApiModelProperty("商品价格") + @Max(value = 99999999, message = "价格不能超过99999999") + private Double price; + /** + * 规格信息json + */ + @ApiModelProperty("规格信息json") + private String specs; + /** + * 成本价格 + */ + @ApiModelProperty("成本价格") + @Max(value = 99999999, message = "成本价格不能超过99999999") + private Double cost; + /** + * 重量 + */ + @ApiModelProperty("重量") + @Max(value = 99999999, message = "重量不能超过99999999") + private Double weight; + /** + * 卖家id + */ + @ApiModelProperty("卖家id") + private Long sellerId; + /** + * 卖家名称 + */ + @ApiModelProperty("卖家名称") + private String sellerName; + /** + * 分类id + */ + @ApiModelProperty("分类id") + private Long categoryId; + /** + * 缩略图 + */ + @ApiModelProperty("缩略图") + private String thumbnail; + + + @ApiModelProperty("hash_code") + private Integer hashCode; + + /** + * 运费模板ID(非数据库字段) + */ + @ApiModelProperty("运费模板ID") + private Long templateId; + + @JsonIgnore + protected String scanRounds; + + @ApiModelProperty("规格列表") + private List specList; + + @ApiModelProperty("谁承担运费0:买家承担,1:卖家承担") + private Integer goodsTransfeeCharge; + + @ApiModelProperty("是否被删除 0 删除 1 未删除") + private Integer disabled; + + @ApiModelProperty("上架状态 0下架 1上架") + private Integer marketEnable; + + @ApiModelProperty("商品类型NORMAL普通POINT积分") + private String goodsType; + + @ApiModelProperty("最后修改时间") + private Long lastModify; + + @ApiModelProperty("运费脚本") + private List scripts; + + public List getSpecList() { + if (this.getSpecs() != null) { + return JSONUtil.toList(this.getSpecs(), SpecValueVO.class); + } + + return specList; + } + + public GoodsSkuVO(DraftGoodsSkuDO draftSku) { + this.setCost(draftSku.getCost()); + this.setPrice(draftSku.getPrice()); + this.setQuantity(draftSku.getQuantity()); + this.setSkuId(draftSku.getDraftSkuId()); + this.setSn(draftSku.getSn()); + this.setWeight(draftSku.getWeight()); + this.setSpecList(JSONUtil.toList(draftSku.getSpecs(), SpecValueVO.class)); + } + + + @Override + public String toString() { + return "GoodsSkuVO{" + + "specList=" + specList + + ", goodsTransfeeCharge=" + goodsTransfeeCharge + + ", disabled=" + disabled + + ", marketEnable=" + marketEnable + + ", goodsType='" + goodsType + '\'' + + ", lastModify=" + lastModify + + ", scripts=" + scripts + + '}'; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/SpecValueVO.java b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/SpecValueVO.java new file mode 100644 index 00000000..06a82907 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/mall/manage/models/goods/vo/SpecValueVO.java @@ -0,0 +1,95 @@ +package com.budwk.app.zhgh.mall.manage.models.goods.vo; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 规格值实体 + * @author fky + */ +@Data +@NoArgsConstructor +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class SpecValueVO implements Serializable { + + /** + * 序列号 + */ + private static final long serialVersionUID = 1426807099688672502L; + + /** + * 主键 + */ + @ApiModelProperty("规格值id") + private Long specValueId; + /** + * 规格项id + */ + @ApiModelProperty("规格项id") + private Long specId; + /** + * 规格值名字 + */ + @ApiModelProperty("规格值名字") + private String specValue; + /** + * 所属卖家 + */ + @ApiModelProperty("所属卖家") + private Long sellerId; + + /** + * 规格名称 + */ + @ApiModelProperty("规格名称") + private String specName; + + /** + * 商品sku——id + */ + @ApiModelProperty("sku_id") + private Long skuId; + /** + * 商品大图 + */ + @ApiModelProperty("商品大图") + private String big; + /** + * 商品小图 + */ + @ApiModelProperty("商品小图") + private String small; + /** + * 商品缩略图 + */ + @ApiModelProperty("商品缩略图") + private String thumbnail; + /** + * 商品极小图 + */ + @ApiModelProperty("商品极小图") + private String tiny; + + /** + * 规格类型,1图片 0 非图片 + */ + @ApiModelProperty("该规格是否有图片,1 有 0 没有") + private Integer specType; + /** + * 规格图片 + */ + @ApiModelProperty("规格的图片") + private String specImage; + + @Override + public String toString() { + return "SpecValueVO [skuId=" + skuId + ", big=" + big + ", small=" + small + ", thumbnail=" + thumbnail + + ", tiny=" + tiny + ", specType=" + specType + ", specImage=" + specImage + "]"; + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpApplyController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpApplyController.java new file mode 100644 index 00000000..63bb6348 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpApplyController.java @@ -0,0 +1,170 @@ +package com.budwk.app.zhgh.staffbenefit.difficulthelp.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.flow.engine.FlowEngine; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.models.DifficultHelpInfo; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.service.DifficultHelpCommonService; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.vo.DifficultHelpPageParam; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiOperation; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import javax.validation.Valid; + +/** + * @version 1.0 + * @Author zzr + * @name:DifficultHelpApplyController + * @Date 2025/7/31 8:41 + * @注释 困难补助申请 + */ +@IocBean +@Ok("json") +@ApiOperation("困难补助申请") +@At("/platform/difficultHelp/apply") +public class DifficultHelpApplyController { + + @Inject + private Dao dao; + @Inject + private FlowEngine flowEngine; + @Inject + private DifficultHelpCommonService difficultHelpCommonService; + + @At("") + @SaCheckPermission("difficultHelp.apply") + @Ok("beetl:/platform/zhgh/staffbenefit/difficulthelp/apply/index.html") + public void index() { + } + + @At + @SaCheckPermission("difficultHelp.apply") + @Ok("beetl:/platform/zhgh/staffbenefit/difficulthelp/apply/form.html") + public void form() { + } + + + @At + @ApiOperation("困难补助申请,我的申请列表") + @SaCheckPermission("difficultHelp.apply") + public Result pageData(DifficultHelpPageParam pageParam) { + Sql sql = Sqls.create(""" + SELECT + info.id, + info.proxyUserName, + info.proxyLoginName, + info.userName, + info.loginName, + info.unitName, + info.unionName, + info.subsidyStandards, + info.applyTime, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariale, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariable, + IF((SELECT taskName FROM wf_process_task tt WHERE tt.id = t.taskParentId) = 'startTask', 1, 0) canRevoke, + (SELECT MAX(id) FROM wf_process_task WHERE processInstanceId = ins.id AND taskName = 'startTask') AS startTaskId + FROM + difficult_help_info info + LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id + LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id AND t.taskState = 10 + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + $condition + """); + Cnd cnd = Cnd.NEW(); + pageParam.buildSearch(cnd, "info."); + if (StrUtil.isAllBlank(pageParam.getPageOrderName(), pageParam.getPageOrderBy())) { + cnd.desc("info.applyTime"); + } else { + cnd.orderBy("info." + pageParam.getPageOrderName(), PageUtil.getOrder(pageParam.getPageOrderBy())); + } + sql.setCondition(cnd); + Pagination pagination = difficultHelpCommonService.listPageMap(pageParam.getPageNumber(), pageParam.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + @At + @ApiOperation("获取受助人") + @SaCheckPermission("difficultHelp.apply") + public Result queryRecipients(String key){ + Sql sql = Sqls.create(""" + SELECT + id, + loginname, + username, + birthday, + mobile, + sex, + unitName, + unionName, + unionId, + unitId + FROM + `vw_user` + $condition + """); + Cnd cnd = Cnd.NEW(); + + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + if (AuthUtil.hasRoleOr(RoleConstant.BRANCH_UNION_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_ADMIN.name(), RoleConstant.BRANCH_UNION_OPERATOR.name())) { + cnd.and("unionid", "=", SecurityUtil.getUnionId()); + } else { + cnd.and("id", "=", SecurityUtil.getUserId()); + } + } + + if (Strings.isNotBlank(key)) { + SqlExpressionGroup group = new SqlExpressionGroup(); + group.orLike("username", key); + group.orLike("loginname", key); + cnd.and(group); + } + sql.setCondition(cnd); + Pagination pagination = difficultHelpCommonService.listPageMap(1, 10, sql); + return Result.success().addData(pagination.getList()); + } + + + + @At + @Aop(TransAop.READ_COMMITTED) + @ApiOperation("困难帮扶删除申请") + @SLog(tag = "困难帮扶申请", msg = "删除困难帮扶申请") + public Result onDelete(@Valid String id){ + dao.clear(DifficultHelpInfo.class, Cnd.where("id", "=", id)); + // 流程相关操作 + flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(id); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpBranchUnionApprovalController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpBranchUnionApprovalController.java new file mode 100644 index 00000000..198d850b --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpBranchUnionApprovalController.java @@ -0,0 +1,119 @@ +package com.budwk.app.zhgh.staffbenefit.difficulthelp.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.flow.enums.ProcessTaskStateEnum; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.service.DifficultHelpCommonService; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.vo.DifficultHelpPageParam; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.util.List; + +/** + * @version 1.0 + * @Author zzr + * @name:DifficultHelpBranchUnionApprovalController + * @Date 2025/7/31 11:47 + * @注释 + */ +@IocBean +@Ok("json") +@ApiOperation("困难补助分工会审核") +@At("/platform/difficultHelp/branchUnionApproval") +public class DifficultHelpBranchUnionApprovalController { + + @Inject + private Dao dao; + @Inject + private DifficultHelpCommonService difficultHelpCommonService; + + @At("") + @SaCheckPermission("difficultHelp.branchUnionApproval") + @Ok("beetl:/platform/zhgh/staffbenefit/difficulthelp/branchunionapproval/index.html") + public void index() { + } + + @At + @SaCheckPermission("difficultHelp.branchUnionApproval") + @Ok("beetl:/platform/zhgh/staffbenefit/difficulthelp/branchunionapproval/form.html") + public void form() { + } + + + @At + @ApiOperation("困难补助分工会审核列表") + @SaCheckPermission("difficultHelp.branchUnionApproval") + public Result pageData(DifficultHelpPageParam pageParam) { + Sql sql = Sqls.create(""" + SELECT + info.id, + info.proxyUserName, + info.proxyLoginName, + info.userName, + info.loginName, + info.unitName, + info.unionName, + info.subsidyStandards, + info.applyTime, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariale, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariable, + IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName, + IF(rt.id IS NOT NULL, 1, 0) AS canRevoke + FROM + wf_process_task t + LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId + LEFT JOIN difficult_help_info info ON info.id = ins.businessNo + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10 + LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10 + $condition + """); + Cnd cnd = Cnd.NEW(); + pageParam.buildSearch(cnd, "info."); + + cnd.and("t.taskName", "=", "9d11798e-a0e4-4ff5-939b-e6c5519e0eb6"); + cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId())); + + if (pageParam.getAudit()) { + cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.WITHDRAW.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode())); + } else { + cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode()); + } + if (StrUtil.isAllBlank(pageParam.getPageOrderName(), pageParam.getPageOrderBy())) { + cnd.desc("t.createdAt"); + cnd.desc("info.applyTime"); + } else { + cnd.orderBy("info." + pageParam.getPageOrderName(), PageUtil.getOrder(pageParam.getPageOrderBy())); + } + cnd.groupBy("t.id"); + sql.setCondition(cnd); + + Pagination pagination = difficultHelpCommonService.listPageMap(pageParam.getPageNumber(), pageParam.getPageSize(), sql); + return Result.success().addData(pagination); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpReadingController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpReadingController.java new file mode 100644 index 00000000..9bc0865c --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpReadingController.java @@ -0,0 +1,86 @@ +package com.budwk.app.zhgh.staffbenefit.difficulthelp.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.service.DifficultHelpCommonService; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.vo.DifficultHelpPageParam; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @version 1.0 + * @Author zzr + * @name:DifficultHelpReadingController + * @Date 2025/7/31 15:07 + * @注释 + */ +@IocBean +@Ok("json") +@ApiOperation("困难补助汇总阅览") +@At("/platform/difficultHelp/reading") +public class DifficultHelpReadingController { + + @Inject + private Dao dao; + @Inject + private DifficultHelpCommonService difficultHelpCommonService; + + @At("") + @SaCheckPermission("difficultHelp.reading") + @Ok("beetl:/platform/zhgh/staffbenefit/difficulthelp/reading/index.html") + public void index() { + } + + + @At + @ApiOperation("困难补助汇总阅览列表") + @SaCheckPermission("difficultHelp.reading") + public Result pageData(DifficultHelpPageParam pageParam) { + Sql sql = Sqls.create(""" + SELECT + info.id, + info.proxyUserName, + info.proxyLoginName, + info.userName, + info.loginName, + info.unitName, + info.unionName, + info.subsidyStandards, + info.applyTime, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariale, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariable + FROM + difficult_help_info info + LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id + LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + $condition + """); + Cnd cnd = Cnd.NEW(); + pageParam.buildSearch(cnd, "info."); + Pagination pagination = difficultHelpCommonService.listPageMap(pageParam.getPageNumber(), pageParam.getPageSize(), sql); + return Result.success().addData(pagination); + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpSchoolUnionApprovalController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpSchoolUnionApprovalController.java new file mode 100644 index 00000000..0908b1b1 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpSchoolUnionApprovalController.java @@ -0,0 +1,119 @@ +package com.budwk.app.zhgh.staffbenefit.difficulthelp.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.flow.enums.ProcessTaskStateEnum; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.service.DifficultHelpCommonService; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.vo.DifficultHelpPageParam; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.util.List; + +/** + * @version 1.0 + * @Author zzr + * @name:DifficultHelpSchoolUnionApprovalController + * @Date 2025/7/31 11:47 + * @注释 + */ +@IocBean +@Ok("json") +@ApiOperation("困难补助校工会审核") +@At("/platform/difficultHelp/schoolUnionApproval") +public class DifficultHelpSchoolUnionApprovalController { + + @Inject + private Dao dao; + @Inject + private DifficultHelpCommonService difficultHelpCommonService; + + @At("") + @SaCheckPermission("difficultHelp.schoolUnionApproval") + @Ok("beetl:/platform/zhgh/staffbenefit/difficulthelp/schoolunionapproval/index.html") + public void index() { + } + + @At + @SaCheckPermission("difficultHelp.schoolUnionApproval") + @Ok("beetl:/platform/zhgh/staffbenefit/difficulthelp/schoolunionapproval/form.html") + public void form() { + } + + + @At + @ApiOperation("困难补助校工会审核列表") + @SaCheckPermission("difficultHelp.schoolUnionApproval") + public Result pageData(DifficultHelpPageParam pageParam) { + Sql sql = Sqls.create(""" + SELECT + info.id, + info.proxyUserName, + info.proxyLoginName, + info.userName, + info.loginName, + info.unitName, + info.unionName, + info.subsidyStandards, + info.applyTime, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariable, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariable, + IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName, + IF(rt.id IS NOT NULL, 1, 0) AS canRevoke + FROM + wf_process_task t + LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId + LEFT JOIN difficult_help_info info ON info.id = ins.businessNo + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10 + LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10 + $condition + """); + Cnd cnd = Cnd.NEW(); + pageParam.buildSearch(cnd, "info."); + + cnd.and("t.taskName", "=", "715ece82-4ae3-433c-ad18-ed875f45d1e3"); + cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId())); + + if (pageParam.getAudit()) { + cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.WITHDRAW.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode())); + } else { + cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode()); + } + if (StrUtil.isAllBlank(pageParam.getPageOrderName(), pageParam.getPageOrderBy())) { + cnd.desc("t.createdAt"); + cnd.desc("info.applyTime"); + } else { + cnd.orderBy("info." + pageParam.getPageOrderName(), PageUtil.getOrder(pageParam.getPageOrderBy())); + } + cnd.groupBy("t.id"); + sql.setCondition(cnd); + + Pagination pagination = difficultHelpCommonService.listPageMap(pageParam.getPageNumber(), pageParam.getPageSize(), sql); + return Result.success().addData(pagination); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpViewController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpViewController.java new file mode 100644 index 00000000..31036922 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpViewController.java @@ -0,0 +1,47 @@ +package com.budwk.app.zhgh.staffbenefit.difficulthelp.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.models.DifficultHelpInfo; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.service.DifficultHelpCommonService; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @version 1.0 + * @Author zzr + * @name:DifficultHelpViewController + * @Date 2025/7/31 11:50 + * @注释 + */ +@IocBean +@Ok("json") +@ApiOperation("困难补助查看") +@At("/platform/difficultHelp/view") +public class DifficultHelpViewController { + + @Inject + private Dao dao; + @Inject + private DifficultHelpCommonService difficultHelpCommonService; + + @At("") + @SaCheckPermission("difficultHelp.apply") + @Ok("beetl:/platform/zhgh/staffbenefit/difficulthelp/view/index.html") + public void index() { + } + + + @At + @ApiModelProperty("获取困难补助申请") + @SaCheckPermission("difficultHelp.apply") + public Result findOne(String id) { + DifficultHelpInfo helpInfo = dao.fetch(DifficultHelpInfo.class, id); + return Result.success().addData(helpInfo); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/interceptor/DifficultHelpSaveInterceptor.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/interceptor/DifficultHelpSaveInterceptor.java new file mode 100644 index 00000000..8ae79f5c --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/interceptor/DifficultHelpSaveInterceptor.java @@ -0,0 +1,40 @@ +package com.budwk.app.zhgh.staffbenefit.difficulthelp.interceptor; + +import com.budwk.app.flow.constant.FlowConst; +import com.budwk.app.flow.engine.FlowInterceptor; +import com.budwk.app.flow.engine.core.Execution; +import com.budwk.app.flow.engine.core.ServiceContext; +import com.budwk.app.flow.entity.ProcessInstance; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.models.DifficultHelpInfo; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.json.Json; + +import java.util.Date; + +/** + * @version 1.0 + * @Author zzr + * @name:DifficultHelpSaveInterceptor + * @Date 2025/7/31 11:04 + * @注释 + */ +public class DifficultHelpSaveInterceptor implements FlowInterceptor { + + @Override + public void intercept(Execution execution) { + System.out.println("difficult help apply .................."); + String formDataStr = execution.getArgs().getStr(FlowConst.FORM_DATA); + + Dao dao = ServiceContext.find(Dao.class); + DifficultHelpInfo article = Json.fromJson(DifficultHelpInfo.class, formDataStr); + article.setApplyTime(new Date()); + dao.insertOrUpdate(article); + + execution.getArgs().set(FlowConst.FORM_DATA, Json.toJson(article)); + + int instanceId = execution.getArgs().getInt(FlowConst.PROCESS_INSTANCE_ID_KEY); + dao.update(ProcessInstance.class, Chain.make("businessNo", article.getId()), Cnd.where(ProcessInstance::getId, "=", instanceId)); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/models/DifficultHelpInfo.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/models/DifficultHelpInfo.java new file mode 100644 index 00000000..e89635f8 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/models/DifficultHelpInfo.java @@ -0,0 +1,160 @@ +package com.budwk.app.zhgh.staffbenefit.difficulthelp.models; + +import cn.hutool.json.JSONObject; +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.util.Date; +import java.util.List; + +/** + * @version 1.0 + * @Author zzr + * @name:DifficulHelpInfo + * @Date 2025/7/30 17:33 + * @注释 + */ +@Data +@Table +@EqualsAndHashCode(callSuper = true) +public class DifficultHelpInfo extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("申请时间") + @ColDefine(type = ColType.DATETIME) + private Date applyTime; + + @Column + @Comment("申请模式") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String mode; + + @Column + @Comment("填写人id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String proxyUserId; + + @Column + @Comment("填写人姓名") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String proxyUserName; + + @Column + @Comment("填写人工号") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String proxyLoginName; + + @Column + @Comment("申请人id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String userId; + + @Column + @Comment("申请人姓名") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String userName; + + @Column + @Comment("申请人工号") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String loginName; + + @Column + @Comment("性别") + @ColDefine(type = ColType.VARCHAR, width = 10) + private String sex; + + @Column + @Comment("单位") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("单位名称") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String unitName; + + @Column + @Comment("分工会id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("工会名称") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String unionName; + + @Column + @Comment("月收入") + @ColDefine(type = ColType.VARCHAR, width = 10) + private String monthlyIncome; + + @Column + @Comment("出生日期") + @ColDefine(type = ColType.DATE) + private Date birthday; + + @Column + @Comment("联系电话") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String mobile; + + @Column + @Comment("身份证号码") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String idCard; + + @Column + @Comment("职务职称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String officialCapacity; + + @Column + @Comment("银行卡号(华夏银行工资卡卡号)") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String bankCardNum; + + @Column + @Comment("家庭住址") + @ColDefine(type = ColType.VARCHAR, width = 200) + private String homeAddress; + + @Column + @Comment("补助标准") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String subsidyStandards; + + @Column + @Comment("家庭成员") + @ColDefine(type = ColType.MYSQL_JSON) + private List familyList; + + @Column + @Comment("申请理由") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String reason; + + @Column + @Comment("备注") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String remarks; + + @Column + @Comment("附件") + @ColDefine(type = ColType.MYSQL_JSON) + private List files; + + @Column + @Comment("申请人签字") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String sign; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/service/DifficultHelpCommonService.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/service/DifficultHelpCommonService.java new file mode 100644 index 00000000..34b6e296 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/service/DifficultHelpCommonService.java @@ -0,0 +1,14 @@ +package com.budwk.app.zhgh.staffbenefit.difficulthelp.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.models.DifficultHelpInfo; + +/** + * @version 1.0 + * @Author zzr + * @name:DifficultHelpCommonService + * @Date 2025/7/31 9:16 + * @注释 + */ +public interface DifficultHelpCommonService extends BaseService { +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/service/impl/DifficultHelpCommonServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/service/impl/DifficultHelpCommonServiceImpl.java new file mode 100644 index 00000000..d6d1696c --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/service/impl/DifficultHelpCommonServiceImpl.java @@ -0,0 +1,22 @@ +package com.budwk.app.zhgh.staffbenefit.difficulthelp.service.impl; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.models.DifficultHelpInfo; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.service.DifficultHelpCommonService; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +/** + * @version 1.0 + * @Author zzr + * @name:DifficultHelpCommonServiceImpl + * @Date 2025/7/31 9:16 + * @注释 + */ +@IocBean(args = {"refer:dao"}) +public class DifficultHelpCommonServiceImpl extends BaseServiceImpl implements DifficultHelpCommonService { + + public DifficultHelpCommonServiceImpl(Dao dao) { + super(dao); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/vo/DifficultHelpPageParam.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/vo/DifficultHelpPageParam.java new file mode 100644 index 00000000..0955a5f4 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/vo/DifficultHelpPageParam.java @@ -0,0 +1,59 @@ +package com.budwk.app.zhgh.staffbenefit.difficulthelp.vo; + +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.difficulthelp.models.DifficultHelpInfo; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.Cnd; +import org.nutz.lang.Lang; + +import java.util.List; + +/** + * @version 1.0 + * @Author zzr + * @name:DifficultHelpPageParam + * @Date 2025/7/31 9:50 + * @注释 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class DifficultHelpPageParam extends PageForm { + + private String year; + + private String unionId; + + private String unitId; + + private List dateRange; + + public void buildSearch(Cnd cnd, String prefix){ + if (cnd == null) { + cnd = Cnd.NEW(); + } + + cnd.andEX("YEAR(" + prefix + "applyTime)", "=", this.getYear()); + + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + if (AuthUtil.hasRoleOr(RoleConstant.BRANCH_UNION_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_ADMIN.name(), RoleConstant.BRANCH_UNION_OPERATOR.name())) { + cnd.and(prefix + "unionid", "=", SecurityUtil.getUnionId()); + } else { + cnd.and(prefix + "userId", "=", SecurityUtil.getUserId()); + } + } else { + cnd.andEX(prefix + "unionId", "=", this.getUnionId()); + } + + cnd.andEX(prefix + "unitId", "=", this.getUnitId()); + + if (Lang.isNotEmpty(this.getDateRange())) { + cnd.andEX("DATE(" + prefix + "applyTime)", ">=", this.getDateRange().get(0)); + cnd.andEX("DATE(" + prefix + "applyTime)", "<=", this.getDateRange().get(1)); + } + + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/constant/MemberChangeOrigin.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/constant/MemberChangeOrigin.java index dea5c619..eba2f917 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/constant/MemberChangeOrigin.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/constant/MemberChangeOrigin.java @@ -16,14 +16,15 @@ import lombok.Getter; @AllArgsConstructor public enum MemberChangeOrigin { - PERSONAL("个人"), + PERSONAL("个人申请变更"), BRANCH_UNION("分工会变更"), BRANCH_UNION_VERIFICATION("分工会名单事项核对"), UNION_GROUP("工会小组变更"), SCHOOL_UNION("校工会变更"), SCHOOL_UNION_VERIFICATION("校工会名单事项核对"), SYSTEM("系统数据更新"), - OTHER("其他"); + HAND_MOVEMENT("手动数据更新"), + OTHER("其他方式变更"); /** * 避免和枚举类的name冲突 diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/constant/MemberChangeType.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/constant/MemberChangeType.java index f905537f..60d47d98 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/constant/MemberChangeType.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/constant/MemberChangeType.java @@ -1,5 +1,6 @@ package com.budwk.app.zhgh.staffmanage.member.constant; +import com.budwk.app.base.annotation.DictEnum; import lombok.AllArgsConstructor; import lombok.Getter; @@ -12,13 +13,22 @@ import lombok.Getter; */ @Getter @AllArgsConstructor +@DictEnum(key = "MemberChangeType", name = "会员变更类型") public enum MemberChangeType { //变更类型 NEW("新入职"), RESTORE("入会"), WITHDRAWAL("退会"), + WORK("在职"), + LEAVE_SCHOOL("离校"), + RETIRE("退休"), + RESIGN("辞职"), + OUT("调出"), + LEAVE_OFFICE("离职"), + OTHER("其他减员"), UNIT_CHANGE("单位异动"), + UNION_CHANGE("工会关系异动"), BASIC_CHANGE("基本信息异动"); diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyBranchUnionApprovalController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyBranchUnionApprovalController.java new file mode 100644 index 00000000..7210d56f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyBranchUnionApprovalController.java @@ -0,0 +1,156 @@ +package com.budwk.app.zhgh.staffmanage.member.controller.apply; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.BpmProcessConstant; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.bpm.enums.BpmProcessTaskStatusEnum; +import com.budwk.app.bpm.enums.BpmTaskApprovalTypeEnum; +import com.budwk.app.bpm.param.BpmTaskApprovalParam; +import com.budwk.app.bpm.service.BpmService; +import com.budwk.app.flow.enums.ProcessTaskStateEnum; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.web.commons.base.Globals; +import com.budwk.app.web.controllers.open.commons.service.CommonService; +import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberApplyPageForm; +import com.budwk.app.zhgh.staffmanage.member.service.MemberApplyRecordService; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; +import com.budwk.app.zhgh.staffmanage.member.vo.MemberCommonVo; +import io.swagger.annotations.ApiOperation; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.Static; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 会员入会申请分工会审核 + * @author fky + */ +@IocBean +@Ok("json:full") +@ApiOperation("会员入会申请分工会审核") +@At("/platform/member/apply/branchUnionApproval") +public class MemberApplyBranchUnionApprovalController { + + @Inject + private BpmService bpmService; + @Inject + private CommonService commonService; + @Inject + private MemberCommonService memberCommonService; + @Inject + private MemberApplyRecordService memberApplyRecordService; + + @At("") + @Ok("beetl:/platform/zhgh/staffmanage/member/apply/branchunionapproval/index.html") + @SaCheckPermission("member.apply.branchUnionApproval") + public void index() { + } + + @At + @Ok("beetl:/platform/zhgh/staffmanage/member/apply/branchunionapproval/form.html") + @SaCheckPermission("member.apply.branchUnionApproval") + public void form() { + } + + @At + @ApiOperation("会员入会申请分工会审核列表") + @SaCheckPermission("member.apply.branchUnionApproval") + public Result pageData(MemberApplyPageForm pageForm) { + Sql sql = Sqls.create(""" + SELECT + info.id, + info.userName, + info.loginName, + info.unitName, + info.unionName, + info.userState, + info.preparedBy, + info.personType, + info.sign, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariale, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariable, + IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName, + IF(rt.id IS NOT NULL, 1, 0) AS canRevoke + FROM + wf_process_task t + LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId + LEFT JOIN member_apply_record info ON info.id = ins.businessNo + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10 + LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10 + $condition + """); + Cnd cnd = Cnd.NEW(); + MemberApplyPageForm.buildSearch(cnd, pageForm); + + if ("HMC".equals(Globals.SchoolCode)) { + cnd.and("t.taskName", "=", "8337f4ee-d8ff-45e2-8e21-978d916f64da"); + } else { + cnd.and("t.taskName", "=", "9d94ac55-ef3d-4c28-9f77-1a8de099f1ad"); + } + + cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId())); + + if (pageForm.getAudit()) { + cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.WITHDRAW.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode())); + } else { + cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode()); + } + if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.desc("t.createdAt"); + cnd.desc("info.applyDateTime"); + } else { + cnd.orderBy("info." + pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } + sql.setCondition(cnd); + Pagination pagination = memberApplyRecordService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + + @At + @ApiOperation("分工会审核撤回") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("member.apply.branchUnionApproval") + @SLog(tag = "会员管理-入会申请-分工会撤回", msg = "分工会入会审核撤回") + public Result revoke(@Valid String taskId) { + bpmService.revokeTask(taskId); + return Result.success(); + } +} + + + + + diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyBranchUnionAuditController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyBranchUnionAuditController.java deleted file mode 100644 index 59fb9dfa..00000000 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyBranchUnionAuditController.java +++ /dev/null @@ -1,186 +0,0 @@ -package com.budwk.app.zhgh.staffmanage.member.controller.apply; - -import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.dev33.satoken.annotation.SaMode; -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.ObjectUtil; -import com.budwk.app.base.annotation.SLog; -import com.budwk.app.base.constant.BpmProcessConstant; -import com.budwk.app.base.constant.RoleConstant; -import com.budwk.app.base.page.Pagination; -import com.budwk.app.base.result.Result; -import com.budwk.app.bpm.enums.BpmProcessTaskStatusEnum; -import com.budwk.app.bpm.enums.BpmTaskApprovalTypeEnum; -import com.budwk.app.bpm.param.BpmTaskApprovalParam; -import com.budwk.app.bpm.service.BpmService; -import com.budwk.app.bpm.vo.BpmTaskApprovalRecordVo; -import com.budwk.app.sys.models.Sys_user_history; -import com.budwk.app.web.commons.auth.utils.AuthUtil; -import com.budwk.app.web.commons.auth.utils.SecurityUtil; -import com.budwk.app.web.controllers.open.commons.service.CommonService; -import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; -import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberApplyBranchAuditPageForm; -import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberApplyPageForm; -import com.budwk.app.zhgh.staffmanage.member.service.MemberApplyRecordService; -import com.budwk.app.zhgh.staffmanage.member.service.MemberManageService; -import com.budwk.app.zhgh.staffmanage.member.vo.MemberApplyVo; -import io.swagger.annotations.ApiOperation; -import org.nutz.aop.interceptor.ioc.TransAop; -import org.nutz.dao.Cnd; -import org.nutz.dao.Sqls; -import org.nutz.dao.sql.Sql; -import org.nutz.dao.util.cri.Static; -import org.nutz.ioc.aop.Aop; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.Lang; -import org.nutz.lang.util.NutMap; -import org.nutz.mvc.annotation.At; -import org.nutz.mvc.annotation.Ok; -import org.nutz.mvc.annotation.Param; - -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * 会员入会申请分工会审核 - */ -@IocBean -@At("/platform/member/apply/branchUnionAudit") -@Ok("json:full") -public class MemberApplyBranchUnionAuditController { - - @Inject - private MemberApplyRecordService memberApplyRecordService; - @Inject - private MemberManageService memberManageService; - @Inject - private BpmService bpmService; - @Inject - private CommonService commonService; - - @At("") - @Ok("beetl:/platform/zhgh/staffmanage/member/apply/branchunionaudit/index.html") - @SaCheckPermission("member.apply.branchUnionAudit") - public void index() { - } - - @At - @SaCheckPermission("member.apply.branchUnionAudit") - public Result pageData(MemberApplyPageForm pageForm) { - Sql sql = Sqls.create(""" - SELECT - record.id, - vu.id AS userId, - vu.username, - vu.loginname, - record.changeType, - record.changeTypes, - record.changeOrigin, - record.applyDateTime, - record.unitId, - IFNULL(record.unionId, vu.unionid) AS unionId, - vu.unionname AS unionName, - IFNULL(record.unitName, vu.unitname) AS unitName, - IFNULL(record.userState, vu.userState) AS userState, - IFNULL(record.preparedBy, vu.preparedBy) AS preparedBy, - IFNULL(record.personType, vu.personType) AS personType, - inst.id processInstanceId, - inst.processInstanceNodeId, - inst.processInstanceNodeName, - inst.processInstanceTaskIds, - inst.processInstanceStatus, - task.id processInstanceTaskId, - task.taskStatus processInstanceTaskStatus, - COUNT(nt.id) OVER (PARTITION BY task.id) > 0 AS nextTaskIsComplete - FROM - bpm_process_task task - INNER JOIN bpm_process_node_define nd ON nd.id = task.processTaskNodeId - INNER JOIN bpm_process_instance inst ON inst.id = task.processInstanceId - INNER JOIN bpm_process_define define On inst.processDefineId = define.id - INNER JOIN member_apply_record record ON record.id = inst.processInstanceBusinessId - LEFT JOIN bpm_process_task nt ON nt.prevTaskId = task.id AND nt.taskStatus = 'COMPLETE' - LEFT JOIN vw_user vu ON vu.id = record.userId - $condition - """); - Cnd cnd = Cnd.NEW(); - MemberApplyPageForm.buildSearch(cnd, pageForm); - if(!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())){ - cnd.and(new Static("JSON_CONTAINS( task.assignments, '\"%s\"' )".formatted(SecurityUtil.getUserLoginname()))); - } - cnd.and("nd.nodeCode","=",20); - if (pageForm.getAudit() != null) { - if (pageForm.getAudit()) { - cnd.and("task.taskStatus", "=", BpmProcessTaskStatusEnum.COMPLETE); - } else { - cnd.and("task.taskStatus", "=", BpmProcessTaskStatusEnum.ACTIVE); - } - } - cnd.and("define.`code`", "=", BpmProcessConstant.MEMBER_SINGLE_APPLY.name()); - cnd.desc("task.createdOn"); - cnd.groupBy("record.id"); - sql.setCondition(cnd); - Pagination listPageVO = memberApplyRecordService.listPageVO(pageForm, sql, MemberApplyVo.class); - return Result.success(listPageVO); - } - - - @At - @Aop(TransAop.READ_COMMITTED) - @ApiOperation("会员入会分工会审核") - @SaCheckPermission("member.apply.branchUnionAudit") - @SLog(tag = "会员管理-会员入会申请-分工会审核", msg = "会员入会审核(分工会)") - public Result approval(@Param("approval") @Valid BpmTaskApprovalParam approvalParam) { - approvalParam.getBpmTaskApprovalTypeEnum(); - Map variables = BeanUtil.beanToMap(approvalParam); - - List assignments = new ArrayList<>(); - if(approvalParam.getBpmTaskApprovalTypeEnum().equals(BpmTaskApprovalTypeEnum.PASS)){ - String approvalLoginName = commonService.findUserLoginNameByRoleCode(RoleConstant.SCHOOL_UNION_ADMIN); - assignments.add(approvalLoginName); - } - bpmService.completeTask(approvalParam.getProcessInstanceTaskId(), approvalParam.getBpmTaskApprovalTypeEnum(), variables, assignments); - return Result.success(); - } - - - @At - @ApiOperation("分工会审核撤回") - @Aop(TransAop.READ_COMMITTED) - @SaCheckPermission("member.apply.branchUnionAudit") - @SLog(tag = "会员管理-入会申请-分工会撤回", msg = "分工会入会审核撤回") - public Result revoke(@Valid String taskId) { - bpmService.revokeTask(taskId); - return Result.success(); - } - - - /** - * 获取变更信息,审核 - * @param recordId - * @return - */ - @At - @SaCheckPermission(value = {"member.apply.branchUnionAudit","member.apply.mine","member.apply.schoolUnionAudit"}, mode = SaMode.OR) - public Result findAuditChangeInfo(@Valid String recordId) { - Sys_user_history history = memberApplyRecordService.dao().fetch(Sys_user_history.class, Cnd.where("recordId", "=", recordId).or("id","=",recordId)); - MemberApplyRecord record = memberApplyRecordService.dao().fetch(MemberApplyRecord.class, recordId); - if (ObjectUtil.isAllEmpty(history, record)) { - return Result.error("获取变更信息失败"); - } - List nodeTasks = bpmService.getNodeTasks(BpmProcessConstant.MEMBER_SINGLE_APPLY, recordId); - if (Lang.isNotEmpty(history)) { - List nutMaps = memberManageService.compareMemberChangeInfo(history); - return Result.success(NutMap.NEW().addv("changeList", nutMaps).addv("nodeTasks", nodeTasks)); - } - List nutMaps = memberManageService.compareMemberChangeInfo(record); - return Result.success(NutMap.NEW().addv("changeList", nutMaps).addv("nodeTasks", nodeTasks)); - } -} - - - - - diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyController.java index 670d6a82..6f964df7 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyController.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyController.java @@ -2,22 +2,21 @@ package com.budwk.app.zhgh.staffmanage.member.controller.apply; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaMode; -import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.budwk.app.base.annotation.SLog; -import com.budwk.app.base.constant.BpmProcessConstant; import com.budwk.app.base.constant.RoleConstant; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.result.Result; -import com.budwk.app.bpm.service.BpmService; -import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.bpm.enums.BpmProcessInstanceStatusEnum; +import com.budwk.app.bpm.models.BpmProcessInstance; +import com.budwk.app.flow.engine.FlowEngine; import com.budwk.app.web.commons.auth.utils.AuthUtil; import com.budwk.app.sys.views.View_user; import com.budwk.app.web.commons.auth.utils.SecurityUtil; -import com.budwk.app.web.controllers.open.commons.service.CommonService; -import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin; -import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType; import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; +import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberApplyPageForm; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; import io.swagger.annotations.ApiOperation; import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.dao.Cnd; @@ -28,27 +27,26 @@ import org.nutz.dao.util.cri.Static; import org.nutz.ioc.aop.Aop; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; import javax.validation.Valid; -import java.util.List; -import java.util.stream.Stream; /** * 会员申请 */ @IocBean -@At("/platform/member/apply/submit") @Ok("json:full") +@At("/platform/member/apply/submit") public class MemberApplyController { @Inject private Dao dao; @Inject - private BpmService bpmservice; + private FlowEngine flowEngine; @Inject - private CommonService commonService; + private MemberCommonService memberCommonService; @At("") @Ok("beetl:/platform/zhgh/staffmanage/member/apply/submit/index.html") @@ -56,8 +54,77 @@ public class MemberApplyController { public void index() { } + @At + @Ok("beetl:/platform/zhgh/staffmanage/member/apply/submit/form.html") + @SaCheckPermission("member.apply.submit") + public void form() { + } @At + @ApiOperation("会员入会申请,我的申请列表") + @SaCheckPermission("member.apply.submit") + public Result pageData(MemberApplyPageForm pageForm) { + Sql sql = Sqls.create(""" + SELECT + info.id, + info.userName, + info.loginName, + info.unitName, + info.unionName, + info.userState, + info.preparedBy, + info.personType, + info.sign, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariale, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariable, + IF((SELECT taskName FROM wf_process_task tt WHERE tt.id = t.taskParentId) = 'startTask', 1, 0) canRevoke, + (select MAX(id) from wf_process_task where processInstanceId = ins.id and taskName = 'startTask') AS startTaskId + FROM + member_apply_record info + LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id + LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id AND t.taskState = 10 + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + $condition + """); + Cnd cnd = Cnd.NEW(); + MemberApplyPageForm.buildSearch(cnd, pageForm); + if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.desc("info.applyDateTime"); + } else { + cnd.orderBy("info." + pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } + sql.setCondition(cnd); + Pagination pagination = memberCommonService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + @At + @ApiOperation("删除入会申请") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("member.apply.submit") + @SLog(tag = "会员入会申请", msg = "删除入会申请id: ${args[0]}") + public Result onDelete(@Valid String id) { + dao.clear(MemberApplyRecord.class, Cnd.where("id", "=", id)); + // 流程相关操作 + flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(id); + return Result.success(); + } + + + @At + @ApiOperation("根据申请或修改,查询不同数据") @SaCheckPermission(value = {"member.apply.submit","member.branchUnion.record","member.schoolUnion.record"}, mode = SaMode.OR) public Result findOne(@Valid String id, @Valid Boolean isEdit) { if (isEdit) { @@ -69,53 +136,20 @@ public class MemberApplyController { } - @At - @Aop(TransAop.READ_COMMITTED) - @ApiOperation("保存入会申请") - @SaCheckPermission("member.apply.submit") - @SLog(tag = "会员管理-入会申请-保存申请", msg = "保存申请") - public Result doSave(MemberApplyRecord record){ - record.setMember(true); - record.setUserId(SecurityUtil.getUserId()); - record.setChangeOrigin(MemberChangeOrigin.PERSONAL.name()); - record.setChangeType(MemberChangeType.RESTORE.name()); - record.setChangeTypes(List.of(MemberChangeType.RESTORE.name())); - dao.insertOrUpdate(record); - bpmservice.startSaveProcessInstance(BpmProcessConstant.MEMBER_SINGLE_APPLY.name(), - "【会员入会申请】" + record.getUsername(), record.getId(), null); - return Result.success(); - } - - /** - * 提交申请 + * 查询申请记录 + * @param id + * @return */ @At - @Aop(TransAop.READ_COMMITTED) - @ApiOperation("提交入会申请") + @ApiOperation("根据id查询申请记录") @SaCheckPermission("member.apply.submit") - @SLog(tag = "会员管理-入会申请-提交申请", msg = "提交申请") - public Object doSubmit(MemberApplyRecord record) { - record.setMember(true); - record.setUserId(SecurityUtil.getUserId()); - record.setChangeType(MemberChangeType.RESTORE.name()); - record.setChangeTypes(List.of(MemberChangeType.RESTORE.name())); - dao.insertOrUpdate(record); - //设置分工会审核人 - List users = commonService.findUserInfoByRoleCode("unionId", SecurityUtil.getUnionId(), RoleConstant.BRANCH_UNION_CHAIRMAN.name()); - if (ObjectUtil.isEmpty(users)) { - return Result.error("您的分工会没有设置审核人,请联系校工会!"); - } - List operatorUsers = commonService.findUserInfoByRoleCode("unionId", SecurityUtil.getUnionId(), RoleConstant.BRANCH_UNION_OPERATOR.name()); - - List assignments = Stream.concat(users.stream(), operatorUsers.stream()).distinct().toList(); - - bpmservice.startSubmitProcessInstance(BpmProcessConstant.MEMBER_SINGLE_APPLY.name(), - "【会员入会申请】" + record.getUsername(), record.getId(), assignments.stream().map(Sys_user::getLoginname).toList(), null); - return Result.success(); + public Result findApplyById(String id) { + return Result.success(dao.fetch(MemberApplyRecord.class,id)); } + @At @SaCheckPermission("member.apply.submit") public Result getApplyUserByUnionOperate(@Valid String keyWord){ @@ -135,20 +169,32 @@ public class MemberApplyController { if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { sql.setVar("unionSql", new Static(" and u.unionId = %s".formatted(SecurityUtil.getUnionId()))); } - Pagination pagination = commonService.listPageMap(1, 20, sql); + Pagination pagination = memberCommonService.listPageMap(1, 20, sql); return Result.success(pagination.getList()); } - + /** + * 校验当前申请人是否有未走完的流程,只有等流程走完才能再次申请 + * @return + */ @At @SaCheckPermission("member.apply.submit") - public Result findApplyById(String id) { - return Result.success(dao.fetch(MemberApplyRecord.class,id)); + @ApiOperation("校验当前申请人是否有未走完的流程") + public Result validateApply(){ + int count = dao.count(BpmProcessInstance.class, Cnd.where("processInstanceInitiatorId", "=", SecurityUtil.getUserId()) + .and("processInstanceStatus", "=", BpmProcessInstanceStatusEnum.RUNNING.name())); + return Result.success().addData(count); } + + /** + * 获取当前登录用户信息,是用来判断当前用户是否是会员 + * @return + */ @At + @ApiOperation("获取当前登录用户信息") @SaCheckPermission("member.apply.submit") - public Result findUserInfo() { + public Result getSelfUserInfo() { return Result.success(dao.fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId()))); } diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyMineController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyMineController.java deleted file mode 100644 index 2744fcc9..00000000 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyMineController.java +++ /dev/null @@ -1,180 +0,0 @@ -package com.budwk.app.zhgh.staffmanage.member.controller.apply; - -import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.dev33.satoken.annotation.SaMode; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import com.budwk.app.base.annotation.SLog; -import com.budwk.app.base.constant.BpmProcessConstant; -import com.budwk.app.base.constant.RoleConstant; -import com.budwk.app.base.page.Pagination; -import com.budwk.app.base.param.PageForm; -import com.budwk.app.base.result.Result; -import com.budwk.app.bpm.service.BpmService; -import com.budwk.app.bpm.vo.BpmTaskApprovalRecordVo; -import com.budwk.app.sys.models.Sys_user_history; -import com.budwk.app.web.commons.auth.utils.AuthUtil; -import com.budwk.app.web.commons.auth.utils.SecurityUtil; -import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; -import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberApplyPageForm; -import com.budwk.app.zhgh.staffmanage.member.service.MemberApplyRecordService; -import com.budwk.app.zhgh.staffmanage.member.service.MemberManageService; -import com.budwk.app.zhgh.staffmanage.member.vo.MemberApplyVo; -import io.swagger.annotations.ApiOperation; -import org.nutz.aop.interceptor.ioc.TransAop; -import org.nutz.dao.Cnd; -import org.nutz.dao.Sqls; -import org.nutz.dao.sql.Sql; -import org.nutz.ioc.aop.Aop; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.Lang; -import org.nutz.lang.util.NutMap; -import org.nutz.mvc.annotation.At; -import org.nutz.mvc.annotation.Ok; - -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.List; - -/** - * 我的申请 - */ -@IocBean -@At("/platform/member/apply/mine") -@Ok("json:full") -public class MemberApplyMineController { - - @Inject - private MemberApplyRecordService memberApplyRecordService; - @Inject - private BpmService bpmService; - @Inject - private MemberManageService memberManageService; - - @At("") - @Ok("beetl:/platform/zhgh/staffmanage/member/apply/mine/index.html") - @SaCheckPermission("member.apply.mine") - public void index() { - } - - - @At - @SaCheckPermission("member.apply.mine") - public Result pageData(MemberApplyPageForm pageForm) { - Sql sql = Sqls.create(""" - SELECT - record.id, - vu.id AS userId, - vu.username, - vu.loginname, - record.changeType, - record.changeTypes, - record.changeOrigin, - record.applyDateTime, - record.unitId, - IFNULL(record.unionId, vu.unionid) AS unionId, - vu.unionname AS unionName, - IFNULL(record.unitName, vu.unitname) AS unitName, - IFNULL(record.userState, vu.userState) AS userState, - IFNULL(record.preparedBy, vu.preparedBy) AS preparedBy, - IFNULL(record.personType, vu.personType) AS personType, - inst.id processInstanceId, - inst.processInstanceNodeId, - inst.processInstanceNodeCode, - inst.processInstanceNodeName, - inst.processInstanceTaskIds, - inst.processInstanceStatus, - task.id processInstanceTaskId, - task.taskStatus processInstanceTaskStatus, - ( - SELECT - count( 1 ) > 0 - FROM - bpm_process_task - WHERE - prevTaskId = ( SELECT id FROM bpm_process_task WHERE processInstanceId = inst.id AND processTaskNodeCode IN ( 10, 40, 70 ) ORDER BY createdAt DESC LIMIT 1 ) - AND taskStatus = 'COMPELTE' - ) AS nextTaskIsComplete - FROM - bpm_process_task task - INNER JOIN bpm_process_node_define nd ON nd.id = task.processTaskNodeId - INNER JOIN bpm_process_instance inst ON inst.id = task.processInstanceId - INNER JOIN bpm_process_define define On inst.processDefineId = define.id - INNER JOIN member_apply_record record ON record.id = inst.processInstanceBusinessId - LEFT JOIN bpm_process_task nt ON nt.prevTaskId = task.id AND nt.taskStatus = 'COMPLETE' - LEFT JOIN vw_user vu ON vu.id = record.userId - $condition - """); - Cnd cnd = Cnd.NEW(); - MemberApplyPageForm.buildSearch(cnd, pageForm); - cnd.and("nd.nodeCode", "=", 10); - cnd.and("define.`code`", "=", BpmProcessConstant.MEMBER_SINGLE_APPLY.name()); - if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { - if (AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())) { - cnd.andEX("vu.unionId","=", SecurityUtil.getUnionId()); - } else { - cnd.and("vu.id", "=", SecurityUtil.getUserId()); - } - } - cnd.desc("record.applyDateTime"); - sql.setCondition(cnd); - Pagination listPageVO = memberApplyRecordService.listPageVO(pageForm, sql, MemberApplyVo.class); - return Result.success(listPageVO); - } - - @At - @ApiOperation("删除会员申请记录") - @Aop(TransAop.READ_COMMITTED) - @SaCheckPermission("member.apply.mine") - @SLog(tag = "会员管理-入会申请-我的申请记录", msg = "删除申请") - public Result delete(@Valid String id) { - memberApplyRecordService.delete(id); - bpmService.deleteInstance(id); - return Result.success(); - } - - - @At - @ApiOperation("个人申请撤回") - @Aop(TransAop.READ_COMMITTED) - @SaCheckPermission("member.apply.mine") - @SLog(tag = "会员管理-入会申请-个人申请撤回", msg = "个人申请撤回") - public Result revokeApply(@Valid String id) { - bpmService.revokeApply(id); - return Result.success(); - } - - - /** - * 获取变更信息,审核 - * @param recordId - * @return - */ - @At - @SaCheckPermission("member.apply.mine") - public Result findAuditChangeInfo(@Valid String recordId) { - MemberApplyRecord record = new MemberApplyRecord(); - Cnd cnd = Cnd.NEW(); - cnd.and(Cnd.exps("recordId", "=", recordId).or("id","=",recordId)); - if (!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())) { - cnd.and("loginname", "=", SecurityUtil.getUserLoginname()); - record = memberApplyRecordService.dao().fetch(MemberApplyRecord.class, Cnd.where("loginname", "=", SecurityUtil.getUserLoginname()) - .and("id", "=", recordId)); - } else { - record = memberApplyRecordService.dao().fetch(MemberApplyRecord.class, recordId); - } - Sys_user_history history = memberApplyRecordService.dao().fetch(Sys_user_history.class, cnd); - - if (ObjectUtil.isAllEmpty(history, record)) { - return Result.error("您暂无权限查询"); - } - List nodeTasks = bpmService.getNodeTasks(BpmProcessConstant.MEMBER_SINGLE_APPLY, recordId); - if (Lang.isNotEmpty(history)) { - List nutMaps = memberManageService.compareMemberChangeInfo(history); - return Result.success(NutMap.NEW().addv("changeList", nutMaps).addv("nodeTasks", nodeTasks)); - } - List nutMaps = memberManageService.compareMemberChangeInfo(record); - return Result.success(NutMap.NEW().addv("changeList", nutMaps).addv("nodeTasks", nodeTasks)); - } -} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplySchoolUnionApprovalController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplySchoolUnionApprovalController.java new file mode 100644 index 00000000..48445e77 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplySchoolUnionApprovalController.java @@ -0,0 +1,174 @@ +package com.budwk.app.zhgh.staffmanage.member.controller.apply; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.bpm.enums.BpmTaskApprovalTypeEnum; +import com.budwk.app.bpm.param.BpmTaskApprovalParam; +import com.budwk.app.bpm.service.BpmService; +import com.budwk.app.flow.enums.ProcessTaskStateEnum; +import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.web.commons.base.Globals; +import com.budwk.app.web.controllers.open.commons.service.CommonService; +import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; +import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberApplyPageForm; +import com.budwk.app.zhgh.staffmanage.member.service.MemberApplyRecordService; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; +import com.budwk.app.zhgh.staffmanage.member.vo.MemberCommonVo; +import io.swagger.annotations.ApiOperation; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.validation.Valid; +import java.util.List; +import java.util.Map; + +/** + * 会员入会申请校工会审核 + * @author fky + */ +@IocBean +@Ok("json:full") +@At("/platform/member/apply/schoolUnionApproval") +public class MemberApplySchoolUnionApprovalController { + + @Inject + private Dao dao; + @Inject + private BpmService bpmService; + @Inject + private CommonService commonService; + @Inject + private MemberCommonService memberCommonService; + @Inject + private MemberApplyRecordService memberApplyRecordService; + + @At("") + @Ok("beetl:/platform/zhgh/staffmanage/member/apply/schoolunionapproval/index.html") + @SaCheckPermission("member.apply.schoolUnionApproval") + public void index() { + } + + @At + @Ok("beetl:/platform/zhgh/staffmanage/member/apply/schoolunionapproval/form.html") + @SaCheckPermission("member.apply.schoolUnionApproval") + public void form() { + } + + + @At + @ApiOperation("会员入会校工会审核列表") + @SaCheckPermission("member.apply.schoolUnionApproval") + public Result pageData(MemberApplyPageForm pageForm) { + Sql sql = Sqls.create(""" + SELECT + info.id, + info.userName, + info.loginName, + info.unitName, + info.unionName, + info.userState, + info.preparedBy, + info.personType, + info.sign, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariale, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariable, + IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName, + IF(rt.id IS NOT NULL, 1, 0) AS canRevoke + FROM + wf_process_task t + LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId + LEFT JOIN member_apply_record info ON info.id = ins.businessNo + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10 + LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10 + $condition + """); + Cnd cnd = Cnd.NEW(); + MemberApplyPageForm.buildSearch(cnd, pageForm); + if ("HMC".equals(Globals.SchoolCode)) { + cnd.and("t.taskName", "=", "5cdf34fe-4ba8-4e79-9832-ac5565a90d1a"); + } else { + cnd.and("t.taskName", "=", "00b620c5-5c64-48bd-9394-3621c1d91af8"); + } + cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId())); + + if (pageForm.getAudit()) { + cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.WITHDRAW.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode())); + } else { + cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode()); + } + if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.desc("t.createdAt"); + cnd.desc("info.applyDateTime"); + } else { + cnd.orderBy("info." + pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } + sql.setCondition(cnd); + Pagination pagination = memberApplyRecordService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + + @At + @Aop(TransAop.READ_COMMITTED) + @ApiOperation("会员入会校工会审核") + @SaCheckPermission("member.apply.schoolUnionApproval") + @SLog(tag = "会员管理-会员入会申请-校工会审核", msg = "会员入会审核(校工会)") + public Result approval(@Param("approval") @Valid BpmTaskApprovalParam approvalParam) { + Map variables = BeanUtil.beanToMap(approvalParam); + + if (approvalParam.getBpmTaskApprovalTypeEnum().equals(BpmTaskApprovalTypeEnum.PASS)) { + // 审核通过了,要去改基础数据 + MemberApplyRecord record = memberCommonService.dao().fetch(MemberApplyRecord.class, Cnd.where("id", "=", approvalParam.getProcessInstanceBusinessId())); + Sys_user sysUser = new Sys_user(); + BeanUtil.copyProperties(record, sysUser); + sysUser.setId(record.getUserId()); + dao.updateIgnoreNull(sysUser); + } + bpmService.completeTask(approvalParam.getProcessInstanceTaskId(), approvalParam.getBpmTaskApprovalTypeEnum(), variables, null); + return Result.success(); + } + + + @At + @ApiOperation("校工会审核撤回") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("member.apply.schoolUnionApproval") + @SLog(tag = "会员管理-入会申请-校工会撤回", msg = "校工会入会审核撤回") + public Result revoke(@Valid String taskId) { + bpmService.revokeTask(taskId); + return Result.success(); + } +} + + + + + diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplySchoolUnionAuditController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplySchoolUnionAuditController.java deleted file mode 100644 index 0b32cdfc..00000000 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplySchoolUnionAuditController.java +++ /dev/null @@ -1,181 +0,0 @@ -package com.budwk.app.zhgh.staffmanage.member.controller.apply; - -import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.ObjectUtil; -import com.budwk.app.base.annotation.SLog; -import com.budwk.app.base.constant.BpmProcessConstant; -import com.budwk.app.base.constant.RoleConstant; -import com.budwk.app.base.page.Pagination; -import com.budwk.app.base.result.Result; -import com.budwk.app.bpm.enums.BpmProcessTaskStatusEnum; -import com.budwk.app.bpm.enums.BpmTaskApprovalTypeEnum; -import com.budwk.app.bpm.param.BpmTaskApprovalParam; -import com.budwk.app.bpm.service.BpmService; -import com.budwk.app.bpm.vo.BpmTaskApprovalRecordVo; -import com.budwk.app.sys.models.Sys_user_history; -import com.budwk.app.web.commons.auth.utils.AuthUtil; -import com.budwk.app.web.commons.auth.utils.SecurityUtil; -import com.budwk.app.web.controllers.open.commons.service.CommonService; -import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; -import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberApplyPageForm; -import com.budwk.app.zhgh.staffmanage.member.service.MemberApplyRecordService; -import com.budwk.app.zhgh.staffmanage.member.service.MemberManageService; -import com.budwk.app.zhgh.staffmanage.member.vo.MemberApplyVo; -import io.swagger.annotations.ApiOperation; -import org.nutz.aop.interceptor.ioc.TransAop; -import org.nutz.dao.Cnd; -import org.nutz.dao.Sqls; -import org.nutz.dao.sql.Sql; -import org.nutz.dao.util.cri.Static; -import org.nutz.ioc.aop.Aop; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.Lang; -import org.nutz.lang.util.NutMap; -import org.nutz.mvc.annotation.At; -import org.nutz.mvc.annotation.Ok; -import org.nutz.mvc.annotation.Param; - -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * 会员入会申请校工会审核 - */ -@IocBean -@At("/platform/member/apply/schoolUnionAudit") -@Ok("json:full") -public class MemberApplySchoolUnionAuditController { - - @Inject - private MemberApplyRecordService memberApplyRecordService; - @Inject - private CommonService commonService; - @Inject - private BpmService bpmService; - @Inject - private MemberManageService memberManageService; - - @At("") - @Ok("beetl:/platform/zhgh/staffmanage/member/apply/schoolunionaudit/index.html") - @SaCheckPermission("member.apply.schoolUnionAudit") - public void index() { - } - - @At - @SaCheckPermission("member.apply.schoolUnionAudit") - public Result pageData(MemberApplyPageForm pageForm) { - Sql sql = Sqls.create(""" - SELECT - record.id, - vu.id AS userId, - vu.username, - vu.loginname, - record.changeType, - record.changeTypes, - record.changeOrigin, - record.applyDateTime, - record.unitId, - IFNULL(record.unionId, vu.unionid) AS unionId, - vu.unionname AS unionName, - IFNULL(record.unitName, vu.unitname) AS unitName, - IFNULL(record.userState, vu.userState) AS userState, - IFNULL(record.preparedBy, vu.preparedBy) AS preparedBy, - IFNULL(record.personType, vu.personType) AS personType, - inst.id processInstanceId, - inst.processInstanceNodeId, - inst.processInstanceNodeName, - inst.processInstanceTaskIds, - inst.processInstanceStatus, - task.id processInstanceTaskId, - task.taskStatus processInstanceTaskStatus, - COUNT(nt.id) OVER (PARTITION BY task.id) > 0 AS nextTaskIsComplete - FROM - bpm_process_task task - INNER JOIN bpm_process_node_define nd ON nd.id = task.processTaskNodeId - INNER JOIN bpm_process_instance inst ON inst.id = task.processInstanceId - INNER JOIN bpm_process_define define On inst.processDefineId = define.id - INNER JOIN member_apply_record record ON record.id = inst.processInstanceBusinessId - LEFT JOIN bpm_process_task nt ON nt.prevTaskId = task.id AND nt.taskStatus = 'COMPLETE' - LEFT JOIN vw_user vu ON vu.id = record.userId - $condition - """); - Cnd cnd = Cnd.NEW(); - MemberApplyPageForm.buildSearch(cnd, pageForm); - if(!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())){ - cnd.and(new Static("JSON_CONTAINS( task.assignments, '\"%s\"' )".formatted(SecurityUtil.getUserLoginname()))); - } - cnd.and("nd.nodeCode","=",50); - if (pageForm.getAudit() != null) { - if (pageForm.getAudit()) { - cnd.and("task.taskStatus", "=", BpmProcessTaskStatusEnum.COMPLETE); - } else { - cnd.and("task.taskStatus", "=", BpmProcessTaskStatusEnum.ACTIVE); - } - } - cnd.and("define.`code`", "=", BpmProcessConstant.MEMBER_SINGLE_APPLY.name()); - cnd.desc("task.createdOn"); -// cnd.groupBy("record.id"); - sql.setCondition(cnd); - Pagination listPageVO = memberApplyRecordService.listPageVO(pageForm, sql, MemberApplyVo.class); - return Result.success(listPageVO); - } - - - @At - @Aop(TransAop.READ_COMMITTED) - @ApiOperation("会员入会校工会审核") - @SaCheckPermission("member.apply.branchUnionAudit") - @SLog(tag = "会员管理-会员入会申请-校工会审核", msg = "会员入会审核(校工会)") - public Result approval(@Param("approval") @Valid BpmTaskApprovalParam approvalParam) { - Map variables = BeanUtil.beanToMap(approvalParam); - if (approvalParam.getBpmTaskApprovalTypeEnum().equals(BpmTaskApprovalTypeEnum.PASS)) { - MemberApplyRecord record = memberManageService.dao().fetch(MemberApplyRecord.class, Cnd.where("id", "=", approvalParam.getProcessInstanceBusinessId())); - memberManageService.compareMemberChangeInfoAndUpdateUser(record); - } - bpmService.completeTask(approvalParam.getProcessInstanceTaskId(), approvalParam.getBpmTaskApprovalTypeEnum(), variables, null); - return Result.success(); - } - - - @At - @ApiOperation("校工会审核撤回") - @Aop(TransAop.READ_COMMITTED) - @SaCheckPermission("member.apply.branchUnionAudit") - @SLog(tag = "会员管理-入会申请-校工会撤回", msg = "校工会入会审核撤回") - public Result revoke(@Valid String taskId) { - bpmService.revokeTask(taskId); - return Result.success(); - } - - - /** - * 获取变更信息,审核 - * @param recordId - * @return - */ - @At - @SaCheckPermission(value = "member.apply.branchUnionAudit") - public Result findAuditChangeInfo(@Valid String recordId){ - Sys_user_history history = memberApplyRecordService.dao().fetch(Sys_user_history.class, Cnd.where("recordId", "=", recordId).or("id","=",recordId)); - MemberApplyRecord record = memberApplyRecordService.dao().fetch(MemberApplyRecord.class, recordId); - if (ObjectUtil.isAllEmpty(history, record)) { - return Result.error("获取变更信息失败"); - } - List nodeTasks = bpmService.getNodeTasks(BpmProcessConstant.MEMBER_SINGLE_APPLY, recordId); - if (Lang.isNotEmpty(history)) { - List nutMaps = memberManageService.compareMemberChangeInfo(history); - return Result.success(NutMap.NEW().addv("changeList", nutMaps).addv("nodeTasks", nodeTasks)); - } - List nutMaps = memberManageService.compareMemberChangeInfo(record); - return Result.success(NutMap.NEW().addv("changeList", nutMaps).addv("nodeTasks", nodeTasks)); - } -} - - - - - diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyViewController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyViewController.java new file mode 100644 index 00000000..a3dcff87 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/apply/MemberApplyViewController.java @@ -0,0 +1,72 @@ +package com.budwk.app.zhgh.staffmanage.member.controller.apply; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.BpmProcessConstant; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.bpm.service.BpmService; +import com.budwk.app.bpm.vo.BpmTaskApprovalRecordVo; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; +import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberApplyPageForm; +import com.budwk.app.zhgh.staffmanage.member.service.MemberApplyRecordService; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; +import com.budwk.app.zhgh.staffmanage.member.vo.MemberCommonVo; +import io.swagger.annotations.ApiOperation; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import javax.validation.Valid; +import java.util.List; + +/** + * 我的申请 + * @author fky + */ +@IocBean +@Ok("json:full") +@ApiOperation("会员入会申请,查看") +@At("/platform/member/apply/view") +public class MemberApplyViewController { + + @Inject + private Dao dao; + @Inject + private BpmService bpmService; + @Inject + private MemberCommonService memberCommonService; + @Inject + private MemberApplyRecordService memberApplyRecordService; + + @At("") + @Ok("beetl:/platform/zhgh/staffmanage/member/apply/view/index.html") + @SaCheckPermission("member.apply.submit") + public void index() { + } + + /** + * 获取申请信息 + * @param id + * @return + */ + @At + @ApiOperation("获取申请信息") + @SaCheckPermission(value = {"member.apply.submit", "member.apply.branchUnionApproval", "member.apply.branchUnionApproval"}, mode = SaMode.OR) + public Result findMemberApplyRecord(@Valid String id) { + MemberApplyRecord record = dao.fetch(MemberApplyRecord.class, id); + return Result.success().addData(record); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/branch/MemberBranchUnionAuditController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/branch/MemberBranchUnionAuditController.java deleted file mode 100644 index b84b219b..00000000 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/branch/MemberBranchUnionAuditController.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.budwk.app.zhgh.staffmanage.member.controller.branch; - -import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.dev33.satoken.annotation.SaMode; -import cn.hutool.core.util.ObjectUtil; -import com.budwk.app.base.annotation.SLog; -import com.budwk.app.base.constant.BpmProcessConstant; -import com.budwk.app.base.page.Pagination; -import com.budwk.app.base.result.Result; -import com.budwk.app.bpm.param.BpmTaskApprovalParam; -import com.budwk.app.bpm.service.BpmService; -import com.budwk.app.bpm.vo.BpmTaskApprovalRecordVo; -import com.budwk.app.sys.models.Sys_user_history; -import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; -import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberManagePageForm; -import com.budwk.app.zhgh.staffmanage.member.service.MemberBranchUnionManageService; -import com.budwk.app.zhgh.staffmanage.member.service.MemberManageService; -import io.swagger.annotations.ApiOperation; -import lombok.extern.slf4j.Slf4j; -import org.nutz.aop.interceptor.ioc.TransAop; -import org.nutz.dao.Cnd; -import org.nutz.ioc.aop.Aop; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.Lang; -import org.nutz.lang.util.NutMap; -import org.nutz.mvc.annotation.At; -import org.nutz.mvc.annotation.Ok; -import org.nutz.mvc.annotation.Param; - -import javax.validation.Valid; -import java.util.List; - -/** - * @version 1.0 - * @Author zzr - * @name:MemberBranchUnionAuditController - * @Date 2024/8/13 8:48 - * @注释 分工会管理,分工会审核 - */ -@Slf4j -@IocBean -@Ok("json") -@At("/platform/member/branchUnion/audit") -public class MemberBranchUnionAuditController { - - @Inject - private MemberBranchUnionManageService memberBranchUnionManageService; - @Inject - private MemberManageService memberManageService; - @Inject - private BpmService bpmService; - - - @At("") - @Ok("beetl:/platform/zhgh/staffmanage/member/branch/audit/index.html") - @SaCheckPermission("member.branchUnion.audit") - public void index() { - } - - - @At - @SaCheckPermission("member.branchUnion.audit") - public Result pageData(MemberManagePageForm pageForm) { - Pagination pageData = memberBranchUnionManageService.getPageData(pageForm); - return Result.success(pageData); - } - - - @At - @ApiOperation("分工会审核") - @Aop(TransAop.READ_COMMITTED) - @SaCheckPermission("member.branchUnion.audit") - @SLog(tag = "会员管理-分工会管理", type = "memberBranchUnionManage", msg = "分工会审核") - public Result approval(@Param("approval") @Valid BpmTaskApprovalParam approvalParam) { - bpmService.completeTask(approvalParam.getProcessInstanceTaskId(), approvalParam.getBpmTaskApprovalTypeEnum(), null, null); - return Result.success(); - } - - - @At - @ApiOperation("分工会审核撤回") - @Aop(TransAop.READ_COMMITTED) - @SaCheckPermission("member.branchUnion.audit") - @SLog(tag = "会员管理-分工会管理", type = "memberBranchUnionManage", msg = "分工会审核撤回") - public Result revoke(@Valid String taskId) { - bpmService.revokeTask(taskId); - return Result.success(); - } - - - /** - * 获取变更信息,审核 - * @param recordId - * @return - */ - @At - @SaCheckPermission(value = {"member.branchUnion.audit", "member.schoolUnion.audit"}, mode = SaMode.OR) - public Result findAuditChangeInfo(String recordId) { - Sys_user_history history = memberBranchUnionManageService.dao().fetch(Sys_user_history.class, Cnd.where("recordId", "=", recordId).or("id","=",recordId)); - MemberApplyRecord record = memberBranchUnionManageService.dao().fetch(MemberApplyRecord.class, recordId); - if (ObjectUtil.isAllEmpty(history, record)) { - return Result.error("获取变更信息失败"); - } - List nodeTasks = bpmService.getNodeTasks(BpmProcessConstant.MEMBER_BRANCH_UNION_CHANGE, recordId); - if (Lang.isNotEmpty(history)) { - List nutMaps = memberManageService.compareMemberChangeInfo(history); - return Result.success(NutMap.NEW().addv("changeList", nutMaps).addv("nodeTasks", nodeTasks)); - } - List nutMaps = memberManageService.compareMemberChangeInfo(record); - return Result.success(NutMap.NEW().addv("changeList", nutMaps).addv("nodeTasks", nodeTasks)); - } -} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/branch/MemberBranchUnionManageController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/branch/MemberBranchUnionManageController.java deleted file mode 100644 index f0557db2..00000000 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/branch/MemberBranchUnionManageController.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.budwk.app.zhgh.staffmanage.member.controller.branch; - -import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.hutool.core.util.StrUtil; -import com.budwk.app.base.annotation.RepeatSubmit; -import com.budwk.app.base.annotation.SLog; -import com.budwk.app.base.constant.BpmProcessConstant; -import com.budwk.app.base.constant.RoleConstant; -import com.budwk.app.base.exception.BaseException; -import com.budwk.app.base.page.Pagination; -import com.budwk.app.base.result.Result; -import com.budwk.app.bpm.service.BpmService; -import com.budwk.app.sys.models.Sys_user; -import com.budwk.app.web.controllers.open.commons.service.CommonService; -import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin; -import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; -import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberManagePageForm; -import com.budwk.app.zhgh.staffmanage.member.service.MemberManageService; -import lombok.extern.slf4j.Slf4j; -import org.nutz.aop.interceptor.ioc.TransAop; -import org.nutz.dao.Cnd; -import org.nutz.dao.sql.Sql; -import org.nutz.ioc.aop.Aop; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.util.NutMap; -import org.nutz.mvc.annotation.At; -import org.nutz.mvc.annotation.Ok; -import org.nutz.mvc.annotation.Param; - -import javax.validation.Valid; -import java.util.List; -import java.util.Objects; - -/** - * @version 1.0 - * @Author zzr - * @name:MemberBranchUnionManageListController - * @Date 2024/8/12 14:06 - * @注释 会员分工会管理 - */ -@IocBean -@At("/platform/member/branchUnion/manage/list") -@Slf4j -@Ok("json") -public class MemberBranchUnionManageController { - - @Inject - private MemberManageService memberManageService; - @Inject - private CommonService commonService; - @Inject - private BpmService bpmservice; - - - @At("") - @Ok("beetl:/platform/zhgh/staffmanage/member/branch/manage/index.html") - @SaCheckPermission("member.branchUnion.manage.list") - public void index() { - } - - - @At - @SaCheckPermission("member.branchUnion.manage.list") - @Ok("json:{dateFormat:'yyyy-MM-dd'}") - public Result pageData(MemberManagePageForm pageForm) { - Sql sql = memberManageService.getSql(pageForm, "branchUnion"); - Pagination pagination = memberManageService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); - return Result.success(pagination); - } - - - @At - @SaCheckPermission("member.branchUnion.manage.list") - @SLog(tag = "添加会员", type = "memberBranchManage", msg = "添加会员") - public Result addMember(@Valid MemberApplyRecord record) { - return null; - } - - - @At - @SaCheckPermission("member.branchUnion.manage.list") - public Result getChangeInfoByUserId(String userId) { - return Result.success(memberManageService.getMemberChangeInfoByUserId(userId)); - } - - - @At - @SaCheckPermission("member.branchUnion.manage.list") - @Aop(TransAop.READ_COMMITTED) - @RepeatSubmit - @SLog(tag = "分工会管理-会员管理", type = "MemberBranchManageList", msg = "分工会普通变更") - public Result generalMemberChange(@Param("record") MemberApplyRecord record) { - try { - if (Objects.isNull(record)) { - return Result.error("数据获取失败"); - } - Sys_user user = memberManageService.dao().fetch(Sys_user.class, Cnd.where("loginname", "=", record.getLoginname())); - record.setUserId(user.getId()); - if ( record.getEdit() == null || !record.getEdit()) { - // 校验是否有变更的字段 - List changeInfoList = memberManageService.compareMemberChangeInfo(record); - // 存储变更的类型 - List changeTypeList = memberManageService.compareMemberChangeType(changeInfoList, record); - // 有字段发生变更会走下面的方法,没有则会抛异常 - record.setChangeTypes(changeTypeList); - record.setChangeOrigin(MemberChangeOrigin.BRANCH_UNION.name()); - memberManageService.dao().insert(record); - } else { - record.setChangeOrigin(MemberChangeOrigin.BRANCH_UNION.name()); - memberManageService.dao().updateIgnoreNull(record); - } - - String approvalLoginName = commonService.findUserLoginNameByRoleCode(RoleConstant.SCHOOL_UNION_MEMBER_ADMIN); - if (StrUtil.isBlank(approvalLoginName)) { - throw new BaseException("校工会会员管理员未设置"); - } - bpmservice.startSubmitProcessInstance(BpmProcessConstant.MEMBER_BRANCH_UNION_CHANGE.name(), "【会员分工会变更】" +record.getUsername(), record.getId(), List.of(approvalLoginName), null); - return Result.success(); - } catch (Exception e) { - return Result.error(e.getMessage()); - } - } -} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/branch/MemberBranchUnionRecordController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/branch/MemberBranchUnionRecordController.java deleted file mode 100644 index 456216cf..00000000 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/branch/MemberBranchUnionRecordController.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.budwk.app.zhgh.staffmanage.member.controller.branch; - -import cn.dev33.satoken.annotation.SaCheckPermission; -import com.budwk.app.base.page.Pagination; -import com.budwk.app.base.result.Result; -import com.budwk.app.sys.models.Sys_user_history; -import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberManagePageForm; -import com.budwk.app.zhgh.staffmanage.member.service.MemberManageService; -import lombok.extern.slf4j.Slf4j; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.util.NutMap; -import org.nutz.mvc.annotation.At; -import org.nutz.mvc.annotation.Ok; - -import javax.validation.Valid; -import java.util.List; - -/** - * @version 1.0 - * @Author zzr - * @name:MemberBranchRecordController - * @Date 2024/8/13 16:25 - * @注释 分工会 会员变更记录 - */ -@Slf4j -@IocBean -@Ok("json") -@At("/platform/member/branchUnion/record") -public class MemberBranchUnionRecordController { - - @Inject - private MemberManageService memberManageService; - - - @At("") - @Ok("beetl:/platform/zhgh/staffmanage/member/branch/record/index.html") - @SaCheckPermission("member.branchUnion.record") - public void index() { - } - - - @At - @SaCheckPermission("member.branchUnion.record") - public Result pageData(MemberManagePageForm pageForm){ - Pagination pagination = memberManageService.memberHistoryRecords(pageForm); - return Result.success(pagination); - } - - - @At - @SaCheckPermission("member.branchUnion.record") - public Result findAuditChangeInfo(@Valid String recordId) { - Sys_user_history history = memberManageService.dao().fetch(Sys_user_history.class, recordId); - List list = memberManageService.compareMemberChangeInfo(history); - return Result.success(list); - } -} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberBranchUnionAuditController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberBranchUnionAuditController.java new file mode 100644 index 00000000..09ec5c84 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberBranchUnionAuditController.java @@ -0,0 +1,160 @@ +package com.budwk.app.zhgh.staffmanage.member.controller.change; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.BpmProcessConstant; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.bpm.enums.BpmTaskApprovalTypeEnum; +import com.budwk.app.bpm.models.BpmProcessInstance; +import com.budwk.app.bpm.models.BpmProcessTask; +import com.budwk.app.bpm.param.BpmTaskApprovalParam; +import com.budwk.app.bpm.service.BpmService; +import com.budwk.app.bpm.vo.BpmTaskApprovalRecordVo; +import com.budwk.app.flow.enums.ProcessTaskStateEnum; +import com.budwk.app.sys.models.Sys_user_history; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.web.controllers.open.commons.service.CommonService; +import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; +import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberChangePageForm; +import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberManagePageForm; +import com.budwk.app.zhgh.staffmanage.member.service.MemberBranchUnionManageService; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @version 1.0 + * @Author zzr + * @name:MemberBranchUnionAuditController + * @Date 2024/8/13 8:48 + * @注释 分工会管理,分工会审核 + */ +@Slf4j +@IocBean +@Ok("json") +@At("/platform/member/change/branchUnion/audit") +public class MemberBranchUnionAuditController { + + @Inject + private Dao dao; + @Inject + private BpmService bpmService; + @Inject + private CommonService commonService; + @Inject + private MemberCommonService memberCommonService; + @Inject + private MemberBranchUnionManageService memberBranchUnionManageService; + + + @At("") + @Ok("beetl:/platform/zhgh/staffmanage/member/change/branchUnionAudit/index.html") + @SaCheckPermission("member.change.branchUnion.audit") + public void index() { + } + + @At + @Ok("beetl:/platform/zhgh/staffmanage/member/change/branchUnionAudit/form.html") + @SaCheckPermission("member.change.branchUnion.audit") + public void form() { + } + + + @At + @ApiModelProperty("会员变更申请,分工会审核列表") + @SaCheckPermission("member.change.branchUnion.audit") + public Result pageData(MemberChangePageForm pageForm) { + Sql sql = Sqls.create(""" + SELECT + info.id, + info.sex, + info.userName, + info.loginName, + info.unitName, + info.unionName, + info.userState, + info.preparedBy, + info.personType, + info.changeTypes, + info.applyDateTime, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariale, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariale + FROM + wf_process_task t + LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId + LEFT JOIN member_change_record info ON info.id = ins.businessNo + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + $condition + """); + Cnd cnd = Cnd.NEW(); + pageForm.buildSearch(cnd, "info."); + + cnd.and("t.taskName", "=", "8ca3bcf0-7b86-4ef2-b19f-b76a1707e2da"); + cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId())); + + if (pageForm.getAudit()) { + cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.WITHDRAW.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode())); + } else { + cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode()); + } + + if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.desc("info.applyDateTime"); + } else { + cnd.orderBy("info." + pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } + sql.setCondition(cnd); + Pagination pagination = memberCommonService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + + @At + @ApiOperation("分工会审核撤回") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("member.change.branchUnion.audit") + @SLog(tag = "会员管理-分工会管理", type = "memberBranchUnionManage", msg = "分工会审核撤回") + public Result revoke(@Valid String taskId) { + bpmService.revokeTask(taskId); + return Result.success(); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeApplyController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeApplyController.java new file mode 100644 index 00000000..f1b00071 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeApplyController.java @@ -0,0 +1,150 @@ +package com.budwk.app.zhgh.staffmanage.member.controller.change; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.BpmProcessConstant; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.bpm.service.BpmService; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.sys.models.Sys_unit; +import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.web.controllers.open.commons.service.CommonService; +import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin; +import com.budwk.app.zhgh.staffmanage.member.models.MemberChangeRecord; +import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberChangePageForm; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.util.List; +import java.util.stream.Stream; + +@Slf4j +@IocBean +@Ok("json:full") +@ApiModel("会员变更申请") +@At("/platform/member/change/apply") +public class MemberChangeApplyController { + + @Inject + private Dao dao; + @Inject + private BpmService bpmService; + @Inject + private CommonService commonService; + @Inject + private MemberCommonService memberCommonService; + + @At("") + @Ok("beetl:/platform/zhgh/staffmanage/member/change/submit/index.html") + @SaCheckPermission("member.change.apply") + public void index() { + } + + @At + @Ok("beetl:/platform/zhgh/staffmanage/member/change/submit/form.html") + @SaCheckPermission("member.change.apply") + public void form() { + } + + @At + @ApiOperation("会员变更申请,我的申请列表") + @SaCheckPermission("member.change.apply") + public Result pageData(MemberChangePageForm pageForm) { + Sql sql = Sqls.create(""" + SELECT + info.id, + info.username, + info.loginname, + info.sex, + info.unitName, + info.unionName, + info.userState, + info.preparedBy, + info.personType, + info.changeTypes, + info.applyDateTime, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariale, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariale + FROM + member_change_record info + LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id + LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id + AND t.taskState = 10 + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + $condition + """); + Cnd cnd = Cnd.NEW(); + pageForm.buildSearch(cnd, "info."); + if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.desc("info.applyDateTime"); + } else { + cnd.orderBy("info." + pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } + sql.setCondition(cnd); + Pagination pagination = memberCommonService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + + @At + @ApiModelProperty("根据id查询变更记录") + @SaCheckPermission("member.change.apply") + public Result findChangeById(String id){ + return Result.success().addData(dao.fetch(MemberChangeRecord.class, id)); + } + + /** + * 不知道有什么用,移过来的 + * @param userId + * @return + */ + @At + @SaCheckPermission(value = {"member.change.branchUnion.audit","member.change.schoolUnion.audit"}, mode = SaMode.OR) + public Result getUserByIdForMemberChange(String userId){ + View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", userId)); + NutMap nutMap = Lang.obj2nutmap(user); + if (StrUtil.isNotBlank(user.getUnionId())) { + Sys_union union = dao.fetch(Sys_union.class, Cnd.where("id", "=", user.getUnionId())); + nutMap.put("union", union); + } + if (StrUtil.isNotBlank(user.getUnitId())) { + Sys_unit unit = dao.fetch(Sys_unit.class, Cnd.where("id", "=", user.getUnitId())); + nutMap.put("unit", unit); + } + return Result.success().addData(nutMap); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeManageController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeManageController.java index 8c868892..d8785c62 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeManageController.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeManageController.java @@ -1,61 +1,145 @@ -//package com.budwk.app.zhgh.member.controller.change; -// -//import cn.dev33.satoken.annotation.SaCheckPermission; -//import com.budwk.app.base.annotation.SLog; -//import com.budwk.app.base.page.Pagination; -//import com.budwk.app.base.result.Result; -//import com.budwk.app.zhgh.member.models.MemberApplyRecord; -//import com.budwk.app.zhgh.member.param.MemberManagePageForm; -//import com.budwk.app.zhgh.member.service.MemberManageService; -//import lombok.extern.slf4j.Slf4j; -//import org.nutz.dao.sql.Sql; -//import org.nutz.ioc.loader.annotation.Inject; -//import org.nutz.ioc.loader.annotation.IocBean; -//import org.nutz.lang.util.NutMap; -//import org.nutz.mvc.annotation.At; -//import org.nutz.mvc.annotation.Ok; -// -//import javax.validation.Valid; -// -///** -// * @version 1.0 -// * @Author zzr -// * @name:MemberChangeManageController -// * @Date 2024/8/6 8:39 -// * @注释 -// */ -//@IocBean -//@Ok("json") -//@At("/platform/member/change/manage") -//@Slf4j -//public class MemberChangeManageController { -// -// @Inject -// private MemberManageService memberService; -// -// @At("") -// @Ok("beetl:/platform/zhgh/staffmanage/member/change/manage/index.html") -// @SaCheckPermission("member.branch.manage") -// public void index() { -// } -// -// -// @At -// @SaCheckPermission("member.branch.manage") -// public Result pageData(MemberManagePageForm pageForm) { -// Sql sql = memberService.getSql(pageForm,null); -// Pagination pagination = memberService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); -// return Result.success(pagination); -// } -// -// -// @At -// @SaCheckPermission("member.branch.manage") -// public Result getNumData(MemberManagePageForm pageForm) { -// NutMap map = memberService.getButtonNum(pageForm); -// return Result.success(map); -// } -// -// -// -//} +package com.budwk.app.zhgh.staffmanage.member.controller.change; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.date.DateUtil; +import com.budwk.app.base.annotation.RepeatSubmit; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.BpmProcessConstant; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.bpm.enums.BpmTaskApprovalTypeEnum; +import com.budwk.app.bpm.models.BpmProcessInstance; +import com.budwk.app.bpm.models.BpmProcessTask; +import com.budwk.app.bpm.param.BpmTaskApprovalParam; +import com.budwk.app.bpm.service.BpmService; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.web.controllers.open.commons.service.CommonService; +import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType; +import com.budwk.app.zhgh.staffmanage.member.models.MemberChangeRecord; +import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberManagePageForm; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; +import java.util.Map; + +/** + * @version 1.0 + * @Author zzr + * @name:MemberChangeManageController + * @Date 2024/8/12 14:06 + * @注释 会员变更高级管理 + */ +@Slf4j +@IocBean +@Ok("json") +@At("/platform/member/change/manage") +public class MemberChangeManageController { + + @Inject + private Dao dao; + @Inject + private BpmService bpmService; + @Inject + private CommonService commonService; + @Inject + private MemberCommonService memberCommonService; + + @At("") + @Ok("beetl:/platform/zhgh/staffmanage/member/change/manage/index.html") + @SaCheckPermission(value = {"member.change.mange", "staff.member.change.mange"}, mode = SaMode.OR) + public void index() { + } + + + @At + @SaCheckPermission(value = {"member.change.mange", "staff.member.change.mange"}, mode = SaMode.OR) + public Result pageData(MemberManagePageForm pageForm){ + Sql sql = memberCommonService.getSql(pageForm, "schoolUnion"); + Pagination pagination = memberCommonService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + + @At + @RepeatSubmit + @Aop(TransAop.READ_COMMITTED) + @SLog(tag = "会员高级管理-会员变更", msg = "分工会/校工会会员管理员提交变更") + @SaCheckPermission(value = {"member.change.mange", "staff.member.change.mange"}, mode = SaMode.OR) + public Result doSubmitChange(@Param("record") MemberChangeRecord record, @Param("approvalRemark") String approvalRemark){ + // 检验是否有变更 + if (Lang.isEmpty(record)) { + return Result.error("未获取到异动数据"); + } + List changeInfos = memberCommonService.getChangeInfos(record); + if (Lang.isEmpty(changeInfos)) { + return Result.error("未校验到变更数据,请确认数据是否存在变更"); + } + + if (Lang.isEmpty(record.getChangeTypes())) { + record.setChangeTypes(List.of(MemberChangeType.BASIC_CHANGE.name())); + } else { + List changeTypes = record.getChangeTypes(); + changeTypes.add(MemberChangeType.BASIC_CHANGE.name()); + record.setChangeTypes(changeTypes); + } + + record.setApplyDateTime(DateUtil.date()); + record.setChangeOrigin("党委会变更"); + dao.insertOrUpdate(record); + + bpmService.startSubmitProcessInstance(BpmProcessConstant.MEMBER_CHANGE.name(), + "【会员变更】" + record.getUsername(), record.getId(), List.of(SecurityUtil.getUserLoginname()), null); + + // 有这个菜单权限的,那就是默认分工会审核通过了 + BpmProcessInstance instance = dao.fetch(BpmProcessInstance.class, Cnd.where("processInstanceBusinessId", "=", record.getId())); + BpmProcessTask task = dao.fetch(BpmProcessTask.class, Cnd.where(BpmProcessTask::getProcessInstanceId, "=", instance.getId()) + .desc(BpmProcessTask::getCreatedAt)); + BpmTaskApprovalParam param = new BpmTaskApprovalParam(); + param.setProcessInstanceId(instance.getId()); + param.setProcessInstanceBusinessId(record.getId()); + param.setProcessInstanceTaskId(task.getId()); + param.setBpmTaskApprovalType(BpmTaskApprovalTypeEnum.PASS.name()); + param.setBpmTaskApprovalTypeEnum(BpmTaskApprovalTypeEnum.PASS); + param.setApprovalOpinion("分工会审核通过"); + // 表示分工会审核通过 + param.getBpmTaskApprovalTypeEnum(); + Map variables = BeanUtil.beanToMap(param); + bpmService.completeTask(param.getProcessInstanceTaskId(), param.getBpmTaskApprovalTypeEnum(), variables, List.of(SecurityUtil.getUserLoginname())); + + // 如果有校工会或者超管的角色,直接审核通过了 + if (AuthUtil.hasRoleOr(RoleConstant.SCHOOL_UNION_CHAIRMAN.name(), RoleConstant.SCHOOL_UNION_MEMBER_ADMIN.name(), RoleConstant.SYSADMIN.name())) { + BpmProcessInstance committeeInstance = dao.fetch(BpmProcessInstance.class, Cnd.where("processInstanceBusinessId", "=", record.getId())); + BpmProcessTask committeeTask = dao.fetch(BpmProcessTask.class, Cnd.where(BpmProcessTask::getProcessInstanceId, "=", committeeInstance.getId()) + .desc(BpmProcessTask::getCreatedAt)); + + BpmTaskApprovalParam committeeParam = new BpmTaskApprovalParam(); + committeeParam.setProcessInstanceId(committeeInstance.getId()); + committeeParam.setProcessInstanceBusinessId(record.getId()); + committeeParam.setProcessInstanceTaskId(committeeTask.getId()); + committeeParam.setBpmTaskApprovalType(BpmTaskApprovalTypeEnum.PASS.name()); + committeeParam.setBpmTaskApprovalTypeEnum(BpmTaskApprovalTypeEnum.PASS); + committeeParam.setApprovalOpinion("校工会审核通过"); + + memberCommonService.compareChangeInfoAndUpdateMember(committeeParam.getProcessInstanceBusinessId()); + bpmService.completeTask(committeeParam.getProcessInstanceTaskId(), committeeParam.getBpmTaskApprovalTypeEnum(), null, null); + } + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeRecordController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeRecordController.java index 23b7cb2c..c1854416 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeRecordController.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeRecordController.java @@ -4,28 +4,32 @@ import cn.dev33.satoken.annotation.SaCheckPermission; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.result.Result; import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberManagePageForm; -import com.budwk.app.zhgh.staffmanage.member.service.MemberManageService; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; import lombok.extern.slf4j.Slf4j; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; +import javax.validation.Valid; +import java.util.List; + /** * @version 1.0 * @Author zzr - * @name:MemberChangeRecordsController - * @Date 2024/8/8 8:40 - * @注释 + * @name:MemberSchoolRecordController + * @Date 2024/8/13 16:27 + * @注释 校工会 会员变更记录 */ +@Slf4j @IocBean @Ok("json") @At("/platform/member/change/record") -@Slf4j public class MemberChangeRecordController { @Inject - private MemberManageService memberService; + private MemberCommonService memberCommonService; @At("") @Ok("beetl:/platform/zhgh/staffmanage/member/change/record/index.html") @@ -35,8 +39,16 @@ public class MemberChangeRecordController { @At @SaCheckPermission("member.change.record") - public Result pageData(MemberManagePageForm pageForm) { - Pagination pagination = memberService.memberHistoryRecords(pageForm); + public Result pageData(MemberManagePageForm pageForm){ + Pagination pagination = memberCommonService.memberHistoryRecords(pageForm); return Result.success(pagination); } + + + @At + @SaCheckPermission("member.change.record") + public Result findAuditChangeInfo(@Valid String recordId) { + List list = memberCommonService.getChangeInfos(recordId); + return Result.success(list); + } } diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeViewController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeViewController.java new file mode 100644 index 00000000..2ce50fce --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeViewController.java @@ -0,0 +1,89 @@ +package com.budwk.app.zhgh.staffmanage.member.controller.change; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.result.Result; +import com.budwk.app.bpm.service.BpmService; +import com.budwk.app.zhgh.staffmanage.member.models.MemberChangeRecord; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiOperation; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import javax.validation.Valid; +import java.util.List; + +/** + * @version 1.0 + * @Author zzr + * @name:MemberChangeMineController + * @Date 2025/2/14 11:13 + * @注释 + */ + +@IocBean +@Ok("json:full") +@ApiModel("会员变更申请查看") +@At("/platform/member/change/view") +public class MemberChangeViewController { + + @Inject + private Dao dao; + @Inject + private BpmService bpmService; + @Inject + private MemberCommonService memberCommonService; + + + @At("") + @Ok("beetl:/platform/zhgh/staffmanage/member/change/view/index.html") + @SaCheckPermission("member.change.apply") + public void index() { + } + + + @At + @ApiOperation("个人申请撤回") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("member.change.apply") + @SLog(tag = "会员变更申请", msg = "撤回申请") + public Result doRevoke(@Valid String id){ + bpmService.revokeApply(id); + return Result.success(); + } + + + @At + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("member.change.apply") + @SLog(tag = "会员入会申请", msg = "删除申请") + public Result doDelete(String id){ + dao.clear(MemberChangeRecord.class, Cnd.where("id", "=", id)); + bpmService.deleteInstance(id); + return Result.success(); + } + + + @At + @ApiOperation("根据id查询变更记录") + @SaCheckPermission("member.change.apply") + public Result findMemberChangeRecord(String id){ + MemberChangeRecord record = dao.fetch(MemberChangeRecord.class, id); + NutMap nutMap = Lang.obj2nutmap(record); + + List changeInfos = memberCommonService.getChangeInfos(nutMap.getString("id")); + nutMap.put("changeInfos", changeInfos); + return Result.success().addData(nutMap); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberSchoolUnionAuditController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberSchoolUnionAuditController.java new file mode 100644 index 00000000..079b2328 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberSchoolUnionAuditController.java @@ -0,0 +1,222 @@ +package com.budwk.app.zhgh.staffmanage.member.controller.change; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.RepeatSubmit; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.BpmProcessConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.bpm.enums.BpmTaskApprovalTypeEnum; +import com.budwk.app.bpm.models.BpmProcessInstance; +import com.budwk.app.bpm.models.BpmProcessTask; +import com.budwk.app.bpm.param.BpmTaskApprovalParam; +import com.budwk.app.bpm.service.BpmService; +import com.budwk.app.bpm.vo.BpmTaskApprovalRecordVo; +import com.budwk.app.flow.enums.ProcessTaskStateEnum; +import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.sys.models.Sys_user_history; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; +import com.budwk.app.zhgh.staffmanage.member.models.MemberChangeRecord; +import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberChangePageForm; +import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberManagePageForm; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; +import com.budwk.app.zhgh.staffmanage.member.service.MemberSchoolUnionManageService; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.validation.Valid; +import java.util.List; +import java.util.Map; + +/** + * @version 1.0 + * @Author zzr + * @name:MemberSchoolUnionAuditController + * @Date 2024/8/13 8:49 + * @注释 + */ +@Slf4j +@IocBean +@Ok("json") +@At("/platform/member/change/schoolUnion/audit") +public class MemberSchoolUnionAuditController { + + @Inject + private Dao dao; + @Inject + private BpmService bpmService; + @Inject + private MemberCommonService memberCommonService; + @Inject + private MemberSchoolUnionManageService memberSchoolUnionManageService; + + @At("") + @Ok("beetl:/platform/zhgh/staffmanage/member/change/schoolUnionAudit/index.html") + @SaCheckPermission("member.change.schoolUnion.audit") + public void index() { + } + + @At + @Ok("beetl:/platform/zhgh/staffmanage/member/change/schoolUnionAudit/form.html") + @SaCheckPermission("member.change.schoolUnion.audit") + public void form() { + } + + + @At + @SaCheckPermission("member.change.schoolUnion.audit") + public Result pageData(MemberChangePageForm pageForm) { + Sql sql = Sqls.create(""" + SELECT + info.id, + info.sex, + info.userName, + info.loginName, + info.unitName, + info.unionName, + info.userState, + info.preparedBy, + info.personType, + info.changeTypes, + info.applyDateTime, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariale, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariale + FROM + wf_process_task t + LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId + LEFT JOIN member_change_record info ON info.id = ins.businessNo + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + $condition + """); + Cnd cnd = Cnd.NEW(); + pageForm.buildSearch(cnd, "info."); + + cnd.and("t.taskName", "=", "f18d8726-75bc-43a9-87a8-2dd73341bdce"); + cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId())); + + if (pageForm.getAudit()) { + cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.WITHDRAW.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode())); + } else { + cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode()); + } + + if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.desc("info.applyDateTime"); + } else { + cnd.orderBy("info." + pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } + sql.setCondition(cnd); + Pagination pagination = memberCommonService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + @At + @RepeatSubmit + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("member.change.schoolUnion.audit") + @SLog(tag = "会员管理-校工会管理", type = "memberSchoolUnionAudit", msg = "校工会会员审核") + public Result approval(@Param("approval") @Valid BpmTaskApprovalParam approvalParam) { + Map variables = BeanUtil.beanToMap(approvalParam); + if (approvalParam.getBpmTaskApprovalTypeEnum().equals(BpmTaskApprovalTypeEnum.PASS)) { + MemberChangeRecord record = memberCommonService.dao().fetch(MemberChangeRecord.class, Cnd.where("id", "=", approvalParam.getProcessInstanceBusinessId())); + if (StrUtil.isNotEmpty(approvalParam.getApprovalRemark())) { + memberCommonService.dao().update(MemberChangeRecord.class, Chain.make("remark", approvalParam.getApprovalRemark()), Cnd.where("id", "=", record.getId())); + } + memberCommonService.compareChangeInfoAndUpdateMember(record); + } + bpmService.completeTask(approvalParam.getProcessInstanceTaskId(), approvalParam.getBpmTaskApprovalTypeEnum(), variables, null); + return Result.success(); + } + + + @At + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("member.change.schoolUnion.audit") + @SLog(type = "memberChange", tag = "会员变更", msg = "校工会批量审核") + public Object doBatchApproval(@Param("data") String[] ids){ + if (ids.length == 0) { + return Result.error("未获取到选择数据"); + } + + for (String id : ids) { + BpmProcessInstance committeeInstance = dao.fetch(BpmProcessInstance.class, Cnd.where("processInstanceBusinessId", "=", id)); + BpmProcessTask committeeTask = dao.fetch(BpmProcessTask.class, Cnd.where(BpmProcessTask::getProcessInstanceId, "=", committeeInstance.getId()) + .desc(BpmProcessTask::getCreatedAt)); + + BpmTaskApprovalParam committeeParam = new BpmTaskApprovalParam(); + committeeParam.setProcessInstanceId(committeeInstance.getId()); + committeeParam.setProcessInstanceBusinessId(id); + committeeParam.setProcessInstanceTaskId(committeeTask.getId()); + committeeParam.setBpmTaskApprovalType(BpmTaskApprovalTypeEnum.PASS.name()); + committeeParam.setBpmTaskApprovalTypeEnum(BpmTaskApprovalTypeEnum.PASS); + committeeParam.setApprovalOpinion("校工会审核通过"); + + memberCommonService.compareChangeInfoAndUpdateMember(committeeParam.getProcessInstanceBusinessId()); + bpmService.completeTask(committeeParam.getProcessInstanceTaskId(), committeeParam.getBpmTaskApprovalTypeEnum(), null, null); + } + + return Result.success(); + } + + + + + @At + @ApiOperation("校工会审核撤回") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("member.change.schoolUnion.audit") + @SLog(tag = "会员管理-校工会管理", type = "memberSchoolUnionAudit", msg = "校工会审核撤回") + public Result revoke(@Valid String taskId) { + bpmService.revokeTask(taskId); + + // 审核通过的撤回,要将数据也改变回去 + BpmProcessTask oldTask = dao.fetch(BpmProcessTask.class, taskId); + BpmProcessInstance fetch = dao.fetch(BpmProcessInstance.class, oldTask.getProcessInstanceId()); + String businessId = fetch.getProcessInstanceBusinessId(); + + // 先查询历史记录,然后再把历史记录赋值给现在数据库存储的记录 + Sys_user_history history = dao.fetch(Sys_user_history.class, Cnd.where(Sys_user_history::getRecordId, "=", businessId)); + Sys_user info = dao.fetch(Sys_user.class, Cnd.where(Sys_user::getLoginname, "=", history.getLoginname())); + + String userId = info.getId(); + BeanUtil.copyProperties(history, info); + info.setId(userId); + dao.update(info); + dao.delete(history); + + return Result.success(); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/MemberSchoolUnionAuditController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/MemberSchoolUnionAuditController.java deleted file mode 100644 index 908e489d..00000000 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/MemberSchoolUnionAuditController.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.budwk.app.zhgh.staffmanage.member.controller.school; - -import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.dev33.satoken.annotation.SaMode; -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import com.budwk.app.base.annotation.RepeatSubmit; -import com.budwk.app.base.annotation.SLog; -import com.budwk.app.base.constant.BpmProcessConstant; -import com.budwk.app.base.page.Pagination; -import com.budwk.app.base.result.Result; -import com.budwk.app.bpm.enums.BpmTaskApprovalTypeEnum; -import com.budwk.app.bpm.param.BpmTaskApprovalParam; -import com.budwk.app.bpm.service.BpmService; -import com.budwk.app.bpm.vo.BpmTaskApprovalRecordVo; -import com.budwk.app.sys.models.Sys_user_history; -import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; -import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberManagePageForm; -import com.budwk.app.zhgh.staffmanage.member.service.MemberManageService; -import com.budwk.app.zhgh.staffmanage.member.service.MemberSchoolUnionManageService; -import io.swagger.annotations.ApiOperation; -import lombok.extern.slf4j.Slf4j; -import org.nutz.aop.interceptor.ioc.TransAop; -import org.nutz.dao.Chain; -import org.nutz.dao.Cnd; -import org.nutz.ioc.aop.Aop; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.Lang; -import org.nutz.lang.util.NutMap; -import org.nutz.mvc.annotation.At; -import org.nutz.mvc.annotation.Ok; -import org.nutz.mvc.annotation.Param; - -import javax.validation.Valid; -import java.util.List; -import java.util.Map; - -/** - * @version 1.0 - * @Author zzr - * @name:MemberSchoolUnionAuditController - * @Date 2024/8/13 8:49 - * @注释 - */ -@Slf4j -@IocBean -@Ok("json") -@At("/platform/member/schoolUnion/audit") -public class MemberSchoolUnionAuditController { - - @Inject - private BpmService bpmService; - - @Inject - private MemberManageService memberManageService; - - @Inject - private MemberSchoolUnionManageService memberSchoolUnionManageService; - - @At("") - @Ok("beetl:/platform/zhgh/staffmanage/member/school/audit/index.html") - @SaCheckPermission("member.schoolUnion.audit") - public void index() { - } - - - @At - @SaCheckPermission("member.schoolUnion.audit") - public Result pageData(MemberManagePageForm pageForm) { - Pagination pageData = memberSchoolUnionManageService.getPageData(pageForm); - return Result.success(pageData); - } - - - @At - @RepeatSubmit - @Aop(TransAop.READ_COMMITTED) - @SaCheckPermission("member.schoolUnion.audit") - @SLog(tag = "会员管理-校工会管理", type = "memberSchoolUnionAudit", msg = "校工会会员审核") - public Result approval(@Param("approval") @Valid BpmTaskApprovalParam approvalParam) { - Map variables = BeanUtil.beanToMap(approvalParam); - if (approvalParam.getBpmTaskApprovalTypeEnum().equals(BpmTaskApprovalTypeEnum.PASS)) { - MemberApplyRecord record = memberManageService.dao().fetch(MemberApplyRecord.class, Cnd.where("id", "=", approvalParam.getProcessInstanceBusinessId())); - if (StrUtil.isNotEmpty(approvalParam.getApprovalRemark())) { - memberManageService.dao().update(MemberApplyRecord.class, Chain.make("remark", approvalParam.getApprovalRemark()), Cnd.where("id", "=", record.getId())); - } - memberManageService.compareMemberChangeInfoAndUpdateUser(record); - } - bpmService.completeTask(approvalParam.getProcessInstanceTaskId(), approvalParam.getBpmTaskApprovalTypeEnum(), variables, null); - return Result.success(); - } - - - @At - @ApiOperation("校工会审核撤回") - @Aop(TransAop.READ_COMMITTED) - @SaCheckPermission("member.schoolUnion.audit") - @SLog(tag = "会员管理-校工会管理", type = "memberSchoolUnionAudit", msg = "校工会审核撤回") - public Result revoke(@Valid String taskId) { - bpmService.revokeTask(taskId); - return Result.success(); - } - - - /** - * 获取变更信息,审核 - * @param recordId - * @return - */ - @At - @SaCheckPermission(value = {"member.branchUnion.audit", "member.schoolUnion.audit"}, mode = SaMode.OR) - public Result findAuditChangeInfo(String recordId) { - Sys_user_history history = memberManageService.dao().fetch(Sys_user_history.class, Cnd.where("recordId", "=", recordId).or("id","=",recordId)); - MemberApplyRecord record = memberManageService.dao().fetch(MemberApplyRecord.class, recordId); - if (ObjectUtil.isAllEmpty(history, record)) { - return Result.error("获取变更信息失败"); - } - List nodeTasks = bpmService.getNodeTasks(BpmProcessConstant.MEMBER_BRANCH_UNION_CHANGE, recordId); - if (Lang.isNotEmpty(history)) { - List nutMaps = memberManageService.compareMemberChangeInfo(history); - return Result.success(NutMap.NEW().addv("changeList", nutMaps).addv("nodeTasks", nodeTasks)); - } - List nutMaps = memberManageService.compareMemberChangeInfo(record); - return Result.success(NutMap.NEW().addv("changeList", nutMaps).addv("nodeTasks", nodeTasks)); - } -} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/MemberSchoolUnionManageController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/MemberSchoolUnionManageController.java deleted file mode 100644 index 1727a3f6..00000000 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/MemberSchoolUnionManageController.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.budwk.app.zhgh.staffmanage.member.controller.school; - -import cn.dev33.satoken.annotation.SaCheckPermission; -import com.budwk.app.base.annotation.RepeatSubmit; -import com.budwk.app.base.annotation.SLog; -import com.budwk.app.base.page.Pagination; -import com.budwk.app.base.result.Result; -import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin; -import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; -import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberManagePageForm; -import com.budwk.app.zhgh.staffmanage.member.service.MemberManageService; -import lombok.extern.slf4j.Slf4j; -import org.nutz.dao.sql.Sql; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.util.NutMap; -import org.nutz.mvc.annotation.At; -import org.nutz.mvc.annotation.Ok; -import org.nutz.mvc.annotation.Param; - -import javax.validation.Valid; -import java.util.List; - -/** - * @version 1.0 - * @Author zzr - * @name:MemberSchoolUnionManageController - * @Date 2024/8/12 14:06 - * @注释 会员校工会管理 - */ -@IocBean -@At("/platform/member/schoolUnion/manage/list") -@Slf4j -@Ok("json") -public class MemberSchoolUnionManageController { - - @Inject - private MemberManageService memberManageService; - - @At("") - @Ok("beetl:/platform/zhgh/staffmanage/member/school/manage/index.html") - @SaCheckPermission("member.schoolUnion.manage.list") - public void index() { - } - - - @At - @SaCheckPermission("member.schoolUnion.manage.list") - public Result pageData(MemberManagePageForm pageForm){ - Sql sql = memberManageService.getSql(pageForm, "schoolUnion"); - Pagination pagination = memberManageService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); - return Result.success(pagination); - } - - - @At - @SaCheckPermission("member.schoolUnion.manage.list") - @SLog(tag = "添加会员", type = "memberBranchManage", msg = "添加会员") - public Result addMember(@Valid MemberApplyRecord record) { - return null; - } - - - @At - @SaCheckPermission("member.schoolUnion.manage.list") - public Result getChangeInfoByUserId(String userId) { - return Result.success(memberManageService.getMemberChangeInfoByUserId(userId)); - } - - - @At - @RepeatSubmit - @SaCheckPermission("member.branchUnion.manage.list") - @SLog(tag = "校工会管理-会员管理", type = "MemberBranchManageList", msg = "校工会普通变更") - public Result generalMemberChange(@Param("record") MemberApplyRecord record, @Param("approvalRemark") String approvalRemark){ - //校工会变更,直接更改 - try { - // 校验是否有变更的字段 - List changeInfoList = memberManageService.compareMemberChangeInfo(record); - // 存储变更的类型 - List changeTypeList = memberManageService.compareMemberChangeType(changeInfoList, record); - record.setChangeTypes(changeTypeList); - record.setChangeOrigin(MemberChangeOrigin.SCHOOL_UNION.name()); - record.setRemark(approvalRemark); - memberManageService.insert(record); - memberManageService.compareMemberChangeInfoAndUpdateUser(record); - return Result.success(); - } catch (Exception e) { - e.printStackTrace(); - return Result.error(e.getMessage()); - } - } -} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/MemberSchoolUnionRecordController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/MemberSchoolUnionRecordController.java deleted file mode 100644 index b69be012..00000000 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/MemberSchoolUnionRecordController.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.budwk.app.zhgh.staffmanage.member.controller.school; - -import cn.dev33.satoken.annotation.SaCheckPermission; -import com.budwk.app.base.page.Pagination; -import com.budwk.app.base.result.Result; -import com.budwk.app.sys.models.Sys_user_history; -import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberManagePageForm; -import com.budwk.app.zhgh.staffmanage.member.service.MemberManageService; -import lombok.extern.slf4j.Slf4j; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.util.NutMap; -import org.nutz.mvc.annotation.At; -import org.nutz.mvc.annotation.Ok; - -import javax.validation.Valid; -import java.util.List; - -/** - * @version 1.0 - * @Author zzr - * @name:MemberSchoolRecordController - * @Date 2024/8/13 16:27 - * @注释 校工会 会员变更记录 - */ -@Slf4j -@IocBean -@Ok("json") -@At("/platform/member/schoolUnion/record") -public class MemberSchoolUnionRecordController { - - @Inject - private MemberManageService memberManageService; - - @At("") - @Ok("beetl:/platform/zhgh/staffmanage/member/school/record/index.html") - @SaCheckPermission("member.schoolUnion.record") - public void index() { - } - - @At - @SaCheckPermission("member.schoolUnion.record") - public Result pageData(MemberManagePageForm pageForm){ - Pagination pagination = memberManageService.memberHistoryRecords(pageForm); - return Result.success(pagination); - } - - - @At - @SaCheckPermission("member.schoolUnion.record") - public Result findAuditChangeInfo(@Valid String recordId) { - Sys_user_history history = memberManageService.dao().fetch(Sys_user_history.class, recordId); - List list = memberManageService.compareMemberChangeInfo(history); - return Result.success(list); - } -} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/branch/verification/MemberBranchVerificationCheckController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/verification/MemberBranchVerificationCheckController.java similarity index 86% rename from src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/branch/verification/MemberBranchVerificationCheckController.java rename to src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/verification/MemberBranchVerificationCheckController.java index 68392dc0..b7dd9464 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/branch/verification/MemberBranchVerificationCheckController.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/verification/MemberBranchVerificationCheckController.java @@ -1,4 +1,4 @@ -package com.budwk.app.zhgh.staffmanage.member.controller.branch.verification; +package com.budwk.app.zhgh.staffmanage.member.controller.verification; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaMode; @@ -12,20 +12,16 @@ import com.budwk.app.base.constant.RoleConstant; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.result.Result; import com.budwk.app.sys.models.Sys_user; -import com.budwk.app.sys.models.Sys_user_change_info; import com.budwk.app.sys.models.Sys_user_history; import com.budwk.app.web.commons.auth.utils.AuthUtil; import com.budwk.app.web.commons.auth.utils.SecurityUtil; import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin; -import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; -import com.budwk.app.zhgh.staffmanage.member.models.MemberListVerificationProject; -import com.budwk.app.zhgh.staffmanage.member.models.MemberListVerificationUser; -import com.budwk.app.zhgh.staffmanage.member.models.MemberVerificationBranchUnionFeedback; +import com.budwk.app.zhgh.staffmanage.member.models.*; import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberListVerificationPageForm; import com.budwk.app.zhgh.staffmanage.member.param.MemberVerificationBranchUnionFeedbackParam; import com.budwk.app.zhgh.staffmanage.member.param.MemberVerificationGetChangeParam; import com.budwk.app.zhgh.staffmanage.member.service.MemberListVerificationService; -import com.budwk.app.zhgh.staffmanage.member.service.MemberManageService; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.nutz.aop.interceptor.ioc.TransAop; @@ -65,7 +61,7 @@ public class MemberBranchVerificationCheckController { private MemberListVerificationService memberListVerificationService; @Inject - private MemberManageService memberManageService; + private MemberCommonService memberCommonService; @At("") @Ok("beetl:/platform/zhgh/staffmanage/member/branch/verification/check/index.html") @@ -113,16 +109,15 @@ public class MemberBranchVerificationCheckController { @ApiOperation("分工会 名单核对事项,单个人员变更") @SaCheckPermission("member.branchUnion.verification.check") @SLog(tag = "分工会管理-名单核对事项", type = "branchUnionVerification", msg = "分工会单个人员变更") - public Result doCheckMember(@Param("record") MemberApplyRecord record) { + public Result doCheckMember(@Param("record") MemberChangeRecord record) { if (Objects.isNull(record)) { return Result.error("数据获取失败"); } - Dao dao = memberManageService.dao(); -// memberManageService.compareMemberChangeInfoAndUpdateUser(record); + Dao dao = memberCommonService.dao(); // 校验是否有变更的东西 - memberManageService.compareMemberChangeInfo(record); + memberCommonService.compareChangeInfoAndUpdateMember(record); record.setChangeOrigin(MemberChangeOrigin.BRANCH_UNION_VERIFICATION.name()); - MemberApplyRecord applyRecord = dao.fetch(MemberApplyRecord.class, Cnd.where("userId", "=", record.getUserId()) + MemberChangeRecord applyRecord = dao.fetch(MemberChangeRecord.class, Cnd.where("userId", "=", record.getUserId()) .and("verificationProjectId", "=", record.getVerificationProjectId())); //查出当前核对事项是否有变更记录,有则修改 if (Lang.isNotEmpty(applyRecord)) { @@ -152,7 +147,7 @@ public class MemberBranchVerificationCheckController { @SaCheckPermission("member.branchUnion.verification.check") @SLog(tag = "分工会管理-名单核对事项", type = "branchUnionVerification", msg = "名单核对事项无误提交") public Result correctSubmission(@Param("data") @Valid MemberVerificationBranchUnionFeedbackParam param) { - memberManageService.dao().update(MemberVerificationBranchUnionFeedback.class, + memberCommonService.dao().update(MemberVerificationBranchUnionFeedback.class, Chain.make("isSubmit", true).add("status", "分工会无误提交") .add("welfareJson", param.getWelfareJson()), Cnd.where("verificationProjectId", "=", param.getVerificationProjectId()) @@ -189,7 +184,7 @@ public class MemberBranchVerificationCheckController { @At @SaCheckPermission("member.branchUnion.verification.check") public Result validateSubmitButton(@Valid @Param("verificationProjectId") String verificationProjectId) { - MemberVerificationBranchUnionFeedback feedback = memberManageService.dao().fetch(MemberVerificationBranchUnionFeedback.class, + MemberVerificationBranchUnionFeedback feedback = memberCommonService.dao().fetch(MemberVerificationBranchUnionFeedback.class, Cnd.where("verificationProjectId", "=", verificationProjectId).and("unionId", "=", SecurityUtil.getUnionId())); boolean flag = feedback.getBranchUnionSubmitNum() == 0 || feedback.getBranchUnionSubmit(); @@ -240,15 +235,10 @@ public class MemberBranchVerificationCheckController { @ApiOperation("分工会 名单核对事项,获取变更记录") @SaCheckPermission("member.branchUnion.verification.check") public Result getVerificationChangeInfo(@Valid @Param("data") MemberVerificationGetChangeParam param) { - MemberApplyRecord record = memberManageService.dao().fetch(MemberApplyRecord.class, + MemberChangeRecord record = memberCommonService.dao().fetch(MemberChangeRecord.class, Cnd.where("userId", "=", param.getUserId()).and("verificationProjectId", "=", param.getVerificationProjectId())); if (Lang.isNotEmpty(record)) { - Sys_user_history history = memberManageService.dao().fetch(Sys_user_history.class, Cnd.where("recordId", "=", record.getId()).desc("changeTime")); - if (Lang.isNotEmpty(history)) { - return Result.success(memberManageService.compareMemberChangeInfo(history)); - } else { - return Result.success(memberManageService.compareMemberChangeInfo(record)); - } + return Result.success(memberCommonService.getChangeInfos(record)); } return Result.error(); } @@ -258,9 +248,9 @@ public class MemberBranchVerificationCheckController { @ApiOperation("分工会 名单核对事项,查看反馈结果") @SaCheckPermission(value = {"member.branchUnion.verification.check", "member.schoolUnion.verification.check"}, mode = SaMode.OR) public Result getVerificationFeedback(String verificationProjectId, String unionId) { - MemberVerificationBranchUnionFeedback fetch = memberManageService.dao().fetch(MemberVerificationBranchUnionFeedback.class, + MemberVerificationBranchUnionFeedback fetch = memberCommonService.dao().fetch(MemberVerificationBranchUnionFeedback.class, Cnd.where("verificationProjectId", "=", verificationProjectId).and("unionId", "=", unionId)); - MemberListVerificationProject verificationProject = memberManageService.dao().fetch(MemberListVerificationProject.class, Cnd.where("id", "=", verificationProjectId)); + MemberListVerificationProject verificationProject = memberCommonService.dao().fetch(MemberListVerificationProject.class, Cnd.where("id", "=", verificationProjectId)); NutMap nutMap = Lang.obj2nutmap(verificationProject); nutMap.put("feedbackDate", DateUtil.format(DateUtil.date(fetch.getUpdatedAt()), "yyyy-MM-dd HH:mm:ss")); nutMap.put("unionName", fetch.getUnionName()); diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/verification/MemberListVerificationController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/verification/MemberListVerificationController.java similarity index 94% rename from src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/verification/MemberListVerificationController.java rename to src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/verification/MemberListVerificationController.java index 4ce95898..871398ea 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/verification/MemberListVerificationController.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/verification/MemberListVerificationController.java @@ -1,4 +1,4 @@ -package com.budwk.app.zhgh.staffmanage.member.controller.school.verification; +package com.budwk.app.zhgh.staffmanage.member.controller.verification; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.date.DateUtil; @@ -14,15 +14,11 @@ import com.budwk.app.sys.models.Sys_union; import com.budwk.app.sys.services.SysDictService; import com.budwk.app.zhgh.benefit.mode.BenefitUserTemp; import com.budwk.app.zhgh.staffmanage.member.mode.MemberImportTemp; -import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; -import com.budwk.app.zhgh.staffmanage.member.models.MemberListVerificationProject; -import com.budwk.app.zhgh.staffmanage.member.models.MemberListVerificationUser; -import com.budwk.app.zhgh.staffmanage.member.models.MemberVerificationBranchUnionFeedback; +import com.budwk.app.zhgh.staffmanage.member.models.*; import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberListVerificationPageForm; import com.budwk.app.zhgh.staffmanage.member.param.MemberListVerificationParam; import com.budwk.app.zhgh.staffmanage.member.param.MemberListVerificationProjectParam; import com.budwk.app.zhgh.staffmanage.member.service.MemberListVerificationService; -import com.budwk.app.zhgh.welfare.mode.WelfareUserTemp; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.formula.functions.T; @@ -188,7 +184,7 @@ public class MemberListVerificationController { public Result removeVerificationProject(String verificationProjectId) { Dao dao = memberListVerificationService.dao(); dao.clear(MemberListVerificationProject.class, Cnd.where("id", "=", verificationProjectId)); - dao.clear(MemberApplyRecord.class, Cnd.where("verificationProjectId", "=", verificationProjectId)); + dao.clear(MemberChangeRecord.class, Cnd.where("verificationProjectId", "=", verificationProjectId)); dao.clear(MemberListVerificationUser.class, Cnd.where("verificationProjectId", "=", verificationProjectId)); dao.clear(MemberVerificationBranchUnionFeedback.class, Cnd.where("verificationProjectId", "=", verificationProjectId)); return Result.success(); diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/verification/MemberSchoolVerificationCheckController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/verification/MemberSchoolVerificationCheckController.java similarity index 85% rename from src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/verification/MemberSchoolVerificationCheckController.java rename to src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/verification/MemberSchoolVerificationCheckController.java index ff172596..f3a5b076 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/school/verification/MemberSchoolVerificationCheckController.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/verification/MemberSchoolVerificationCheckController.java @@ -1,4 +1,4 @@ -package com.budwk.app.zhgh.staffmanage.member.controller.school.verification; +package com.budwk.app.zhgh.staffmanage.member.controller.verification; import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.entity.ExportParams; @@ -6,7 +6,6 @@ import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.bean.BeanUtil; -import cn.hutool.json.JSONObject; import com.budwk.app.base.annotation.RepeatSubmit; import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.page.Pagination; @@ -16,16 +15,12 @@ import com.budwk.app.sys.models.Sys_user; import com.budwk.app.sys.models.Sys_user_change_info; import com.budwk.app.sys.models.Sys_user_history; import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin; -import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType; -import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; -import com.budwk.app.zhgh.staffmanage.member.models.MemberListVerificationProject; -import com.budwk.app.zhgh.staffmanage.member.models.MemberListVerificationUser; -import com.budwk.app.zhgh.staffmanage.member.models.MemberVerificationBranchUnionFeedback; +import com.budwk.app.zhgh.staffmanage.member.models.*; import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberListVerificationPageForm; import com.budwk.app.zhgh.staffmanage.member.param.MemberSchoolVerificationSubmitParam; import com.budwk.app.zhgh.staffmanage.member.param.MemberVerificationGetChangeParam; import com.budwk.app.zhgh.staffmanage.member.service.MemberListVerificationService; -import com.budwk.app.zhgh.staffmanage.member.service.MemberManageService; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.Workbook; @@ -33,9 +28,7 @@ import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.dao.Chain; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; -import org.nutz.dao.Sqls; import org.nutz.dao.sql.Sql; -import org.nutz.dao.util.cri.Static; import org.nutz.ioc.aop.Aop; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; @@ -68,7 +61,7 @@ public class MemberSchoolVerificationCheckController { private MemberListVerificationService memberListVerificationService; @Inject - private MemberManageService memberManageService; + private MemberCommonService memberCommonService; @At("") @Ok("beetl:/platform/zhgh/staffmanage/member/school/verification/check/index.html") @@ -96,15 +89,10 @@ public class MemberSchoolVerificationCheckController { @At @SaCheckPermission("member.schoolUnion.verification.check") public Result getVerificationChangeInfo(@Valid @Param("data") MemberVerificationGetChangeParam param) { - MemberApplyRecord record = memberManageService.dao().fetch(MemberApplyRecord.class, + MemberChangeRecord record = memberCommonService.dao().fetch(MemberChangeRecord.class, Cnd.where("userId", "=", param.getUserId()).and("verificationProjectId", "=", param.getVerificationProjectId())); if (Lang.isNotEmpty(record)) { - Sys_user_history history = memberManageService.dao().fetch(Sys_user_history.class, Cnd.where("recordId", "=", record.getId()).desc("changeTime")); - if (Lang.isNotEmpty(history)) { - return Result.success(memberManageService.compareMemberChangeInfo(history)); - } else { - return Result.success(memberManageService.compareMemberChangeInfo(record)); - } + return Result.success(memberCommonService.getChangeInfos(record)); } return Result.success(); } @@ -126,18 +114,18 @@ public class MemberSchoolVerificationCheckController { Chain chain = Chain.make("schoolUnionChecked", true); chain.add("verificationOption", param.getOption()); - MemberApplyRecord record = memberManageService.dao().fetch(MemberApplyRecord.class, + MemberChangeRecord record = memberCommonService.dao().fetch(MemberChangeRecord.class, Cnd.where("userId", "=", param.getUserId()) .and("verificationProjectId", "=", param.getVerificationProjectId())); if (param.getFlag()) { chain.add("currentState", 2); - memberManageService.compareMemberChangeInfoAndUpdateUser(record); + memberCommonService.compareChangeInfoAndUpdateMember(record); } else { chain.add("currentState", 1); - memberManageService.update(record); + memberCommonService.update(record); } - memberManageService.dao().update(MemberListVerificationUser.class, chain, + memberCommonService.dao().update(MemberListVerificationUser.class, chain, Cnd.where("userId", "=", param.getUserId()).and("verificationProjectId", "=", param.getVerificationProjectId())); return Result.success(); } @@ -148,19 +136,19 @@ public class MemberSchoolVerificationCheckController { @SaCheckPermission("member.schoolUnion.verification.check") @SLog(type = "member", tag = "名单核对事项", msg = "校工会提交") public Result schoolVerificationSubmit(@Valid @Param("data") MemberSchoolVerificationSubmitParam param) { - MemberVerificationBranchUnionFeedback fetch = memberManageService.dao().fetch(MemberVerificationBranchUnionFeedback.class, + MemberVerificationBranchUnionFeedback fetch = memberCommonService.dao().fetch(MemberVerificationBranchUnionFeedback.class, Cnd.where("verificationProjectId", "=", param.getVerificationProjectId()) .and("unionId", "=", param.getUnionId())); fetch.setSchoolUnionSubmit(true); fetch.setSchoolUnionSubmitNum(fetch.getSchoolUnionSubmitNum() + 1); fetch.setStatus("待分工会重新提交"); // 更新反馈表的数据,校工会提交置为true - memberManageService.dao().update(fetch); + memberCommonService.dao().update(fetch); Cnd cnd = Cnd.NEW(); cnd.and("unionId", "=", param.getUnionId()); cnd.and("verificationProjectId", "=", param.getVerificationProjectId()); - memberManageService.dao().update(MemberListVerificationUser.class, + memberCommonService.dao().update(MemberListVerificationUser.class, Chain.make("branchUnionChecked", false).add("schoolUnionChecked", true), cnd); return Result.success(); @@ -179,7 +167,7 @@ public class MemberSchoolVerificationCheckController { @SaCheckPermission("member.schoolUnion.verification.check") public Result getChangeTypeUserPageData(MemberListVerificationPageForm pageForm) { Sql sql = memberListVerificationService.getChangeTypeUserSql(pageForm); - Pagination pagination = memberManageService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + Pagination pagination = memberCommonService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); return Result.success(pagination); } @@ -189,7 +177,7 @@ public class MemberSchoolVerificationCheckController { @SaCheckPermission("member.schoolUnion.verification.check") public void exportChangeTypeUserByUnionIdExcel(MemberListVerificationPageForm pageForm, HttpServletResponse response) { Sql sql = memberListVerificationService.getChangeTypeUserSql(pageForm); - List list = memberManageService.listMap(sql); + List list = memberCommonService.listMap(sql); List excelExportEntities = memberListVerificationService.buildExportEntities(); NutMap nutMap = list.stream().findFirst().orElse(NutMap.NEW()); String labelName = ""; @@ -215,9 +203,9 @@ public class MemberSchoolVerificationCheckController { @Ok("void") @SaCheckPermission("member.schoolUnion.verification.check") public void exportAllChangeTypeUserExcel(MemberListVerificationPageForm pageForm, HttpServletResponse response){ - MemberListVerificationProject project = memberManageService.dao().fetch(MemberListVerificationProject.class, pageForm.getVerificationProjectId()); + MemberListVerificationProject project = memberCommonService.dao().fetch(MemberListVerificationProject.class, pageForm.getVerificationProjectId()); Sql sql = memberListVerificationService.getChangeTypeUserSql(pageForm); - List list = memberManageService.listMap(sql); + List list = memberCommonService.listMap(sql); List excelExportEntities = memberListVerificationService.buildExportEntities(); String labelName = ""; switch (pageForm.getChangeType()) { @@ -244,13 +232,13 @@ public class MemberSchoolVerificationCheckController { @ApiOperation("校工会 名单核对事项,单个人员变更") @SaCheckPermission("member.schoolUnion.verification.check") @SLog(tag = "校工会管理-名单核对事项", type = "schoolUnionVerification", msg = "校工会单个人员变更") - public Result doCheckMember(@Param("record") MemberApplyRecord record){ + public Result doCheckMember(@Param("record") MemberChangeRecord record){ if (Objects.isNull(record)) { return Result.error("数据获取失败"); } - Dao dao = memberManageService.dao(); + Dao dao = memberCommonService.dao(); record.setChangeOrigin(MemberChangeOrigin.SCHOOL_UNION_VERIFICATION.name()); - MemberApplyRecord applyRecord = dao.fetch(MemberApplyRecord.class, Cnd.where("userId", "=", record.getUserId()) + MemberChangeRecord applyRecord = dao.fetch(MemberChangeRecord.class, Cnd.where("userId", "=", record.getUserId()) .and("verificationProjectId", "=", record.getVerificationProjectId())); // 如果之前有变更,删除之前记录 if (Lang.isNotEmpty(applyRecord)) { @@ -271,7 +259,7 @@ public class MemberSchoolVerificationCheckController { .and("verificationProjectId", "=", record.getVerificationProjectId())); dao.clear(Sys_user_history.class, Cnd.where("recordId", "=", record.getId())); - memberManageService.compareMemberChangeInfoAndUpdateUser(record); + memberCommonService.compareChangeInfoAndUpdateMember(record); dao.update(MemberListVerificationUser.class, Chain.make("schoolUnionChecked", true).add("currentState", 2), @@ -289,13 +277,13 @@ public class MemberSchoolVerificationCheckController { @SLog(tag = "校工会管理-名单核对事项", type = "schoolUnionVerification", msg = "退回分工会无误提交") public Result doRollback(@Valid @Param("id") String id, @Valid @Param("rollbackReason") String rollbackReason){ - MemberVerificationBranchUnionFeedback feedback = memberManageService.dao().fetch(MemberVerificationBranchUnionFeedback.class, + MemberVerificationBranchUnionFeedback feedback = memberCommonService.dao().fetch(MemberVerificationBranchUnionFeedback.class, Cnd.where("id", "=", id)); feedback.setIsRollback(true); feedback.setRollbackReason(rollbackReason); feedback.setSchoolUnionSubmitNum(feedback.getSchoolUnionSubmitNum() + 1); feedback.setStatus("校工会退回"); - memberManageService.dao().update(feedback); + memberCommonService.dao().update(feedback); return Result.success(); } @@ -305,7 +293,7 @@ public class MemberSchoolVerificationCheckController { @Ok("void") @SaCheckPermission("member.schoolUnion.verification.check") public void doExportByPageDataForExcel(MemberListVerificationPageForm pageForm, HttpServletResponse response){ - MemberListVerificationProject project = memberManageService.dao().fetch(MemberListVerificationProject.class, pageForm.getVerificationProjectId()); + MemberListVerificationProject project = memberCommonService.dao().fetch(MemberListVerificationProject.class, pageForm.getVerificationProjectId()); List mapList = memberListVerificationService.getSchoolListVerificationUnion(pageForm); mapList.forEach(v-> { v.put("branchUnionSubmit" ,v.getBoolean("branchUnionSubmit") ? "已提交" : "未提交"); diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberApplyBranchApprovalInterceptor.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberApplyBranchApprovalInterceptor.java new file mode 100644 index 00000000..efd3e136 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberApplyBranchApprovalInterceptor.java @@ -0,0 +1,93 @@ +package com.budwk.app.zhgh.staffmanage.member.interceptor; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjectUtil; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.flow.constant.FlowConst; +import com.budwk.app.flow.engine.FlowInterceptor; +import com.budwk.app.flow.engine.core.Execution; +import com.budwk.app.flow.engine.core.ServiceContext; +import com.budwk.app.flow.enums.ProcessSubmitTypeEnum; +import com.budwk.app.sys.models.Sys_role; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.sys.models.Sys_user_role; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; +import com.budwk.app.zhgh.staffmanage.specialstaff.model.SpecialStaff; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.json.Json; + +/** + * @version 1.0 + * @Author zzr + * @name:MemberApplyBranchApprovalInterceptor + * @Date 2025/7/29 17:14 + * @注释 + */ +public class MemberApplyBranchApprovalInterceptor implements FlowInterceptor { + + @Override + public void intercept(Execution execution) { + System.out.println("member apply branch approval .................."); + String formDataStr = execution.getArgs().getStr(FlowConst.FORM_DATA); + MemberApplyRecord record = Json.fromJson(MemberApplyRecord.class, formDataStr); + + Dao dao = ServiceContext.find(Dao.class); + + // 如果是HMC,分工会接收,要判断更会关系有没有变化,然后再去改变用户数据 + boolean submitType = execution.getArgs().getInt("submitType").equals(ProcessSubmitTypeEnum.AGREE.getCode()); + if (submitType) { + if ("HMC".equals(record.getOrigin())) { + // 判断是否改变了工会关系 + View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", record.getUserId())); + + if (!ObjectUtil.equals(user.getUnionId(), record.getAllocationUnionId())) { + // 去判断特殊人员表里面有没有这些人,有的话先删除再增加 + if (dao.count(SpecialStaff.class, Cnd.where("userId", "=", record.getUserId())) > 0) { + dao.clear(SpecialStaff.class, Cnd.where("userId", "=", record.getUserId())); + user = dao.fetch(View_user.class, Cnd.where("id", "=", record.getUserId())); + } + + // 获取分配工会信息 + Sys_union union = dao.fetch(Sys_union.class, Cnd.where("id", "=", record.getAllocationUnionId())); + SpecialStaff staff = new SpecialStaff(); + staff.setUserId(record.getUserId()); + staff.setPersonnelRelationUnitId(user.getUnitId()); + staff.setPersonnelRelationUnitName(user.getUnitName()); + staff.setUnionRelationUnionId(union.getId()); + staff.setUnionRelationUnionName(union.getName()); + staff.setIsManyUnit(false); + staff.setSpecialStaffType("HMC_RELATION"); + dao.insert(staff); + } + + Sys_user sysUser = new Sys_user(); + BeanUtil.copyProperties(record, sysUser); + sysUser.setId(record.getUserId()); + sysUser.setMember(true); + // 这是HMC的 + sysUser.setPreparedBy("会员"); + dao.updateIgnoreNull(sysUser); + + // 还要设置会员角色 + Sys_role role = dao.fetch(Sys_role.class, Cnd.where(Sys_role::getCode, "=", RoleConstant.MEMBER.name())); + + int count = dao.count(Sys_user_role.class, Cnd.where("userId", "=", user.getId()).and("roleId", "=", role.getId())); + if (count == 0) { + Sys_user_role userRole = new Sys_user_role(); + userRole.setUserId(user.getId()); + userRole.setRoleId(role.getId()); + dao.insert(userRole); + } + + // 短信啊,TMD HMC,狗屎 + } else { + // 其他的高校,发短信给下一步(校工会)审核 + } + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberApplySaveInterceptor.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberApplySaveInterceptor.java new file mode 100644 index 00000000..84c8ead8 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberApplySaveInterceptor.java @@ -0,0 +1,47 @@ +package com.budwk.app.zhgh.staffmanage.member.interceptor; + +import com.budwk.app.flow.constant.FlowConst; +import com.budwk.app.flow.engine.FlowInterceptor; +import com.budwk.app.flow.engine.core.Execution; +import com.budwk.app.flow.engine.core.ServiceContext; +import com.budwk.app.flow.entity.ProcessInstance; +import com.budwk.app.web.commons.base.Globals; +import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.json.Json; + +/** + * @version 1.0 + * @Author zzr + * @name:MemberApplySaveInterceptor + * @Date 2025/7/28 16:39 + * @注释 + */ +public class MemberApplySaveInterceptor implements FlowInterceptor { + + @Override + public void intercept(Execution execution) { + System.out.println("member apply .................."); + String formDataStr = execution.getArgs().getStr(FlowConst.FORM_DATA); + // 设置流程变量 + if ("HMC".equals(Globals.SchoolCode)) { + execution.getArgs().set("origin", "HMC"); + } else { + execution.getArgs().set("origin", "OTHER"); + } + + MemberApplyRecord record = Json.fromJson(MemberApplyRecord.class, formDataStr); + + Dao dao = ServiceContext.find(Dao.class); + dao.insertOrUpdate(record); + + execution.getArgs().set(FlowConst.FORM_DATA, Json.toJson(record)); + + int instanceId = execution.getArgs().getInt(FlowConst.PROCESS_INSTANCE_ID_KEY); + dao.update(ProcessInstance.class, Chain.make("businessNo", record.getId()), Cnd.where(ProcessInstance::getId, "=", instanceId)); + + System.out.println(execution); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberApplySchoolApprovalInterceptor.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberApplySchoolApprovalInterceptor.java new file mode 100644 index 00000000..f2ecb869 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberApplySchoolApprovalInterceptor.java @@ -0,0 +1,53 @@ +package com.budwk.app.zhgh.staffmanage.member.interceptor; + +import cn.hutool.core.bean.BeanUtil; +import com.budwk.app.flow.constant.FlowConst; +import com.budwk.app.flow.engine.FlowInterceptor; +import com.budwk.app.flow.engine.core.Execution; +import com.budwk.app.flow.engine.core.ServiceContext; +import com.budwk.app.flow.enums.ProcessSubmitTypeEnum; +import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.json.Json; + +/** + * @version 1.0 + * @Author zzr + * @name:MemberApplySchoolApprovalInterceptor + * @Date 2025/7/29 15:34 + * @注释 + */ +public class MemberApplySchoolApprovalInterceptor implements FlowInterceptor { + + @Override + public void intercept(Execution execution) { + System.out.println("member apply school approval .................."); + String formDataStr = execution.getArgs().getStr(FlowConst.FORM_DATA); + MemberApplyRecord record = Json.fromJson(MemberApplyRecord.class, formDataStr); + String allocationUnionId = execution.getArgs().getStr(FlowConst.TASK_FORM_DATA_PREFIX + "allocation_unionId"); + + Dao dao = ServiceContext.find(Dao.class); + dao.update(MemberApplyRecord.class, Chain.make("allocationUnionId", allocationUnionId), + Cnd.where(MemberApplyRecord::getId, "=", record.getId())); + + // 判断如果是审核通过,并且不是HMC, 去修改用户表的基础数据 + boolean submitType = execution.getArgs().getInt("submitType").equals(ProcessSubmitTypeEnum.AGREE.getCode()); + if (submitType) { + if (!"HMC".equals(record.getOrigin())) { + Sys_user sysUser = new Sys_user(); + BeanUtil.copyProperties(record, sysUser); + sysUser.setId(record.getUserId()); + dao.updateIgnoreNull(sysUser); + // 正常的发送短信,审核通过 + } else { + // 发TMD短信 HMC,流程在流转到分工会接收环节 + } + } else { + // 没审核通过,发短信告知本人 + } + + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberChangeSaveInterceptor.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberChangeSaveInterceptor.java new file mode 100644 index 00000000..3d6629bb --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberChangeSaveInterceptor.java @@ -0,0 +1,68 @@ +package com.budwk.app.zhgh.staffmanage.member.interceptor; + +import cn.hutool.core.date.DateUtil; +import com.budwk.app.base.exception.BaseException; +import com.budwk.app.flow.constant.FlowConst; +import com.budwk.app.flow.engine.FlowInterceptor; +import com.budwk.app.flow.engine.core.Execution; +import com.budwk.app.flow.engine.core.ServiceContext; +import com.budwk.app.flow.entity.ProcessInstance; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin; +import com.budwk.app.zhgh.staffmanage.member.models.MemberChangeRecord; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.json.Json; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; + +import java.util.Date; +import java.util.List; + +/** + * @version 1.0 + * @Author zzr + * @name:MemberChangeSaveInterceptor + * @Date 2025/7/28 16:39 + * @注释 + */ +public class MemberChangeSaveInterceptor implements FlowInterceptor { + + @Override + public void intercept(Execution execution) { + System.out.println("member change .................."); + String formDataStr = execution.getArgs().getStr(FlowConst.FORM_DATA); + MemberChangeRecord record = Json.fromJson(MemberChangeRecord.class, formDataStr); + + Dao dao = ServiceContext.find(Dao.class); + MemberCommonService memberCommonService = ServiceContext.find(MemberCommonService.class); + + // 校验有没有发生变更 + List changeInfos = memberCommonService.getChangeInfos(record); + if (Lang.isEmpty(changeInfos)) { + throw new BaseException("未获取到异动数据"); + } + + View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", record.getUserId())); + // 比较有哪些变更类型 + List changeTypes = memberCommonService.compareChangeType(record, user); + + record.setChangeTypes(changeTypes); + record.setUserId(SecurityUtil.getUserId()); + // 变更来源 个人 + record.setChangeOrigin(MemberChangeOrigin.PERSONAL.name()); + + dao.insertOrUpdate(record); + + execution.getArgs().set(FlowConst.FORM_DATA, Json.toJson(record)); + + int instanceId = execution.getArgs().getInt(FlowConst.PROCESS_INSTANCE_ID_KEY); + dao.update(ProcessInstance.class, Chain.make("businessNo", record.getId()), Cnd.where(ProcessInstance::getId, "=", instanceId)); + + System.out.println(execution); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberChangeSchoolApprovalInterceptor.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberChangeSchoolApprovalInterceptor.java new file mode 100644 index 00000000..fee055f4 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/interceptor/MemberChangeSchoolApprovalInterceptor.java @@ -0,0 +1,37 @@ +package com.budwk.app.zhgh.staffmanage.member.interceptor; + +import com.budwk.app.flow.constant.FlowConst; +import com.budwk.app.flow.engine.FlowInterceptor; +import com.budwk.app.flow.engine.core.Execution; +import com.budwk.app.flow.engine.core.ServiceContext; +import com.budwk.app.flow.enums.ProcessSubmitTypeEnum; +import com.budwk.app.zhgh.staffmanage.member.models.MemberChangeRecord; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; +import org.nutz.json.Json; + +/** + * @version 1.0 + * @Author zzr + * @name:MemberChangeSchoolApprovalInterceptor + * @Date 2025/7/30 9:06 + * @注释 + */ +public class MemberChangeSchoolApprovalInterceptor implements FlowInterceptor { + + @Override + public void intercept(Execution execution) { + System.out.println("member change school approval .................."); + String formDataStr = execution.getArgs().getStr(FlowConst.FORM_DATA); + MemberChangeRecord record = Json.fromJson(MemberChangeRecord.class, formDataStr); + + MemberCommonService memberCommonService = ServiceContext.find(MemberCommonService.class); + // 是否审核通过 + boolean submitType = execution.getArgs().getInt("submitType").equals(ProcessSubmitTypeEnum.AGREE.getCode()); + // 审核通过后去修改用户表字段 + if (submitType) { + memberCommonService.compareChangeInfoAndUpdateMember(record); + } else { + // 没审核通过的操作 + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/models/MemberApplyRecord.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/models/MemberApplyRecord.java index dd355a59..d610ed2f 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/models/MemberApplyRecord.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/models/MemberApplyRecord.java @@ -52,6 +52,11 @@ public class MemberApplyRecord extends BaseModel { @Size(max = 100) private String loginname; + @Column + @Comment("出生日期") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String birthday; + @Column @Comment("单位id") @ColDefine(type = ColType.VARCHAR, width = 32) @@ -59,12 +64,6 @@ public class MemberApplyRecord extends BaseModel { @Size(max = 32) private String unitId; - @Column - @Comment("变更单位id") - @ColDefine(type = ColType.VARCHAR, width = 32) - @Size(max = 32) - private String changeUnitId; - @Column @Comment("单位名称") @ColDefine(type = ColType.VARCHAR, width = 200) @@ -79,12 +78,6 @@ public class MemberApplyRecord extends BaseModel { @Size(max = 32) private String unionId; - @Column - @Comment("变更工会id") - @ColDefine(type = ColType.VARCHAR, width = 32) - @Size(max = 32) - private String changeUnionId; - @Column @Comment("工会名称") @ColDefine(type = ColType.VARCHAR, width = 50) @@ -128,11 +121,10 @@ public class MemberApplyRecord extends BaseModel { private String education; @Column - @Comment("党政职务") + @Comment("职务") @ColDefine(type = ColType.VARCHAR, width = 50) - @NotBlank(message = "党政职务不能为空") @Size(max = 50) - private String governmentPosition; + private String position; @Column @Comment("在职状态") @@ -169,13 +161,6 @@ public class MemberApplyRecord extends BaseModel { @Size(max = 255) private String email; - @Column - @Comment("是否愿意加入大病互助基金会") - @ColDefine(type = ColType.BOOLEAN) - @Default(value = "0") - @NotNull(message = "愿意加入大病互助基金会不能为空") - private Boolean wantJoinLoveMutualAidAssociation; - @Column @Comment("会员状态") @ColDefine(type = ColType.BOOLEAN) @@ -188,6 +173,11 @@ public class MemberApplyRecord extends BaseModel { @Default(value = "0") private Boolean welfareMember; + @Column + @Comment("校区") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String campus; + @Column @Comment("家庭主要成员及其工作单位") @ColDefine(type = ColType.MYSQL_JSON) @@ -211,7 +201,7 @@ public class MemberApplyRecord extends BaseModel { @Column @Comment("变更类型") - @ColDefine(type = ColType.VARCHAR, width = 20) + @ColDefine(type = ColType.VARCHAR, width = 50) private String changeType; @Column @@ -231,20 +221,22 @@ public class MemberApplyRecord extends BaseModel { private Date applyDateTime; @Column - @Comment("名单事项核对Id") - @ColDefine(type = ColType.VARCHAR, width = 32) - private String verificationProjectId; - - private Boolean edit; + @Comment("分配的工会关系") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String allocationUnionId; @Column - @Comment("详细变更记录") - @ColDefine(type = ColType.TEXT) - private String changeInfos; - + @Comment("是否自愿加入工会") + @ColDefine(type = ColType.BOOLEAN) + private Boolean isVoluntary; @Column - @Comment("详细变更记录") - @ColDefine(type = ColType.TEXT) - private String remark; + @Comment("签字") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String sign; + + @Column + @Comment("来源,高校编码") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String origin; } diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/models/MemberChangeRecord.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/models/MemberChangeRecord.java new file mode 100644 index 00000000..059ea0c2 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/models/MemberChangeRecord.java @@ -0,0 +1,225 @@ +package com.budwk.app.zhgh.staffmanage.member.models; + +import cn.hutool.json.JSONObject; +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import javax.validation.constraints.Size; +import java.util.Date; +import java.util.List; + +/** + * 会员变更记录 + * + * @author: 1V + * @date: 2021/1/25 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +@Table("member_change_record") +@EqualsAndHashCode(callSuper = true) +public class MemberChangeRecord extends BaseModel { + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("用户id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Size(max = 32) + private String userId; + + @Column + @Comment("姓名") + @ColDefine(type = ColType.VARCHAR, width = 100) + @Size(max = 100) + private String username; + + @Column + @Comment("工号") + @ColDefine(type = ColType.VARCHAR, width = 100) + @Size(max = 100) + private String loginname; + + @Column + @Comment("单位id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Size(max = 32) + private String unitId; + + @Column + @Comment("单位名称") + @ColDefine(type = ColType.VARCHAR, width = 200) + @Size(max = 200) + private String unitName; + + @Column + @Comment("工会id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Size(max = 32) + private String unionId; + + @Column + @Comment("工会名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + @Size(max = 50) + private String unionName; + + @Column + @Comment("性别") + @ColDefine(type = ColType.VARCHAR, width = 10) + @Size(max = 10) + private String sex; + + @Column + @Comment("出生日期") + @ColDefine(type = ColType.VARCHAR, width = 10) + @Size(max = 10) + private String birthday; + + @Column + @Comment("证件号码") + @ColDefine(type = ColType.VARCHAR, width = 30) + @Size(max = 30) + private String idCard; + + @Column + @Comment("民族") + @ColDefine(type = ColType.VARCHAR, width = 20) + @Size(max = 20) + private String nation; + + @Column + @Comment("政治面貌") + @ColDefine(type = ColType.VARCHAR, width = 100) + @Size(max = 100) + private String political; + + @Column + @Comment("学历") + @ColDefine(type = ColType.VARCHAR, width = 20) + @Size(max = 20) + private String education; + + @Column + @Comment("学位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String academicDegree; + + @Column + @Comment("党政职务") + @ColDefine(type = ColType.VARCHAR, width = 50) + @Size(max = 50) + private String position; + + @Column + @Comment("在职状态") + @ColDefine(type = ColType.VARCHAR, width = 50) + @Size(max = 50) + private String userState; + + @Column + @Comment("人事编制") + @ColDefine(type = ColType.VARCHAR, width = 50) + @Size(max = 50) + private String preparedBy; + + @Column + @Comment("人员类别") + @ColDefine(type = ColType.VARCHAR, width = 50) + @Size(max = 50) + private String personType; + + @Column + @Comment("手机号码") + @ColDefine(type = ColType.VARCHAR, width = 32) + @Size(max = 32) + private String mobile; + + @Column + @Comment("电子邮箱") + @ColDefine(type = ColType.VARCHAR, width = 255) + @Size(max = 255) + private String email; + + @Column + @Comment("会员状态") + @ColDefine(type = ColType.BOOLEAN) + @Default(value = "0") + private Boolean member; + + @Column + @Comment("福利会员状态") + @ColDefine(type = ColType.BOOLEAN) + @Default(value = "0") + private Boolean welfareMember; + + @Column + @Comment("校区") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String campus; + + @Column + @Comment("退休日期") + @ColDefine(type = ColType.DATE) + private Date retireDate; + + @Column + @Comment("家庭主要成员及其工作单位") + @ColDefine(type = ColType.MYSQL_JSON) + private List families; + + @Column + @Comment("个人简况") + @ColDefine(type = ColType.VARCHAR, customType = "text") + private String personalData; + + @Column + @Comment("备注") + @ColDefine(type = ColType.VARCHAR, width = 255) + private String notes; + + @Column + @Comment("变更类型") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String changeType; + + @Column + @Comment("变更类型集合") + @ColDefine(type = ColType.MYSQL_JSON) + private List changeTypes; + + @Column + @Comment("变更来源") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String changeOrigin; + + @Column + @Comment("申请时间") + @ColDefine(type = ColType.DATETIME) + @PrevInsert(now = true) + private Date applyDateTime; + + @Column + @Comment("福利享受截止日期") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String welfareStopDate; + + @Column + @Comment("名单事项核对Id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String verificationProjectId; + + @Comment("备注(南邮的)") + @ColDefine(type = ColType.TEXT) + private String remark; + + private Boolean edit; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/param/pageform/MemberApplyPageForm.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/param/pageform/MemberApplyPageForm.java index b52455e3..56ebdc47 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/param/pageform/MemberApplyPageForm.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/param/pageform/MemberApplyPageForm.java @@ -35,14 +35,14 @@ public class MemberApplyPageForm extends PageForm { } if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { SqlExpressionGroup seg = new SqlExpressionGroup(); - seg.or("vu.loginname", "like", "%" + pageForm.getSearchKeyword() + "%"); - seg.or("vu.username", "like", "%" + pageForm.getSearchKeyword() + "%"); + seg.or("info.loginName", "like", "%" + pageForm.getSearchKeyword() + "%"); + seg.or("info.username", "like", "%" + pageForm.getSearchKeyword() + "%"); cnd.and(seg); } - cnd.andEX("vu.unionId","=",pageForm.getUnionId()); - cnd.andEX("vu.unitId","=",pageForm.getUnitId()); - cnd.andEX("vu.userState","=",pageForm.getUserState()); - cnd.andEX("vu.personType","=",pageForm.getPersonType()); - cnd.andEX("vu.preparedBy","=",pageForm.getPreparedBy()); + cnd.andEX("info.unionId","=",pageForm.getUnionId()); + cnd.andEX("info.unitId","=",pageForm.getUnitId()); + cnd.andEX("info.userState","=",pageForm.getUserState()); + cnd.andEX("info.personType","=",pageForm.getPersonType()); + cnd.andEX("info.preparedBy","=",pageForm.getPreparedBy()); } } diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/param/pageform/MemberChangePageForm.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/param/pageform/MemberChangePageForm.java new file mode 100644 index 00000000..0522a4c0 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/param/pageform/MemberChangePageForm.java @@ -0,0 +1,62 @@ +package com.budwk.app.zhgh.staffmanage.member.param.pageform; + +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.zhgh.staffmanage.member.models.MemberChangeRecord; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.Cnd; +import org.nutz.dao.util.cri.SqlExpressionGroup; + +/** + * @version 1.0 + * @Author zzr + * @name:MemberChangePageForm + * @Date 2025/2/14 14:05 + * @注释 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class MemberChangePageForm extends PageForm { + + // 工会id + @ApiModelProperty("工会id") + private String unionId; + + // 单位id + @ApiModelProperty("单位id") + private String unitId; + + // 在职状态 + @ApiModelProperty("在职状态") + private String userState; + + // 在职状态 + @ApiModelProperty("编制类型") + private String preparedBy; + + // 人员类型 + @ApiModelProperty("人员类型") + private String personType; + + + public void buildSearch(Cnd cnd, String prefix){ + if (cnd == null) { + cnd = Cnd.NEW(); + } + + if (StrUtil.isNotBlank(this.getSearchKeyword())) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.orLike(prefix + "username", this.getSearchKeyword()); + seg.orLike(prefix + "loginname", this.getSearchKeyword()); + cnd.and(seg); + } + + cnd.andEX(prefix + "unionId", "=", this.getUnionId()); + cnd.andEX(prefix + "unitId", "=", this.getUnitId()); + cnd.andEX(prefix + "userState", "=", this.getUserState()); + cnd.andEX(prefix + "preparedBy", "=", this.getPreparedBy()); + cnd.andEX(prefix + "personType", "=", this.getPersonType()); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/param/pageform/MemberManagePageForm.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/param/pageform/MemberManagePageForm.java index 5f861b57..8f061be1 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/param/pageform/MemberManagePageForm.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/param/pageform/MemberManagePageForm.java @@ -64,7 +64,11 @@ public class MemberManagePageForm extends PageForm { cnd = Cnd.NEW(); } if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { - cnd.and("u.unionId", "=", SecurityUtil.getUnionId()); + if (AuthUtil.hasRoleOr(RoleConstant.BRANCH_UNION_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_OPERATOR.name())) { + cnd.and("u.unionId", "=", SecurityUtil.getUnionId()); + } else { + cnd.and("record.userId", "=", SecurityUtil.getUserId()); + } } else { cnd.andEX("u.unionId", "=", pageForm.getUnionId()); } diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/MemberManageService.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/MemberCommonService.java similarity index 55% rename from src/main/java/com/budwk/app/zhgh/staffmanage/member/service/MemberManageService.java rename to src/main/java/com/budwk/app/zhgh/staffmanage/member/service/MemberCommonService.java index e11a2095..614adce2 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/MemberManageService.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/MemberCommonService.java @@ -3,15 +3,15 @@ package com.budwk.app.zhgh.staffmanage.member.service; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.service.BaseService; import com.budwk.app.sys.models.Sys_user; -import com.budwk.app.sys.models.Sys_user_history; +import com.budwk.app.sys.views.View_user; import com.budwk.app.zhgh.staffmanage.member.models.MemberApplyRecord; +import com.budwk.app.zhgh.staffmanage.member.models.MemberChangeRecord; import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberManagePageForm; import org.nutz.dao.sql.Sql; import org.nutz.lang.util.NutMap; import java.util.List; import java.util.Map; -import java.util.Set; /** * @version 1.0 @@ -20,7 +20,7 @@ import java.util.Set; * @Date 2024/8/6 10:42 * @注释 */ -public interface MemberManageService extends BaseService { +public interface MemberCommonService extends BaseService { /** * 多条件查询Sql @@ -43,43 +43,47 @@ public interface MemberManageService extends BaseService { */ Pagination memberHistoryRecords(MemberManagePageForm pageForm); - /** - * 根据用户id获取会员变更信息(时间线),所有的变更记录 - * @param userId 用户id - * @return List - */ - List getMemberChangeInfoByUserId(String userId); /** - * 会员变更信息对比 - * @param current 当前数据 - * @param previous 上一条数据 + * 获取可变更字段 * @return */ - List compareChange(Sys_user_history current, Sys_user_history previous, Set allowChangeFieldNames, Map dictMap); - - List compareMemberChangeInfo(Sys_user_history history); + NutMap getDictAllowChangeFields(); /** - * 校验是否有变更 - * @param record - */ - List compareMemberChangeInfo(MemberApplyRecord record); - - /** - * 获取变更类型 - * @param changeList 变更记录 + * 获取变更详情 + * @param recordId 变更记录id * @return */ - List compareMemberChangeType(List changeList, MemberApplyRecord record); + List getChangeInfos(String recordId); + List getChangeInfos(MemberChangeRecord record); /** - * 会员变更信息对比 并更新数据 + * 比较有哪些变更类型 + * @param record + * @param user + * @return + */ + List compareChangeType(MemberChangeRecord record, View_user user); + + /** + * 存储比较变更信息并更新会员信息 + * @param recordId + */ + void compareChangeInfoAndUpdateMember(String recordId); + /** + * 存储比较变更信息并更新会员信息 * @param record */ - void compareMemberChangeInfoAndUpdateUser(MemberApplyRecord record); + void compareChangeInfoAndUpdateMember(MemberChangeRecord record); + /** + * 获取会员的变更信息 + * @param userId + * @return + */ + List getAllChangeInfo(String userId); /** * 比较两个对象,并记录变更的字段工具 @@ -90,12 +94,4 @@ public interface MemberManageService extends BaseService { * @param changeList 变更集合 */ void extractChange(NutMap newMap, NutMap sourceMap, String fieldName, Map fieldsMap, List changeList); - - /** - * 获取会员变更信息,memberApplyRecord表中名单核对事项人员与sys_user表中人员对比 - * @param userId - * @param verificationProjectId - * @return - */ - List getLastTimeMemberChangeInfoByUserId(String userId, String verificationProjectId); } diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberBranchUnionManageServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberBranchUnionManageServiceImpl.java index ee6cb0e4..d2437646 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberBranchUnionManageServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberBranchUnionManageServiceImpl.java @@ -42,8 +42,8 @@ public class MemberBranchUnionManageServiceImpl extends BaseServiceImpl implements MemberManageService { +public class MemberManageServiceImpl extends BaseServiceImpl implements MemberCommonService { @Inject private SysDictService sysDictService; + @Inject + private SysRoleService sysRoleService; + @Inject + private SysUserService sysUserService; public MemberManageServiceImpl(Dao dao) { super(dao); @@ -83,7 +90,6 @@ public class MemberManageServiceImpl extends BaseServiceImpl implement u.personType, u.welfareMember, u.isModelWorker, - u.wantJoinLoveMutualAidAssociation, his.id hisId, his.changeTypes, his.changeTime @@ -96,7 +102,8 @@ public class MemberManageServiceImpl extends BaseServiceImpl implement MemberManagePageForm.buildSearch(cnd, pageForm); cnd.desc("his.changeTime"); cnd.groupBy("u.id"); - if ("branchUnion".equals(queryType)) { + + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { cnd.and("u.unionId", "=", SecurityUtil.getUnionId()); } sql.setCondition(cnd); @@ -192,316 +199,281 @@ public class MemberManageServiceImpl extends BaseServiceImpl implement cnd.desc("his.changeTime"); } - if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name(), RoleConstant.SCHOOL_UNION_MEMBER_ADMIN.name())) { cnd.andEX("his.unionId", "=", SecurityUtil.getUnionId()); } sql.setCondition(cnd); return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); } - /** - * 根据用户id获取用户变更信息 - * - * @param userId 用户id - * @return - */ + @Override - public List getMemberChangeInfoByUserId(String userId) { - Sys_user user = dao().fetch(Sys_user.class, userId); - Sys_user_history history = new Sys_user_history(); - //获取当前用户信息 - BeanUtil.copyProperties(user, history); - history.setChangeTime(new Date()); - //获取用户变更信息 - List userHistories = dao().query(Sys_user_history.class, Cnd.where("loginname", "=", user.getLoginname())); - userHistories.add(history); - //按时间排序 - CollectionUtil.sort(userHistories, Comparator.comparing(Sys_user_history::getChangeTime).reversed()); - - //获取允许变更的字段 - List dictList = sysDictService.getSubListByCode("MEMBER_ALLOW_CHANGES_FIELD"); + public NutMap getDictAllowChangeFields() { + //获取可变更字段 + List dictList = sysDictService.getSubListByCode("ALLOW_CHANGE_FIELDS"); Set allowChangeFieldNames = dictList.stream().map(Sys_dict::getCode).collect(Collectors.toSet()); + allowChangeFieldNames.add("member"); Map dictMap = dictList.stream().collect(Collectors.toMap(Sys_dict::getCode, Sys_dict::getName)); - - List resultList = new ArrayList<>(); - for (int i = 1; i < userHistories.size(); i++) { - Sys_user_history current = userHistories.get(i); - Sys_user_history previous = userHistories.get(i - 1); - NutMap nutMap = compareAndRecordChange(current, previous, allowChangeFieldNames, dictMap); - resultList.add(nutMap); - } - return resultList; + dictMap.put("member", "会员状态"); + return NutMap.NEW().addv("allowChangeFieldNames", allowChangeFieldNames).addv("dictMap", dictMap); } - - /** - * 比较两个对象,并记录变更的字段 - * - * @param current 当前数据 - * @param previous 上一次的数据 - * @param allowChangeFieldNames 允许变更的字段名 - * @param dictMap 字典数据 - * @return NutMap - */ - public NutMap compareAndRecordChange(Sys_user_history current, Sys_user_history previous, Set allowChangeFieldNames, Map dictMap) { - NutMap nutMap = NutMap.NEW(); - if (StrUtil.isNotBlank(current.getChangeOrigin())) { - String title = MemberChangeOrigin.valueOf(MemberChangeOrigin.class , current.getChangeOrigin()).changeOriginName; - nutMap.put("title", title + "(" + DateUtil.format(current.getChangeTime(), "yyyy-MM-dd HH:mm:ss") + ")"); + @Override + public List getChangeInfos(String recordId) { + Sys_user_history history = dao().fetch(Sys_user_history.class, Cnd.where("recordId", "=", recordId)); + if (Lang.isNotEmpty(history)) { + return history.getChangeInfos(); } else { - nutMap.put("title", DateUtil.format(current.getChangeTime(), "yyyy-MM-dd HH:mm:ss")); + MemberChangeRecord record = dao().fetch(MemberChangeRecord.class, recordId); + return getChangeInfos(record); } - nutMap.put("remark", current.getRemark()); - - nutMap.put("changeTime", DateUtil.format(current.getChangeTime(), "yyyy-MM-dd HH:mm:ss")); - List changeList = new ArrayList<>(); - - NutMap currentMap = Lang.obj2nutmap(current); - NutMap previousMap = Lang.obj2nutmap(previous); - - for (String fieldName : allowChangeFieldNames) { - extractChange(currentMap, previousMap, fieldName, dictMap, changeList); - } - nutMap.put("changeList", changeList); - return nutMap; } - - /** - * 比较两个对象,并记录变更的字段 - * - * @param current 当前数据 - * @param previous 上一次的数据 - * @param allowChangeFieldNames 允许变更的字段名 - * @param dictMap 字典数据 - * @return NutMap - */ @Override - public List compareChange(Sys_user_history current, Sys_user_history previous, Set allowChangeFieldNames, Map dictMap) { - List changeList = new ArrayList<>(); - NutMap currentMap = Lang.obj2nutmap(current); - NutMap previousMap = Lang.obj2nutmap(previous); + public List getChangeInfos(MemberChangeRecord record) { + View_user info = dao().fetch(View_user.class, Cnd.where("id", "=", record.getUserId())); - for (String fieldName : allowChangeFieldNames) { - extractChange(currentMap, previousMap, fieldName, dictMap, changeList); - } - return changeList; - } - - - /** - * 校验是否有变更 - * @param - */ - @Override - public List compareMemberChangeInfo(Sys_user_history history) { - List infos = history.getChangeInfos(); - if (ObjectUtil.isEmpty(infos)) { - throw new BaseException("获取变更记录失败"); - } - return infos; - } - - /** - * 校验是否有变更 - * @param record - */ - @Override - public List compareMemberChangeInfo(MemberApplyRecord record) { - if (ObjectUtil.isEmpty(record) || ObjectUtil.isEmpty(record.getLoginname())) { - throw new BaseException("未获取到变更记录"); - } - - NutMap previousMap = NutMap.NEW(); - - View_user user = dao().fetch(View_user.class, Cnd.where("loginname", "=", record.getLoginname())); - previousMap = Lang.obj2nutmap(user); - - //获取允许变更的字段 - List dictList = sysDictService.getSubListByCode("MEMBER_ALLOW_CHANGES_FIELD"); - Set allowChangeFieldNames = dictList.stream().map(Sys_dict::getCode).collect(Collectors.toSet()); - Map dictMap = dictList.stream().collect(Collectors.toMap(Sys_dict::getCode, Sys_dict::getName)); + NutMap map = getDictAllowChangeFields(); + Set allowChangeFieldNames = map.getAs("allowChangeFieldNames", Set.class); + Map dictMap = map.getAs("dictMap", Map.class); + // 新数据 + NutMap newMap = Lang.obj2nutmap(record); + // 原数据 + NutMap sourceMap = Lang.obj2nutmap(info); List changeList = new ArrayList<>(); - NutMap currentMap = Lang.obj2nutmap(record); - for (String fieldName : allowChangeFieldNames) { - extractChange(currentMap, previousMap, fieldName, dictMap, changeList); - } - if (Lang.isEmpty(changeList)) { - throw new BaseException("未获取到变更数据,请核对是否修改了数据"); + extractChange(newMap, sourceMap, fieldName, dictMap, changeList); } return changeList; } @Override - public List compareMemberChangeType(List changeList, MemberApplyRecord record) { - if (Lang.isEmpty(changeList)) { - return null; - } + public List compareChangeType(MemberChangeRecord record, View_user user) { List changeTypes = new ArrayList<>(); - // 有单位发生变化的记录数据 - long unitChangeCount = changeList.stream().filter(item -> item != null && "unitId".equals(item.get("fieldName"))).count(); - if (unitChangeCount > 0) { - // 有单位的变化,表明是单位变更 - changeTypes.add(MemberChangeType.UNIT_CHANGE.name()); - // 如果有非单位变更,表明是基本信息变更 - long nonUnitChangeCount = changeList.size() - unitChangeCount; - if (nonUnitChangeCount > 0) { - changeTypes.add(MemberChangeType.BASIC_CHANGE.name()); + changeTypes.add(MemberChangeType.BASIC_CHANGE.name()); + if (!ObjectUtil.equals(user.getUserState(), record.getUserState())) { + List list = Arrays.stream(MemberChangeType.values()) + .filter(v -> v.getChangeTypeName().equals(record.getUserState())).toList(); + if (Lang.isNotEmpty(list)) { + changeTypes.add(list.get(0).name()); } - } else { - // 没有单位的变化,表明是基本信息变更 - changeTypes.add(MemberChangeType.BASIC_CHANGE.name()); } - - // record中是否存在前端传递过来的变更状态,(入会/退会) - String changeType = record.getChangeType(); - if (StrUtil.isNotBlank(changeType)) { - changeTypes.add(changeType); + if (!ObjectUtil.equals(user.getMember() == 1, record.getMember())){ + if (record.getMember()) { + changeTypes.add(MemberChangeType.RESTORE.name()); + } else { + changeTypes.add(MemberChangeType.WITHDRAWAL.name()); + } + } + if (!ObjectUtil.equals(user.getUnitId(), record.getUnitId())) { + changeTypes.add(MemberChangeType.UNIT_CHANGE.name()); + } + if (!ObjectUtil.equals(user.getUnionId(), record.getUnionId())) { + changeTypes.add(MemberChangeType.UNION_CHANGE.name()); } - return changeTypes; } - /** - * 比较会员信息变更记录,并保存历史数据 - * - * @param record 传递的记录 - * @return - */ - @Aop(TransAop.READ_COMMITTED) + @Override - public void compareMemberChangeInfoAndUpdateUser(MemberApplyRecord record) { - List changeList = compareMemberChangeInfo(record); + public void compareChangeInfoAndUpdateMember(String recordId) { + MemberChangeRecord record = dao().fetch(MemberChangeRecord.class, recordId); + compareChangeInfoAndUpdateMember(record); + } - View_user user = dao().fetch(View_user.class, Cnd.where("loginname", "=", record.getLoginname())); + @Override + public void compareChangeInfoAndUpdateMember(MemberChangeRecord record) { + List changeList = getChangeInfos(record); + + // 如果有工会关系人员,这个user用来存储数据 + View_user user = dao().fetch(View_user.class, Cnd.where("id", "=", record.getUserId())); + // 获取会员信息,用于存储变更记录 + Sys_user info = dao().fetch(Sys_user.class, Cnd.where("id", "=", record.getUserId())); + String userId = info.getId(); Sys_user_history history = new Sys_user_history(); - // 存储变更记录 - if (ObjectUtil.isNotEmpty(changeList)) { - // 将当前的用户数据(user)记录成历史数据 - BeanUtil.copyProperties(user, history); - - if (Lang.isNotEmpty(record.getChangeTypes())) { - history.setChangeTypes(record.getChangeTypes()); - } else { - List changeTypes = this.compareMemberChangeType(changeList, record); - history.setChangeTypes(changeTypes); - } + if (Lang.isNotEmpty(changeList)) { + BeanUtil.copyProperties(info, history); } - if (ObjectUtil.isNotEmpty(history) && ObjectUtil.isNotEmpty(history.getLoginname())) { - Date nowDate = new Date(); + if (Lang.isNotEmpty(history)) { history.setRecordId(record.getId()); - history.setChangeTime(nowDate); - history.setUnionId(user.getUnionId()); - history.setUnionName(user.getUnionName()); - history.setChangeOrigin(StrUtil.isNotBlank(record.getChangeOrigin()) ? record.getChangeOrigin() : MemberChangeOrigin.SCHOOL_UNION.name()); - history.setChangeReason(record.getNotes()); - history.setRemark(record.getRemark()); - // 到此,表明审核通过,需要存储历史数据,并修改用户数据 - Chain chain = Chain.make("unitPath", null); + history.setChangeTime(DateUtil.date()); + history.setChangeTypes(record.getChangeTypes()); + history.setChangeOrigin(record.getChangeOrigin()); - changeList.forEach(v -> { - if ("unitId".equals(v.getString("fieldName"))) { - chain.add(v.getString("fieldName"), record.getUnitId()); - } else { - chain.add(v.getString("fieldName"), v.getString("newValue")); - } - }); - chain.add("member", record.getMember()); - chain.add("welfareMember", record.getWelfareMember()); - - Sys_role memberRole = dao().fetch(Sys_role.class, Cnd.where("`code`", "=", "MEMBER")); - dao().clear(Sys_user_role.class, Cnd.where("userId", "=", user.getId()).and("roleId","=", memberRole.getId())); + // 获取会员角色,加入或退出会员组别,写了之后用处不大,注释了,暂且保留,想优化就把下面注释打开,305行与304-348行取消注释 +// Sys_role role = sysRoleService.getByCode(RoleConstant.MEMBER); + // 加入会员 if (record.getMember()) { - Sys_user_role userRole = new Sys_user_role(); - userRole.setRoleId(memberRole.getId()); - userRole.setUserId(user.getId()); - dao().insert(userRole); +// int activityCount = dao().count(ActivityUserScope.class, Cnd.where("userId", "=", userId).and("groupId", "=", 1)); +// int memberCount = dao().count(Sys_user_role.class, Cnd.where("userId", "=", userId).and("roleId", "=", role.getId())); +// if (activityCount <= 0) { +// // 取消或加入会员组别 +// if (record.getIsJoinActivityMemberScope() != null && record.getIsJoinActivityMemberScope()) { +// ActivityUserScope scope = new ActivityUserScope(); +// scope.setUserId(userId); +// scope.setGroupId(1); +// scope.setGroupName("工会会员"); +// dao().insert(scope); +// } +// } +// if (memberCount <= 0) { +// Sys_user_role userRole = new Sys_user_role(); +// userRole.setUserId(userId); +// userRole.setRoleId(role.getId()); +// dao().insert(userRole); +// } +// // 杭医特有,其他学校请删除 +// record.setPreparedBy("会员"); +// } else { +// if (record.getIsExitActivityMemberScope() != null && record.getIsExitActivityMemberScope()) { +// dao().clear(ActivityUserScope.class, Cnd.where("userId", "=", userId).and("groupId", "=", 1)); +// } +// dao().clear(Sys_user_role.class, Cnd.where("userId", "=", userId).and("roleId", "=", Roles.MEMBER)); +// // 杭医特有,其他学校请删除 +// record.setPreparedBy("教职工"); +// } +// +// // 加入福利会员 是否加入福利项目 +// if (record.getWelfareMember() && record.getIsJoinWelfareProject() != null && record.getIsJoinWelfareProject()) { +// WelfareList welfareList = new WelfareList(); +// welfareList.setId(R.UU32()); +// welfareList.setProjectId(record.getWelfareProjectId()); +// welfareList.setUserId(userId); +// welfareList.setIsReceive(false); +// welfareList.setIsAutoSelect(false); +// welfareList.setUserState(record.getUserState()); +// welfareList.setPersonType(record.getPersonType()); +// welfareList.setWelfareUnitId(record.getUnitId()); +// dao().insert(welfareList); } - AtomicBoolean isRetire = new AtomicBoolean(false); - String changeInfos = changeList.stream().map(v -> { - if ("userState".equals(v.getString("fieldName")) && "退休".equals(v.getString("newValue"))) { - isRetire.set(true); - chain.add("retireDate", DateUtil.date()); - } - return "(变更字段:" + v.getString("name") + ",变更前:" + HtmlUtil.cleanHtmlTag(v.getString("value","")) + ",变更后:" + HtmlUtil.cleanHtmlTag(v.getString("newValue","")) + ")"; - }).collect(Collectors.joining(";")); - record.setChangeInfos(changeInfos); + // 到此,表明审核通过,需要存储历史数据,并修改用户数据 + BeanUtil.copyProperties(record, info); + info.setId(userId); + // 如果有单位变更,则需要记录单位关系 + if (record.getChangeTypes().contains(MemberChangeType.UNIT_CHANGE.name())) { + info.setUnitId(record.getUnitId()); + } + + // 如果工会发生变更了,就是工会关系变更,记录到特殊人员表中 + if (record.getChangeTypes().contains(MemberChangeType.UNION_CHANGE.name())) { + if (dao().count(SpecialStaff.class, Cnd.where("userId", "=", record.getUserId())) > 0) { + dao().clear(SpecialStaff.class, Cnd.where("userId", "=", record.getUserId())); + user = dao().fetch(View_user.class, Cnd.where("id", "=", record.getUserId())); + } + + if (!ObjectUtil.equals(user.getUnionId(), record.getUnionId())) { + Sys_union union = dao().fetch(Sys_union.class, Cnd.where("id", "=", record.getUnionId())); + // 记录工会关系变更的数据 + NutMap map = NutMap.NEW(); + map.put("field", "unionId"); + map.put("fieldName", "工会"); + map.put("sourceValue", record.getUnionName()); + map.put("newValue", union.getName()); + changeList.add(map); + + SpecialStaff staff = new SpecialStaff(); + staff.setUserId(userId); + staff.setPersonnelRelationUnitId(user.getUnitId()); + staff.setPersonnelRelationUnitName(user.getUnitName()); + staff.setUnionRelationUnionId(union.getId()); + staff.setUnionRelationUnionName(union.getName()); + staff.setIsManyUnit(false); + staff.setSpecialStaffType("HMC_RELATION"); + dao().insert(staff); + } + } + + // 如果有工会关系变更,也需要记录变更了什么工会 history.setChangeInfos(changeList); + String changeInfos = changeList.stream().map(v -> { + return v.getString("fieldName") + ":" + HtmlUtil.cleanHtmlTag(v.getString("sourceValue")) + "->" + HtmlUtil.cleanHtmlTag(v.getString("newValue")); + }).collect(Collectors.joining(";")); history.setChangeInfosStr(changeInfos); + dao().updateIgnoreNull(info); dao().insert(history); - dao().update(Sys_user.class, chain, Cnd.where("loginname", "=", record.getLoginname())); - } else { - throw new BaseException("未获取到变更数据,请核对是否修改了数据"); + sysUserService.deleteCache(info.getId()); } } - @Override - public List getLastTimeMemberChangeInfoByUserId(String userId, String verificationProjectId) { - MemberApplyRecord record = dao().fetch(MemberApplyRecord.class, Cnd.where("userId", "=", userId) - .and("verificationProjectId","=",verificationProjectId)); - if (ObjectUtil.isEmpty(record) || ObjectUtil.isEmpty(record.getLoginname())) { - throw new NullPointerException("数据获取失败"); + public List getAllChangeInfo(String userId) { + List resultMapList = new ArrayList<>(); + + Sql sql = Sqls.fetchString(Sqls.create("select loginname from sys_user where id = @id").setParam("id", userId).toString()); + dao().execute(sql); + String loginName = sql.getString(); + + MemberChangeRecord record = dao().fetch(MemberChangeRecord.class, Cnd.where("userId", "=", userId).desc("applyDateTime")); + + List historyList = dao().query(Sys_user_history.class, Cnd.where("loginname", "=", loginName) + .and("changeInfos", "is not", null).desc("changeTime")); + + List recordList = historyList.stream().map(Sys_user_history::getRecordId).toList(); + + if (Lang.isNotEmpty(record) && !recordList.contains(record.getId())) { + NutMap map = NutMap.NEW(); + List changeInfos = getChangeInfos(record.getId()); + map.put("changeInfos", changeInfos); + map.put("timestamp", DateUtil.format(record.getApplyDateTime(), "yyyy-MM-dd HH:mm:ss")); + map.put("changeOriginName", MemberChangeOrigin.valueOf(MemberChangeOrigin.class, record.getChangeOrigin()).changeOriginName); + resultMapList.add(map); } - View_user user = dao().fetch(View_user.class, Cnd.where("loginname", "=", record.getLoginname())); - - //获取允许变更的字段 - List dictList = sysDictService.getSubListByCode("MEMBER_ALLOW_CHANGES_FIELD"); - Set allowChangeFieldNames = dictList.stream().map(Sys_dict::getCode).collect(Collectors.toSet()); - Map dictMap = dictList.stream().collect(Collectors.toMap(Sys_dict::getCode, Sys_dict::getName)); - - List changeList = new ArrayList<>(); - - NutMap currentMap = Lang.obj2nutmap(record); - NutMap previousMap = Lang.obj2nutmap(user); - - for (String fieldName : allowChangeFieldNames) { - extractChange(currentMap, previousMap, fieldName, dictMap, changeList); + for (Sys_user_history history : historyList) { + NutMap map = NutMap.NEW(); + List changeInfos = history.getChangeInfos(); + map.put("changeInfos", changeInfos); + map.put("timestamp", DateUtil.format(history.getChangeTime(), "yyyy-MM-dd HH:mm:ss")); + map.put("changeOriginName", MemberChangeOrigin.valueOf(MemberChangeOrigin.class, history.getChangeOrigin()).changeOriginName); + resultMapList.add(map); } - return changeList; + return resultMapList; } - - /** * 比较两个对象,并记录变更的字段工具 * - * @param current 当前数据 - * @param previous 上一次的数据 - * @param dictMap 字典数据 + * @param newMap 新数据 + * @param sourceMap 原数据 + * @param fieldsMap 变更字段 * @param changeList 变更集合 */ @Override - public void extractChange(NutMap current, NutMap previous, String fieldName, Map dictMap, List changeList) { + public void extractChange(NutMap newMap, NutMap sourceMap, String fieldName, Map fieldsMap, List changeList) { try { - Object currentValue = this.booleanVerification(current.get(fieldName)); - Object previousValue = this.booleanVerification(previous.get(fieldName)); + Object currentValue = this.booleanVerification(newMap.get(fieldName)); + Object previousValue = this.booleanVerification(sourceMap.get(fieldName)); + + if ("unitId".equals(fieldName)) { + currentValue = (newMap.get(fieldName) == null ? this.booleanVerification(newMap.get("unitId")) : currentValue); + previousValue = (sourceMap.get(fieldName) == null ? this.booleanVerification(sourceMap.get("unitId")) : previousValue); + } if (!ObjectUtil.equals(currentValue, previousValue)) { - String name = dictMap.getOrDefault(fieldName, fieldName); - if ("unitId".equals(fieldName)) { - List unitList = dao().query(Sys_unit.class, Cnd.where("id", "in", List.of(previousValue, currentValue))); + String name = fieldsMap.getOrDefault(fieldName, fieldName); + if ("unitId".equals(fieldName) || "unitid".equals(fieldName)) { + List unitList = dao().query(Sys_unit.class, + Cnd.where("id", "in", List.of(previousValue, currentValue))); Object finalPreviousValue = previousValue; - previousValue = unitList.stream().filter(v->v.getId().equals(String.valueOf(finalPreviousValue))).findFirst().orElse(new Sys_unit()).getName(); + previousValue = unitList.stream().filter(v -> v.getId().equals(String.valueOf(finalPreviousValue))) + .findFirst().orElse(new Sys_unit()).getName(); Object finalCurrentValue = currentValue; - currentValue = unitList.stream().filter(v->v.getId().equals(String.valueOf(finalCurrentValue))).findFirst().orElse(new Sys_unit()).getName(); - } else if ("families".equals(fieldName)) { - return; + currentValue = unitList.stream().filter(v -> v.getId().equals(String.valueOf(finalCurrentValue))) + .findFirst().orElse(new Sys_unit()).getName(); } changeList.add(NutMap.NEW() - .setv("fieldName", fieldName) - .setv("name", name) - .setv("value", previousValue) + .setv("field", fieldName) + .setv("fieldName", name) + .setv("sourceValue", previousValue) .setv("newValue", currentValue)); } + } catch (Exception e) { log.error("Error while extracting and comparing changes for field: {}", fieldName, e); } diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberSchoolUnionManageServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberSchoolUnionManageServiceImpl.java index 2e6d5d7a..6d6a23c1 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberSchoolUnionManageServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberSchoolUnionManageServiceImpl.java @@ -40,7 +40,7 @@ public class MemberSchoolUnionManageServiceImpl extends BaseServiceImpl changeTypes; private String changeOrigin; private Date applyDateTime; - private String verificationProjectId; + private String allocationUnionId; } diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentChartSummaryController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentChartSummaryController.java new file mode 100644 index 00000000..a74b598a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentChartSummaryController.java @@ -0,0 +1,184 @@ +package com.budwk.app.zhgh.staffmanage.memberCost.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.staffmanage.memberCost.service.MemberPaymentService; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @ClassName MemberPaymentChartSummaryController + * @Description 图表汇总 + * @Author zhf + * @Date 2025/3/11 下午3:20 + */ +@Slf4j +@IocBean +@Ok("json:full") +@ApiOperation("会员缴费图表汇总") +@At("/platform/member/payment/chartSummary") +public class MemberPaymentChartSummaryController { + + + @Inject + private MemberPaymentService memberPaymentService; + + + @At("") + @Ok("beetl:/platform/zhgh/staffmanage/membercost/chartSummary/index.html") + @SaCheckPermission("member.payment.chartSummary") + public void index() { + } + + + @At + @ApiOperation("获取缴费项目图表") + @SaCheckPermission("member.payment.chartSummary") + public Result getPayProjectChart(@Param("startYear") Integer startYear, + @Param("endYear") Integer endYear) { + Sql sql = Sqls.create(""" + SELECT + mpp.projectName, + COUNT( mpi.id ) AS num + FROM + member_payment_project mpp + LEFT JOIN member_payment_info mpi ON mpi.paymentProjectId = mpp.id + AND mpi.isPayment = 1 + WHERE + YEAR ( mpp.createTime ) BETWEEN @startYear + AND @endYear + GROUP BY + mpp.id + """).setParam("startYear", startYear).setParam("endYear", endYear); + return Result.success(memberPaymentService.listMap(sql)); + } + + @At + @ApiOperation("获取退款项目图表") + @SaCheckPermission("member.payment.chartSummary") + public Result getRefundProjectChart(@Param("startYear") Integer startYear, + @Param("endYear") Integer endYear) { + Sql sql = Sqls.create(""" + SELECT + mpp.projectName, + COUNT( pt.id ) AS num + FROM + member_payment_project mpp + LEFT JOIN member_payment_info mpi ON mpi.paymentProjectId = mpp.id + LEFT JOIN payment_transaction pt ON pt.memberPaymentInfoId = mpi.id + AND pt.isRefund = 1 + WHERE + YEAR ( mpp.createTime ) BETWEEN @startYear + AND @endYear + GROUP BY + mpp.id + """).setParam("startYear", startYear).setParam("endYear", endYear); + return Result.success(memberPaymentService.listMap(sql)); + } + + @At + @ApiOperation("获取缴费金额图表") + @SaCheckPermission("member.payment.chartSummary") + public Result getPayMoneyChart(@Param("startYear") Integer startYear, + @Param("endYear") Integer endYear) { + Sql sql = Sqls.create(""" + SELECT + mpp.projectName, + SUM( pt.tradingAmount * 0.01 ) AS money + FROM + member_payment_project mpp + LEFT JOIN member_payment_info mpi ON mpi.paymentProjectId = mpp.id + AND mpi.isPayment = 1 + LEFT JOIN payment_transaction pt ON pt.memberPaymentInfoId = mpi.id + AND pt.isRefund = 0 + AND pt.tradingState = 'PAY_SUCCESS' + WHERE + YEAR ( mpp.createTime ) BETWEEN @startYear + AND @endYear + GROUP BY + mpp.id + """).setParam("startYear", startYear).setParam("endYear", endYear); + return Result.success(memberPaymentService.listMap(sql)); + } + + + @At + @ApiOperation("获取缴费、退款数量") + @SaCheckPermission("member.payment.chartSummary") + public Result getNumData(@Param("startYear") Integer startYear, + @Param("endYear") Integer endYear) { + + Sql sql = Sqls.create(""" + SELECT + pt.tradingAmount * 0.01 AS money, + pt.isRefund + FROM + member_payment_project mpp + LEFT JOIN member_payment_info mpi ON mpi.paymentProjectId = mpp.id + AND mpi.isPayment = 1 + LEFT JOIN payment_transaction pt ON pt.memberPaymentInfoId = mpi.id + AND pt.tradingState = 'PAY_SUCCESS' + WHERE + YEAR ( mpp.createTime ) BETWEEN @startYear + AND @endYear + """).setParam("startYear", startYear).setParam("endYear", endYear); + List map = memberPaymentService.listMap(sql); + + double payMoney = map.stream().filter(v -> !v.getBoolean("isRefund")).mapToDouble(v -> v.getDouble("money")).sum(); + double refundMoney = map.stream().filter(v -> v.getBoolean("isRefund")).mapToDouble(v -> v.getDouble("money")).sum(); + int refundSize = map.stream().filter(v -> v.getBoolean("isRefund")).collect(Collectors.toList()).size(); + int paySize = map.stream().filter(v -> !v.getBoolean("isRefund")).collect(Collectors.toList()).size(); + NutMap data = new NutMap(); + data.put("payMoney", payMoney); + data.put("refundMoney", refundMoney); + data.put("paySize", paySize); + data.put("refundSize", refundSize); + return Result.success(data); + } + + + @At + @ApiOperation("按分工会统计会员缴费金额") + @SaCheckPermission("member.payment.chartSummary") + public Result allUnionMoney(String paymentProjectId) { + Sql sql = Sqls.create(""" + SELECT + un.name AS unionname, + COALESCE ( SUM( subquery.money ), 0 ) AS money + FROM + sys_union un + LEFT JOIN ( + SELECT + pt.unionId, + SUM( pt.tradingAmount * 0.01 ) AS money + FROM + payment_transaction pt + INNER JOIN member_payment_info mpi ON mpi.id = pt.memberPaymentInfoId + AND mpi.paymentProjectId = @paymentProjectId + WHERE + pt.tradingState = 'PAY_SUCCESS' + AND pt.isRefund = 0 + GROUP BY + pt.unionId + ) subquery ON subquery.unionId = un.id + GROUP BY + un.id, + un.unionname, + un.unioncode + ORDER BY + un.unioncode; + """).setParam("paymentProjectId", paymentProjectId); + return Result.success(memberPaymentService.listMap(sql)); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentConfigController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentConfigController.java new file mode 100644 index 00000000..e8919964 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentConfigController.java @@ -0,0 +1,103 @@ +package com.budwk.app.zhgh.staffmanage.memberCost.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentConfig; +import com.budwk.app.zhgh.staffmanage.memberCost.service.MemberPaymentService; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +@Slf4j +@IocBean +@Ok("json:full") +@ApiOperation("会员缴费配置管理") +@At("/platform/member/payment/config") +public class MemberPaymentConfigController { + + @Inject + private MemberPaymentService memberPaymentService; + + @At("") + @Ok("beetl:/platform/zhgh/staffmanage/membercost/config.html") + @SaCheckPermission("member.payment.config") + public void index() {} + + + @At + @ApiOperation("缴费配置界面数据") + @SaCheckPermission("member.payment.config") + public Result pageData(PageForm pageForm, @Param("name") String name) { + Sql sql = Sqls.create("select * from member_payment_config $condition"); + Cnd cnd = Cnd.NEW(); + + if (Strings.isNotBlank(name)) { + cnd.and(Cnd.likeEX("name", name)); + } +// cnd.desc("project.`year`"); + cnd.desc("createdAt"); + sql.setCondition(cnd); + Pagination pagination = memberPaymentService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + @At + @ApiOperation("获取缴费配置") + @SaCheckPermission("member.payment.config") + public Result getPaymentConfig(){ + MemberPaymentConfig config = memberPaymentService.getConfig(); + return Result.success().addData(config); + } + + @At + @ApiOperation("获取缴费配置列表") + @SaCheckPermission("member.payment.config") + public Result getPaymentConfigList(){ + List paymentConfigList = memberPaymentService.getPaymentConfigList(); + return Result.success().addData(paymentConfigList); + } + + @At + @ApiOperation("删除缴费配置") + @SaCheckPermission("member.payment.config") + @SLog(tag = "会员缴费配置", msg = "删除缴费配置,${args[0]}") + public Result doRemove(String id){ + memberPaymentService.dao().clear(MemberPaymentConfig.class, Cnd.where("id", "=", id)); + return Result.success(); + } + + @At + @ApiOperation("打开/关闭缴费配置") + @SaCheckPermission("member.payment.config") + public Result openClosedConfig(String id){ + //位运算 取反 + memberPaymentService.dao().update(MemberPaymentConfig.class, + Chain.makeSpecial("isDisabled", "isDisabled ^ 1"), + Cnd.where("id", "=", id)); + return Result.success(); + } + + + @At + @ApiOperation("添加/修改缴费配置") + @SaCheckPermission("member.payment.config") + @SLog(tag = "会员缴费配置", msg = "添加/修改缴费配置,id:${args[0].id}") + public Result doAddOrModify(MemberPaymentConfig memberPaymentConfig){ + memberPaymentService.dao().insertOrUpdate(memberPaymentConfig); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentMineController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentMineController.java new file mode 100644 index 00000000..cafd183c --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentMineController.java @@ -0,0 +1,187 @@ +package com.budwk.app.zhgh.staffmanage.memberCost.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import com.budwk.app.base.annotation.RepeatSubmit; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.payment.model.PaymentRefundRecord; +import com.budwk.app.base.payment.model.PaymentTransaction; +import com.budwk.app.base.payment.wxpay.service.WxPayCommonService; +import com.budwk.app.base.payment.wxpay.vo.WxPayNeedParamVo; +import com.budwk.app.base.result.Result; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentInfo; +import com.budwk.app.zhgh.staffmanage.memberCost.service.MemberPaymentService; +import com.ijpay.wxpay.model.v3.Amount; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.FieldFilter; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.Daos; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @version 1.0 + * @Author zzr + * @name:MemberPaymentMineController + * @Date 2025/3/10 8:44 + * @注释 我的缴费列表 + */ +@Slf4j +@IocBean +@Ok("json:full") +@ApiOperation("我的缴费列表") +@At("/platform/member/payment/mine") +public class MemberPaymentMineController { + + @Inject + private Dao dao; + @Inject + private WxPayCommonService wxPayCommonService; + @Inject + private MemberPaymentService memberPaymentService; + + @At("") + @Ok("beetl:/platform/zhgh/staffmanage/membercost/mine/index.html") + @SaCheckPermission("member.payment.mine") + public void index() { + } + + + @At + @ApiOperation("缴费配置界面数据") + @SaCheckPermission("member.payment.mine") + public Result pageData(PageForm pageForm, Integer year, Integer isPay) { + Sql sql = Sqls.create(""" + SELECT + mpp.`year`, + mpp.projectName, + mpp.startTime, + mpp.endTime, + mpi.id, + mpi.isPayment, + mpi.payPersonnel, + mpi.personType, + mpi.userState, + mpi.paymentMonth, + mpi.isRefund, + mpi.refundState, + mpc.paymentStartMonth, + mpc.paymentEndMonth, + mpc.payStandards + FROM + `member_payment_info` mpi + LEFT JOIN member_payment_project mpp ON mpi.paymentProjectId = mpp.id + LEFT JOIN member_payment_config mpc ON mpc.id = mpp.configId + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("YEAR(mpp.createTime)", "=", year); + cnd.andEX("mpi.userId", "=", SecurityUtil.getUserId()); + cnd.and("mpp.endTime", ">=", DateUtil.today()); + cnd.andEX("mpp.isDisabled", "=", 0); + if (ObjectUtil.isNotNull(isPay)) { + if (isPay == 0) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.or("mpi.isPayment", "=", 0); + seg.or("mpi.isPayment", "is", null); + cnd.and(seg); + } else { + cnd.and("mpi.isPayment", "=", isPay); + } + } + sql.setCondition(cnd); + Pagination pagination = memberPaymentService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + @At + @RepeatSubmit + @ApiOperation("PC端唤起微信支付") + @SaCheckPermission("member.payment.mine") + @SLog(tag = "会员缴费", msg = "微信PC端订单支付,下单Id:${args[1]},交易金额:${args[0]}") + public Result pcOrderPay(Integer paymentMoney, String paymentInfoId) { + WxPayNeedParamVo paramVo = new WxPayNeedParamVo(); + paramVo.setDescription(SecurityUtil.getUserUsername() + "会费缴纳支付"); + paramVo.setAttach(""); + paramVo.setMemberPaymentInfoId(paymentInfoId); + paramVo.setAmount(new Amount().setTotal(paymentMoney)); + return wxPayCommonService.nativePay(paramVo); + } + + + @At + @ApiOperation("获取是否已经缴费") + @SaCheckPermission("member.payment.mine") + public Result getIsPay(String paymentInfoId) { + int count = memberPaymentService.dao().count(MemberPaymentInfo.class, + Cnd.where("id", "=", paymentInfoId).and("isPayment", "=", 1)); + return Result.success().addData(count); + } + + + @At + @ApiOperation("获取缴费信息") + @SaCheckPermission("member.payment.mine") + public Result getPaymentInfoById(String id) { + Sql sql = Sqls.create(""" + SELECT + mpi.id, + mpi.loginname, + u.username, + u.unionname, + u.unitname, + mpp.projectName, + mpi.isPayment, + mpi.payPersonnel, + mpi.personType, + mpi.paymentMonth, + mpi.paymentMoney + FROM + `member_payment_info` mpi + LEFT JOIN member_payment_project mpp ON mpi.paymentProjectId = mpp.id + LEFT JOIN `user` u ON u.loginname = mpi.loginname + WHERE + mpi.id = @id + """).setParam("id", id); + // 查出id的缴费信息,并且查出缴费记录 + sql.setCallback(Sqls.callback.map()); + dao.execute(sql); + NutMap result = (NutMap) sql.getResult(); + + // 订单信息 + FieldFilter transFieldFilter = FieldFilter.locked(PaymentTransaction.class, "resultJson"); + List transList = Daos.ext(dao, transFieldFilter).query(PaymentTransaction.class, Cnd.where("memberPaymentInfoId", "=", id).desc("createdAt")); + + if (Lang.isNotEmpty(transList)) { + result.put("transList", transList); + // 退款信息 + + List transIdList = transList.stream().map(PaymentTransaction::getId).collect(Collectors.toList()); + + FieldFilter refundFieldFilter = FieldFilter.locked(PaymentRefundRecord.class, "resultJson"); + List refundRecordList = Daos.ext(dao, refundFieldFilter).query(PaymentRefundRecord.class, + Cnd.where("paymentTransactionId", "in", transIdList).desc("createdAt")); + if (Lang.isNotEmpty(refundRecordList)) { + result.put("refundRecordList", refundRecordList); + } + } + return Result.success().addData(result); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentProjectController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentProjectController.java new file mode 100644 index 00000000..7b71b4df --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentProjectController.java @@ -0,0 +1,295 @@ +package com.budwk.app.zhgh.staffmanage.memberCost.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentConfig; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentInfo; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentProject; +import com.budwk.app.zhgh.staffmanage.memberCost.service.MemberPaymentService; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.impl.NutTxDao; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; + +@Slf4j +@IocBean +@Ok("json:full") +@ApiOperation("会员缴费项目管理") +@At("/platform/member/payment/project") +public class MemberPaymentProjectController { + + @Inject + private MemberPaymentService memberPaymentService; + + @At("") + @Ok("beetl:/platform/zhgh/staffmanage/membercost/project.html") + @SaCheckPermission("member.payment.project") + public void index() { + } + + + @At + @ApiOperation("缴费项目界面数据") + @SaCheckPermission("member.payment.project") + public Result pageData(PageForm pageForm, + @Param("year") String year, + @Param("projectName") String projectName) { + Sql sql = Sqls.create("select project.*,IF((SELECT count(1) FROM member_payment_info WHERE paymentProjectId = project.id)>0,TRUE,FALSE) created from member_payment_project project $condition"); + Cnd cnd = Cnd.NEW(); + cnd.andEX("project.`year`", "=", year); + if (Strings.isNotBlank(projectName)) { + cnd.and(Cnd.likeEX("project.projectName", projectName)); + } +// cnd.desc("project.`year`"); + cnd.desc("project.createTime"); + sql.setCondition(cnd); + Pagination pagination = memberPaymentService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + /** + * 是否开启 + * + * @param id 项目Id + * @return + */ + @At + @ApiOperation("开启/禁用缴费项目") + @SaCheckPermission("member.payment.project") + public Result openClosedProject(String id) { + //位运算 取反 + memberPaymentService.dao().update(MemberPaymentProject.class, + Chain.makeSpecial("isDisabled", "isDisabled ^ 1"), + Cnd.where("id", "=", id)); + return Result.success(); + } + + + /** + * 添加或修改缴费项目 + * + * @param paymentProject + * @return + */ + @At + @ApiOperation("添加/修改缴费项目") + @SaCheckPermission("member.payment.project") + @SLog(tag = "会员缴费项目", msg = "添加/修改缴费项目") + public Result doSave(MemberPaymentProject paymentProject) { + memberPaymentService.insertOrUpdate(paymentProject); + return Result.success(); + } + + + /** + * 设置缴费人员 + * + * @param id 缴费项目Id + * @param isRenew 是否更行缴费人员 + * @return + */ + @At + @ApiOperation("设置缴费人员") + @SaCheckPermission("member.payment.project") + @SLog(tag = "会员缴费项目", msg = "设置缴费人员") + public Result doSetPayment(String id, Boolean isRenew) { + //如果不是更新缴费人员,就删除该项目下的所有待缴费信息,再重新设置 + if (!isRenew) { + memberPaymentService.clear(Cnd.where("paymentProjectId", "=", id)); + } + + //获取缴费项目 + MemberPaymentProject project = memberPaymentService.dao().fetch(MemberPaymentProject.class, id); + //获取缴费配置 + MemberPaymentConfig config = memberPaymentService.getConfigById(project.getConfigId()); + List payStandards = config.getPayStandards(); + //缴费人员类型 + List personTypeList = payStandards.stream().map(MemberPaymentConfig.PayStandards::getPersonType).collect(Collectors.toList()); + + //获取所有有入会时间的会员 + List memberList = memberPaymentService.dao().query(Sys_user.class, Cnd.where("personType", "in", personTypeList)); + //获取该项目下的代缴人员 + List paymentUserIdList = memberPaymentService.query(Cnd.where("paymentProjectId", "=", id)).stream().map(MemberPaymentInfo::getUserId).collect(Collectors.toList()); + //过滤出需要新增到记录表中的人员 + List needInsertUserIds = memberList.stream().filter(v -> !paymentUserIdList.contains(v.getId())).collect(Collectors.toList()); + + + //该缴费配置的缴费月份是几月到几月,转为数组 + String[] strings = {config.getPaymentStartMonth(),config.getPaymentEndMonth()}; + DateTime beginDate = DateUtil.parse(strings[0] + "-01"); + //获取月份的最后一天 + DateTime endDate = DateUtil.endOfMonth(DateUtil.parse(strings[1] + "-01")); + + List memberPaymentInfos = new ArrayList<>(); + needInsertUserIds.forEach(v -> { + MemberPaymentInfo paymentInfo = new MemberPaymentInfo(); + paymentInfo.setPersonType(v.getPersonType()); + paymentInfo.setUserState(v.getUserState()); + long differMonth = 0; + //如果是新入职教工,计算需要缴纳的月数 + if (v.getMemberTime() == null) { + differMonth = DateUtil.betweenMonth(beginDate, endDate, false)+1; + paymentInfo.setPaymentMonth(String.valueOf(differMonth)); + paymentInfo.setPayPersonnel("普通会员"); + } else if (v.getMemberTime().after(beginDate) && v.getMemberTime().before(endDate)){ + differMonth = DateUtil.betweenMonth(v.getMemberTime(), endDate, false)+1; + paymentInfo.setPaymentMonth(String.valueOf(differMonth)); + paymentInfo.setPayPersonnel("新进会员"); + //getPayment(v, payStandards, paymentInfo, differMonth,"新进会员"); + + }else if(v.getRetireDate()!=null&&v.getRetireDate().after(beginDate)&&v.getRetireDate().before(endDate)){ + //如果是退休会员 + differMonth = DateUtil.betweenMonth(beginDate, v.getRetireDate(), false)+1; + paymentInfo.setPaymentMonth(String.valueOf(differMonth)); + paymentInfo.setPayPersonnel("退休会员"); + //getPayment(v, payStandards, paymentInfo, differMonth,"退休会员"); + }else { + //如果是普通会员 + differMonth = DateUtil.betweenMonth(beginDate, endDate, false)+1; + paymentInfo.setPaymentMonth(String.valueOf(differMonth)); + paymentInfo.setPayPersonnel("普通会员"); + //getPayment(v, payStandards, paymentInfo, differMonth,"普通会员"); + } + paymentInfo.setUserId(v.getId()); + paymentInfo.setLoginname(v.getLoginname()); + paymentInfo.setPaymentProjectId(id); + paymentInfo.setPayment(false); + memberPaymentInfos.add(paymentInfo); + }); + + if (memberPaymentInfos.size() < 500) { + memberPaymentService.insert(memberPaymentInfos); + } else { + List> splitList = CollectionUtil.split(memberPaymentInfos, 500); + NutTxDao nutTxDao = new NutTxDao(memberPaymentService.dao()).setDebug(true); + nutTxDao.beginRC(); + ExecutorService executorService = Executors.newWorkStealingPool(); + List> taskList = new ArrayList<>(); + for (List everyList : splitList) { + taskList.add(() -> nutTxDao.insert(everyList).size()); + } + List> futureList = null; + AtomicInteger atomicInteger = new AtomicInteger(); + try { + futureList = executorService.invokeAll(taskList); + for (Future future : futureList) { + atomicInteger.getAndAdd((Integer) future.get()); + } + if (atomicInteger.get() != memberPaymentInfos.size()) { + throw new RuntimeException("插入数据与期望数据条数不符"); + } + nutTxDao.commit(); + } catch (Exception e) { + nutTxDao.rollback(); + throw new RuntimeException(e); + } finally { + executorService.shutdown(); + } + } + return Result.success(); + } + + private static void getPayment(Sys_user v, List payStandards, MemberPaymentInfo paymentInfo, long differMonth,String payPersonnel) { + List list = payStandards.stream().filter(v1 -> v1.getPersonType().equals(v.getPersonType()) && payPersonnel.equals(v1.getPayPersonnel())).collect(Collectors.toList()); + MemberPaymentConfig.PayStandards standards = null; + if (list!=null&&list.size()>0){ + standards = list.get(0); + } + if ("在编".equals(v.getPersonType())&&standards!=null){ + AtomicReference value= new AtomicReference<>(0); + standards.getPayModeValueList().forEach(v1->{ + value.set(value.get()+v1.getInt("value")); + }); + paymentInfo.setPaymentMoney(String.valueOf(value.get()*0.05* differMonth)); + } + if ("非编".equals(v.getPersonType())&&standards!=null){ + paymentInfo.setPaymentMoney(String.valueOf(Integer.valueOf(standards.getPayModeValue())* differMonth)); + } + } + + + /** + * 删除 + * + * @param id 项目Id + * @return + */ + @At + @ApiOperation("删除缴费项目") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("member.payment.project") + @SLog(tag = "会员缴费项目", msg = "删除缴费项目: ${args[0]}") + public Result doRemove(String id) { + int paymentCount = memberPaymentService.count(Cnd.where("paymentProjectId", "=", id).and("isPayment", "=", 1)); + if (paymentCount > 0) { + return Result.error().addMsg("该项目已有人完成缴费,请将缴费人员设置为未缴后再进行删除!"); + } + memberPaymentService.dao().clear(MemberPaymentProject.class, Cnd.where("id", "=", id)); + memberPaymentService.clear(Cnd.where("paymentProjectId", "=", id)); + return Result.success(); + } + + + /** + * 获取全部缴费项目 + * + * @param year + * @return + */ + @At + @ApiOperation("获取全部缴费项目") + @SaCheckPermission(value = {"member.payment.project", "member.payment.summary"}, mode = SaMode.OR) + public Result getAllProject(String year) { + Cnd cnd = Cnd.NEW(); + cnd.and("isDisabled", "=", 0); + if (Strings.isNotBlank(year)) { + cnd.and("`year`", "=", year); + } + cnd.desc("createTime"); + cnd.desc("year"); + return Result.success().addData(memberPaymentService.dao().query(MemberPaymentProject.class, cnd)); + } + + + @At("/findOne") + @ApiOperation("获取缴费项目信息") + @SaCheckPermission(value = {"member.payment.project", "member.payment.summary"}, mode = SaMode.OR) + public Result findOne(String id) { + MemberPaymentProject oneProject = memberPaymentService.findOneProject(id); + return Result.success().addData(oneProject); + } + + + +} + diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentRefundController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentRefundController.java new file mode 100644 index 00000000..a406f76c --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentRefundController.java @@ -0,0 +1,115 @@ +package com.budwk.app.zhgh.staffmanage.memberCost.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.ObjectUtil; +import com.budwk.app.base.annotation.RepeatSubmit; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.payment.enums.TradingStateEnum; +import com.budwk.app.base.payment.model.PaymentTransaction; +import com.budwk.app.base.payment.wxpay.service.WxPayCommonService; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.staffmanage.memberCost.service.MemberPaymentService; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +/** + * @ClassName MemberPaymentRefundController + * @Description 退款 + * @Author zhf + * @Date 2025/3/11 上午8:51 + */ +@Slf4j +@IocBean +@Ok("json:full") +@ApiOperation("会员缴费退款") +@At("/platform/member/payment/refund") +public class MemberPaymentRefundController { + + @Inject + private WxPayCommonService wxPayCommonService; + @Inject + private MemberPaymentService memberPaymentService; + + @At("") + @Ok("beetl:/platform/zhgh/staffmanage/membercost/refund/index.html") + @SaCheckPermission("member.payment.refund") + public void index() { + } + + @At + @ApiOperation("退款数据列表") + @SaCheckPermission("member.payment.refund") + public Result pageData(PageForm pageForm, String paymentProjectId, String transactionId, Integer isRefund) { + Sql sql = Sqls.create(""" + SELECT + mpp.`year`, + mpp.projectName, + mpp.startTime, + mpp.endTime, + mpi.isPayment, + mpi.payPersonnel, + mpi.personType, + mpi.paymentMonth, + mpi.paymentTime, + pt.id, + pt.outTradeNo, + pt.transactionId, + pt.userName, + pt.loginName, + pt.unitName, + pt.unionName, + pt.tradingAmount, + pt.isRefund, + prr.createdAt AS refundTime + FROM + payment_transaction pt + LEFT JOIN `member_payment_info` mpi ON pt.memberPaymentInfoId = mpi.id + LEFT JOIN `payment_refund_record` prr ON pt.id = prr.paymentTransactionId + LEFT JOIN member_payment_project mpp ON mpi.paymentProjectId = mpp.id + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("mpi.paymentProjectId", "=", paymentProjectId); + cnd.andEX("pt.tradingState", "=", TradingStateEnum.PAY_SUCCESS); + cnd.and(Cnd.likeEX("pt.transactionId", transactionId)); + if (isRefund != 3) { + cnd.andEX("pt.isRefund", "=", isRefund); + } + if (ObjectUtil.isNotEmpty(pageForm.getSearchKeyword())) { + SqlExpressionGroup group = new SqlExpressionGroup(); + group.orLike("pt.userName", pageForm.getSearchKeyword()); + group.orLike("pt.loginName", pageForm.getSearchKeyword()); + cnd.and(group); + } + cnd.groupBy("pt.id"); + cnd.desc("mpi.paymentTime"); + sql.setCondition(cnd); + Pagination pagination = memberPaymentService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + @At + @RepeatSubmit + @ApiOperation("缴费退款") + @SaCheckPermission("member.payment.refund") + @SLog(tag = "会员缴费退款", msg = "会员缴费退款: ${args[0]}") + public Result doRefund(@Param("id") String id) { + PaymentTransaction transaction = memberPaymentService.dao().fetch(PaymentTransaction.class, id); + Result refund = wxPayCommonService.refund(transaction.getTransactionId(), transaction.getOutTradeNo()); + return Result.success().addData(refund); + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentSummaryController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentSummaryController.java new file mode 100644 index 00000000..6181a141 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentSummaryController.java @@ -0,0 +1,287 @@ +package com.budwk.app.zhgh.staffmanage.memberCost.controller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.ExcelImportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.ImportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.sys.services.SysUserService; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentInfo; +import com.budwk.app.zhgh.staffmanage.memberCost.service.MemberPaymentService; +import com.budwk.app.zhgh.staffmanage.memberCost.template.MemberPaymentTemp; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.AdaptBy; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; +import org.nutz.mvc.upload.TempFile; +import org.nutz.mvc.upload.UploadAdaptor; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedOutputStream; +import java.math.BigDecimal; +import java.net.URLEncoder; +import java.util.*; +import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +@Slf4j +@IocBean +@Ok("json:full") +@ApiOperation("会员缴费汇总") +@At("/platform/member/payment/summary") +public class MemberPaymentSummaryController { + + @Inject + private MemberPaymentService memberPaymentService; + + @Inject + private SysUserService sysUserService; + + @At("") + @Ok("beetl:/platform/zhgh/staffmanage/membercost/summary.html") + @SaCheckPermission("member.payment.summary") + public void index() { + } + + + @At + @ApiOperation("会员缴费汇总数据") + @SaCheckPermission("member.payment.summary") + public Result pageData(PageForm pageForm, + @Param("unionId") String unionId, + @Param("unitId") String unitId, + @Param("unionGroupId") String unionGroupId, + @Param("threeUnitId") String threeUnitId, + @Param("personType") String personType, + @Param("userState") String userState, + @Param("paymentProjectId") String paymentProjectId, + @Param("year") String year, + @Param("isPay") String isPay, + @Param("schoolTimeStart") String schoolTimeStart, + @Param("schoolTimeEnd") String schoolTimeEnd, + @Param("retireDateStart") String retireDateStart, + @Param("retireDateEnd") String retireDateEnd, + @Param("search") String search) { + Sql sql = memberPaymentService.getSummarySql(pageForm.getPageOrderName(), pageForm.getPageOrderBy(), pageForm.getSearchName(), + pageForm.getSearchKeyword(), unionId, unitId, threeUnitId, unionGroupId, + personType, userState, paymentProjectId, year, isPay, schoolTimeStart, schoolTimeEnd, + retireDateStart, retireDateEnd, search); + Pagination pagination = memberPaymentService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + + @At + @ApiOperation("修改缴费信息") + @SLog(tag = "缴费汇总", msg = "修改缴费信息") + @SaCheckPermission("member.payment.summary") + public Result modify(@Param("ids") String[] ids, String paymentMoney, boolean isPay, String remark) { + List idList = Arrays.asList(ids); + if (Lang.isNotEmpty(idList)) { + if (!isPay) { + //未缴费设为已缴费 + memberPaymentService.update(Chain.make("paymentMoney", paymentMoney) + .add("remark", remark).add("isPayment", 1) + .add("paymentTime", new Date()), + Cnd.where("id", "in", idList)); + } else { + //已缴费设为未缴费 + memberPaymentService.update(Chain.make("paymentMoney", null) + .add("isPayment", 0).add("paymentTime", null), + Cnd.where("id", "in", idList)); + } + } + return Result.success(); + } + + @At + @ApiOperation("删除缴费信息") + @SaCheckPermission("member.payment.summary") + @SLog(tag = "缴费汇总", msg = "根据缴费Id删除缴费信息") + public Result doRemoveById(String id) { + memberPaymentService.delete(id); + return Result.success(); + } + + @At + @Ok("void") + @ApiOperation("下载导入模版") + @SaCheckPermission("member.payment.summary") + public void downloadImportTemp(HttpServletResponse response) { + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, MemberPaymentTemp.class, new ArrayList<>()); + CommonDownloadUtil.download("会员缴费导入模版.xlsx", workbook, response); + } + + + @At + @ApiOperation("导入缴费信息") + @SaCheckPermission("member.payment.summary") + @SLog(tag = "导入缴费信息", msg = "导入缴费信息") + @AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"}) + public Result doImport(TempFile file, String projectId) { + try { + List memberPaymentTempList = ExcelImportUtil.importExcel(file.getFile(), MemberPaymentTemp.class, new ImportParams()); + + List paymentUserList = memberPaymentService.query(Cnd.where("paymentProjectId", "=", projectId)); + Map infoMap = paymentUserList.stream().collect(Collectors.toMap(MemberPaymentInfo::getLoginname, v -> v)); + List errorInfos = new ArrayList<>(); + List needInsertList = new ArrayList<>(); + + //缴费比例 + for (MemberPaymentTemp v : memberPaymentTempList) { + if (infoMap.containsKey(v.getLoginname().trim())) { + MemberPaymentInfo memberPaymentInfo = infoMap.get(v.getLoginname().trim()); + + // 如果系统里边没有这个工号,返回错误信息,然后跳过 + if (Lang.isEmpty(memberPaymentInfo)) { + v.setResult("请检查该工号是否正确!"); + errorInfos.add(v); + continue; + } + + memberPaymentInfo.setPayment(v.getIsPay()); + + if (Strings.isNotBlank(v.getPaymentBase())) { + String paymentBase = v.getPaymentBase(); + + BigDecimal value = new BigDecimal(paymentBase); + BigDecimal multipliedValue = value.multiply(new BigDecimal(100)); + // 转换为整数类型 + int result = multipliedValue.intValueExact(); + memberPaymentInfo.setPaymentMoney(String.valueOf(result)); + memberPaymentInfo.setPaymentTime(v.getIsPay() ? DateUtil.date() : null); + memberPaymentInfo.setRemark(v.getRemark()); + memberPaymentInfo.setPaymentMethod("导入"); + needInsertList.add(memberPaymentInfo); + } else { + v.setResult("请填写该教职工的缴费数据!"); + errorInfos.add(v); + } + } else { + v.setResult("该教工可能不在此次缴费项目之中,请重新设置缴费人员或检查人员是否正确!"); + errorInfos.add(v); + } + } + + int i = 0; + if (Lang.isNotEmpty(needInsertList)) { + i = memberPaymentService.updateIgnoreNull(needInsertList); + } + + if (Lang.isNotEmpty(errorInfos)) { + NutMap nutMap = NutMap.NEW(); + nutMap.setv("totalCount", memberPaymentTempList.size()); + nutMap.setv("successCount", i); + nutMap.setv("errorCount", errorInfos.size()); + nutMap.setv("errorList", errorInfos.stream().map(v -> { + return NutMap.NEW().addv("工号", v.getLoginname()).addv("姓名", v.getUsername()).addv("错误原因", v.getResult()); + }).collect(Collectors.toList())); + return Result.success(nutMap); + } + return Result.success(); + } catch (Exception e) { + e.printStackTrace(); + return Result.error(); + } + } + + + @At + @Ok("void") + @ApiOperation("导出缴费信息") + @SaCheckPermission("member.payment.summary") + public void doExport(@Param("searchName") String searchName, + @Param("searchKeyword") String searchKeyword, + @Param("unionId") String unionId, + @Param("unitId") String unitId, + @Param("unionGroupId") String unionGroupId, + @Param("threeUnitId") String threeUnitId, + @Param("personType") String personType, + @Param("userState") String userState, + @Param("paymentProjectId") String paymentProjectId, + @Param("year") String year, + @Param("isPay") String isPay, + @Param("schoolTimeStart") String schoolTimeStart, + @Param("schoolTimeEnd") String schoolTimeEnd, + @Param("retireDateStart") String retireDateStart, + @Param("retireDateEnd") String retireDateEnd, + boolean isZip, HttpServletResponse response) { + Sql sql = memberPaymentService.getSummarySql(null, null, searchName, searchKeyword, unionId, unitId, threeUnitId, + unionGroupId, personType, userState, paymentProjectId, year, isPay, schoolTimeStart, schoolTimeEnd, + retireDateStart, retireDateEnd, ""); + + List list = memberPaymentService.listMap(sql); + NutMap nutMap = list.stream().findFirst().orElse(null); + + List unionIdList = memberPaymentService.dao().query(Sys_union.class, Cnd.NEW()); + try { + assert nutMap != null; + if (isZip) { + response.setContentType("application/octet-stream"); + response.setHeader("content-disposition", "attachment;filename=" + + URLEncoder.encode((Lang.isNotEmpty(nutMap) ? nutMap.getString("projectName") : "") + "缴费详情.zip", "UTF-8")); + ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream())); + for (Sys_union union : unionIdList) { + String fileName = union.getUnionCode() + union.getName().replaceAll("/", "、") + "缴费记录表.xlsx"; + zipOutputStream.putNextEntry(new ZipEntry(fileName)); + List unionUserList = list.stream().filter(v -> Strings.isNotBlank(v.getString("unionid")) && v.getString("unionid").equals(union.getId())).collect(Collectors.toList()); + Workbook workbook = memberPaymentService.exportOrZip(unionUserList, response.getOutputStream()); + workbook.write(zipOutputStream); + zipOutputStream.closeEntry(); + response.flushBuffer(); + } + zipOutputStream.flush(); + zipOutputStream.close(); + } else { + String fileName = (Lang.isNotEmpty(nutMap) ? nutMap.getString("projectName") : "") + "缴费详情表.xlsx"; + Workbook workbook = memberPaymentService.exportOrZip(list, response.getOutputStream()); + CommonDownloadUtil.download(fileName, workbook, response); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + + @At + @ApiOperation("发送缴费信息") + @SaCheckPermission("member.payment.summary") + public Result sendPaymentMsg(@Param("id") String id) { + if (Strings.isNotBlank(id)) { + List paymentInfos = memberPaymentService.query(Cnd.where("isPayment", "=", 0)); +// msgApi.sendMsg(); + } else { + MemberPaymentInfo paymentInfo = memberPaymentService.fetch(id); +// msgApi.sendMsg(); + } + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentUserController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentUserController.java new file mode 100644 index 00000000..cd50d5a4 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/controller/MemberPaymentUserController.java @@ -0,0 +1,85 @@ +package com.budwk.app.zhgh.staffmanage.memberCost.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentInfo; +import com.budwk.app.zhgh.staffmanage.memberCost.service.MemberPaymentService; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +/** + * 个人缴费管理 + * @author hpf + */ +@Slf4j +@IocBean +@Ok("json:full") +@ApiOperation("个人缴费管理") +@At("/platform/member/payment/user") +public class MemberPaymentUserController { + + @Inject + private MemberPaymentService memberPaymentService; + + @At("") + @Ok("beetl:/platform/zhgh/staffmanage/membercost/user.html") + @SaCheckPermission("member.payment.user") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("member.payment.user") + public Result pageData(PageForm pageForm, @Param("year") String year, @Param("projectName") String projectName){ + Sql sql = Sqls.create(""" + SELECT + mpi.*, + mpp.`year`, + mpp.projectName, + mpp.startTime, + mpp.endTime, + mpp.configId, + mpc.payStandards, + mpc.paymentStartMonth, + mpc.paymentEndMonth + FROM + member_payment_info mpi + LEFT JOIN member_payment_project mpp ON mpi.paymentProjectId = mpp.id + LEFT JOIN member_payment_config mpc ON mpc.id = mpp.configId + $condition + """); + Cnd cnd = Cnd.NEW(); + + cnd.andEX("mpp.isDisabled", "=", false); + cnd.andEX("mpp.year", "=", year); + cnd.and("mpi.userId", "=", SecurityUtil.getUserId()); + if (Strings.isNotBlank(projectName)) { + cnd.and(Cnd.likeEX("mpp.projectName", projectName)); + } + cnd.desc("mpp.createTime"); + sql.setCondition(cnd); + Pagination pagination = memberPaymentService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success().addData(pagination); + } + + @At + @ApiOperation("保存或修改") + @SaCheckPermission("member.payment.user") + public Result doSave(MemberPaymentInfo memberPaymentInfo) { + memberPaymentService.insertOrUpdate(memberPaymentInfo); + return null; + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/h5controller/MobileMemberCostListController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/h5controller/MobileMemberCostListController.java new file mode 100644 index 00000000..bf55bd61 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/h5controller/MobileMemberCostListController.java @@ -0,0 +1,97 @@ +package com.budwk.app.zhgh.staffmanage.memberCost.h5controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.payment.wxpay.service.WxPayCommonService; +import com.budwk.app.base.payment.wxpay.vo.WxPayNeedParamVo; +import com.budwk.app.base.result.Result; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentInfo; +import com.budwk.app.zhgh.staffmanage.memberCost.service.MemberPaymentService; +import com.ijpay.wxpay.model.v3.Amount; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @ClassName MobileMemberCostListController + * @Description TODO + * @Author zhf + * @Date 2024/1/26 15:37 + */ +@Slf4j +@IocBean +@Ok("json:full") +@At("/mobile/memberCost/list") +public class MobileMemberCostListController { + + @Inject + private MemberPaymentService memberPaymentService; + @Inject + private WxPayCommonService wxPayCommonService; + + @At("") + @SaCheckPermission("member.payment.user") + @Ok("beetl:/mobile/memberCost/memberCostList.html") + public void index() { + } + + @At("/paySuccess") + @SaCheckPermission("member.payment.user") + @Ok("beetl:/mobile/memberCost/paySuccess.html") + public void paySuccess() { + } + + @At("/summary") + @SaCheckPermission("member.payment.user") + @Ok("beetl:/mobile/memberCost/summary.html") + public void summary() { + } + + + @At + @ApiOperation("获取缴费列表") + @SaCheckPermission("member.payment.user") + public Result pageData(Integer memberActive) { + Sql sql = Sqls.create(""" + SELECT + mpi.*, + mpp.projectName + FROM + member_payment_info mpi + LEFT JOIN member_payment_project mpp ON mpi.paymentProjectId = mpp.id + WHERE + mpi.userId = @userId + AND mpp.isDisabled =0 + and mpi.isPayment =@isPayment + """).setParam("userId", SecurityUtil.getUserId()).setParam("isPayment", memberActive); + + return Result.success().addData(memberPaymentService.listMap(sql)); + } + + @At + @ApiOperation("获取支付信息") + @SaCheckPermission("member.payment.user") + public Result getPayInfo(String id) { + MemberPaymentInfo info = memberPaymentService.fetch(id); + return Result.success().addData(info); + } + + @At + @ApiOperation("唤起微信支付") + @SaCheckPermission("member.payment.user") + @SLog(tag = "会员管理", msg = "唤起微信支付,支付金额:${args[0]};唯一Id:${args[1]}") + public Result pullWeChatPay(Integer money, String busId) { + WxPayNeedParamVo wxPayNeedParamVo = new WxPayNeedParamVo(); + wxPayNeedParamVo.setDescription("会费缴纳"); + wxPayNeedParamVo.setMemberPaymentInfoId(busId); + wxPayNeedParamVo.setAmount(new Amount().setTotal(money)); + return wxPayCommonService.jsApiPay(wxPayNeedParamVo); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/model/MemberPaymentConfig.java b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/model/MemberPaymentConfig.java new file mode 100644 index 00000000..59e3a01f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/model/MemberPaymentConfig.java @@ -0,0 +1,73 @@ +package com.budwk.app.zhgh.staffmanage.memberCost.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; +import org.nutz.lang.util.NutMap; + +import java.io.Serializable; +import java.util.List; + +@Data +@Table +@EqualsAndHashCode(callSuper = true) +public class MemberPaymentConfig extends BaseModel { + + @Column + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("缴费配置名称") + @ColDefine(type = ColType.VARCHAR,width = 50) + private String name; + + @Column + @Comment("缴费标准") + @ColDefine(type = ColType.MYSQL_JSON) + private List payStandards; + + @Column + @Comment("未缴费退会时长") + @ColDefine(type = ColType.VARCHAR,width = 10) + private String unPaidExitDuration; + + @Column + @Comment("退会模式(1,。自动退会;2.人工退会)") + @ColDefine(type = ColType.VARCHAR,width = 10) + private String exitMode; + + @Column + @Comment("缴费时长(多久缴费一次)") + @ColDefine(type = ColType.VARCHAR,width = 10) + private String paidDuration; + + @Column + @Comment("是否开启") + @ColDefine(type = ColType.BOOLEAN) + private boolean isDisabled; + + @Column + @Comment("开始缴费月份") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String paymentStartMonth; + + @Column + @Comment("结束缴费月份") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String paymentEndMonth; + + @Data + public static class PayStandards implements Serializable { + private String payPersonnel; + private String payMode; + private String personType; + private String payModeValue; + private List payModeValueList; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/model/MemberPaymentInfo.java b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/model/MemberPaymentInfo.java new file mode 100644 index 00000000..d136bdba --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/model/MemberPaymentInfo.java @@ -0,0 +1,118 @@ +package com.budwk.app.zhgh.staffmanage.memberCost.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.util.Date; + +@Data +@Table +@EqualsAndHashCode(callSuper = true) +public class MemberPaymentInfo extends BaseModel { + + @Column + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("用户id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String userId; + + @Column + @Comment("工号") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String loginname; + + @Column + @Comment("缴费项目id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String paymentProjectId; + + @Column + @Comment("工资") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String wages; + + @Column + @Comment("是否缴费") + @ColDefine(type = ColType.BOOLEAN) + private boolean isPayment; + + @Column + @Comment("缴费基数1") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String paymentBaseOne; + + @Column + @Comment("缴费基数2") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String paymentBaseTwo; + + @Column + @Comment("缴费金额") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String paymentMoney; + + @Column + @Comment("缴费日期") + @ColDefine(type = ColType.DATETIME) + private Date paymentTime; + + @Column + @Comment("备注") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String remark; + + @Column + @Comment("支付记录Id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String payId; + + @Column + @Comment("支付宝记录Id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String tradeNo; + + @Column + @Comment("缴费方式") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String paymentMethod; + + + @Column + @Comment("缴费月份") + @ColDefine(type = ColType.VARCHAR, width = 10) + private String paymentMonth; + + @Column + @Comment("人员类型") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String personType; + + @Column + @Comment("在职状态") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String userState; + + @Column + @Comment("会员类型") + @ColDefine(type = ColType.VARCHAR, width = 10) + private String payPersonnel; + + @Column + @Comment("是否退款") + @ColDefine(type = ColType.BOOLEAN) + private Boolean isRefund; + + @Column + @Comment("退款状态") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String refundState; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/model/MemberPaymentProject.java b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/model/MemberPaymentProject.java new file mode 100644 index 00000000..2d629cd7 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/model/MemberPaymentProject.java @@ -0,0 +1,68 @@ +package com.budwk.app.zhgh.staffmanage.memberCost.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.util.Date; + +@Data +@Table +@EqualsAndHashCode(callSuper = true) +public class MemberPaymentProject extends BaseModel { + + @Column + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("年度") + @ColDefine(type = ColType.VARCHAR, width = 4) + private String year; + + @Column + @Comment("项目名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String projectName; + + @Column + @Comment("是否开启") + @ColDefine(type = ColType.BOOLEAN) + private boolean isDisabled; + + @Column + @Comment("创建时间") + @ColDefine(type = ColType.DATETIME) + private Date createTime; + + + @Column + @Comment("开始缴费月份") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String paymentStartMonth; + + @Column + @Comment("结束缴费月份") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String paymentEndMonth; + + @Column + @Comment("开始缴费时间") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String startTime; + + @Column + @Comment("结束缴费时间") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String endTime; + + @Column + @Comment("缴费配置id") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String configId; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/service/MemberPaymentService.java b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/service/MemberPaymentService.java new file mode 100644 index 00000000..08e1b963 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/service/MemberPaymentService.java @@ -0,0 +1,76 @@ +package com.budwk.app.zhgh.staffmanage.memberCost.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentConfig; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentInfo; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentProject; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.dao.sql.Sql; +import org.nutz.lang.util.NutMap; + +import java.io.OutputStream; +import java.util.List; + +public interface MemberPaymentService extends BaseService { + + /** + * 根据id查询缴费项目 + * @param id + * @return + */ + MemberPaymentProject findOneProject(String id); + + /** + * 导出缴费信息的公共方法 + * @return + */ + Workbook exportOrZip(List list, OutputStream outputStream)throws Exception; + + /** + * 获取缴费配置信息 + * @return + */ + MemberPaymentConfig getConfig(); + + /** + * 获取缴费配置列表 + * @return + */ + List getPaymentConfigList(); + + /** + * 根据id获取缴费配置信息 + * @param configId + * @return + */ + MemberPaymentConfig getConfigById(String configId); + + /** + * 会员缴费汇总数据公共sql + * + * @param pageOrderName + * @param pageOrderBy + * @param searchName + * @param searchKeyword + * @param unionId + * @param unitId + * @param threeUnitId + * @param unionGroupId + * @param personType + * @param userState + * @param paymentProjectId + * @param year + * @param isPay + * @param schoolTimeStart + * @param schoolTimeEnd + * @param retireDateStart + * @param retireDateEnd + * @param search + * @return + */ + Sql getSummarySql(String pageOrderName, String pageOrderBy, String searchName, String searchKeyword, + String unionId, String unitId, String threeUnitId, String unionGroupId, + String personType, String userState, String paymentProjectId, String year, + String isPay,String schoolTimeStart, String schoolTimeEnd, String retireDateStart, + String retireDateEnd, String search); +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/service/impl/MemberPaymentServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/service/impl/MemberPaymentServiceImpl.java new file mode 100644 index 00000000..5a7d6a17 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/service/impl/MemberPaymentServiceImpl.java @@ -0,0 +1,174 @@ +package com.budwk.app.zhgh.staffmanage.memberCost.service.impl; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentConfig; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentInfo; +import com.budwk.app.zhgh.staffmanage.memberCost.model.MemberPaymentProject; +import com.budwk.app.zhgh.staffmanage.memberCost.service.MemberPaymentService; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; + +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@IocBean(args = {"refer:dao"}) +public class MemberPaymentServiceImpl extends BaseServiceImpl implements MemberPaymentService { + public MemberPaymentServiceImpl(Dao dao) { + super(dao); + } + + @Override + public MemberPaymentProject findOneProject(String id) { + return dao().fetch(MemberPaymentProject.class, id); + } + + + @Override + public Workbook exportOrZip(List list, OutputStream outputStream) throws Exception { + List exportEntities = new ArrayList<>(); + exportEntities.add(new ExcelExportEntity("工号", "loginname", 20)); + exportEntities.add(new ExcelExportEntity("姓名", "username", 20)); +// exportEntities.add(new ExcelExportEntity("年度", "year", 20)); + exportEntities.add(new ExcelExportEntity("缴费项目", "projectName", 20)); + exportEntities.add(new ExcelExportEntity("性别", "sex", 20)); + exportEntities.add(new ExcelExportEntity("联系电话", "mobile", 20)); +// exportEntities.add(new ExcelExportEntity("身份证号", "idcard", 30)); + exportEntities.add(new ExcelExportEntity("在职状态", "userState", 20)); + exportEntities.add(new ExcelExportEntity("人员类型", "personType", 20)); + exportEntities.add(new ExcelExportEntity("所属工会", "unionname", 20)); + exportEntities.add(new ExcelExportEntity("所属单位", "unitname", 30)); + exportEntities.add(new ExcelExportEntity("是否缴费", "isPay", 10)); + exportEntities.add(new ExcelExportEntity("缴费金额", "payMoney", 10)); + exportEntities.add(new ExcelExportEntity("缴费时间", "paymentTime", 20)); + exportEntities.add(new ExcelExportEntity("备注", "remark", 30)); + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + exportParams.setHeight((short) 10); + return ExcelExportUtil.exportExcel(exportParams, exportEntities, list); + } + + + @Override + public MemberPaymentConfig getConfig() { + return dao().fetch(MemberPaymentConfig.class); + } + + @Override + public List getPaymentConfigList() { + return dao().query(MemberPaymentConfig.class, Cnd.NEW().and("isDisabled", "=", "0")); + } + + @Override + public MemberPaymentConfig getConfigById(String configId) { + return dao().fetch(MemberPaymentConfig.class, configId); + } + + + /** + * 会员缴费汇总数据公共sql + * + * @param pageOrderName + * @param pageOrderBy + * @param searchName + * @param searchKeyword + * @param unionId + * @param unitId + * @param threeUnitId + * @param unionGroupId + * @param personType + * @param userState + * @param paymentProjectId + * @param year + * @param isPay + * @param schoolTimeStart + * @param schoolTimeEnd + * @param retireDateStart + * @param retireDateEnd + * @param search + * @return + */ + @Override + public Sql getSummarySql(String pageOrderName, String pageOrderBy, String searchName, String searchKeyword, String unionId, String unitId, String threeUnitId, String unionGroupId, String personType, String userState, String paymentProjectId, String year, String isPay, String schoolTimeStart, String schoolTimeEnd, String retireDateStart, String retireDateEnd, String search) { + Sql sql = Sqls.create(""" + SELECT + mpi.*, + (IFNULL( mpi.paymentMoney, 0 ) / 100) AS payMoney, + IF(mpi.isPayment = 1,'已缴费','未缴费') AS isPay, + mpp.projectName, + u.username, + u.sex, + u.member, + u.welfareMember, + u.unionName AS unionname, + u.unionId AS unionid, + u.unitName AS unitname, + u.unitId AS unitid, + u.mobile, + u.birthday, + u.arrivalAtSchoolDate AS schoolTime, + u.retireDate + FROM + `member_payment_info` mpi + LEFT JOIN `vw_user` u ON u.id = mpi.userId + left join `member_payment_project` mpp on mpp.id = mpi.paymentProjectId + $condition + """); + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(searchName) && StrUtil.isNotBlank(searchKeyword)) { + cnd.and(Cnd.likeEX(searchName, searchKeyword)); + } + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + if (AuthUtil.hasRoleOr(RoleConstant.BRANCH_UNION_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_OPERATOR.name())) { + cnd.and("u.unionid", "=", SecurityUtil.getUnionId()); + } else { + cnd.and("u.id", "=", SecurityUtil.getUserId()); + } + } + if (Strings.isNotBlank(search)) { + cnd.orEX("u.username", "like", "%" + search + "%"); + } + cnd.andEX("mpp.`year`", "=", year); + cnd.andEX("mpi.paymentProjectId", "=", paymentProjectId); + if (Strings.isNotBlank(isPay) && !"null".equals(isPay)) { + cnd.andEX("mpi.isPayment", "=", "true".equals(isPay) ? 1 : 0); + } + cnd.andEX("u.unionId", "=", unionId); + cnd.andEX("u.unitId", "=", unitId); + cnd.andEX("u.personType", "=", personType); + cnd.andEX("u.userState", "=", userState); + + cnd.andEX("u.arrivalAtSchoolDate", ">=", schoolTimeStart); + cnd.andEX("u.arrivalAtSchoolDate", "<=", schoolTimeEnd); + + cnd.andEX("u.retireDate", ">=", retireDateStart); + cnd.andEX("u.retireDate", "<=", retireDateEnd); + cnd.groupBy("u.id"); + + if (StrUtil.isNotBlank(pageOrderName) && StrUtil.isNotBlank(pageOrderBy)) { + cnd.orderBy(pageOrderName, "ascending".equalsIgnoreCase(pageOrderBy) ? "ASC" : "DESC"); + } else { + cnd.desc("mpi.isPayment"); + cnd.desc("mpi.paymentTime"); + cnd.asc("u.loginname"); + } + sql.setCondition(cnd); + return sql; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/template/MemberPaymentTemp.java b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/template/MemberPaymentTemp.java new file mode 100644 index 00000000..de5d4e2b --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/memberCost/template/MemberPaymentTemp.java @@ -0,0 +1,34 @@ +package com.budwk.app.zhgh.staffmanage.memberCost.template; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import lombok.Data; + +@Data +public class MemberPaymentTemp { + + @Excel(name = "工号") + private String loginname; + + @Excel(name = "姓名") + private String username; + + @Excel(name = "缴纳金额") + private String paymentBase; + + @Excel(name = "是否缴费") + private Boolean isPay; + +// @Excel(name = "缴纳基数2") +// String paymentBaseTwo; + +// @Excel(name = "缴费金额") +// String paymentMoney; +// +// @Excel(name = "缴费日期") +// Date paymentTime; + + @Excel(name = "备注") + String remark; + + String result; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/controller/SourceChangeManageController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/controller/SourceChangeManageController.java index dac9a17e..4584ffaf 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/controller/SourceChangeManageController.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/controller/SourceChangeManageController.java @@ -10,7 +10,7 @@ import com.budwk.app.bpm.service.BpmService; import com.budwk.app.bpm.vo.BpmTaskApprovalRecordVo; import com.budwk.app.sys.models.Sys_user_history; import com.budwk.app.sys.services.SysUserService; -import com.budwk.app.zhgh.staffmanage.member.service.MemberManageService; +import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService; import com.budwk.app.zhgh.staffmanage.sourcechange.param.SourceChangePageForm; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; @@ -21,7 +21,6 @@ import org.nutz.dao.util.cri.SqlExpressionGroup; import org.nutz.dao.util.cri.Static; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.Lang; import org.nutz.lang.util.NutMap; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; @@ -48,7 +47,7 @@ public class SourceChangeManageController { @Inject private SysUserService sysUserService; @Inject - private MemberManageService memberManageService; + private MemberCommonService memberCommonService; @At("") @Ok("beetl:/platform/zhgh/staffmanage/sourcechange/manage/index.html") @@ -118,22 +117,24 @@ public class SourceChangeManageController { @ApiOperation("人员管理,人员全部变更信息查看") @SaCheckPermission("staff.sourcechange.manage") public Result getChangeInfoByUserId(String userId) { - return Result.success(memberManageService.getMemberChangeInfoByUserId(userId)); +// return Result.success(memberCommonService.memberHistoryRecordsByUserId(userId)); + return Result.success(); } @At @ApiOperation("人员管理,人员当前变更信息查看") @SaCheckPermission("staff.sourcechange.manage") public Result findAuditChangeInfo(@Valid String recordId) { - Sys_user_history history = memberManageService.dao().fetch(Sys_user_history.class, recordId); - List nodeTasks = new ArrayList<>(); - try { - nodeTasks = bpmService.getNodeTasks(BpmProcessConstant.MEMBER_BRANCH_UNION_CHANGE, recordId); - } catch (Exception e) { - log.error("FIND_AUDIT_CHANGE_INFO BY BpmTaskApprovalRecordVo error:{}", e.getMessage()); - } - - List list = memberManageService.compareMemberChangeInfo(history); - return Result.success(NutMap.NEW().addv("changeList", list).addv("nodeTasks", nodeTasks).addv("remark", history.getRemark())); +// Sys_user_history history = memberCommonService.dao().fetch(Sys_user_history.class, recordId); +// List nodeTasks = new ArrayList<>(); +// try { +// nodeTasks = bpmService.getNodeTasks(BpmProcessConstant.MEMBER_BRANCH_UNION_CHANGE, recordId); +// } catch (Exception e) { +// log.error("FIND_AUDIT_CHANGE_INFO BY BpmTaskApprovalRecordVo error:{}", e.getMessage()); +// } +// +// List list = memberCommonService.compareMemberChangeInfo(history); +// return Result.success(NutMap.NEW().addv("changeList", list).addv("nodeTasks", nodeTasks).addv("remark", history.getRemark())); + return Result.success(); } } diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/specialstaff/controller/SpecialStaffManageController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/specialstaff/controller/SpecialStaffManageController.java index 29f8cc4e..bae54621 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/specialstaff/controller/SpecialStaffManageController.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/specialstaff/controller/SpecialStaffManageController.java @@ -101,7 +101,6 @@ public class SpecialStaffManageController { public Result addSpecialStaff(@Param("data") SpecialStaffVo specialStaffVo) { SpecialStaff staff = new SpecialStaff(); Sys_user user = dao.fetch(Sys_user.class, specialStaffVo.getUserId()); - boolean isNotify = false; View_user viewUser = dao.fetch(View_user.class, Cnd.where("id", "=", specialStaffVo.getUserId())); SpecialStaff specialStaff = dao.fetch(SpecialStaff.class, Cnd.where("userId", "=", specialStaffVo.getUserId())); if (Lang.isNotEmpty(specialStaff)) { @@ -109,26 +108,23 @@ public class SpecialStaffManageController { } BeanUtil.copyProperties(specialStaffVo, staff); if (specialStaffVo.getIsManyUnit()!=null && specialStaffVo.getIsManyUnit()) { - - if (!user.getUnitId().equals(specialStaffVo.getUnionRelationUnitId())) { - isNotify = true; - } // 如果是多单位人员, 更改单位为工会关系 - user.setUnitId(specialStaffVo.getUnionRelationUnitId()); +// user.setUnitid(specialStaffVo.getUnionRelationUnitId()); +// user.setThreeUnitId(specialStaffVo.getUnionRelationThreeUnitId()); +// user.setIsManyUnit(true); dao.updateIgnoreNull(user); - staff.setIsManyUnit(true); + staff.setPersonnelRelationUnitId(viewUser.getUnitId()); staff.setPersonnelRelationUnitName(viewUser.getUnitName()); + staff.setPersonnelRelationUnionId(viewUser.getUnionId()); staff.setPersonnelRelationUnionName(viewUser.getUnionName()); +// staff.setPersonnelRelationThreeUnitId(viewUser.getThreeUnitId()); +// staff.setPersonnelRelationThreeUnitName(viewUser.getThreeUnitName()); +// staff.setPersonnelRelationUnionGroupId(viewUser.getUnionGroupId()); +// staff.setPersonnelRelationUnionGroupName(viewUser.getUnionGroupName()); } staff.setUserId(user.getId()); dao.insertOrUpdate(staff); - sysRoleService.clearCache(); - sysUserService.clearCache(); - - if (isNotify) { - SysUserPublisher.notify(SysUserEvent.builder().userId(user.getId()).memberChangeType(MemberChangeType.UNIT_CHANGE).build()); - } return Result.success(); } @@ -140,7 +136,9 @@ public class SpecialStaffManageController { public Result removeSpecialStaff(@Valid String userId) { SpecialStaff staff = dao.fetch(SpecialStaff.class, Cnd.where("userId", "=", userId)); if (staff.getIsManyUnit()) { - dao.update(Sys_user.class, Chain.make("unitId", staff.getPersonnelRelationUnitId()), Cnd.where("id", "=", userId)); + dao.update(Sys_user.class, Chain.make("unitId", staff.getPersonnelRelationUnitId()) + .add("threeUnitId", staff.getPersonnelRelationThreeUnitId()) + .add("isManyUnit", null), Cnd.where("id", "=", userId)); SysUserPublisher.notify(SysUserEvent.builder().userId(userId).memberChangeType(MemberChangeType.UNIT_CHANGE).build()); } dao.clear(SpecialStaff.class, Cnd.where("userId", "=", userId)); @@ -151,18 +149,31 @@ public class SpecialStaffManageController { @At @ApiOperation("特别人员管理,查询用户") @SaCheckPermission("staff.special.manage") - public Result queryUser(String keyWord) { + public Result queryUser(String keyWord, Boolean flag) { Sql sql = Sqls.create(""" - select id,username,loginname,unitId,unitName,unionId,unionName from `vw_user` $condition limit 0,10 + select + id, + username, + loginname, + unitId, + unitName, + unionId, + unionName + from + `vw_user` + $condition """); Cnd cnd = Cnd.NEW(); - cnd.where("id", "not in", "(select userId from special_staff)"); + if (flag) { + cnd.and("id", "not in", "(select userId from special_staff)"); + } if (StrUtil.isNotBlank(keyWord)) { SqlExpressionGroup seg = new SqlExpressionGroup(); seg.orLike("username", keyWord); seg.orLike("loginname", keyWord); cnd.and(seg); } + cnd.limit(0, 10); sql.setCondition(cnd); List list = specialStaffManageService.listMap(sql); return Result.success(list); diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/specialstaff/model/SpecialStaff.java b/src/main/java/com/budwk/app/zhgh/staffmanage/specialstaff/model/SpecialStaff.java index 1be95f19..2c3703d4 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/specialstaff/model/SpecialStaff.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/specialstaff/model/SpecialStaff.java @@ -30,6 +30,9 @@ public class SpecialStaff extends BaseModel { @ColDefine(type = ColType.VARCHAR, width = 32) private String userId; + /** + * 人事关系 + */ @Column @Comment("人事关系部门") @ColDefine(type = ColType.VARCHAR, width = 32) @@ -40,6 +43,11 @@ public class SpecialStaff extends BaseModel { @ColDefine(type = ColType.VARCHAR, width = 100) private String personnelRelationUnitName; + @Column + @Comment("人事关系工会") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String personnelRelationUnionId; + @Column @Comment("人事关系工会名称") @ColDefine(type = ColType.VARCHAR, width = 100) @@ -51,25 +59,59 @@ public class SpecialStaff extends BaseModel { private String personnelRelationThreeUnitId; @Column - @Comment("人事关系三级单位") + @Comment("人事关系三级单位名称") @ColDefine(type = ColType.VARCHAR, width = 100) private String personnelRelationThreeUnitName; + @Column + @Comment("人事关系工会小组") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String personnelRelationUnionGroupId; + @Column @Comment("人事关系工会小组名称") @ColDefine(type = ColType.VARCHAR, width = 100) private String personnelRelationUnionGroupName; + + /** + * 工会关系 + */ @Column @Comment("工会关系部门") @ColDefine(type = ColType.VARCHAR, width = 32) private String unionRelationUnitId; + @Column + @Comment("工会关系部门名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionRelationUnitName; + + @Column + @Comment("工会关系工会") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionRelationUnionId; + + @Column + @Comment("工会关系工会名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionRelationUnionName; + @Column @Comment("工会关系三级单位") @ColDefine(type = ColType.VARCHAR, width = 32) private String unionRelationThreeUnitId; + @Column + @Comment("工会关系三级单位名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionRelationThreeUnitName; + + @Column + @Comment("工会关系小组") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionRelationUnionGroupId; + @Column @Comment("工会关系小组名称") @ColDefine(type = ColType.VARCHAR, width = 100) @@ -90,4 +132,6 @@ public class SpecialStaff extends BaseModel { @Comment("特殊人员备注") @ColDefine(type = ColType.VARCHAR, width = 200) private String specialStaffRemark; + + } diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/specialstaff/service/impl/SpecialStaffManageServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffmanage/specialstaff/service/impl/SpecialStaffManageServiceImpl.java index 39060bee..4be5c541 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/specialstaff/service/impl/SpecialStaffManageServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/specialstaff/service/impl/SpecialStaffManageServiceImpl.java @@ -43,13 +43,13 @@ public class SpecialStaffManageServiceImpl extends BaseServiceImpl u.welfareMember, u.personType, u.userState, - u.unitName AS unionRelationUnitName, - u.unionName AS unionRelationUnionName, u.mobile, + dict.`name` AS distSpecialStaffType, u.birthday FROM `special_staff` s LEFT JOIN `vw_user` u ON s.userId = u.id + LEFT JOIN `sys_dict` dict ON dict.`code` = s.specialStaffType $condition """); Cnd cnd = Cnd.NEW(); @@ -88,9 +88,13 @@ public class SpecialStaffManageServiceImpl extends BaseServiceImpl id AS userId, username, loginname, - unitId AS personnelRelationUnitId, - unitName AS personnelRelationUnitName, - unionName AS personnelRelationUnionName, + unitid AS personnelRelationUnitId, + unitname AS personnelRelationUnitName, + unionname AS personnelRelationUnionName, + threeUnitId AS personnelRelationThreeUnitId, + threeUnitName AS personnelRelationThreeUnitName, + unionGroupId AS personnelRelationUnionGroupId, + unionGroupName AS personnelRelationUnionGroupName, userState, personType, mobile diff --git a/src/main/resources/static/assets/mobile/svg/memberPay/hf.svg b/src/main/resources/static/assets/mobile/svg/memberPay/hf.svg new file mode 100644 index 00000000..44f321b0 --- /dev/null +++ b/src/main/resources/static/assets/mobile/svg/memberPay/hf.svg @@ -0,0 +1 @@ + diff --git a/src/main/resources/static/assets/mobile/svg/memberPay/icon_xsgj.svg b/src/main/resources/static/assets/mobile/svg/memberPay/icon_xsgj.svg new file mode 100644 index 00000000..967d95d8 --- /dev/null +++ b/src/main/resources/static/assets/mobile/svg/memberPay/icon_xsgj.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/resources/static/assets/mobile/svg/memberPay/money.svg b/src/main/resources/static/assets/mobile/svg/memberPay/money.svg new file mode 100644 index 00000000..a104a4e5 --- /dev/null +++ b/src/main/resources/static/assets/mobile/svg/memberPay/money.svg @@ -0,0 +1 @@ + diff --git a/src/main/resources/static/assets/mobile/svg/memberPay/payFail.png b/src/main/resources/static/assets/mobile/svg/memberPay/payFail.png new file mode 100644 index 0000000000000000000000000000000000000000..9bd2a26b82384fd756bdd56da10f9aca14d2ff59 GIT binary patch literal 116813 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%0D7+P|fwo=i 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

F7W90Nl(X=9)ak4Q!@rtnzN23;q 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%0Dk7Q|H-XfI#* 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 P!47#D73msD)8PLLd|A5u literal 0 HcmV?d00001 diff --git a/src/main/resources/static/assets/mobile/svg/memberPay/paySuccess.svg b/src/main/resources/static/assets/mobile/svg/memberPay/paySuccess.svg new file mode 100644 index 00000000..1cda4d31 --- /dev/null +++ b/src/main/resources/static/assets/mobile/svg/memberPay/paySuccess.svg @@ -0,0 +1 @@ + diff --git a/src/main/resources/static/assets/mobile/svg/memberPay/wx.svg b/src/main/resources/static/assets/mobile/svg/memberPay/wx.svg new file mode 100644 index 00000000..6ae981ec --- /dev/null +++ b/src/main/resources/static/assets/mobile/svg/memberPay/wx.svg @@ -0,0 +1 @@ + diff --git a/src/main/resources/static/assets/mobile/svg/memberPay/wx_img.png b/src/main/resources/static/assets/mobile/svg/memberPay/wx_img.png new file mode 100644 index 0000000000000000000000000000000000000000..dd3d9e2f0f302231c66adb477aab22573f86b629 GIT binary patch literal 62232 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�!Mf!4 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 lfNz1J=>P8_5#FH--j=gBowfJAmV diff --git a/src/main/resources/static/assets/mobile/svg/memberPay/zf_img.png b/src/main/resources/static/assets/mobile/svg/memberPay/zf_img.png new file mode 100644 index 0000000000000000000000000000000000000000..c3ae16bb2353e7c95e20c33da86ed4f84123d9b0 GIT binary patch literal 124448 zcmafacRbZ^9Pcs8mc2z*vR4@y5k&}PXJjRN?@b8VMRo|0h|1=WagwYQvNf5sHU%jQDFT6@&`?*shd|)XA`k?xh|j|- z!K=Y`@EeJ{x``J8K}L)F4-b)@%Y;CXYCGJ#sjK_g&D+iEv70-m#?70Y?w)Rs9Gu}_ z_)p~B_cKo4V^Eykv%6rZGQL@p=^TOJ;;tnALS<4!m4>i-LPc|kb3JJuluOE#awJhf@9}ff!UI?eA;Y zq|0Z7;7mo#anUT3;icR|d=b(ALWlUmgm{1dgDolIIRfDv5Uj$5sGvZs{nJo9hZrwU zpJGIe7qOKSBNFitS^T$o@NYCD9vVd46T)x*jCfUfgG+?4y$Ubfq)y^Cet7FSgm02@ z%7q&b5#d=XLf;UaGWdv_7is$mIJF2~iG4@Tm0P+;H>l$w+WTJgXKH?zq-%IF#NxNL zIk#|W;j?p%iWTD(sz)S?T)CM!+_dV;1X=^+2n5T)aL1{PQp)o0#rfZlmYp&Gx{FSo zHr==sFJWg-Tb|()BB<^TVkRt?mPQHOQF!ltkWS?f5EF)o$Fm3Kl9ME_Oi70V4-x`o zj&EGdFVy`a&(20lMz+ptUDzsyPEb6PoOhc`2;GJMdpa4oiSWq2k@c>B{heRE?PseLU7Uu0fYe8x_!aFIDwY?~4VRl`sh`N5%1Cv`YJ-;y)qGb2VG@5Wo`$1OFJXJ)p^w$`V%44T{6nVv&rB^bB!tReh-s}Z$vvgE zP8#PLAZE-;BIL4Cmr4tN&AIZFPLHemi|1?nauvr^b9L@5VNW{QM6(-*DU)9~CE}0c zTW*U#kEqon_<`?pqwx&~OMK5OuVHVg3+CY&MNY#kA1^9|*A^ zQ$Bk3%gXFotlGmkV-`LXgUyohRm0?~HtfdIzVxi^`BoTW9{hxG+BIT}Csd!EBU4gt z8*3Tge8aoO{gI}L*oY+RiTLNsTT%>xODMSKCi`PN?OZw zbsoyzw8gummv~boG{`iZ)F;)2U*CVN_?^ljSBq~o#ie&el?s zPRv2fWlZ(VqFGv{=SDKKzUYgMNw8+wzr66$&A?b-S0I=^^()N_xfg~nLSHOb=o@$$ zDE$nmAk%+qaN(_mVMysMgAcmsa*`hmZ-17v8#I?+s~WiHcQ09YP|vcs&GIDj(1xNm zCi>Q^81-U(oBAH+#7hi45_VW)l~GSaf>j}>m)h13Y7f@5e9s-R`icf=-M{Ho@u>1q z>Z82h9{qTfJvDQivcGcg3|tzZ7zh$35LObd8FhU3=w0YL>50IJwh8NX&vl0N)d`G` zd)|#ap}ZYA7r8wjlBR1-dQH(ylRkrg6-R7V16D|OzV1-2Ob_4Qarsxg!}u37iW%mR z7Ly{rmcr~TE@QL#Eyd=K(@Tej;ms%WZ>akoH>GwxE*{n>zTCjK5o?dW>d&b7sM3wi zx>9P!ZpumC%GyC<@^#ni?!~q%{m-4UA2khs9P$44?TgS<<#=W9T9WL~T&H}iwqGri z$BEG;YPsEa60RknGA1&D`_5%(XY5tJG*mPUFx)X5tJD}ZTNPS$88vd&Wi`qn&ymaN zt9$b<=Uta?j>|0F0$uWz?^ky2yH1F&9j}qDWv`uIm)*76<=u7J9c2H;M#DaO-TQj5 zr?<~HUuXB0)z|Y8SlH4#h1Aj1opjHV%cc= z{%K^VIHx&h>fJAwAJg9yxUQK<&9r?81d4?}`Wu~u( z+&p|7qjSrrN0LP6o?t*Kb6O+!wzi?_=uG9{FOOfsvd?p$=N8|iaLD*5I3`xlU$65> zP%xchG2pk$SJw2{uX~H!2VUEg^v=;*!^I!(Rq0YPXo38MqVfGx~{$o8N1)^>^6(9@6)?uQuaEcft6c z!Iopd)K=2HsP82uHw7b&q+XOi@9lG~`e)i`LvQuM)&S#}`SXEcm;mDo%S!jkH&y%Z zZ#Dd0FuH5`Gk7P!WnyCHPW{*QRrS@^tFD!MCdleLt&Yk+hhjD<-mzj6msl-b?#y@> z20HE}^?&UD+D~xR>gxJ~Z*`TETZPw(cLVdn%=-*a-o34F`^7ggik$Wf+NO+Rr@uaf zdA`>2NzmWOsZ}jx$MyS0{cj$D(Z9kpv{N$jLAfjD0%&MceoAXpP5?M>) za_?H=MRhs%rJQiLiJbLpzfbO_0+gSXmpU%bmIeo*b^jC&bWU~l&t`?y?+~x52MB(b zL;6$-7rVStC~U?2c~+dqZoz)Lt^O<&BaXK5L0wHY%72x|uYf&Rj7&$D*_P$!-BnWf zku?>tr*)j=WUgo4YJYPuUy0FsL#y6$uXlT9IoW)(#r+@Gp7kVez2-ZGDuvsj?kDr= z)eqcO?e_ZCjpVDm|7ovYAI6M?9XhuE^cveA6EQCcXvOrbvDUltO|v!dHtp>D?yfWX zk#1;BnFl8OS0A@coctv^yzn>d<7tguyUX1E!}f=RohBDBlq9kFr_awuV&}i#{&xE( z_bu+kFYPZo|e2aS)%H^~kX29Z?(<=dW^ zx8>DxC~g!-%Rqnvw)FVjz+?!f0n;>#YURk{KfZCQyFGkpgDM-+*;8B&K0OxQd$N7R z`@KLC&?cvi`aNv~B9Iq>2#-P_4$k2B6$HXZ41xIj5P^_;i9j&ArCE00Lf}nmYp5#g z`%kQ$_<7s@3Ykp^)v3Bq%}=Lt3FV4Ny!&TLawJ`rCzj1oDDHR3msE$q6$Q;v^Tkg) z|MH!Gk+x-21?+rWTe@9h7pGaIIzlJxz+bA7JJgvqKt27(b&-uU`m4|1u05jnd-{c` z_lt**I?qwE(BGYzJvmypoMS`bMRhzBV|un8WnUJK`x7}|8~J(MYgjw@3;d}o^Z$DJ z<-WxK`SN*M%m2Rn|MT+0g+APS|L^Z+(h6q&@2C8~U$zl`x_Ur`^2n(p*xA`hv12ZE zh+J06CX-2ua=u2E*>_Hv3W50L%#dB$f!Vv6#v_wNfbw`~!XT4WjOnwLaAzYb;#V;+ z;7QkbQ*j45R_C%Qe<2AyCqqf79PW^fNI7f0geXZu)8X;s>0Wp><&m3$mf=l8?>kQ# zvY}ED#7SuP0k)jL(2Mk=UNgS)jlU7&2qD*wh$W71ev*%))b1)`-b|jl5nb*kJa4xJ2gO(Zi zEi*7DBhtSeoQrN?LU~a4)t+BIV_%XHp?sKzmf?PJN12N7O$BLR?Vr6A?A0?x&9V_H zHR@0#M~oF`me%Lx?T$JZC_@-F{pq4q*V2u zOs=0td8qTHGchy&`XTOsio;YfuP8QQdGeQ&<&wN6YAb2$TsW?g7n_dxWIAMvY1777 zwM+F!vc@k59DbO(iQK$p>3YL#|1MGK!#jjI4f=!oXl9NLBB3#-8WJ z$dX6PeIyuAJh8g=X1irA@gBl*4nN;*h(o6lYU#5 z8jOkK_m9~}ZjIY@ESgrrhWn-iSjYT=cWrKlM^lx%vSu5Yw~fe*=8d<%!mLC7HYJ&f z5NVI3^xCG}DZzbd@ul7^OYK{FwJKMj#V1JK`6h*D<%*i#s|o>IleTZ$$2o|ZMVXCj zD365P!35QMsh;TC|K(v4g3GT;46Yycm~B_eL|~^HGl-9if`(KhKK^2ngt! znLT?b_Oz&oOW?CeCRrMfGSw6ORX^SY*H5Eg9V@>rDb^d31t^Se1YWGz$<6HdJbBmS z^`7NIyCK`)z0tWl42zCJe|~OYik+h+NY%z`g_vR@%tT_HuO+B*MHmakWMwg{7VAAr zPPTD&CbzM%d6}E5D#fBElDVo+S2BXe9%olnB=KmN%MXUdq8rY7JB)b8J>WnpD4-#j0s>@R<@VcOO47fm7W z#_ylsHkrwL4li>*Ba(DYJEM`7qPFW4BduI0FTe8a*|S$=Wkjv5t$#2WR96=vyyvpa z-B=WQW%K9+DcrYpfk)%;{NVOk`*zC!UtqIwuxwHkkA@P;W2(AzWTiMx^>dy&&nte? zinnivM@M504+Gbxn;EsWwfRLw;cc!^nbuN%__4Q)%s*?J7IUv0HE2Aa+?k{_li0wQ zW$byOduKWh)qH=WIC#F_@~pq!*uWrqaJjg;{^Lho<-2gLE?(?u4cc?Z%qaZ(_it`v zx*0B71b=*ikbuD9>xv3=Qx($2Wb`a~`QU?Au-`AvIhg@_I<28T6L$S1(0R9Q{l}4=Akysvp})dWCWk(6pM<_a z^w_EzC)Ev3s&Jt`#Er2h6rHaM^yto6R5Nxwq%trtkO|%wTfoYcmX^97?YfvXxZ@dB znJHUZauf|eHqKZYJQvk5SYC1H$A&twPeLo&E*zyKh@d3JGPypwGAM;0Pz#i^;|H^^C>E#oq6r!(Ga|JCfqh)!<}) zG`X_SoKE!i-30QJ>FvJOFu^XD5}%WjU8kCz#c6kiQP0+`g5f;=wg*1KhO{l2ZqvUX zv>-V9BoYIz2n(x)geaJrnhuSR6GIPxNx*d8c@l09^vfdt&uHwcmKHW)VPXG`#$_=v zv2a17s=4nanhoA7G`DWu;_Tb%7qY!evB0y~PvhA#&^&W?$XCuLI#WwRg1Retb*RVL}? zwVY@xChwd&mz!fg-v$O2cGoBUkJjt4yOVBc*fyvKdU|^3#9<{PD`z+Lo-0fEVn(@G zFTB_<9dUp@SX5LrdyO1Do1C27Su3!t=Slpl@MDR+S8$3B|^cpeK6C z!)Wl^w>jLN?ff*tqB+i(Bqb&JMMQ4t>FJqLJ+VB$naPF{$A%0oTo3yYOxlj=wysI~ z^~(g_V=kJ}q8+7l>LDd1)xPe_NY@0Q4W<(T0Rip+Jg^IDwjWGXxv1gS=NTEWk6PN= zmuTWR(|d;^?q=A@9dXZUkUH?kmuHmlx;;IW)3^RAghyBy1 zPy1{3N(qb>{&)zO=T;^R>?1zrx20IRq3SnVF(DVKTX$J%e?gxYc*Xy$J|K`@?+4RtU}(YY^*Mx&wZ2IaTO+xELfi;9a0y1Tm<72dnBDi&NoxUY^1=PHF= z#I$Tv_MlMnzRmO72LL0e;#8@UQH2gHS|hLN-%Ytn%U`^pZ%|^mes9#d?V-r!_kAZq z$5l&}OY82Iij}J_&9Xc8(nLkhqg`uyp7%w0+sMK!g;E?#W*Gx*7~(%wt$wkUILFLU z=Q4u*@aD}^kps12Js4MT^z-92Hv2!y6yX5<@n8;&jEuY&A}iwmj$vnJ?$8O{qCM`P zJ*IG-X(2(*CcDd!n~#O*jeJDXsZnRxiDRcJvHbwJo2Rb=9`N(^-8JT+>F9_e!bXb* z#M%4eVlz>BkfQ2Ig)pmwdtSk z>mw1D^-DNOj1!H*y5GI%Te~m9_mRxYpYc>-mLkvXAPq?y)mi7V z=qc;i&k_>>Cz`)J@7btpViGqoVfy+W4nDNkxqPX8R&dl<(23k}|{BSEKdsV$-OPE@`r49?- zjFw%D$bB_7Iq#>Wm$OJ3r(JRVPw5n!j4kFkAeEpgb;OYJQ_h07asqv))8u+OH znnxqyJcp23r@8Sj$1C$@e?OH7ne(+>M|p<6+;h47Ahub-b4QtN)>@oK(4;NlM2HU4 z-6e1NYFkZq)=pbqQuP^a9O1jv>I#87ckbvK84(#643CUN<>y~yll3IDJl)E~e%BNQ zI01d{ySNebKe)@cl@6&-|LL63L95~y6ujx-fi;%M3cjWH{JK_fy>9S1<$dX2&bv+k z^WIceb}cKN1+*M*^%2K*>e5BegfDUhuRfUl+~~C|CMii^V36AXXn1OaVAC+Cx)HY!sao~ow*6TIQ%<4&NMMOiTzm}N?)c^ za7&DdaBv&=jB7n>8qfU6-YiPG4NEcA=tX2_XQ$3X^JjH63N15^3{w&i6vUn$VeZ#U zk))VbUi$o*)v<=vuV(JePva_063m^2=4qAACy5>Y{(K~4!lNaGzPxxA0|FK@Gt?et z4Z*j1w5+LV^#BbHNhO;0ym;|K#(fTJ*_DYrwsX`Y*0z` zmFo=j^j40Jq-Q(GQzNq$|5RVzrqB~P|9n*8%~+_5*pQ>$`A=gOokSeLH^^M5jJBRDQ*|#rYKN#y8su;H2#rWN z{C&hp)s9Y9N&*m$YfwzhWF>iV@W)Vcu@i4`-)ix$W zw1Ldt?I6JYwXatwg}uZFn><-2@*Yz^BkF?}hTgiXg{v1LWW{1yRA^v8dzPvM&cIODmrMxM-KVyjm7aUT_pIXlHr zQ^ty4zn&1Zw^7*G$c&qG0NJc-n1U5K$UEEXktZ&|Cjl4H6B?!ddTD3!WyurfYg3h^ zU%cF@g_uVy(G2+B znPrXf+LFFNv}o8tpa0SeBi;M=36jtt9N|YGVq#)8gOGbc4gOdzl|rh(z`&ILN7!$Y zgRdGJvqnvKk4^xE&mRAl78e&+*1VPGDA3i!yJ3S9!JHF)w1lj`r}TKR!BX`N4CWa_ z=NTVn^8s6hHYbrqK9H}F@Yblh2sVhFoxQy7Lu+PW^3d7ngvm2k(9; z=vF#gK4V*2TKcz`@%;I#>go%Y2Vaeb#>QgZWu8@4i99WOIvD(0@=ZmBiWEz7A%K%NrT;dE%kA$nQ{|PW6A=ZO(X5i)wR7NaXGnoBg+taQRJ}% zoGg?Cd;}cU!xdTU-poz;i>Nr-%b>1>u4IOi$Pc1N3Qnb9eL{VaLVbV!{AsT~JFJF& zo_pPo^6J&A1wh4*khsy)<7U)d!Mnn(8bD?)-y%(@oJp`P9??6##j!XZ=~8z$m&QkDUgB)}(V9{Caa6 zVbSb|xroEnXa5RLX`wQKpOSap00a)jw5f^wr};8J{}%Msoz<}#Ka2(L^N5iXlUmktfAMk67f>t5FJ8q+1 zau0XCPZxDg2`%?OGXiRSY;s3?WOLv;X0ASTwO&j{<|**R{ouB;Y1h5UQirObS!kah zx4ZVz3yv3?q?r#Y*@V-!&I3y%we-e2z8Oh(g{<2$kj^W9~bp$GcKzi@!_{B-roU?(*F#IHnyK|Q|y+r6_5QBrQsG4PD9(ws2f;Gi%GmX6WV|zpt z1ztEoD!QG7?R%U|&;;`{m!6WQ@B?go4u@dwv8%y$^48S&9DC- zt*ERbp6}_y1sQ~r^flQebFpiwnY}W<$FH&VefI5s)ds-kv6~xCL}DL12~~2Q>`^*J zD-|J;9H=DrsH#<5r)k^$R6Q?fd2lDepyPAjEeG?Pr^0+9yoDo(r9;d4~4g{ zFAhTfPf4v`568*-P z@Yg^S!1{0IVSjFrdMHL* zJvMn=O6o_;ObLqpN}ENspZNkSF=3n4)ag3%q#jqe zdKMN*Inr(ma~)CpzY0!FCfqW=?SmAJLU+`+?Ff@!xZsvQen&#Tfa9VLqK=@!TtL<2 zi5>o+ys!TlIr-UsCx=a-^|Qnj@*alG644NcF%EQn*k1;!zU(~pleac{RHI0VjdgKFUjt_c19GP;}REs-d$)M3}(67 zF;t~A@HFeDM0&@cA>za4riYJeSr6NGcYXhB@PKUDkDMo=d4z+oZ+Y_5vJiB%vb%Yo zVc_HTy?!>76@A%Sj0}Lv}q4D-)9qwmc z_uH6jo;}&QW=8V4hOtn!2ev7;hDK9R`kN)Cm%#Gs7K#jD!u z#71K`Jg+<^VH`1GSkcL{Eby-B`El?`+o83sx)t!%&s}r zm?iv(KB^sBt^2V`Hj9>_REZ?M`&@V4vslPDa#*4NPm?>zin?w8(Fyc+!k<5X0*wPX zvJh>_m3ku}K(_5)iRe6B)w38VhT>13=y9S$=-FNvN7yD&SU48zkxg*C_F-`0>kGmC zZKX3WXz-b6nJ`&N$?e8Gsg(zr`@cOK4Ul7KEE@yie1VR(_I%@Ve&^uX@!&{k3lQs6 z^*N>E*t75l^{ySOJJz6?!puWHiHSK6IG*7(MXG60*vVK}qPJXY6+xBb777qO2tMuX*_P+gi0oU6 zSqTtX{rW`C)|FXz$oo`#1)M%vWu7#)0;;fQw zQIALT@K(al0pUN(e`V%+cM+Qb<}D0$b>C+5t(aI%|8DxrQxRVLWlLAet>O~QcF%!~ z^XpJ?)X>q)x$olqGhF*8p92EqHMqr{Qn0OEd( zjxHov9&?@kNj@b8#RwxyteH;%v_@M%nds`-oT(B zkK=uhTp161mpU0@Y5%ge`CogsQ?7;?(4Sa3N z>qMt4#*svZ>+(NYSg=-4Bh((DO6Uf#T(~M{YhvL&`es!QpdVd=F?>@4hjuZOwEexAFaFgUmKNeO=3`JJW*oz-`y_rTPmj~?H+7z zvPF)M@N3NedTF{uo#yS|%%EECRuO(LG`O&t2b*Eh)H%?{qZCxP9u$%E~>%9u{7C48B%k%CpZNrCtiyY9t-Z5@| zouMM|;xni~-&dpn<$_Cxxi}<6G0`GMgW+09UIi`Mfo0lqOD=8@JQMI>Gy77LygycX ziDX9ImZlQ9qTJngMmQ#F`FTH>sQ4!cCQ;He{!!=eFD0A;y} z>C_uOW`bzj)B9z2_540euJ^zMz%GZKE(2u(MdK!%uHxCjppB>JRvRlX74bt53#yT) zhuM4eMdj@M!Y=MtXdELQBUYdM%l#MF`sVH1o0^(r(Bg5F8=3$hJ75IR`f>8Ni;D|z zFq{SG=O+yqSj~;H~s-LtEem z;S|mOM;^ekfuZFwFkI$BGD|L+8QT19#Dlv$iz(Za>P3BIG_GH?c-2R?o#AlWTC1x? zCbSqJZaz@Ni&>JPlt*=Zowb;`M--5}E~EdYch{^+R%a-X&^W`cy{^zn?s=zdsh;cnatj;r75X+JfHlq`ulp&!Is^RA3t8Twz7k=EcKEU z0dos0skAK#RG_Cjfw9JIR?*wXXI?sNTRJX>8Jr6`wU*7#WDV}~__%S*MMeArd|{^~ zbg;{1IxEx6{i;WE%Q6Etle=Rm6iN@I&P>ZtX2pW)hcUZ22q#rA=D~&&AfOyRPH41| zsp-)j|GBLcSykO{`qpW+Yo_(x8v(;Qzg9^k8>+kmy$Vu4eT)a!v#%89mrFEtC!)U+aPD%>tpG58tD zQfrt`l@=r&WkG%p940venSYu!99!pPin-oB<5~@!oy#NBQXls1|pK-SX#e9!@XxB(j2v@{vw- zC2rthEbA(L@nFIi!iDXkZhFE@c-S_EU&aKal9MHOxB{xBHN zNX<055dLmI-hzYU_Dv*IYFe?mf=zLo1Q={va-HSs-WoNT| z{P?jQaMb>M>>}3!*xA7QZ$PJ7>dUm6yawL0P#p=jW|pCP43DllP};H+yalUFYxWs>k9NYT!*=IsE|fpN!s^e&$0)P?@;UG`8E& zc%%M!CjjNa*(*_b(2?HoS5+_f!OVLh;(*UWeG=@Cx5+xliim?k!+8wvp9Ug@G|mlw zE_G0$Qd8e9;1+Qg#9U_!r?l?+dzB*Unx^G9?Y5+J{Bg>)MX6vPozGb<6vCd&Eek{# zfoPl8RuANO^q#bD&-s3tm@JL2M#BsMMcT1Djkg$QMJfg}HJVY{59W7+y5}JO1)AgV z_wOnSHmlSRt$zSC#d%&i{Y4)?(m}Q0gtwD{;M9R+`||4Q*oq3AJ!fRZ_$ekXs1cM6 zFnl{ZJ3)6G|6qRsx(1ZnoNqI{VI-K1AR4}^sE8-6b(z$~lc|W$R6H_iIUBhk7T{+m z?F|-;Q*~>MPRQT;006HH6{zz>f)x3mEZK)V)+CHl25fiS9JYtq^b6bb`ynhsjGx4z zl$2=^NP?5NG>T)DIM~@wvWQ$xT(g#(CU=p!P+I2Z>^R{R)_m9qEuZ6bGZx60_pSX8 zN=F~OYvei9^nfXYTDSgl_KAG*fTZZFme+(!p$-~jTBq$m#-af0fHViAADljjaY0 zhHisv4eexTYU-J{9OQne6S{{cCljP+gK6PPgXV>g^6=mNWe=^A#K2(L{66J1o2hIK zzN~oHhbegvV)JO(xjZ2bw>@*gQ`D1t#u6;)O~+rWU<1(q-flQ?|?n)omUA^u}0r<-uR zkcZfu3BnB5Xw#|f|HjNpCg=4Wv5D2i`^-UV;^Ayt2z)@{$5@mH8y_FvX0J{tjkN1j zJ2;{^@f?Q%bk6?iU~`ZMIWXW#YvcVQbo%>g(%O*f&UE&eK1M>+ z_A2GZMDLTgZwvWJ^Kw&HFTw@7cP|pq9JnxmwF&X@Z{c?H6_howqiQZt_0Hr7zNJh)1#XQ*%t)ThzLB$Qksv6OGre5WefEU#rP~SQSW9n zTIO$41`kQOKI!`U`dq+8zl|wnPzzfbw=bW!K-k|^iaCsmHS}?Yb{Jj6zjux#?do4# zL;B|rW(dv{0255FpPCSlh?1@SzK+5gqEc+<<_rM&|La)C`O@gJZtt4N5|M zByF6kE@%(QA!|0?rD}iOPLlyDL)4Cw7$5Xx>}N93htAGxih5XodC+*#(ahmY+5+9*?{sPj-I-U5Ff8WUMxE&NpsJP#Q0fCg%6#9^BwmILVM`%A2Gei*Kf zVK1Q%k!gx!xEnsDs{qir@&MH0f-*%D4sKL7yHlKSuJp-DO!#;U;&3c#r zB)fE)rf}b_ytkFt)&CNiczpIdEJ<~WM)SoQ*>9rStgI{_qgN8zUIWvAeWRihy}hYq zji^Xv#sgV=7a69qsQrW0Qp{bu(Bifd&4XJMFP_s8j;CtSQjZ%8-TJ@*VqB@ikCU7` zC6C2MOshMs4Y1%Q!@@w?ba?gX)HAxG0tyq9X8*Msl&+p$gwt4+732UxTB@k{{%`~o zGu-%M6t(Eu-hu8IccJ%XHg^6m)UE(2~PO%CkyM- zFig;F=fU=}9>{cHWXd0{eE?Xz_ij1u(|r9*pwrJIpT!kMJwvmWqRroKQO1B^xT%PB zog&EZ$`6k4D|d=-ML84sWGQq`N<;wdkHSn8{ZDZ1tH*rA=fDTHn`1q zL`52no0hO4Aj_zX`2gOMW3B{P2O<%KP~hUZ2uvvmgl#Q}xDB>~_V0pbDO8oi4sz^t=1um*TR1l>c+H06CQMfs7h&-J+OUakkYW9f@ok>= zKRsB6aio%jPEb=*gO8PPx~7g578SMpR|aL5w0xigF^7-!^^mVjH%*K$nmaz&_D3g5 zL!uGF?KlG(IU%| zXeoMU%o68cftUmNDWSg4Yiqb21UzJJnPQh!%AAT!jeS-*?2vtnn^Y%XJ`SiIoH{yI z>G%>LOt8T84W|D|c)JAcitpGuv(&k8gT(-1isUf=LN8rWjSTLthz%uobSOK&?l`!6 z%eV2>Vo3&d4M?*PA>iibhMmOGAb=1cDtT^4-%?is!Ye0LTKGnNUt3ZBeY_&wT6@c(Zyt_I&7j|5!$U@&N8v2b(Id7=Hg7DIh52@G2SKGj&c1b(cb4gyDwqE; z7S-Xw2C6=+b0%$-;bJPX^Sew;T{0htbqH z15V_pE0VO>sV<-UoP2C)hef-w%VG^npI>~-f~*kz6K@!7eKpy4et_y}qU{zZzBu zGWFK2hsgpc0V;~a(o&o7U<4Ecx?g%0w}%kd#i@0`t28r3rY}bV?Pe4)Gk)Rpx8P(! zY4T&bGCubg%^jRqtPi!V)0gcjlB;{#74fUl1;nGTPRaP^*l4=wlTp%Uc=mdO%69CJZk>N= zEyl#kbp4Kjw5z=Yl=8V~UyuY{CP7B*1{{xb?Ez7M2sV`D63O`xG!U4-tX~`XMtS3; zFX0uMS;(;k6jW3If(NGD5OQ=4@+lP+Kcc|(q#`DSit&J8zO4i^JO||U_^Ngk@I^JX zbK#Ar^$_QS_SgXpZgZoWZI@RFD>we zj$LL)k-+D`#i;?|9(-Zv?!zTbU<;{<2_f;h2}u(n-UUEkP|_A2Q90A^vl||NA>_{N z>sa?KZfm;;fQny0Km{ZMNS1+Dh132(ird(5#l__?duYfoL4U_(euDNyz@5h7H&BTS zL41UXg(Eq!o$zo%;m;aMHkoh~M;IIAJ%L$+Dgyu*7!aHjMA%^?rQDt7`|GLivMVNq z*}|h*l{xmX#w3aZpXYHYX=yEx2E!$%{=Ci>;&sRdHL!7>Wy3ZIP#-ith?5O*lOb1^x%YwxNAG>qY?gjDDDzZUB(NoX?T$G^;d#K3Ut_+7wOi`FVTO zf%fG6&e*uLB8!*^!UlNNA*|r5}+xtB(D=W$rvzFSP0nowbM`cUy&dHAZEdo1064&}1i*c|QpGc`gv7Tk7ess%?{OJQ+2K0^A2Mowe6i`jX*yg|wp`8D6SumBiFd2w2e~Oh8_x4#aEE}sb?}SLt#!<7&B%oag*#DOV zhKmjmKX|Wswi~6mD;{{4UabStBG|*#YVN$dkdF^l%%?_Xo!_hX@HXjt6d@z`LVtZyNorO!c z1nvm1p_GLfaN0XO^aVx=4xF*n0;~XeUR*&zfn&NH{3I*j?8}1%v5>Sa1R(`CgCKkP zbad1Z)Dh(oDO~6i&QPjE06a=af|jMev7JCARhwcYM=u9=aPcGQwL6Sf_j(Y#`hLS{sb;xPH0p7pOL}&eJomCgg=!PCg4IB ziTuuw`~Iu%>LD8bWO!K5tjU`M7b2&iBa7|CJ)TrvExav%CKFy?w>@KGB!9K{O5agH zev6@n#oZvGw9O4DF0S-m$WuaqjtKg!$;UekS0?f-RfC#)!#KAd)GjTnrYUA-mky_e z9t1QWNSAUFe+XTj_w|@13KM87CHBvn?C6xthq%+8C0gt_kIAj7(35SSDLbBsERD z;vU99gu`(`w}6}fzTMrUd0I-rQSt8q8lDE2%wBGu*DpTE>PKk=wJ8Mc4m~24AG868 z2Z5{C8zAbl5aLIuMZHrW-dN|ebdC$+L0ZYy__Et$E%FXldC2VJRl}!UrL`}C4wJ@1 z&(o4V_?yU4$h+J*y8FRA+BgCp{u3af-i{YK@t zPw&l`{M!N449`GhKPp>HPKUXV<6C-=(a&5BJsc_EVoAK0U`D3~tPO5DXz?mzJ35H{ zFqh>fOsOr+^`vcmffp(o8XC&aKk#TYKokyAZ;uh9!^O85^J);Ud~RggeBjPyjQ?Z( z;ZyLK#DVC+CE1XJ5aaE4_a$g~Huz{NbojUreEhci`j*_Ho`#)1c_`@MR<7m~BFT!! z^sKvwB%B0uZRoo$a?uGMwgTjNu7}bJLI&`dS!b4{eahW3h;Kk2(YUUWD&AUHhzH&V z=+p0o-og-#*62w4N#_^Hxggl*c{+FrG)s&;co0P@BP984sCG z_|iM%6QZpU#POBLk8HZ9-AvLg7QNhA%I3aG{E9|~Xi({dFiCNj&v0# z4DqW68zqYMW^a3bx+X*s4Ad+i)_dX$-3{;ba38(2&mJVO>7}$srpv>~O2U*ZKM1)H z)cxC(A82b5*#dqy@>;TTa9Bz`OsDz3TA`01im&#}ukr6^vlp-UP?3pN{ zBI2P!D3X;VjsN-c{=efrzT-Rk-k$e)?)x{c>s;58&B_O^sv1;&w6*m z%TBg1ymWYG&=-3ss!c@KLh(<; zjA&WMoJPD3qo~d{Dk!0SHZ&<*w&~;H;9Pqpmd(cbG#5Xk*?jNOcx?^#_^z?j^ekaa zEz~OCvNg1Y%Q=OCfvS1yksv{S zsxu958XKoSstU3(ss!!KnHSGfZ_#2O`=zbMa!8OWMYy3vfcKKFIPTwdqN{G$Hpv%+ z*~(Q5@~Z@Q(8h>*yOzivduol>Tt)-!eECfg_fs&rqgee%58 zPEJk@x3=LWXw^tbO1^sa%G26N5oT!n=9J>n`&&}w9vMwEh5ljvdO_ZQt$ttthtBcE zECTxi0BETO+5(05KY!mm=e^xPORLH9u5`(ODn!v%y-swG zB%;tGWDVZHT?W@zZ`nwBkNr}D-wsNdUgXj@|0<`LLq;mW-rfo4o}nC<s;4u za%v^=!TExV*Q7E}v`k-)JlwhbY}xtwt5MX~TTYD!Pd^Z10xlFM5@~EDO(`_a_KWnu zTfjd;>`WY-$3ft~xpF6V>!v#0`8{-+8cOL_-IC;UpJm60%VkR399><8r-9ZTk7}X- z#|NxYw_ge(k^%TeMXlgfajw-2EE6VQC1$s;rX?W+2ItQ$vKVsZ5_cxbnY8f7H+~*S zxB&SW%CrNY0>ms>mqbOBUCxNmaGR+oN!BI%{B>wu*42If`_k&AKig9%DHnIU1ZBA1 z>`s5r zepUzJoJ%L9o%K_5R%x<-zW&0C9}tkhgXbUi*Zf%;HvBgAV!;ZUy;aw>`}f7$NS*9R zOg;mTZc5wj`}ZBq^?Y+BKHn9RS%OIeYzgH1z|O#*!sIp0X|p2cfRCDBLr^pG?>v1i z>aDX5^nk#~Y;oycUb7K$TChVzSBz~-Y+In2(0KKWG{~evweXno}m?*1p-VGZXK~lPXgWm-21{_rs7;N-e z{kqRfq`_Vro0=NU0%n6I9aTL+G)p^ov6v^LuK^{*?Cw0LrfLo0;7Ih|Y{&%5wzr-C z&^W)ZU#!wn79u`Z2l2HG;j=TFBBIZX0u%JE7|5EewX@vRujM@gpjALFa_F;n#eNsF zpzLRT$x(982Tiyxit})M>DHQiFh)^)O`UFLtY@yN$Nj-fH$?a7Z7`p-RIo_HB$s=2 zw{@UEO9Oz)aI~~g1(erITDCpaGBJT&Yb~}DQ9HnJ0*MiE@Imu{;{Z|uqUgo_2BXaP zF`;EwUIv4oVp-ajy|5B$A+3;$p5S5VSx4Hr?;SSbMs*8iwI*sVAOg~Dd!Wg{>nFCA zgZBtD0F?lky4!hq%z1fPu!O+lMI#c}?|iuZ%tPG?AF9 z8IXMfDC*JU$As-50RXTJ;}pt@n?5Dpd)@5$o!=C+hK_Z1@QRpSaWp;lX6~(`n|Y^X zP)z=0!fZ7B^jYtlAsZKAJit!3>%7Lx%ijw{CnKK9)Lhf4Fila|l35_ZOqL7KH;~Fy zRGGnZB&S8E4ef848_}^4U?%s-J@Q2yA(zy=S^WeR0Sx$fMCkb*^__)_qPv@`BSVdJ zLBJQ#nxfO=&c8fv6Z@G;l3~&V=Sh78s(24%hpv+1WBF6*HDFkvN zBjEk*Wt{3nXY%X26V@=!07$Z6rJTqmayH@kkQ^saS>SvkT1HUw05Z@HZ6<&!dcCfD zhd^Qg3Eu?D5H2>;c;wO$7y|q{o4^k3i)INTL=^*e88(A#PPQ?B9EwtFen$UO%{aI@ z@wpK1YS|^jlJ0%Jm#$=MJL(>v{{2Q^pXBt^{@It)xA)IIXtha`lV2*mJerVv^igod z-QD+`HUQBkPf(KmDGdO2U+ajOOdzYk2O+*Y=5;o(n1E=geZki2p!+876(9@{X5nd} z>(|%UzlAIV2>V~ZZ?;Rfd&x!RHZuTQ0Fm#vrz()e2CoN^`8Yd6(&1}$?~j;nh^dE% z+~ey+c4le{qZYkx0&&rx=W3ktC;obP04pyAWwu~V5u2I)S!fh?g!X|9<+cazAums5 zo?MKo4H_RnVU>>#<70|?qXX61OiY|cdA+Ud&2!xU;d+pW3UgJek~yn@qwbsW2TR$b z@_S_%w*GGYi6kej)h*Q@kDhq{r&^&o#Vlm$bt%hcr*+?c?`aFX%`4+Vt=h(N659k^ z5P)pz7B3>wf_scG$AE!|Pd9fa6FlRc6LS`uGwC%oAdkit!Y?JP7>vW+Z{LFa1s7QT z@9#1(P2o9!&HYxjsWoWRKT&sU;X6Pfp&)F*Z-(`a1-~KSeGnsnZAc#PO_#dyVX5A| zOAiq)L_L>LQr^E0S=k;D4oy&OAr-YLh^0WC4SOU!@|A_~Fk`==E&yChQde58ZoIsb zi-QkPoJ*tIx7H=~)5~~`Czi7N#I-&#be<~xUOD#UcKfMP-@yPimQ)4aD{nQW_so5j zQ;gL%wEVH%kjv@gxM|{ZJ05Q9ZH1p4yyA)#&Z|oAmQUv0q-GjCzaU|)u}*OR-{)qM zYtxuM@0I1~oX2u84xxUv00Yr0AO;sx+OPGbJ8NH<1YUw;13M^1)~XTOE%1lrjIp%T zcQB7OPz05M3WgVSxRC8+XK?Fi0%(w30K85DT!0({g2Wy`wngIeTjk}vw+}~j zjNuf7`*#NT(a6(CP8I*Jyae94o)Zb*1MoXXMdlUqUBkN{!W1z5ct`M55ibJQP-CRY z-|b@KH}6QUUHsL!>S!$`<1<7QSsN=l!wmnEbCafE9Eef^wBgvm zNf_!z!RHYu44@)3;A|Ur=~pq2daLd*->`9G3xEs!;hx*CN)m1m3Za{~jLn}eASr7AY z2*?Zcn;#)TmzZg_LK+N_cwj4_OfZPK6%(alq2d2u4fR{EHx|{Rhq5fKCp@hV{$SW#p z59;9S;0j)BW+LHem&?;xo9Z*v0ubc%f6Y8Dh|1sB{`C_PBS_87k;}`=s9Hc7LZJtV zO0DCs@%|q!U#RXUC9|)Kt}u7D?s>qvW>4@^Gn;d9hPCWzSJBx~Q?Dkfkk0Y&6TE?c z7J7lxMiV?9d<#%a!pagw%oB=%noPmC2xm$gfKQ+mAQymE5ZIPr-Q+qktZy4+zq6|h z5TbICL=^D5`ucjRgBd$?dQCcR?k3!1+A|$>dhpv2DBT!<_Z6CbXeqN$7qGIj5~hHG zkrCPfsI>1d_fGlaM*0YHe#_2{2_mt!y?m6yb%xx~+xpMBFDhB33uuO7?(%5L@2y7TQcG z6-Yu5I9ilKUsOtl#?R2V1yn?y`Rfv0u(0cXvBQzU4yhzn%ZZb6rhZNZ$;xZr6HR?b zH~E1&VcMFU)E!0MB|H%qPh-{mXT8NKihvQLC#$_0q}Lf{SjR-=Yr)7xZafqZ*qfk8 z*y%!Z+-B7e_1<7@(!iZYk~h37J|Z~+Z6{V2Li$(tg)r1>3$)wVFOL)Jo&;XthsrGTcgeUpI+38a=>AW(+2;WQ0A@in|;0aguTHDdpl1O z@*Z-kcPYm27lBrSY$4cTq2DCV07AUZ%*anY*7x?g%CEXdd@TWl=x7w{C2=m6BrIu~ z=nd9WIljLkqDz#mh~{Y-f%?dI=d%*&2@A2Mx1U1oP36LiOY^OV?dO;O_=f3c9@*v& zpPw_+r=xX%Eg%+9{A;UlA?4V!sp{iRQ<|kij^n>IgKE~=-l=?Z+MPo;0oDG@x2kEQ z=tbNgzJEf?b?4}>j|V|Uln~Wu@gx<2Y%fpcK3ITFnKUUR#0bY4sSM$r+k>?jGx74! zgjgag$4@Tii|Bz!xBy@wU=PNUI>+RdptFTN7A9d_g8T6Azi4Z7I&cWpa4a(cDxw%#;yAO_NFYoxzPEl^U}$|2bs@-EkgN&yB>_# zEhsW;19Bam#42%XaofDna40SwERi;1S*mp$2D-ON$|JS8Wr54l;@RBj6R96|T}CmV zGdmeq$tW%zP5YB?LMPC2`=Z+W^Z(95i9SrOQ7~FSNYGrn$DyZX6}KrW)ek8g zkKgF{@H3(pRqxykzcjpFdU2o2aI{S{)OPOs;URFbhOQM?2klB;5vLm&6DOvEOPojEJU` zO@&R!vh*IG4=+_T&=QWn6+f_q(iGqtNvgtE>)f?0ZFLNZ2WyI`ipCdYQjO*2la`vJ zlun#47Z^0VZL_DOvhQihI_II&jTR^>&^3_@1t+rOovB6|Av@OZ-@kOp8zfpJxuiL@ zSJ{e-i8(&b@fq*94PiAp*PNH>&}U)KQ<;)Lh7!SS1+Se2E zJMsD90M!btLAPI5t~c1I({P5`KlQxp6}+X0vZtW`n`<pdTvO8FNs9&}do z;os+D8d+t#McDzBuyh-7P{t@7Z}X2#vIJFP^#uBJz?=w%1Y3;4jW?* zFlV$wUt)kF5pm#Z1|sl5mkLD>0F7HXtKhlRfU;;8F@ARC}wwrkZq43V;NPW|)UBK+J;mY^eh-t`Rsvie%OwA1xyNr|7; zW$Cs_NtgZ1ns{h$+@7GgHlx@H0}?>J3MAJ_`=PzLVqZ1baP>|!Y{D47WY*3 z;YV|PEgs`ngzGdLoDZF>ZLW@YOISsl8?S$SbK@R5JwvWv$|o08W3|*atiPm5AD?f? z`9P`8nPqL|@3N!(Er!Zol1W*2`64e$>2f^&sVk*5{6nl%$A}|=U+>&Cg;kEn%Ku#4 zUL7evS$Rc3r9}+$OB0;T`<8VeLCuSUG0*puimIs z;)vzM-i|}M7Ucp24v3dIo^zUgH+Sx0+~@}>Ibur{r5q2zY0Ha+})ll!*~29qw1hW zZ^1F2?YZ>SIVV2WH)ugXP5_oylrwAcCf=tGQ;<;DwryzPmt9JhaOM?S{#z2;Tq&W) z{4}|q8cfEtnqI}Hj=XLzQU1m-Hg-gfnsHar8r8G1iCR8mE>p{AnUd*n5dH8qr)Xr# zF@7W+nBjW z1g89tA6jbt&9-wA=I4iMaR{^#)U?aA4yb>7P{yzNb;%K$RGm-JbEf=XCyVMjzG>hg z1=6iO*5C7|@3+!J7QczxuJ~nf{=Ve#1wQihKk=e%Z*y;7;n=EtV^O4lsHc6Vuv0xA zbX7ce%w~#~th(YPiN>)VP61)3+{}WtL1Z%ZqBdHM$lYqpgt zF4J{TiKX=Y37(g+J~g!RhkDHcd{L`AS!C<1(#k>$_uh)(CeOOz-5#d_KfeC^frX#_ z#fm&0wc^k4a||xHInJltTvILJJ{}{uw)6jQ+Q_H-cpYz{X?B^~xk&5jhW3qdt?n%3 zuecVNSH`6G=P)^*3s?K{(9vP#4~vD}ZzlbTE6-TjH}8z{r%Gqb-1H{>`8qpSn{jcI z|5h2-iRIrNl;mAivTe$8ZzBe|SH71~+3U&n=}OkED@#IlcCgl9r(#fT`&2s#urA=X zKDXEx`P={Oxy?FCW@1~(L#tFNt2y__EW7h`RaQpxf?)e^YMG$Du9Q>_~enbJRhtA_4x`sMTtf??OXe~mF=`H^h4Q9*5%C~qefI5)TEEB z#AMHYE)l5h3=$X#@VzKyo_y5rpi;qJu_GiBJJ7c|fHN!OXs!;Wr^p6@fjf7?KOn@k zXZ8T&(;k`rD%9Q%fog^yMG3|%4dT02DIezI=zwn-(ZFX65Z&50% zxH(;^?`p_(^Uz(Rt7!Ufc8*i@6K~>a@m`@nHT>gCOYFhzBvI!FAPDmTw8yX&*F8gT zaB}QS!?b#*r1{EQ7jUiTuqwFj9$*#aw`CYvVZ(KEQgvY;e#U&zID7U_mfA~cEApb$ zZKkXedDf=P$NH)D_Vi2uwrT6&Z=Ke^@ZUEdE45JmDKL=tzBKz7bAs_^gDxI!bFuQ3 zr>fW%u+H?Sb;?hRWco9ydwSa^NR;?9vApRYuFt$K2w2(KJ|5fYl3!20e2j1e<;Zbw zHP&Ya55|h$ot7gjfS0dlU0Z*d+tlan9~gJq;txO{(TX!weY>t?5IkQn*c?`LU1jA8 zu=*7?73u%J!#G>!aq#@VXHl;Bml72dGN~rle^}GFNGrJ5} z%1^r6lXn#OJm87DLvf@@F$-;BnMi-?s+DD9`L2wWQpPed>v5>JQlPm^$A4=ZNkJF% z0?36>DAYFSCkR&v2dGsqxJm9I#_b*Rlyy_pZVIekQnl9#mdMNN0O+@pMG^65dC?Y~ z9$*OQ>WJz0^JfVZcku`A0#^;pyez~-@nH41nFF=h(}K!dE6=eHU!zNrSp9%T;$zH` zN!JeE1KNutYX$lENYUK$P>6}W?78qLKaXcKd7xG&7dBj?Hcy6nl$DTX8!l-!KSoIl zG=o?OiCP)TGq5NC`P)j$bS?z(OjTQ~p`M&35$$RMZ6#1lq6tPE7GQJR$8Hq*J^V~` zM2dstBQ(%NehHBfbXiC(N)T~NWujDhZt-aw>{yETS^47Y5yVa@LvDr}XH~bEdzzTl zJnYtRSfSV?r6o{2l1hcl&|j58Oz9hzM^q+@N{WxL?*8vLT$O+Unw<_PO;$*}x{W~> zZUsAY$Zq$dhKtA!>K~j_QocMcDXQZ^by?O7R{(ILzP%WSQ(#l3* z9VuBsx*)Mk5NS|+d6g?-9KLFUEtL?dqFu*Q`VamFZ3XyB$^KAd6i$X=3Cfo4;m2-#P;Y|G?%n{!KVZP0SR<*kvgEKcYE^Jvy0B0M`HXB=yUj}VM9IJd};xY3qSNx zSy|)sBHAD%saW-r4ws0-HSu4=izF$Mu=S#sCY^GrL+3D3^sur~;R{~9yw`y55;fw_ z7EZHF=s>giAo$5c(HL(3Iaji|1?`7KowNw#gS=+$eQ=k+S`yt%z&mK~;Rx+ggu&|d zt5+c~D_OlE01Hf~fQRtriR}u8HK3=4Tx9=2V%Hm|oJHNEWK!OLFrz==8FTdL5;Nr} zZ#sEQdJ)k%PDEb_2o{Jjh%rCaeZp(uJ^_)4MwYmh6%D`&pwS0J{mNL_kP8?V*&_&U z0Bwh6=T=r04G2c?O+*+Z-NwhW-61_$?uk#TvE?*dp`W;UJS#a%9-0>AI04BaSq>n5 za8kfc+BuIM-(B+7PXIdxsX@1r3p>Y=zq!>Ym+SGVNTy@S7x7K75zrVOF&qyP%#v_N zcKJEVT<{atbDJ4UyESF}vr;MKr3>DeNy}LU1?PYC#KgHV6*lm=2+zK@2~R^!P48k) zi8MG9#21Hcw;V3y(OC;#0S$ioOLUiAm7VEZe^AOwZ`*eMo7NKW+z#oT-8S8IpHjh@OfJ^Rp$9di`61ClGfMuSH7XWzEi#} zpkeigRTI4Rn^OJe=02WqUq*pOSSZYh@{J$15O)kHXh>&Lf63YPzhHWm4NUdbCR3 z`pU}D$%%%2ehGM$1^XaB^10ha1rNVu;PHI?m$g`!k9>vfAr-buCkQ=-V;ieNb}y*o zHDa(n@t@IZd9-=ES1DUWdmOGulf!dXFaN7R)%e;aefB(L>y=LGN*Ky`@f&EbU#KQ}j*QN6?C z>b)f1WQx~~^knC!1F!I_W@jvFDhmPjk(i1yH;|409fN&+eT)un# zg@v|V^vqv(zQ&%yrLpx1RpOl~-_P3xk@Bl}{z6Lm^#>0g5IkH~u5%tu*B*7j^D~AW zKYDI5W<{#)_~=|P^p29Gys}Rp14jd;1ylx=1nMH`HZs11pMPL|W(RA;rq`LH-zBFX zyUiDPq`{dKo%nB8*)GxwsI^TzmS)Lu%7R$}W$VNI3I>KO3F!FQ!2==nysq1|LY5?a0=VmN`*>FX?jlJw7DE$;*CW)qhO06v4&x^@ybFfOmlpaR z=n!C!RqTXz3}|S;xLFOAjYomkqR^Fn=M-dxIZxnU4lGC92h3kU2r-%h&;m|l>~W;? zWbdio{O;MGcdvDn?95LEkeEmHJ1h4`g(V3h#)-MQDI`k*e+T#zezw|!*iu`MCDkAa z=?`$A<7>u_7>|XK{dRd@;7UR)Deh2@pty+f{5Cb!{OT3Ew&B1Dmm11FIkg>c9U=Dm zbna|2?N0H_IAO@OcSWk9f9rS!X|?nvucaQ>!Jc4)W1e`ZnV z__DR&)qAPNdpDWnoBGVIltqJ=vcsX717HkGEdg9t*l#F|P-EP_chBMAS^tx)+y>di3x7< z?5Zk0D*wW_Y7W1)&C*jL+tEDP{DJ~G!wwILwuLS)PPdShIVKuZ38+3GjY>-+5q_W& z0?KD-KBhuFhD!t0g#7C8Rr2I7$}1YsQjtOv{0h5HyhQ^bV{mkHqiwh|E@ermDYWL* z&)DbgrJ{l)1H~josj7_}BbQed2{92*lHYbtDU2-v$3rq4Y-~bu)=vd)e$lT~&{xJ; z>~2k48c6Lw~GB!lTDkZ@(91w&nLcJD>_Zj#I@4m&)nt}j+A zg#>?BO3u2Bk@5^{wQG2g{?{M7q=`Xy2B|c8dlM7Rcv)#pRfhxREX#?lQX_fPYI8N! zM~1j}jnm?fCCW<0E|$MlUV}v~--G%M#7&sct=!yIjB5n7p^m|OaHALt?Wc|b0f)q+ zEa*ls-O2EpmB|@vjvkM=IrTb8&5ZLH@G?;58+3A|wJ)Xx@EcX=MgjFmGE5L<2E(s` z=!g?V|SAF@uCN1-k{M6OPOPwJ-Urx#AeABulwnJWp2dY2?h_cG@KY~ z0;pq5)_ecpIrjujc*DGU9@HY2Ioub(N+s%kE=W z?OYk3q+UJTCX93US+;aF<`a~;r9EkzSJ(F`+?pw(3vL(M2sCiy@1uW486u*4vgg}b zGfJ7LCVQD^+KmcwX4^(H%tHPR6(VXbsJbAK@UC#wFhR`#)e}%Pr%kM*q4=kAs#`C6)k z|Dizdo`J8lLc3R9o|f=+p9+3>tpP#ipEP$SE7Uhu+f`6zc` zYd>RE0~v|9{CSh5lf>zI=7su284dhM%gd>_qAgy7J+N*J^46{2oHc9iv+R9l> z_AGslaVd*cjb-fg`AARwo1-WHrB|Fi^{7eG=Nccz*L~)^$@ID(Q}vQ(HPkuV=LYw# zz8p@?cKp4jXwjzD)R|c&%Nwk#l=!K{RO|$(R~>tLMMn5!bn6av5wXTA0(J`%^OIH0 z%{rbzHP<6`ZjXK+?LK|xhil(8RzAV2e1A2lDo+R{>F@a{8o}R^Z@rh=*_HWNpH0dg zUd*UDnIELr(`4?r*0=kB>a{tsr$H_$$84xQ<*7f#(O%x7*BE!#=H0b;zd(r_w3)2j zR~RD{Zkh;1aflf1k&NGK+9q?-&wcUi1XbDN{Lvc`_v-t2EM>XB`2O0gmA=#H%5u*2 zDwbKps$idQwt@>;m;ATJY-^xltoNik+nhLh>-Z}}(a-lewFi{cc}wjgs6;yYl4phM z_I^Ee&m;cElb5l-H@j?68_d`rdtQO_>rtPte5rmuc6Dxi)l6ne7!_Z^xT&lyV#a8> z)92Mf#h*X-OWXV325cYq+_^Z^|I6t9_w-3NxLJw5L))C!_I zKfw!8UxLWs;?7T*Wzx~dDQ^!xMCWF2&aPAZG1F|acH8Xx%2fjgH!cf0&5lxis@MGJ z%AaiHnBrUSb*n(3;bz3c7pf{^cW-<0RQj&*y-YEp7Gr(9Mo^uM;{0!T6zV`$7G$H5 ziypzE@K|I2A5Gf$gpE#Ia1<*#ZiZI>b(+ayH`aN*ODS=KdF z1Hs8ftY3Mlk2^(u&L1;q8-Q++9d7yyTZQU(c6wWG=Z>2;{->QNgl}*o0T)7 z{zCY7pwf>8Aqb1+;tw)}0I6dH37N2gni|M! zca%lBRqTlAcNIWzR=t=277EELnZ<&?0{A~F>u@y8AYb9$0xC?xT5zhKwWhwby<-3P z_V(hV;??{&7Y9YCq^3R8Tble`RrpvtyvJ;}s1(}N_DR2zN;5 zMnaLdJB|1zBwMp`j+SANa1%Z6pKHn+zmRF0m*Yegg60&`EC9}sAmLW&QpDvC0S?Mx39d#Y9=M4=nF;JM4SSV(h}9w^ zPDV0s{`^RwdsCy!_^N3RHI3$=n#t-{HFt3D(O^M2wDG7Y@eUIL2^IlKzUhV5Xr7AgLYyj}s)L^`uZp0A6r+QqXF{o78pl(bA6`m7bk{%4uP_!_=im{! zoN9I!8e@{WxQ=^2vN_wfA%6#X9*9NNlCg15ef&5nDn`yeG9@W#6Bjf0>Ok#xApb$I zLAM6x9=fpOr{EC9u z-hQ;Cli!xrJ;Ul*A&)gJf1sx$PpQO^8}EblH~6Vksgk%qUag}We{U~zS}-m}kXM>Y zEJWVnmTC7ZxAGHV;SW~@w4YofgJD;zY0>^Zly)%;NS25Kl-u!byFs>sKh#)OUM%z! zFMdd?hx;6E)^u`f3Fo&wdq(WsO| z9Q8KwY9)S$AQ{och>>?LMpj@MSCnU{c%W288|vq`UGU7;t%$_Lfjfi|6rd?FJL&jF zj$22qtq-NJi|CT0h6vk%y<^rR8dgA^f+KKce;?TZXK0f% z9a!a_$kaDeZx4$-aYXakS|N9#pUzvOWp`I9BZXox;DZik{8FZB550=Gt5n zQZ15qJ)-C2aAw^PgC09RKEBzXBUe$f5)My!S09FrK*|ouUNLSbl*T zBcDS?UyWM2-;24wF{rKArY!NyW4urV2EptH-~?j_cM(o1Reu;qCo-$<@<>-4{8W4J zUKg3F0qyerWivxAavUYw50R&X2B~}_?kfzv$dd5&{(_QPa1FY9^rlEVMI+WJ?W5}9 zsXlI&Ijt4G{hwYRLRn9kPQO^0#0zpr2*zIG%HB&q6&ea`bh7h_sKo^rcj8~jOo4K z$V8WH(EEJU8`9Lu7itKt?dx0hghKF+rps&AnWe0hU7h3Ep*u8Uofza2zZRfv<`SSCX zH4Pp$N{E( zvhnZ*h^Zp!02w(42%7|35+n=rfsx<&`nefaFa}~s^JL5ZMc4{f#1I;F=)LbHKKUKV zU(vIq#}+-<_GxGPRP}2d=}C~sWjhTXjOf9gZr9=SE!5HszR^baZ$7Z zMN~r!A=ZOiyvOREHLEhsF^Ea8;(6lVt6)Cq;^d@>zC5P2y>s`%QZSx6c}U!eze9EZ z8~%mLB-)}wFOqW=*Bd_pB!WNh7Dy=4vuwpQ%Sf7463!kT`_7zELyh#G744{RhOF{+ znNa~CQ6SVwOx^UEz&WcgB;FEe4NetYMmWXMogx(-=M1b8U+#q7cmR(8kzy#Ts7{M) ztHvmeb9LumyGZDA47dk`vK;5q0oF?9^CAorlamnibJ!#)Cpw-g>+Qi^bL-BI|8;08 zab*$_a{u;pEHeAzMe5bR&rW+WOWU7GY8+~>surN!=E-UD3ZeH5ql)!mE*tqYF6!gL zCjzN=*m@>9s3LHe;Z`v=(ZNkl`rxZAFmQMxM1}yHutmb+aF8FsD*ioU6@Ya4*CKjv zg4iQz@pjuL5F>D!A?ODd6!h>Ud#h7ssV^^V`_+6(s;&FD2}^7ElVH_yRX*wtnkPn^ zSouOGXpfpQI#jReXnxYbofPuGC4*1;##`3VGKHgGB!$e_4chMs6v&u{s6T@B7f1@p z4!hSyKN(tVwmNp?)uW`}mv7STUik6jjphv|?p5;USArj0D^E;mOSj@p)$8d*eU8Eh zDtlbqWEvMlHaPhhKQ%MFd0b|BEPDTV-M$17l&S;^#bFH~1sp7aP%(Zw)Qp4r+m|o5 zdpJ}(;dsTMxTq}YAlCWboAcs_?4|Q$CSG-FEono5rSA)IS>PsHBj zJk_GaT&Y&5{}qgK9FO_r z=zcF{&qx09G5dhNIJUJR$ss=97(GvRX)tIwjV2hTwYeoS-fFx=#i%-CcIdjGmlb^T z1hasDg?>*J@27^{(3U{zZz+Em&Q1aa3jIUh0DLxsGH--_}ZOo5P@S>l|nk==; z=$%{`CiD(4a-c2n>XEwa(WeN<74d?R&Dp~5x7asLPEIx*I{)j4bEq7Tr@cAPV`pEh z7Nq2To&;Tw;;y_3@Cy!Z{+3X1xUf9It2F*%%3mwt&T`Lar03YtCoj%l&5}Tw+6*%| z8AuR3%z3jO!x4aJnF)Q;=I`NnK2?8vk5a&Z9Zj6W=3_kC=3%`fmqendel8hjNSCOx zmg)3F?{1u&tsjThPG@FdU~b=zM9m$E7vsAcyl7NHFBf!H^zIZ~6V^O>*hHD1k&JoC zzZ57*FO!%WeeC1K>W}h#W-T9`c^M#B*s>SVis2ZQ)QH&>Oz5W1^cO1CyZ_LN$Ym6e|CN$$^>sfJbLo#-CKdr=;qS)&68= zu+>VQKA^)cSpC!c_Hc-SOIh4*D!G8;>&~oM z>qSMTbfEI(t{knshx!rhrd}rS(r3!Yau_z*9$szh2&682<6*3)mBn{q|5JzHTqAn@}65WeE34>+jSmc>> zx)%lZFPn$P=Fe8BO8M>@C#vIOed7y_CW4+-O?M@2nP*sb!_v&H6XFaJ}<%@3-h2_cpA>odlhVBD>3NQMWWP zG#-G@h{R}UXlQxh=F^=M0737_74t&z1$P}8Yl%Vx2Q}%1BPLHSyYMn#Gz?l!Eyl*j ziW^$jb=`GdmQ`0~i5`{n4dQG|ijaxq6<<{IdM#)AAXVQTKL{*4RvF3)02dp!o`W+E z%0cpWh)3qkbPe*nS>6=)eCK~D+TOTrYU$v)fg8MP*X6En73bP@a~-SSV&e^3#--yZC7gT%uBw8IQiIEHdspQ$LBG&9%~n&fCydW#ZYD3 zScJv~<^LLZI-r@f%Yf>^Ou+yg11@M!m!es+&XH*Ryxd+m0Z=7IFnl#Qbg1i57AjPH zmPLik?vs^Z=SrkKoU>#1^-NuP>Gr*(CyhaEZ!l-%(^$EbXPqwhL#JML`YSo5+x^Ld zSgLYw3a1E%D6}8B$71rsXVtG_H-j$fnl}H;jM??X2!*QSznR~k9p-!Of->)!+>QuQ ziw%cG8L1dtX*sBkaU~5@2cau+f8O8q)CBnkh^|R* zzXp^ur})8@*_rSO?L0p0e{Lf8-mScev%SdOM;t6M)6>%o!fUB>JV6A_3W{-(#exV( z!WnuF?P;+1W8txj;%{^8jv}RzX}IG2mIS7o6xy4eAYF!14TYjP0;L7Lq@#rG-m*e9 z_jW3bvi(Wss#v+}_xtT$nzP?Jz^v}hoh8&bYV^^23;Tsed)^Y$uPRC^XWW8n^YV<= zd1F*4@*!}N698@^a?^Aw=utAr5IN{8(~z*Q5YR!AyHO6F-k2~~fD8E!y(!fzHzYe% zFO8)`w4sfDo6JsxvlkVn#e3skKQgnx*!WfO8ECFKtQnP5KJg2B=KB@a7Fx}?QJG)9 zJT=27>3Zm?7syX=ddD6;?rW@r8-~SEn&%T5NOX^w91#vX7ex15mRiGepMnHsQy$oe z$uZH8F(ODnB{ehQ$5-+TiK!AXWMtow2Z?%3HYK|9>N=_OsdCp{q;8j2xQoF{i0}}7 zF{py>r*HkoKQ`{1;8ObT)&Vg!C_FhLK^Hv`+K-`+8yajL3jL8vIxvLE0yqmv!~zJj zgy)|&WM%B0``WH^p~JkKjWO>1UVi3+15JwY`uEtcijU9bDXjmTqk5ik{BFLg5*1^P zt!CS)IDI{NecI>78!n}$%L)H^ZFNvMS*A;SZyRh@o9<1@8wjkIp>5hWUrPzyUNlff zJ9DGdxmS2gXAoWqnf~zS97Y(Vz1OmPxrlMUIIprs1x!rtj{D)!0VpjGn#W8vZIHY* zz5itpQn$bLH#OlV!E#I0=-EG3?Vs6f-v3c0mLVMKa!|O*-rw2FGd42MWjO%gX-mPRoEk72XBQL zoJ;2Tz__WJ-)-0KCxu55{vv)eIDz5b+UR=_W?{TKVt>)4(6`7$2}3V)>eMNoowB+K zfL%W?#&>=ydI^6c#(+d>uS~Ky{ccIq)vf$4f`fs)Og-l@WiL4 zR-8#5Uz;AI*{k?2mcHwe5Yz7)Di&<@l!vQXia)RZZpjmsZ*%$-L#{DHnSJ=kuKs=J z-gA4Ti4D)vVQ%UPGak!?h(PJk8_D6e77u0kPRp{ic#jPZ2krW7a(p*}6yCn2Z<0r5 z`d;y!pEksg@<7(z-AxCe8KPGRK(SIu(u%)-a?VKn@(nX0dPUiR;sbC5l&6Xt-orUu z{PO&{R?yy1dRg?fHJizoeVF=vIC>f?+#08VJUyKY;ruG?{WSSY<`p%~iQ=KOzL#61 zwXb*V(`%hv%Lt7qRz7lKQS@Pc1CA4@XBpFMEgGN6g)pJ~ z$x38mPjYZBO6rQgI8{p2S|IuTmg7HWHyd4vpej(5|MRbJdAh!`aPlDExq~&VPj1nE ztvMQRd{2Z@BK_oDG3VkHJ@tcL91c<9iA!Sh1_`N)8FpfcO2wRKTw5YD%GYg?ov1l{ zP21=zea#}vz`2R#mWuJ2FuMKhLPG5QhxQzy`?k~m=Gh+}MUQ(e&PdLtN^(1hZP}63 zYl9On16eUgj&$9*;dGuVfd4X-tR^OJMJ9EUN1ei}f?Xt9{W6{j99N~r(UESax*T@a zAiku~;Ywwcc-gv6r!)V`MB}U~&zuhY{#<;O%L$S7`b~DiiFb{q8C;&lPQDdW=1=U2 zReJWONunf5_)O10pi=mWpH+&_%gYS*_r{B$*7*22lJka#TT8QMGI!KnVXbhjYf(D< zO}7qLFnFl7pJF^&cmKfMl=_=LsgU}21D9Eu$A=DqfPuB2mI{wOk!}6+V{+@!U7R|G z0B_cH<-RyC6@@usCJ(=Juw5?VZQh-DdLnGS|CH$U-0jEOl;<$ap!j4nGtja^mDZYF zvQZ^`ZArW(+r4A;jl3Tg8c?^*%R&)0&DjUpJcZ&d&%B#CXOtKw3uQ z_X(mD_rlOAg&jLyAS;QFsRaN*WXp*9@0li~S0m%yyz~@nmH*T*`1CO-V-gv%55(sU zsMOAVNE$Y*P-{1C6l>dd*9h4^2kF9ZPgnj3*e}Tw-PPmsqc>P?aBZ%U&^?YPFVyw^ zeMpiWk$M|zDw$u3b%vobFw!-MwA7h)DfX3nZC3ODN=B1w9(2F!iSRd%7mb^ea`)DT zET7Mjq%$&q^mNU{?EF4CR@Z8ydjWCP!W+sKUHOmBUFh}l6zF^_11_&1nX}s> z?c_e|$&B+IyX0m5nyuw=IRB{2hUypJ#&ZumfN4N1kpz-L9ZuIdH|23&4bJy>m)>}M zI57SCZu9Zqt3KtKJa|`PuQxOJLb2??)xGu&F<-9{-|-3egAbg)}Br6SqDlchbM|aIzDihZWV}jpSlr z!Gi}Q2;WJZ^9EzniQ1i3Px)qNsn^Kfo_ur8JBmMZ5Uu}f`)P0niIeXGBvNbbo!7sVg_eP5B6 zC7k>IWaNbl(o*lIe>ZN3wc1*IE&dO^)%qgd%Tgz*l-!qWOGJW}=MNm$q%$ylI2z^l z&$9DZW{E}e&Gg`y!e&4ipO#E}7Jevin-O>TYjmX(78;<>)k`lu#xN-WBA7(rf$GzG z;vpr{rDqo1%iJh?i_Pp#o;+z(0cL0){Ne98>-6v5d|)lXCAJ{buxIkeu+5u5ix-FMj`7lF~4<>97R+Uv%K^R3}j;$KDe^Afr6>R4SOJjUpQ~U5&^Dq!x z1Sn05NSPzx*Tp5=Z%j`n=78q*)!{JZU^K~YTb3Me7nOg(cuCn66+s7jAGlG_k@;FV zyv;KiK)rud`gqag4p3Ftxg^-f$43F8{ZpQvaTq&~8AEp@yw30Jk^95Td=a$_tC$#W zABZU1=-x~(;=4e~bC6>UOX;KePo5&{@}_@X!Ux8&6ldkNa*baKBc0rk| z%)Cc^#H2J%Q;okp5jXXq%xFIiZDg0}g%kU9QU=V;Yw)ayVvm<$Uo3w^Nxn^V2_o2{ znuRguZVe3?tn%gSS3A5D5oCTb72dro+L}>-DU{jSn^g`$K3iLxiLr5qQnS-K$8j(x z=GiUPUDXywezudtOzkbmPw-jfqZMB|$yk4=nH)d)D|GMQn~sVH{QMTK73%z3K4+s3 zD<8Lb;9tR-TG3i0Z4J+=p!iKQ?picT`2{|v`Q%!w-U>`w%PlMv%Q(n+wMF-?5!x6< ziQ11IhmImaO+QT1>KCcw!AwSk#WbIU^i+u5@BCnGSy{60j+X$S!(39oy!)ggoA5uP z-a4Sk_xm5VK++(kBqSz`fe1(|$dK-l8yzCuDGCZoN~a)=3>YvvrNc=#Lpp>JiiBYO zuKE6apXWavyYJm`#X08{XPpB_7K#u(3c3ln;_!Hzwee0EkbGTSb`wExjVn z3EX`^Z`x2m%mv#Xz_Gwc1-#VRwx`mBsdDSxxmsYWmj?XbQO9OLm_}?m37i9nBc=fa zl6>X33bWP>dI1A1}*?G7LK-f#Py*S6cP3L0m3OKrGexNA1ys?~xc6o!0F#UWFyA#^GSkxu$I%@5S9 zhklipP$>al;j2$LgW->x=cfXD^JwxGl@hR5T;Vi;OZ z{@a;@GVDS{+Zlg~ElHq#Dp)A9Wm(kIehbP?Mxrf}9sdL?9v0$hC>TC{Mb+$W86S~; zD8jHq?q=4!4hyog9N^sNZ?WngQGk`&B<2z5yW%h#YCgq`W~d9)4HjFhcdd*tibfe( zfuG-83tkRm43*Cl8SJZbCO&?}{xh8vfSZCi=o0y#wh*N1qCILWZ>5ASgBB2s}jW4 zck<; z0%L!WO|4>o7onyLOG^d(HanMv0n8)6nEqr0gRFZWYjrCz()&o&$iYF zFDHss;f=?vB51c7)>8V5^pHlw881ubQN(jM|1t^3SAIS3xi&v4a=)52NG_vd`1T^L zX!}NLWDL8FSBXHWZi7&k#NgC!vS#r`0k@`dQeg7|Y^5O<%ar?GY^FMNpb7_K*48q* zcSR1>rH7&~7(ZQwH7AI9IM6xSYR5b)Q=5(e#~491=XgH;4YK8~{#y<1>h{G!ew?ux zPJi4RRdF1qzW_7zaCc%IR6i%4MEDRC<)Hr`mlx=tm3@$`bFS(36+$8A7c)CL7T z%enZWFC=|-Je(4(n?opp3u1!1TMJq@k}+aOd0m6riSiLCQ%}@hy=~lEN%N1j(Fqtw zYiS1E#@Rb@P4p*!vE<}7q#7*CI!F0#0>Uig?ZBedk_C#yTKm+R7-EGMKl zSt8_2^A|_S)UI4diVlz;uX@J`Bhy0#^bR{k;(10sZYf^quzE1APo-C+52YFN*4OCq zZuw$WFC(wNHXzx`;V(_0LK%OyvgsD6N2(I9%|i_jb*g*r!2Hsi?TBB85PA=CJcei5 zre^yIBjMVirsgp$`qEiw%BAcF-$u+kyigGFgd zcPOUBma*oVS;)1;(l+3&^Erm2`$9(ye>*xa2XtxRm(f4CRS@=-qKMwyao}^JOflm| z0^_r$^6^U-Iy%X}#-yY!H(|((=#Y(XW;TxYJu9ls233OuJmGM!JOJdAZ6Jcm3++#b zZci$cRs8#aZQRJCUQ_^gGS+(Ayh0Y#JwqN;9>!yISASFABG%7?Kbv{O)+vaeb2OlT zM9vM}1Qf7y0O&No7N|!7Ff0o>cX)ivL8`v@G_b$>iJjf~VdVUM0mXbq2d%ralD%+^-l^vmYM6pu`mq#KEJ|;LHz% z@26B$A3_(6BlZEXT@CsP{`~QI@i!_((3CeI{NG7N4^aW~t<^M(AmsGfn;!rh8gNz0 zvj#s7uFTn-v+W$fMH*Yq*F6pUB@iFV4Y-P-1dB6@ZzMqc2c)3_6hg1_SctcGZ7%S0 zx8bz6s0OXh5b*<}bG!5@71P%`v!KMISo#l-ym9Vt;klO8H0H~i|87uWxk+spC$(Q# zqPS~MJjo{=<&?Kq2EOCX6ugK}P56bTf!CRO7 z>?Ph9JdjJC^??=dQjlo9iqv?>{J%@M=0iN-nbNYv5Teu)cszp>7N#gyr!G#9H-U>I zJ_8pc#jsLGXW^<10pev!X0~xHsS?i@N+SL=HCsPI|JJ_;&Ts=E8nWd5ZbFsDOeX)O z(fe!j{SER+40rS!f|N3}weGFqH+sjmP=Vt&2aB<*R?=56j-HceTX|~a40o_p*a9wG zUcT983jIo;Ms+*O|I+*Q0{-k1L9W_|}#&KIf!$z*CU ztY4O0%&J5Z)e9q0RcpOl*gQ*S-a2b@;~M*scf1;JFDV2uYI16eCU0*8jfO4A+7hLkAH^O1hH{b87jnEBqMEVpN!<(c*!%|gn;>f5~mT5^W`RW%DN)0_@R82 z>v{rz)P; zDf?Z>YHaA0PWq>UQxSv}sVni1sV+z8R=r+5BW#aNUT(mZJ!Zjsw|l!I-B6d2aXd^m zaq)5VB*vG{Q7}Ast`;6a2+a%ArY8X%Iv$qa;M@?gWLycnc=e2wMx2H)d7-&hMrEMG zBiAc=x|8}P3zShoVrL>!^fvFK!5diyHw-;S%=pe{#{~ZMHl>OCn8-R!Le7e}^mvUI zn}4xtWyFAm0sx~VQW2D!yRCHGP$IK3=}zHDIW0N!b6|159wwA_Qq}9eM?G&JZJCzP2rh63&th`E544NZX| zSY*P+cAM&4~f7qfHNQ`5k&H`dpy*JZGDy>+orou(=c|tozb$YLK)N z;CEd|WtS)2ZZ~;8Ym9{HtH3TFvR)an3yZg$3NZ@K$*?tE=+Y6Y9}B8F3abWkE4U8P z=nY%uQS+64t`qxOkqhYlfmJZkq9oy^t?^8qY`*4Z6AS>^4s&nA@ZLgy(zn#C(s(UV z_FYZ2PDUSMZMgPOA69dc`Dnu(xKyr1!Bu!^Ma3qn1J+fCvR!k_TeA`@b4t&=BgVeH zptOaz6^U@R9hsl9O?y{4vA|P`pQZ$ZuAU@t#ILxZpof$#?@jTwK)Pof-*Nkd?ZKq} zFv(x3C!yT_Czcru2TBC+tu+MW)|J`+1F)TH#RhkOKx$B3s#=IA8-lcWMvq0}T%{+I;gCgI# z9Ehs$3}69*!s`~GG1NKx>@R4@+}yOk|C0$6OpKu7>Y=neq;KZ>vm zf={0+-qHbJt{ZD+Zmy-M#;s)aF>Uil{K*{2Wh-C4CEiF0!8mvZm)jaEq|iHo_KaDj zbrJ8L*h-7XuIBVpM6PJea+A{_?x+@p*v|Hk*}Q5YG=1TWnVX|KRR{^fyw2-4i>GNh za#jgN`_ZAU0yXDtCQ=%0y+kfniaS!`v6e}3{N1ew89eP+L8qSwfy5V}6FLwp3TM|t z9HAw@)!F6~q{JpwDBv%Ga)nph)+p=sM>Ak|%LSHd- zxDW@x;zR`pnLj7kL^%h9Jmld~hBr+Ot(a;%PL)}n9;~l@_Xiv^kZmn+ltX~k0_dPI z1bV$I0~1@Q#j|0Xzc;cW{i)=|t9}>JMGhf6&UkS^tG4}pb_6^;9m-w$+%LGxJv|d8 zdJ9e;m73u7u4*p)MU^?Nm>pR%7pX|lS^d=roT+hPEs^^>BFM{7FucjQYs}hXT=kIX7$DUJMpSoH+ zln2Qs*|~2@{vK1Y+O82O>AeB1$dZ90puN~4UUc4dlR0S!LzEM~CZwoW$t>Uqax34u zAc5Rvu8|g3<$oOZkS?kx=W4@qE?fuA%iSh0wz!tvMlK`UYn=~zxO#LWKn%&ve6&%# zJ`BXBI{Z42Sm?$0(p6=*_#+ji`0 zRe4TX=gi5uteVQ$9sd!fkz%WlP)f1k1~KS_h1KR6k7nWR=oys{-&1^Lv__MWQpi@T zObY{-g9~lKX#_D_5mP^$UP@H@MPo48@cX+KMm@kYbc!^&JII6>=1m(iVPh6~irj$oh zQ6~=C#Kjp^+lc|88<14I9U6iiFV>`%o7Q8Uzw?UBQWa~yJDP8a3_=LyLDe2N?UB4{ zv@l@+#gAG6LtQ;oOjH!c@k^7>>~2HI(VDify3;hU=fMUKGK08NB6wSrXWYh$3sCXO z%$rkEjx_=0gcHRFT8^mDSg$&8tAHuYDL|3pY>gL>Ir4@&KFO;tPK|J40J;@#u&N3R zCieCc>z!ZNS@Rl8t{W%F_|^~_bNl#2sHm@AqzSjI4D1u1!kB5mQm^uQWE6R9&r6y~ zyC)2?OjTRs4X}-@m{oFT<>@V!8%yf|Dc6Y7Rz5i^^gIp7u$^syz3jSfgXr;bwlQ28 z6A9G~yU`pQeEIKiH{Ysdy2GE-t*9J)*d3(=bR#95U92&U8>`XLZOg_xNRpaZW zo2Xjl*muQh6!<$?O9!*Q4ClhhKTF~U(znX8s1JJj$=@Q}&7^}9f~sDN_pA-}1hT^) zFM3;@$9bEiz{N9LtGcHdpZ91R=w6^Q~g#0 zKG)ZKQxnXn>wI^J^6!QGu4@@*NZxCmw#mAA(^GelLYIG-m;x>dpyUy4mOz48cL8?V$Y~y$2*48nbyL80 zJrDjx1kOMsyxCb5K<03L_7kszNCw;l;BCmCDy7(MBH`$^{P}&o$uGqC?SzMcjUPcUDzTeu3X`xNwJo#z2=CXQs5@>^44{q z{W*AmQ*_<2cy{0)5+ozos|M-@GnrU#SUvW;M7|q2OI2j6lcukD|=hb0qST6C{Xj*b{u6Oo3VAiwV7b#= zL$*GG3McHwn(AF@nDDyKf4hk>3yFt<=^X!Z8xp?K57w_%n@-z2Tv4I(y zV*71nIrUB?kEm?-UKU=tFkvY`X9u&IA}gX<*~Ug@;(y`sEN_v6WhO%%H|j7i$$kKx zm-K9d4OiuiQ~_noP=b}Ic#3nPItCIPh2A|!M)(=Nr>aJ+;{8w zg_}Y=O6MIK7#;pTRVMhZ#>(s!QupgMcC{zx7}O~bF#JB=nW9<8{@e%K8q~b4g|(GH zz74D#?r0<`a&>_G^P`K@zSUHPIeSebI~jsM8F+>OCoVvsXFPXtWZV16x6&*hD;sMTn>+q z5`-9(^@|~EQLKTx65h39WhSkW-i`)$rNqNm=O76lJ>E+As)3CIqauv~2q5SH#N*<0 zVSYZX%0U@uj^d7F)Ih}9NRqu2p#~m2@!b1N_MVd2PnWONicN}&iB>)(Ft}2;?8MAq z{b}Qs(^BeukSajhovc?okNd^%GE1_j%h2d?E$fogY)$-Gla%H=N!;TAD!fO_I*E!x zJiVw!p*A#6U%dcn$dx)cdSCdQG6?M{!dAF(FmuQV{{C}gXx=M@GE{Y>8-(>z+-#i& zq(CoA{W`^#K7+atgIWPPu>qsVA8)g}jaZO+Vtk04?!h|s_KvT8C$WKB_8iy&ASKqB zHcCl{J~<0t4?H%ktyh2js_JV!=}3k!k=E8u&bRFIf;r^3{-vsY?2S?$I5a!>51iYA zE75j01JQDddGS`}Y54f&P(Fkrfjb_@IMd=T>pSlwAjB@KWN%o1Z!3vg=!>>t@qUx0 zzsK!~lK{x4P?NSTFO!BW``vn99=aTZs!<-_ZGGv#_EiO&R&u{ZT+FY2@sl@zyWzDs z%JE_P^;GxJ53AOUKj<~kJ9F?$PV_UpsN35*6e}3hZ}J5dcA&3ux;9^9i(>#4j9$=V z#}8nS=Kv9bI97mihNu>~3sxafW@^PjY#9g1?RUfDz=)901pL4ZFvx+C5$&Zh7(*23 zu0cdDffKkSkPCqJCww5>$_E$`@WL9Op6(+y5r?JbqtQ?HXrcEfaajuwIg-u8H;R-p zGFiYA+uh9q008JwA!GQoq(3+HYCf8|e$hkV=txX{t&Up-u$x3t`P#%}P329ogM%Xg zHzVkAsh*g^WPk_SXk?40o9obF8)byreoBYX&DFYwpMR`bpdv0w^_JW*8 zqYRddmI4rot34LMY%VHN+LQEqbx#{Y0Ya^|Kj*2sstp`VOC|mAf&c~PS{BA-WTd6_ zFEuQ9Gl#37G{k~S(vCkoKL5VItetz(82KFzKx+~|y2lLnaPN*RU z8UU)?HeL$olvuwk=Ju#*d5e9Cfe%Jeu_%RIY0TrHr=u_OF$+8|fjLQjX_K!Cs|$2y zu~bQTi6L~Hxr%4@V4)zh6)-5vF@ky=tf>G5MfRSZ1Z&yJm8(~Y`KDd9ymk_X09rQz zmVCN;I54137_=ioyr88}QFV19k!rG;{IU8J(BuINpnfq}ny9DDPy(KSM2~oY*$@T4 zU1VIQ_D9cusWbLh53v4#FQx=>_f{cQ)WX`C7@k%&49fP;H>n zm1(GH%g=MQHhkC?k2S<%Yx~ky;nj5LH$VCkMIvcuUI1emc(DeA*CzY1L>gg4V)3wr zDMJS41$UM0xDvRaH*#`H;;9eExf0J_TQip})Pzv8OaYe{@;NDKKxgMk9E=-YPw!XH zA#kRMiI3eEZlA5*Y$U|uTioXbmc6Siigur``Z>lY)R)Furmu^#x<190HfMS=!i1%y zlnj0Eu}qb(r~LlePw!Dv>peC)8KcARKb$M`5%t))Fiz+P&p@Sml;`Gf;!UmUvXTg} ziEC!dJrudl$D}0;=CJ7_M!-3^QB*(l1TWrHbUpUvV~720fxb)S2IfZ=8{Z@WuAO~i7Aos{lWvqMcKbL?72{i z_eOakE^^Zu^Am~j)Aa?t^*V;k#ao-^Da#~u-xwhEYkcAlF`G}~ykaQm3!^U<#CJM3i7JJ)toNOTA zi^Rp#w|t-W4mXpyU#l$iQrY=K(gq3!g{hdCnP&hT9GM4f<-!y~h)9=iNjGSI0=j(z zwF}UF);ZH&32Z*6lAs7>=n@^o>Bju(WWnwj-|MlubItF*v*NfYNWz(8#zsbf1FkHf z6aqE|V6jvgeKP$n?e-ji-N07_Xjnj^HS3(CBRY7L{7B#}gs2{C2zryofIdtiS6Mvs7So%=*L^QiwX($*C#b{E zG0s%_2s%!et@MvtA12>=+xo>GZ|VvCTTghDlNx4`U!q5kwbeoo%*g^c=PMQ%|+lm;`-{5QkD8eT-^wr>k7k|w^UOT zlUA{g7`?{0#NwEOsr_YvR3YnqOxApj{k>C#?7CRkp~uTWfcbBEWsHtic}NFjm_r$i zKe$l4J|md=?S(P=FBf(Z_cenGvz{tiK2VkdU4X9%Xbq{4x5GO{oPqfBv7;*=9R=`> zYE&of5}s`iWTahX0^|Rpp$jY%o?`3c^m(Q5Lh{ckKf6%fl9${n^0w94e}X?H$jjX1 zW4+=}7+mKNN>!_)pq3$7kg6awC}UI6b}60&XMC?P72Tw#bSjll4o>UC!Fb)dqyvwU ziPoMs8@`J0S^{=M`h)ZPf7BKbZ;wt-^UV)=(wYzNmZ@Rb4Ml#Z@n4LOte-ef6^C}T zIFYrGZrJT>t=#BO7K4+zR+9|$c&{^65L<(x(SVb&r4AwA`u0x$YG2Qz$Oi}=@z(#k7CH(T!AI40!q8vxW+wV6NCmR7hp}jmGX`R zg7iE{nNd|JqSTab&3(kA}jk!9#j@J|2NvL^a zXcb@!I?XBSSzipZTE>z&8K;0i51b3-!r13tDM(qZ58P_3Qt37mZzMa%S`*mPE%8^DJ+|W=GSX5)ib}jrjt@q<-ngHj ze8(nc+D|D3si>}0dHxh1%D%59u~T0Brm(L?ftfxr-r^!TtIaHJUrL=g&9@tw;$=YU zaXAq~O_Y2((HiZnO|bW zwoRlW*HFmQdsUXJ0V@bZcd6Ap_8EJRRm5Xx=huFS5L?h2H1e)I^p?TsHT>1h-!IDxyE(Q-8m*>~R`=lPLpEjYELH52N!1DzPIAp#OsoN;_7ug2A*4c*2kbo6 zZFuA2V2m?MzZCpjU-B%vNqhqAvim=0haWpTw|?uX_xQYa)DswSAd_3cm0qBOq+p2WK&ZH=n4WV85b!H5Qu|Q z8Q{66F+S7eEs$ahmT?#N@)nGkxHv-r$7~&2LkVDb039wM5apx!LD>K}f&*7AO`x*@ z>zSySnEN!!ml((21PnvKVk#*u1x|$Vpdcbt`Ci5$EoSjF&s+F+MuqG8Z7icDx`dya z+MA&G9AJSkh`m(iTJr-3c(N{>}V2%M({O9pb2i92>0oS27F)@|&+>^l&Xkx<$ zHauhweyo1Uh_%dMm39xc#bwM^J2Hj=!47PAWaRa|szy7Nyk&ki@)RH-+$-+qf{*)eMMuZdP(SJ*p-cr;QdWGAPnn0Q|4QSNb&3_l z9bit34LbFpiI8{{+uA$om7&b709hm9(y;Mdr$AzTOA<_B4o^4)66$X{Gnsjbo7vRt zqmTJ6*V(R;cGxb+niSb*@uFAyBNe!=Zw}#I3X6&|z|wklnKX`$91#ywGyi^Zlxm!V z4sC^>8Wa^5O%k-w>PImelp_Zs*KsA#7yJSgbp)(K7pXYL{0;X2B(gKzb5kN9h|V}g zoBqgSH*2>4R@%Vp<)Lz?{YftfO$4BT_jFyouMX5yKpzrT8MIlcplw|CM9ExOb~)Jq zBj2<&cuj4&?a*`nZiWAz-TL<3$`T)VhQlW4T&j=@93nyp`Z{#P_F9I9h8!@^35{4J zl{uOB1Voi8zzzj0z+phk0)2m88tPUe(}?6V4InYE4E`NpP-YautpX~PAx6-D;r`iH z@$F>QB-O%pjVx7A;d%nv*yTDfgK9Sza&x%7he9WMnUiZD*|pQ<9aQ>!Ak01O9;oU7 zu~k~8fS*5ST0I$0gR+DCt#r38oR~{=iGsJk(0aZwq5e%}-V+H7!T9m<;aw+JtQBoc z`0TTB4JV`e*yT|j^{&9N)l~6R!;u!0`7-{!up&b#BCA7=~=j2GkL+s1gP`A}B$0cJ6vuvul}v9hLOg2(I7C8Ld^ zHCUz-Z@$Z^ZDlhyfY3*k8CPe3G6T=eQm(9`jybpX)o%>!#8NFN{YW_Do(6#`x>ON17I-dJI)o!bZj9eNT3B913L z!6EK7U)=NF@BmQb599XF2G#)Y%S!|=OZhX@L$?5^lMvoZ%1j`)!XPD|J~XiiRJWzMh4eEA;vlItHu#O9MA=TjRIQBcXb*cj?0$GcC5Xnc^6cZrVHmEq9k73JVKjb@6}cL%rLJvi`Vi3)S>?s7F-uq^qqvzJ?* zPm3Clqfb|WJ$h(O>-*XN^6oC%TM5tJ(k7k(P<9aV4aD0~6w+YPRj1FGqww1h|_%;^E}s(rj{dc}q?kmN0kwQL&`$Nnzd-NMzJ%!+XxGjEpBj?H@(8 zKj!hP&=k3lIPPVj^R}eWMds@18JNYUg@n|#=iHQA$ekaBR;%CqU^Ee|Kqf-=E$b+z zF)5D8S06d~z^C}SIipa+lR=Y$%!LcBN_%ShKs&dBH zwPWLL!M;2MoNRA4IBSgCfE|-q;UWrhK&Lu&k2^otZ~spJTeeXpPquw{XSnTApr6f4 zb@7K>%OrW}bupIdHg}mo(AM?vR>2cpsH2OWzvtZnMVeZt)|omDi2@MfZnw9Z>%He> zh`A#n+W+Ot4UbAG-&1c0mQn2Kmvuu3Gtc&uC*)zB5*XS`egoK-&ezE*K9FbZFvfoU zJnd)8FW6PkBn9VY$Zsx<0$VRtb$2%E9?&M^zV?$z*SqEySEP1ySWNZ%L1LN$cd+>>7 z#P$=%t(|RBasa*nOmp*a>#oetPR=Vkrh^zZyn}AMsst?SGb%bZ)*^X4xxKKkmU>)7 z$CkwS;6kMWC-r#E#rPvr^UhKcL}S0s=_459``ac9y>tK~N{XggrKRnU+(}MLf?Tda zA$#N24~8*z@&3Vk2PV~S(&q2Ny8UZPaf$D(s(v&_=KZPwRBkYWcH3d80w&aw{BT2F zen}&}Rz6bgEQPs1p|$FUSL~ry=M(07UZ}L$+M%i(`yVib-FYNv-c_qsA;b_oXlwoj zIZch$cgW}k!Ws|(g>djkGM1YFBJ{+qXT|LIv9m%;%grgjUqAjw5tD!U4sgGpuCCL) zbrQ#cqNf{dk^hPz-NL(FPY+ytso@hNcnYBX7FL(OY7N}3gbIxauwIErm-LEgurh+_ z$aIq#bkeRCy(fnC9li+~^xUDk1-ZO+*%zK?Ne2fMiNuHqcYXNL%jtAG(j^7)cRj++ z6+U;DjIJ0|DOW)uz=qx=V^bDlI4u$-85x|eGYud2auu8qQRbojg6>=z5e{<-M>tM< zfQTIwhuk*iB^QpT0%z;(uWHF0Q56rpg^znf$05Fb9)4-7T*>uQYFg@U$MgPYXP4Wn zX6w8Kqyc9B*zX3=RXJbAivoDnYpzs7Mp(H0SkRORbq>q@z0epGyQ4^ouLI=mwRHP; z@)x+O`1hJm1kD!RQKATIFX$j>R2$=9{21LCa`B#?si_(!?ol4=j@^yy6M4Oe)bXX3 zg9L^E$jeLbn^d8!twvQE36;)Khd(Yg?ZF?dHbBt2dll=?WlvW26dPbJm5s0O8P`&E zeW&@+xziw@ElQK5{vwDMmvQ81-1>w^uzc5s7u)}*yEnHb80o_mT~J* zi6-z61%{K(>+?I^wuBFDla#_1rP0zR7TnF#kd{Ak32g%PM!*(Hk*L-Ima*J7-+W(* z5&}$rwgQq<)1S^DtafUA|EEYJvw!pZ!kqc3U-0uJ_Uk*ol^U7iU@o(hwXsvPMfHG4 z9%wtpXJ#ZE*i3ZjK#>VBugN`LRn)E|3vtA*XeZTGGM%b@+7D( zf@E>8ZBt`srYU_dTP`+Bq9Z#CKdQiAWEtQfnSTp_M;t0x!(LIkJnjA$l(}wX@OVJV zMvb>j)MESEYoKxS77u|*`lx;((pXg~p2rK7ukRJA011%%I~C=U^07yWe|{4-v);*x z3A}S}>W!frlJ6_;+JU6dL2V1?%MVxfBwUu1tJqxgFELh-MRNt>_%!`#)>Id|-y1N;2+0x`aeAHv6^}3Af2FOHekG zOeQQ$DyOm@U=&K}i;Trbxlfv6130Hb=lTEi*b1V3D>D`&d$*RT0+0H-LjhyZF`;fe@)7%*<`KdW^FESKT=3p+t9E%UWuPA*qEefltIrx>E3Sr{?dAw)$yU9B(Jj@{}2N_z$ zix|Y(4z~FGxw0)|Fwvn5x;ludQ`8Q^D6*8fgGU4 zWcE2?fz@(+s+{}daD5#nMW0JWO%1r%=J(UYT3e^;mHX_@4=tdYLHH{3ZDRcJ=)`G2Y%xB+f{4n)gf=Oz95+d%2O;ocTt6M#WQ zwJmpf!LQ2##5zRQ)Lr|b5n}jL`g3vI#r@FF9~!91nV$lO8*=E?iW z&KaW&zU+WVtAU)7s`$Z7ahltybk6&ai|gyJ8Yh5J%G$E(18y$g8fYQ|L0!4HzGB!k zb=rFAM%SblVNZSRxYvQ1V9?4z*vS{peFHZ>gAZ z{{~C##f!ghgx4RN18Fsk#8?yFmY_s(UT18L)Aggm08NT>yefBt!@kCIwOpe$uu~fq zG3|)(+!~#q=td`-{kB(0c)b4wwB@B{VnP_WvoYq|R9b#EacMraQ{_qQ%l1q7zG*rl z+Ji^tV-?;KCI{-AOXp!UcTF_-UHNxZJJ*9`D>sd41$^!$Y_{lSRtB}67Hw}IyU_9t`E`j%KpIk}F}{JtBk zH+d5W69yTJ$k8QUl1;YqQ!-VRg4w~x{?WSRGrpiBHx?LYM3m<2qz8#rogTI ze3{e3yI-2Z9Y8&xcVPYCsoL z>NbuHbpN;%cHjd5#Jnx$O(7&CDu^#(NARxK$)O*8bKdo#dSnhDqUJ6yxBr#_a2hDY z4mk1+pJg?%d87Eup>Ava#EO8-^^~Gn>hhMNh0$3J@zh5bdii*j-@FMtZ?~>+nx~r0EfrcY?;k zQD-sT2l@i0n6?hJ%_P*|b@Bk`WW&K5{)U`fv(-(S&*~>>ru#zY4a#H59w6MA0Zua<3kKiHiCssr-o!p24>m4wjNU|ZvCajogAmFW2#OZ296 z@zCCPiX|We%vokFY`Syy^K9V$eURHxpEAk$z_>>d_&9^ct zTITEt+?RD~rfXz4)NDK@dxek>bm;TeGsdSyx{i+{YH!?RKGu!b53?E&SS{%nxuV&q zEg|nx=8y&w)qp({6@`>!4rji^L65Z=N89}fzNBU48^#Ht{AQRn5fQ16{gr{nsmCA1 zpU}hPBqdTAWp|&txVe!Te`|qRTW=lol1q6g%U?JnC5?;I79%lk>@4UdL5=rsQnEhX z^}BZ1=cSd;sx2O$ZsBJm;b#uab+=3jNXSC!Nn4B zsF~48wVHBhu-c}7eWbHVywpH1zbT5}#rWCh(kGR!I7M!u2n8Qc*o5)p#01MdSFN;@VDio zA8PO#8L$x{3Id7JL@qZJdo;oH1!)c762#JXc20IM6f1xW(B&#m~^v{8y= zsRUC-3KEdJZbgs>GzEgSk)+v+7W^FQh-eW%WwQjcg7wUxX zv*AsR&r!)a$P@JN0?slPS%;*h%JAELuQpe6veDesdh(hhU@jfQuFQxZ7K)HcWSn<= zL2=S-p*f)>7CwG2`%jDI=b=QqlZO5Tjk!_3k^-7!Cp7mf{#jnwY`0Bj+S=~#QjbRO z2eYeX7n?2>Q5NrBt4P-w!x%6u%no}B@R#|$FfslDYL-9%4h#UUc!>!qthW~v%$`K8 zN_hGBXl}nW6iOo{^iD^3GcF{r=gZpsy<9y4PeetS&upl5qIqD$0Iicp_QRyOaP|HVsHt z#bo{%sxN`5QN%h9?=s^&4KMdMQ5YMZfAo+PZIh`qTOfZ&MTH?_Eg%%dfGQ6Pgflid z#V`n{H|JY7iCljx$r%5=e6nOpOQ4i{(AMqba$LHTpLl{aX))}B2z&MTPZbW`j$VjsCmff?h8Z4;z+1-yy+i%U@^%LC89`ruTG<(g=;#q7# zmpU&CBwNMI4VyoCC~n`OnCfm}#h>S84U5hnu_a6lFyQDCrDnOgC1={-=g0Zb1vtf= zH|5*sS58oSJ=>hYnBhnrodNu$@1~I%)3b~;$KEBpq%y{oae0q&9o7YuO5_XdTKMXHjWd}lS9yk=YDYIFYP=gz?-JLgl_VKgGX*8l!1N;*{fP1EAxDWJvY z9FR}o*zdPNk@OvrdTDsPm>XQl%INv7PaoMslj4wvW@bo9eJGhZRi;jzUUO;7?7)je z4SB@y3ZCzmi0p!(-X2Eo-QzQ;nCTt0Mp3R%8&8}!JPlgFH+zw$OdQP(8ydH7ufZ&C z#ryJjV33xNLQFWDLT7zlP~#wE4YLYyn-Qpc&=@eja?^w)RN##-hO$uiJgz46bM7V2 zThe_VZ|+X!z+F#48y%0v`5M^3X=NnJ?1Mg!ijn3t>N!1}mw{XlLI-%=3s*EEBbB4* zJ~>SNYBGQE!oj$q?jfXr7FN93Xf=YJ&^98bE)o>XX*W}> z&4Z*BF*yzLqB=V1SrRERQhLFkE98009QrLKm8t1ErF|)mkM6d?CQH<^heI2U?0MRN z10*mKAQ2na=%bT$BR2v5@w6~QJk7%-i`$>h*$hzglaejB$|b3W@!Si`O#b2H?LCUe zH|J!PKGuAFvq6!>h)OGzXCfab%@twx6lLm7&TI}8Z=mU0Kc!I10}vvBU$6@2BTByf z9~uK&CZJE#7@vQ|9!!+!gL4Vwo&J-Kxk9@)jwuJr7*Yw_+j3b0HfFoP^{Li5aDn0u z8N=mZl9E#Ydv<4ys=vywFwS{mjR>t2Fu8Y*zgs?_HVSmpF;UL=Y2@Jc(HxnQu$Wy5 zcXz#vgFGH zzQ6gMr#)o;8im3|nLJand;6=O-T_tV1a1U5r2bD$ z&M@96KrIv8+A|Hs1a4C=%71dZiXX6fno$M8M}yv$UH-B{X2dh7y(6&g29dayW3?BM z-Y~|!rUlYwJrwXphJe3b=$QXB+IYGBRB732w6Jj@UI2>vcP>7)JLtz|^FzsZsX0Fp z6@U#l4G2yjOizFJ&~TIueY1OM{!gg)9onWge4Lg1BO6$uKBs08fBpDB?VrHVg=rrb z2Z!_%&rbupP{E$9*F=RL13k8(7{|w*XZlZ;XcnK6{cGqb_J6X!@1?C{W2J81DBT$1 zOX4u1kP_-P{3qZGqh~%U<&qH?`Ijd@Oh__%TnB!UVnIZqrC*vSS+`{XB7n--yd})8H zi3E9C^mLt__z1~1J_Z?KD(Vd)4if%-WdiaYX|sBC&Ehm5*u0EDe346MnQiy7ZDki% zN+ZoU!R3dZcAJIb(mHql$s&6M^|25v@pB+*rI@@>ehMr2Y5e-1)R95#`>yvf+?VrW z#moN&g?rS#Zp}uIH9hg`c?{?<&&xtaY&QShk@GE`_00rabW%Kj|=}zGWcC{d<*B_=DtR9$&5h zy_tS$^Qw3MZt0SmE}C1#MEIoUzw3m$Fko5=1fl<3^z(>_ZzPg$2u+j>-=O~uiYWY7 z6cCg~i36+23nAKzENVf;zuQ(N8ZZI}|HcMK!_W#*2@0O{5uLd&`GyryH@bAx1K-&U zgujgXH-x9npTgt+H_DBS7?kBw<}pe@1Bb8s^5EZK2zw1p3VHfs?}_N=Fv@TL9xto< znB>-&RrDj1N-^{QJ%Js%31f~JbBSD<5~Y7H9GkMQUcM?4n+N@L9QNPcekGmu8DO-; zyEF8DWcYV!p*^rSlsujPz3~ejy72$K6Un^(f3n_73W5Jk`Uf2Un+b%z3t{q~E9o)d zR=~XcgKl`hETlro+x~w;z4k=Pq|FewihA#K>;HTE`UmCz&7B8sI`oW6YpHW7p~T~_ z&66=~Dde^--?UnXK00&&9~m9?AB4_EP}ZH4pGiG?)=@%-ynH*(T7?V?z7EyRci4*g zw9RrF@=>kIDU$e+{3$Bn?AE_wnm1)e6yHKk_;1mtT0IB1V3hXlA-E?ujYMnCh6^2I z`n`qsg30Qu!GUBi&tSs;ch$xm`4iqKo&WT|7oLZi#3pmAO#B;MA?RlIM0mLPu<@~JYc$;L@zSYA^NaBdI z(9wf1eGiTetBd~M3a*nlY)cGqRKOyGDEgVTDxoHFPwn3g;=YcIw7j#fkJ4agh9RGf9qsaM$_C}m{fALHeZv=3PH#~ErIUWze%tp1^IL&YZ9i}YG%Uo z-^_tNf#Q%JC*1#=GZ}?9zQ5xfX!gdO$*WfTywU%?o%jvk z$&;h^YMlQ!^A5zK!69hBvd~80fL`RFDeakL%Y>S4W$YIPO%XxIMHD0a8#>Y8Puaou zWMG<_s|}1_qLdgxM>|0ChD0h<8Fd5mlB>Yu4?>r5cXPy|)%bAVAh zniI8nh^o9Rm_!d|yf7a?B0+uvP~}w#AZ2yNhs1&2^8e&AN#JPSM0o@Pye(lWpp5|y z*?_Xe83+jhQ#UoMSf3xHGMk8?N1*e&_tP;+Amkdbs|IF901tYOWJFn+NugxRI-HOsE0jG#2xVq-jx7n<$v8$p9PJKi7TT*L~gJVKd|o5;$4u=}2{^Zp%msrN~FK8mUvG01lEuFo+ki z(g%8MHI1-`lrCl4K{w$;VIim|L!A#+>gv&;#!n{uY4+WGt&^n(;!uBFR+WLu16>sG zh=5Zg<>87C!7p9_-3-pfPH@VkV#Yn?{mh!%MNR-#BOyK>>?^n#zre46Lmhj9CLEA~ z?kKQ>AkG&S77+FPL~ang`FOVsPPdWo&>aJLO6cN1gac3&+P|;XVC|{49^x@=EKlZT^HiAY0u@69&`wX?7mKMzc5YSPNhNBlaU4`N< zMA_;qdBP%cS_aT6RCC2ozi*X&gd~abkLo|bn!H_$213)ta4A0@OL9-SxIngk9_cu2;kDQHOTXQ~u z=twa#Ue%?82LNNl)xicIZ|_4&OpJ{0Dk^~L3zYGPR#qG`4gkFeg{GKTjeL=qcEDbP zBr$Rz&H|2(B6r4H1(P~^LG85INO{N|0Wv+#Z!Qsli-Y;03V^WY!Iji%L<+2I8^kw9 z4#-#dfkIU@7uaqCq62OZoS$KC1K!9~>MC5(5|Dn%VBp*6K4#e|4f<6XiV_mf?=gNU zVbMgGlL74p98sqXR%q(c$20IArbA{$;pd*u@W+>K{jQG4;6 z08y9jQjsapv7xO6wi_9|F#>uPwtyj^SggK-KqKiY>4je;F?dz-WF*e`OI{vjTRxqiRv&EUcwYr@se{nhyG3uycH`I*L&wet;MzgczE1+O**sf`02K#V z$EZWLwOHkGhqv23;GC?!Y}YW=QuNVF!LOx8IOG|B1C2N*I7jzMP$+H6Ip*G}{&uD8 zi5w%f@A38((qFoejkiLJx#ZN}m-6Tg%!YXOO!NngX)DQ_26w-ZyCt1__bY4fIf-q$8E0*8d<$u9-oD~U`+g-c2f@-#|Cbq z_s2=?A-F+7_1*__#R8%K$ee(u)fJ$JBM(TYu(o{wpR9uJG$-JIqSD$VIxV9mL_|R7 z9^x9J9nRx!s}3Khr>f2t`r#?1kEeIAX~<}@(2>-Nk$gNTA}^01h9P&}ha|0+E1}NI z3A|l|HvkDy900x_^LNrdg`o>zTAB6(y1aqSCoxa@?V;P3-^7u9FEvg&6_J_0VLKK} zLBew<#nJacsWAjiQL34tVemahKms8mjZeYM2yQ;x4h|Dx9&t5PZ}^dp24a@5Esyk# z4rkk085_KA&9b|Digz|N!|}ZNqn%s!TAK7 zRzLeY2DB)ZTjg3~1t)?^&`?~>K36Qt(#vJP%AKGIb1t{A5cjQYZvP{^SzC#(pv)KG z{u6nf1HY-X&K)}f2VJ0L2Z$q>is00uu}JJC443;3RJ4Q6}I~NH0v*XrDyKopEx*VL+wLN zzdj@eeH2*apl~o90yr~wQ3j-N$l1oR#ZQtzl1M@eSb0*^0VM*VFgBJ~L0j@e-jxME zbVnC%R>Lqp%>XhLs4hN4qvffY2xgscm&d+N4-O0<`hg&94rP$71d~w^pnic#Z)t{t zG_1nU*Ik(R$Y}|(sN0nb%9XoBVRgON-G6f4Axp|qZ+}1CXbyhakFFdeq!=`>NBXh} zmQoqKF!R7-kzRRh7yk*QNCc+QsBWlXiX2Yff*#W0W8nItN4?6youDD`a-ill_1d{_ zAwPfqyiCyDJ6M~WYZpB*W6~0*2X+Wx*YHtQMc1etEIMKkjU33kab! z>{w^TZ%-}c;7z^9$dbErt3wf5eab_d>gBpZQf``1(VBL;$XcFNz9ytJ&g%Xp|jQA6XAuNA~3;WjzL0!#D z*u-o=H9{(%x9PE!`0&mkL2t&Q@X3g6;?vR#X9V$B_+kMUZ>MR$wM4+ay%|H`&+xPe?ewUr3zisT`s!(vXs4{+^ zgZX%8vcOPoFa3Yp>r}>>omD~$O+{K^kvGyY5?K*=Jy^*aYVlu(A>Q$`SA^MzmoDZ- z-kIyB!bV0oWLq6?G3(*ws$P}Sa<>TCw-!*%vJ9bZ^rT$Uk9c-D%q0NEdRo(jTN~N( z1@MdeIIe0cyI%}_Y%0C>sdn|N;=jFl?YQZq%^jv0L#6y59mLkt78gtYUEJ~E?dK1R zIic`_FN;2i&dGKYU%1NQShK7DZL4SG7{(IYyXos@_)WW!zcBg}yYlw$qOU^l!=V3m z*r7~KBC~re(r-qL>4yJp-O-tkZ#sGi{jZzB!C>J&-tBz7Dn+IKUsGq+jM11eC5o%v zoHtMpwlK(5`{QRxD;`cwPd=`C$1ft^^1MHcCHPTx$JAI3zDFwv8U1@cFNvFRqk?7( z6{SuJ|N3{Voq89s;z+N?Uk3TcRS~L9Gj$v&L8zOp44NfPl9)<1PQs~I+P?@HVm9H{QwHH#$y>m#NgB}q@024upu4_L- z3u?G(BNOuktDaU1IR-ch`p6VCMb==NIejD7f6w!8FzmL+8*8?)XQ)7`ZM1cGq+aRG(!(|z9;o25r^?fa-r zoTvLAUL(_Q^f7gQF_*2+y9HN@3^ryeM6N07>>YJ{j7{7BJgw;b?(f5%XUA`N=m_KY zdnicDHkcH_Bck&kFNU^Nn6kQ>!S2(eDcj@EZs;L(>JogWl)0xg^ z=>86W+7Rl%-tDnA9Ea+lNTH40V>m@?Sd4qh#yrKGJD4BBdz$;(iKeW35jhsqKYoZF zQw?D&+lx=zB!}%+?kTQYc;w&afK?Z)?zPPJTo`lTn$2OKN;Kfx={^Zv{moatda)1AtjUyQtcGLALV?$tNK?YKwZaGw9fevhHM=k9hlIfTDht^C5PV!YvQxV7UII0LzI(ucCJL!K1~L| zo8OY5Vi&M_lry^m(CPI+8hONHypBqgB$^CN$mW>NG?tiTf= zp8QjzF2P=?^L-V%({JUNw`FmTheel#HwaxkHIVk*vH?+nIo7DJ#?+kciEJIB_&$9eivBYte%V@j(su_8SuF3v*s znm0$FfI94Ti;cLFI$R0lq{{7jtq)&YHk;kNlOz6dmcBe7xDhu`hpP0rr@Ss85Y$+C z6i{7is8zpf>91`k&aW=5?7hxO^GzMdHxNTbO*-O8l70m7w2b0n)@L=ejU`etJXS7bH7bqMa(adG^tU~iiUDhb1~e_ zEDk(8c{YnWjDT7UIDDaqAxs*+lvm929NYxFv9W2LZ9UuuZJ+8lx|iZ zv95I7Hrbw&!>VX~aZRa{`pabTc#p3z4Eycsz1PvVIkH=g&YQI>gcDbpll)@d$Ns|G zZ&&;&l&#-Q^JBZ-au4e^d-G5JSeuO$S~ZNXZ}n@`(AI1P_PSJDn=^~)(B@#EsVClN zynWehgko}OX>o4B#$sZl%JqHUv{7t07wn+9=|iVvP9|pSS{QbuHx-IWNPH{wBi(O2 z;(ZRms<8U5+x=er4ft_j*+v!XlDqM~K^TGwP8IB?4iLw7x$WB~)o4j{#!)#eJWz8L zl*f)^QP_l&Pl@v zmu2+viZPdGa*nv5pNTEQ#5uX2!;Z{D?hGHxOT86@w!&K(x-tI2)vSk(JRSNo)#jmi z)o6_}Y~SS%?N;Ayj7Gait?V5YLUObY;nq+SdZ96Ho8XJ-@-e6l4y2*l9!$YceTu9* zr}lK4w$LxNLaOdM_y4=rl9 zG?;Csr!9>;uH&>$bM7nsiyaJ97#wxjO7!Cog_)%_!TaPKOjizhKEWR>tOcw)?tK-RrX;QvyEb1rJ6I=zJjqo+yIR}a$t(65WxE8A6nq`q^^ zS6*>LK4nKC{YusS>Uy{iv z&SBXQByY>%Z9rY(#fxfo@2XMH`NY;?SB5PNc`l9c7`Nj*_{of-zGmEyZDH*w923tp zCUwVjFl>FH8t-n9b2t|+PjT&HiVkM#{-2-4;c9G{SN;tb^KPq4XeH@d5aW*Vh@C&t z^edJ^+8JNxXa$NTp?_0dw?_k#=UyDG^j3IyyigjyLP9b0GSmk_QmL`mwx^uf_t;Qe z3ope#JJlcjd#kX9{5rB=n^#@oJi0<*s4FdnERJ>h>*!<}*Uh>kDAg?OVnOgl`;A~G zc2n?k-|KIZigwjV4PE<+G?SE~y?0=(Q@X}YH(0edm=w~I5!X43TPNZt2JRR3{I~_g zotOY^`w<{#(5W1yX47oY`ViR0Z?|in(%ZP<;nAkLr0Dk06D@* z_2@s>ampT!X+(k5p9*mupoz$~KTlP)IlC95Y)&^_$&1SMIdXlD2StmO#c!zb$aFG0p(K#FXXV8XyoxDL<*;`eLz&=gR zZl$yyb`6QuxU?R`0SYqtuTF=mQd|V{Jpk3So_{d+_Y)~U((kphJS$6~5$~CZmz!#A zWI2zxJs91~jS>|BD@|NuF zQJ`1UXkA7GseV*=5T~lQkBF?(-)&Q_ACMF=V)>O76?Zj2ZgIt0|C?(cdZux|g%5gP z-xwUoQ*Rng+E?t!7qr9ErdGO07uwWxR;LTt2QM}oUC5vP^HpO$!RGj z@fH2rYVVW(+usMx(2ECw0wNP}-Pi0w%~N}u&foe#v3Xxy>~9#sG99c)KAP_I5_;MW zxXp(saun^ww?ogx69o1*QdV5?Cd>Dhm~@ZuGbU3}LJx=cl}m^|hbT%EP9!MY#ikBqs^Tj;pS(vh~yoClPOWVa1*0z?Ja+ANV`zCm?%Xyg;0vpty`^bJaIl(VyQ=jW~O5gyc{!TmeMBRdMsI7PCx|qwq+@ zlZ)p1k_&`(>i{UXi|Cr;83Qax~H5(O(qc;9ZV50U+W zJe2WZMae598Hi?(ayoG2Uu_TVTS&j#6kC5vG7K@Y`Apei34v_44Gq<#;_eG5XuI=W zW+I<~D5_i~g$B#|&awc9OwQ4(&+PeEQCi}tJCB@){am_Q+Qj$Cxbw_6Ir)!)F2LM4 z%(JeWhmKl6nGlIuqx7WAVr_Ib?<#UnCEFbTWVe%3NanbSoAO6PfHg*nw0)LUVr95YKJ(akA=IkJiWWy z-&d(YYGYO!wFjq8x5epRAI^1=kU;9aFe=PnSI6liD(P@e#mX=xH|Ckoi)5%@$B(dX z#icm|P;qoOJM?h{C{>|lG2GJb`Jb4PHB;yoZtvT0I2B$vi93Vy#&^U(h|02w|VM zvGsf&&OAsM?nb`?r=O1zyTXb-FRA?2PYvYKrN54_yBi;?Z{EjXs{TAPiW-t8tRq-* zr=#ZE~72RZ5W125fgevWhjPo3-bSy`B@V8)~W4xv=^?VmR8PUx^r@hD=R z|4jU?ZYNg4b#!P>GOVs$`OrwYtT*X!PPf_Wp!n%L}n47FI92*0w9s&Jp5gbCd!$ z*ESoveb&bg^v_F5JYQ7Fv6^-=@4}2BP?CW*Y`$p}WEHhSo@kTb>I(+`H=MapQCNUj!qBGi@f~J;P}0pV&jw8t z&tJtnGG4z=;MNj!di%dWvoj{`Ns|-iEIdQ*@Tp(-9iy>X5K>`w?5bg^i~5Kc3=x!2 zOSI!JC;a>&T3>qCF}E%#^Lm@-(|K8J-`WLK(GG>7!eCn3j=1Wv%y;!k%=kl|UiE(O z23ogN@2GzZFHrr+*Gh$1sB5%JaV*r~(gbZOh|PN|%Vwlm8`Qa9#%VI{iNd~1Y}@^X zXlvCrjmYrK$4vXbIoY7mr9K_}!1(#~ov@7TBXOZc*>=DR5R!={KI#UQE@s5Ujx<44J#Wd~$A9~zdb`r2u77?oVq{Vlt5dK~w_h>C|0AN) zk&P^9VEAb^_UA%H?rw)Trrq!^mQv`?$FT;vI3Ky+^1VcA-)+CwlLaqoT5QEAgu<=q zzh!PFX_UCMxcKc^U^q^V-!Dv=;NM@>avD8fxC^9?^>horG~4gS5m|;bXF~EOwm}6^OkPZEp^D}t z4I-_EvH%5AKmmR+BweOE2AyCP<|j2qJ2*p@hvcqFM}v|dMFKuu)2*7p&zM`*_30Ni z?XX)d=T`2UZ0=9=&)bm!cE7gfo@Qw_aD{9;#MYOv_-oOI?0?YX8B(T@yN7WPeO#zE z)301vzfcPsti2$AOD5vX2=<#vQmr8MKK#P$HhHdLv#VIX+B8h6kLFalmUZe=tS(of zMB0+f%|;Vf1!Lo4{4#7)RyQ5}LSduF#ljI&$5^Z=A>T;EY_adpdiVueb3|~dBcgU} z3R|}yJWtYT8NB8~ zYaG`H=LbAB+QWC|6-bSON^1TJ-F+F>u`b;@rR zAofnk#Hg?*-1t5`)@gxRyBQX#bHIt1;^9Q__x=32TwFrp+7*QcV48sR&HKKyKs>M- zrU#7_dK!6}#O(E1pXEjo&EAEzMZQ`{6%7p+|E`Rjea|Pz*Wqz+9nFBgCTghjg?a4~ za^r-)@wD}(LALeY@At;{`**h{#}qj}KHm;Z!PEy2q2mk7(Lr-BQZxC7RCzn`^# z={SMSu2^fQN#iK+E~sG$w)o|%Qx}SAG&KH2yydb7OH?2(DJ$NNM)|FqlK*{_ZVr%#?9cO#~Z`Ym>5INN|s z^V4E?0ynEKNj=qP?GhX|RNG;0-%IY*BmL=AoH5hEhMv97BP;I~@1d}!jpTH+{Zd0o;VzZB}L*6>@!18aDuzW1GunX&&Ay}8n zf=<x4A$<&} z@H2SdW$EoMBBq&NEkc*q)EvB5%z)ND51KB=F+_d8Y4J3!(~*Qi)Q-}LK4pD<)LJoZ zNNe(?POWe>={}nketb-x^dkn;9Dpa&QQiouM@=G(Um1{q8FR!%N{{*8l9&kR!)CDZ za(zCGuUXthXTti}xGlWiIB`7wMav|)iDg;#Pta%e)bEFsUYf}3wfGof<1nQ&_>zj+ z>(N)8I8Tz(cK;Nv^^14wnk}ic|BSeveoJ{sxS*{qe+uLoUnr8oa|<%06Nq>ISD;z~_*u>k+p9<+*M?OgYL9cMd_8k$goc9aC>*Iim;Af@Q(gYF#p?@?#$VouZie2&gQ2b^`K_3=^e;2d zr24GpBA)yiDNTa5_xNj~0WTc@UMEvnjiWvBUm@G@W1?zPa^!|OUy24yGB&?qq?vqS z$$!n?GPeY6e0G1?6{jv0)ACsW0X~FBYg|$>TROs?@RCqWi#d?<$Ni-$Cwe0g=XM<* zWAW+cOUEqntCguaTzSgFZ+>twU0Z$exjs6inP&c{sdwuEfw$qxv8ho!+3EkzKYj_s z`&U@%04!An@x<-v7|Bk2D`I=&PLl4>hV1&Yh8B zVIgjYoUb@ujkQGgxT{O%(OFr9sc?P%@5CwFdGD3|))oEjIaL6^@*OuaYWjEArmckj z7ZaDt3LWFuqrbX|A8&Jhe(K+`OqXr?_Q=4Op}dl-{KscLr7-+MyZTRf-%I=(U6Zpo z`yU+B(p-kHrnrNw`rx5KbcIH z-q^jvOLqWd)3d?(ntiJ#8sJ3&9r;dBj5Hv2es~}cI{)s^?ZCRuemfubin{%NTLhf` zx(?3?bU=IeIjCXUkGMWL7pek~p7UTHAt9`@tdrAsJJq$gZ)616HXC4>HZtNf0Cd`N zF&P<|nH4yMHWD~wnaCY+c~l8TBr@H4Y0qkZ4EFtNSk>sNeV z=vGjEkaEi6!SOG-%Crg_r(h7ks$u=-<3i-9SyL4nQSN5r>#-F@?u!NpmJ~h&D02W+ zT$>1_%~-tR=rb}Rav~7!1bkMT1S>|@U)a`Qw&O4dC(Ks78E6$rBKZcNtbmS*Kxxv* z8#(B|rD-%j*K>1Ht>6*xdt>-ZQ8!lK7NU=U$1T=Z&SHOOsA{pGhWox9&Fct zwJDNC_h)dVIQ5k^kokq@1As!oBAQr(ZxK0xB2Cf)nhp?h#<9c2_o;+yR}XqW~K>MS{L%3qxn_m$I1)ruui7-&_nwWqV({VvT!H*U=R@f|pH{n*6#ZFee*iJrfhaW{q z=oSI;ATr1(xK~O8$15qbgtUEm&`u9`LRLX)!o~(Zv&;9oQx!t<>Hs!lvC|v3HDf`3K&Nt#xI8AmGoOiG zG{H|@XWO~OZVPBEpqT?Z7yu@3`3YtKdDHfIzXNhCUdMl zCrwZ(LL2~G3BY=!Up$K7a{4Z%Z$UzO%3TEZq zXx40GM*jIxj2Pkqm`bD-Iwh>069@kRAIH}sJl@$cfr%_YW1jx`p(MkS4Z?|aK17fj zhR*_WwS`oOnWlgWr_Re20YF>kV2B<79exEn z7z^@@MRfNZl46MCKEmZs2yGZr8>tgdqCp0sM*`l3=bz#>Cj@N?uq`;kSwj@z#l!%h z2*Q_uE^J=Rx7d5cUV@b~)z=66Xv-EsdYIyHIDzTfBjUSLJjTzHNEMjfitX7mNTzF2MN0;D-#Wu_sPmxYAsM-*b4n^s^<6)SmWF zg7DMbmg4(u&)T2gcaQd{<%?R{gj* z!D?Y2lm>!l<&$^brtOpF+}zxp@V-OORw%DQhXwf=mG;vDrQ zj=?lj-0M>;el);`q#zKCkCb1hhP<-Kd<_k?prtPgCOzYe2C#z$h;zfU-`$N6;P|ap zX-K$}dn*`4W+{92Ga({kVgOrz03u}#KQkAr0lF;;7(jifkOV-$ zR0SWA6P%~$@pN*wVhSm8=- ze|mX(#v?b2m=4P=R|fvW+BdkH0Y)@!?~l!PpW@zaXs@zu)l(e+xmzoH`x9Dyhu|pe zWQ;awvD+POCc;xA2_CY-dOZd0Vfsaw+c|V{>d^pt1vERrmv!k_+U{9d9WomVe88j* zb}D-QWyuJDDg_YNTiK z&*RIz^9s4KWCfpCNUM9u%SAA`CMH#Te@6nzJB`PMUu$F`B6B$fFuei)1x|eGVhNzw zBm8rBpnp+1*Gxe4z%{guI^fJOt5le)V0fOFw?0^bJqJu*t`H<~4-dCPCa;Ugv;))Q zXMm^!g^UhDw_@az5in~2(-&<(>vwi`BBnHP1}4Vq$b9%*Q9<}|KN0|?kP`n*5cpeK z-}&o6a#*eE)EsaM)<pVO13NUAWosKHsI$olNpd_1m#S zZKTrz=o=}mRy^C}U=_b9Hu2Tn48-^%z%PV*n>44`UD}O0UJs7B*C3&;4x2bs1))(o z@DX6d0x(oqM&+LVfh>|ZK5hldK;sli ztQ!k`=&dHUhoH&>QHO{SUP;L=D2MIzd8smwl_R*7wGvyms+Ab??Qno?Nt(sBB>;=AG_ zzuA8qN)dz>0dWV_4+0TPMs#cd5v`&NzEy`X1ZfP#vw}sqS0oUnaobwJjd3<((5i{Q zztw+RXDwI9_f@G)H^8W=PO?lu5oZ7MbBND!m5pwhBi~!laV_@UeF{rrO9ggQ&~ItT z50owueIQ|2WDmt<3J*dGc-WcvZuSYlnh_mpzh&3S#v@&6iaKED4mSn3(9837c}y!v z{c2qH=o~O<;IK~o%9XDSxGfd1ln47kBLRAr{mEdqSty@OPR*BN_WfXa2UKY-A!X$R zil;*iDW3of4KjS-j@%L|jQ!$IK?Tzu1ZfWYKD-Rn7sx47{kgXhl^O_H#I$4`N^wA9 zG{ev`pa;9zKb)XM%+a&5ju^*!ZA}J45sV_dIPVb~HsZxC)SJbJMQV)I$)-`44#Cf5 zWx#HcL2rp9W<#2$MQyQz_tVjj;SevpbW`Nrl{xrLq^!6HCH9|@ipc42ZiPF~G;*(z0bAc1&Rj+4lG~n@#(`MSal{Dp z^@9YESt$X|3y2XyhC+&gQ8b|w)OIhPnuCuhg=LW4a}hqDC#~BRsy$#o0nC2XwOav# z&vpL$#eXahB#^#;KLraOvd2I#J+{b%8U(TpYP(%W`^-X1Yl6590#X<7gfz-^#y-S z(J%ehL_y866S+aPm{l&|Y!D}He> z-H=LD53s>3xLdqVgidMB4l$6fumli1q<&y&fjAAs^?qa>@nq!GS3m~jb?Nb|J-^Bx z<=WNS${0p-a^e|{_I>7&n7#;)*_zVv;o;$k#`;+5R*8`S-MMq3F28Q9udfHJT>`lzE-9&4tnaRvA8E_Mx9()H zxTzJh)X@DOu}qt-Uf&3F-QsWzIr}Z42{P-mdXkZ@?rA9epOhC4Ew)&T-4ja)DCkp< z;huDoDKZjJV(8s`Ht=W$rY#N3(QKVG)B$A`l{Ki;lRUl&_ z;S0BcN)w*fRsi8JSy|cUwzj?sM~j`mOC888vz54W=T4E!j0SdpZ$)}>%ffT=2w>vI zedBCT8I4o{9{SJ`p%oyEV^CEEhu;h6$RkKGcq$}LERoub1K&g zhcbI?i$<1eR~wHDm{y7~3a1Y(2ChiD`%0huW@Tmd<=eMkTWizy!zDrS@r9PjtOR~Im^MHB;$><(U#d-^&mO3BX;RaI5ha4^Tb&}Ma_Azm}v^43VuaRx>d zS|$xcmW6&m&gai>qNC4n>!gmFEe$w@6w(QOI^&8RdfB(|{{4F{#%Frw=3RyszAaFC z37<8mK71ot#yJ2uF}3ExG2B`lSFR*N@JQMJxT>vv60V06`ne40>BNOAZ(!!F!`_P~ zf8gu0gA|^d1BUG#9n;+yviPfvB2Xfaj*k9ObdLhrra<*pzqlEln%cFyf{TP8v6aXe zcqHpKf9mq(%aE#%hPGVO)I8DN-VOvb0@9watUq9F{1CQX$cm!Gunu}Yyn=!=V;=Y; z?|{w-j0{&;FHxk`>k>>_POST}CJqhuQUuuApRO6}s&tYAEr!a&~6*0h^#H7&6|dMbWb!E2ohUM_@iv1LO* zM??*%34yugxzEucBNyCYX*pi&g}fuk&@pe`(2Z6&f1QDPm`5ls6pUGlEE^8NwtZ{0 zi53LvIJmhH`xY^)X6n|k^G!E}>!1yL4x$CwxWEtAk&524;Ck@MmKm3|*(66X*I7*t z4i1<(u%3K-DDLIu1!*(g5M?Mm>O^q>7PxmsMXw=;_I>|e4-ymg?J+#tix&G|f3?RT z%doDlZo_jP5a5I&lr^SZ*}*{wCTG^ik74+|We<5!M;iO0~(+2hnTLo@j`??0HI<0O7VcJ`j4!;ZwI}u?Eka~43 zEtSk3Wal8cTL977+uM6XL*rUBm!6(pz~jOkowTlZN`XapKb>Hf3WMo3p=l z%O&4HTV4GqEG5T;f*yxJy!RDaD8l|vC^UN0yAGm(Lx%c-gzYV-gxfAIVh|{qQ2anv z&^0o8DbOLmH4&(k?>$=S46=U5QncGRBjwMWIK(Vsc>tz`O<%TF!_!oedxu_Se22?g z8=tJMV$P|a?MfNRpXODKWYvP#pqeRaORbqIpRlpvrk#d@{jDYhRq3#%o0|m0K0MsJ zfk&`~fe&?t>O+(JER^0$Scad+U1ilTB%oO(Y`-r8izITWzkfAHaW8}?4J{UbaZU%b za~3)=`x-dEJ>JWgk(C_D6{Dl3(Cq*K<*$|um|l;8bRDwCp}k&*E-B7&Qno3eEH+eAa4*HYOKxGEjV&CPui7e|14+#jji zJnPK4)H5Ke)YyFAKz5EwNT@Q)1dTX}peHsLkMSeD<##5TL(JY|l1KkFZIvoo7dL^o zg8YR22|V=LlrMg)!be;O3;VrUf9_5Mc~ zINaEbC`0(OleS3MB6MV4o>j_!4E+OFv{v#D{*Qz{mN?G1$@xERgH$eT#hP-?gxeYoE4Q1x%E#&A%qW-;%O#Sd**#=I1aiAMP zIW?usyup=`0smDNU7_?IxVSc8E1`FvuGC0_3t^>nv4`#Sy2dgEJ?Lk5Lk=1WY;KqJ z2~IlYhZ{Zm_Ztr3-E)iXL;dN`_$MFHQ#Up%5bJxhEGt6Gsd-9Hcq@>|M5jOTwvj>^ z(vQN8=J-!-9G>kC-d%=U)<j{0f78C2e*N`>Nzb!x$CsAQD0{b`0tep?|Leh3uPvSrJZhPA z<4`{Xm-`XVNNK%sf9kn27dO|-*5B7mg&1~EvSz<4V$A6a>9Kw1c$bYk475#5Kia-~ z3`_fZi=m0E+b_o0-;bbhK&2_lT#Y+`%XpW^S0YfXAQt`kGwNG1>TN<__Df2-&)4m} z)4ms65q=D2xDF0Bi^O%_MZyp*c=Nv=K9Y|l!O`NUy{6(5Juj6DVC(G z3t4so?RQaMpWa?dZV`q5GCV5J>bL3#t6R$_R_+KExrQW1T=0~k2vfLHr1JIa6f`ta z$=W=Qbp+HIK6p?Dn!%GNS*|q7tze#Y&v9P5bX5INQm2xJhM3~k-&Y-!@vky&8Qp1A z95)Wi%ZumiWI=g{MfZvs$djq}`gUKb)@clW!q+eRQiX(urk9sT*xlw{TRMk7L(><% zHi{BFHgW|-VX&&B4zw7|5?gYIT%>jmr>tnyu=F?UsjXsVH8shRitO@;Cbfv-CvDmv z2fe#eI;I^lm_Rl^qMgKuEnmKacFW|O=aA=b51|#CG}aAmP_zU6cydLBbhy? zNMWGR{$)NmkJnS)`~)S%<@R>4japyF<0p6&w@#{uSl!L8t27n*%FhSS)?h7h%~asr zTm2tPCpkEMjFZ(F=g>`Aj~j_z;kEk>!M{?v)e8GW?Y~%J_s4SLU8g^GJZE4>2|bIYJ?}lR02_x$wiUPegJE$84vZAyvaOWj&Hpg*Nk3ooe7Lfzszgn&BomEaS{h9fHsfP$ zZA*lpxGTH60e_jhd;fs3C{wu6;-VK}i3kUK-_MvP1T=C8NJ=WJD!=Qo6*(Vf^l6js zT-?UBQpv+RW6jJXtc6c1=<(S+m(}%34IO7!d+z@k!<-5?xT&g&N%dP7otmC1*sAJ( zV~r(jOmki0&KO#diSmv9G=inCyOCpDJ6!vBR?gP?d__m+=gTpkQ#~_+%W{}ymW+&V zz+$=QTx?q_WmNj~!qXaxQrVJ(x6lAR8B9?K&MT1uHWSan=y$^&++3L)^pX~LTV-zz zzo2zDjSfn@Dldi~l?(hm^-EkUXcTO;e&D|{(KtjV1!RnS?0a9Y?5fa3oAl(T>JIRZ zKJ@meFXTnnxeCLP$oYFyQNgTN3x_Ip3EVLuRLdqVqGx_Kca8Zt%Oq#;92Hd)u2zvO zdEU2R_4Q4NJo(GI0WmTpf&+y*iNiPKeu>spx~D7r89i`{tzcj}NN|FWYsyFA6H!orFT3(Rm>nmGd2w7;S2y$xyBJu? zDE*Yq50{q5cbvynJ0z9sIn1DLW`4X%ELXA+LtnP`)LL*{+4lLQPHnT4bH=fv2`4g6 zo7^K}DHu0)9yZ)LI7##I3C4O`k2`|RN54&iaYLRou?IOSx8zRg<8Jew?}qgcOU+o` z-`H4+c{R)uf?sKal~3>P3$1>(<-ac*j~S}#IvZ+QChtKaXB1|&b+%jzfY6UNu<>|~?jDw7mg zX`#XU<2tRF*VNY23y+DG`$4$z8JIgQB$oNXd{fM{y78R8&6%P-;d1F~B_cAo}UjLVSKkTL83MB&5ME>Lsh3*fh zn+iRXtE;bGdq*9UYf@Od>W!Y<$xAKnpZC@jULb74QCg-_WP{VvvU;FWq$y^wq-v%YHdLAV{He1 zn{H|(cE-f?RomjF%c7?<8?I`&oT02ETj8y_aPNvbKa7tO7`7e}q>hE&T-`?7mfh{$ z%`Ubin~IrGzp053u)svVe0q|3?8Y>trV`cGrL~E_rZu+Sb>_7wHa^QURcUe$kI=Xy5*vNC(e8555`j~-T4nF`&}pP76>tQhgGVJ#kB+S>Ee zi;iZzA`|*^XXom~yPhvL%s9xT1{K@enQf)RTQl@$rlw8k#vKncGBqbZ$cI^~(a{n0 z4C}jd;B|7cvfJnLg+rkY?{dECX+3zG)zY1Ya*a@|+c>5cVROH1@b+yJHLWLtYLPaC zxj6I5KUKBMJlJZ0vb9{nXS-$Q&OmAMnMrVyMk+7=apAVifMl7>ALz_nl2zxTuQb4p z*TvDI?gne;)XnRPKxW&dq3ItSIPxiX2GnK0Hw3I(Q7r{o{pQr{U(c|j2kCd zUN> zHLsa6%xbI2$|}ji+^QoYr4uFG;Zn16=#v2_Q|-B~xw+dG_^WSZqYs|n3#9nwx7QoE z=(qPOt&x6k*TC%a3o7dkSVK-=>!wTuu&x*J=4&zwzJ1^A-09+Cozq8-*avm)%kOJsXrUcQ_c8D(+n%Os~-&m&1LZf+5`FP1%- zrk8lMXIFO=$5ji5?&lU{mxz7O4Z9%z>dhPLQC8X-;__Vof+OXP5&<)}3^ak==D|tp zu0O^ZN+bTVVu$WH$)xo6Q`VwNvvpeLjy5YDP)_J3N&B3V&@AjC6Mu!oUr(0;hFiHxj4x3oc&41KV23 zBYPzyGYQEiJA3cn>%6}A?|wYKf81AmaGvk?F`uvFP*E<*-i}}>_^9D2CPYpN88v4u zF4|>oDkrz}&p3@il@2G87oOtN%&9JLbn|xv*l`SEoK!%G`Xu<>yI`BI7d~N=+1{QxwavqMlpYJ*FI>8GiYb6Byt&0v<*KbIlcne^ z#hw=?j8Z4&g!-%!BB$Nc!>lA7I5^(6jYc@m1;lZrd3qk)P`a$55X_0^>mT>wTg5lM zFtd!eWeOS^$C}^kv6Y75ubz^bBYCm^80Mn$*M_$IxM@5RR2K2LBac2!Ra`&zfV|q> ze7zBS33~~vo9%~b5NpV*1^s<^D7N6}$jO`AKE*Xypt=vR!TH9`_IMULBYOF~&3p%? z;4A7a9xub}+O&$>&eeCfj)c7WDy%9~$&;4$4JJ@WzpNu!Bc%2C%Pg6X=P$^=jWdFs z*So4Ybd~Idzyvu^05Yk>S2%9TNJ9YD~ucGHQqU>UDH)Y{>xiyazih(wxrD zvFn$db(ng#8m_HxEWGr*)fZP)JuqW*iZMd^+OKQYEwd;2$|e?rf?3Lf3mA+}G0m*F zmh~hS7kly-|M9Jw;1K$HUe0j8b;vKn7@5ZfN`%P-2I~M zkRBgin73S8N@@q~d%fLBNsInRnZtdj7l`LCyVB>VRWwA~FgVnwNq14XmWz*%GPn6? z5a+?8(+}Lt@9Vs8jHvs;;l1M2bqg+m$g*;~ zYs0rtY(tY5BdKU{agXdWw!mbpZ&wIpdER7xhO+Y4Ma7KsDDz)Sykt_5!-mA$@1U3& z9Ti{EaRJr%=Ki^r<&w6|vdx`O&QskZMaoHJ*6J^X^YW~83W>k_@YhFG1AT9IP2Nh< zs_HOAG{3}Kyi@y#@tyR0Fak6*87zuY#sVYSxi|F-p1+I^W!&qOoSYd9&&Hb5!_AaO z&&{3u;nSzDH-BW0E_|a(>Mo|tfZH!P2GiQt2uPRCT4R3FHbK7L&BtEDZzZA?+|66zsirVH**_OX4-*flvA z;8A!E@f7lfms7=o&4c}w%x1o1R*xe_%vTqb6XP;`VL(2uSsroJzjTCrd(Q9}m8@Y$ zTY*62B`0Y%n2Ak>VRq8CO2jK#g(D6cZs}oYm#X$~Av&eEu@anw*V{W#QJ;pkgw`Iz}ueQ)*W0qh?h zN|8Ll&1YEME2kJ-^RamtH5{t=riUF9{e7m&kuvv#&9kWQ)z*vkFF3C_ZIB&4vX1y` z-dXxs2nPQ&TLg?t+>wUMPruVhlxx)J=wnoBeXH2as^9Q7rKi}A)oEk%>*W&n+i;T& zLqkRajC`~`h|{7a!!PLQuy-agYX^V)l=MF9Q?$!eu{Sd2$=nU%IqZ8qj<)k#J-IuUc)%XATOGyGrmt3F4MY_xdO!)dR*!v%BP7IC|54vn%#VI*VCz5?1 znI1f^+#7FH;?!oG-O%a0E-x3~5*!^`oj^X2yAUQ`W`0X6gQQpPs@bPc6 zyC$u&r&`R5mDY9`rn&hukPrGdY8o=hTLd0vBNZcG6=RksIKbE3+= zA$A76NW*ixge^yI^0u^~I`lS0N4MBw)NZ|fVfUkaM8pFa1wM~uOAj#Iu%Y(Uq^UtC??O`5YP;m~=M z{x}NT6phaAct(EKw%`>UR>H|k@}x=J$?2_PBtKPmyx&bbbNBPNib`J}8a)v<)!!Dc z{T}k5z%Tq__pk8FDk?Mq9J`yOIUmn0Qc|#{SR9?)^IxTyTjGY(j?}LoZ=>i>^b+z5 zMwuC|t5ZgGh$n=l9aXB=Ckn{a_B^a5=M(vwlG3$9GnTpjYaOJJhlGnnE5wVQnmF9~ z-{_D&DF|Hn4yU|l;)pGu5arnVR9sy{=gBuf0yL%XTJi1!3(75Dj5 z)8eDc7UWO=E3{<}u~U`$?~C30kavm^?XY$H&L_J}&O? za!%uL{F^rq!EErje?brLT3ViT)#r|h(3dZ>$DN2;sMhaz_AHcF5zYK5@-Q{!6pc!$ z=;`XS-PUU_;k|^xJSTl=KCqZ&w(D4S^!FP@tK2G>eEj+>CMmvr`7*^iM<=ChOP7}c zo!VDcIqjB!>UQ)lt$ABT#m2I)d+1vI#fr{5*HG`yc}%hg-vavRhUO0A&swiGCgxVA z*EUZ0{xo71ajzV-Bi%|(NwHdVywh0wa&>od%b!n;yj)ym6Aq3y1|G>VmP=1{G)3RA z)AVOd4Lhm(MZk607OhSvG}aiUoCHiwO`W9J;LVhjln7>L+rQ4d5HJU*g*p_(pffA{ zVAcfp(K;vU!-o@Qjjz!-1W*<1>$~Uhks~im#h23&wOv=Qu*l9p>-pH_SKn%0@_hXC z>FD9ZI|3BEJ0>cJ=Ky7(q7hY(p^gLv)N49yaQ*r>kckhl_F9*YctVz<%sMGyc%(8b ze`$+B+aubaaV|nz@&{V7Y)#uANU;$j0kmrw#qCTopUA1vp@a=y>x1Id3vS{AsPJH~h-` z29eRRcr(AtBVv~pMD~HKE7#svS4bqXv&T1AuReH3JL=4?*W)x z-Pm}GfYet0hPVQzlGDL$^>VImyRc5qFp)Ra7|nLd*OpQ zMp<{MwWX;lqtCYUBWf`8-|Om3(7tt@Z@Pf;j9FcTr$W5p$d9**!H-ZyoN$P5u^`Bd zW>wk2Vc9KlGVkpe*31-8-!NFT)NKqr9QSKmy2FGH+k?OR_mZ6p&kA7jx#-cy_n4Vx zW}<;0OTnk1HT@a4Bs4VLe)K8`)q@Pg0_{eugrP3hILsFZ$Y+^yS2IYy{2Z* z^Ap(z=EC#!_(W~GFX0-SWk$jzT)cQutH9x;Z(Q$;Q-sJJ2HcBbbf*hJo)MP@4FWW& zKyesuZEm1ufS`gPy$ET-Xitep4*N>UYz@!+cw6B1on#~zx&ulcH<|C<6WcaU;KZl| z7-s8madXE3tSW9B@P+J}QQW9ICP#r$9xq$hb!6 z+7!`8)mJvfU*I}%qIA#>7hRBXFAfiycd@RsQNHa{y$EydML+ z2{sE8P$W4~!cQE0_A%HnR zwlltf*2nGJTucEz_<%xvo9SaoA3nSRy?_y$G&D4)u^JAa_wCzxKv>`j;e)(@c7YCI zJY`NDC2AE1B)_1GAn4w`dnXsZ2v}ALsf>dLv1!>vNKIGQPd_aYpEo;eM<-u4Ja=~> zKy1eq9i1Ayn+P!*wihp6fNcUiqpGLJ0yE2Byu9O~X>HhkcJ@ZBzk1egIfMmfe}Uy4 z0x*R8mW~qzgTYSsX|e$t0Ya9=$@v&kvEI^mchd<%(z-R$|uo^)atj z`a^Ix1a_356!MBvKs8390;k}6V`Jin4^MI5MXful@q@fejPeQExE!f&mWW6cV> zWe^1DE$}KPCMLEZwstidLmfj$M~5YU1UrP^d@q|+M17RlfV~7^RkvB^NRISd+DrG` ztzxb3j8&DIA;F{FhVKUv=h-}pii03bZ|};>urM-dovs*|dvJ{e;{?w`ci;dmE9+%_ zeYWAo*kQm{$BrEF#uU}wtfv~ureNs4eft&^9)1B<2egw}br1&v4nc5GN0s`4SHTt9 z;=Pik^x!+`9Y0Fe^YC?-EnQBGckLe0&7BhAV#TQUtOcGf;4bixQ5h@_*>B zCH}b*ZR?`aIb5(vKKJ}oEwloWqE<}!VG6-VU1bbx6Rd?I6;)IaRB$NKJbwHbzcB$@ zLatB)&MOZ>7#!xmLqkGttM)RhBS*l`qcKPZ1B<=7pPgom;1F;Xs|IG!_OB&WMR<1y zCG5?Ayu)PU>YAE<+-QRI0Sr0a?K1V*vR#OHKhR6$u1yxe-|q!WMM}Xy(n*nV30xzD zkL39@%)?Ir%)Cd6BY6JBJb*#qsS#z(E)RT+!!<#USaBRV>tcrYXa`;PS07yfBq9! zg$2jiAdCQfZ*WM+L2~#I4391DAzo^<&f?X%_wuvKYC<=IsJR^ps|x3N{mT zmWi3!EMRywgb9QjA$ak5`>y+KH=tmKc*Fae0iuq-gM)Wh=Wn~u$Ft82uy0{410y#N z4{=Bcb`a`NGu#3Q5W_%+q69;L-34Y6H61Gpt}da=qOWZoi$5kOCyTo*^6sKy`-`Bh z--p@yO+vz>nwpCUQ(&<#bb&H9`Sn4KMZ*3m;!1#^xtQnI(oW5@R);Cqdj!ecJTJ@Mm@!Dzb72}2L=uTZe3Yf zDO*XZTp3Vc8tw;vegUt9FPs8X&3DFfU3(w&@?{17D}prw`(%-F3Yr!gYh z2C)Jrkmx@cq(_V>2Ywmjs?iHiO2TEla`h_Kl<$g=ag*?4IBD@Yg>~O92)tyyw};}r zL5;CXU0obb65*&=x6@8}H7~ZelNZ5B5{iNYe0rrgw_V?{y4e`ku52`2!LJ0i9|6cN zX=lPYLGnm|#j#-O5vd{KuZ@%U^I}VQ|FzxxI}B(H4zK8(%)5jH5@}On*CXy;!BlY+ z0za9xf5HrWdW?&UFC+xYA7pD-<$k((vM4%6($Q{x`ED4m_E*rs#A;xsfMX*H&EpGY zQE7KM90wGOkwHRR1dQE@_=zxJ+F9mm!gs0=@nq{fd-kl%BAeiH4^f{SnQ;}?2{Ap0 z%ZN*8eoDylx4=IK7Xjz_pAC8_64^^UK$d|5-T&7aOU?f{#~4uA`?*M;AMc|OVylQt z$KdQ0u3n` ziHN*}e^t}aPyihSU$yL7+$&YsHZC6wA}$UBDMA9FmD2jA#Rcdyap(v*6H?>|IB>Vs zdHgZ6-;c-k0+z+SL9hTd@Jj>|H<7yh%WOQs&wreU$1f}E)K~SjIh_;mQea&DnMAmq z2r&slJH&YSS2QE1-L3tvjlkdMblOpD&9HBkL6&jB(9rNloMjCW(TP~l5z14rv=IXq ze*u}@PUxW!`-6rAulg zIC~+-Nj)K9;imBg*NufXA`_8XpDrf?Fxjn@Mno|rOZ+EK68Qz;#VvlF_~#(Gwm5Nw ziwovLB^}|9S(_!q5=X|6%*-vc86W`jn$xLg(hWm64wH|^TK)YyxvzQi;vM^_RP9V3 zgd4A2XO#$->r2l=gnn?QWiLhnw!LQ%9R1F|qdEN=OC$*W51bs#6eD6S-#C(;Nlfw86AnbWN+|ol zd~-2sLC16LM)#S`AW`wV+GS+t~2{7)tNv}d~| zp0r?>juV#0EkM#43wT@&F9kVG9u_x8NZjWpQo2fJo4@eA`??cxt3K%$Nt~v(igpxX z+7jL+so^%!)oO5yZT|95wBPaM27wFVb8n6B1+HYY+sX zuS1woLUVs9Qt0tPVKV`z>0Yx&-R67fgrJf8A}Hu#+c>ARbj3wJZ{8d-*RHClP(!YOY?TU5_hU*5 zF-SmessnW#xCAGslRW|>M!B^;7U$ghW16{HbI+tOgnXxquH6{q_xO%ZHYJ-2 zX_11)WGKy;XD;4mDZ7)cQ~8`#8Rke{UcPMURl{4!7?sKV@l><@+3?Y~mZ$rOnn{^R z5TqhTC?piF&(0aQu)G!c#9Bn;QZ`mmx%@{E@(e;1xv2D`1yyw zbXZgDvqvb6yGy(oq)#X>p(BW7N!Vj^{Y`EAgab5GJ9q6fsd~;z$l~xNIAP^TO9;a^ zRlLRrUBtOebK587au^DM5N7C>?Ak#%kzNQ?VasPzY}}GBWZkl~ak^Ll+@&w?5`nQ zMNP&S%FMDQq@#YV&W@E9*;gTS+ADfVS=kt7f>5n~`t<4MqkG0Z!d8Dy!F`nD5F>!L z`7vlMz=$jXtFu@i!f=xAY+_mqKVabcqQj=7sO8@G`g+r*IQjXBj&Mj+2%QLy2YlcD zK-tY@`Zk&;-8{YTbM^;|_e@@bF?d47ZU#jQkt0GgfEoav^btP3=Z_wd6tB-Jqb_wB z(qMQRY%za^_@;Puj0dSsb#*m%Hpz^r=oUH&!k`dF5QgTemR5Cypm8qz+IAw}fL8U$ z@#9b4DTn_=eQ=x1#{4zh1Kd*t1UtY2)te2JQ^}e%zLq8wf^thCEfz(VT(u}Epg7SB z|4~151JbMXbOFXf^azpuK*F%}Vc!W@{on1Yt}-<>HPDKH?^5t*-2ZReF_q}2`f11c z`1a*=1R#Whk`LukLcoR4UmRfqahT2LkPYJlh`O7KD7opI!Df zEa@zaGAh1M!4DvT)k@KTBKe*!dY>$rJ_hzrZ^S9Gx=U_^HI@xupHB(ETlM*=-q z^Af)jzMvd|copW1;C-3lKN9&Y60Ja@9){o;_W-3w)u;G%oS(wp;}<$>yD^VgOe@ch zGt;d8D}+tuDhdqOzWJh*^x`!DAs{U-!Ob=06 z`3xN%jwvLa1NgCJcNU$C^q_e}K8?JV+TK)>W#4mlS)w)p7!#Y8{8?`UIU$XVjO?^6 zr`$$lBamagpy$!B@B5`beCKlR0`JkLhA!==6ciLhMnxD6oHRTo7@+U8s#2akQ@8L7 zAmv5{v1!!4)4usK@gh)Nm{}Q)y@v=aI4I~0k}6f{1v(VD5Kf`!heg$#Py^zjrnO&2 zzNiJGRU2;LesFJeOqCq`{NHD{NXr2S1Eh@x)Ie1Z3X2nsXl}4q@*e z1sO4+`(xLCHa8RD8AgdRq3~9GPHm`<@Lkc8j?e%7vs_)8YAo64DA`X->)kVT97h{P zL3|>SrOL?2Fg|;YP$fEQ*J<0{Z8&O#)T~V8HA0C#*{wNQ?|xy7MS0`mg8T@t676TU zz$b{(2zfi=MmZQGq@%>BhTUYTkj8z~7X2`(f(##Zv6~P;qEmnZjzrA9sCu8c6J_E( z%+|TvL%u(19Hvkh%7G|O?OVlx_qMLa8z4#fEbX$0Wk9xhdc+WuJvs*P z)aT-xNMb#4%Lyxg{W=})uv}VDkqqZsdyAgKMSb))KDDsxq&W8$`E66Pw zS#m{%V8mgnokN$OGmG&>?2T_?4uAFPA`0(BaL`-oSr;QIc3SbEkjZYMoQOEl{KuP{ zSDDn+;isIWUYogP;U~eMZzH5tC-?9ZGEQ&(rwWjqwZC(FrqV`H9`ed8KktvGnc2`7 z(oyyJrVso@^TA^a&gxIf->z=BFJSaT%$^T;VBBwt5q{wikD&zc3#a!ZF7Y*4G%^-Y zqrBGRvE_CjPkc;%*PJOoxzdF73E#LqBpkPX98#zJ7JkZOW68ts%jiW0KFbwH?P9&G z%Zys~7T$&HU)?Uk$th3zi6QyeTbG+NnrQ8NAFxM4Y!e1T45=s(pNS<;hMY_ z7k-Aa?P`3`OS*rT1h4MT_9AT)KhWm5C;us15J#$}SP6&aMB1oYQ$t@W83(nVW9Umc zC8a6`sXeI`Uw5zT8u0&#qfk@lywnr#Q_tMl_mD?jU9yPj(TFuko3zLJk@cyqJu?&B z+b88b{ff|CXMP{66YT6i*x?lSb(Vg&#QqZ5X`0=sjr*_U7Js<)zfob-_QmrKsdw9s zmZ|;zCT6l7Vi3}@jUcxcU#7C5y_2D<$Z$O=i+A1J|y*`zWZ4# z|IOzo!39e~v3|D&Nn@06@m!*%3~@QHRQ6u2;VbD$>PHXNlS?fgvt4<7{M#ZKFOiXzm2zZq<$g^OmvCPY@;}!thYxZ@1xsWKL=~Qx6OZI7*p^3^cl)~ z@o0gE`jMC4-Qvo;0M{!wsW~VLVyH%2hJDfbf z9!8sV;{7}EUt<-5nl1o@_d@)j7To<|gl?GpyL|Mu)=QXG>HOkDlZ!zOIeA+C|## z=z5#Svq7CA>LNbN+Ir_o34_md&}Z344!Ur)v`ly2+rED@c5C~Sb6K}+IQ9yjKM>wf zBOUkJ=Gr|%36=kCwkR}1Xt~XU^69i6zeDW(GOs(8tUf){{qwgQBj)Jm@*sRmU<{a0 z6$pN{r`#vISX!37c*~7ZR)+cw=g4Qqc^_Lh^+rMywVQ;4^YGzm3r(?)o&n5#zXhE( zA7E?{qX>6UP&}8oxaT{ikmKdAMB)NmfGel^Wa@j0(jEWr`^rrAXq8Y>YIf%&khrf8 zoFV%pXk7e2mY+%`*5}BD9bZxKh?b?=MfKHfNv_1*Gq3M>EZs!cxoM|D!xc8A;8W7a zdN1ZilkSjHtY|Z_*xF=wBS|aiUN8E@tCdUbzM{O`yYsXQ!#-9ov2K*lOGo!=eT`Qj z?atJZFQ6z8`xj=D_%56dO0nc)hx_ej0{kD1HtTNHse0@Y5lOLWGr#$jWVtn`x6AQu z(w>GG@5ET2Yl*!fsyn90^FOb07d6bb_@(*#%ywn6^X67UXvB?`Xy~|o_UDUNvmw8^Zin?1eZvFi`xHxqOmP+8*&g(AHxNfFD5OS`J zwz>A-j^#&su2E#VH)=vuzyA7|V&l=fy(z4SBwzA_@*VQje+~-^_ZnFT#BQ-% zRF;ogw9S&Rf-Zp&O6IEE-kX~r+|p64>cOo!#t0Nl&2F5eD_+!v#0 z!wTr#KN3U3;S%o1DF^H@i)zXR~bA^h{Npn@hr?&t-%2O4wI!8xz-7 zo^^Y>V3E#H!(*f~3lpl+q$-K##)hj7dB=P#W73FK+Fn7_v^(z&>8%YLxb6=Q(e2hy zCzV}`G#_BQu)HJn)T`;xc}nf9%>R99P#78QF?{Kf!@XOZX$uqlMI;3d&m1P@mJ9p7 z+rCRmVo9CN;egRy*R9*yL*n(kosA>ij)C7ta>~+e?HrY7)sa8>PkI+~&vB)nEM}T2 zW`lTDuO70;j@hB8dY+>qoU-hj1G49t7pTv^(9bxjW)){D&GX+H?0nXl8H_+kvB4;Y zzWLitD$)-HR+_o!zhbzuU%@X*kw4r7%cE-tsO_|!)H@{JX-kFFE1&tHh8WoCv-0Xu5x z>@bZQP8hp{x|Ln*no*;+%_ywYXEx{(*1t^<^S)Sr?SB8TB= z-(0Z1@>VsL?&`H*)T|GS9$Ot#Xy(4Ip{}N_E`L`E&O;<&>9X-6rEn1Ee!t)QRif+q z21`mjK{uwIV3Dv3Wp^FEjc+cPOz3u(yz=lZXYnfcp@u-&?)Z)kL}lv>X&ywmM~gSC zcTFPZIg%M-{2_3G7q4%vB*nP7W~)6Cv5U~_WTi3av)*Sr?<6`ZXRGzf6dtrCMvg*xUpJ?tpv7O?rl5(^K3jtFAJnsE z+rR&qi8hLNw5FmVLDbM!$RxZ^2x=-}CnvuPch!3R0czY}~X;|o7|z51gA z{iRF^JLtM0TYx}$6Ri*8KBw)MS6iOX41nm%=wj)glW8AJ=2|CsJ$j2%B|nqX?%*5h z*(x5KkX@F$>1L~^7ihWEv$>eF-chol>(_yNSkiIQ1c^x@Qd**}o6F`LQ$%XG;;=2S zil84q-)qz#sw?(%nJo7Ha6*{ECW@*wiKES74QQ{bcE&eIKaAj~_97WETh#6r(VjElY+A z+?mnG)VH4sqyI?oI7G41(--MeaXS_2XE9OEkk5={=`=*w)Ao04FYeBM0-0fONU#@! zysI8Bc+dersKMQ0DdQ@WjwRm66F7djZy6?jF)wim9n7OR5Cyi>v3 z6RHohhKQQD4jWExA)2(FK!qcE4Q>A-Z6(^F9DcF?MZJ_Upo#G2iq%H3`x{Eds}|!O zt)E8kz6`{Cyg!$mP+_UPrYbE@j0h?M+aPG&ncLe#%<4f=MtX?pzRr#0j;}BGWpwBi zTP2K-y#%nk^GP6E)tfd9ovAja;*U3Q?lD^<+x1nN#Yw2 zbnc`0-EOj?;i|`S#D{Y5eS4;p?WnZtRtJxk{n`!|l>?Nbl5VRBv))ru_19FTYHs*h z-})1(WHLW>fKDH}s<;z}pTFG+HX+?~O(m{wh@nF*xdlou1NZEdan(f|5A++ta(QxH5Mo;q{b6|NL^%2y$Ka zR%X7#(IlqyVw#0qfZHN~FObmyF(3g?v@PQdf%SOXrLoe zE;Pe&i=*Gjc-pxr;u0CzKE^YxrQ7$`Fez@ikDh8(5*fMgx>=#=RMed+JzC+{ms)^m zWV-xE{Z!Q40lrgfYiP)?HyU*J8F(!4@Lf;R8n@6YFl5jFebi3bZGD6N4j=6}dR5qj ze!C-LjxxJ}_I-a@48ugHZpD(*qS8NyUD#Yy_exOukyyCT$B^S!^{!rgU`mP|9H!8q z$7vpz-~Gk1=UMaUVIiT{cxuJB-JDjxS9y8e`Iy>glUDe=d6X#Uc*Pxdm}sxMoO$d1 z#Iur>WAjr~q8)=Bd-m*j8HnkR)*X|Bi?zE(lQ-uDn%?mX{c?Y(`PxgU)=Xx-<+KB9 zn!=Zt`d><_erybXaqCWh=@DAaSILYmz1kFdDFfGY6(`!rJIhY^B4aP z^!IvffVUC*&vJ6$Vgw7Sgl!CAAv)T3OOc5x;-k^Z&w?#+R!X>716%>NXT z?{V?d3i-&Zh#NkIY**Tq_C!@as-LC&el>n^dBEk|AxxU$B=knX=bfEL+PL4pKMLL6 zwxo;N55#>>XmN~e|FpGEQK-+J?^i)#qEtEPVCd+6 zDuvUmQiNdq!UUDn4{7G&_g)4s+01I>Ii#=eyYKKrVYKX4scwR&#dNshk2e>X4bLCH zQ~i--s-i`_B>ZOG=47nKwd9s3Wj+QjBe`{NwmbzoxDBi2W_OwXN#Ebd=Vol1e8Np;-wH@@kZFb z#&KkU4DS!Uat9a0oWcfH-On|W?}SC1592J^>stVLk1Bmg@;W=LHS1}4lAB3e!9`F@{?N#C7AgBj_Z~bre<3o8vpC$8 zJgw0$`Fn3upKY(^di^RO&u0P8`hN5ohrZOb-yq$nEh+t=mJ(3d*L0!aa>uP(x8^ov zH=jL`n!fvz!mnID|I@UkEbWs@g_+=EugITJCa^9E_CKm?9E%ed67p5|7OA_}azwNB z-j{~5K;CJamwfKC-t6|{E|(|HsK9 z&sJB|+4=ps^XhgT&C=Rl^)ijU_tj{8J`X6mtsa-kS)|xpUo6=6uc!DW#vBU)@U(tV z@}S62nS%@Sa44BheVD5dJId$jcZbVGl8Z|TokYuhyD$@kL$;87>X|-|$g}vJ2<&Zj! zFq~U`FxUI+I9%r6kRL~1Nk-34Fe^@mfa*n+TRg)`IQ#SWZyPfY4%HYl*kbBA5m+xLVYTWPKxUQ>N zCENB1=opIf5t6sQn2+#a21F%wn5*!}LOAI@a=u}|%ev|9|0XP4$jOz$Ui?vu!?00I z|A>)uI=rjmE~BN zyK%H=h3hB%RRs-A%}fkYCAbrSs&zo!^1y2sOt>Xpj5%I>gI<6|Xr}1(*h;t1Fcbzg zXVv>gW-K>X%Ko(4%)a^~dQDy@Wq}Z3{%X~kS##~Qn+rflcieeJ^t`4T-6e%14;~DE z=RfgHrzgYj{gt)xZ3OscfNpu$V)tCuT`Nt=;f^qk$JcVQ;*|58(G7yiu4c}| zo&1j5PDzK!w`FF-n@IXB^=qe=X8uIk%>2lB=g%fy82QvBR;nVuQS^$M+G7yr>$!rR zpKU$OdwJ}oWYVaL^sAozV^JB3uCx?|lT@|1NVBo_E+jbk5+(>_>0CY}_#6wJ);n1D z0ea`+IvEcITMaiwcJ_UEQ+tV%GHD028OD=!jm8&aF!rNvs9IE#OI`i$X%>HGVc%!8 zmD@eP?iseb*O3*0DYKT(6AI&kV^EFX3KPHK(WD$!%Ia8}82hDgqwh)I`h%c?hG)6% zUAz35L#s!Wa_;@BK6Xj-^h?>odDYfb_rQ{^l`Y5~m)Y)4W#2Ek|7+HY>2zoABT<&a zym2vUFA@^Y6CyJG2X34T3zRG}cK(oJnKiy@$Q6tSfVTaRI2Uxx$6^fTGp)+Oe#<6*fOhb)Xwqdnvx7DpI&1~6%rMGLEe<}PHU<$YB(nI%D2ua zctA!V*wl1AKgnsO1-QX?8_X;^1ZY-OYLy!IJxe^es$@ZcN&8Y+PU5wa;YrDe)9x&$ zz!o$#)DSk`zkE_7nI8F2i%#QPZVD(da(^@8Gckb*Lk4!zILGV@P&jw}(X-s&S|C_Q z!n?!&emhTQW=73Q&&jk(gIHW8ks?KLq(N&XvMH2;L2N6_ctjlH(ZYtY|W6ij}O0ykO*D= z<$3Ct=Cue%pRuno{$inXfhC@y`=T4XeWk9@N35IW6mRV%bBpRuzp^CQrSF<{t2XBa z)Qj%x8@GOAddT90?9+GoKK*etH5Y3MQM^RT^WVQ20eTFy-$T5fo2vy1T;O0p+~?HoKoh)`!{4;r2Dp7Lxkdl(w3Sfg^0Cf| znxzNE0$md!$Ly*mavVw&oW@TwN-^r#>ApU_|AXs%Gg>2VhO^^AGl#BEl3lPaWqMwB z)VkID*n7SmhaZ~uy6o8_CO2_=y7eL7zPKmnRu2nMjw~+4{!z%i_q0M29%ui(Vrl>7 z+|$;@w?)NzPDPE4F(oDKWc4toTz*Vw+k7U<5{tKX1YR^pc_>J3^E6kqs)Qpnepsr^5X*^Z* zCF^~nbLv^EGy^ethSc+C&q|S#&+H~C3aGsKbv!tB^Az>N`~BYrJM>b|%+H0L>_0{> z_?r4wu0_(d8}Bp^7bT#(sYhv3)Ux^|MR(`RKoSo5HlNbP>r-!cry+mwN;d2~z5Iar zF@^gq?T3&1C+IFFH0Ta@+^NviszTAbZKh|7^5DUfHh0V)+IZ+@shK}cDDUs+%2NEV zood@6owzrx_|NKMOL9ThY}3NG`%?~+N$U~ls{Y`ti`vDbkyVU|o;nS_oVjG4Z_C4M z(&&2>n&|gK^4Xi;m*(;K*Ds>3F`XIvOmxq7eUA~C-zy}Fa-noYzsvf0**5;7U#p8H z8!5`%>9}-(E3R_3^?F>9Iyp5v+4jxQk8^F4DZBA;VZviA zYIpJ2HY@tS4__a&r_b1{dHDB5Ji#`p&C_+!?XzEMYD!lP?U4;zHyLq&5Y~X&j zKKcJzK)#MWRx2B2-W-BzS&bq;nae}|CmB5}uRyjw7wdVHCE&a~DUIEH>4Wc+Ufpk| zglh9MsTYXf@K9){hpa#2c4ko$636c}i~?t}ly^-#b;jJ$cJ$=S#2bvzmLA-Wjp1MU;eE12cObA+@D8`us_YG ztq+9f`0E57ptL|+wqefuuB{#>NU^~#thfT**6^SxDKXyphe_?&WQGI8qxF<@?*?a< z7k;yYLETGDPC7s$AqhL1Z&@=mpadxnH>Y1 z4Y1>ifq^P?t%RNi>}2tz9A)D?(vo($X4Z_CC zl+DLr?rpJp2h2#T(eUj5O_im2QeFnuT~Sf-3`V?QjCaRGr~BFjAq@e)M+~P8F~5kS~J6p3EC&LwOPv+=MS-%}Ww}=x_k-u`ZYpCH4b=?uF<*x#c3{d3giRCB4>) z5k5k92VvX}f{O%-Ivt5Iiif~m0_8!F)Wh?K5Ke+O_m0Je3qnJufm&<>%`Q z?z3$EDWO*bm5#yE?AwseV3r`u=^&7#_W;3Sm;mS+)Zy@p5iBzR7ce)|prq6LjovsCK9LEH+n#<-^M&bhrRm`)%z+pgC{orCyc>y^OscDBP z7fT?kqym7zZG_$d+A|1_3*(2%I$>7}{!odh=u z^#b}Zgk<^I)2D|(c4Oa&ka6W+Am!d`How!idzU@rtp&1%r|;c52kB)gre|LU<^!15 zpH(spr-k5IA?AWm0!l+6=XvvPa58{(F>7EaF>x8fH)4?h@Ht{!afQ)aDE}bHASAC4 zCEY(+4893VZ&;wv4duE9ME$GL=V?e#Uc|)Iqx2f}Yzjmy;C@F!R{+r@=r{pj&=_nC zLLREqd8R(nW$Y3n0Di0t;5g?qUABvzSVo57^0faXso10xK^~%x4^9vmcXCSx{tZzM z-dB^kqN?g~VPRSvRmhTZ!RI`~*kYU>;9_^7jKz#-GrV`-I24C*Dp7`j>3O?^#`+=u^Z4AE+<>77Nrg>DL4vmlP^`@ zg%a=(C{wH@qls@)1hI-0t4JgW$)Ztic#@3kz;s zcE-IvK*cfstXpIetN6YZnxTI}d>_Bql{eF^yU7AfX5X z)~OK6b|@<{J=IkQ(>ykK2*!S8c5r*&k8xrpiU(GZ0ERTeyn6^+F+%(_1Yn6OF>y9M z#lXE0mk!TC;iOdJzCj!+f&#}Ghc&7}l1+%OAVHJxjU!f%{nt7iSXyhc$i5UIupLsD zqe`b^RIuubINyZ6fi3WO#QvJ`1v>~TSoT5UqKb|{M=-H_T^pTqQb1ny{*zR%5N zgy7~#7cQM%4y%it-1b=aRW8}J_C`qh@oK>Ofw?2(zW~n3Zrt6LRhxP z0;9#TI!*r&7)fGa`0p}21YoD_5aUDCh9kZgFpUXyu`tWlpV4j$dd@HlsF~^IZKranA%CR5^Sap)LiWIS7z; z7#r&hF+d#~GeE4%gP{iEUshO%&nL7o(qAqE=3j1(-F$>`>sVbO7Z@9N0uOACK-G!S z<(<%c68iwo+#DOj+s1UhUBit53P;efdJ8=GL@`9#rdV)Ad>tXI{`V)F0vZ7PevqTf zdETaLA&_m*nf?9!=ztLF1TeO(aPB`qdA>65%;339%y1%nEciK%W(aVb=PnJgSM!R2i9>2c@0oTeOQ= zr+w!y&J@|t+ZB#Lx=8KhEFEc zal}c%;n&cp1RG6kcS;*SlMROfp{F0zt9Y{h%wo^6IEWey=p%C4SM^KQ9bW=~tOAMt zT}Qu)caRCaCUlUU|70MkK&%3Zh*rKm7ogp3#P&q!R4^@I#z_j2K}b`@?f&kDt78Tr zOw~{j13nzSl-S&a<$WGEsHCh!nIXj^IBw_}V8aO;h;PO{#ov|-d>%~_L+ApCnfJuj z5bMs<(D1-M;68fdQqhNe{|2YTI`-4nuxfmP5NZK#O#^*^U@N|fG1>_1ZNI#)1$6N<*Y|We^M33L$Dq zz`vUZV5kXp8CAd*m}5kS`Kd*7ij;UB z;rNX&fVVhs;D9|>6q+6u7Rwlgfi)I{%Cpo`bZOZEh)F+WpK%as;%E^%qu1C0g%?ij z@FK1`VFD}t24}Dy04t~n#rg)~@?f4dV$kzi@kyBDcgn)2g~ z9F$6ekN}cVGW|E?&lxj$zMR8!0T@l-&-)Xbl^`2|mIzt`)R9{aH~an-Vn&AT^V_(N z5F$g<(DP;&2b7>NW5lI}6ZEb(J0d0)j@mNx_I+lPAMu=EP%tvQVrmH^Yn>3~pje0b z9MC>sp8^L?8rr74x5mfD1fuF;o_&3N3Blk0sX(BtB~%llR)2o=y;GKsggQGNG67<% z1QeJ6*NJ2SvkPE8BgF5S*%lu-BqS7!O@!%KdxU-*7fNuADEHD6@f!a%kWl95auEa_2ocb7q|4BH!mH8XH8P>2xwGGPM`DP0v9DznbHcK!N! z#4h+Hvvs_!$CUlD#GE-H7l391>q)4?YvnO+fs~ZA3@~&6Ts|?j2DLn3^oTtfFiL?~ z#^aHxlS0H^Xo3)GX?OQc(>7Od)gT&VWY}O+aE5jM@hdAU>t;o#J>qjMbE>J(T>9dg z<_PYeaQ(athp0F73=A44a(WtqIL<92YW9k+Ku+|ZQ2)XUs2mb=b0d%o?d~i3R`d(Y zIS>>=lhhA+k8xY-4LQS3jDo>uA&4P~s%Ov}`#Ivv$HPOxHV&mcGA=a ze&_Ky&%Nq-dH33D%{AwkV~h!p0i{m@%&c9b$n2(>`_)Wk6~z->ma> z_(Wu2EvRL%Z~TFr1B3+-8=yOIgg4j>ir8MbS1t779gzPV83c_Z+Ba0 z!v!H85-yZr%Yw-W2!;`N35d%`9f6FInfa6eA8`d-fZ)}E1QA9Z%>VXttDA+)?47aT zm1f3^V--ZO2f2-j)C!`Zfcg_u+lcTS&Y49Pgfbx3`(K>S*?|EH(8~V`G@Z_FM?^%R z(0k7jA#Y~!V-PJP2@L4D*jEiM9cNseFhchCXpG+uw%pT4kCx8RC7dC-}gr1GF*6&j==0Z8khnG>TF4I zS8kAqLLi!fwQI;m(gj3mjOZ^Rpe#dj4SO7a(gcx|4CzFpoQtliDyVZ0aOe*$tUG+B^qf}oHK94@!{cEtH^Uz@>rqj|Tpd_sWJc4;{tAX`@6{TR%E0d+ivBOMNpL~@ zQ+su(#L;y_FA8ib2rBuI>;{RyMMa3(6O>6KU|jXXJC;HEHO%|@0P{y7iKW$$B%z_{ zMkLJ;JzapS31{xTQ3c{L^G@Sc3&1U)R6esAelu|y3J>}GQ8$?5hD;>`2O2~rL}USx zxD6Dy!4G^P`zOF;$x0hYCB7o|-q5J-_N67Lkcse&0FMD(JdzYB>4Y^`mi*qB$l+4g zZZ=te04Xcfbj%VGG~iSPmu@BB{#t$p1k!)<^dL{kbfl;TgC6jJO6zAf_uE7qsH#nB zkzru+um_O314xs2Z&Uet&o=FDBKkTIAt4z9G`D<=tHLx% zJ{|ad%`+@TZDQf63mtc1(dVM9toa})8If-K9;9!VR&WF0bnj2k{Y`=F2OK+m!HCEg zl;t2QM24b*WdcAXUUl@wDJT6d0SaDTA4&Xxp*#y`b-GHU4*n?JF5^iG{PbPOEvh9c z_Ir5CTw(q%jQo`Vb!*w5$GT)M3f_OL`u|NGI)U+UeenSYtN^4Si3LRKMUayT-7BL~ zO9UW?N7MHNnRh?M?!qUbq|mE`0n?Y)s5gWH_ViZ`lWkY##(k zHFqUS%cxpX{PDM=$ zf7!u@kc86Cw)=gzlqF1!3$q40#aI8nqA?ps-m{J37O|BpiJp!B_pOv3nwgc=y?b7p zo~C&(I`f}PUnpLKCROGAyUY!_H~CtM$DVQgSl7*>XhB3C!N1fW(6X!P=6CQH7De&( zLcX6c57;lTBCdewcWus1r}Hd*sWzDn7uYLbEWpe`o==nvu_!$1SX}epbt1oOO!TCI zIbAax=A@kmK;i=Lm~7#{509neSSeytgAZn|_J^|qy?rRl7rg2Ke3gy3W_CA`S#gFN zSt^`#ecHw%Wk;?T4_|6)P!2_u(yv(x`u zzT>k-%^Qd83zN*fhWh$Ys~8klD;YlOYO9f^bX^RCM{&D^3m^5PNT=mkf1>iM>c5Qi zpCuZ&i+x_OlQ+@TMpi0Vd(qy0bw_B*VfbG4zymPP)F)IHN=-_t+ITc2Xchyn5C?NY zLnZN{SzbcH#}yy2(1M2EVr4EQ1$0E6`gsOKkxSE6<-uM5jf{FuCVyjlglpxN$NPQ> zbA5f#Pl8qua%S+n0_&ZJV$=E=DqZ;h=5ooBsMAd_IhSN{sTa5S0U8bN#epp?EkvC{ zVGj!vT;-4rm&rNwx}pF(GcPrp3lKnn5f#W}-*0XHZ?Wn|SG}CMb&`NK@-K^k8k+f} z5%y5n(!bX@(7bU3TaEt%3n4a!WlpEm(r*yxFvI+u8|i-E$&= zllCGoBMwBpc))c5g$Q0b!t{rY9Hsq7Utp~8)&b9PIE1zMkX z&6z*{+kRMn=`z-o&JRA1c{Fv*^xyWbJGg(BzcF>$)A{VF-Rq5i$2s8ns?_~oBeYlm zV-}A^jjlcXXxeqvyu{#fzrlJQWhvMD|Luq0e)2pYOC0obdTZrI_V;SF!t*?XxDYd#Q#ZZU$bm)~d=+`R0Zyr2 z6C2|W=Nj{^$U?IaQxgO7FfcVUu}S+kp}1n)S|qv*GfE-(B-(Wjz=Ds<{eG_F*D6@ z**=FS{oF{rntlISy|Ddo(_MZ2Fg5@V=?<~il6|6-u7q|=I&U|8W3Z&aP=gR{TvbpC z%>saNA;&W*`Pd(~?#LIpK{hQTF2?Ziv65-1w!H%PSJ?cIbFNdD67OPx^c%`nf`5+L za0&oZ1kvo(g?BWiq0yxjJmx{z_(tC;oWRrqGx%dWRVJjWfOOn}L5BUd3i|pW9smdZ zE%x@<8;RMK6D9+tQU!leEY(3z8*CQhHkMN=;4TU9k$wx(yGcpntz<8N^y+5gW}T7Q zE{J(+!kafRAJ9WpGh0Z$dO~NH#mC7)9nB6)?~F0`BHt%bQb&VbO&(pueKaeN+`sfp z=C_rlbM;+}o6O7Ta^9<#rd+x_Np9Da`wJk&Cl?;LQp4lVI3L+i?o@k~2Q)Pu88;-C z1)m0D2AC?A6 z?}KHBE)RXIIIDJZu#CV-JN8nQcp{TQyP%^YQ0ZrmUPd3|5QsiyI_pbDSd67!c~ zL;(nGoFc%nY~O@)MBO{_iax?9#d^mesD{ix`3Eqr^FY7<_j6eL1>auMj$V>_fc>hTIcicl)=M;S&L`%c*+ z*H;%#!Seti%n4lTpr4#=cP2Jd4sx=szP>E4Etb&RMPns%!Aj(EuN^Mr!9T?ur}lk< z7nRGxoU_|okQh9{nKSC}iP_j@7K?CY*5vS)xkA%>`LCZIYu~^2ydE!cL5c7$0|c1j zif@wl#tL*op#2CL4%mx8-`J`G@did5P-@K_!9F+Dw9$}qF5nzIG|_GH@&fyScn*!S zPm|(6P_9#|k@n54!y>(Japo)j=+dNCFtY>`-e(!Kql$Gx9G*bE$2x(m7}Gl;4&;h+ zXZ^cpzg_>TJ&(zZ#l9U8>Q=C`-ncN|iqJ&TGT#0$_0<%nY2mu-$G3bQ9{ zbEpmsW>Hh6Y9K-z{1BR56sQp_$E=GTJ+64~uTa4WVd4qlnZnapjz_pY)v8g9`bY-n zaf!g`Q#!kvF?;MG#HW7i&45B|FR^`s zp6JlK+iw}y7A`2vrK7AcIhnT$lQn`E`_j&n#tI7Z7xaZtU={7h>QyV|qHKmihZdhg2wb9|vS?T$;`g2RVC#g+F|CRzY!8jtU#+naI*RdZ1e*vz(MbkweZW#PoTHY0z-Ak2nIYG6 z&DB`;w}_B8yK8DNo7^(K;N~MiqR^?|uI@Z~^;mz718Y2;xunIa@hD!YK z+dF(p%WXq6^?8=db46Rk@(B?LpQl-Oo;yIFUarKE&I}S?=!5+k7j{q!^^s5ypBd2C zPc|y?1VtqPz)S8qTs;)MBp<(0OZV(KNqW&7@Y^qDE-Xds^ziR|RXAYl@+V~Jz?K9g zO8#4K(0p9QVEdJxOO1}IzL=E;QI|IH?wcA=jPKyZ)vAbxLH zK)z$^Qfw}^RSNraJ#Ilewl9qfo^ML&qeiK^C+&HKNBLzQCdOpPW4DK88x2S4o1@Fs zFq6mUfURo&D9r5!C(2K=zcPOn6sfzp2|?G+vhE#Gq|4th{G^nmg`-ojz7SmOi2JhU zZZ&jevigx-oeI13z?MHZ#yw0eT)hASN!*c)uz(A~k#7C=Cr5r2OI1FMY{im^d)%0UYksK^{G=Ae@&f>%mj=tL+X8;l_BqV^pf~AN|1~I4$ zVKh5*nXI?JH#kw?uiry6ggiC8RTJ=w0z3?CYnYxaF#gx6?7CdTy6=MX4Y6oC!d8PI zho9G7uKbbvQzj=C*hJ}XuyX_bLEtPFi73VyVWv37qi&Yr4x1wtS4jo%_))odNgAVO z(pNgt)J^p8*OQ+{RqunsK~ka~v)cCUy;LY?1TR!7aE8xc$-_Z!eZOIGq@@YZen4tif;+$Z^16 z7}}ap@&L}OoKw-D>=Sg*NeF9pAcDcP6O1@w=|;TkIpOf^+h0+epsMsO$L0J6U(CXA=J^ym>2G z`QT=Dv)4=AX&n)u7OfAdl9_aeQ&Qkk)Cr`_{4t$0JALw|R6M{b;FY;*S&l^Rk0ZyS z8~ZztH+BwvQQRA+TzINQ*Pk=pvM-YzTB=GuTTs6h``Yn#PTr<_Ei{YecA-fJC*kWj zg_L#nm210%Sh2pS$ zhaHO9+}zAI{hzMCa1z;mKkS|GrS$g_)w>do-r4xl`!0ct=mV_ z-zj|!O(5haz7K6@Dhii`516yH(#Vfh^ zK`B$4<)cT{oHdW`pb^#1)w%r~&Y2x3{V+%HT2H{INH!aL6agsr(q@&CyO{o1Um&4Kg z*5)RKg__KRBkd3T7U|uzt}9Xb#W~|U)tkjdPBL;Vb;+_r($A-TbZ@MSIys7(hhfd? zg_de}l&5)wR23;*h5f)MV#*Mv2Per58jYl$YlW#3NIWrnBhcRwabu(9Q&^0Qje z#Ym8H@%mKT_YEE0Wb#$AP)p1lb@<~N8ORfq86M$s1-*D;W7 zOnEofo>i}2sKPT|@$zLKPt3coeLhQyyE|z;ON-kCxbQPkczCE!*h6iWJs|^wZ^dG!uNZwYT8A)Y)>I{W)faxZROzv#he1)%vo=LT{c1bTZ%{JA z=f z2b6Qa)F=HLpb%GBcnm}xw@UyIeDRDJ-E!W2lCJ4p5p{3Fd4+fB8w&LtMA;W&bN$dirC%{N=-mP6stN z(gzIUfkHEVr_E^R;=|GMu$$S@t5xq}KXVu|fF?reM!_C6!pyFotGX5KWbDSLBy_)X zmxgyhytCpr8GC@_E46z`N1JUb47?vdNL0iN3wzmG#V#0CvYCoi8|Sj~zvCifkqbtt zT3w=@mEFGOIrijfX0aaE*Qr^QTw&v*Kd9Mi=+|rn9G%Y2ZF@Tb$!_rpPWBf)pgs+4 z@|oPNj?mXA&8ke7WtZr9&17ED9L&U*HtNZ1kkw`T;d3$=YCg>8y#nJ3$}8SH@bUZ& z-cf`N>B)EAswYxl%1OS}?N918VKcifalObta#dTuP%p(N_T)T3Z46yjGF^<#{6=mY z5CX&=^0AuB%{EPJ9|5;-J+W+Ly+}mMuvmXbidY^8hgtcJy<&@F#=C^FsuA(Q{dynP zJY9!wRTes;5KC%@uL&9)qFP=1QuX)BZZ{%d#_~Q*mH#vJpul&n$px-T^PIm}InCv9 z#N!n5bV>77OWtcL@@-C&@3B{sDrnXx$Y<^F-?$SsK5l>+B3C$~%e_Uw9?S#=rmWNi zj=%Ol7~ZQe%|yQC0LJsygLq+(tV{9bZ51zWpkmLm(X zRCri=#roYRJY0*_TIBJ=BK!vR$*=dY1CM ztI-R8rBXFEvTP&F@~@1MB*D6cp}K`^i7pP+zoHB8$h@F+;AkUkw{nXd)xUKMpCute zWQvO%j|5Xrcp9fw(B8pexL$Bjf6Krgl;u~pg_COW#0i(K;Dw1ur-R*a&(bwpJG<29 zWrHiG3mJM`*GuT3T7j=k}+;6t%!c)svfG&z!Y0%3b4 zopgd<_Rn$$R}@$hnm0E$6T7$HzGc8fM}vi^t(Az0iLrlnS)Yd@wAJ$V@7{f>BFSiB z*pkTGW{Ap5d{;TvyU|z4_bfb|J(&QNo}PY7mttQk{@XWW*fZsP(T>%U&f0VzcqX6M zUtyVZtTtKl{hKb!6ljgmEO8w)Q+1=hf4|peC6x3)t>O|kw#dGVJ6*UoSLorP*VvXG z36t3~Uc>)>;2%NBWc2)sg5b`@pw@Y9QMKqMX!L68enJgROmG%jBzSXhaL96FwF>?a zcW#s4<>MT;r#wkCnGc5%#!>Ao{P*g)Y;n<;G3n{)S2s3Z)DQnTJ*{@P57xy4!p6XW zWN`K=Q>oQcc63(0bK+=I z<1S7IyOx@c4ioj$T>{k%j7FtS9uoQIn)yN!65Ng6=$&pacwMg)<(h5#HC8FlNOihB z%I5a<@u5yu$8xT@!q=N!T}?4NI~&b6C@Ai>fZ5U6Ilt?Z(ns9OeDvJFiaA+cWZb!? z>lV&4OKqNHZT?ik8{G0Z0KZT_tJT9dF!$n0R!>ynXcfH0rgx_fD3 z-Ko7`o@rrBN!R%evtIeR#(+b|v2u>i?MvU`TmboX9;_3K8%jkuz6tFj-+;5p6pGC4c$uEAig#hl7mx-mTeii9LL~A_NvC?zQhFW-ab> z?;ai;Sb$*)__!ABMg#c&?I9&lNIIa!Q29_=jPEcmlqs!0ySNx1#^&%scRLDv0Ujq; ziw0H{lH2B2huOm^T$bF;(#C=Q?w5lD5y=}jgrucoRoQ||OZgpSdj(_KjOSgcgPHp9 zgUe~%8Wm&xuM!{iEbVPHXWM;)ma!X9Iw8=aL71F(wSXB#7SzfnC#%p;M~q4JRW|85 z*E;^_swb$k@Ak5~SZ&|FK3%d;7Pu&0Rb6cfCazqLp{NMk4E4NV2q8cBebfAJe=UZ? z4s;}VV{X7Mhtti@A^OY`DA*NtgA9o4rO#Sks>kJtNkNtRt*xz3U`{J2BNGQ7@Yu6j zG+4eO;?p8XKjs~w6Xlm<|#Hp;^GkyRbk`qNZr)i7&K_# zoEQA`+>$w}eF3M_4I@i?bsf$aP^4%XfoG}1pURAb4t^$4;KOQG??Z}0`mC^9#)xvX zxtJK@b6_JvyeXRK<;xu&hXA(Bj!a?s@gq|t)#_cy9ex1^j3R>!RW|e#8#kcL#>B_B zZXXEUQ z+BXpBcznHW(XFbcX2WDmQOiz<+yNF6;#T6Ej!Z`CA0cp8x2iZ+-Wt-^!HaFIe$Rx% zMHzjQRJsddP3n8suhY}fF#RY<7Z3g-ELz{-U~wEjZ!#X}Cdz^Q+>dWiyPmi|ZFDz+ zSAWS}0^SNa9@bd=r`v26SN@R9#lzCU`?3(kshK7Ox2Gpn8hm#bOeAmxf@! z#{2(d{p7RDg4iAdmC^%%15Cv0GC`sgDbd)O? z;w}P_Hhf~Ey}20$p~($KeyQV@E%8LI_=347F6{2%`qh>*sQ}*t!p#P^_*r#B8oExk zXxkmhEb~wjoZvu+*buLZg)jf)^&&7KMcebExTuNDZWNmt8w-Orzfa!ZV&v7+_IWYO)eo0CEZM@Ou*u~uGQlnJVs6K0QMfA$Xu5_EKQJlEiW zc~4*V{Xd%VGhQ|q-mPwP-zb|QF3Rc{!8uW<8eDQ0P+>`^un?Sly#AG&fPmmfim5YN zIkkE9g9(1*`vZyZ(%?SAC3gdcM#1L@0X{y}Wi+?8Y(+1b5PwtBCZGM(Pv^@GUbpTl z!6t&;Vdg#S`EJ?Y{OP$Tyu9gyhs$9_o@~mP7MB&zNigBOT5NxB4_HJjoZ)=TIM>j( zR4WV0q_=z#37@Af5qzCJFdHz%dEiJeo z76y5f)zPN7Q^x{ES(f#68d1%AQiD{{?HM)I)lU!>zBu?1{`#~?#QmTP=sgHuhJcXp z%i``2AToCD>&9;@dwU#Mh3jl& zawIABD6yEavNxfzs#DKABNAv3w|kfv5({Pn;9ZyVLtInXG9-4ay>F8sG18%b>+apV zkQK>^rQKcL+TK4Al#+@8qicW{nO|w3qd<;OXFVsM6}Z?LAEJu~IJfn+li--khIyod z*gfN1A(u!8bqe+3B7dELoxLnia^lY?;&dILML_X=4$P2vgbe~0mWAEp$_`B&xmvRh zxXC>6@9|LTbW!ZwqTjEIOqtV_2L?8zxbZWij{t$CPCggV|ou~2${|0)@Y@NR@# zli2%Kn3n*z8_fG?gJp>ag%Qn(|M$4hovijlwHHf)+`CZ&g7J9@)V`L1=LM z!`oHN(LsD2w(cG?rMG-Rj;Y3%xAQLWhc5X-IFwlU1XeJG+v*bp=7{Ht_J@ z0m7gaP}&f_UQ~OwZHD!I&j@cnN4&zem}MDYn}FT6VR|AtCK~*2DuH{Ld3x*KrQjy@ z-n52@uUGvQ`JDg$ZH?Qvvr0+`r3T~md6Em01KN}8dwOs_B~YpqjX6$j{Juv)6kZ0I zloB6h>m`{TGzY>tNai7kW;Qi3!Y#MtP6Im_CXpvzJA{(r?FzhC61*_rf+NFP`hni9 zPx6fE4o`Mn&Zu)kaiCR21aDbA84RC-e3k0YpFesxHzvwdq!>Ee+A#M{>bG7!K&f;4 zyzPX^W3lj)98PYh*Z?mXTHt`^4S)Y0H(TcoSHursD~{NIf946fMc=>x%PWlqIN?DM zuiDx|MW`z)KC7}(xgMvMt($ltw0PihW2|}jb)Uj#<$C%dvmr=dX<$QME;YCaj2$Ut z@=tdm^lTSEWYq@3-OrytYx7ZFc#EYyLF>q>xvlhpzXScp=-R==dB6oH>IdX1BcRtf zISFArV+uI@kddXwGY{Vi8IHJ<)^w7l8ew6=A}D{*r2S)42@ zUwM}9g@4a7g0&ZJjM-F0k({VCGN)B2(^yh_=YhmNS^J3dSL3O(D_xB>gVCD|p447s zVjvSva5_o08s0G&__lyp2~;@DdCk=oelOLQTy1~Q;{lahKYV`jB$yDs zV3rUga4uzCTm&G3LY5j1hg+Rz5?oh+bEZ4hJ!P^#SD60nOV8jD?Yq<}cNS6&u{7z| zgDb>d9v(BuXomX3sRxrl+T%&aGfHXizdjd(#0OAl$ikKc;$1wv8)$$sC97Y(Qw>QD z65E6arE)lF1f_h4Ov~y9oWB&KglfPDLpYBJuHO5AoDq`tXkzcN7@<{V-=@aPRQk8HQW@ zVt8r_FK%%MIGXB_l!~3jAo0+r4MOsSWW#%Mrlx5{i*Pm&cAe-1itC7K!QewkFaWYh4;r zMp!jf&TXJ@JhDkbJ84|xqQDHVm$7)tltL|ImYr@tUr9afZU2IQnCE$ zML<2w4kYs>lXsnaa%2gt?3WoC;hl?LfMNK&cS-NY3-{U>$i0c5tSUV7u6q8m_2)5W z++jwQX;o}52yre$QNR#y_f5s)W92aDNBJLPm5wp=;iG?-+KIAE-v*h=mFv!5`_3U= zA>Z4Tj`J#`4~#>*4>?KV@2k`V3!uy7hS8caP(tYykF7%@JxWPYa&1aw%ll5}^=bV{ zKrWWyR2f1DhGP$&`@DH5)=(z0$RD7d$*m$w4{na$+W8!*5TfZxA z`9~@)?5gKogQ>EJMhgaOXqY@svZVG0-B(At_xDKoEEHsac5i*Lq11)j(O3+f3=<6k zB;*aLg;zd{i-c-O#@^5WUSV4E@2kqiXmRe24=bqVFB2Ti!eKWtF@cbint-4g)h6vv z&pMx~Zp2_TbIR=EB1!tl-ym5O@WMO6;6E2jV|iueVtdMgw*Np?!!?KJge;nB=pq%-VRqC7&$k(xXL4+0UoeQJP!>WtV|{%D_n!RL?-us!jB3b zDhu7b84r2m*|^JjO0FL+bJvplBnY%n5n28h#oAnE1%=;}U)v3_TDFXH*G8gcK_Ryu zsmiw3Ip&xw4HCJJE^~1krFEJn=p{8ZRB*<{K{*)wg$ZiU;cwp}fqlxFtgZ%aBc{L= zUnnL)qlgs}5|Vg1m4mDO%#2Jk6@Sg2VKfEc&J zUgQt{mISX_wA!o8e2zFk)ejveh%X~4ivVqVA0x~JPzVMIXCio`p#-b&rGRk%8|xyWKf=A1;O)v6!I%TI zK&bQTe~+6UcWVU%+l%l36c0;`jEd~ex(;Xk@!Tmx<9_-!6J<0I`E0gms6`5cksW`B&d6lNLK+!)mc=JNa=dB7X45X$oxFUY=$*)HM zY%zr*6Gc5ryeLQSCl;BOSeXr3-EY`kQ38{>P>=;*OwTOmU+tM+pWIlU-H-i8R) z9jbx*XDwK7d{)Sn^WX7t^5KTbA6J{7iYBSEJA`p3_<)aY_AnO_gH#0M?tn3aDQX}| zFbrNr2lYKGXl=Oi00(WqCD0Js$?%u}4kskDs%&KDaPxCoK6JjvP4-cv(U!dI9yVVp z6Hc;wt-m$QUCE$}xsP<*`>~c}|zWgE4roeoc#@3zMN8-B! z+;3M!Nl*qEE8~gCj)1e;%Kjo*tvvDQAE~xF<)G`l3lX9L zV8#iguxhs=WjtS1fh=7X2hRE=q*Czihvw#p0eJu{OjtMsRvrNQTXN%jVV&0>P6mS9 zCex(Eq?B8od#{$yHlI_@jQ`>0R#m zgCqc!`c{1!F0;LhOXtuK31~M^kg=Vd_`(aEf!Uirn-!fTk&0{#z)A2q+wI(KW&BG5 zH}eqieGv1V#-^)IMw0Y62+tz7G6 zxE>AfdQyOzC^9RH8C0SGLkth=92^`puk5SMtA~<6DGyv{1YbKpKlfa*rr=Vt^`hjA zr*A#}Dl(P575(Dy@bq6$Bdgq3>+9E8Y}pZvqrVw0JQ_N`9W;XAnXntbwtIHLBBKfm$k)*3V>>7oIkc#cnS7SP_Z`hlv1}y{gJ4=xbd$p6^ zp${(RXK^FS^P6o=+cGMFmJyW+fr;$~TpUA>x@J@*8dILclL&^Y+fZ`pXeBVEWQ})V zTJF*a8}Vr+ugtrW_@om(Z^tXSo62=M$4>lWe0Wh{+^(cge(P!B)`)kR;f>m6eBIOm z{4=Y^Dc`B^wDI0j$zm~3#3@vpU=6x;ExW&bo8ErV$47bX)w@F?h+~MlXz%1K(TpTX zR}qRQO-)2pda0b+`8B{*@twP|F8&zETQo`uW5NM&5$>Wk1!Cz?z!#9D26nXz4CT2X ziC$i|{ptGd_Ebhsck0X4i`Nxxy3FKwv!m0~br(=}PS*PhgN|9?Dn`2?0pv1}4enfe zx^oHY4Ha+inyS!Qq%`~ZQH&4%QB#6(Ly@WX{BU6|;BwIjo&xHb%>!dY>LHVSjzewh zid6L0N+yfuU47Zi>Z7c~>_7{(Z6)i5B%_i_A}uz`iha`C!Xx-9DNW1K)9sr0nW22T zEc$CWj`Y1FRA#7NNoE{!x|&t46%R?d@|Vl8=oZwJp=kCc!X}#@uT09yli1|C_OKPc zZ*giDs};>Ic1ad{ZyRhzJC0RUQLgHu`yFMNoWICRf3^O%_dB1-6*Inb{K`itm z$e4~=Fx0p{PW!R4_1ekYmXr-9??}&!z6xCroWr9IUC& zC_7@@=iwt_`KiyYy+$L%hp#;BwN&=zjMlpQhy3%m$&<1_uLc6-!D=;4m9da$$0g(H zi_dXwgxqmE+^S2x{aJ&x5y#!sF7IIK1mcA;~biy%0pvgSY;FVaN8hdI%PETi*D6NP2iCMH?$AfIlArTHoX7WjD4?m z!|1jMWFatCk$8a?#j*>#<1VNVfGTHb3MrucD~C0OyHkzCS1Qk;1=_0pI@L1x`9?+TWt~4%cwr$x z3E-uS-jV`X6UNcUgJLzvk{S|PaXKOdutH|Tf|g8BObi?Pg+Rjx1$dw?(mj9>?^uoZ z4>R(dxXbA)8@-SE*Qs6{fsQ~33HsZW-DV781bl@yQF4T#S*M?c1q$?a*m>kI&7jqPiBr^ZR#%*1Z%x5Sv}H{`R1^r35{%<Ug<=H=VV|Jl77`H&1^5r{CQ#NR_p#>P{}=@}0PZ2_tr6cdK>VO-1Fs!0y@i1r z+ih2CW`d!S0MH`rTR>T%NdY1Bim2(Qlsf+5SsCvcWvZ{P5cB*hEc zX}hfTqoR{R0g@^(UVsZ%M)c;*i<=M5T8y~dg&$q#?KbedDZLjKnSeH|Q)A0kcS%+v zUGw6|Uc|3#dh3@o%s?Ai6LD_%Z2+R1Vl?MDb^Pw<=`-rlSX@vJ~% zV2N532UO$XTq8ZwRfHc4**#qQm~zd>$KqhX08HyxSh?L@H`wg(s=-F@FSyH00)rew zof{_V!C!9tUE%@;$&6vsTL@e(bmPWpGNA6Be42TZ8+z669vL?KbEx)T{`6Y5G4^Z# z)df9u7`#r;LylJmrS|TS0`dIm+=UEq4*@cRVgMr1wO4JUS~ua^TD*dESb-X`uqzJV z&2gm}j@qSvonPn;RRGQe7aqVv<$U8_WZ(v1l$Su1|aO?boIwrL}7OLrbAw7d% zUo1%YQ*ZSsw!6{6XTh(cF&=nSK+0f&0_Ton=O7Kn8r+9U_hnjIE3784D|C30kv8_t zo5U!ep9v~E-v$FHA(IETIkaAY4hmQmvM7xQc>-Tn_AMcWhfY`k+bfN~Phtn(7_I-% z(@J6$6*rKU*St7Qbi!Qs<-cO-QSl=t^8Dw89iW-egV}u)xA==55`Tb6{%t6u8s}Lu z^a1N@KA;KSNiOqO+I#pNGG_SeEiLGNj~~N1gR~wSUgaX_U^^gN1B3}QZi)KW;F52h z51ih5);j-O*D$5m=D(gF^cEa6U#*<5KmA7uYEXPn6t1w&*?#dvW-c*)dJDU^GBYXL zj6dY^{b1jFm27~YyV8Y2z7Op|aKa)%dVOMPN<7K(@N&RIQ9X|g*aW~eXx^6sG<_#b zz#pyY??zJ`;B62(x!*+SMm3%FHno|bkC`JY14YQoSFcXoSrU$)I=)#PW0n?XdoMzB zopz%5%F2e$w?fiA8;$RoQ*I8ZPYY4JfBWZM{r#bbf`p~Fe(V2s=|9x`*1H(Uu@TRl z=9!I)7d0S(G?q|g@cfiJL4TTmIH;H?fuEA134U1ezGw{k*0pfrI1l##}zpV}*WrBL% z^FsDtKC4;bJFf=)v0*q$($}h&vaHZN0GE{x5LSoVi$ul65kXhv+?FT#Pu8;qQH3}Y zxnp%ZtK!{;XPw;1E+4F({I1XX9cPE)L&-`pJiSIu@OKw3Uj(cwd$RT5_$TL0+_*)+ zPuTW5&d#Ln1)SKx3pm3E6qEq9`s zb6THx?LMu@>WRO@AH;q${;cjejgq;TwCecU`-83tD7t=Mo>y03sLo%dLj%a{J?nSoQ$Y;tGO%C$;{LJ!Wu6XEbwIQ7NoiW3XUL9C64DiV`|7yL`v!@cfMWhu|0qXAhWHqXl3o0U_(Uh`oajA>qQ0T#ygm?*gFyI1f zZ@xV=Fu@Z8MEY{ZF{aGl-T1|#;!=4glIN9lf6fDd9fZtSMq&#Q0!ajXY{Jl>mC+Pa67v{Xn36AO$jLi8nKN*bk5^T0Mj^dI0IT7; zQJ3K6nDPNPv7L5-08;SXk`tkY)+-g9LWZ>T^mCVLQvx&+5uEr{l1v(br7@;Cb|ORD zN(0i%Z5jl4xv4`TMI=%fOjro3%p6!A=5JoU+yTA{;_7gmbMp@?@-tC^X8fEI*s$+_ z0CFFa%t5Jrf&eJfe}K`0u0mwzA{_r`or?*5Y`_L|)Uzr`n8B6v7#ev!r!RbSgWFV? z$gp^p)ZwnnRkCi!REKUB%5Aqj{YRAkH;GBc*B@tjlaJV;T>!=t{x>OLT)x*mRhDNCKl0l{eebX2i z>Ed#6=&}oAe9=+h^FtsqZ%A**B?PgY@#(w;PM*l=ei^Sadh) zjEU`vc5kv?X)j>^Wq~3`kxMgZnR|O5T`-4k0*3(|B?YtO5nRW0Oy3XaS5`m{Dx9FsNNC4b~D=Z0b9JnoTL;xIi|6HD%pj{g8dnC;!MvH%KL zIwYZMw}LG1Vh&h{i=s=v$`Z-~mx>L>6<(5$w?^7yoa*rYd|(@A=)^w}qxPC7PM^m@ zc}bF7Hi{(Ji0{x2z^NwNYczAf|3V;IaMf7=_?`@y z*%g=ipo9cc0Cx*3;N1WR0rDwGgv&P<$ez2$-(14cdC)lVKDb)Gac`?P zl(&a^e9e6sIpQ}-p1#0;4e2ysafRFD{XK?eZdlHr=CL6xUjieV=ae@{6vAP5QDXyW z3P>%2dN-bLx!eaQPbfj)b`E61QMnx1_O#pjn!to6eaBvMWYW(<8{aLKC<2OOR7{u#bbL0E>?|*#+sn0e6+lIajq?7>{M^71%3kgyxG(JCt z==3-yoJ3<^xDUXAuN^6Fkc$cG3t%!SWN90@>p+?bTjg6tRZE1ywBi`o$rQ&@wJ~XyBS#7<+94y#cb5($DKW zXTP@p@*~t8Bu62`jn26-T(4WG2mM$Gj?iw3ghCD)z!s2nfe(u;OTzPOW^QzL(=?DV z?ly+JOqp2OXQqtKDk~#SyY7-Alg;`7ZZRA~XK7NkBM3A;@F2SfqgsocFugUf{ke9{ zv~=p=N)wRf{sOgR#3*L=_k)7FSFJ|zc(b+5?{;Z$6jQL;<+W0XswLUt81=v5(~?%B zP*nH$%QLDU)g*z^L({;J6{ia*FDcmqDqO{5=x@W0fJC10&roW$pv1I^WD^!m+fmT^VFQ!7~yEfBB)n*ZUo*IIds6g!%;iNu+^34+pgks`#Pt zacorLM*W+JrMOGksTtIUe9HlpYK9(NWZg)5CdN+{p~$@~3e^exg1CIEF?xDwzuBFP ziv9yiwRo@rJYSDb2A{@d{5{Br92qGbS65NY)|uK|_0X-ph;^@((%I-_<*_dKh*O7p z;$jt?M^ta}(}|tcKw8t-k6DXJ)S--hELN}ZwN=Usfnxau$BpxAJWaxQx^^}zmj`cK zcV08<+kS;1h|L6wzN66A`Ec~0=5uIK(z>1a%OJQCI8_oO+!%!E1V7$rzaQkkl8QA_Y_3jo+7FQqgY|g0=pvJzZB(ClFzJ8-jp%;>SDRz+Tx7n`WYmat=HnF*x?4@N$7?x z=oRVIdS6Q})Dd0kDKZO5KBuUWAXn_;QJu=tZd{;^V^P~jk)aAY7i)o*HA|0!>70}F zG0J&&L4E-EO`Qm<3oO$tpe$P5+*IVFe33$*q|oRZj8xn8hD;eb`n`rs;gjJUWdFFQ zh!Z8iNIL*60FM_P1?3vF08ufN(d{eOUiA^Xi0ODv26u6^ij z5u7)&(&xD;v>dcOrdqgn=qt@x3~(tMx+Ah(39431f|la6967AA_bmy&^0Tt)WNUvW z`sN+}@a84TJ2p{s>DBQVvSg^v%1vc3zyNVaDc}O8X8eYB&_aaD7fN8G6eSgvaFM|Z zn_f!rJ0pb$K+;4Yy5!ap4cA*Cjn-|Y2$~|OaDY+*93I!*1tl2mPQ=Q}3Wc(QWO@hO zH*oC%Dg!47h}-IPo%G#H?q%fB?f0R}7P@j0L_6Uz@n^S4qofD-B~Q}(*XwyaQB-() zVl0Y9a*e@wLTT*gyaSe@7DBgEb!9eQr7aaQCbPX)ey5z8F?ABGfq)h@3XqvxJ z_NhLp_>eTd82yJM1sz!2qyaHXvTUMmVBR%UJnlZgj}Y-7yVc{?%)jFDbgVZ85gbxEvbQnTTH$*-Jx#*)RaJ-MDP1{>{t zt8-khf|K`YwhRXw3Z(yE0Q?UF@K-Y-ZbtR0cOAX^(0XoW+L>0J%ge9aN2?8(ady-? zPd$#3m%D?d7-A$}fhe2JB9qA=l}btL?k1B-q|@mong7JBR$i~S>U26MN~O~AQmOQ- zLZNV^TrR(Z#VJ64jbnT=;#3kXuh=I3Mis)4mzkE82Lws%>INv+OWtz*#Y6{Y^P~- zPPKj2I&ro5NiCvRo7Bk1|-Mdy@YCT82Heyu&%_IS%@-^F( zxmL?#G%(d8>D4A*y@9gcKuoLLYO%gz(hM<|y~pDbvsx8dmYv~wev0F`(Q>(brdqAe zRIAlwwOXAJ1Yrz|j;|3JuZTp;%LqwOn3e@uUo0nHL4~w<8R-ftid9a0Mx<(%NX;B$ zM8wNpSvB${Iz$XCpZg^$rf0c1TKPMpqIi|_x^m^Kw#^~?xMXTrBwDvj?Yd+pY5DI? zEP8s&&DkO;djR-YmJPUEF0aGk@Hm}LFT*e{mSr6*%Q^`mEC50&mFlPVzgmTxiG!vF z+X3sVaF{(#FC&a{l-X!!M@*bwEl6I?L}aE;tz^4VmSN2Z6lFPUohOxbs$v_Y&`y2> z6*VF6nAPr`DhQFh+kYEo@Tz-Za!M&B;td*~N2_h9w%J-)2>_}n|B~Zn_bjN05Nb4t zsvS!e&t_TM5}&0?8L9ZYY#%D$U-rC}q$UtTKF>*WmMEJRESsUY{jUMu#$A;Dp@|)D<@xDR%*YMYM+YiQ>^VH z-&ej*wf0wj9`TxttpAih|EfaW%E?zOe^t>J2`Xl0<^8I~`KtX-4d!yq%*7g-h)pPC zv*(e%I}B8fve8l%(xoaU0W&GSl&YAQ5vw3;lsuNk2g`pG=W#_6tjGwrEK|cJ#hkE1 zF;DDJ%n`ew?zp9#bB2PT8O43EDvg4u)QMJ(YdwP1>R6yc?nL7`5S7uQ{F#U&R|oW+ z4~T||NGlkgQ5hVF*HMmcp`m6312qjSk11ChgfOy^w{j4$7RXmQpi*}1yrRv?%g*bx zB{hqKa=^r@{H9iiT73f1Au~ZS*kcs!gV*Vcv{WslxOcU4tF?8i7<>q_K8LCd&;*r% zt9+oxn`nnn3b6B&B&)z@qO8C;MKNk*D%+rM6#1c3egAjGYS0qEAMkRTUzY zmxWhRvw{W@LowegXppU-@~$g?*CJN65GAu#FxudE(^f2HoUdM5N1`!eQ|lm<=4U;# zw3bR%n>S_^^T%prC-;bUsLUZdWaexZ%e|+airF}kDFIJk!m88n3kSeQDUqt2QrzT9C#K0u2)frfs2R2$9 zgBmCf3jM%yz4Ivt2h?ERkm_7h**R-<z24OK8 z9hg=<5(9I!+ObOYr#Ej6m8k>3IGMhYYS$YSDwUTRg+mpV6+Qn3Xb=q)gr_z?3Kc@+ zRR~f^f=XiLHHeYdm~T}}dZA_x7F3=iud$7oAX2TlR;tqmj8aINnbU>IZKi&A7?_)3 z@G?;7J7`gj@6aJ)y>l830E`qnqtY=ce>WN|m{|zIXvsyhiic`+2*f0z8j*^Ynk71o zQ?29D3r060U25_;VxeKHsTm{UH>2<`h4R%K^yoRm5fkc6kI|ZP?TrHT%6k#<@m);zQ+Ka<$bl_%kN^23I+B}e;Vd93typ`Hq zn$p#s=$N>a8jQX_{jv2GFks^l1s8-FXOHDCowI`}luT+B|m^DhS zMi5j?r9@}+&p_Sd)65`*sF>u`22KpjrPebVd}=vCL8lyMq5^0g@1LG!K+kfZW>H~u z>dLGmo7&Wo(OR`egLSGxqb0S|JO)Fd;pwhO!J= zi>g}9i+W7NjjZe2 z=;8~@wu#=n#G>g>Pn{a6utwJYMV%&HqG7sL>tqBS6`}U>YncZb4FyK)?10rgqSX|- z6%(0R0@EV`wdYNA>YPA-n!swCAqIoMdhXT8Jh+;~tE@+Aa@}>1|8CjvU z-U*^H0An<)BwCg!VsJh)gAZb&AA!kth}6+m_2znEFqnYBKt}5vW(Hk)-_4LLF|iFM z>twYCu=NVnMvqq|U$e^BXe0{_vmc;8kJxCXni-8yi~FdVX#jJvV|pHXW*?Fnbwe%I z2Q}G1jb3^yFO{CzO&La@bw5<6-55C(UG5+zOvGyMp;0|qSx!yM#A@WEV)V`!wM8Q` zFsq!@NJ3CCol=9gXGYmUL$Oj5mIA6#KC}IvmEQ#meHToem%w_KCo?=iSMfa~O?p>N zZP)X5wnE5eMwV91g2Y0(%#K=#iR+j(>rx99ZY4vNk>iSGV@M^ZxG9qz6-z;h+ z&8Su^uTiJVz}O+j>LAKYas?xAeJgFUnH@b{!E;z8aN6KGXcNjtP=9!j*|yuv=iIQj z^Gc26*V;9d&LmouXU3s{tWfzHA%&GDn0f{zw1LK7Pnnt#!?za57!BN4qn&5HosOB~ z1XxS#qP4GJL0OvVkOdtDuh-U%oX#5U51U0KYsnf!FOzfDD=wC7tXKJ3>A=m-85${7 zy}YgUlu^(0#h9p2D+(VvO5G|k>K$KCXwpiOGilNb@m`p}ZB)7IDN?g!VkW-YXaNH& zoej0{9H~LOBnGNgFE*U&ysJiW-_7duwZd-9PD?eSwi@vT(Hh8@iSB6T08MN9qY*FX zl~lgE`x=EBStWyJ60{M~)pK1VXC|#|O2kBmSTEr<;+;&fa;EOJMue+vBCdBOsY_`| zs>fts?|n8h0BGjD>%FT+D!JKH9@N6KGDDPBp3Q2^RW_U0n>C=&TLo>UNVVbpR`L|D)O`@U-WqCKw1MNauB)diX#;(RlE{qu z1hd}%q)GKhSLk`IwsLFOnP`=_TXmLQtv*@zy!DcAy`5e?4p#*AIej&2FrhVKrK?ak ztF1;?ThXp%Q}X3%=BAffInBf_8+kcvozHB74YNd~wp5)}ukf`2X@7TTDe z<>Zn;NxqGemzFtKZ67O2w;t8qtj<--LY7KtPC|xtz*7VXWYOQ%~WWqL@53R?XTu>!~TouOc%{WN0$1cUd38nj(%K+Z5w$ZAV7Qj2ZfOupiJ>Y7^YI~wgn*J4`L z_q#Q-5QO|8cEvGh;vsxid}EJo+)W1)mk%-Tdi}grI+{p=oP)%17ms#uWxm* zV$?3QR!O1;gHo$jEVE&V%_b1K0`}QWS{5L3@@+;VF_V=_FAEiE!u1+CMlZH;C7q~@%!{;%bweAd!+O@{UF}qt?-vu= zrBIk=*P~sja;&6hyI$H(v#UsHY#%o;xuZFr_ZGy9s2*D=Z%SXL7(lMLOX|2`?T3r&;%<`H>4w%$L z{XvJ6*Q#Qst5CL;yvC)pF07*qo IM6N<$g0VVZ1poj5 literal 0 HcmV?d00001 diff --git a/src/main/resources/static/assets/mobile/svg/memberPay/zfb.svg b/src/main/resources/static/assets/mobile/svg/memberPay/zfb.svg new file mode 100644 index 00000000..48cd7697 --- /dev/null +++ b/src/main/resources/static/assets/mobile/svg/memberPay/zfb.svg @@ -0,0 +1 @@ + diff --git a/src/main/resources/static/assets/platform/js/tool/businessTool.js b/src/main/resources/static/assets/platform/js/tool/businessTool.js index 84fab627..d949c332 100644 --- a/src/main/resources/static/assets/platform/js/tool/businessTool.js +++ b/src/main/resources/static/assets/platform/js/tool/businessTool.js @@ -81,5 +81,17 @@ const businessTool = { return "" } }) + }, + getEnumOptions(name = null) { + return commonUtil + .axiosService() + .post("/open/common/dictEnumOptions", {name}) + .then((resp) => { + if (resp.code === 0) { + return resp.data + } else { + return [] + } + }) } } diff --git a/src/main/resources/static/assets/platform/module/mall/addGoods.css b/src/main/resources/static/assets/platform/module/mall/addGoods.css new file mode 100644 index 00000000..555c309a --- /dev/null +++ b/src/main/resources/static/assets/platform/module/mall/addGoods.css @@ -0,0 +1,530 @@ +/*选择商品品类*/ +.content-goods-publish { + padding: 15px; + margin: 0 auto; + text-align: center; + border-radius: 0.8em; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); + background: none repeat 0 0 #fff; + + /*商品品类*/ + .goods-category { + min-height: 500px; + border-radius: 0.8em; + text-align: left; + padding: 10px; + background: #ededed; + + ul { + padding: 12px 8px; + list-style: none; + width: 300px; + background: none repeat 0 0 #fff; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); + border-radius: 0.4em; + display: inline-block; + letter-spacing: normal; + margin-right: 15px; + vertical-align: top; + word-spacing: normal; + + li { + line-height: 20px; + padding: 10px 5px; + cursor: pointer; + color: #333; + font-size: 12px; + display: flex; + flex-wrap: nowrap; + flex-direction: row; + justify-content: space-between; + align-items: center; + } + } + } + + /** 当前品类被选中的样式 */ + .activeClass { + border-radius: 0.4em; + background-color: color-mix(in srgb, var(--color-primary) 20%, transparent); + border: 1px solid color-mix(in srgb, var(--color-primary) 80%, transparent); + /*background-color: rgba(33, 112, 80, 0.2);*/ + /*border: 1px solid rgba(33, 112, 80, 0.8);*/ + color: #fff; + } + + /*!*当前选择的商品品类文字*!*/ + .current-goods-category { + text-align: left; + padding: 10px; + width: 100%; + border: 1px solid #fbeed5; + color: #c09853; + background-color: #fcf8e3; + margin: 10px auto; + padding: 8px 35px 8px 14px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + font-size: 12px; + font-weight: bold; + } +} + +/*编辑基本信息*/ +.el-form { + padding-bottom: 80px; + + .el-form-item { + width: 100%; + text-align: left; + } +} + +.sku-val { + justify-content: flex-start; + flex-wrap: wrap; + + >.ivu-form { + flex-wrap: wrap !important; + } + + /deep/ .sku-item-content-val { + margin-right: 20px; + } +} + +div.base-info-item { + h4 { + margin-bottom: 10px; + padding: 0 10px; + border: 1px solid #ddd; + background-color: #f8f8f8; + font-weight: bold; + color: #333; + font-size: 14px; + line-height: 40px; + text-align: left; + } + + >div { + padding-left: 5%; + } + + .form-item-view { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: space-between; + // padding-left: 80px; + + .form-item-view-wholesale { + display: flex; + + .form-item-view-wholesale-preview { + padding-left: 5%; + } + + } + + .layout { + margin-bottom: 20px; + width: 100%; + justify-content: center; + + .sku-item-content { + margin: 20px 0; + display: flex; + width: 100% !important; + flex: 1; + + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + width: 100%; + + >.ivu-card-body { + width: 100%; + } + + .ivu-card-body { + width: 100%; + justify-content: center; + align-items: flex-start; + } + + .sku-item-content-name { + display: flex; + align-items: flex-start; + justify-content: flex-start; + width: 100%; + } + } + } + + .shop-category-text { + font-size: 12px; + } + } + + .form-item-view-bottom { + margin-bottom: 50px; + } + + .item-goods-properts-row { + display: flex; + flex-direction: row; + word-break: break-all; + white-space: normal; + width: 300px; + height: 100px; + } + + .item-goods-properts { + display: flex; + flex-direction: row; + margin-bottom: 10px; + } + + .form-item { + display: flex; + align-items: center; + } + + /** 审核信息-拒绝原因 */ + .auth-info { + color: red; + } + + .el-form-item { + width: 30%; + min-width: 300px; + } + + .goods-name-width { + width: 50%; + min-width: 300px; + } + + .el-form-item__content { + margin-left: 120px; + text-align: left; + } + + p.goods-group-manager { + padding-left: 7.5%; + text-align: left; + color: #999; + font-size: 13px; + } + + /*teatarea*/ + /deep/ .el-textarea { + width: 150%; + } + + .seo-text { + width: 150%; + } +} + +/*折叠面板*/ +.el-collapse-item { + /deep/ .el-collapse-item__header { + text-align: left; + background-color: #f8f8f8; + padding: 0 10px; + font-weight: bold; + color: #333; + font-size: 14px; + } + + .el-form-item { + margin-left: 5%; + width: 25%; + } + + /deep/ .el-form-item__content { + margin-left: 120px; + text-align: left; + } + + p.goods-group-manager { + padding-left: 12%; + text-align: left; + color: #999; + } + + /deep/ .el-collapse-item__content { + padding: 10px 0; + text-align: left; + } +} + +.success { + >h1 { + font-size: 28px; + } + + >* { + margin: 10px; + } +} + +.operation { + >* { + margin: 10px 0; + } +} + +/*商品描述*/ +.goods-intro { + line-height: 40; +} + +/** 底部步骤 */ +.footer { + width: 100%; + margin-top: 20px; + padding: 10px; + background-color: #ffc; + position: sticky; + bottom: 0px; + text-align: center; + z-index: 999; + + >.ivu-btn { + margin: 0 10px; + } +} + +/*图片上传组件第一张图设置封面*/ +.goods-images { + /deep/ li.el-upload-list__item:first-child { + position: relative; + } + + /deep/ li.el-upload-list__item:first-child:after { + content: "封"; + color: #fff; + font-weight: bold; + font-size: 12px; + position: absolute; + left: -15px; + top: -6px; + width: 40px; + height: 24px; + padding-top: 6px; + background: #13ce66; + text-align: center; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + -webkit-box-shadow: 0 0 1pc 1px rgba(0, 0, 0, 0.2); + box-shadow: 0 0 1pc 1px rgba(0, 0, 0, 0.2); + } +} + +.el-form-item__label { + word-break: break-all; +} + +.step-list { + height: 60px; + padding: 10px 30px; + background-color: #fff; + margin-bottom: 20px; + border-radius: 0.8em; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); +} + +.add-sku-btn { + margin-top: 10px; +} + +.sku-item:not(:first-child) { + margin-top: 10px; +} + +.sku-upload-list { + text-align: center; + border: 1px solid transparent; + border-radius: 4px; + overflow: hidden; + background: #fff; + position: relative; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); + margin-right: 8px; +} + +.preview-picture { + width: 100%; + margin: 0 auto; + display: block; + // text-align: center; + border: 1px solid transparent; + // justify-self: center; + // align-self: center; +} + +.preview-picture img { + width: 100%; + height: 100%; +} + +.sku-upload-list img { + width: 100%; + height: 100%; +} + +.sku-upload-list-cover { + display: none; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + background: rgba(0, 0, 0, 0.6); +} + +.sku-upload-list:hover .sku-upload-list-cover { + display: block; +} + +.sku-upload-list-cover i { + color: #fff; + font-size: 20px; + cursor: pointer; + margin: 0 2px; +} + +.required { + /deep/ .ivu-form-item-label::before { + content: "*"; + display: inline-block; + margin-right: 4px; + line-height: 1; + font-family: SimSun; + font-size: 14px; + color: #ed4014; + } +} + +.demo-upload-list { + width: 150px; + height: 150px; + text-align: center; + border: 1px solid transparent; + border-radius: 4px; + display: inline-block; + background: #fff; + position: relative; + margin-right: 4px; + vertical-align: bottom; +} + +.demo-upload-list img { + width: 100%; + height: 100%; +} + +.demo-upload-list-cover { + display: none; + position: absolute; + top: 0; + bottom: 0; + left: 0; + + right: 0; + background: rgba(0, 0, 0, 0.6); + + justify-content: space-between; + align-items: center; + flex-direction: column; +} + +.demo-upload-list:hover .demo-upload-list-cover { + display: flex; +} + +.demo-upload-list-cover div { + margin-top: 50px; + width: 100%; + + >i { + width: 50%; + margin-top: 8px; + color: #fff; + font-size: 20px; + cursor: pointer; + } +} + +.active-goods-type { + background: #e8e8e8; +} + +.goods-type-list { + max-height: 500px; + overflow-y: auto; +} + +.template-item { + justify-content: flex-start !important; +} + +.tree-bar { + height: auto !important; + max-height: auto !important; + min-height: 240px !important; +} + +.goods-type-item { + padding: 20px 0; + width: 100%; + cursor: pointer; + transition: 0.35s; + display: flex; + justify-content: center; + align-items: center; + + /deep/ img { + margin-right: 20px; + width: 100px; + margin-left: 10px; + } + + + + /deep/ p { + color: #999; + font-size: 14px; + margin-top: 10px; + } +} + +.goods-type-item:hover { + background: #ededed; +} + +.goods-list-box { + height: 450px; + overflow: auto; +} + +h2 { + cursor: pointer; + font-size: 21px; + color: #333; +} + +.form-item-view-wholesale-form-col { + height: 400px; +} + +.form-item-view-wholesale-row-del { + display: "flex"; + justify-content: "space-between"; + align-items: "center"; +} +.promise-intro-btn{ + margin: 10px 0; + text-align: left; +} diff --git a/src/main/resources/views/platform/zhgh/activity/fitnesswalk/activityManage.html b/src/main/resources/views/platform/zhgh/activity/fitnesswalk/activityManage.html new file mode 100644 index 00000000..e56f0eec --- /dev/null +++ b/src/main/resources/views/platform/zhgh/activity/fitnesswalk/activityManage.html @@ -0,0 +1,1916 @@ + + + +

+ + + + + + + +
+ +
+
+ + + 确 定 + +
+ + + + + + + + + + + + + + {{viewData.name}} + + + + + {{viewData.address}} + + + + + + + + + {{moment(viewData.apply_start_time).format('YYYY-MM-DD HH:mm:ss')}} + + + + + {{moment(viewData.apply_end_time).format('YYYY-MM-DD HH:mm:ss')}} + + + + + + + + {{moment(viewData.start_time).format('YYYY-MM-DD HH:mm:ss')}} + + + + + {{moment(viewData.end_time).format('YYYY-MM-DD HH:mm:ss')}} + + + + + + + 打卡模式 + 计步模式 + GPS模式 + + + + + {{viewData.dailyLottery?viewData.dailyLottery:'暂无'}} + + + + + {{viewData.walkingStepCount?viewData.walkingStepCount:'暂无'}} + + + + + + + +
暂无
+
+
+
+
+ + + + + + + + + + + + + + +
+
+ + +
+
+ +
+ + + 关 闭 + +
+ + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/activity/fitnesswalk/bindingRecord.html b/src/main/resources/views/platform/zhgh/activity/fitnesswalk/bindingRecord.html new file mode 100644 index 00000000..700b3079 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/activity/fitnesswalk/bindingRecord.html @@ -0,0 +1,266 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + 批量删除  + + + + + 删除已选 + + + 全部删除 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/activity/fitnesswalk/punchStatistics.html b/src/main/resources/views/platform/zhgh/activity/fitnesswalk/punchStatistics.html new file mode 100644 index 00000000..30519a81 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/activity/fitnesswalk/punchStatistics.html @@ -0,0 +1,264 @@ + +
+ + + + + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepRaffle.html b/src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepRaffle.html new file mode 100644 index 00000000..f7ac7d3a --- /dev/null +++ b/src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepRaffle.html @@ -0,0 +1,383 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + 设置抽奖条件 + 查看中奖人员 + 导出达标人员 + + + + + + + + + + + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepRanking.html b/src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepRanking.html new file mode 100644 index 00000000..283c606c --- /dev/null +++ b/src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepRanking.html @@ -0,0 +1,177 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + 今日排行榜 + 总排行榜 + + 导出{{pageForm.mode == 'today' ? '今日排行榜' : '总排行榜'}} + + + + + + + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepStatistics.html b/src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepStatistics.html new file mode 100644 index 00000000..c0e42f11 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepStatistics.html @@ -0,0 +1,202 @@ + +
+ + + + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepWining.html b/src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepWining.html new file mode 100644 index 00000000..52b085d9 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/activity/fitnesswalk/stepWining.html @@ -0,0 +1,187 @@ + + +
+ + + + + + + + + + + + + + + + + + 奖项名称: + + + + {{ item.name }} + + + + + + + + + 导出中奖名单 + + + + + + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/data/revel.html b/src/main/resources/views/platform/zhgh/dayofficework/workershome/data/revel.html new file mode 100644 index 00000000..76d8018f --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/data/revel.html @@ -0,0 +1,460 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 取 消 + 确 定 + + + + + + + + + + + + + + + + + + + + + + + + + + 取 消 + 确 定 + + + + + + + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+ + 关 闭 + +
+ +
+ + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/data/type.html b/src/main/resources/views/platform/zhgh/dayofficework/workershome/data/type.html new file mode 100644 index 00000000..87391201 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/data/type.html @@ -0,0 +1,207 @@ + + +
+ + + + + + + + + + + + 新增工作资料类型 + + + + + + + + + + + + + + + + + + + + + + + + 取 消 + 确 定 + + + + + + + + + + + + + + 取 消 + 确 定 + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/apply.html b/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/apply.html new file mode 100644 index 00000000..c801f61d --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/apply.html @@ -0,0 +1,222 @@ + + +
+ + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/components/info.js b/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/components/info.js new file mode 100644 index 00000000..a6349b9b --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/components/info.js @@ -0,0 +1,66 @@ +const INFO = { + template: /*language=HTML*/ ` +
+ + + + {{ viewData.username }} + {{ viewData.loginName }} + {{ viewData.mobile }} + + {{ viewData.unionName }} + {{ viewData.applyTime }} + + +
+ 暂无 +
+ + +
+ 暂无 +
+ + + + 暂无 + +
+
+ + + + + +
+
+ `, + props: { + activeName: { + type: String, + default: '1' + } + }, + data() { + return { + activeName: '1', + viewData: {}, + organizationAudit: {}, + schoolAudit: {}, + } + }, + methods: { + async openView(id) { + const resp = await $.get('/platform/workershome/declaration/apply/getInfoById', {id: id}) + if (resp.code === 0) { + this.viewData = resp.data + this.organizationAudit = resp.data.organizationAudit + this.schoolAudit = resp.data.schoolAudit + } else { + this.viewData = {} + this.organizationAudit = {} + this.schoolAudit = {} + } + } + } +} diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/mine.html b/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/mine.html new file mode 100644 index 00000000..747a6862 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/mine.html @@ -0,0 +1,175 @@ + + +
+ + + + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/organizationAudit.html b/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/organizationAudit.html new file mode 100644 index 00000000..91f5b672 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/organizationAudit.html @@ -0,0 +1,230 @@ + + +
+ + + + + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/schoolAudit.html b/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/schoolAudit.html new file mode 100644 index 00000000..22009bb6 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/schoolAudit.html @@ -0,0 +1,286 @@ + + +
+ + + + + + + + + + + 关 闭 + 确 定 + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/statistics.html b/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/statistics.html new file mode 100644 index 00000000..14d010ae --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/declaration/statistics.html @@ -0,0 +1,177 @@ + +
+ + + + + + + + + 关 闭 + 确 定 + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/info/apply.html b/src/main/resources/views/platform/zhgh/dayofficework/workershome/info/apply.html new file mode 100644 index 00000000..70eb9070 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/info/apply.html @@ -0,0 +1,347 @@ + + + + +
+ + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/info/info.html b/src/main/resources/views/platform/zhgh/dayofficework/workershome/info/info.html new file mode 100644 index 00000000..5dbda59f --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/info/info.html @@ -0,0 +1,223 @@ + + + + +
+ + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/info/mine.html b/src/main/resources/views/platform/zhgh/dayofficework/workershome/info/mine.html new file mode 100644 index 00000000..246a06d1 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/info/mine.html @@ -0,0 +1,162 @@ + + +
+ + + + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/info/schoolAudit.html b/src/main/resources/views/platform/zhgh/dayofficework/workershome/info/schoolAudit.html new file mode 100644 index 00000000..8120ab21 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/info/schoolAudit.html @@ -0,0 +1,229 @@ + + +
+ + + + + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/components/addReviewProxy.js b/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/components/addReviewProxy.js new file mode 100644 index 00000000..5fb1eeff --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/components/addReviewProxy.js @@ -0,0 +1,385 @@ +const ADD_REVIEW_PROXY = { + template: /*language=HTML*/ ` +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 工会评议 + 主席/副主席评议 + + + + + + + + 自我评议 + + + 教工评议 + + + + + + + + 评分模式 + 满意度模式 + + + + + + + + + + + 校工会 + + + 全部分工会 + + + + 自选分工会 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 添加测评内容 + + + +
+ +
+ +
+
+ `, + props: { + is_view: {type: Boolean, default: false}, + data: { + type: Object, + default: { + nrs: [{ + bzs: [{}] + }], + unionIds: [] + } + } + }, + data() { + return { + activityGroupList: [], + isEvaluationIndex: false, + zbList: [], + formRules: { + xxx: [{required: true, message: '请填写年度', trigger: ['blur', 'change']}], + }, + pickerOptions: { + disabledDate(time) { + return ( + time.getFullYear() > new Date().getFullYear() + ); + } + }, + relationData: [ + {moduleName: '提案系统模块', id: 'proposal'}, + {moduleName: '二级教代会', id: 'secteameet'}, + {moduleName: '慰问/补助', id: 'ConandDif'}, + ], + roleDataReview: {}, + reviewUnions: [], + } + }, + components: { + 'drawer-user-scope': httpVueLoader('/components/module/activity/DrawerUserScope.vue'), + }, + methods: { + async getActivityGroup() { + const {data} = await this.$axios.get('/platform/activity/basic/scope/getActivityUserScopeGroup') + this.activityGroupList = data + }, + async getByZbData() { + const { + code, + data, + msg + } = await this.$axios.get('/platform/wakeshome/review/viewZb/edit', {id: this.data.zbId}) + if (data) { + this.$set(this.data, "nrs", data.nrs) + } else { + this.$set(this.data, "nrs", [{bzs: [{}]}]) + } + }, + async getZbList() { + const res = await this.$axios.get("/platform/wakeshome/review/Xjkhzb/getZbList") + this.zbList = res.data + }, + getSummaries(param) { + const {columns, data} = param; + const sums = []; + columns.forEach((column, index) => { + if (index === 0 && this.data.scoringMode === 1) { + sums[index] = '小计'; + return; + } else if ([1, 3, 4].includes(index) && this.data.scoringMode === 1) { + sums[index] = ''; + return; + } else if ([1, 2, 3].includes(index) && this.data.scoringMode === 2) { + sums[index] = ''; + return; + } + const values = data.map(item => Number(item[column.property])); + if (!values.every(value => isNaN(value))) { + sums[index] = values.reduce((prev, curr) => { + const value = Number(curr); + if (!isNaN(value)) { + return prev + curr; + } else { + return prev; + } + }, 0); + sums[index] += ' 分'; + } else { + sums[index] = ''; + } + }); + return sums; + }, + }, + async created() { + await this.getActivityGroup() + await this.getZbList() + if (!this.data || !Object.keys(this.data).length) { + this.data = { + nrs: [{ + bzs: [{inspection: null, score: null, isEvidence: true}] + }], + } + } + + if (this.$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN')) { + this.reviewUnions = await this.$businessTool.listUnion() + } else { + this.reviewUnions = await this.$businessTool.listUnion(this.unionId) + this.$set(this.data, "unionIds", this.reviewUnions[0].id) + } + }, + watch: { + data: { + deep: true, + handler(val) { + this.$emit('change', val) + } + } + }, + computed: { + schoolContent() { + if (this.data.reviewMode == 1) { + return '勾选后,仅校工会管理员可参加测评' + } else if (this.data.reviewMode == 2) { + return '勾选后,全校所有人员可评议校工会,也可根据右侧选框【可评议人员】指定评议人员范围' + } else { + return '请选择评议模式' + } + }, + allUnionContent() { + if (this.data.reviewMode == 1) { + return '勾选后,仅各工会管理员可对本分工会进行自我评议' + } else if (this.data.reviewMode == 2) { + return '勾选后,所有分工会人员对本分工会进行评议,不可跨工会评议' + } else { + return '请选择评议模式' + } + }, + selectUnionContent() { + if (this.data.reviewMode == 1) { + return '勾选后,仅右侧选择的分工会管理员可对本分工会进行自我评议' + } else if (this.data.reviewMode == 2) { + return '勾选后,可根据右侧选框【自选分工会】指定分工会评议范围' + } else { + return '请选择评议模式' + } + } + } +} diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/components/reviewResult.js b/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/components/reviewResult.js new file mode 100644 index 00000000..1cafeb0a --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/components/reviewResult.js @@ -0,0 +1,113 @@ +const REVIEW_RESULT = { + template: /*language=HTML*/ ` +
+ + + + + + + + + + + + + + + + + + + + + + +
+ 简述工作情况 + + + + + +
+
+ + + + + +
+
+ `, + props: { + id: {type: String, default: ''} + }, + data() { + return { + viewInfo: { + commentPeo: {}, + zbxx: [] + } + } + }, + methods:{ + async findOne(peoId){ + const resp = await this.$axios.get('/platform/wakeshome/review/statistics/getBzById',{peoId:peoId}) + if (resp.code === 0) { + this.viewInfo = resp.data + } + } + } +} diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/doReview.html b/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/doReview.html new file mode 100644 index 00000000..dfeece78 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/doReview.html @@ -0,0 +1,444 @@ + + +
+ + + + + + + + + + + + + + +
+ + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/khzb.html b/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/khzb.html new file mode 100644 index 00000000..8f3ae51d --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/khzb.html @@ -0,0 +1,211 @@ + + +
+ + + + + + + + +
+ + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/statistics.html b/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/statistics.html new file mode 100644 index 00000000..41762ff3 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/statistics.html @@ -0,0 +1,421 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 取 消 + 确 定 + + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/xjkhzb.html b/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/xjkhzb.html new file mode 100644 index 00000000..667cfaaf --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workershome/review/xjkhzb.html @@ -0,0 +1,137 @@ + + +
+ + + + + + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/apply/form.html b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/apply/form.html new file mode 100644 index 00000000..686fad2e --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/apply/form.html @@ -0,0 +1,541 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/apply/index.html b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/apply/index.html new file mode 100644 index 00000000..24d601b7 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/apply/index.html @@ -0,0 +1,177 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + 帮扶申请 + + + + + + + + + + + + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/branchunionapproval/form.html b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/branchunionapproval/form.html new file mode 100644 index 00000000..0feb2031 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/branchunionapproval/form.html @@ -0,0 +1,45 @@ +
+ + + + + + +
+ + diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/branchunionapproval/index.html b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/branchunionapproval/index.html new file mode 100644 index 00000000..6651bfbd --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/branchunionapproval/index.html @@ -0,0 +1,141 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + 已审核 + 未审核 + + + + + + + + + + + + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/schoolunionapproval/form.html b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/schoolunionapproval/form.html new file mode 100644 index 00000000..e0049de8 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/schoolunionapproval/form.html @@ -0,0 +1,49 @@ +
+ + + + + + + + + +
+ + diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/schoolunionapproval/index.html b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/schoolunionapproval/index.html new file mode 100644 index 00000000..6651bfbd --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/schoolunionapproval/index.html @@ -0,0 +1,141 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + 已审核 + 未审核 + + + + + + + + + + + + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/view/index.html b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/view/index.html new file mode 100644 index 00000000..b6cedfc3 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/view/index.html @@ -0,0 +1,126 @@ +
+ + {{ viewData.proxyUserName }} + {{ viewData.proxyLoginName }} + {{ viewData.mode == 1 ? '本人申请' : '替他人申请' }} + + {{ viewData.userName + '(' + viewData.loginName + ')' }} + {{ viewData.sex }} + {{ viewData.birthday }} + + {{ viewData.unionName }} + {{ viewData.unitName }} + {{ viewData.officialCapacity }} + + {{ viewData.mobile }} + {{ viewData.idCard }} + + {{ viewData.monthlyIncome }} + {{ viewData.bankCardNum }} + + {{ viewData.subsidyStandards }} + + {{ viewData.reason }} + + + + + + + + + + + + + + 暂无 + + + + + 暂无 + + + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/apply/branchunionapproval/form.html b/src/main/resources/views/platform/zhgh/staffmanage/member/apply/branchunionapproval/form.html new file mode 100644 index 00000000..d08e1ab0 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/member/apply/branchunionapproval/form.html @@ -0,0 +1,45 @@ +
+ + + + + + +
+ + diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/apply/branchunionapproval/index.html b/src/main/resources/views/platform/zhgh/staffmanage/member/apply/branchunionapproval/index.html new file mode 100644 index 00000000..f0c0e5c4 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/member/apply/branchunionapproval/index.html @@ -0,0 +1,126 @@ + +
+ + + + + + + 已审核 + 未审核 + + + + + + + + + + + + + + + +
+ + diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/apply/branchunionaudit/index.html b/src/main/resources/views/platform/zhgh/staffmanage/member/apply/branchunionaudit/index.html deleted file mode 100644 index 6b24647c..00000000 --- a/src/main/resources/views/platform/zhgh/staffmanage/member/apply/branchunionaudit/index.html +++ /dev/null @@ -1,233 +0,0 @@ - -
- - - - - -
- - diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/apply/common/commonQuery.js b/src/main/resources/views/platform/zhgh/staffmanage/member/apply/common/commonQuery.js new file mode 100644 index 00000000..e34ef3d6 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/member/apply/common/commonQuery.js @@ -0,0 +1,85 @@ +const COMMON_QUERY = { + template: /*language=HTML*/ ` + + + + + + + `, + store, + mixins: [initTableMixins], + data() { + return{ + unions: [], + units: [], + pageForm: { + searchKeyword: '', + unionId: '', + unitId: '', + userState: '', + personType: '' + } + } + }, + methods: { + doSearch(){ + this.$emit('search', this.pageForm) + }, + async initData(){ + if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) { + this.$businessTool.listUnion(this.pageForm.unionId).then((data) => { + this.unions = data + }) + this.$businessTool.listUnit().then((data) => { + this.units = data + }) + } else if (this.$auth.hasRole("BRANCH_UNION_CHAIRMAN")) { + this.$businessTool.listUnion(this.$store.state.user.union.id).then((data) => { + this.unions = data + }) + this.$businessTool.listUnit(this.$store.state.user.union.id).then((data) => { + this.units = data + }) + } + }, + async flushUnits(){ + this.$set(this.pageForm, "unitId", null) + this.units = [] + if (this.pageForm.unionId) { + this.units = await this.$businessTool.listUnit(this.pageForm.unionId) + } + } + }, + async created() { + this.initData() + } +} diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/apply/common/memberApplyAuditInfo.js b/src/main/resources/views/platform/zhgh/staffmanage/member/apply/common/memberApplyAuditInfo.js new file mode 100644 index 00000000..62b3f165 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/member/apply/common/memberApplyAuditInfo.js @@ -0,0 +1,127 @@ +const MEMBER_APPLY_AUDIT_INFO = { + template: /*language=HTML*/ ` +
+ + + + {{ viewData.loginname }} + {{ viewData.username }} + {{ viewData.sex }} + + {{ viewData.nation }} + {{ moment(viewData.birthday).format("YYYY年MM月DD日") }} + {{ viewData.political }} + + {{ viewData.education }} + {{ viewData.academicDegree }} + {{ viewData.position }} + + {{ viewData.userUnitName }} + {{ viewData.userUnionName }} + {{ viewData.campus }} + + {{ viewData.idCard }} + {{ viewData.mobile }} + {{ viewData.email }} + + {{ viewData.userState }} + {{ viewData.personType }} + + + + + + + + + + + + + + + + +
+ 暂无 +
+ + + + 暂无 + +
+
+ + +
+
+
+ {{nodeTask.nodeName}} +
+ + + {{ task.actualOwnerLoginName + '-' + task.actualOwnerUserName}} + + {{ task.endOn}} + +
+ 同意 + + 退回 + + 拒绝 + +
+
+ + {{ task.extVariable.approvalOpinion }} + + + + + +
+
+
+
+
+
+ `, + data() { + return{ + activeName: "basicInfo", + viewData: { + nodeTasks: {} + } + } + }, + methods: { + async onOpen(id){ + const resp = await $.post('/platform/member/apply/mine/findMemberApplyRecord', {id}) + if (resp.code === 0) { + this.viewData = resp.data + this.$emit('union-name', this.viewData.userUnionName) + if (this.viewData.families) { + this.viewData.families = JSON.parse(this.viewData.families) + } else { + this.viewData.families = [] + } + } + } + } +} diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/apply/mine/index.html b/src/main/resources/views/platform/zhgh/staffmanage/member/apply/mine/index.html index a0e37c18..f4e44107 100644 --- a/src/main/resources/views/platform/zhgh/staffmanage/member/apply/mine/index.html +++ b/src/main/resources/views/platform/zhgh/staffmanage/member/apply/mine/index.html @@ -5,40 +5,7 @@ layout("/layouts/platform.html"){ - - + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/change/submit/form.html b/src/main/resources/views/platform/zhgh/staffmanage/member/change/submit/form.html new file mode 100644 index 00000000..d3ae80ae --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/member/change/submit/form.html @@ -0,0 +1,532 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 会员 + 非会员 + + + + + + + + 福利会员 + 非福利会员 + + + + + + + + + + + +
+ + diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/change/submit/index.html b/src/main/resources/views/platform/zhgh/staffmanage/member/change/submit/index.html new file mode 100644 index 00000000..652576ea --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/member/change/submit/index.html @@ -0,0 +1,155 @@ + +
+ + + + + +
+ + diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/change/submit/oldindex.html b/src/main/resources/views/platform/zhgh/staffmanage/member/change/submit/oldindex.html new file mode 100644 index 00000000..cb250d17 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/member/change/submit/oldindex.html @@ -0,0 +1,60 @@ + +
+ +
+ + diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/change/view/index.html b/src/main/resources/views/platform/zhgh/staffmanage/member/change/view/index.html new file mode 100644 index 00000000..983e32bb --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/member/change/view/index.html @@ -0,0 +1,165 @@ +
+ + + + {{ viewData.loginname }} + {{ viewData.username }} + {{ viewData.sex }} + + {{ viewData.nation }} + {{ viewData.birthday ? $moment(viewData.birthday).format("YYYY年MM月DD日") : '暂无' }} + {{ viewData.political }} + + {{ viewData.education }} + {{ viewData.academicDegree }} + {{ viewData.position }} + + {{ viewData.unitname }} + {{ viewData.unionname }} + {{ viewData.campus }} + + {{ viewData.idCard }} + {{ viewData.mobile }} + {{ viewData.email }} + + {{ viewData.userState }} + {{ viewData.personType }} + {{ viewData.schoolTime }} + + + + {{ viewData.member ? '会员' : '非会员' }} + {{ viewData.welfareMember ? '福利会员' : '非福利会员' }} + + + + + + + + + + + + + + + + + +
+ 无数据 +
+
+
+ + + + + + + + + + + + +
+ + + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/common/apply/memberApply.js b/src/main/resources/views/platform/zhgh/staffmanage/member/common/apply/memberApply.js deleted file mode 100644 index fe4def2f..00000000 --- a/src/main/resources/views/platform/zhgh/staffmanage/member/common/apply/memberApply.js +++ /dev/null @@ -1,252 +0,0 @@ -const MEMBER_APPLY = { - template: ` - - -

入会申请

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- `, - props: { - adminOperate: { type: Boolean, default: false }, - id: { type: String }, - url: { type: String, default: "/platform/member/apply/submit/doSubmit" } - }, - data() { - return { - formDisabled: false, - formData: { - families: [] - }, - formRules: { - userId: [{ required: true, message: "必填", trigger: "change" }], - userName: [{ required: true, message: "必填", trigger: "change" }], - sex: [{ required: true, message: "必填", trigger: "change" }], - idCard: [ - { required: true, message: "身份证号不能为空", trigger: "blur" }, - { - pattern: /(^\d{6}(18|19|20)\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}([0-9xX])$)/, - message: "身份证号格式不正确", - trigger: "blur" - } - ], - nation: [{ required: true, message: "必填", trigger: "change" }], - political: [{ required: true, message: "必填", trigger: "change" }], - education: [{ required: true, message: "必填", trigger: "change" }], - // unitName: [{ required: true, message: "必填", trigger: "change" }], - governmentPosition: [{ required: true, message: "必填", trigger: "change" }], - mobile: [ - { required: true, message: "手机号不能为空", trigger: "blur" }, - { pattern: /^1[3-9]\d{9}$/, message: "手机号格式不正确", trigger: "blur" } - ], - email: [{ required: true, message: "必填", trigger: "change" }], - wantJoinLoveMutualAidAssociation: [{ required: true, message: "必填", trigger: "change" }], - personalData: [{ required: true, message: "必填", trigger: "change" }] - }, - units: [], - isAdmin: false - // id: GetQueryString("id"), - // TASK_ID: parseInt(GetQueryString("TASK_ID")) - } - }, - methods: { - getUnionName() { - const data = this.units.find((v) => v.id === unitId) - this.$set(this.formData, "unionName", data.unionName) - }, - init() { - if (this.id) { - this.findOne(this.id) - } else { - this.assignmentFormData() - } - this.$businessTool.listUnit().then((data) => { - debugger - this.units = data - }) - this.isAdmin = this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN", "BRANCH_UNION_CHAIRMAN"]) - }, - findOne(id) { - this.$axios.post("/platform/member/apply/submit/findOne", { id: id }).then((res) => { - if (res.code === 0) { - this.assignmentFormData(res.data) - } - }) - }, - doSubmit(sequenceFlowName) { - this.$axios - .post(this.url, { - ...this.formData, - TASK_ID: this.TASK_ID, - sequenceFlowName - }) - .then((res) => { - if (res.code === 0) { - this.$message.success(res.msg) - // location.href = "/platform/member/apply/mine" - } - }) - }, - assignmentFormData(data) { - const source = data - // 特定字段的默认值映射 - const defaultValues = { - families: [] - } - - const setField = (key) => { - // 检查字段是否在 defaultValues 映射中,如果在,则使用其默认值,否则从 source 获取值 - const value = defaultValues.hasOwnProperty(key) ? defaultValues[key] : source[key] - this.$set(this.formData, key, value) - } - // 遍历表单项并设置值 - this.$refs.formRef.fields.forEach((formItem) => { - setField(formItem.prop) - }) - this.$set(this.formData, "loginname", data.loginname) - this.$set(this.formData, "userId", data.id) - } - }, - created() { - // this.init() - } -} diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/common/audit/memberAuditChangeInfo.js b/src/main/resources/views/platform/zhgh/staffmanage/member/common/audit/memberAuditChangeInfo.js deleted file mode 100644 index fbfd8827..00000000 --- a/src/main/resources/views/platform/zhgh/staffmanage/member/common/audit/memberAuditChangeInfo.js +++ /dev/null @@ -1,158 +0,0 @@ -const MEMBER_AUDIT_CHANGE_INFO = { - template: - /*language=HTML*/ - ` - - - - -
-
- 当前信息 -
- - {{ viewData.username }} - {{ viewData.sex }} - {{ viewData.nation }} - {{ viewData.userState }} - - {{ viewData.personType }} - {{ viewData.education }} - {{ viewData.political }} - {{ viewData.marriage || '' }} - {{ viewData.idCard }} - {{ viewData.mobile }} - {{ viewData.email }} - {{ viewData.member ? '是' : '否' }} - {{ viewData.welfareMember ? '是' : '否' }} - - - - -
- {{ viewData.unionName + '-' + viewData.unitName + ( viewData.governmentPosition ? ( '(' - + viewData.governmentPosition + ')' ) : '' ) }} -
-
-
-
- -
-
- {{ '变更记录' + (remark ? ('(变更/审核说明:' + remark + ')') : '') }} -
- - - - - - - - - - -
- -
- - -
-
-
- {{nodeTask.nodeName}} -
- - - {{ task.actualOwnerLoginName + '-' + task.actualOwnerUserName}} - - {{ task.endOn}} - -
- 同意 - - 退回 - - 拒绝 - -
-
- - {{ task.extVariable.approvalOpinion }} - - - - - -
-
-
-
-
-
- `, - props: { - is_default_url: { - type: Boolean, - default: false - } - }, - data() { - return { - activeName: "basicInfo", - changeList: [], - nodeTasks: [], - viewData: {}, - remark: "" - } - }, - methods: { - findAuditChangeInfo(recordId) { - if (!recordId) { - return - } - let url = loc() + "/findAuditChangeInfo" - if (this.is_default_url) { - url = "/platform/sourcechange/manage/findAuditChangeInfo" - } - this.$axios.post(url, { recordId: recordId }).then((res) => { - if (res.code === 0) { - this.changeList = res.data.changeList - this.nodeTasks = res.data.nodeTasks - this.remark = res.data.remark - } - }) - }, - findUserInfo(userId) { - if (!userId) { - return - } - this.$axios.post("/platform/member/apply/common/findOne", { id: userId }).then((res) => { - if (res.code === 0) { - this.viewData = res.data - } - }) - }, - onOpen(data) { - this.findAuditChangeInfo(data.recordId) - this.$nextTick(() => { - this.findUserInfo(data.userId) - }) - } - } -} diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/common/audit/memberAuditRecord.js b/src/main/resources/views/platform/zhgh/staffmanage/member/common/audit/memberAuditRecord.js deleted file mode 100644 index 05915966..00000000 --- a/src/main/resources/views/platform/zhgh/staffmanage/member/common/audit/memberAuditRecord.js +++ /dev/null @@ -1,71 +0,0 @@ -const MEMBER_AUDIT_RECORD = { - template: ` -
- - -
- `, - dicts: ["PROCESS_TASK_SUBMIT_TYPE"], - props: { - id: { - type: String, - required: true - } - }, - watch: { - id: { - handler: function (val) { - if (val) { - this.findOne() - } - }, - immediate: true - } - }, - data() { - return { - approvalRecord: [] - } - }, - methods: { - findOne() { - if (!this.id) { - return - } - this.$axios.post("/platform/wf/processCommon/approvalRecord", { businessNo: this.id }).then((res) => { - if (res.code === 0) { - this.approvalRecord = res.data - } - }) - } - } -} diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/common/audit/memberAuditTable.js b/src/main/resources/views/platform/zhgh/staffmanage/member/common/audit/memberAuditTable.js deleted file mode 100644 index 9c946316..00000000 --- a/src/main/resources/views/platform/zhgh/staffmanage/member/common/audit/memberAuditTable.js +++ /dev/null @@ -1,201 +0,0 @@ -const MEMBER_AUDIT_TABLE = { - template: ` -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 已审核 - 未审核 - - - - - - - - - - - - - - - - - - - -
- `, - mixins: [initTableMixins], - data() { - return { - pageForm: { - audit: false - }, - tableColumns: [ - { prop: "loginname", label: "工号", sortable: true }, - { prop: "username", label: "姓名", sortable: true }, - { prop: "userState", label: "在职状态", sortable: true }, - { prop: "preparedBy", label: "聘用方式", sortable: true }, - { prop: "personType", label: "人员类型", sortable: true }, - { prop: "unionName", label: "所属工会", sortable: true }, - { prop: "unitName", label: "所属单位", sortable: true }, - { prop: "processInstanceNodeName", label: "当前节点", sortable: true } - ], - unions: [], - units: [], - changeTypeData: [], - auditChangeVisible: false, - userId: "", - recordId: "" - } - }, - methods: { - // 审核 - openApproval(row) { - this.$emit("open-approval", row) - }, - // 退回 - openRevoke(taskId) { - this.$confirm("您确定要撤回吗?", "提示", { - confirmButtonText: "确定", - cancelButtonText: "取消", - type: "warning" - }).then(() => { - this.$axios.post(loc() + "/revoke", { taskId }).then((resp) => { - this.$message.success(resp.msg) - this.doSearch() - }) - }) - }, - openEdit(row) { - this.$emit("open-edit", row) - }, - openUserChangeInfo(row) { - this.$emit("open-change-view", row) - }, - getChangeTypes(changeTypes) { - if (changeTypes) { - if (!changeTypes || changeTypes.length === 0 || !this.changeTypeData || this.changeTypeData.length === 0) return null - return changeTypes - .map((v) => { - return this.changeTypeData.find((item) => item.code === v).name - }) - .join(",") - } - return null - }, - openView(userId) { - this.$emit("open-view", userId) - }, - openChangeView(row) { - this.$emit("open-change-view", row) - }, - pageData() { - this.$axios.post(loc() + "/pageData", this.pageForm).then((res) => { - if (res.code === 0) { - this.tableData = res.data.list - this.pageForm.totalCount = res.data.totalCount - } - }) - }, - initData() { - if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) { - this.$businessTool.listUnion(this.pageForm.unionId).then((data) => { - this.unions = data - }) - } else { - this.$businessTool.listUnion(this.$store.state.user.union.id).then((data) => { - this.unions = data - }) - } - this.doSearch() - }, - flushUnits() { - this.$set(this.pageForm, "unitId", null) - this.units = [] - if (this.pageForm.unionId) { - this.$businessTool.listUnit(this.pageForm.unionId).then((data) => { - this.units = data - }) - } - } - }, - async created() { - this.initData() - this.changeTypeData = await this.$businessTool.getAllDictOptions("MEMBER_CHANGE_TYPE") - } -} diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/common/change/memberChange.js b/src/main/resources/views/platform/zhgh/staffmanage/member/common/change/memberChange.js deleted file mode 100644 index 4835e518..00000000 --- a/src/main/resources/views/platform/zhgh/staffmanage/member/common/change/memberChange.js +++ /dev/null @@ -1,368 +0,0 @@ -const MEMBER_CHANGE = { - template: /*language=HTML*/ ` - -

信息变更

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {{item.name}} - - - - - - - - - - - - - - - - - - 关 闭 - 提 交 - -
- `, - props: { - id: { type: String, required: true }, - url: { type: String, required: true }, - edit: { type: Boolean, default: false }, - showClose: { type: Boolean, default: false } - }, - store, - data() { - return { - formDisabled: false, - formData: { - families: [], - changeMember: null, - changeWelfareMember: null, - changeWantJoinLoveMutualAidAssociation: null, - verificationProjectId: "" - }, - formRules: { - username: [{ required: false, message: "必填", trigger: "change" }], - sex: [{ required: false, message: "必填", trigger: "change" }], - idCard: [ - { required: false, message: "身份证号不能为空", trigger: "blur" }, - { - pattern: /(^\d{6}(18|19|20)\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}([0-9xX])$)/, - message: "身份证号格式不正确", - trigger: "blur" - } - ], - nation: [{ required: false, message: "必填", trigger: "change" }], - political: [{ required: false, message: "必填", trigger: "change" }], - education: [{ required: false, message: "必填", trigger: "change" }], - unitName: [{ required: false, message: "必填", trigger: "change" }], - governmentPosition: [{ required: false, message: "必填", trigger: "change" }], - mobile: [ - { required: true, message: "手机号不能为空", trigger: "blur" }, - { pattern: /^1[3-9]\d{9}$/, message: "手机号格式不正确", trigger: "blur" } - ], - email: [{ required: false, message: "必填", trigger: "change" }], - changeWantJoinLoveMutualAidAssociation: [{ required: false, message: "必填", trigger: "change" }], - personalData: [{ required: false, message: "必填", trigger: "change" }] - }, - allowChangeFields: [], - units: [], - changeTypeOptions: [] - } - }, - methods: { - clickDataType(e) { - e === this.formData.changeType ? (this.formData.changeType = "") : (this.formData.changeType = e) - this.doSetMemberStatus(e) - }, - doSetMemberStatus(name) { - this.$set(this.formData, "changeMember", name ? name === "RESTORE" : "") - this.$set(this.formData, "changeWelfareMember", name ? name === "RESTORE" : "") - this.$set(this.formData, "changeWantJoinLoveMutualAidAssociation", name ? name === "RESTORE" : "") - }, - init() { - if (this.id) { - this.findOne(this.id, this.edit) - } - if (!this.allowChangeFields || this.allowChangeFields.length === 0) { - this.$businessTool.getDictOptions("MEMBER_ALLOW_CHANGES_FIELD").then((data) => { - this.allowChangeFields = data.map((v) => v.code) - }) - } - if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) { - this.$businessTool.listUnit().then((data) => { - this.units = data - }) - } else { - this.$businessTool.listUnit(this.$store.state.user.union.id).then((data) => { - this.units = data - }) - } - this.$businessTool.getDictOptions("MEMBER_CHANGE_TYPE").then((data) => { - this.changeTypeOptions = data - }) - }, - assignmentFormData(data) { - const source = data - // 特定字段的默认值映射 - const defaultValues = { - families: [] - } - - const setField = (key) => { - // 检查字段是否在 defaultValues 映射中,如果在,则使用其默认值,否则从 source 获取值 - const value = defaultValues.hasOwnProperty(key) ? defaultValues[key] : source[key] - this.$set(this.formData, key, value) - } - // 遍历表单项并设置值 - this.$refs.formRef.fields.forEach((formItem) => { - setField(formItem.prop) - }) - this.$set(this.formData, "loginname", data.loginname) - this.$set(this.formData, "userId", data.id) - }, - findOne(id, isEdit) { - this.$axios.post("/platform/member/apply/submit/findOne", { id: id, isEdit: isEdit }).then((res) => { - if (res.code === 0) { - this.assignmentFormData(res.data) - } - }) - }, - allowFields(prop) { - return !this.allowChangeFields.includes(prop) - }, - getUnionName(unitId) { - const data = this.units.find((v) => v.id === unitId) - this.$set(this.formData, "unionName", data.unionName) - }, - doSubmit() { - //是否确认提交? - this.$confirm("是否确认提交?提交后将进入审核流程,请仔细核对变更数据是否准确!", "提示", { - confirmButtonText: "确定", - cancelButtonText: "取消", - type: "warning" - }).then(() => { - this.setSubmitUserMemberStatus() - if (this.edit) { - this.formData.edit = this.edit - this.formData.id = this.id - } - this.$axios - .post(this.url, { - record: JSON.stringify(this.formData), - approvalRemark: this.formData.approvalRemark - }) - .then((res) => { - if (res.code === 0) { - this.$message.success(res.msg) - this.$emit("submit-ready", null) - } - }) - }) - }, - setSubmitUserMemberStatus() { - if (this.formData.changeType) { - this.formData.member = this.formData.changeMember - this.formData.welfareMember = this.formData.changeWelfareMember - } - }, - verificationInit(data) { - this.allowChangeFields = data.renewFields - this.$set(this.formData, "changeOrigin", data.changeOrigin) - this.$set(this.formData, "verificationProjectId", data.verificationProjectId) - this.init() - } - }, - created() {} -} diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/common/change/memberChangeInfo.js b/src/main/resources/views/platform/zhgh/staffmanage/member/common/change/memberChangeInfo.js deleted file mode 100644 index 623b198a..00000000 --- a/src/main/resources/views/platform/zhgh/staffmanage/member/common/change/memberChangeInfo.js +++ /dev/null @@ -1,108 +0,0 @@ -const MEMBER_CHANGE_INFO = { - template: /*language=html*/ ` - -
-
- 当前信息 -
- - {{ viewData.username }} - {{ viewData.sex }} - {{ viewData.nation }} - {{ viewData.userState }} - - {{ viewData.personType }} - {{ viewData.education }} - {{ viewData.political }} - {{ viewData.marriage || '' }} - {{ viewData.idCard }} - {{ viewData.mobile }} - {{ viewData.email }} - {{ viewData.member ? '是' : '否' }} - {{ viewData.welfareMember ? '是' : '否' }} - - - -
- {{ viewData.unionName + '-' + viewData.unitName + ( viewData.governmentPosition ? ( '(' + viewData.governmentPosition + ')' ) : '' ) }} -
-
-
-
- -
-
- 变更信息 -
- - - - - - -
-
-
变更/审核说明:
-
-
- {{ item.remark }} -
-
- - - - - - - - - - - - -
-
-
-
- `, - data() { - return { - viewList: [], - activeName: "", - viewData: {} - } - }, - methods: { - formattedTitle(title) { - const datePattern = /\(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\)/ - return title.replace(datePattern, '$&') - }, - onOpen(id, changeTime) { - if (!id) { - return - } - this.$axios.post(loc() + "/getChangeInfoByUserId", { userId: id }).then((res) => { - if (res.code === 0) { - this.viewList = res.data.sort((a, b) => new Date(b.title) - new Date(a.title)) - this.activeName = changeTime || (this.viewList && this.viewList.length > 0 ? this.viewList[0].changeTime : "") - this.findUserInfo(id) - } - }) - }, - findUserInfo(id) { - this.$axios.post("/platform/member/apply/common/findOne", { id }).then((res) => { - if (res.code === 0) { - this.viewData = res.data - } - }) - } - } -} diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/common/info/memberInfo.js b/src/main/resources/views/platform/zhgh/staffmanage/member/common/info/memberInfo.js index 02d1690a..520cf639 100644 --- a/src/main/resources/views/platform/zhgh/staffmanage/member/common/info/memberInfo.js +++ b/src/main/resources/views/platform/zhgh/staffmanage/member/common/info/memberInfo.js @@ -5,60 +5,62 @@ {{ viewData.loginname }} {{ viewData.username }} - {{ viewData.username }} {{ viewData.sex }} - {{ viewData.birthday ? $moment(viewData.birthday).format('YYYY-MM-DD') : null }} - {{ viewData.nation }} - {{ viewData.nativePlace }} - {{ viewData.nationality }} - {{ viewData.idCardType }} - {{ viewData.idCard }} - {{ viewData.political }} - {{ viewData.joinPartyDate ? $moment(viewData.joinPartyDate).format('YYYY-MM-DD') : null }} - {{ viewData.arrivalAtSchoolDate ? $moment(viewData.arrivalAtSchoolDate).format('YYYY-MM-DD') : null}} - {{ viewData.identityType }} - {{ viewData.preparedBy }} - {{ viewData.personType }} - {{ viewData.userState }} - {{ viewData.retireDate ? - $moment(viewData.retireDate).format('YYYY-MM-DD') : null }} - - {{ viewData.mobile }} - {{ viewData.email }} + + {{ viewData.nation }} + {{ viewData.birthday ? $moment(viewData.birthday).format('YYYY-MM-DD') : null }} + {{ viewData.political }} + + {{ viewData.education }} + {{ viewData.academicDegree }} + {{ viewData.position }} + + {{ viewData.unitName }} + {{ viewData.unionName }} + {{ viewData.campus }} + + {{ viewData.idcard }} + {{ viewData.mobile }} + {{ viewData.email }} + + {{ viewData.userState }} + {{ viewData.personType }} + {{ viewData.arrivalAtSchoolDate ? $moment(viewData.arrivalAtSchoolDate).format('YYYY-MM-DD') : null}} + + + + {{ viewData.member ? '会员' : '非会员' }} + {{ viewData.welfareMember ? '福利会员' : '非福利会员' }} + + + + + + + + + + + + + + + + + + +
+ 无数据 +
-
会员信息
- - - - - - {{ viewData.unitName }} - {{ viewData.unionName }} - - -
学历信息
- - {{ viewData.education }} - {{ viewData.academicDegree }} - - - -
职称信息
- - {{ viewData.technicalTitle }} - {{ viewData.technicalTitleLevel }} - - - -
职务信息
- - {{ viewData.position }} - {{ viewData.positionLevel }} - {{ viewData.employeeLevel }} - - - `, data() { diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/common/record/memberRecord.js b/src/main/resources/views/platform/zhgh/staffmanage/member/common/record/memberRecord.js deleted file mode 100644 index 35f44986..00000000 --- a/src/main/resources/views/platform/zhgh/staffmanage/member/common/record/memberRecord.js +++ /dev/null @@ -1,143 +0,0 @@ -const MEMBER_RECORD = { - template: ` -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- `, - mixins: [initTableMixins], - data() { - return { - userId: "", - recordId: "", - tableColumns: [ - { prop: "loginname", label: "工号" }, - { prop: "username", label: "姓名" }, - { prop: "sex", label: "性别", sortable: true, width: "100px" }, - { prop: "birthday", label: "出生年月", sortable: true }, - { prop: "personType", label: "人员类型", sortable: true }, - { prop: "userState", label: "在职状态", sortable: true }, - { prop: "unionName", label: "所属工会", sortable: true }, - { prop: "unitName", label: "所属单位", sortable: true }, - { prop: "remark", label: "变更说明", sortable: true } - ], - unions: [], - units: [], - changeTypeData: [], - changeInfoVisible: false, - changeTime: "" - } - }, - methods: { - openUserChangeInfo(row) { - this.$emit("open-change-info", row) - }, - getChangeTypes(changeTypes) { - if (changeTypes) { - const c = JSON.parse(changeTypes) - if (!c || c.length === 0 || !this.changeTypeData || this.changeTypeData.length === 0) return null - return c - .map((v) => { - return this.changeTypeData.find((item) => item.code === v).name - }) - .join(",") - } - return null - }, - openView(userId) { - this.$emit("open-view", userId) - }, - async initData() { - if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) { - this.unions = await this.$businessTool.listUnion(this.pageForm.unionId) - this.units = await this.$businessTool.listUnit() - } else { - this.unions = await this.$businessTool.listUnion(this.$store.state.user.union.id) - this.units = await this.$businessTool.listUnit(this.$store.state.user.union.id) - } - this.pageData() - }, - async flushUnits() { - this.$set(this.pageForm, "unitId", null) - this.units = [] - if (this.pageForm.unionId) { - this.$businessTool.listUnit(this.pageForm.unionId).then((data) => { - this.units = data - }) - } - } - }, - created() { - this.pageData() - this.$businessTool.getAllDictOptions("MEMBER_CHANGE_TYPE").then((res) => { - this.changeTypeData = res - }) - } -} diff --git a/src/main/resources/views/platform/zhgh/staffmanage/membercost/chartSummary/index.html b/src/main/resources/views/platform/zhgh/staffmanage/membercost/chartSummary/index.html new file mode 100644 index 00000000..c2de1e4f --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/membercost/chartSummary/index.html @@ -0,0 +1,376 @@ + + + + +
+ +
+ +
+ +
+ + - + +
+ +
总缴费金额
+
{{numData.payMoney?numData.payMoney:'0'}}
+
+
+ +
退款金额
+
{{numData.refundMoney?numData.refundMoney:'0'}}
+
+
+ +
退款订单数
+
{{numData.refundSize?numData.refundSize:'0'}}
+
+
+ +
总缴费人数
+
{{numData.paySize?numData.paySize:'0'}}
+
+
+
+ +
+ + - + +
+ +
已缴人数
+
+
+ +
已缴金额
+
+
+
+ + + +
+ +
+
+ + + +
+ +
+
+
+
+
+
+
+ + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/staffmanage/membercost/config.html b/src/main/resources/views/platform/zhgh/staffmanage/membercost/config.html new file mode 100644 index 00000000..4c9d74eb --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/membercost/config.html @@ -0,0 +1,370 @@ + + +
+ + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/staffmanage/membercost/mine/index.html b/src/main/resources/views/platform/zhgh/staffmanage/membercost/mine/index.html new file mode 100644 index 00000000..93f8b9a8 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/membercost/mine/index.html @@ -0,0 +1,368 @@ + + +
+ + + + + + + + + + + + + + + +
+ +
{{formData.paymentStartMonth}}至{{formData.paymentEndMonth}}
+
+ +
+ ( + + ) * 0.5% * {{formData.paymentMonth}}个月 +
+
固定金额缴费
+
+ +
+ +
+ + + +
+
+ +
¥ {{formData.paymentMoney}}
+
+
+ +
+ + {{formData.transactionId}} + + +
¥ {{formData.paymentMoney}}
+
+
+ + +
+ +
+ + 请打开手机微信,扫一扫完成支付 +
+
+
+ +
+ +
+
+
+
+
+
+
+
+
+
+ +
+
+ 支付成功! +
+
+
+ + {{formData.transactionId}} + + +
¥ {{formData.paymentMoney}} +
+
+
+
+
+
+ + 关 闭 + 下一步 + +
+
+ +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/staffmanage/membercost/mine/minePayInfo.js b/src/main/resources/views/platform/zhgh/staffmanage/membercost/mine/minePayInfo.js new file mode 100644 index 00000000..29b804f7 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/membercost/mine/minePayInfo.js @@ -0,0 +1,125 @@ +const MINE_PAY_INFO = { + template: /*language=html*/ ` +
+ + {{ viewData.loginname }} + {{ viewData.username }} + {{ viewData.projectName }} + {{ viewData.unionname }} + {{ viewData.unitname }} + {{ viewData.personType }} + + 已缴费 + 未缴费 + + {{ viewData.paymentMoney }} + {{ viewData.paymentMonth }} + + + + + + + + {{ refundData.outRefundTradeNo }} + {{ refundData.refundNo }} + + {{ refundData.total ? (Number(refundData.total) / 100) : 0 }} + + {{ moment(refundData.updatedAt).format("YYYY-MM-DD HH:mm:ss") }} + + {{ getRefundStates(refundData.refundState) }} + + + + 关 闭 + + +
+ `, + props: { + tradingStates: { type: Array, default: () => [] }, + refundStates: { type: Array, default: () => [] }, + tradingChannels: { type: Array, default: () => [] }, + }, + data() { + return{ + viewData: {}, + refundData: {}, + refundDialogVisible: false + } + }, + methods: { + showRefundInfo(row) { + this.refundData = {} + this.refundData = this.viewData.refundRecordList.find(item => item.paymentTransactionId === row.id) + if (this.refundData) { + this.refundDialogVisible = true + } else { + this.$message.error("此订单无退款记录") + } + }, + async onOpen(id) { + const resp = await $.post('/platform/member/payment/mine/getPaymentInfoById', {id}) + if (resp.code === 0) { + this.viewData = resp.data + } else { + this.$message.error("操作失败") + } + }, + getTradingStates(data) { + if (!data) { + return + } + return this.tradingStates.find(item => item.name === data).tradingStateName + }, + getRefundStates(data) { + if (!data) { + return + } + debugger + return this.refundStates.find(item => item.name === data).refundStateName + }, + getTradingChannel(data) { + if (!data) { + return + } + return this.tradingChannels.find(item => item.name === data).tradingChannelName + }, + } +} diff --git a/src/main/resources/views/platform/zhgh/staffmanage/membercost/project.html b/src/main/resources/views/platform/zhgh/staffmanage/membercost/project.html new file mode 100644 index 00000000..4fa59f8c --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/membercost/project.html @@ -0,0 +1,410 @@ + + + + +
+ + + + + + + + + + 二维码 + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/staffmanage/membercost/refund/index.html b/src/main/resources/views/platform/zhgh/staffmanage/membercost/refund/index.html new file mode 100644 index 00000000..a2cbbcc0 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/membercost/refund/index.html @@ -0,0 +1,185 @@ + +
+ + + +
+ + + + + diff --git a/src/main/resources/views/platform/zhgh/staffmanage/membercost/summary.html b/src/main/resources/views/platform/zhgh/staffmanage/membercost/summary.html new file mode 100644 index 00000000..f02e8af8 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/membercost/summary.html @@ -0,0 +1,483 @@ + + +
+ + + + + + + + + + + + + + + + +
+ + 取 消 + 确 定 + +
+
+
+ + + diff --git a/src/main/resources/views/platform/zhgh/staffmanage/membercost/user.html b/src/main/resources/views/platform/zhgh/staffmanage/membercost/user.html new file mode 100644 index 00000000..b16a718d --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffmanage/membercost/user.html @@ -0,0 +1,337 @@ + +
+ + + + + + + + +
+ + diff --git a/src/main/resources/views/platform/zhgh/staffmanage/specialstaff/manage/addOrModifySpecialStaff.js b/src/main/resources/views/platform/zhgh/staffmanage/specialstaff/manage/addOrModifySpecialStaff.js index a06d12c0..6520d84c 100644 --- a/src/main/resources/views/platform/zhgh/staffmanage/specialstaff/manage/addOrModifySpecialStaff.js +++ b/src/main/resources/views/platform/zhgh/staffmanage/specialstaff/manage/addOrModifySpecialStaff.js @@ -1,86 +1,155 @@ const ADD_OR_MODIFY_SPECIAL_STAFF = { - template: ` + template: /*language=HTML*/ `
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 提交 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 关闭 + 提交 + +
`, store, @@ -89,13 +158,15 @@ const ADD_OR_MODIFY_SPECIAL_STAFF = { }, data() { return { + isThreeUnit: false, formData: {}, units: [], specialStaffTypeList: [], users: [], formRules: { userId: [{ required: true, message: "请输入工号", trigger: "change" }], - specialStaffType: [{ required: true, message: "请选择多单位人员类型", trigger: "change" }], + specialStaffType: [{ required: true, message: "请选择人员类型", trigger: "change" }], + unionRelationUnionId: [{ required: true, message: "请选择工会关系所属工会", trigger: "change" }], specialStaffRemark: [{ required: true, message: "请填写多单位人员备注", trigger: "change" }] } } diff --git a/src/main/resources/views/platform/zhgh/staffmanage/specialstaff/manage/index.html b/src/main/resources/views/platform/zhgh/staffmanage/specialstaff/manage/index.html index f6711ae0..95be731d 100644 --- a/src/main/resources/views/platform/zhgh/staffmanage/specialstaff/manage/index.html +++ b/src/main/resources/views/platform/zhgh/staffmanage/specialstaff/manage/index.html @@ -52,9 +52,17 @@ layout("/layouts/platform.html"){ :sortable="column.sortable" header-align="center" show-overflow-tooltip> - + + + @@ -82,104 +90,362 @@ layout("/layouts/platform.html"){ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 关闭 + 提交 + + + + + + +
+ + + + + + + + + +
+
+
+
+ +
+
+
+ 项目名称: + {{item.projectName}} +
+
+ 所属时间: + {{item.paymentStartMonth}} 至 {{item.paymentEndMonth}} +
+
+ 缴费时间: + {{moment(item.startTime).format('MM-DD') + ' 至 ' + moment(item.endTime).format('MM-DD')}} +
+
+
+ +
+ +
+ + +
+ + + + + + + + + + + + + +
+ +
+ + + + + +
+ + + + diff --git a/src/main/resources/views/platform/zhghh5/staffmanage/memberCost/paySuccess.html b/src/main/resources/views/platform/zhghh5/staffmanage/memberCost/paySuccess.html new file mode 100644 index 00000000..603cafd6 --- /dev/null +++ b/src/main/resources/views/platform/zhghh5/staffmanage/memberCost/paySuccess.html @@ -0,0 +1,134 @@ + + + +
+ +
+
+ + 支付成功 + 您已付款成功,请返回查看会费情况 +
+
+
+
¥{{total_amount}}
+
+ +
+
+ + 订单编号 + + {{out_trade_no}} + + + + 支付时间 + + {{timestamp}} + + +
+
+ + +
+ + + + + + diff --git a/src/main/resources/views/platform/zhghh5/staffmanage/memberCost/summary.html b/src/main/resources/views/platform/zhghh5/staffmanage/memberCost/summary.html new file mode 100644 index 00000000..c6fe050c --- /dev/null +++ b/src/main/resources/views/platform/zhghh5/staffmanage/memberCost/summary.html @@ -0,0 +1,198 @@ + +
+ + + + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ 提交 +
+
+
+
+
+
+ + +