From d54eb56aed38ff7baa6509e584311e062c8dec7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=A3=E5=93=B2=E5=A5=87?= <13840175730@139.com> Date: Tue, 21 Oct 2025 16:09:28 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E8=AF=BE=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-admin/pom.xml | 81 +- .../cn/xluobo/BusinessServerApplication.java | 25 + .../cn/xluobo/OauthServerApplication.java | 21 + .../domain/req/ReqSearchAdIntentionOrder.java | 19 + .../intention/enums/DealResultTypeEnum.java | 29 + .../repo/mapper/AdIntentionOrderMapper.java | 15 + .../repo/mapping/AdIntentionOrderMapper.xml | 5 + .../repo/model/AdIntentionOrder.java | 109 +++ .../service/IAdIntentionOrderService.java | 15 + .../impl/AdIntentionOrderServiceImpl.java | 20 + .../business/enums/BusinessTableEnums.java | 71 ++ .../repo/mapper/MkDiscountCourseMapper.java | 16 + .../repo/mapper/MkDiscountDeptMapper.java | 16 + .../repo/mapper/MkDiscountDetailMapper.java | 16 + .../repo/mapper/MkDiscountMapper.java | 16 + .../repo/mapping/MkDiscountCourseMapper.xml | 5 + .../repo/mapping/MkDiscountDeptMapper.xml | 5 + .../repo/mapping/MkDiscountDetailMapper.xml | 5 + .../repo/mapping/MkDiscountMapper.xml | 5 + .../mk/discount/repo/model/MkDiscount.java | 103 +++ .../discount/repo/model/MkDiscountCourse.java | 40 + .../discount/repo/model/MkDiscountDept.java | 40 + .../discount/repo/model/MkDiscountDetail.java | 55 ++ .../service/IMkDiscountCourseService.java | 16 + .../service/IMkDiscountDeptService.java | 16 + .../service/IMkDiscountDetailService.java | 16 + .../discount/service/IMkDiscountService.java | 16 + .../impl/MkDiscountCourseServiceImpl.java | 20 + .../impl/MkDiscountDeptServiceImpl.java | 20 + .../impl/MkDiscountDetailServiceImpl.java | 20 + .../service/impl/MkDiscountServiceImpl.java | 20 + .../controller/AnalysisReportController.java | 35 + .../domain/resp/RespMonthCourseOrderFee.java | 29 + .../service/AnalysisReportService.java | 99 +++ .../controller/DashboardController.java | 32 + .../dashboard/domain/resp/DashboardData.java | 58 ++ .../dashboard/service/DashboardService.java | 91 ++ .../sc/base/controller/ScRoomController.java | 89 ++ .../base/controller/ScSchoolController.java | 89 ++ .../sc/base/domain/req/ReqRoomSelect.java | 16 + .../sc/base/domain/req/ReqSchoolSelect.java | 20 + .../sc/base/domain/req/ReqSearchScRoom.java | 17 + .../sc/base/domain/req/ReqSearchScSchool.java | 17 + .../sc/base/domain/resp/RespRoomInfo.java | 16 + .../sc/base/domain/resp/RespRoomSelect.java | 15 + .../sc/base/domain/resp/RespSchoolSelect.java | 25 + .../sc/base/repo/mapper/ScRoomMapper.java | 40 + .../sc/base/repo/mapper/ScSchoolMapper.java | 27 + .../sc/base/repo/mapping/ScRoomMapper.xml | 30 + .../sc/base/repo/mapping/ScSchoolMapper.xml | 19 + .../business/sc/base/repo/model/ScRoom.java | 82 ++ .../business/sc/base/repo/model/ScSchool.java | 79 ++ .../base/service/BusinessScRoomService.java | 142 ++++ .../base/service/BusinessScSchoolService.java | 134 +++ .../sc/base/service/IScRoomService.java | 25 + .../sc/base/service/IScSchoolService.java | 34 + .../base/service/impl/ScRoomServiceImpl.java | 28 + .../service/impl/ScSchoolServiceImpl.java | 48 ++ .../controller/ScClaTimeAttendController.java | 91 ++ .../controller/ScClaTimeController.java | 125 +++ .../controller/ScClaTimeRuleController.java | 79 ++ .../controller/ScCourseClaController.java | 94 +++ .../course/controller/ScCourseController.java | 155 ++++ .../controller/ScCourseTypeController.java | 89 ++ .../sc/course/domain/export/ExpCourse.java | 66 ++ .../course/domain/export/ExpCourseCharge.java | 12 + .../course/domain/req/ReqAddScCourseCla.java | 63 ++ .../domain/req/ReqBusinessAddClaStu.java | 18 + .../domain/req/ReqBusinessAddStuCla.java | 18 + .../domain/req/ReqBusinessClaBegin.java | 72 ++ .../req/ReqBusinessOrderCourseDetail.java | 18 + .../course/domain/req/ReqCourseClaSelect.java | 18 + .../course/domain/req/ReqSearchScCourse.java | 47 ++ .../domain/req/ReqSearchScCourseCla.java | 23 + .../domain/req/ReqSearchScCourseType.java | 15 + .../sc/course/domain/req/ReqSelect.java | 32 + .../sc/course/domain/req/cla/ReqClaCount.java | 16 + .../domain/req/course/ReqAddScCourse.java | 155 ++++ .../req/course/ReqAddScCourseChargeItem.java | 42 + .../domain/req/course/ReqChangeScCourse.java | 28 + .../domain/req/time/ReqClaTimeCount.java | 20 + .../domain/req/time/ReqSearchClaTime.java | 69 ++ .../req/time/ReqSearchScClaTimeAttend.java | 27 + .../req/time/ReqSearchScClaTimeRule.java | 30 + .../resp/RespBusinessChooseCourseCharge.java | 38 + .../resp/RespBusinessChooseCourseInfo.java | 33 + .../course/domain/resp/RespBusinessCla.java | 32 + .../domain/resp/RespBusinessClaInfo.java | 20 + .../domain/resp/RespBusinessClaStudent.java | 45 + .../domain/resp/RespBusinessCourseInfo.java | 18 + .../domain/resp/RespBusinessStudent.java | 30 + .../domain/resp/RespBusinessStudentCla.java | 41 + .../course/domain/resp/RespCourseClaInfo.java | 40 + .../domain/resp/RespCourseClaSelectInfo.java | 27 + .../domain/resp/cla/RespClaAllDetailInfo.java | 31 + .../resp/course/RespScCourseDetail.java | 19 + .../domain/resp/course/RespSearchCourse.java | 65 ++ .../domain/resp/time/ClaTimeCalendarItem.java | 58 ++ .../domain/resp/time/ClaTimeColumnTitle.java | 22 + .../domain/resp/time/ClaTimeContainer.java | 23 + .../time/RespBusinessClaTimeCalendar.java | 21 + .../course/domain/resp/time/RespClaTime.java | 73 ++ .../domain/resp/time/RespClaTimeAttend.java | 47 ++ .../domain/resp/time/RespClaTimeCalendar.java | 26 + .../domain/resp/time/RespClaTimeRule.java | 29 + .../sc/course/enums/ChargeDateUnitEnum.java | 41 + .../sc/course/enums/CourseChargeTypeEnum.java | 42 + .../repo/enums/ClaTimeAttendStatusEnums.java | 45 + .../repo/enums/ClaTimeRepeatTypeEnums.java | 29 + .../repo/enums/ClaTimeRuleTypeEnums.java | 30 + .../course/repo/enums/ClaTimeSourceEnums.java | 31 + .../course/repo/enums/ClaTimeStatusEnums.java | 31 + .../repo/mapper/ScClaTimeAttendMapper.java | 87 ++ .../course/repo/mapper/ScClaTimeMapper.java | 48 ++ .../repo/mapper/ScClaTimeRuleMapper.java | 52 ++ .../repo/mapper/ScCourseChargeMapper.java | 16 + .../course/repo/mapper/ScCourseClaMapper.java | 62 ++ .../sc/course/repo/mapper/ScCourseMapper.java | 64 ++ .../repo/mapper/ScCourseTypeMapper.java | 15 + .../repo/mapping/ScClaTimeAttendMapper.xml | 105 +++ .../course/repo/mapping/ScClaTimeMapper.xml | 129 +++ .../repo/mapping/ScClaTimeRuleMapper.xml | 58 ++ .../repo/mapping/ScCourseChargeMapper.xml | 5 + .../course/repo/mapping/ScCourseClaMapper.xml | 85 ++ .../sc/course/repo/mapping/ScCourseMapper.xml | 126 +++ .../repo/mapping/ScCourseTypeMapper.xml | 5 + .../sc/course/repo/model/ScClaTime.java | 231 ++++++ .../sc/course/repo/model/ScClaTimeAttend.java | 125 +++ .../sc/course/repo/model/ScClaTimeRule.java | 190 +++++ .../sc/course/repo/model/ScCourse.java | 111 +++ .../sc/course/repo/model/ScCourseCharge.java | 84 ++ .../sc/course/repo/model/ScCourseCla.java | 170 ++++ .../sc/course/repo/model/ScCourseType.java | 66 ++ .../service/BusinessClaTimeRuleService.java | 182 ++++ .../service/BusinessClaTimeService.java | 433 ++++++++++ .../BusinessScClaTimeAttendService.java | 129 +++ .../service/BusinessScCourseClaService.java | 275 ++++++ .../service/BusinessScCourseService.java | 537 ++++++++++++ .../service/BusinessScCourseTypeService.java | 140 ++++ .../service/IScClaTimeAttendService.java | 69 ++ .../course/service/IScClaTimeRuleService.java | 80 ++ .../sc/course/service/IScClaTimeService.java | 32 + .../service/IScCourseChargeService.java | 33 + .../course/service/IScCourseClaService.java | 31 + .../sc/course/service/IScCourseService.java | 25 + .../course/service/IScCourseTypeService.java | 15 + .../impl/ScClaTimeAttendServiceImpl.java | 60 ++ .../impl/ScClaTimeRuleServiceImpl.java | 300 +++++++ .../service/impl/ScClaTimeServiceImpl.java | 36 + .../impl/ScCourseChargeServiceImpl.java | 77 ++ .../service/impl/ScCourseClaServiceImpl.java | 56 ++ .../service/impl/ScCourseServiceImpl.java | 39 + .../service/impl/ScCourseTypeServiceImpl.java | 20 + .../ScStudentCourseLogController.java | 33 + .../log/domain/req/ReqSearchStuCourseLog.java | 27 + .../business/sc/log/enums/LogTypeEnum.java | 34 + .../repo/mapper/ScStudentCourseLogMapper.java | 22 + .../repo/mapping/ScStudentCourseLogMapper.xml | 28 + .../sc/log/repo/model/ScStudentCourseLog.java | 127 +++ .../BusinessScStudentCourseLogService.java | 39 + .../service/IScStudentCourseLogService.java | 16 + .../impl/ScStudentCourseLogServiceImpl.java | 20 + .../order/controller/ScOrderController.java | 67 ++ .../order/domain/req/ReqBusinessSignUp.java | 102 +++ .../domain/req/ReqBusinessSignUpItem.java | 58 ++ .../domain/req/ReqBusinessSignUpReceipt.java | 20 + .../req/ReqReportMonthCourseIncome.java | 24 + .../sc/order/domain/req/ReqSearchScOrder.java | 60 ++ .../sc/order/domain/resp/RespOrder.java | 44 + .../resp/RespReportMonthCourseIncome.java | 24 + .../sc/order/enums/OrderDetailTagEnum.java | 30 + .../sc/order/enums/OrderStatusEnum.java | 32 + .../sc/order/enums/OrderTypeEnum.java | 28 + .../order/repo/mapper/OrderReportMapper.java | 23 + .../repo/mapper/ScOrderAccountMapper.java | 16 + .../repo/mapper/ScOrderDetailMapper.java | 16 + .../sc/order/repo/mapper/ScOrderMapper.java | 28 + .../order/repo/mapping/OrderReportMapper.xml | 32 + .../repo/mapping/ScOrderAccountMapper.xml | 5 + .../repo/mapping/ScOrderDetailMapper.xml | 5 + .../sc/order/repo/mapping/ScOrderMapper.xml | 59 ++ .../business/sc/order/repo/model/ScOrder.java | 175 ++++ .../sc/order/repo/model/ScOrderAccount.java | 61 ++ .../sc/order/repo/model/ScOrderDetail.java | 244 ++++++ .../order/service/BusinessScOrderService.java | 757 +++++++++++++++++ .../order/service/IScOrderAccountService.java | 25 + .../order/service/IScOrderDetailService.java | 49 ++ .../sc/order/service/IScOrderService.java | 38 + .../impl/ScOrderAccountServiceImpl.java | 30 + .../impl/ScOrderDetailServiceImpl.java | 56 ++ .../service/impl/ScOrderServiceImpl.java | 43 + .../ScStudentAccountController.java | 35 + .../controller/ScStudentController.java | 89 ++ .../controller/ScStudentCourseController.java | 119 +++ .../student/domain/req/ReqClaTimeAttend.java | 106 +++ .../domain/req/ReqClaTimeAttendItem.java | 26 + .../domain/req/ReqSearchScStudent.java | 22 + .../domain/req/ReqSearchStuCourseSignUp.java | 29 + .../domain/req/ReqSearchStudentCourse.java | 16 + .../domain/req/ReqSearchStudentCourseCla.java | 28 + .../domain/req/ReqStudentCourseChooseCla.java | 35 + .../student/domain/req/ReqStudentSelect.java | 19 + .../resp/RespBusinessStudentCourseInfo.java | 23 + .../domain/resp/RespCourseClaStudent.java | 113 +++ .../domain/resp/RespSearchStudent.java | 44 + .../resp/RespStuCourseSignUpStudent.java | 120 +++ .../domain/resp/RespStudentCourse.java | 103 +++ .../enums/StudentCourseStatusEnum.java | 29 + .../mapper/ScStudentAccountLogMapper.java | 16 + .../repo/mapper/ScStudentAccountMapper.java | 16 + .../repo/mapper/ScStudentContactMapper.java | 16 + .../repo/mapper/ScStudentCourseMapper.java | 101 +++ .../mapper/ScStudentCourseOrderMapper.java | 71 ++ .../student/repo/mapper/ScStudentMapper.java | 49 ++ .../mapping/ScStudentAccountLogMapper.xml | 5 + .../repo/mapping/ScStudentAccountMapper.xml | 5 + .../repo/mapping/ScStudentContactMapper.xml | 5 + .../repo/mapping/ScStudentCourseMapper.xml | 194 +++++ .../mapping/ScStudentCourseOrderMapper.xml | 52 ++ .../student/repo/mapping/ScStudentMapper.xml | 62 ++ .../sc/student/repo/model/ScStudent.java | 131 +++ .../student/repo/model/ScStudentAccount.java | 74 ++ .../repo/model/ScStudentAccountLog.java | 77 ++ .../student/repo/model/ScStudentContact.java | 71 ++ .../student/repo/model/ScStudentCourse.java | 134 +++ .../repo/model/ScStudentCourseOrder.java | 133 +++ .../BusinessScStudentAccountService.java | 34 + .../BusinessScStudentCourseService.java | 578 +++++++++++++ .../service/BusinessScStudentService.java | 222 +++++ .../service/IScStudentAccountLogService.java | 16 + .../service/IScStudentAccountService.java | 32 + .../service/IScStudentContactService.java | 24 + .../service/IScStudentCourseOrderService.java | 70 ++ .../service/IScStudentCourseService.java | 89 ++ .../sc/student/service/IScStudentService.java | 32 + .../impl/ScStudentAccountLogServiceImpl.java | 20 + .../impl/ScStudentAccountServiceImpl.java | 70 ++ .../impl/ScStudentContactServiceImpl.java | 31 + .../impl/ScStudentCourseOrderServiceImpl.java | 154 ++++ .../impl/ScStudentCourseServiceImpl.java | 208 +++++ .../service/impl/ScStudentServiceImpl.java | 52 ++ .../domain/req/ReqSearchStockCategory.java | 12 + .../req/ReqSearchStockCategoryProperty.java | 18 + .../domain/resp/RespLazyLoadCategory.java | 18 + .../enums/StockCategoryPropertyEnum.java | 52 ++ .../repo/mapper/StockCategoryMapper.java | 25 + .../mapper/StockCategoryPropertyMapper.java | 29 + .../repo/mapping/StockCategoryMapper.xml | 12 + .../mapping/StockCategoryPropertyMapper.xml | 22 + .../category/repo/model/StockCategory.java | 112 +++ .../repo/model/StockCategoryProperty.java | 81 ++ .../IStockCategoryPropertyService.java | 31 + .../service/IStockCategoryService.java | 42 + .../StockCategoryPropertyServiceImpl.java | 36 + .../impl/StockCategoryServiceImpl.java | 65 ++ .../goods/domain/req/ReqSearchStockGoods.java | 17 + .../req/ReqSearchStockGoodsProperty.java | 17 + .../domain/req/ReqSearchStockInfoChange.java | 27 + .../goods/repo/mapper/StockGoodsMapper.java | 29 + .../repo/mapper/StockGoodsPropertyMapper.java | 15 + .../repo/mapper/StockInfoChangeMapper.java | 15 + .../goods/repo/mapping/StockGoodsMapper.xml | 19 + .../repo/mapping/StockGoodsPropertyMapper.xml | 5 + .../repo/mapping/StockInfoChangeMapper.xml | 5 + .../stock/goods/repo/model/StockGoods.java | 100 +++ .../goods/repo/model/StockGoodsProperty.java | 50 ++ .../goods/repo/model/StockInfoChange.java | 143 ++++ .../service/IStockGoodsPropertyService.java | 24 + .../goods/service/IStockGoodsService.java | 22 + .../service/IStockInfoChangeService.java | 15 + .../impl/StockGoodsPropertyServiceImpl.java | 29 + .../service/impl/StockGoodsServiceImpl.java | 27 + .../impl/StockInfoChangeServiceImpl.java | 20 + .../info/domain/req/ReqSearchStockInfo.java | 21 + .../info/repo/mapper/StockInfoMapper.java | 29 + .../info/repo/mapping/StockInfoMapper.xml | 27 + .../stock/info/repo/model/StockInfo.java | 110 +++ .../stock/info/service/IStockInfoService.java | 15 + .../service/impl/StockInfoServiceImpl.java | 20 + .../sys/admin/domain/req/ReqPageSelect.java | 18 + .../admin/domain/req/ReqSearchOnlineUser.java | 15 + .../admin/domain/req/ReqSearchSysDept.java | 13 + .../domain/req/ReqSearchSysDictData.java | 20 + .../domain/req/ReqSearchSysDictType.java | 24 + .../admin/domain/req/ReqSearchSysMenu.java | 13 + .../admin/domain/req/ReqSearchSysRole.java | 13 + .../admin/domain/req/ReqSearchSysTenant.java | 22 + .../admin/domain/req/ReqSearchSysUser.java | 18 + .../admin/domain/req/ReqUpdateUserPwd.java | 21 + .../admin/domain/req/ReqUpdateUserRole.java | 24 + .../admin/domain/req/ReqUpdateUserTenant.java | 18 + .../sys/admin/domain/req/ReqUploadFile.java | 19 + .../sys/admin/domain/resp/RespTreeSelect.java | 38 + .../admin/domain/resp/RespTreeSelectMenu.java | 67 ++ .../sys/admin/domain/resp/RespUserInfo.java | 25 + .../sys/admin/domain/resp/RespUserMenu.java | 49 ++ .../business/sys/admin/enums/RoleEnum.java | 34 + .../business/sys/admin/model/SysUserDept.java | 35 + .../sys/admin/model/SysUserTenant.java | 23 + .../sys/admin/repo/mapper/ISysDeptMapper.java | 37 + .../admin/repo/mapper/ISysDictDataMapper.java | 16 + .../admin/repo/mapper/ISysDictTypeMapper.java | 16 + .../sys/admin/repo/mapper/ISysFileMapper.java | 16 + .../sys/admin/repo/mapper/ISysMenuMapper.java | 59 ++ .../sys/admin/repo/mapper/ISysRoleMapper.java | 29 + .../admin/repo/mapper/ISysRoleMenuMapper.java | 16 + .../admin/repo/mapper/ISysUserDeptMapper.java | 16 + .../sys/admin/repo/mapper/ISysUserMapper.java | 40 + .../admin/repo/mapper/ISysUserRoleMapper.java | 16 + .../repo/mapper/ISysUserTenantMapper.java | 19 + .../sys/admin/repo/mapping/ISysDeptMapper.xml | 16 + .../admin/repo/mapping/ISysDictDataMapper.xml | 5 + .../admin/repo/mapping/ISysDictTypeMapper.xml | 5 + .../sys/admin/repo/mapping/ISysFileMapper.xml | 5 + .../sys/admin/repo/mapping/ISysMenuMapper.xml | 51 ++ .../sys/admin/repo/mapping/ISysRoleMapper.xml | 21 + .../admin/repo/mapping/ISysRoleMenuMapper.xml | 5 + .../admin/repo/mapping/ISysTenantMapper.xml | 23 + .../admin/repo/mapping/ISysUserDeptMapper.xml | 5 + .../sys/admin/repo/mapping/ISysUserMapper.xml | 37 + .../admin/repo/mapping/ISysUserRoleMapper.xml | 5 + .../repo/mapping/ISysUserTenantMapper.xml | 11 + .../admin/service/BusinessSysDeptService.java | 132 +++ .../service/BusinessSysDictDataService.java | 168 ++++ .../sys/admin/service/ISysDeptService.java | 55 ++ .../admin/service/ISysDictDataService.java | 41 + .../admin/service/ISysDictTypeService.java | 17 + .../sys/admin/service/ISysFileService.java | 16 + .../sys/admin/service/ISysMenuService.java | 58 ++ .../admin/service/ISysRoleMenuService.java | 29 + .../sys/admin/service/ISysRoleService.java | 54 ++ .../admin/service/ISysUserDeptService.java | 16 + .../admin/service/ISysUserRoleService.java | 16 + .../sys/admin/service/ISysUserService.java | 62 ++ .../admin/service/ISysUserTenantService.java | 18 + .../service/impl/ISysDeptServiceImpl.java | 69 ++ .../service/impl/ISysDictDataServiceImpl.java | 90 ++ .../service/impl/ISysDictTypeServiceImpl.java | 27 + .../service/impl/ISysFileServiceImpl.java | 20 + .../service/impl/ISysMenuServiceImpl.java | 47 ++ .../service/impl/ISysRoleMenuServiceImpl.java | 43 + .../service/impl/ISysRoleServiceImpl.java | 75 ++ .../service/impl/ISysUserDeptServiceImpl.java | 20 + .../service/impl/ISysUserRoleServiceImpl.java | 20 + .../service/impl/ISysUserServiceImpl.java | 89 ++ .../impl/ISysUserTenantServiceImpl.java | 24 + .../holiday/repo/mapper/SysHolidayMapper.java | 16 + .../holiday/repo/mapping/SysHolidayMapper.xml | 5 + .../sys/holiday/repo/model/SysHoliday.java | 48 ++ .../holiday/service/ISysHolidayService.java | 39 + .../service/impl/SysHolidayServiceImpl.java | 98 +++ .../log/repo/mapper/SysOperateLogMapper.java | 16 + .../repo/mapper/SysUserLoginLogMapper.java | 16 + .../log/repo/mapping/SysOperateLogMapper.xml | 5 + .../repo/mapping/SysUserLoginLogMapper.xml | 5 + .../sys/log/repo/model/SysOperateLog.java | 127 +++ .../sys/log/repo/model/SysUserLoginLog.java | 67 ++ .../log/service/ISysOperateLogService.java | 22 + .../log/service/ISysUserLoginLogService.java | 26 + .../impl/SysOperateLogServiceImpl.java | 26 + .../impl/SysUserLoginLogServiceImpl.java | 73 ++ .../SysReceiptAccountController.java | 88 ++ .../req/ReqSearchSysReceiptAccount.java | 16 + .../repo/mapper/SysReceiptAccountMapper.java | 15 + .../repo/mapping/SysReceiptAccountMapper.xml | 5 + .../receipt/repo/model/SysReceiptAccount.java | 76 ++ .../BusinessSysReceiptAccountService.java | 130 +++ .../service/ISysReceiptAccountService.java | 19 + .../impl/SysReceiptAccountServiceImpl.java | 30 + .../staff/controller/SysStaffController.java | 91 ++ .../staff/domain/req/ReqBusinessAddStaff.java | 65 ++ .../sys/staff/domain/req/ReqSearchStaff.java | 19 + .../domain/resp/RespBusinessStaffDetail.java | 34 + .../sys/staff/domain/resp/RespStaffInfo.java | 21 + .../sys/staff/repo/mapper/SysStaffMapper.java | 38 + .../sys/staff/repo/mapping/SysStaffMapper.xml | 32 + .../sys/staff/repo/model/SysStaff.java | 134 +++ .../service/BusinessSysStaffService.java | 384 +++++++++ .../sys/staff/service/ISysStaffService.java | 46 ++ .../service/impl/SysStaffServiceImpl.java | 77 ++ .../sys/tag/controller/SysTagController.java | 78 ++ .../sys/tag/domain/req/ReqSearchSysTag.java | 17 + .../sys/tag/repo/mapper/SysTagMapper.java | 15 + .../sys/tag/repo/mapping/SysTagMapper.xml | 5 + .../business/sys/tag/repo/model/SysTag.java | 76 ++ .../tag/service/BusinessSysTagService.java | 122 +++ .../sys/tag/service/ISysTagService.java | 25 + .../tag/service/impl/SysTagServiceImpl.java | 38 + .../tool/export/domain/ExportBaseBean.java | 11 + .../export/handler/SelectWriteHandler.java | 74 ++ .../handler/bean/SelectValidationData.java | 47 ++ .../strategy/CourseExportMergeStrategy.java | 72 ++ .../gen/domain/req/ReqSearchToolGenTable.java | 19 + .../impt/controller/ImportController.java | 61 ++ .../business/tool/impt/domain/ImportBase.java | 12 + .../tool/impt/domain/ImportCourse.java | 54 ++ .../tool/impt/domain/ImportCourseCla.java | 90 ++ .../tool/impt/domain/ImportStudentOrder.java | 103 +++ .../tool/impt/domain/ReqDownImplTemplate.java | 20 + .../tool/impt/domain/ReqUploadImplData.java | 27 + .../listener/ImportCourseClaListener.java | 258 ++++++ .../impt/listener/ImportCourseListener.java | 208 +++++ .../listener/ImportStudentOrderListener.java | 782 ++++++++++++++++++ .../impt/repo/mapper/ToolImportMapper.java | 16 + .../impt/repo/mapping/ToolImportMapper.xml | 5 + .../tool/impt/repo/model/ToolImport.java | 69 ++ .../impt/repo/service/IToolImportService.java | 16 + .../service/impl/ToolImportServiceImpl.java | 20 + .../impt/service/BusinessImportService.java | 115 +++ .../strategy/AbstractImportStrategy.java | 36 + .../service/strategy/IImportStrategy.java | 46 ++ .../impt/service/strategy/ImportContext.java | 144 ++++ .../strategy/impl/ImportCourseClaImpl.java | 296 +++++++ .../strategy/impl/ImportCourseImpl.java | 159 ++++ .../strategy/impl/ImportStudentOrderImpl.java | 214 +++++ .../controller/WechatCpAccountController.java | 78 ++ .../controller/WechatCpContactController.java | 78 ++ .../WechatCpContactWayController.java | 78 ++ .../WechatCpCustomerController.java | 37 + .../WechatCpGroupTagController.java | 88 ++ .../cp/controller/WechatCpUserController.java | 36 + .../wechat/cp/domain/cp/ReqCpBase.java | 17 + .../cp/domain/cp/ReqCpExternalContact.java | 21 + .../wechat/cp/domain/cp/ReqCpUserDetail.java | 18 + .../wechat/cp/domain/cp/ReqCpUserList.java | 27 + .../cp/domain/req/ReqSearchCpCustomer.java | 27 + .../domain/req/ReqSearchWechatCpAccount.java | 17 + .../domain/req/ReqSearchWechatCpContact.java | 15 + .../ReqSearchWechatCpContactFollowTag.java | 20 + .../req/ReqSearchWechatCpContactWay.java | 15 + .../domain/req/ReqSearchWechatCpGroupTag.java | 15 + .../cp/domain/req/ReqSearchWechatCpUser.java | 15 + .../cp/domain/req/RespWechatCpContactWay.java | 21 + .../enums/WechatCpAgentSecretTypeEnum.java | 24 + .../cp/repo/mapper/WechatCpAccountMapper.java | 25 + .../mapper/WechatCpContactFollowMapper.java | 15 + .../WechatCpContactFollowTagMapper.java | 15 + .../cp/repo/mapper/WechatCpContactMapper.java | 15 + .../repo/mapper/WechatCpContactWayMapper.java | 23 + .../cp/repo/mapper/WechatCpGroupMapper.java | 15 + .../repo/mapper/WechatCpGroupTagMapper.java | 15 + .../cp/repo/mapper/WechatCpUserMapper.java | 15 + .../cp/repo/mapping/WechatCpAccountMapper.xml | 12 + .../mapping/WechatCpContactFollowMapper.xml | 5 + .../WechatCpContactFollowTagMapper.xml | 5 + .../cp/repo/mapping/WechatCpContactMapper.xml | 5 + .../repo/mapping/WechatCpContactWayMapper.xml | 14 + .../cp/repo/mapping/WechatCpGroupMapper.xml | 5 + .../repo/mapping/WechatCpGroupTagMapper.xml | 5 + .../cp/repo/mapping/WechatCpUserMapper.xml | 5 + .../wechat/cp/repo/model/WechatCpAccount.java | 109 +++ .../wechat/cp/repo/model/WechatCpContact.java | 145 ++++ .../cp/repo/model/WechatCpContactFollow.java | 110 +++ .../repo/model/WechatCpContactFollowTag.java | 102 +++ .../cp/repo/model/WechatCpContactWay.java | 259 ++++++ .../wechat/cp/repo/model/WechatCpGroup.java | 104 +++ .../cp/repo/model/WechatCpGroupTag.java | 116 +++ .../wechat/cp/repo/model/WechatCpUser.java | 153 ++++ .../BusinessWechatCpAccountService.java | 121 +++ .../BusinessWechatCpContactService.java | 111 +++ .../BusinessWechatCpContactWayService.java | 147 ++++ .../BusinessWechatCpCustomerService.java | 41 + .../BusinessWechatCpGroupTagService.java | 170 ++++ .../service/BusinessWechatCpUserService.java | 43 + .../cp/service/IWechatCpAccountService.java | 48 ++ .../IWechatCpContactFollowService.java | 22 + .../IWechatCpContactFollowTagService.java | 22 + .../cp/service/IWechatCpContactService.java | 15 + .../service/IWechatCpContactWayService.java | 23 + .../cp/service/IWechatCpGroupService.java | 15 + .../cp/service/IWechatCpGroupTagService.java | 15 + .../cp/service/IWechatCpUserService.java | 15 + .../service/ThirdWechatCpContactService.java | 163 ++++ .../cp/service/ThirdWechatCpUserService.java | 49 ++ .../cp/service/WechatCpSyncService.java | 353 ++++++++ .../impl/WechatCpAccountServiceImpl.java | 53 ++ .../WechatCpContactFollowServiceImpl.java | 27 + .../WechatCpContactFollowTagServiceImpl.java | 29 + .../impl/WechatCpContactServiceImpl.java | 20 + .../impl/WechatCpContactWayServiceImpl.java | 37 + .../impl/WechatCpGroupServiceImpl.java | 20 + .../impl/WechatCpGroupTagServiceImpl.java | 20 + .../service/impl/WechatCpUserServiceImpl.java | 20 + .../controller/WechatCpJsController.java | 71 ++ .../WechatCpServerCheckController.java | 111 +++ .../repo/mapper/WechatUserInfoMapper.java | 16 + .../repo/mapping/WechatUserInfoMapper.xml | 5 + .../user/repo/model/WechatUserInfo.java | 109 +++ .../user/service/IWechatUserInfoService.java | 27 + .../impl/WechatUserInfoServiceImpl.java | 44 + .../cn/xluobo/config/async/AsyncConfig.java | 30 + .../config/cache/CaffeineCacheConfig.java | 30 + .../converter/CustomConverterConfig.java | 31 + ...omMappingJackson2HttpMessageConverter.java | 61 ++ .../config/exception/BusinessException.java | 12 + .../config/http/RestTemplateConfig.java | 19 + .../IntegrationAuthentication.java | 37 + .../IntegrationAuthenticationContext.java | 21 + .../IntegrationAuthenticationFilter.java | 120 +++ ...tractPreparedIntegrationAuthenticator.java | 25 + .../IntegrationAuthenticator.java | 38 + .../UsernamePasswordAuthenticator.java | 37 + ...ificationCodeIntegrationAuthenticator.java | 30 + .../sms/event/SmsAuthenticateBeforeEvent.java | 17 + .../event/SmsAuthenticateSuccessEvent.java | 17 + .../wechat/miniapp/WechatMiniAppToken.java | 20 + .../cn/xluobo/config/login/LoginTypeEnum.java | 26 + .../config/mybatis/MybatisConfiguration.java | 55 ++ .../config/properties/AddressProperties.java | 21 + .../config/properties/OAuth2ClientDetail.java | 51 ++ .../config/properties/OAuth2SsoDetail.java | 20 + .../properties/UploadConfigProperties.java | 50 ++ .../WechatOAuth2ClientProperties.java | 17 + .../security/CustomAccessDecisionManager.java | 53 ++ .../CustomAuthenticationFailureHandler.java | 39 + .../CustomAuthenticationSuccessHandler.java | 121 +++ .../CustomFilterSecurityInterceptor.java | 59 ++ .../CustomSecurityMetadataSource.java | 75 ++ .../config/security/CustomUserService.java | 21 + ...mUsernamePasswordAuthenticationFilter.java | 60 ++ .../LoginPwdDaoAuthenticationProvider.java | 38 + .../xluobo/config/tenant/MyTenantHandler.java | 42 + .../xluobo/config/tenant/MyTenantParser.java | 97 +++ .../config/tenant/TenantContextHolder.java | 34 + .../wechat/cp/WechatCpConfiguration.java | 91 ++ .../wechat/cp/builder/AbstractBuilder.java | 14 + .../wechat/cp/builder/ImageBuilder.java | 25 + .../config/wechat/cp/builder/TextBuilder.java | 22 + .../handler/ChangeExternalContactHandler.java | 68 ++ .../config/wechat/cp/handler/LogHandler.java | 25 + .../config/wechat/cp/handler/MsgHandler.java | 40 + .../cn/xluobo/core/api/APIBaseResponse.java | 32 + .../java/cn/xluobo/core/api/APIResponse.java | 92 +++ .../java/cn/xluobo/core/api/ApiResEnums.java | 46 ++ .../cn/xluobo/core/constants/SysConstant.java | 44 + .../core/domain/select/GroupSelect.java | 28 + .../java/cn/xluobo/core/file/FileUtils.java | 96 +++ .../src/main/java/cn/xluobo/core/log/Log.java | 38 + .../java/cn/xluobo/core/log/SysLogAspect.java | 209 +++++ .../xluobo/core/log/enums/BusinessType.java | 30 + .../cn/xluobo/core/log/enums/ClientType.java | 28 + .../xluobo/core/log/enums/OperateModule.java | 29 + .../cn/xluobo/core/page/ReqDeptCondition.java | 17 + .../java/cn/xluobo/core/page/ReqPageBase.java | 18 + .../java/cn/xluobo/core/page/RespPage.java | 50 ++ .../serializer/json/LongJsonSerializer.java | 20 + .../java/cn/xluobo/core/utils/DateUtil.java | 67 ++ .../cn/xluobo/core/utils/MimeTypeUtils.java | 55 ++ .../cn/xluobo/core/utils/ServletUtils.java | 59 ++ .../cn/xluobo/core/utils/aes/EncryptUtil.java | 320 +++++++ .../core/utils/bean/ExtendBeanUtils.java | 38 + .../utils/bean/ExtendBeanUtilsCallBack.java | 10 + .../core/utils/http/HttpClientConfig.java | 94 +++ .../cn/xluobo/core/utils/http/HttpHelper.java | 56 ++ .../cn/xluobo/core/utils/http/HttpUtils.java | 282 +++++++ .../cn/xluobo/core/utils/ip/AddressUtils.java | 47 ++ .../java/cn/xluobo/core/utils/ip/IpUtils.java | 164 ++++ .../xluobo/core/utils/pinyin/PinYinUtil.java | 94 +++ .../cn/xluobo/scheduled/HolidayScheduled.java | 34 + .../java/cn/xluobo/utils/ContextUtils.java | 80 ++ .../main/java/cn/xluobo/utils/JsonUtils.java | 28 + .../main/java/com/ruoyi/RuoYiApplication.java | 2 +- .../common/core/domain/model/LoginUser.java | 7 + .../framework/config/CacheNameConstants.java | 14 + .../framework/config/CacheNameEnums.java | 42 + 565 files changed, 32012 insertions(+), 8 deletions(-) create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/BusinessServerApplication.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/OauthServerApplication.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/domain/req/ReqSearchAdIntentionOrder.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/enums/DealResultTypeEnum.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/repo/mapper/AdIntentionOrderMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/repo/mapping/AdIntentionOrderMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/repo/model/AdIntentionOrder.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/service/IAdIntentionOrderService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/service/impl/AdIntentionOrderServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/enums/BusinessTableEnums.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountCourseMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountDeptMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountDetailMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountCourseMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountDeptMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountDetailMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscount.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscountCourse.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscountDept.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscountDetail.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountCourseService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountDeptService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountDetailService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountCourseServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountDeptServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountDetailServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/report/analysis/controller/AnalysisReportController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/report/analysis/domain/resp/RespMonthCourseOrderFee.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/report/analysis/service/AnalysisReportService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/report/dashboard/controller/DashboardController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/report/dashboard/domain/resp/DashboardData.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/report/dashboard/service/DashboardService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/controller/ScRoomController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/controller/ScSchoolController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqRoomSelect.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqSchoolSelect.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqSearchScRoom.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqSearchScSchool.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/resp/RespRoomInfo.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/resp/RespRoomSelect.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/resp/RespSchoolSelect.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapper/ScRoomMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapper/ScSchoolMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapping/ScRoomMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapping/ScSchoolMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/model/ScRoom.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/model/ScSchool.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/BusinessScRoomService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/BusinessScSchoolService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/IScRoomService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/IScSchoolService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/impl/ScRoomServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/impl/ScSchoolServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScClaTimeAttendController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScClaTimeController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScClaTimeRuleController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScCourseClaController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScCourseController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScCourseTypeController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/export/ExpCourse.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/export/ExpCourseCharge.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqAddScCourseCla.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessAddClaStu.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessAddStuCla.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessClaBegin.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessOrderCourseDetail.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqCourseClaSelect.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSearchScCourse.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSearchScCourseCla.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSearchScCourseType.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSelect.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/cla/ReqClaCount.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/course/ReqAddScCourse.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/course/ReqAddScCourseChargeItem.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/course/ReqChangeScCourse.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqClaTimeCount.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqSearchClaTime.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqSearchScClaTimeAttend.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqSearchScClaTimeRule.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessChooseCourseCharge.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessChooseCourseInfo.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessCla.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessClaInfo.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessClaStudent.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessCourseInfo.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessStudent.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessStudentCla.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespCourseClaInfo.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespCourseClaSelectInfo.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/cla/RespClaAllDetailInfo.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/course/RespScCourseDetail.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/course/RespSearchCourse.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/ClaTimeCalendarItem.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/ClaTimeColumnTitle.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/ClaTimeContainer.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespBusinessClaTimeCalendar.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTime.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTimeAttend.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTimeCalendar.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTimeRule.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/enums/ChargeDateUnitEnum.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/enums/CourseChargeTypeEnum.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeAttendStatusEnums.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeRepeatTypeEnums.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeRuleTypeEnums.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeSourceEnums.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeStatusEnums.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScClaTimeAttendMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScClaTimeMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScClaTimeRuleMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseChargeMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseClaMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseTypeMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeAttendMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeRuleMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseChargeMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseClaMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseTypeMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTime.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTimeAttend.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTimeRule.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourse.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourseCharge.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourseCla.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourseType.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessClaTimeRuleService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessClaTimeService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScClaTimeAttendService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScCourseClaService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScCourseService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScCourseTypeService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScClaTimeAttendService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScClaTimeRuleService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScClaTimeService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseChargeService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseClaService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseTypeService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScClaTimeAttendServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScClaTimeRuleServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScClaTimeServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseChargeServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseClaServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseTypeServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/controller/ScStudentCourseLogController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/domain/req/ReqSearchStuCourseLog.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/enums/LogTypeEnum.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/repo/mapper/ScStudentCourseLogMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/repo/mapping/ScStudentCourseLogMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/repo/model/ScStudentCourseLog.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/service/BusinessScStudentCourseLogService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/service/IScStudentCourseLogService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/service/impl/ScStudentCourseLogServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/controller/ScOrderController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqBusinessSignUp.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqBusinessSignUpItem.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqBusinessSignUpReceipt.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqReportMonthCourseIncome.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqSearchScOrder.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/resp/RespOrder.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/resp/RespReportMonthCourseIncome.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/enums/OrderDetailTagEnum.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/enums/OrderStatusEnum.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/enums/OrderTypeEnum.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/OrderReportMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/ScOrderAccountMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/ScOrderDetailMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/ScOrderMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/OrderReportMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/ScOrderAccountMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/ScOrderDetailMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/ScOrderMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/model/ScOrder.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/model/ScOrderAccount.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/model/ScOrderDetail.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/BusinessScOrderService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/IScOrderAccountService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/IScOrderDetailService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/IScOrderService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/impl/ScOrderAccountServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/impl/ScOrderDetailServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/impl/ScOrderServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/controller/ScStudentAccountController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/controller/ScStudentController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/controller/ScStudentCourseController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqClaTimeAttend.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqClaTimeAttendItem.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchScStudent.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchStuCourseSignUp.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchStudentCourse.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchStudentCourseCla.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqStudentCourseChooseCla.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqStudentSelect.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespBusinessStudentCourseInfo.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespCourseClaStudent.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespSearchStudent.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespStuCourseSignUpStudent.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespStudentCourse.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/enums/StudentCourseStatusEnum.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentAccountLogMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentAccountMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentContactMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentCourseMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentCourseOrderMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentAccountLogMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentAccountMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentContactMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentCourseMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentCourseOrderMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudent.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentAccount.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentAccountLog.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentContact.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentCourse.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentCourseOrder.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentAccountService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentCourseService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentAccountLogService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentAccountService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentContactService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentCourseOrderService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentCourseService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentAccountLogServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentAccountServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentContactServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentCourseOrderServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentCourseServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/domain/req/ReqSearchStockCategory.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/domain/req/ReqSearchStockCategoryProperty.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/domain/resp/RespLazyLoadCategory.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/enums/StockCategoryPropertyEnum.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapper/StockCategoryMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapper/StockCategoryPropertyMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapping/StockCategoryMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapping/StockCategoryPropertyMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/model/StockCategory.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/model/StockCategoryProperty.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/IStockCategoryPropertyService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/IStockCategoryService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/impl/StockCategoryPropertyServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/impl/StockCategoryServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/domain/req/ReqSearchStockGoods.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/domain/req/ReqSearchStockGoodsProperty.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/domain/req/ReqSearchStockInfoChange.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapper/StockGoodsMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapper/StockGoodsPropertyMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapper/StockInfoChangeMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapping/StockGoodsMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapping/StockGoodsPropertyMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapping/StockInfoChangeMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockGoods.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockGoodsProperty.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockInfoChange.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/IStockGoodsPropertyService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/IStockGoodsService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/IStockInfoChangeService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/impl/StockGoodsPropertyServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/impl/StockGoodsServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/impl/StockInfoChangeServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/domain/req/ReqSearchStockInfo.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/repo/mapper/StockInfoMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/repo/mapping/StockInfoMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/repo/model/StockInfo.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/service/IStockInfoService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/service/impl/StockInfoServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqPageSelect.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchOnlineUser.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysDept.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysDictData.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysDictType.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysMenu.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysRole.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysTenant.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysUser.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUpdateUserPwd.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUpdateUserRole.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUpdateUserTenant.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUploadFile.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespTreeSelect.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespTreeSelectMenu.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespUserInfo.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespUserMenu.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/enums/RoleEnum.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/model/SysUserDept.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/model/SysUserTenant.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysDeptMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysDictDataMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysDictTypeMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysFileMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysMenuMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysRoleMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysRoleMenuMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserDeptMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserRoleMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserTenantMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysDeptMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysDictDataMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysDictTypeMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysFileMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysMenuMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysRoleMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysRoleMenuMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysTenantMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserDeptMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserRoleMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserTenantMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDeptService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDictDataService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysDeptService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysDictDataService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysDictTypeService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysFileService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysMenuService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysRoleMenuService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysRoleService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserDeptService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserRoleService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserTenantService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysDeptServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysDictDataServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysDictTypeServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysFileServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysMenuServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysRoleMenuServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysRoleServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserDeptServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserRoleServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserTenantServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/repo/mapper/SysHolidayMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/repo/mapping/SysHolidayMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/repo/model/SysHoliday.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/service/ISysHolidayService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/service/impl/SysHolidayServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapper/SysOperateLogMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapper/SysUserLoginLogMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapping/SysOperateLogMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapping/SysUserLoginLogMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/model/SysOperateLog.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/model/SysUserLoginLog.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/ISysOperateLogService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/ISysUserLoginLogService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/impl/SysOperateLogServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/impl/SysUserLoginLogServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/controller/SysReceiptAccountController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/domain/req/ReqSearchSysReceiptAccount.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/repo/mapper/SysReceiptAccountMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/repo/mapping/SysReceiptAccountMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/repo/model/SysReceiptAccount.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/service/BusinessSysReceiptAccountService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/service/ISysReceiptAccountService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/service/impl/SysReceiptAccountServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/controller/SysStaffController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/req/ReqBusinessAddStaff.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/req/ReqSearchStaff.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/resp/RespBusinessStaffDetail.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/resp/RespStaffInfo.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/repo/mapper/SysStaffMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/repo/mapping/SysStaffMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/repo/model/SysStaff.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/service/BusinessSysStaffService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/service/ISysStaffService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/service/impl/SysStaffServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/controller/SysTagController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/domain/req/ReqSearchSysTag.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/repo/mapper/SysTagMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/repo/mapping/SysTagMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/repo/model/SysTag.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/service/BusinessSysTagService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/service/ISysTagService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/service/impl/SysTagServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/domain/ExportBaseBean.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/handler/SelectWriteHandler.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/handler/bean/SelectValidationData.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/strategy/CourseExportMergeStrategy.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/gen/domain/req/ReqSearchToolGenTable.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/controller/ImportController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportBase.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportCourse.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportCourseCla.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportStudentOrder.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ReqDownImplTemplate.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ReqUploadImplData.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/listener/ImportCourseClaListener.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/listener/ImportCourseListener.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/listener/ImportStudentOrderListener.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/mapper/ToolImportMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/mapping/ToolImportMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/model/ToolImport.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/service/IToolImportService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/service/impl/ToolImportServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/BusinessImportService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/AbstractImportStrategy.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/IImportStrategy.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/ImportContext.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/impl/ImportCourseClaImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/impl/ImportCourseImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/impl/ImportStudentOrderImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpAccountController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpContactController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpContactWayController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpCustomerController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpGroupTagController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpUserController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpBase.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpExternalContact.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpUserDetail.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpUserList.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchCpCustomer.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpAccount.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpContact.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpContactFollowTag.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpContactWay.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpGroupTag.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpUser.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/RespWechatCpContactWay.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/enums/WechatCpAgentSecretTypeEnum.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpAccountMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactFollowMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactFollowTagMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactWayMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpGroupMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpGroupTagMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpUserMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpAccountMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactFollowMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactFollowTagMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactWayMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpGroupMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpGroupTagMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpUserMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpAccount.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContact.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactFollow.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactFollowTag.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactWay.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpGroup.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpGroupTag.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpUser.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpAccountService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpContactService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpContactWayService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpCustomerService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpGroupTagService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpUserService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpAccountService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactFollowService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactFollowTagService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactWayService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpGroupService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpGroupTagService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpUserService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/ThirdWechatCpContactService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/ThirdWechatCpUserService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/WechatCpSyncService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpAccountServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactFollowServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactFollowTagServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactWayServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpGroupServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpGroupTagServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpUserServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/server/controller/WechatCpJsController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/server/controller/WechatCpServerCheckController.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/repo/mapper/WechatUserInfoMapper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/repo/mapping/WechatUserInfoMapper.xml create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/repo/model/WechatUserInfo.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/service/IWechatUserInfoService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/service/impl/WechatUserInfoServiceImpl.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/async/AsyncConfig.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/cache/CaffeineCacheConfig.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/converter/CustomConverterConfig.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/converter/CustomMappingJackson2HttpMessageConverter.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/exception/BusinessException.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/http/RestTemplateConfig.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/integration/IntegrationAuthentication.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/integration/IntegrationAuthenticationContext.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/integration/IntegrationAuthenticationFilter.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/AbstractPreparedIntegrationAuthenticator.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/IntegrationAuthenticator.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/UsernamePasswordAuthenticator.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/VerificationCodeIntegrationAuthenticator.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/sms/event/SmsAuthenticateBeforeEvent.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/sms/event/SmsAuthenticateSuccessEvent.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/wechat/miniapp/WechatMiniAppToken.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/login/LoginTypeEnum.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/mybatis/MybatisConfiguration.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/properties/AddressProperties.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/properties/OAuth2ClientDetail.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/properties/OAuth2SsoDetail.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/properties/UploadConfigProperties.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/properties/WechatOAuth2ClientProperties.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAccessDecisionManager.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAuthenticationFailureHandler.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAuthenticationSuccessHandler.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomFilterSecurityInterceptor.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomSecurityMetadataSource.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomUserService.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomUsernamePasswordAuthenticationFilter.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/security/LoginPwdDaoAuthenticationProvider.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/tenant/MyTenantHandler.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/tenant/MyTenantParser.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/tenant/TenantContextHolder.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/WechatCpConfiguration.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/builder/AbstractBuilder.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/builder/ImageBuilder.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/builder/TextBuilder.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/handler/ChangeExternalContactHandler.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/handler/LogHandler.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/handler/MsgHandler.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/api/APIBaseResponse.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/api/APIResponse.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/api/ApiResEnums.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/constants/SysConstant.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/domain/select/GroupSelect.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/file/FileUtils.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/log/Log.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/log/SysLogAspect.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/log/enums/BusinessType.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/log/enums/ClientType.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/log/enums/OperateModule.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/page/ReqDeptCondition.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/page/ReqPageBase.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/page/RespPage.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/serializer/json/LongJsonSerializer.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/utils/DateUtil.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/utils/MimeTypeUtils.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/utils/ServletUtils.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/utils/aes/EncryptUtil.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/utils/bean/ExtendBeanUtils.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/utils/bean/ExtendBeanUtilsCallBack.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/utils/http/HttpClientConfig.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/utils/http/HttpHelper.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/utils/http/HttpUtils.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/utils/ip/AddressUtils.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/utils/ip/IpUtils.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/core/utils/pinyin/PinYinUtil.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/scheduled/HolidayScheduled.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/utils/ContextUtils.java create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/utils/JsonUtils.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/CacheNameConstants.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/CacheNameEnums.java diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml index 4a473df..042973b 100644 --- a/ruoyi-admin/pom.xml +++ b/ruoyi-admin/pom.xml @@ -15,6 +15,33 @@ web服务入口 + + 1.8 + UTF-8 + UTF-8 + + 1.0-SNAPSHOT + 1.0-SNAPSHOT + 1.0-SNAPSHOT + 1.0-SNAPSHOT + 2.1.10.RELEASE + 3.3.0 + 8.0.16 + 1.18.10 + 3.9 + 2.6 + 1.0.11.RELEASE + 3.2.2 + 30.1.1-jre + 2.9.10 + 1.19 + 2.2.6 + 4.5.2 + 4.6.0 + 2.5.0 + 1.4.7 + + @@ -37,7 +64,7 @@ 1.6.2 - + mysql mysql-connector-java @@ -98,6 +125,46 @@ dysmsapi20170525 true + + + joda-time + joda-time + + + + com.alibaba + easyexcel + + + com.alibaba + fastjson + + + ${easyexcel.version} + + + + com.github.ben-manes.caffeine + caffeine + + + + com.github.binarywang + weixin-java-cp + ${weixin-java-binarywang.version} + + + + com.github.binarywang + weixin-java-miniapp + 4.6.0 + + + + com.belerweb + pinyin4j + ${pinyin4j.version} + @@ -117,15 +184,15 @@ - - org.apache.maven.plugins - maven-war-plugin - 3.1.0 + + org.apache.maven.plugins + maven-war-plugin + 3.1.0 false ${project.artifactId} - - + + ${project.artifactId} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/BusinessServerApplication.java b/ruoyi-admin/src/main/java/cn/xluobo/BusinessServerApplication.java new file mode 100644 index 0000000..b32104f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/BusinessServerApplication.java @@ -0,0 +1,25 @@ +package cn.xluobo; + +import cn.xluobo.config.properties.AddressProperties; +import cn.xluobo.config.properties.UploadConfigProperties; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; + +import java.net.UnknownHostException; + +@SpringBootApplication +@EnableConfigurationProperties({UploadConfigProperties.class, AddressProperties.class}) +@EnableScheduling +@EnableAsync +public class BusinessServerApplication { + + public static void main(String[] args) throws UnknownHostException { + SpringApplication.run(BusinessServerApplication.class, args); + } + +} + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/OauthServerApplication.java b/ruoyi-admin/src/main/java/cn/xluobo/OauthServerApplication.java new file mode 100644 index 0000000..d5b8b27 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/OauthServerApplication.java @@ -0,0 +1,21 @@ +package cn.xluobo; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import java.net.UnknownHostException; + +@SpringBootApplication(scanBasePackages = {"cn.xluobo","cn.jljiayu"}) +@EnableTransactionManagement +@MapperScan(value = {"cn.xluobo.*.*.*.repo.mapper"}) +public class OauthServerApplication { + + public static void main(String[] args) throws UnknownHostException { + SpringApplication.run(OauthServerApplication.class, args); + } + +} + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/domain/req/ReqSearchAdIntentionOrder.java b/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/domain/req/ReqSearchAdIntentionOrder.java new file mode 100644 index 0000000..eec58a7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/domain/req/ReqSearchAdIntentionOrder.java @@ -0,0 +1,19 @@ +package cn.xluobo.business.ad.intention.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchAdIntentionOrder extends ReqPageBase implements Serializable { + private String orgName; + private String contact; + private String contactPhone; + private String accountOpen; + private String hadDeal; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/enums/DealResultTypeEnum.java b/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/enums/DealResultTypeEnum.java new file mode 100644 index 0000000..0ccde9d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/enums/DealResultTypeEnum.java @@ -0,0 +1,29 @@ +package cn.xluobo.business.ad.intention.enums; + +/** + * 试用申请处理结果类型 + * 2022/3/21 12:23 下午 + * + * @author zhangby + **/ +public enum DealResultTypeEnum { + + OPEN_ACCOUNT("01", "开通试用账号"), + WAIT("02", "犹豫"), + NOT_TRIAL("03", "产品不适用"), + OTHER("99", "其他"), + ; + + private String value; + + private String text; + + DealResultTypeEnum(String value, String text) { + this.value = value; + this.text = text; + } + + public String getValue() { + return value; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/repo/mapper/AdIntentionOrderMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/repo/mapper/AdIntentionOrderMapper.java new file mode 100644 index 0000000..9cfe0c0 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/repo/mapper/AdIntentionOrderMapper.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.ad.intention.repo.mapper; + +import cn.xluobo.business.ad.intention.repo.model.AdIntentionOrder; + +/** + *

+ * 申请试用表 Mapper 接口 + *

+ * + * @author zhangby + * @since 2022-03-13 09:43:27 + */ +public interface AdIntentionOrderMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/repo/mapping/AdIntentionOrderMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/repo/mapping/AdIntentionOrderMapper.xml new file mode 100644 index 0000000..e8e1d41 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/repo/mapping/AdIntentionOrderMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/repo/model/AdIntentionOrder.java b/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/repo/model/AdIntentionOrder.java new file mode 100644 index 0000000..140048e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/repo/model/AdIntentionOrder.java @@ -0,0 +1,109 @@ +package cn.xluobo.business.ad.intention.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 申请试用表 + *

+ * + * @author zhangby + * @since 2022-03-13 09:43:27 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("ad_intention_order") +public class AdIntentionOrder implements Serializable { + + + @TableId(value = "order_id", type = IdType.ASSIGN_ID) + private String orderId; + + /** + * 机构名称 + */ + @TableField("org_name") + private String orgName; + + /** + * 联系人 + */ + @TableField("contact") + private String contact; + + /** + * 联系电话 + */ + @TableField("contact_phone") + private String contactPhone; + + /** + * 申请时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 申请试用说明 + */ + @TableField("intention_memo") + private String intentionMemo; + + /** + * 是否开通账号1开通 0未开通 + */ + @TableField("account_open") + private Integer accountOpen; + + /** + * 是否已处理完毕 1已处理 0未处理 + */ + @TableField("had_deal") + private Integer hadDeal; + + /** + * 处理结果类型 + */ + @TableField("deal_result_type") + private String dealResultType; + + /** + * 处理结果 + */ + @TableField("deal_result") + private String dealResult; + + /** + * 处理时间 + */ + @TableField("deal_time") + private Date dealTime; + + /** + * 账号信息 + */ + @TableField("user_id") + private String userId; + + /** + * 账号信息 + */ + @TableField("user_name") + private String userName; + + /** + * 账号开通时间 + */ + @TableField("account_open_date") + private Date accountOpenDate; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/service/IAdIntentionOrderService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/service/IAdIntentionOrderService.java new file mode 100644 index 0000000..6e04894 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/service/IAdIntentionOrderService.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.ad.intention.service; + +import cn.xluobo.business.ad.intention.repo.model.AdIntentionOrder; + +/** + *

+ * 申请试用表 服务类 + *

+ * + * @author zhangby + * @since 2022-03-13 09:43:27 + */ +public interface IAdIntentionOrderService extends com.baomidou.mybatisplus.extension.service.IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/service/impl/AdIntentionOrderServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/service/impl/AdIntentionOrderServiceImpl.java new file mode 100644 index 0000000..2937a4e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/ad/intention/service/impl/AdIntentionOrderServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.ad.intention.service.impl; + +import cn.xluobo.business.ad.intention.repo.mapper.AdIntentionOrderMapper; +import cn.xluobo.business.ad.intention.repo.model.AdIntentionOrder; +import cn.xluobo.business.ad.intention.service.IAdIntentionOrderService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 申请试用表 服务实现类 + *

+ * + * @author zhangby + * @since 2022-03-13 09:43:27 + */ +@Service +public class AdIntentionOrderServiceImpl extends ServiceImpl implements IAdIntentionOrderService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/enums/BusinessTableEnums.java b/ruoyi-admin/src/main/java/cn/xluobo/business/enums/BusinessTableEnums.java new file mode 100644 index 0000000..352eef5 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/enums/BusinessTableEnums.java @@ -0,0 +1,71 @@ +package cn.xluobo.business.enums; + +/** + * 表枚举 + */ +public enum BusinessTableEnums { + + SYS_USER("sys_user","系统用户"), + SYS_STAFF("sys_staff","员工表",true), + SYS_DEPT("sys_dept","部门",true), + + SYS_TAG("sys_tag","标签",true), + + SYS_RECEIPT_ACCOUNT("sys_receipt_account","机构收费账户",true), + + SC_SCHOOL("sc_school","学校",true), + SC_ROOM("sc_room","教室",true), + SC_TEACHER("sc_teacher","教师",true), + SC_COURSE("sc_course","课程",true), + SC_COURSE_CLA("sc_course_cla","课程班级",true), + SC_STUDENT("sc_student","学生",true), + SC_COURSE_TYPE("sc_course_type","课程类型",true), + SC_ORDER("sc_order","订单",true), + SC_STUDENT_ACCOUNT("sc_student_account","学生余额账户",true), + SC_STUDENT_COURSE("sc_student_course","学生报读课程",true), + SC_STUDENT_COURSE_LOG("sc_student_course_log","学生日志",true), + + STOCK_GOODS("stock_goods","商品信息",true), + STOCK_INFO("stock_info","库存信息",true), + + WECHAT_CP_ACCOUNT("wechat_cp_account","企业应用信息",true), + WECHAT_CP_CONTACT("wechat_cp_contact","企业外部联系人",true), + WECHAT_CP_CONTACT_WAY("wechat_cp_contact_way","企业客户联系我",true), + WECHAT_CP_GROUP("wechat_cp_group","企业标签组",true), + WECHAT_CP_GROUP_TAG("wechat_cp_group_tag","企业标签",true), + WECHAT_CP_USER("wechat_cp_user","企业通讯录",true), + + ; + + private String table; + + private String tableName; + + /** + * 是否为多租户 table + */ + private boolean isTenant = false; + + BusinessTableEnums(String table, String tableName) { + this.table = table; + this.tableName = tableName; + } + + BusinessTableEnums(String table, String tableName, boolean isTenant) { + this.table = table; + this.tableName = tableName; + this.isTenant = isTenant; + } + + public String getTable() { + return table; + } + + public String getTableName() { + return tableName; + } + + public boolean isTenant() { + return isTenant; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountCourseMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountCourseMapper.java new file mode 100644 index 0000000..5ed8bd9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountCourseMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.mk.discount.repo.mapper; + +import cn.xluobo.business.mk.discount.repo.model.MkDiscountCourse; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 活动课程 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface MkDiscountCourseMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountDeptMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountDeptMapper.java new file mode 100644 index 0000000..dd4121d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountDeptMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.mk.discount.repo.mapper; + +import cn.xluobo.business.mk.discount.repo.model.MkDiscountDept; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 活动校区 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface MkDiscountDeptMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountDetailMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountDetailMapper.java new file mode 100644 index 0000000..1196ba5 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountDetailMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.mk.discount.repo.mapper; + +import cn.xluobo.business.mk.discount.repo.model.MkDiscountDetail; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 优惠配置明细 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface MkDiscountDetailMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountMapper.java new file mode 100644 index 0000000..23ace69 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapper/MkDiscountMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.mk.discount.repo.mapper; + +import cn.xluobo.business.mk.discount.repo.model.MkDiscount; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 优惠配置 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface MkDiscountMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountCourseMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountCourseMapper.xml new file mode 100644 index 0000000..2aaf39f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountCourseMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountDeptMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountDeptMapper.xml new file mode 100644 index 0000000..1f7fef4 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountDeptMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountDetailMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountDetailMapper.xml new file mode 100644 index 0000000..0d3173b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountDetailMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountMapper.xml new file mode 100644 index 0000000..60cdfb4 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/mapping/MkDiscountMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscount.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscount.java new file mode 100644 index 0000000..51bb95b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscount.java @@ -0,0 +1,103 @@ +package cn.xluobo.business.mk.discount.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 优惠配置 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("mk_discount") +public class MkDiscount implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 优惠编号 + */ + @TableId(value = "discount_id", type = IdType.ASSIGN_ID) + private Long discountId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 活动名称 + */ + @TableField("activity_name") + private String activityName; + + /** + * 折扣类型 1满减 2满折 3满赠 + */ + @TableField("discount_type") + private String discountType; + + /** + * 折扣开始时间 + */ + @TableField("begin_date") + private Date beginDate; + + /** + * 结束时间 + */ + @TableField("end_date") + private Date endDate; + + /** + * 是否生效 + */ + @TableField("enable") + private Integer enable; + + /** + * 版本号 + */ + @TableField("version") + private Integer version; + + /** + * 创建者 + */ + @TableField("create_user") + private String createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private String lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscountCourse.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscountCourse.java new file mode 100644 index 0000000..dd6aab1 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscountCourse.java @@ -0,0 +1,40 @@ +package cn.xluobo.business.mk.discount.repo.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * 活动课程 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("mk_discount_course") +public class MkDiscountCourse implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 折扣编号 + */ + @TableField("discount_id") + private Long discountId; + + /** + * 课程 -1为全部课程 + */ + @TableField("course_id") + private Long courseId; + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscountDept.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscountDept.java new file mode 100644 index 0000000..3a7e7c1 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscountDept.java @@ -0,0 +1,40 @@ +package cn.xluobo.business.mk.discount.repo.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * 活动校区 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("mk_discount_dept") +public class MkDiscountDept implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 折扣编号 + */ + @TableField("discount_id") + private Long discountId; + + /** + * 校区 -1为全部校区 + */ + @TableField("dept_id") + private Long deptId; + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscountDetail.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscountDetail.java new file mode 100644 index 0000000..a59a617 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/repo/model/MkDiscountDetail.java @@ -0,0 +1,55 @@ +package cn.xluobo.business.mk.discount.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + *

+ * 优惠配置明细 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("mk_discount_detail") +public class MkDiscountDetail implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细编号 + */ + @TableId(value = "discount_detail_id", type = IdType.ASSIGN_ID) + private Long discountDetailId; + + /** + * 折扣编号 + */ + @TableField("discount_id") + private Long discountId; + + /** + * 满足条件 金额/课时 + */ + @TableField("meet_condition") + private BigDecimal meetCondition; + + /** + * 赠送 金额/折扣/课时 + */ + @TableField("gift") + private BigDecimal gift; + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountCourseService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountCourseService.java new file mode 100644 index 0000000..2fe4c0a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountCourseService.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.mk.discount.service; + +import cn.xluobo.business.mk.discount.repo.model.MkDiscountCourse; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 活动课程 服务类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface IMkDiscountCourseService extends IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountDeptService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountDeptService.java new file mode 100644 index 0000000..c2ed19d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountDeptService.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.mk.discount.service; + +import cn.xluobo.business.mk.discount.repo.model.MkDiscountDept; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 活动校区 服务类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface IMkDiscountDeptService extends IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountDetailService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountDetailService.java new file mode 100644 index 0000000..27eeb23 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountDetailService.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.mk.discount.service; + +import cn.xluobo.business.mk.discount.repo.model.MkDiscountDetail; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 优惠配置明细 服务类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface IMkDiscountDetailService extends IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountService.java new file mode 100644 index 0000000..6900af5 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/IMkDiscountService.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.mk.discount.service; + +import cn.xluobo.business.mk.discount.repo.model.MkDiscount; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 优惠配置 服务类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface IMkDiscountService extends IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountCourseServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountCourseServiceImpl.java new file mode 100644 index 0000000..83ed856 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountCourseServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.mk.discount.service.impl; + +import cn.xluobo.business.mk.discount.repo.mapper.MkDiscountCourseMapper; +import cn.xluobo.business.mk.discount.repo.model.MkDiscountCourse; +import cn.xluobo.business.mk.discount.service.IMkDiscountCourseService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 活动课程 服务实现类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Service +public class MkDiscountCourseServiceImpl extends ServiceImpl implements IMkDiscountCourseService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountDeptServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountDeptServiceImpl.java new file mode 100644 index 0000000..ec61b63 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountDeptServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.mk.discount.service.impl; + +import cn.xluobo.business.mk.discount.repo.mapper.MkDiscountDeptMapper; +import cn.xluobo.business.mk.discount.repo.model.MkDiscountDept; +import cn.xluobo.business.mk.discount.service.IMkDiscountDeptService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 活动校区 服务实现类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Service +public class MkDiscountDeptServiceImpl extends ServiceImpl implements IMkDiscountDeptService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountDetailServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountDetailServiceImpl.java new file mode 100644 index 0000000..3a1d67c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountDetailServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.mk.discount.service.impl; + +import cn.xluobo.business.mk.discount.repo.mapper.MkDiscountDetailMapper; +import cn.xluobo.business.mk.discount.repo.model.MkDiscountDetail; +import cn.xluobo.business.mk.discount.service.IMkDiscountDetailService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 优惠配置明细 服务实现类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Service +public class MkDiscountDetailServiceImpl extends ServiceImpl implements IMkDiscountDetailService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountServiceImpl.java new file mode 100644 index 0000000..fa7ae2a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/mk/discount/service/impl/MkDiscountServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.mk.discount.service.impl; + +import cn.xluobo.business.mk.discount.repo.mapper.MkDiscountMapper; +import cn.xluobo.business.mk.discount.repo.model.MkDiscount; +import cn.xluobo.business.mk.discount.service.IMkDiscountService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 优惠配置 服务实现类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Service +public class MkDiscountServiceImpl extends ServiceImpl implements IMkDiscountService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/report/analysis/controller/AnalysisReportController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/report/analysis/controller/AnalysisReportController.java new file mode 100644 index 0000000..8bf8196 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/report/analysis/controller/AnalysisReportController.java @@ -0,0 +1,35 @@ +package cn.xluobo.business.report.analysis.controller; + +import cn.xluobo.business.report.analysis.domain.resp.RespMonthCourseOrderFee; +import cn.xluobo.business.report.analysis.service.AnalysisReportService; +import cn.xluobo.business.sc.order.domain.req.ReqReportMonthCourseIncome; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/12/24 19:12 + */ +@RestController +@RequestMapping("/api/report/analysis") +public class AnalysisReportController { + + @Autowired + private AnalysisReportService analysisReportService; + + /** + * 月份课程 营业收入报表 + * @return + */ + @GetMapping("/monthCourseOrderFeeReport") + public APIResponse monthCourseOrderFeeReport(ReqReportMonthCourseIncome reqReportMonthCourseIncome) { + List courseOrderFeeList = analysisReportService.monthCourseOrderFeeReport(reqReportMonthCourseIncome); + return APIResponse.toAPIResponse(courseOrderFeeList); + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/report/analysis/domain/resp/RespMonthCourseOrderFee.java b/ruoyi-admin/src/main/java/cn/xluobo/business/report/analysis/domain/resp/RespMonthCourseOrderFee.java new file mode 100644 index 0000000..c3fcbdd --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/report/analysis/domain/resp/RespMonthCourseOrderFee.java @@ -0,0 +1,29 @@ +package cn.xluobo.business.report.analysis.domain.resp; + +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; + +/** + * 月份课程 营业收入 + * + * @author :zhangbaoyu + * @date :Created in 2020/12/24 19:27 + */ +@Data +public class RespMonthCourseOrderFee { + + private Integer id; + + private String month; + + private Long courseId; + + private String courseName; + + private BigDecimal income; + + private List children; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/report/analysis/service/AnalysisReportService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/report/analysis/service/AnalysisReportService.java new file mode 100644 index 0000000..38608b7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/report/analysis/service/AnalysisReportService.java @@ -0,0 +1,99 @@ +package cn.xluobo.business.report.analysis.service; + +import cn.xluobo.business.report.analysis.domain.resp.RespMonthCourseOrderFee; +import cn.xluobo.business.sc.order.domain.req.ReqReportMonthCourseIncome; +import cn.xluobo.business.sc.order.domain.resp.RespReportMonthCourseIncome; +import cn.xluobo.business.sc.order.repo.mapper.OrderReportMapper; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/12/24 19:12 + */ +@Service +public class AnalysisReportService { + + @Autowired + private OrderReportMapper orderReportMapper; + + + /** + * 月份课程 营业收入报表 + * + * @return + */ + public List monthCourseOrderFeeReport(ReqReportMonthCourseIncome reqReportMonthCourseIncome) { + // 查询db 按月、课程 收入情况 + List monthCourseIncomeList = orderReportMapper.selectMonthCourseIncomeList(reqReportMonthCourseIncome); + + // 月份对应数据 + Map> monthMap = Maps.newHashMap(); + for (RespReportMonthCourseIncome respReportMonthCourseIncome : monthCourseIncomeList) { + String month = respReportMonthCourseIncome.getMonth(); + if (monthMap.containsKey(month)) { + monthMap.get(month).add(respReportMonthCourseIncome); + } else { + ArrayList incomeArrayList = Lists.newArrayList(respReportMonthCourseIncome); + monthMap.put(month, incomeArrayList); + } + } + + // 返回结果 月份下 包含各课程收入 + List courseOrderFeeList = Lists.newArrayList(); + + monthMap.forEach((month, value) -> { + + // 一个月份 各课程收入 + List childrenList = Lists.newArrayList(); + + BigDecimal totalFee = BigDecimal.ZERO; + + for (int i = 0; i < value.size(); i++) { + RespReportMonthCourseIncome respReportMonthCourseIncome = value.get(i); + totalFee = totalFee.add(respReportMonthCourseIncome.getFee()); + + RespMonthCourseOrderFee item = new RespMonthCourseOrderFee(); + item.setId(Integer.parseInt(month + (i + 1))); + item.setCourseId(respReportMonthCourseIncome.getCourseId()); + item.setCourseName(respReportMonthCourseIncome.getCourseName()); + item.setIncome(respReportMonthCourseIncome.getFee()); + + childrenList.add(item); + } + + childrenList.sort((o1, o2) -> { + BigDecimal incomeBefore = o1.getIncome(); + BigDecimal incomeAfter = o2.getIncome(); + return incomeBefore.compareTo(incomeAfter); + }); + + + // 月份 总收入 + RespMonthCourseOrderFee orderFee = new RespMonthCourseOrderFee(); + orderFee.setId(Integer.parseInt(month)); + orderFee.setMonth(month); + orderFee.setIncome(totalFee); + orderFee.setChildren(childrenList); + + // 单条记录 + courseOrderFeeList.add(orderFee); + }); + + courseOrderFeeList.sort((o1, o2) -> { + int before = Integer.parseInt(o1.getMonth()); + int after = Integer.parseInt(o2.getMonth()); + return before- after; + }); + + return courseOrderFeeList; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/report/dashboard/controller/DashboardController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/report/dashboard/controller/DashboardController.java new file mode 100644 index 0000000..77d44fe --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/report/dashboard/controller/DashboardController.java @@ -0,0 +1,32 @@ +package cn.xluobo.business.report.dashboard.controller; + +import cn.xluobo.business.report.dashboard.domain.resp.DashboardData; +import cn.xluobo.business.report.dashboard.service.DashboardService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/10/18 15:31 + */ +@RestController +@RequestMapping("/api/report/dashboard") +public class DashboardController { + + @Autowired + private DashboardService dashboardService; + + /** + * 首页各数据项 + * @return + */ + @GetMapping("/data") + public APIResponse dashboardData() { + DashboardData dashboardData = dashboardService.dashboardData(); + return APIResponse.toAPIResponse(dashboardData); + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/report/dashboard/domain/resp/DashboardData.java b/ruoyi-admin/src/main/java/cn/xluobo/business/report/dashboard/domain/resp/DashboardData.java new file mode 100644 index 0000000..efc8081 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/report/dashboard/domain/resp/DashboardData.java @@ -0,0 +1,58 @@ +package cn.xluobo.business.report.dashboard.domain.resp; + +import lombok.Builder; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/10/18 15:35 + */ +@Data +@Builder +public class DashboardData { + + // 今日排课数量 + private Integer todayClaTimeCnt; + + // 今日已上课数量 + private Integer completeTodayClaTimeCnt; + + // 今日报名 + private Integer todayOrderCnt; + + // 本月报名 + private Integer thisMonthOrderCnt; + + // 今日上课实到课人次 + private Integer todayRealAttendCnt; + + // 今日上课应到人次 + private Integer todayNeedAttendCnt; + + // 今日应消课时 + private BigDecimal todayNeedCostHour; + + // 今日实消课时 + private BigDecimal todayRealCostHour; + + // 学员数量 + private Integer studentCnt; + + // 班级数量 + private Integer claCnt; + + // 课程数量 + private Integer courseCnt; + + // 欠费学员数量 + private Integer arrearsStudentCnt; + + // 按期缴费 即将过期人数 + private Integer dateWillExpireCnt; + + // 按课时缴费 即将过期 数量 + private Integer hourWillExpireCnt; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/report/dashboard/service/DashboardService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/report/dashboard/service/DashboardService.java new file mode 100644 index 0000000..b4641d4 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/report/dashboard/service/DashboardService.java @@ -0,0 +1,91 @@ +package cn.xluobo.business.report.dashboard.service; + +import cn.xluobo.business.report.dashboard.domain.resp.DashboardData; +import cn.xluobo.business.sc.course.domain.req.time.ReqClaTimeCount; +import cn.xluobo.business.sc.course.repo.enums.ClaTimeAttendStatusEnums; +import cn.xluobo.business.sc.course.service.IScClaTimeAttendService; +import cn.xluobo.business.sc.course.service.IScClaTimeService; +import cn.xluobo.business.sc.course.service.IScCourseClaService; +import cn.xluobo.business.sc.course.service.IScCourseService; +import cn.xluobo.business.sc.order.enums.OrderTypeEnum; +import cn.xluobo.business.sc.order.service.IScOrderService; +import cn.xluobo.business.sc.student.service.IScStudentCourseService; +import cn.xluobo.business.sc.student.service.IScStudentService; +import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/10/18 15:34 + */ +@Service +@Transactional +public class DashboardService { + + @Autowired + private IScCourseClaService claService; + @Autowired + private IScCourseService courseService; + @Autowired + private IScStudentService studentService; + @Autowired + private IScClaTimeAttendService attendService; + @Autowired + private IScOrderService orderService; + @Autowired + private IScClaTimeService claTimeService; + @Autowired + private IScStudentCourseService studentCourseService; + + /** + * 首页各项数据 + * + * @return + */ + public DashboardData dashboardData() { + String todayDate = DateTime.now().toString("yyyy-MM-dd"); + String thisMonthBegin = DateTime.now().withDayOfMonth(1).toString("yyyy-MM-dd"); + String thisMonthEnd = DateTime.now().plusMonths(1).withDayOfMonth(1).minusDays(1).toString("yyyy-MM-dd"); + int claCnt = claService.count(); + int courseCnt = courseService.count(); + int studentCnt = studentService.count(); + + ReqClaTimeCount reqClaTimeCount = ReqClaTimeCount.builder().beginDate(todayDate).endDate(todayDate).hadBegin(null).build(); + Integer todayClaTimeCnt = claTimeService.claTimeCount(reqClaTimeCount); + + reqClaTimeCount.setHadBegin(true); + Integer completeTodayClaTimeCnt = claTimeService.claTimeCount(reqClaTimeCount); + + Integer todayOrderCnt = orderService.orderCount(todayDate, todayDate, OrderTypeEnum.SIGN_UP.getOrderType()); + Integer thisMonthOrderCnt = orderService.orderCount(thisMonthBegin, thisMonthEnd, OrderTypeEnum.SIGN_UP.getOrderType()); + Integer todayNeedAttendCnt = attendService.getNeedAttendCount(todayDate, todayDate); + Integer todayRealAttendCnt = attendService.getAttendCount(todayDate, todayDate, + new String[]{ClaTimeAttendStatusEnums.AT_CLASS.getAttendStatus()}); + BigDecimal todayNeedCostHour = attendService.getAttendCostHour(todayDate, todayDate, true); + BigDecimal todayRealCostHour = attendService.getAttendCostHour(todayDate, todayDate, false); + Integer arrearsStudentCnt = orderService.arrearsStudentCount(); + Integer dateWillExpireCnt = studentCourseService.getWillExpireDateCount(10); + Integer hourWillExpireCnt = studentCourseService.getWillExpireHourCount(5); + return DashboardData.builder() + .todayClaTimeCnt(todayClaTimeCnt) + .completeTodayClaTimeCnt(completeTodayClaTimeCnt) + .todayOrderCnt(todayOrderCnt) + .thisMonthOrderCnt(thisMonthOrderCnt) + .todayRealAttendCnt(todayRealAttendCnt) + .todayNeedAttendCnt(todayNeedAttendCnt) + .todayNeedCostHour(todayNeedCostHour) + .todayRealCostHour(todayRealCostHour) + .studentCnt(studentCnt) + .claCnt(claCnt) + .courseCnt(courseCnt) + .arrearsStudentCnt(arrearsStudentCnt) + .dateWillExpireCnt(dateWillExpireCnt) + .hourWillExpireCnt(hourWillExpireCnt) + .build(); + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/controller/ScRoomController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/controller/ScRoomController.java new file mode 100644 index 0000000..3f3c5d9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/controller/ScRoomController.java @@ -0,0 +1,89 @@ +package cn.xluobo.business.sc.base.controller; + +import cn.xluobo.business.sc.base.domain.req.ReqRoomSelect; +import cn.xluobo.business.sc.base.domain.req.ReqSearchScRoom; +import cn.xluobo.business.sc.base.repo.model.ScRoom; +import cn.xluobo.business.sc.base.service.BusinessScRoomService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 教室 Controller + *

+ * + * @author zhangby + * @since 2020-09-23 07:36:54 + */ +@RestController +@RequestMapping("/api/sc/room") +public class ScRoomController { + @Autowired + private BusinessScRoomService scRoomService; + + /** + * 列表 + * + * @param reqSearchScRoom + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchScRoom reqSearchScRoom) { + return scRoomService.searchList(reqSearchScRoom); + } + + /** + * 前端select + * + * @return + */ + @GetMapping("/list/select") + public APIResponse select(ReqRoomSelect roomSelect) { + return scRoomService.select(roomSelect); + } + + /** + * 详情 + * + * @param roomId + * @return + */ + @GetMapping("/info/detailById/{roomId}") + public APIResponse detailById(@PathVariable("roomId") Long roomId) { + return scRoomService.detailById(roomId); + } + + /** + * 添加 + * + * @param scRoom + * @return + */ + @PostMapping("/add/addScRoom") + public APIResponse addScRoom(@RequestBody ScRoom scRoom) { + return scRoomService.addScRoom(scRoom); + } + + /** + * 修改 + * + * @param scRoom + * @return + */ + @PutMapping("/update/updateScRoom") + public APIResponse updateScRoom(@RequestBody ScRoom scRoom) { + return scRoomService.updateScRoom(scRoom); + } + + /** + * 删除 + * + * @param roomIds + * @return + */ + @DeleteMapping("/delete/deleteById/{roomIds}") + public APIResponse deleteById(@PathVariable("roomIds") Long[] roomIds) { + return scRoomService.deleteById(roomIds); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/controller/ScSchoolController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/controller/ScSchoolController.java new file mode 100644 index 0000000..14dbc97 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/controller/ScSchoolController.java @@ -0,0 +1,89 @@ +package cn.xluobo.business.sc.base.controller; + +import cn.xluobo.business.sc.base.domain.req.ReqSchoolSelect; +import cn.xluobo.business.sc.base.domain.req.ReqSearchScSchool; +import cn.xluobo.business.sc.base.repo.model.ScSchool; +import cn.xluobo.business.sc.base.service.BusinessScSchoolService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 学校信息 Controller + *

+ * + * @author zhangby + * @since 2020-04-27 07:13:36 + */ +@RestController +@RequestMapping("/api/sc/school") +public class ScSchoolController { + @Autowired + private BusinessScSchoolService scSchoolService; + + /** + * 列表 + * + * @param reqSearchScSchool + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchScSchool reqSearchScSchool) { + return scSchoolService.searchList(reqSearchScSchool); + } + + /** + * 前端select + * + * @return + */ + @GetMapping("/list/select") + public APIResponse select(ReqSchoolSelect schoolSelect) { + return scSchoolService.select(schoolSelect); + } + + /** + * 详情 + * + * @param schoolId + * @return + */ + @GetMapping("/info/detailById/{schoolId}") + public APIResponse detailById(@PathVariable("schoolId") Long schoolId) { + return scSchoolService.detailById(schoolId); + } + + /** + * 添加 + * + * @param scSchool + * @return + */ + @PostMapping("/add/addScSchool") + public APIResponse addScSchool(@RequestBody ScSchool scSchool) { + return scSchoolService.addScSchool(scSchool); + } + + /** + * 修改 + * + * @param scSchool + * @return + */ + @PutMapping("/update/updateScSchool") + public APIResponse updateScSchool(@RequestBody ScSchool scSchool) { + return scSchoolService.updateScSchool(scSchool); + } + + /** + * 删除 + * + * @param schoolIds + * @return + */ + @DeleteMapping("/delete/deleteById/{schoolIds}") + public APIResponse deleteById(@PathVariable("schoolIds") Long[] schoolIds) { + return scSchoolService.deleteById(schoolIds); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqRoomSelect.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqRoomSelect.java new file mode 100644 index 0000000..9d6a7b1 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqRoomSelect.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sc.base.domain.req; + +import lombok.Data; + +/** + * 教室 select + * + * @author :zhangbaoyu + * @date :Created in 2020-04-27 19:41 + */ +@Data +public class ReqRoomSelect { + + private String deptId; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqSchoolSelect.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqSchoolSelect.java new file mode 100644 index 0000000..4f6e68b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqSchoolSelect.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.sc.base.domain.req; + +import lombok.Data; + +/** + * 学校 select + * + * @author :zhangbaoyu + * @date :Created in 2020-04-27 19:41 + */ +@Data +public class ReqSchoolSelect { + + private String search; + + private Integer maxRecord = 50; + + private String schoolId; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqSearchScRoom.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqSearchScRoom.java new file mode 100644 index 0000000..72d30cb --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqSearchScRoom.java @@ -0,0 +1,17 @@ +package cn.xluobo.business.sc.base.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchScRoom extends ReqPageBase implements Serializable { + private Long deptId; + private String roomName; + private String memo; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqSearchScSchool.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqSearchScSchool.java new file mode 100644 index 0000000..031e274 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/req/ReqSearchScSchool.java @@ -0,0 +1,17 @@ +package cn.xluobo.business.sc.base.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchScSchool extends ReqPageBase implements Serializable { + private String provinceCode; + private String cityCode; + private String schoolName; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/resp/RespRoomInfo.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/resp/RespRoomInfo.java new file mode 100644 index 0000000..ef62477 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/resp/RespRoomInfo.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sc.base.domain.resp; + +import cn.xluobo.business.sc.base.repo.model.ScRoom; +import lombok.Data; + +/** + * 教室信息 + * @author :zhangbaoyu + * @date :Created in 2020/9/24 09:27 + */ +@Data +public class RespRoomInfo extends ScRoom { + + private String deptName; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/resp/RespRoomSelect.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/resp/RespRoomSelect.java new file mode 100644 index 0000000..60052a9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/resp/RespRoomSelect.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.sc.base.domain.resp; + +import lombok.Data; + +/** + * 前端 教室 select + */ +@Data +public class RespRoomSelect { + + private Long roomId; + + private String roomName; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/resp/RespSchoolSelect.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/resp/RespSchoolSelect.java new file mode 100644 index 0000000..75d84ca --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/domain/resp/RespSchoolSelect.java @@ -0,0 +1,25 @@ +package cn.xluobo.business.sc.base.domain.resp; + +import lombok.Data; + +/** + * 前端 学校 select + * @author :zhangbaoyu + * @date :Created in 2020-04-27 19:30 + */ +@Data +public class RespSchoolSelect { + + private Long schoolId; + + private String schoolName; + + private String provinceCode; + + private String cityCode; + + private String provinceName; + + private String cityName; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapper/ScRoomMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapper/ScRoomMapper.java new file mode 100644 index 0000000..c037533 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapper/ScRoomMapper.java @@ -0,0 +1,40 @@ +package cn.xluobo.business.sc.base.repo.mapper; + +import cn.xluobo.business.sc.base.domain.req.ReqRoomSelect; +import cn.xluobo.business.sc.base.domain.req.ReqSearchScRoom; +import cn.xluobo.business.sc.base.domain.resp.RespRoomInfo; +import cn.xluobo.business.sc.base.domain.resp.RespRoomSelect; +import cn.xluobo.business.sc.base.repo.model.ScRoom; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 教室 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-09-23 07:36:54 + */ +public interface ScRoomMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + + + /** + * 根据条件 获取教室 + * @param reqSearchScRoom + * @param page + * @return + */ + List selectList(@Param("reqSearchScRoom")ReqSearchScRoom reqSearchScRoom, @Param("page")Page page); + + /** + * 查询 + * + * @param roomSelect + * @return + */ + List selectForSelect(ReqRoomSelect roomSelect); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapper/ScSchoolMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapper/ScSchoolMapper.java new file mode 100644 index 0000000..e813945 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapper/ScSchoolMapper.java @@ -0,0 +1,27 @@ +package cn.xluobo.business.sc.base.repo.mapper; + +import cn.xluobo.business.sc.base.domain.req.ReqSchoolSelect; +import cn.xluobo.business.sc.base.domain.resp.RespSchoolSelect; +import cn.xluobo.business.sc.base.repo.model.ScSchool; + +import java.util.List; + +/** + *

+ * 学校信息 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-04-27 07:13:36 + */ +public interface ScSchoolMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + + /** + * 查询 + * + * @param schoolSelect + * @return + */ + List selectForSelect(ReqSchoolSelect schoolSelect); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapping/ScRoomMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapping/ScRoomMapper.xml new file mode 100644 index 0000000..f7f3449 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapping/ScRoomMapper.xml @@ -0,0 +1,30 @@ + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapping/ScSchoolMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapping/ScSchoolMapper.xml new file mode 100644 index 0000000..b7ac084 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/mapping/ScSchoolMapper.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/model/ScRoom.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/model/ScRoom.java new file mode 100644 index 0000000..d6212e7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/model/ScRoom.java @@ -0,0 +1,82 @@ +package cn.xluobo.business.sc.base.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 教室 + *

+ * + * @author zhangby + * @since 2020-09-23 07:36:54 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_room") +public class ScRoom implements Serializable { + + + /** + * 教室 + */ + @TableId(value = "room_id", type = IdType.ASSIGN_ID) + private Long roomId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 所属校区 + */ + @TableField("dept_id") + private Long deptId; + + /** + * 教室名 + */ + @TableField("room_name") + private String roomName; + + /** + * 备注 + */ + @TableField("memo") + private String memo; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/model/ScSchool.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/model/ScSchool.java new file mode 100644 index 0000000..6dd84a1 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/repo/model/ScSchool.java @@ -0,0 +1,79 @@ +package cn.xluobo.business.sc.base.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 学校信息 + *

+ * + * @author zhangby + * @since 2020-04-27 07:13:36 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_school") +public class ScSchool implements Serializable { + + + /** + * 学校id + */ + @TableId(value = "school_id", type = IdType.AUTO) + private Long schoolId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 省份编码 + */ + @TableField("province_code") + private String provinceCode; + + /** + * 区号 如0431 + */ + @TableField("city_code") + private String cityCode; + + @TableField("school_name") + private String schoolName; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/BusinessScRoomService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/BusinessScRoomService.java new file mode 100644 index 0000000..4519477 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/BusinessScRoomService.java @@ -0,0 +1,142 @@ +package cn.xluobo.business.sc.base.service; + +import cn.xluobo.business.sc.base.domain.req.ReqRoomSelect; +import cn.xluobo.business.sc.base.domain.req.ReqSearchScRoom; +import cn.xluobo.business.sc.base.domain.resp.RespRoomInfo; +import cn.xluobo.business.sc.base.domain.resp.RespRoomSelect; +import cn.xluobo.business.sc.base.repo.mapper.ScRoomMapper; +import cn.xluobo.business.sc.base.repo.model.ScRoom; +import cn.xluobo.business.sc.course.repo.model.ScClaTime; +import cn.xluobo.business.sc.course.service.IScClaTimeService; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessScRoomService { + + @Autowired + private IScRoomService scRoomService; + @Autowired + private ScRoomMapper roomMapper; + @Autowired + private IScClaTimeService claTimeService; + + /** + * 查询 + * + * @param reqSearchScRoom + * @return + */ + public APIResponse searchList(ReqSearchScRoom reqSearchScRoom) { + RespPage page = new RespPage<>(reqSearchScRoom.getPageNum(), reqSearchScRoom.getPageSize()); + List roomSelectList = roomMapper.selectList(reqSearchScRoom, page); + page.setRows(roomSelectList); + return APIResponse.toAPIResponse(page); + } + + /** + * 前端select + * + * @return + */ + public APIResponse select(ReqRoomSelect roomSelect) { + List list = scRoomService.selectRoomSelect(roomSelect); + return APIResponse.toAPIResponse(list); + } + + /** + * 详情 + * + * @param roomId + * @return + */ + public APIResponse detailById(Long roomId) { + if (null == roomId) { + return APIResponse.toAPIResponse(null); + } + ScRoom detailInfo = scRoomService.getById(roomId); + return APIResponse.toAPIResponse(detailInfo); + } + + /** + * 添加 + * + * @param scRoom + * @return + */ + public APIResponse addScRoom(ScRoom scRoom) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + scRoom.setCreateUser(loginUser.getUserId()); + boolean addScRoom = scRoomService.save(scRoom); + if (addScRoom) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 更新 + * + * @param scRoom + * @return + */ + public APIResponse updateScRoom(ScRoom scRoom) { + if (null == scRoom.getRoomId()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + scRoom.setLastUpdateUser(loginUser.getUserId()); + scRoom.setLastUpdateTime(new Date()); + boolean updateScRoom = scRoomService.updateById(scRoom); + if (updateScRoom) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 删除 + * + * @param roomIds + * @return + */ + public APIResponse deleteById(Long[] roomIds) { + if (null == roomIds || roomIds.length == 0) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + + // 教室有 排课未上课 不允许删除 + QueryWrapper qw = new QueryWrapper<>(); + qw.in("room_id", roomIds); + qw.eq("status", "1"); + int unBeginClaTimeCount = claTimeService.count(qw); + if (unBeginClaTimeCount != 0) { + return APIResponse.toExceptionResponse("该教室有'"+unBeginClaTimeCount+"'待上课的排课,无法删除教室"); + } + + boolean deleteScRoom = scRoomService.removeByIds(Arrays.asList(roomIds)); + if (deleteScRoom) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/BusinessScSchoolService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/BusinessScSchoolService.java new file mode 100644 index 0000000..cf19a3b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/BusinessScSchoolService.java @@ -0,0 +1,134 @@ +package cn.xluobo.business.sc.base.service; + +import cn.xluobo.business.sc.base.domain.req.ReqSchoolSelect; +import cn.xluobo.business.sc.base.domain.req.ReqSearchScSchool; +import cn.xluobo.business.sc.base.domain.resp.RespSchoolSelect; +import cn.xluobo.business.sc.base.repo.model.ScSchool; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessScSchoolService { + + @Autowired + private IScSchoolService scSchoolService; + + /** + * 查询 + * + * @param reqSearchScSchool + * @return + */ + public APIResponse searchList(ReqSearchScSchool reqSearchScSchool) { + QueryWrapper qw = new QueryWrapper(); + if(StringUtils.isNotEmpty(reqSearchScSchool.getProvinceCode())){ + qw.eq("province_code",reqSearchScSchool.getProvinceCode()); + } + if(StringUtils.isNotEmpty(reqSearchScSchool.getCityCode())){ + qw.eq("city_code",reqSearchScSchool.getCityCode()); + } + if(StringUtils.isNotEmpty(reqSearchScSchool.getSchoolName())){ + qw.like("school_name",reqSearchScSchool.getSchoolName()); + } + RespPage page = new RespPage(reqSearchScSchool.getPageNum(), reqSearchScSchool.getPageSize()); + RespPage listPage = scSchoolService.page(page, qw); + return APIResponse.toAPIResponse(listPage); + } + + /** + * 前端select + * + * @return + */ + public APIResponse select(ReqSchoolSelect schoolSelect) { + List list = scSchoolService.selectSchoolSelect(schoolSelect); + return APIResponse.toAPIResponse(list); + } + + /** + * 详情 + * + * @param schoolId + * @return + */ + public APIResponse detailById(Long schoolId) { + if (null == schoolId) { + return APIResponse.toAPIResponse(null); + } + ScSchool detailInfo = scSchoolService.getById(schoolId); + return APIResponse.toAPIResponse(detailInfo); + } + + /** + * 添加 + * + * @param scSchool + * @return + */ + public APIResponse addScSchool(ScSchool scSchool) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + scSchool.setCreateUser(loginUser.getUserId()); + boolean addScSchool = scSchoolService.save(scSchool); + if (addScSchool) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 更新 + * + * @param scSchool + * @return + */ + public APIResponse updateScSchool(ScSchool scSchool) { + if (null == scSchool.getSchoolId()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + scSchool.setLastUpdateUser(loginUser.getUserId()); + scSchool.setLastUpdateTime(new Date()); + boolean updateScSchool = scSchoolService.updateById(scSchool); + if (updateScSchool) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 删除 + * + * @param schoolIds + * @return + */ + public APIResponse deleteById(Long[] schoolIds) { + if (null == schoolIds || schoolIds.length == 0) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + boolean deleteScSchool = scSchoolService.removeByIds(Arrays.asList(schoolIds)); + if (deleteScSchool) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/IScRoomService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/IScRoomService.java new file mode 100644 index 0000000..8caf638 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/IScRoomService.java @@ -0,0 +1,25 @@ +package cn.xluobo.business.sc.base.service; + +import cn.xluobo.business.sc.base.domain.req.ReqRoomSelect; +import cn.xluobo.business.sc.base.domain.resp.RespRoomSelect; +import cn.xluobo.business.sc.base.repo.model.ScRoom; + +import java.util.List; + +/** + *

+ * 教室 服务类 + *

+ * + * @author zhangby + * @since 2020-09-23 07:36:54 + */ +public interface IScRoomService extends com.baomidou.mybatisplus.extension.service.IService { + + /** + * 教室 select + * @param roomSelect + * @return + */ + List selectRoomSelect(ReqRoomSelect roomSelect); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/IScSchoolService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/IScSchoolService.java new file mode 100644 index 0000000..594c0f6 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/IScSchoolService.java @@ -0,0 +1,34 @@ +package cn.xluobo.business.sc.base.service; + +import cn.xluobo.business.sc.base.domain.req.ReqSchoolSelect; +import cn.xluobo.business.sc.base.domain.resp.RespSchoolSelect; +import cn.xluobo.business.sc.base.repo.model.ScSchool; + +import java.util.List; + +/** + *

+ * 学校信息 服务类 + *

+ * + * @author zhangby + * @since 2020-04-27 07:13:36 + */ +public interface IScSchoolService extends com.baomidou.mybatisplus.extension.service.IService { + + /** + * 学校select + * + * @param schoolSelect + * @return + */ + List selectSchoolSelect(ReqSchoolSelect schoolSelect); + + /** + * 根据名称获取学校,如果不存在自动保存 + * + * @param schoolName + * @return + */ + Long getSchoolId(String schoolName); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/impl/ScRoomServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/impl/ScRoomServiceImpl.java new file mode 100644 index 0000000..aa4a0bd --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/impl/ScRoomServiceImpl.java @@ -0,0 +1,28 @@ +package cn.xluobo.business.sc.base.service.impl; + +import cn.xluobo.business.sc.base.domain.req.ReqRoomSelect; +import cn.xluobo.business.sc.base.domain.resp.RespRoomSelect; +import cn.xluobo.business.sc.base.repo.mapper.ScRoomMapper; +import cn.xluobo.business.sc.base.repo.model.ScRoom; +import cn.xluobo.business.sc.base.service.IScRoomService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 教室 服务实现类 + *

+ * + * @author zhangby + * @since 2020-09-23 07:36:54 + */ +@Service +public class ScRoomServiceImpl extends ServiceImpl implements IScRoomService { + + @Override + public List selectRoomSelect(ReqRoomSelect roomSelect) { + return baseMapper.selectForSelect(roomSelect); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/impl/ScSchoolServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/impl/ScSchoolServiceImpl.java new file mode 100644 index 0000000..5316e3f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/base/service/impl/ScSchoolServiceImpl.java @@ -0,0 +1,48 @@ +package cn.xluobo.business.sc.base.service.impl; + +import cn.xluobo.business.sc.base.domain.req.ReqSchoolSelect; +import cn.xluobo.business.sc.base.domain.resp.RespSchoolSelect; +import cn.xluobo.business.sc.base.repo.mapper.ScSchoolMapper; +import cn.xluobo.business.sc.base.repo.model.ScSchool; +import cn.xluobo.business.sc.base.service.IScSchoolService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 学校信息 服务实现类 + *

+ * + * @author zhangby + * @since 2020-04-27 07:13:36 + */ +@Service +public class ScSchoolServiceImpl extends ServiceImpl implements IScSchoolService { + + @Override + public List selectSchoolSelect(ReqSchoolSelect schoolSelect) { + return baseMapper.selectForSelect(schoolSelect); + } + + @Override + public Long getSchoolId(String schoolName) { + if(StringUtils.isNotEmpty(schoolName)) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("school_name", schoolName); + List list = this.list(qw); + if(null != list && list.size() >0 ){ + return list.get(0).getSchoolId(); + } else { + ScSchool scSchool = new ScSchool(); + scSchool.setSchoolName(schoolName); + this.save(scSchool); + return scSchool.getSchoolId(); + } + } + return null; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScClaTimeAttendController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScClaTimeAttendController.java new file mode 100644 index 0000000..e219a94 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScClaTimeAttendController.java @@ -0,0 +1,91 @@ +package cn.xluobo.business.sc.course.controller; + +import cn.xluobo.business.sc.course.domain.req.time.ReqSearchScClaTimeAttend; +import cn.xluobo.business.sc.course.domain.resp.time.RespClaTimeAttend; +import cn.xluobo.business.sc.course.repo.model.ScClaTimeAttend; +import cn.xluobo.business.sc.course.service.BusinessScClaTimeAttendService; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.page.RespPage; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 上课出勤表 Controller + *

+ * + * @author zhangby + * @since 2020-09-30 02:33:26 + */ +@RestController +@RequestMapping("/api/sc/cla/time/attend") +public class ScClaTimeAttendController { + @Autowired + private BusinessScClaTimeAttendService scClaTimeAttendService; + + /** + * 列表 + * + * @param reqSearchScClaTimeAttend + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchScClaTimeAttend reqSearchScClaTimeAttend) { + RespPage respPage = scClaTimeAttendService.searchList(reqSearchScClaTimeAttend); + return APIResponse.toAPIResponse(respPage); + } + + /** + * 上课 出席详情 + * @param courseTimeId + * @return + */ + @GetMapping("/info/hadClaTimeAttendDetail/{courseTimeId}") + public APIResponse hadClaTimeAttendDetail(@PathVariable("courseTimeId") Long courseTimeId) { + return scClaTimeAttendService.hadClaTimeAttendDetail(courseTimeId); + } + + /** + * 详情 + * + * @param attendId + * @return + */ +// @GetMapping("/info/detailById/{attendId}") + public APIResponse detailById(@PathVariable("attendId") Long attendId) { + return scClaTimeAttendService.detailById(attendId); + } + + /** + * 添加 + * + * @param scClaTimeAttend + * @return + */ +// @PostMapping("/add/addScClaTimeAttend") + public APIResponse addScClaTimeAttend(@RequestBody ScClaTimeAttend scClaTimeAttend) { + return scClaTimeAttendService.addScClaTimeAttend(scClaTimeAttend); + } + + /** + * 修改 + * + * @param scClaTimeAttend + * @return + */ +// @PutMapping("/update/updateScClaTimeAttend") + public APIResponse updateScClaTimeAttend(@RequestBody ScClaTimeAttend scClaTimeAttend) { + return scClaTimeAttendService.updateScClaTimeAttend(scClaTimeAttend); + } + + /** + * 删除 + * + * @param attendIds + * @return + */ +// @DeleteMapping("/delete/deleteById/{attendIds}") + public APIResponse deleteById(@PathVariable("attendIds") Long[] attendIds) { + return scClaTimeAttendService.deleteById(attendIds); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScClaTimeController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScClaTimeController.java new file mode 100644 index 0000000..4d322a1 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScClaTimeController.java @@ -0,0 +1,125 @@ +package cn.xluobo.business.sc.course.controller; + +import cn.xluobo.business.sc.course.domain.req.time.ReqSearchClaTime; +import cn.xluobo.business.sc.course.domain.resp.time.RespBusinessClaTimeCalendar; +import cn.xluobo.business.sc.course.domain.resp.time.RespClaTime; +import cn.xluobo.business.sc.course.domain.resp.time.RespClaTimeCalendar; +import cn.xluobo.business.sc.course.repo.model.ScClaTime; +import cn.xluobo.business.sc.course.service.BusinessClaTimeService; +import cn.xluobo.business.sc.student.domain.req.ReqClaTimeAttend; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.page.RespPage; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/9/18 14:40 + */ +@RestController +@RequestMapping("/api/sc/cla/time") +public class ScClaTimeController { + + @Autowired + private BusinessClaTimeService claTimeService; + + /** + * 按周获取课表 + * + * @param reqSearchClaTime + * @return 周课表 {@link RespBusinessClaTimeCalendar} + */ + @GetMapping("/list/searchListForCalendar") + public APIResponse searchListForCalendar(ReqSearchClaTime reqSearchClaTime) { + return claTimeService.searchListForCalendar(reqSearchClaTime); + } + + /** + * 获取最近几天的排课日程 + * + * @param reqSearchClaTime + * @return + */ + @GetMapping("/list/searchRecentDayTimeList") + public APIResponse searchRecentDayTimeList(ReqSearchClaTime reqSearchClaTime) { + List respClaTimeList = claTimeService.searchRecentDayTimeList(reqSearchClaTime); + return APIResponse.toAPIResponse(respClaTimeList); + } + + /** + * 获取上课记录 + * + * @param reqSearchClaTime + * @return + */ + @GetMapping("/list/selectListForAttend") + public APIResponse selectListForAttend(ReqSearchClaTime reqSearchClaTime) { + RespPage respPage = claTimeService.selectListForAttend(reqSearchClaTime); + return APIResponse.toAPIResponse(respPage); + } + + /** + * 添加 + * + * @param scClaTime + * @return + */ + @PostMapping("/add/addScClaTime") + public APIResponse addScClaTime(@RequestBody ScClaTime scClaTime) { + return claTimeService.addClaTime(scClaTime); + } + + /** + * 详情 + * + * @param courseTimeId + * @return + */ + @GetMapping("/info/detailById/{courseTimeId}") + public APIResponse detailById(@PathVariable("courseTimeId") Long courseTimeId) { + return claTimeService.detailById(courseTimeId); + } + + /** + * 修改 + * + * @param scClaTime + * @return + */ + @PutMapping("/update/updateScClaTime") + public APIResponse updateScClaTime(@RequestBody ScClaTime scClaTime) { + return claTimeService.updateClaTime(scClaTime); + } + + /** + * 删除 + * + * @param courseTimeId + * @return + */ + @DeleteMapping("/delete/deleteById/{courseTimeId}") + public APIResponse deleteById(@PathVariable("courseTimeId") Long courseTimeId) { + return claTimeService.deleteById(courseTimeId); + } + + /** + * 变更 已记上课 信息 + * @param reqClaTimeAttend + * @return + */ + @PostMapping("/update/changeHadClaTimeAttend") + public APIResponse changeHadClaTimeAttend(@RequestBody ReqClaTimeAttend reqClaTimeAttend) { + return claTimeService.changeHadClaTimeAttend(reqClaTimeAttend); + } + + /** + * 删除 已记上课 信息 + * @return + */ + @DeleteMapping("/delete/deleteHadClaTimeAttend/{courseTimeId}") + public APIResponse deleteHadClaTimeAttend(@PathVariable("courseTimeId") Long courseTimeId) { + return claTimeService.deleteHadClaTimeAttend(courseTimeId); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScClaTimeRuleController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScClaTimeRuleController.java new file mode 100644 index 0000000..6deeb05 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScClaTimeRuleController.java @@ -0,0 +1,79 @@ +package cn.xluobo.business.sc.course.controller; + +import cn.xluobo.business.sc.course.domain.req.time.ReqSearchScClaTimeRule; +import cn.xluobo.business.sc.course.repo.model.ScClaTimeRule; +import cn.xluobo.business.sc.course.service.BusinessClaTimeRuleService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 上课时间配置规则 Controller + *

+ * + * @author zhangby + * @since 2020-09-18 04:18:54 + */ +@RestController +@RequestMapping("/api/sc/cla/time/rule") +public class ScClaTimeRuleController { + + @Autowired + private BusinessClaTimeRuleService scClaTimeRuleService; + + /** + * 列表 + * + * @param reqSearchScClaTimeRule + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchScClaTimeRule reqSearchScClaTimeRule) { + return scClaTimeRuleService.searchList(reqSearchScClaTimeRule); + } + + /** + * 详情 + * + * @param ruleId + * @return + */ + @GetMapping("/info/detailById/{ruleId}") + public APIResponse detailById(@PathVariable("ruleId") Long ruleId) { + return scClaTimeRuleService.detailById(ruleId); + } + + /** + * 添加 + * + * @param scClaTimeRule + * @return + */ + @PostMapping("/add/addScClaTimeRule") + public APIResponse addScClaTimeRule(@RequestBody ScClaTimeRule scClaTimeRule) { + return scClaTimeRuleService.addClaTimeRule(scClaTimeRule); + } + + /** + * 修改 + * + * @param scClaTimeRule + * @return + */ + @PutMapping("/update/updateScClaTimeRule") + public APIResponse updateScClaTimeRule(@RequestBody ScClaTimeRule scClaTimeRule) { + return scClaTimeRuleService.updateClaTimeRule(scClaTimeRule); + } + + /** + * 删除 + * + * @param ruleId + * @return + */ + @DeleteMapping("/delete/deleteById/{ruleId}") + public APIResponse deleteById(@PathVariable("ruleId") Long ruleId) { + return scClaTimeRuleService.deleteById(ruleId); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScCourseClaController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScCourseClaController.java new file mode 100644 index 0000000..2c5cfd2 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScCourseClaController.java @@ -0,0 +1,94 @@ +package cn.xluobo.business.sc.course.controller; + +import cn.xluobo.business.sc.course.domain.req.ReqAddScCourseCla; +import cn.xluobo.business.sc.course.domain.req.ReqSearchScCourseCla; +import cn.xluobo.business.sc.course.domain.resp.cla.RespClaAllDetailInfo; +import cn.xluobo.business.sc.course.repo.model.ScCourseCla; +import cn.xluobo.business.sc.course.service.BusinessScCourseClaService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 课程班级信息 Controller + *

+ * + * @author zhangby + * @since 2020-03-17 01:11:06 + */ +@RestController +@RequestMapping("/api/sc/course/cla") +public class ScCourseClaController { + @Autowired + private BusinessScCourseClaService scCourseClaService; + + /** + * 列表 + * + * @param reqSearchScCourseCla + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchScCourseCla reqSearchScCourseCla) { + return scCourseClaService.searchList(reqSearchScCourseCla); + } + + /** + * 详情 + * + * @param claId + * @return + */ + @GetMapping("/info/detailById/{claId}") + public APIResponse detailById(@PathVariable("claId") Long claId) { + return scCourseClaService.detailById(claId); + } + + /** + * 详情 + * 包含内容较多 + * + * @param claId + * @return + */ + @GetMapping("/info/allDetailInfoById/{claId}") + public APIResponse allDetailInfoById(@PathVariable("claId") Long claId) { + RespClaAllDetailInfo allDetailInfo = scCourseClaService.allDetailInfoById(claId); + return APIResponse.toAPIResponse(allDetailInfo); + } + + /** + * 添加 + * + * @param scCourseCla + * @return + */ + @PostMapping("/add/addScCourseCla") + public APIResponse addScCourseCla(@RequestBody ReqAddScCourseCla scCourseCla) { + return scCourseClaService.addScCourseCla(scCourseCla); + } + + /** + * 修改 + * + * @param scCourseCla + * @return + */ + @PutMapping("/update/updateScCourseCla") + public APIResponse updateScCourseCla(@RequestBody ScCourseCla scCourseCla) { + return scCourseClaService.updateScCourseCla(scCourseCla); + } + + /** + * 删除 + * + * @param claIds + * @return + */ + @DeleteMapping("/delete/deleteById/{claIds}") + public APIResponse deleteById(@PathVariable("claIds") Long[] claIds) { + return scCourseClaService.deleteById(claIds); + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScCourseController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScCourseController.java new file mode 100644 index 0000000..9130f6f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScCourseController.java @@ -0,0 +1,155 @@ +package cn.xluobo.business.sc.course.controller; + +import cn.xluobo.business.sc.course.domain.req.ReqBusinessOrderCourseDetail; +import cn.xluobo.business.sc.course.domain.req.ReqSearchScCourse; +import cn.xluobo.business.sc.course.domain.req.ReqSelect; +import cn.xluobo.business.sc.course.domain.req.course.ReqAddScCourse; +import cn.xluobo.business.sc.course.domain.req.course.ReqChangeScCourse; +import cn.xluobo.business.sc.course.repo.model.ScCourse; +import cn.xluobo.business.sc.course.service.BusinessScCourseService; +import cn.xluobo.business.sc.course.service.IScCourseService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + *

+ * 课程信息 Controller + *

+ * + * @author zhangby + * @since 2020-03-17 11:25:55 + */ +@RestController +@RequestMapping("/api/sc/course") +public class ScCourseController { + + @Autowired + private BusinessScCourseService scCourseService; + + @Autowired + private IScCourseService courseService; + + /** + * 列表 + * + * @param reqSearchScCourse + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchScCourse reqSearchScCourse) { + return scCourseService.searchList(reqSearchScCourse); + } + + /** + * 查询课程列表 + * 含有学生报读状态 + * + * @param reqSearchScCourse + * @return + */ + @GetMapping("/list/selectCourseListWithStudentCourse") + public APIResponse selectCourseListWithStudentCourse(ReqSearchScCourse reqSearchScCourse) { + return scCourseService.selectCourseListWithStudentCourse(reqSearchScCourse); + } + + /** + * 前端select + * + * @return + */ + @GetMapping("/list/select") + public APIResponse select(ReqSelect reqSelect) { + return scCourseService.select(reqSelect); + } + + /** + * 详情 + * + * @param courseId + * @return + */ + @GetMapping("/info/detailById/{courseId}") + public APIResponse detailById(@PathVariable("courseId") Long courseId) { + return scCourseService.detailById(courseId); + } + + /** + * 添加 + * + * @param reqAddScCourse + * @return + */ + @PostMapping("/add/addScCourse") + public APIResponse addScCourse(@RequestBody ReqAddScCourse reqAddScCourse) { + return scCourseService.addScCourse(reqAddScCourse); + } + + /** + * 修改 + * + * @param reqChangeScCourse + * @return + */ + @PutMapping("/update/updateScCourse") + public APIResponse updateScCourse(@RequestBody ReqChangeScCourse reqChangeScCourse) { + return scCourseService.updateScCourse(reqChangeScCourse); + } + + /** + * 删除 + * + * @param courseIds + * @return + */ + @DeleteMapping("/delete/deleteById/{courseIds}") + public APIResponse deleteById(@PathVariable("courseIds") List courseIds) { + return scCourseService.deleteById(courseIds); + } + + /** + * 变更是否开售 + * + * @param scCourse + * @return + */ + @PutMapping("/update/changeCourseSale") + public APIResponse changeCourseSale(@RequestBody ScCourse scCourse) { + return scCourseService.changeCourseSale(scCourse); + } + + /** + * 导出 + * + * @param reqSearchScCourse + */ + @GetMapping("/export/exportCourse") + public APIResponse exportCourse(ReqSearchScCourse reqSearchScCourse) { + return scCourseService.exportCourse(reqSearchScCourse); + } + + /** + * 课程详情 + * 报名选择课程后获取课程详情 + * + * @param orderCourseDetail + * @return + */ + @GetMapping("/info/orderCourseDetail") + public APIResponse orderCourseDetail(ReqBusinessOrderCourseDetail orderCourseDetail) { + return scCourseService.orderCourseDetail(orderCourseDetail); + } + + /** + * 学生是否可报读课程 + * + * @param orderCourseDetail + * @return + */ + @GetMapping("/info/studentCanSignUpCourse") + public APIResponse studentCanSignUpCourse(ReqBusinessOrderCourseDetail orderCourseDetail) { + return scCourseService.studentCanSignUpCourse(orderCourseDetail); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScCourseTypeController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScCourseTypeController.java new file mode 100644 index 0000000..c360953 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/controller/ScCourseTypeController.java @@ -0,0 +1,89 @@ +package cn.xluobo.business.sc.course.controller; + +import cn.xluobo.business.sc.course.domain.req.ReqSearchScCourseType; +import cn.xluobo.business.sc.course.repo.model.ScCourseType; +import cn.xluobo.business.sc.course.service.BusinessScCourseTypeService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 课程类型 Controller + *

+ * + * @author zhangby + * @since 2020-07-09 08:10:25 + */ +@RestController +@RequestMapping("/api/sc/course/type") +public class ScCourseTypeController { + @Autowired + private BusinessScCourseTypeService scCourseTypeService; + + /** + * 列表 + * + * @param reqSearchScCourseType + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchScCourseType reqSearchScCourseType) { + return scCourseTypeService.searchList(reqSearchScCourseType); + } + + /** + * select + * + * @param reqSearchScCourseType + * @return + */ + @GetMapping("/list/select") + public APIResponse select(ReqSearchScCourseType reqSearchScCourseType) { + return scCourseTypeService.select(reqSearchScCourseType); + } + + /** + * 详情 + * + * @param courseTypeId + * @return + */ + @GetMapping("/info/detailById/{courseTypeId}") + public APIResponse detailById(@PathVariable("courseTypeId") Long courseTypeId) { + return scCourseTypeService.detailById(courseTypeId); + } + + /** + * 添加 + * + * @param scCourseType + * @return + */ + @PostMapping("/add/addScCourseType") + public APIResponse addScCourseType(@RequestBody ScCourseType scCourseType) { + return scCourseTypeService.addScCourseType(scCourseType); + } + + /** + * 修改 + * + * @param scCourseType + * @return + */ + @PutMapping("/update/updateScCourseType") + public APIResponse updateScCourseType(@RequestBody ScCourseType scCourseType) { + return scCourseTypeService.updateScCourseType(scCourseType); + } + + /** + * 删除 + * + * @param courseTypeIds + * @return + */ + @DeleteMapping("/delete/deleteById/{courseTypeIds}") + public APIResponse deleteById(@PathVariable("courseTypeIds") Long[] courseTypeIds) { + return scCourseTypeService.deleteById(courseTypeIds); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/export/ExpCourse.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/export/ExpCourse.java new file mode 100644 index 0000000..4605887 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/export/ExpCourse.java @@ -0,0 +1,66 @@ +package cn.xluobo.business.sc.course.domain.export; + +import cn.xluobo.business.tool.export.domain.ExportBaseBean; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 导出课程 + * @author :zhangbaoyu + * @date :Created in 2020/7/29 11:18 + */ +@Data +@ExcelIgnoreUnannotated +public class ExpCourse extends ExportBaseBean { + + private Long courseId; + private Long chargeId; + + @ExcelProperty("课程名称") + private String courseName; + + @ExcelProperty("课程类型") + private String courseTypeName; + + @ExcelProperty("授课模式") + private String teachingMode; + + @ExcelProperty("开班数") + private Integer claCount; + + @ExcelProperty("创建时间") + private Date createTime; + + @ExcelProperty("课程状态") + private String sale; + + @ExcelProperty("课程简介") + private String courseIntro; + + @ExcelProperty("开课校区") + private String departName; + + @ExcelProperty("收费模式") + private String chargeTypeName; + + private String chargeType; + private String dateUnit; + + @ExcelProperty("时间周期") + private String dateUnitName; + + @ExcelProperty("数量") + private BigDecimal count; + + @ExcelProperty("总价") + private BigDecimal totalFee; + + @Override + public String getPrimaryId() { + return String.valueOf(courseId); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/export/ExpCourseCharge.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/export/ExpCourseCharge.java new file mode 100644 index 0000000..9c8a695 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/export/ExpCourseCharge.java @@ -0,0 +1,12 @@ +package cn.xluobo.business.sc.course.domain.export; + +import lombok.Data; + +/** + * 课程收费模式 + * @author :zhangbaoyu + * @date :Created in 2020/7/29 11:26 + */ +@Data +public class ExpCourseCharge { +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqAddScCourseCla.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqAddScCourseCla.java new file mode 100644 index 0000000..4ccda8b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqAddScCourseCla.java @@ -0,0 +1,63 @@ +package cn.xluobo.business.sc.course.domain.req; + +import cn.xluobo.business.sc.course.repo.model.ScCourseCla; +import com.ruoyi.common.core.domain.model.LoginUser; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 新增课程 + * + * @author :zhangbaoyu + * @date :Created in 2020-03-23 13:53 + */ +@Data +public class ReqAddScCourseCla { + + private Long courseId; + + private Long departId; + + private Long staffId; + + private String claName; + + private String claColor; + + private Integer capacity; + + private String recruitStatus; + + private BigDecimal everyStuLoseHour; + + private String openDate; + + private String closeDate; + + private String memo; + + /** + * 获取班级实体 + * + * @param loginUser + * @return + */ + public ScCourseCla getScCourseCla(LoginUser loginUser) { + ScCourseCla cla = new ScCourseCla(); + cla.setCourseId(courseId); + cla.setDepartId(departId); + cla.setStaffId(staffId); + cla.setClaName(claName); + cla.setClaColor(claColor); + cla.setCapacity(capacity); + cla.setRecruitStatus(recruitStatus); + cla.setEveryStuLoseHour(everyStuLoseHour); + cla.setEveryTeaGetHour(everyStuLoseHour); + cla.setOpenDate(openDate); + cla.setCloseDate(closeDate); + cla.setMemo(memo); + cla.setCreateUser(loginUser.getUserId()); + return cla; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessAddClaStu.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessAddClaStu.java new file mode 100644 index 0000000..76b4528 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessAddClaStu.java @@ -0,0 +1,18 @@ +package cn.xluobo.business.sc.course.domain.req; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 班级新增学生 + * @author :zhangbaoyu + * @date :Created in 2020-04-28 19:08 + */ +@Data +public class ReqBusinessAddClaStu implements Serializable { + + private Long claId; + + private Long[] studentIds; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessAddStuCla.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessAddStuCla.java new file mode 100644 index 0000000..0645fd8 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessAddStuCla.java @@ -0,0 +1,18 @@ +package cn.xluobo.business.sc.course.domain.req; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 学生新学课程 + * @author :zhangbaoyu + * @date :Created in 2020-06-21 10:08 + */ +@Data +public class ReqBusinessAddStuCla implements Serializable { + + private Long[] claIds; + + private Long studentId; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessClaBegin.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessClaBegin.java new file mode 100644 index 0000000..51e42b3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessClaBegin.java @@ -0,0 +1,72 @@ +package cn.xluobo.business.sc.course.domain.req; + +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 上课请求参数 + * @author :zhangbaoyu + * @date :Created in 2020/6/8 10:44 + */ +@Data +public class ReqBusinessClaBegin implements Serializable { + + private Long courseTimeId; + + private Long[] studentIds; + + /** + * 实际上课时间 + */ + private String startTime; + + /** + * 实际结束时间 + */ + private String endTime; + + /** + * 其他说明 + */ + private String memo; + + /** + * 消耗课时数量 + */ + private BigDecimal payHourCount; + + /** + * 上课时课程 参数校验 + * @return + */ + public boolean checkParamForHour(){ + if(null == courseTimeId || null == studentIds || studentIds.length == 0){ + return false; + } + if(StringUtils.isAnyEmpty(startTime,endTime)){ + return false; + } + if(null == payHourCount || "0".equals(payHourCount.toString())){ + return false; + } + return true; + } + + /** + * 上周期课程 参数校验 + * @return + */ + public boolean checkParamForDate(){ + if(null == courseTimeId || null == studentIds || studentIds.length == 0){ + return false; + } + if(StringUtils.isAnyEmpty(startTime,endTime)){ + return false; + } + return true; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessOrderCourseDetail.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessOrderCourseDetail.java new file mode 100644 index 0000000..4becc7a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqBusinessOrderCourseDetail.java @@ -0,0 +1,18 @@ +package cn.xluobo.business.sc.course.domain.req; + +import lombok.Data; + +/** + * 报名时 获取课程详情 + * @author :zhangbaoyu + * @date :Created in 2020/9/3 11:08 + */ +@Data +public class ReqBusinessOrderCourseDetail { + + private Long studentId; + + private Long[] courseIds; + + private Long deptId; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqCourseClaSelect.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqCourseClaSelect.java new file mode 100644 index 0000000..5f08acf --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqCourseClaSelect.java @@ -0,0 +1,18 @@ +package cn.xluobo.business.sc.course.domain.req; + +import lombok.Data; + +/** + * 课程班级 select + * + * @author :zhangbaoyu + * @date :Created in 2020-04-27 19:41 + */ +@Data +public class ReqCourseClaSelect { + + private String search; + + private Integer maxRecord = 500; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSearchScCourse.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSearchScCourse.java new file mode 100644 index 0000000..f313e39 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSearchScCourse.java @@ -0,0 +1,47 @@ +package cn.xluobo.business.sc.course.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * 查询课程请求参数 + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchScCourse extends ReqPageBase implements Serializable { + + private String courseName; + + /** + * 是否开售 + */ + private String sale; + + /** + * 教学模式 + */ + private String teachingMode; + + /** + * 课程类型 + */ + private String courseTypeId; + + /** + * 上课校区 + */ + private Long departId; + + /** + * 收费模式 + */ + private String chargeType; + + /** + * 学生 区分结果是否为续费 + */ + private Long studentId; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSearchScCourseCla.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSearchScCourseCla.java new file mode 100644 index 0000000..8f1635d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSearchScCourseCla.java @@ -0,0 +1,23 @@ +package cn.xluobo.business.sc.course.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchScCourseCla extends ReqPageBase implements Serializable { + private Long courseId; + private Long staffId; + private String claName; + private String courseTime; + private Long departId; + /** + * 收费模式 + */ + private String chargeType; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSearchScCourseType.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSearchScCourseType.java new file mode 100644 index 0000000..a3f6c7e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSearchScCourseType.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.sc.course.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchScCourseType extends ReqPageBase implements Serializable { + private String courseType; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSelect.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSelect.java new file mode 100644 index 0000000..41401a9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/ReqSelect.java @@ -0,0 +1,32 @@ +package cn.xluobo.business.sc.course.domain.req; + +import lombok.Data; + +/** + * 前端 select + * + * @author :zhangbaoyu + * @date :Created in 2020-04-27 19:41 + */ +@Data +public class ReqSelect { + + private String search; + + private Integer maxRecord = 50; + + // 是否可分页 + private boolean pageable; + + private long pageNum = 1; + + private long pageSize = 10; + + public long getPageSize() { + if (pageable) { + return pageSize; + } else { + return maxRecord; + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/cla/ReqClaCount.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/cla/ReqClaCount.java new file mode 100644 index 0000000..cd98a5e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/cla/ReqClaCount.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sc.course.domain.req.cla; + +import cn.xluobo.core.page.ReqDeptCondition; +import lombok.Builder; +import lombok.Data; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/10/24 12:27 + */ +@Data +@Builder +public class ReqClaCount extends ReqDeptCondition { + + private Long teacherId; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/course/ReqAddScCourse.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/course/ReqAddScCourse.java new file mode 100644 index 0000000..49b1a41 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/course/ReqAddScCourse.java @@ -0,0 +1,155 @@ +package cn.xluobo.business.sc.course.domain.req.course; + +import cn.xluobo.core.api.APIBaseResponse; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +import java.math.BigDecimal; +import java.util.List; + +/** + * 录入课程 + * + * @author :zhangbaoyu + * @date :Created in 2020/7/8 20:34 + */ +@Data +public class ReqAddScCourse { + + /** + * 课程名 + */ + private String courseName; + + /** + * 课程类型 + */ + private Long courseTypeId; + + /** + * 教学模式 + */ + private String teachingMode; + + /** + * 课程简介 + */ + private String courseIntro; + + /** + * 上课校区 所有 或 部分 all part + */ + private String courseCampus; + + /** + * 上课校区 + */ + private String[] partCampus; + + /** + * 收费模式 + */ + private boolean feeModeHour; + + /** + * 收费模式 + */ + private boolean feeModeDate; + + /** + * 收费模式 + */ + private boolean feeModeCycle; + + private List feeModeHourList; + + private List feeModeDateList; + + private List feeModeCycleList; + + /** + * 参数校验 + * + * @return + */ + public APIBaseResponse checkParam() { + if (StringUtils.isEmpty(courseName)) { + return APIBaseResponse.fail("请输入课程名称"); + } else if (StringUtils.isEmpty(teachingMode)) { + return APIBaseResponse.fail("请选择教学模式"); + } + + if (StringUtils.isEmpty(courseCampus)) { + return APIBaseResponse.fail("请选择上课校区"); + } + if ("part".equals(courseCampus) && null == partCampus) { + return APIBaseResponse.fail("请选择上课校区"); + } + if ("part".equals(courseCampus) && partCampus.length == 0) { + return APIBaseResponse.fail("请选择上课校区"); + } + + if (!feeModeHour && !feeModeDate && !feeModeCycle) { + return APIBaseResponse.fail("请配置收费模式"); + } + + if (feeModeHour && (null == feeModeHourList || feeModeHourList.isEmpty())) { + return APIBaseResponse.fail("请配置课时收费模式"); + } + if (feeModeDate && (null == feeModeDateList || feeModeDateList.isEmpty())) { + return APIBaseResponse.fail("请配置时间收费模式"); + } + if (feeModeCycle && (null == feeModeCycleList || feeModeCycleList.isEmpty())) { + return APIBaseResponse.fail("请配置周期收费模式"); + } + + BigDecimal zero = BigDecimal.ZERO; + if (feeModeHour) { + for (ReqAddScCourseChargeItem item : feeModeHourList) { + BigDecimal cnt = item.getCnt(); + BigDecimal totalFee = item.getTotalFee(); + String campusName = item.getCampusName(); + if(null == cnt || cnt.compareTo(zero)==0){ + return APIBaseResponse.fail("请填写"+campusName+"按课时收费 数量"); + } + if(null == totalFee || totalFee.compareTo(zero)==0){ + return APIBaseResponse.fail("请填写"+campusName+"按课时收费 金额"); + } + } + } + + if (feeModeDate) { + for (ReqAddScCourseChargeItem item : feeModeDateList) { + BigDecimal cnt = item.getCnt(); + BigDecimal totalFee = item.getTotalFee(); + String dateType = item.getDateType(); + String campusName = item.getCampusName(); + if(null == cnt || cnt.compareTo(zero)==0){ + return APIBaseResponse.fail("请填写"+campusName+"按时间收费 数量"); + } + if(null == totalFee || totalFee.compareTo(zero)==0){ + return APIBaseResponse.fail("请填写"+campusName+"按时间收费 金额"); + } + if(StringUtils.isEmpty(dateType)){ + return APIBaseResponse.fail("请填写"+campusName+"按时间收费 时间段"); + } + } + } + + if(feeModeCycle) { + for (ReqAddScCourseChargeItem item : feeModeCycleList) { + BigDecimal cnt = item.getCnt(); + BigDecimal totalFee = item.getTotalFee(); + String campusName = item.getCampusName(); + if(null == cnt || cnt.compareTo(zero)==0){ + return APIBaseResponse.fail("请填写"+campusName+"按期收费 数量"); + } + if(null == totalFee || totalFee.compareTo(zero)==0){ + return APIBaseResponse.fail("请填写"+campusName+"按期收费 金额"); + } + } + } + + return APIBaseResponse.success(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/course/ReqAddScCourseChargeItem.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/course/ReqAddScCourseChargeItem.java new file mode 100644 index 0000000..d47edea --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/course/ReqAddScCourseChargeItem.java @@ -0,0 +1,42 @@ +package cn.xluobo.business.sc.course.domain.req.course; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 课程收费模式 + * @author :zhangbaoyu + * @date :Created in 2020/7/23 11:07 + */ +@Data +public class ReqAddScCourseChargeItem { + + private Long chargeId; + + /** + * 校区id + */ + private Long campusId; + + /** + * 校区名称 + */ + private String campusName; + + /** + * 数量 + */ + private BigDecimal cnt; + + /** + * 总价格 + */ + private BigDecimal totalFee; + + /** + * 时间段 日 月 季 年 + */ + private String dateType; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/course/ReqChangeScCourse.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/course/ReqChangeScCourse.java new file mode 100644 index 0000000..2e0f258 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/course/ReqChangeScCourse.java @@ -0,0 +1,28 @@ +package cn.xluobo.business.sc.course.domain.req.course; + +import cn.xluobo.core.api.APIBaseResponse; +import lombok.Data; + +/** + * 修改课程 + * + * @author :zhangbaoyu + * @date :Created in 2020/7/8 20:34 + */ +@Data +public class ReqChangeScCourse extends ReqAddScCourse{ + + private Long courseId; + + public APIBaseResponse checkParam() { + APIBaseResponse checkParam = super.checkParam(); + if(!checkParam.isSuccess()){ + return checkParam; + } + if(null == courseId){ + return APIBaseResponse.fail("请求参数错误,请稍后重试"); + } + return APIBaseResponse.success(); + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqClaTimeCount.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqClaTimeCount.java new file mode 100644 index 0000000..535232e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqClaTimeCount.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.sc.course.domain.req.time; + +import cn.xluobo.core.page.ReqDeptCondition; +import lombok.Builder; +import lombok.Data; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/10/24 12:21 + */ +@Data +@Builder +public class ReqClaTimeCount extends ReqDeptCondition { + + private String beginDate; + private String endDate; + private Boolean hadBegin; + private Long teacherId; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqSearchClaTime.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqSearchClaTime.java new file mode 100644 index 0000000..de7774e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqSearchClaTime.java @@ -0,0 +1,69 @@ +package cn.xluobo.business.sc.course.domain.req.time; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; +import org.joda.time.DateTime; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/9/18 14:45 + */ +@Data +public class ReqSearchClaTime extends ReqPageBase implements Serializable { + + // 排课 编号 + private Long courseTimeId; + + // 课程 + private Long courseId; + + // 校区 + private Long deptId; + + // 当前登录用户 + private String userId; + + // 班级 + private Long claId; + + // 学生 + private Long studentId; + + private Long teacherId; + + // 开始时间 + private String beginDate; + + // 结束时间 + private String endDate; + + /** + * 与今天相隔几天 + * 如果设置了,将重置 beginDate、endDate + */ + private Integer diffNowDay; + + /** + * 是否已上课 + * true 已上课 + * false 未上课 + */ + private Boolean attended; + + /** + * 排序类型 + * claTimeAttend + */ + private String orderByType; + + public void setDiffNowDay(Integer diffNowDay) { + this.diffNowDay = diffNowDay; + if(null != diffNowDay) { + DateTime now = DateTime.now(); + this.beginDate = now.minusDays(diffNowDay).toString("yyyy-MM-dd"); + this.endDate = now.plusDays(diffNowDay).toString("yyyy-MM-dd"); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqSearchScClaTimeAttend.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqSearchScClaTimeAttend.java new file mode 100644 index 0000000..f9beb34 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqSearchScClaTimeAttend.java @@ -0,0 +1,27 @@ +package cn.xluobo.business.sc.course.domain.req.time; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchScClaTimeAttend extends ReqPageBase implements Serializable { + + private Long courseTimeId; + +// private String chargeType; + private String attendStatus; + + private Long studentCourseId; + + private Long studentId; + + private Long teacherId; + + private String tenantId; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqSearchScClaTimeRule.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqSearchScClaTimeRule.java new file mode 100644 index 0000000..8a1810d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/req/time/ReqSearchScClaTimeRule.java @@ -0,0 +1,30 @@ +package cn.xluobo.business.sc.course.domain.req.time; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchScClaTimeRule extends ReqPageBase implements Serializable { + private Long deptId; + private Long claId; + private Long teacherId; + private String[] claDate; + private Boolean filterHoliday; + private String beginDate; + private String endDate; + + public void setClaDate(String[] claDate) { + this.claDate = claDate; + if (null != claDate && claDate.length == 2 && StringUtils.isAnyEmpty(beginDate, endDate)) { + this.beginDate = claDate[0]; + this.endDate = claDate[1]; + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessChooseCourseCharge.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessChooseCourseCharge.java new file mode 100644 index 0000000..dc2b2cc --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessChooseCourseCharge.java @@ -0,0 +1,38 @@ +package cn.xluobo.business.sc.course.domain.resp; + +import lombok.Builder; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 选择课程的可选 收费模式 + * + * @author :zhangbaoyu + * @date :Created in 2020/8/26 17:16 + */ +@Data +@Builder +public class RespBusinessChooseCourseCharge { + + private Long chargeId; + + /** + * 单个金额 + */ + private BigDecimal totalFee; + + /** + * select label + */ + private String label; + + // 收费类型 + private String chargeType; + + // 数量 + private BigDecimal count; + + // 按时间 时间单位 + private String dateUnit; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessChooseCourseInfo.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessChooseCourseInfo.java new file mode 100644 index 0000000..efe396d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessChooseCourseInfo.java @@ -0,0 +1,33 @@ +package cn.xluobo.business.sc.course.domain.resp; + +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +/** + * 选择课程信息 + * + * @author :zhangbaoyu + * @date :Created in 2020/8/26 17:01 + */ +@Data +@Builder +public class RespBusinessChooseCourseInfo { + + private Long courseId; + + private String courseName; + + private Long deptId; + + private String deptName; + + private String teachingMode; + + private List courseChargeList; + + // 续报 + private Boolean continueCourse; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessCla.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessCla.java new file mode 100644 index 0000000..1cddf07 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessCla.java @@ -0,0 +1,32 @@ +package cn.xluobo.business.sc.course.domain.resp; + +import lombok.Data; + +import java.io.Serializable; + +/** + *

+ * 班级 + *

+ * + * @author zhangby + * @since 2020-06-21 07:13:40 + */ +@Data +public class RespBusinessCla implements Serializable { + + private Long claId; + + private String claName; + + private String chargeName; + + public RespBusinessCla(Long claId, String claName, String chargeName) { + this.claId = claId; + this.claName = claName; + this.chargeName = chargeName; + } + + public RespBusinessCla() { + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessClaInfo.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessClaInfo.java new file mode 100644 index 0000000..30cd5d3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessClaInfo.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.sc.course.domain.resp; + +import lombok.Builder; +import lombok.Data; + +/** + * 业务返回 班级信息 + * @author :zhangbaoyu + * @date :Created in 2020-04-03 14:15 + */ +@Data +@Builder +public class RespBusinessClaInfo { + + private Long claId; + private String claColor; + private String claName; + private String teacherName; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessClaStudent.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessClaStudent.java new file mode 100644 index 0000000..d81d71f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessClaStudent.java @@ -0,0 +1,45 @@ +package cn.xluobo.business.sc.course.domain.resp; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 班级学生 + *

+ * + * @author zhangby + * @since 2020-04-27 07:13:40 + */ +@Data +public class RespBusinessClaStudent implements Serializable { + + /** + * 全部可选学生 + */ + private List students; + + /** + * 已有学生 + */ + private List claStudentIds; + + /** + * 班级信息 + */ + private RespBusinessClaInfo claInfo; + + /** + * 课程信息 + */ + private RespBusinessCourseInfo courseInfo; + + public RespBusinessClaStudent(List students, List claStudentIds, RespBusinessClaInfo claInfo, RespBusinessCourseInfo courseInfo) { + this.students = students; + this.claStudentIds = claStudentIds; + this.claInfo = claInfo; + this.courseInfo = courseInfo; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessCourseInfo.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessCourseInfo.java new file mode 100644 index 0000000..77a2a81 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessCourseInfo.java @@ -0,0 +1,18 @@ +package cn.xluobo.business.sc.course.domain.resp; + +import lombok.Builder; +import lombok.Data; + +/** + * 业务返回 课程信息 + * @author :zhangbaoyu + * @date :Created in 2020-04-03 14:15 + */ +@Data +@Builder +public class RespBusinessCourseInfo { + + private Long courseId; + + private String courseName; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessStudent.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessStudent.java new file mode 100644 index 0000000..aebce5c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessStudent.java @@ -0,0 +1,30 @@ +package cn.xluobo.business.sc.course.domain.resp; + +import lombok.Data; + +import java.io.Serializable; + +/** + *

+ * 班级学生 + *

+ * + * @author zhangby + * @since 2020-04-27 07:13:40 + */ +@Data +public class RespBusinessStudent implements Serializable { + + private Long studentId; + + private String studentName; + + public RespBusinessStudent(Long studentId) { + this.studentId = studentId; + } + + public RespBusinessStudent(Long studentId, String studentName) { + this.studentId = studentId; + this.studentName = studentName; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessStudentCla.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessStudentCla.java new file mode 100644 index 0000000..dd9c9d3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespBusinessStudentCla.java @@ -0,0 +1,41 @@ +package cn.xluobo.business.sc.course.domain.resp; + +import cn.xluobo.business.sc.student.repo.model.ScStudent; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 学生班级 + *

+ * + * @author zhangby + * @since 2020-06-21 07:13:40 + */ +@Data +public class RespBusinessStudentCla implements Serializable { + + /** + * 全部可选班级 + */ + private List claInfoList; + + /** + * 已有课程 + */ + private List claIds; + + /** + * 班级信息 + */ + private ScStudent student; + + + public RespBusinessStudentCla(List claInfoList, List claIds, ScStudent student) { + this.claInfoList = claInfoList; + this.claIds = claIds; + this.student = student; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespCourseClaInfo.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespCourseClaInfo.java new file mode 100644 index 0000000..a75fd6f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespCourseClaInfo.java @@ -0,0 +1,40 @@ +package cn.xluobo.business.sc.course.domain.resp; + +import lombok.Data; + +/** + * 班级列表信息 + * @author :zhangbaoyu + * @date :Created in 2020-03-23 19:36 + */ +@Data +public class RespCourseClaInfo { + + private Long claId; + + private String claName; + + // 当前人数 + private Integer studentCnt; + + // 满班人数 + private String capacity; + + private String recruitStatus; + + private String openDate; + + private Long courseId; + + private String courseName; + + private Long staffId; + + private String staffName; + + private String deptName; + + // 上课星期 + private String weekDay; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespCourseClaSelectInfo.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespCourseClaSelectInfo.java new file mode 100644 index 0000000..5637f65 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/RespCourseClaSelectInfo.java @@ -0,0 +1,27 @@ +package cn.xluobo.business.sc.course.domain.resp; + +import lombok.Data; + +/** + * 班级 select + * @author :zhangbaoyu + * @date :Created in 2020/5/6 13:11 + */ +@Data +public class RespCourseClaSelectInfo { + + private Long claId; + + private String claName; + + private Long courseId; + + private String courseName; + + private String staffName; + + private Long deptId; + + private String deptName; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/cla/RespClaAllDetailInfo.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/cla/RespClaAllDetailInfo.java new file mode 100644 index 0000000..f5ce0b8 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/cla/RespClaAllDetailInfo.java @@ -0,0 +1,31 @@ +package cn.xluobo.business.sc.course.domain.resp.cla; + +import cn.xluobo.business.sc.course.domain.resp.RespBusinessChooseCourseCharge; +import cn.xluobo.business.sc.course.repo.model.ScCourse; +import cn.xluobo.business.sc.course.repo.model.ScCourseCla; +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +/** + * 班级详情 + * @author :zhangbaoyu + * @date :Created in 2020/9/29 18:36 + */ +@Data +@Builder +public class RespClaAllDetailInfo { + + // 班级信息 + private ScCourseCla courseCla; + + // 课程信息 + private ScCourse course; + + // 收费方式 + private List courseChargeList; + + // 上课时间 + private List claTimeList; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/course/RespScCourseDetail.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/course/RespScCourseDetail.java new file mode 100644 index 0000000..73b6a86 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/course/RespScCourseDetail.java @@ -0,0 +1,19 @@ +package cn.xluobo.business.sc.course.domain.resp.course; + +import cn.xluobo.business.sc.course.domain.req.course.ReqAddScCourse; +import lombok.Data; + +/** + * 课程详情 + * + * @author :zhangbaoyu + * @date :Created in 2020/7/8 20:34 + */ +@Data +public class RespScCourseDetail extends ReqAddScCourse { + + private Long courseId; + + private String courseTypeName; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/course/RespSearchCourse.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/course/RespSearchCourse.java new file mode 100644 index 0000000..8614127 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/course/RespSearchCourse.java @@ -0,0 +1,65 @@ +package cn.xluobo.business.sc.course.domain.resp.course; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/7/25 11:11 + */ +@Data +public class RespSearchCourse implements Serializable { + + private Long courseId; + + private String courseName; + + private Long courseTypeId; + + /** + * 课程类型 + */ + private String courseTypeName; + + /** + * 授课模式 + */ + private String teachingMode; + + /** + * 开班数 + */ + private Integer claCount; + + /** + * 收费模式 + */ + private String chargeNames; + + /** + * 开课校区 + */ + private String campusIds; + + /** + * 创建日期 + */ + private Date createTime; + + /** + * 课程状态 + */ + private String sale; + + /** + * 课程简介 + */ + private String courseIntro; + + /** + * 学生课程 + */ + private Long studentCourseId; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/ClaTimeCalendarItem.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/ClaTimeCalendarItem.java new file mode 100644 index 0000000..3bf1a74 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/ClaTimeCalendarItem.java @@ -0,0 +1,58 @@ +package cn.xluobo.business.sc.course.domain.resp.time; + +import cn.xluobo.core.constants.SysConstant; +import lombok.Data; + +/** + * 单节排课信息 + * @author :zhangbaoyu + * @date :Created in 2020/9/23 18:54 + */ +@Data +public class ClaTimeCalendarItem { + + private Long courseTimeId; + + private String claName; + + private String courseName; + + // 日期 + private String claDate; + + // 星期 + private String weekDay; + + private String startTime; + + private String endTime; + + private String staffName; + + private int studentCount; + + // 教室 + private String roomName; + + private String claColor; + + // 上课状态 + private String claTimeStatus; + + public ClaTimeCalendarItem transfer(RespClaTimeCalendar respClaTime) { + this.courseTimeId = respClaTime.getCourseTimeId(); + this.claName = respClaTime.getClaName(); + this.courseName = respClaTime.getCourseName(); + this.claDate = respClaTime.getClaDate(); + this.weekDay = SysConstant.WEEK_DAY_MAP.get(respClaTime.getWeekDay()); + this.startTime = respClaTime.getStartTime().substring(0,5); + this.endTime = respClaTime.getEndTime().substring(0,5); + this.staffName = respClaTime.getStaffName(); + this.studentCount = respClaTime.getStudentCount(); + this.roomName = respClaTime.getRoomName(); + this.claColor = respClaTime.getClaColor(); + this.claTimeStatus = respClaTime.getStatus(); + return this; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/ClaTimeColumnTitle.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/ClaTimeColumnTitle.java new file mode 100644 index 0000000..3c83c90 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/ClaTimeColumnTitle.java @@ -0,0 +1,22 @@ +package cn.xluobo.business.sc.course.domain.resp.time; + +import lombok.Data; + +/** + * 按时间 课表 title + * @author :zhangbaoyu + * @date :Created in 2020/9/23 17:16 + */ +@Data +public class ClaTimeColumnTitle { + + // 星期 + private String weekName; + + // 日期 + private String day; + + // 排课数量 + private int count; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/ClaTimeContainer.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/ClaTimeContainer.java new file mode 100644 index 0000000..ce0b173 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/ClaTimeContainer.java @@ -0,0 +1,23 @@ +package cn.xluobo.business.sc.course.domain.resp.time; + +import lombok.Data; + +import java.util.List; +import java.util.Map; + +/** + * 具体排课数据 + * table 单行 + * @author :zhangbaoyu + * @date :Created in 2020/9/23 18:59 + */ +@Data +public class ClaTimeContainer { + + // 上课时间 + private String time; + + // 排课信息 + private Map> claTimeWeekDayMap; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespBusinessClaTimeCalendar.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespBusinessClaTimeCalendar.java new file mode 100644 index 0000000..530d6a5 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespBusinessClaTimeCalendar.java @@ -0,0 +1,21 @@ +package cn.xluobo.business.sc.course.domain.resp.time; + +import lombok.Data; + +import java.util.List; + +/** + * 按时间 课表 + * @author :zhangbaoyu + * @date :Created in 2020/9/23 17:15 + */ +@Data +public class RespBusinessClaTimeCalendar { + + // 标题 + private List columnTitles; + + // 行数据 + private List claTimeContainer; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTime.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTime.java new file mode 100644 index 0000000..ab4bfed --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTime.java @@ -0,0 +1,73 @@ +package cn.xluobo.business.sc.course.domain.resp.time; + +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 上课记录 + * @author :zhangbaoyu + * @date :Created in 2020/10/2 20:33 + */ +@Data +public class RespClaTime { + + private Long courseTimeId; + + private Long claId; + + private String claName; + + private Long courseId; + + private String courseName; + + private Long teacherId; + + private String staffName; + + /** + * 状态 1:待上课 2:已上课 + */ + private String status; + + private String claDate; + + private String startTime; + + private String endTime; + + private String realClaDate; + + private String realStartTime; + + private String realEndTime; + + // 应到 + private Integer needAttendCnt; + + // 实到 + private Integer realAttendCnt; + + private Integer leaveCnt; + + private Integer outCnt; + + private BigDecimal payHour; + + private BigDecimal payTotalHour; + + private BigDecimal payTotalFee; + + private String roomName; + + private String classTheme; + + private String memo; + + // 最后变更时间 记录上课时间 + private Date lastUpdateTime; + // 记录人 + private String lastUpdateUserName; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTimeAttend.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTimeAttend.java new file mode 100644 index 0000000..db0dce0 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTimeAttend.java @@ -0,0 +1,47 @@ +package cn.xluobo.business.sc.course.domain.resp.time; + +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 上课记录明细 + * + * @author :zhangbaoyu + * @date :Created in 2020/10/4 20:47 + */ +@Data +public class RespClaTimeAttend { + + private Long attendId; + + private Long studentId; + + private String studentName; + + private String claName; + + private String chargeType; + + private Long teacherId; + + private String teacherName; + + private String attendStatus; + + private BigDecimal payHour; + + private BigDecimal payFee; + + private String memo; + + private String realClaDate; + + private String realStartTime; + + private String realEndTime; + + // 创建时间 + private Date createTime; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTimeCalendar.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTimeCalendar.java new file mode 100644 index 0000000..728f2b0 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTimeCalendar.java @@ -0,0 +1,26 @@ +package cn.xluobo.business.sc.course.domain.resp.time; + +import cn.xluobo.business.sc.course.repo.model.ScClaTime; +import lombok.Data; + +/** + * 排课信息(课表) + * @author :zhangbaoyu + * @date :Created in 2020/9/18 14:50 + */ +@Data +public class RespClaTimeCalendar extends ScClaTime { + + private String claColor; + + private String staffName; + + // 上课星期 + private Integer weekDay; + + // 上课 开始小时 + private Integer startHour; + + private Integer studentCount; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTimeRule.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTimeRule.java new file mode 100644 index 0000000..e971c3a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTimeRule.java @@ -0,0 +1,29 @@ +package cn.xluobo.business.sc.course.domain.resp.time; + +import cn.xluobo.business.sc.course.repo.model.ScClaTimeRule; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 排课信息 + * @author :zhangbaoyu + * @date :Created in 2020/9/14 22:14 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class RespClaTimeRule extends ScClaTimeRule { + + private String courseName; + private String claName; + private String staffName; + private String claDate; + private String claTimeBegin; + private String claTimeEnd; + + private String weekDayName; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/enums/ChargeDateUnitEnum.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/enums/ChargeDateUnitEnum.java new file mode 100644 index 0000000..e24576b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/enums/ChargeDateUnitEnum.java @@ -0,0 +1,41 @@ +package cn.xluobo.business.sc.course.enums; + +/** + * 按时间收费周期枚举 + * @author :zhangbaoyu + * @date :Created in 2020/9/5 13:23 + */ +public enum ChargeDateUnitEnum { + + DAY("day","天"), + MONTH("month","月"), + SEASON("season","季"), + YEAR("year","年"), + ; + + ChargeDateUnitEnum(String dateUnit, String dateUnitLabel) { + this.dateUnit = dateUnit; + this.dateUnitLabel = dateUnitLabel; + } + + private final String dateUnit; + + private final String dateUnitLabel; + + public String getDateUnit() { + return dateUnit; + } + + public String getDateUnitLabel() { + return dateUnitLabel; + } + + public static String getDateUnitLabel(String dateUnit) { + for (ChargeDateUnitEnum dateUnitEnum : ChargeDateUnitEnum.values()) { + if (dateUnitEnum.getDateUnit().equals(dateUnit)) { + return dateUnitEnum.getDateUnitLabel(); + } + } + return ""; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/enums/CourseChargeTypeEnum.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/enums/CourseChargeTypeEnum.java new file mode 100644 index 0000000..ee7d316 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/enums/CourseChargeTypeEnum.java @@ -0,0 +1,42 @@ +package cn.xluobo.business.sc.course.enums; + +/** + * 课程收费模式 + * @author :zhangbaoyu + * @date :Created in 2020/8/4 15:30 + */ +public enum CourseChargeTypeEnum { + + // 按课时 + HOUR("hour", "按课时"), + // 按时间 + DATE("date", "按时间"), + // 按期 + CYCLE("cycle", "按期"); + + private final String chargeType; + + private final String chargeTypeName; + + CourseChargeTypeEnum(String chargeType, String chargeTypeName) { + this.chargeType = chargeType; + this.chargeTypeName = chargeTypeName; + } + + public String getChargeType() { + return chargeType; + } + + public String getChargeTypeName() { + return chargeTypeName; + } + + public static String getChargeType(String chargeType) { + for (CourseChargeTypeEnum chargeTypeEnum : CourseChargeTypeEnum.values()) { + if (chargeTypeEnum.getChargeType().equals(chargeType)){ + return chargeTypeEnum.getChargeTypeName(); + } + } + return "未知"; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeAttendStatusEnums.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeAttendStatusEnums.java new file mode 100644 index 0000000..bd03653 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeAttendStatusEnums.java @@ -0,0 +1,45 @@ +package cn.xluobo.business.sc.course.repo.enums; + +/** + * 到课状态 + * @author :zhangbaoyu + * @date :Created in 2020/4/30 15:16 + */ +public enum ClaTimeAttendStatusEnums { + + AT_CLASS("1","到课"), + LEAVE_CLASS("2","请假"), + OUT_CLASS("3","缺勤"), + ; + + private final String attendStatus; + + private final String statusName; + + ClaTimeAttendStatusEnums(String attendStatus, String statusName) { + this.attendStatus = attendStatus; + this.statusName = statusName; + } + + public String getAttendStatus() { + return attendStatus; + } + + public String getStatusName() { + return statusName; + } + + /** + * 根据状态获取名称 + * @param status + * @return + */ + public static String getNameByStatus(String status) { + for (ClaTimeAttendStatusEnums value : ClaTimeAttendStatusEnums.values()) { + if(value.getAttendStatus().equals(status)) { + return value.getStatusName(); + } + } + return ""; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeRepeatTypeEnums.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeRepeatTypeEnums.java new file mode 100644 index 0000000..b9cba7f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeRepeatTypeEnums.java @@ -0,0 +1,29 @@ +package cn.xluobo.business.sc.course.repo.enums; + +/** + * 排课 重复方式 + * @author :zhangbaoyu + * @date :Created in 2020/9/14 22:20 + */ +public enum ClaTimeRepeatTypeEnums { + EVERY_WEEK("1", "每周重复"), + EVERY_SECOND_DAY("2", "隔天重复"), + EVERY_SECOND_WEEK("3", "隔周重复"), + ; + + private String repeatType; + private String repeatTypeName; + + ClaTimeRepeatTypeEnums(String repeatType, String repeatTypeName) { + this.repeatType = repeatType; + this.repeatTypeName = repeatTypeName; + } + + public String getRepeatType() { + return repeatType; + } + + public String getRepeatTypeName() { + return repeatTypeName; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeRuleTypeEnums.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeRuleTypeEnums.java new file mode 100644 index 0000000..ccbb261 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeRuleTypeEnums.java @@ -0,0 +1,30 @@ +package cn.xluobo.business.sc.course.repo.enums; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/9/14 21:55 + */ +public enum ClaTimeRuleTypeEnums { + + + REPEAT_RULE("1", "重复排课"), + ONCE_RULE("2", "单次排课"); + + + private String ruleType; + + private String ruleTypeName; + + ClaTimeRuleTypeEnums(String ruleType, String ruleTypeName) { + this.ruleType = ruleType; + this.ruleTypeName = ruleTypeName; + } + + public String getRuleType() { + return ruleType; + } + + public String getRuleTypeName() { + return ruleTypeName; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeSourceEnums.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeSourceEnums.java new file mode 100644 index 0000000..28e8403 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeSourceEnums.java @@ -0,0 +1,31 @@ +package cn.xluobo.business.sc.course.repo.enums; + +/** + * 排课 来源 + * @author :zhangbaoyu + * @date :Created in 2020/4/30 15:13 + */ +public enum ClaTimeSourceEnums { + + PLAN_CLA_TIME("1","排课"), + UN_PLAN_CLA_TIME("2","未排课上课"), + ONE_ADD("3","单个新增"), + ; + + private final String source; + + private final String sourceName; + + ClaTimeSourceEnums(String source, String sourceName) { + this.source = source; + this.sourceName = sourceName; + } + + public String getSource() { + return source; + } + + public String getSourceName() { + return sourceName; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeStatusEnums.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeStatusEnums.java new file mode 100644 index 0000000..78e27d3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/enums/ClaTimeStatusEnums.java @@ -0,0 +1,31 @@ +package cn.xluobo.business.sc.course.repo.enums; + +/** + * 排课 状态 + * @author :zhangbaoyu + * @date :Created in 2020/4/30 15:16 + */ +public enum ClaTimeStatusEnums { + + WAIT_CLASS("1","待上课"), + HAD_CLASS("2","已上课"), + CHANGE_CLASS("3","已调课"), + ; + + private final String status; + + private final String statusName; + + ClaTimeStatusEnums(String status, String statusName) { + this.status = status; + this.statusName = statusName; + } + + public String getStatus() { + return status; + } + + public String getStatusName() { + return statusName; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScClaTimeAttendMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScClaTimeAttendMapper.java new file mode 100644 index 0000000..c2fa5b8 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScClaTimeAttendMapper.java @@ -0,0 +1,87 @@ +package cn.xluobo.business.sc.course.repo.mapper; + +import cn.xluobo.business.sc.course.domain.req.time.ReqClaTimeCount; +import cn.xluobo.business.sc.course.domain.req.time.ReqSearchScClaTimeAttend; +import cn.xluobo.business.sc.course.domain.resp.time.RespClaTimeAttend; +import cn.xluobo.business.sc.course.repo.model.ScClaTimeAttend; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 上课出勤表 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-09-30 02:33:26 + */ +public interface ScClaTimeAttendMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + + /** + * 获取明细 + * + * @param reqSearchScClaTimeAttend + * @param page + * @return + */ + List selectTimeAttendList(@Param("reqSearchScClaTimeAttend") ReqSearchScClaTimeAttend reqSearchScClaTimeAttend, @Param("page") Page page); + + /** + * 学生出席记录数量 + * + * @param studentCourseId 学生报读课程id + * @param beginDate 开始时间 + * @param endDate 结束时间 + * @return + */ + int selectStudentAttendCount(@Param("studentCourseId") Long studentCourseId, @Param("beginDate") String beginDate, @Param("endDate") String endDate); + + /** + * 应上课人数 + * + * @param beginDate + * @param endDate + * @return + */ + Integer selectNeedAttendCount(@Param("beginDate") String beginDate, @Param("endDate") String endDate); + + /** + * 学生上课出席数量 + * + * @param beginDate + * @param endDate + * @param attendStatus + * @return + */ + Integer selectAttendCount(@Param("beginDate") String beginDate, @Param("endDate") String endDate, @Param("attendStatus") String[] attendStatus); + + /** + * 实消 学生消耗课时数量 + * + * @param beginDate + * @param endDate + * @return + */ + BigDecimal selectAttendCostHour(@Param("beginDate") String beginDate, @Param("endDate") String endDate); + + /** + * 应消 学生消耗课时数量 + * + * @param beginDate + * @param endDate + * @return + */ + BigDecimal selectNeedAttendCostHour(@Param("beginDate") String beginDate, @Param("endDate") String endDate); + + /** + * 教师 指定日期范围内 累计获得课时 + * 只统计 课时,不统计按时间缴费的 + * + * @param reqClaTimeCount + * @return + */ + BigDecimal selectTeacherSumGetHour(ReqClaTimeCount reqClaTimeCount); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScClaTimeMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScClaTimeMapper.java new file mode 100644 index 0000000..7e7c726 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScClaTimeMapper.java @@ -0,0 +1,48 @@ +package cn.xluobo.business.sc.course.repo.mapper; + +import cn.xluobo.business.sc.course.domain.req.time.ReqClaTimeCount; +import cn.xluobo.business.sc.course.domain.req.time.ReqSearchClaTime; +import cn.xluobo.business.sc.course.domain.resp.time.RespClaTime; +import cn.xluobo.business.sc.course.domain.resp.time.RespClaTimeCalendar; +import cn.xluobo.business.sc.course.repo.model.ScClaTime; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 排课信息 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-09-16 + */ +public interface ScClaTimeMapper extends BaseMapper { + + /** + * 获取排课信息 + * + * @param searchClaTime + * @return + */ + List selectListForCalendar(ReqSearchClaTime searchClaTime); + + /** + * 获取上课记录 + * + * @param searchClaTime + * @return + */ + List selectListForAttend(@Param("searchClaTime") ReqSearchClaTime searchClaTime, @Param("page") Page page); + + /** + * 数量 + * + * @param reqClaTimeCount + * @return + */ + Integer selectClaTimeCount(ReqClaTimeCount reqClaTimeCount); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScClaTimeRuleMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScClaTimeRuleMapper.java new file mode 100644 index 0000000..fcf9a94 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScClaTimeRuleMapper.java @@ -0,0 +1,52 @@ +package cn.xluobo.business.sc.course.repo.mapper; + +import cn.xluobo.business.sc.course.domain.req.time.ReqSearchScClaTimeRule; +import cn.xluobo.business.sc.course.domain.resp.time.RespClaTimeRule; +import cn.xluobo.business.sc.course.repo.model.ScClaTimeRule; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 上课时间配置规则 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-09-14 + */ +public interface ScClaTimeRuleMapper extends BaseMapper { + + /** + * 获取一定时间范围内的排课信息 + * + * @param reqSearchScClaTimeRule + * @param page + * @return + */ + List selectByCondition(@Param("reqSearchScClaTimeRule") ReqSearchScClaTimeRule reqSearchScClaTimeRule, @Param("page") Page page); + + /** + * 获取制定日期的排课信息 + * @param claId + * @param day + * @return + */ + List selectByDay(@Param("claId")Long claId, @Param("day")String day); + + /** + * 根据id获取规则 + * @param ruleId + * @return + */ + RespClaTimeRule selectByRuleId(Long ruleId); + + /** + * 获取班级上课时间 + * @param claId + * @return + */ + List selectClaTimeInfo(Long claId); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseChargeMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseChargeMapper.java new file mode 100644 index 0000000..d3e4d29 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseChargeMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sc.course.repo.mapper; + +import cn.xluobo.business.sc.course.repo.model.ScCourseCharge; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 课程收费模式 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-07-08 + */ +public interface ScCourseChargeMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseClaMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseClaMapper.java new file mode 100644 index 0000000..0edaad8 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseClaMapper.java @@ -0,0 +1,62 @@ +package cn.xluobo.business.sc.course.repo.mapper; + +import cn.xluobo.business.sc.course.domain.req.ReqCourseClaSelect; +import cn.xluobo.business.sc.course.domain.req.ReqSearchScCourseCla; +import cn.xluobo.business.sc.course.domain.req.cla.ReqClaCount; +import cn.xluobo.business.sc.course.domain.resp.RespCourseClaInfo; +import cn.xluobo.business.sc.course.domain.resp.RespCourseClaSelectInfo; +import cn.xluobo.business.sc.course.repo.model.ScCourseCla; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.annotation.SqlParser; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 课程班级信息 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-03-17 01:11:06 + */ +public interface ScCourseClaMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + + /** + * 班级列表 + * + * @param reqSearchScCourseCla + * @param page + * @return + */ + List selectClaList(@Param("reqSearchScCourseCla")ReqSearchScCourseCla reqSearchScCourseCla, @Param("page")RespPage page); + + /** + * 班级select + * @param courseClaSelect + * @return + */ + List selectForSelect(ReqCourseClaSelect courseClaSelect); + + /** + * 班级数量 + * @param reqClaCount + * @return + */ + Integer selectClaCount(ReqClaCount reqClaCount); + + /** + * 班级数量 + * @param tenantId + * @return + */ + @SqlParser(filter = true) + Integer selectTenantClaCount(String tenantId); + + /** + * 班级在读学员数量 + * @param claId + * @return + */ + Integer selectStudentCnt(Long claId); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseMapper.java new file mode 100644 index 0000000..c07650c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseMapper.java @@ -0,0 +1,64 @@ +package cn.xluobo.business.sc.course.repo.mapper; + +import cn.xluobo.business.sc.course.domain.export.ExpCourse; +import cn.xluobo.business.sc.course.domain.req.ReqSearchScCourse; +import cn.xluobo.business.sc.course.domain.resp.course.RespSearchCourse; +import cn.xluobo.business.sc.course.repo.model.ScCourse; +import cn.xluobo.core.page.ReqDeptCondition; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.annotation.SqlParser; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 课程信息 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-03-17 11:25:55 + */ +public interface ScCourseMapper extends BaseMapper { + + /** + * 获取课程列表 + * @param reqSearchScCourse + * @param page + * @return + */ + List selectCourseList(@Param("reqSearchScCourse") ReqSearchScCourse reqSearchScCourse, @Param("page") RespPage page); + + /** + * 获取课程列表 + * 包含学生当前课程状态 + * @param reqSearchScCourse + * @param page + * @return + */ + List selectCourseListWithStudentCourse(@Param("reqSearchScCourse") ReqSearchScCourse reqSearchScCourse, @Param("page") RespPage page); + + /** + * 导出课程 + * @param reqSearchScCourse + * @return + */ + List selectCourseForExport(@Param("reqSearchScCourse") ReqSearchScCourse reqSearchScCourse); + + /** + * 课程数量 + * @param reqDeptCondition + * @return + */ + Integer selectCourseCount(ReqDeptCondition reqDeptCondition); + + /** + * 租户下课程数量 + * @param tenantId + * @return + */ + @SqlParser(filter = true) + Integer selectTenantCourseCount(String tenantId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseTypeMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseTypeMapper.java new file mode 100644 index 0000000..a33da77 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapper/ScCourseTypeMapper.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.sc.course.repo.mapper; + +import cn.xluobo.business.sc.course.repo.model.ScCourseType; + +/** + *

+ * 课程类型 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-07-09 08:10:25 + */ +public interface ScCourseTypeMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeAttendMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeAttendMapper.xml new file mode 100644 index 0000000..0bfe1ae --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeAttendMapper.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeMapper.xml new file mode 100644 index 0000000..33542ed --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeMapper.xml @@ -0,0 +1,129 @@ + + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeRuleMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeRuleMapper.xml new file mode 100644 index 0000000..981b9cf --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeRuleMapper.xml @@ -0,0 +1,58 @@ + + + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseChargeMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseChargeMapper.xml new file mode 100644 index 0000000..843f3f2 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseChargeMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseClaMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseClaMapper.xml new file mode 100644 index 0000000..d53a3ec --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseClaMapper.xml @@ -0,0 +1,85 @@ + + + + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseMapper.xml new file mode 100644 index 0000000..b8266d0 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseMapper.xml @@ -0,0 +1,126 @@ + + + + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseTypeMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseTypeMapper.xml new file mode 100644 index 0000000..895d17f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScCourseTypeMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTime.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTime.java new file mode 100644 index 0000000..170521c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTime.java @@ -0,0 +1,231 @@ +package cn.xluobo.business.sc.course.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 排课信息 + *

+ * + * @author zhangby + * @since 2020-09-16 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_cla_time") +public class ScClaTime implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 排课编号 + */ + @TableId(value = "course_time_id", type = IdType.ASSIGN_ID) + private Long courseTimeId; + + /** + * 规则编号 + */ + @TableField("rule_id") + private Long ruleId; + + /** + * 班级id + */ + @TableField("cla_id") + private Long claId; + + /** + * 任课教师 + */ + @TableField("teacher_id") + private Long teacherId; + + /** + * 上课教室 + */ + @TableField("room_id") + private Long roomId; + + /** + * 上课教室 + */ + @TableField("room_name") + private String roomName; + + /** + * 上课主题 + */ + @TableField("class_theme") + private String classTheme; + + /** + * 上课日期 如:2020-02-05 + */ + @TableField("cla_date") + private String claDate; + + /** + * 上课开始时间 + */ + @TableField("start_time") + private String startTime; + + /** + * 上课结束时间 + */ + @TableField("end_time") + private String endTime; + + /** + * 实际上课时间 + */ + @TableField("real_cla_date") + private String realClaDate; + + /** + * 实际开始时间 + */ + @TableField("real_start_time") + private String realStartTime; + + /** + * 实际结束时间 + */ + @TableField("real_end_time") + private String realEndTime; + + /** + * 课时变更数量 + */ + @TableField("pay_hour") + private BigDecimal payHour; + + /** + * 总课时消耗 + */ + @TableField("pay_total_hour") + private BigDecimal payTotalHour; + + /** + * 总学费消耗 + */ + @TableField("pay_total_fee") + private BigDecimal payTotalFee; + + /** + * 来源 1:重复排课 2:未排课上课 3:单个新增 + */ + @TableField("source") + private String source; + + /** + * 状态 1:待上课 2:已上课 + */ + @TableField("status") + private String status; + + /** + * 应到人数 + */ + @TableField("need_attend_cnt") + private Integer needAttendCnt; + + /** + * 实到人数 + */ + @TableField("real_attend_cnt") + private Integer realAttendCnt; + + /** + * 到课人数 + */ + @TableField("at_class_cnt") + private Integer atClassCnt; + + /** + * 请假人数 + */ + @TableField("leave_cnt") + private Integer leaveCnt; + + /** + * 缺勤人数 + */ + @TableField("out_cnt") + private Integer outCnt; + + /** + * 备注 + */ + @TableField("memo") + private String memo; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + @TableField(exist = false) + private Long deptId; + @TableField(exist = false) + private String courseName; + @TableField(exist = false) + private String claName; + @TableField(exist = false) + private String deptName; + + public boolean checkUpdateParam() { + if (StringUtils.isAnyEmpty(claDate, startTime, endTime)) { + return false; + } + if (null == teacherId) { + return false; + } + return true; + } + + public boolean checkAddParam() { + if(null == claId || null == teacherId) { + return false; + } + if (StringUtils.isAnyEmpty(claDate, startTime, endTime)) { + return false; + } + return true; + } + + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTimeAttend.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTimeAttend.java new file mode 100644 index 0000000..2c9989a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTimeAttend.java @@ -0,0 +1,125 @@ +package cn.xluobo.business.sc.course.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 上课出勤表 + *

+ * + * @author zhangby + * @since 2020-09-30 02:33:26 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_cla_time_attend") +public class ScClaTimeAttend implements Serializable { + + + /** + * 主键 + */ + @TableId(value = "attend_id", type = IdType.ASSIGN_ID) + private Long attendId; + + @TableField(value = "student_course_id") + private Long studentCourseId; + + @TableField(value = "course_order_id") + private Long courseOrderId; + + /** + * sc_cla_time.course_time_id + */ + @TableField("course_time_id") + private Long courseTimeId; + + /** + * 学生 + */ + @TableField("student_id") + private Long studentId; + + /** + * 班级 冗余自动 + */ + @TableField("cla_id") + private Long claId; + + /** + * 课程 冗余自动 + */ + @TableField("course_id") + private Long courseId; + + /** + * 上课教师 + */ + @TableField("teacher_id") + private Long teacherId; + + /** + * 教师名 + */ + @TableField("teacher_name") + private String teacherName; + + /** + * 收费模式 hour:课时 date:时间 cycle:期 + */ + @TableField("charge_type") + private String chargeType; + + /** + * 出席状态 1:到课 2:请假 3:缺勤 + */ + @TableField("attend_status") + private String attendStatus; + + /** + * 教师获取课时数量 + */ + @TableField("teacher_get_hour") + private BigDecimal teacherGetHour; + + /** + * 扣减课时数量 + */ + @TableField("pay_hour") + private BigDecimal payHour; + + /** + * 学费消耗 + */ + @TableField("pay_fee") + private BigDecimal payFee; + + /** + * 备注 + */ + @TableField("memo") + private String memo; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTimeRule.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTimeRule.java new file mode 100644 index 0000000..84c37eb --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTimeRule.java @@ -0,0 +1,190 @@ +package cn.xluobo.business.sc.course.repo.model; + +import cn.xluobo.business.sc.course.repo.enums.ClaTimeRepeatTypeEnums; +import cn.xluobo.business.sc.course.repo.enums.ClaTimeRuleTypeEnums; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 上课时间配置规则 + *

+ * + * @author zhangby + * @since 2020-09-14 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_cla_time_rule") +public class ScClaTimeRule implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 规则id + */ + @TableId(value = "rule_id", type = IdType.ASSIGN_ID) + private Long ruleId; + + /** + * 班级 + */ + @TableField("cla_id") + private Long claId; + + /** + * 规则类型 1重复排课 2单次排课 + */ + @TableField("rule_type") + private String ruleType; + + /** + * 开始日期 + */ + @TableField("begin_date") + private String beginDate; + + /** + * 结束日期 + */ + @TableField("end_date") + private String endDate; + + /** + * 单次排课 日期 + */ + @TableField("once_date") + private String onceDate; + + /** + * 重复方式 1每周重复 2隔天重复 3隔周重复 + */ + @TableField("repeat_type") + private String repeatType; + + /** + * 上课星期 周几上课 + */ + @TableField("week_day") + private String weekDay; + + /** + * 是否过滤节假日 1过滤 0不过滤 + */ + @TableField("filter_holiday") + private boolean filterHoliday; + + /** + * 上课时间 + */ + @TableField("start_time") + private String startTime; + + /** + * 下课时间 + */ + @TableField("end_time") + private String endTime; + + /** + * 任课教师 + */ + @TableField("teacher_id") + private Long teacherId; + + /** + * 上课教室 + */ + @TableField("room_id") + private Long roomId; + + /** + * 上课教室 + */ + @TableField("room_name") + private String roomName; + + /** + * 上课主题 + */ + @TableField("class_theme") + private String classTheme; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + /** + * 单次排课 选择的上课日期 + */ + @TableField(exist = false) + private String[] chooseDate; + + /** + * 所属校区 + */ + @TableField(exist = false) + private Long deptId; + + public boolean checkParam() { + if (null == claId || null == teacherId) { + return false; + } + if (StringUtils.isAnyEmpty(ruleType)) { + return false; + } + if (ClaTimeRuleTypeEnums.ONCE_RULE.getRuleType().equals(ruleType)) { + if (StringUtils.isAnyEmpty(startTime, endTime)) { + return false; + } else if (null == chooseDate || chooseDate.length == 0) { + return false; + } + } + if ("1".equals(ruleType) && StringUtils.isAnyEmpty(repeatType)) { + return false; + } + if (ClaTimeRepeatTypeEnums.EVERY_WEEK.getRepeatType().equals(repeatType) + || ClaTimeRepeatTypeEnums.EVERY_SECOND_WEEK.getRepeatType().equals(repeatType)) { + if (StringUtils.isAnyEmpty(weekDay, startTime, endTime, beginDate, endDate)) { + return false; + } + } else { + if (StringUtils.isAnyEmpty(startTime, endTime)) { + return false; + } + } + return true; + } + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourse.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourse.java new file mode 100644 index 0000000..1342026 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourse.java @@ -0,0 +1,111 @@ +package cn.xluobo.business.sc.course.repo.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 课程信息 + *

+ * + * @author zhangby + * @since 2020-03-17 11:25:55 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_course") +public class ScCourse implements Serializable { + + + /** + * 课程id + */ + @TableId(value = "course_id") + private Long courseId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 课程名称 + */ + @TableField("course_name") + private String courseName; + + /** + * 课程类型 + */ + @TableField("course_type_id") + private Long courseTypeId; + + /** + * 授课模式 1 班课 2 一对一 + */ + @TableField("teaching_mode") + private String teachingMode; + + /** + * 课程简介 + */ + @TableField("course_intro") + private String courseIntro; + + /** + * 是否在售 1在售 0停售 + */ + @TableField("sale") + private String sale; + + /** + * 删除标志(1删除 0在用) + */ + @TableField("delete_flag") + @TableLogic + private String deleteFlag; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + @JsonIgnore + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + @JsonIgnore + private Date lastUpdateTime; + + /** + * 导入id + */ + @TableField(value = "import_id") + @JsonIgnore + private Long importId; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourseCharge.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourseCharge.java new file mode 100644 index 0000000..dc59361 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourseCharge.java @@ -0,0 +1,84 @@ +package cn.xluobo.business.sc.course.repo.model; + +import cn.xluobo.business.sc.course.enums.ChargeDateUnitEnum; +import cn.xluobo.business.sc.course.enums.CourseChargeTypeEnum; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + *

+ * 课程收费模式 + *

+ * + * @author zhangby + * @since 2020-07-08 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_course_charge") +public class ScCourseCharge implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 收费编号 + */ + @TableId(value = "charge_id") + private Long chargeId; + + /** + * 课程编号 + */ + @TableField("course_id") + private Long courseId; + + /** + * 校区 -1为全部校区 + */ + @TableField("depart_id") + private Long departId; + + /** + * 收费模式 hour:课时 date:时间 cycle:期 + */ + @TableField("charge_type") + private String chargeType; + + /** + * 课时数量 + */ + @TableField("count") + private BigDecimal count; + + /** + * 总价 + */ + @TableField("total_fee") + private BigDecimal totalFee; + + /** + * 时间周期 天/月/季/年 + */ + @TableField("date_unit") + private String dateUnit; + + public String getChargeName() { + if (CourseChargeTypeEnum.HOUR.getChargeType().equals(chargeType)) { + return "按课时 " + count.toString() + "课时=" + totalFee +"元"; + } else if (CourseChargeTypeEnum.DATE.getChargeType().equals(chargeType)) { + return "按时间 " + count.toString() + ChargeDateUnitEnum.getDateUnitLabel(dateUnit) + "=" + totalFee+"元"; + } else if (CourseChargeTypeEnum.CYCLE.getChargeType().equals(chargeType)) { + return "按周期 " + count.toString() + "课时=" + totalFee +"元"; + } + return ""; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourseCla.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourseCla.java new file mode 100644 index 0000000..9027b6f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourseCla.java @@ -0,0 +1,170 @@ +package cn.xluobo.business.sc.course.repo.model; + +import cn.xluobo.core.api.APIBaseResponse; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 课程班级信息 + *

+ * + * @author zhangby + * @since 2020-08-07 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_course_cla") +public class ScCourseCla implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 班级id + */ + @TableId(value = "cla_id") + private Long claId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 课程id + */ + @TableField("course_id") + private Long courseId; + + /** + * 开班校区 + */ + @TableField("depart_id") + private Long departId; + + /** + * 班主任id + */ + @TableField("staff_id") + private Long staffId; + + /** + * 班级名称 + */ + @TableField("cla_name") + private String claName; + + /** + * 班级颜色 + */ + @TableField("cla_color") + private String claColor; + + /** + * 满班人数 + */ + @TableField("capacity") + private Integer capacity; + + /** + * 招生状态 1开放 2满班后停止 0停止 + */ + @TableField("recruit_status") + private String recruitStatus; + + /** + * 每次上课学生扣除课时 + */ + @TableField("every_stu_lose_hour") + private BigDecimal everyStuLoseHour; + + /** + * 每次上课教师获得课时 + */ + @TableField("every_tea_get_hour") + private BigDecimal everyTeaGetHour; + + /** + * 开班日期 + */ + @TableField("open_date") + private String openDate; + + /** + * 结班日期 + */ + @TableField("close_date") + private String closeDate; + + /** + * 备注 + */ + @TableField("memo") + private String memo; + + /** + * 删除标志(1删除 0在用) + */ + @TableField("delete_flag") + private String deleteFlag; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + @TableField(exist = false) + private String deptName; + + @TableField(exist = false) + private String teacherName; + + // 当前班级人数 + @TableField(exist = false) + private Integer studentCnt; + + /** + * 校验参数 + * @return + */ + public APIBaseResponse checkParam(){ + if(StringUtils.isAnyEmpty(claName,claColor,recruitStatus,openDate)){ + return APIBaseResponse.fail("请求参数错误,请全部填写后,重新提交"); + } + if(null == courseId || null == departId || null == staffId || null == capacity || null == everyStuLoseHour || null == everyTeaGetHour){ + return APIBaseResponse.fail("请求参数错误,请全部填写后,重新提交"); + } + return APIBaseResponse.success(); + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourseType.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourseType.java new file mode 100644 index 0000000..627f0fa --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScCourseType.java @@ -0,0 +1,66 @@ +package cn.xluobo.business.sc.course.repo.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 课程类型 + *

+ * + * @author zhangby + * @since 2020-07-09 08:10:25 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_course_type") +public class ScCourseType implements Serializable { + + + @TableId(value = "course_type_id") + private Long courseTypeId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 课程类型名 + */ + @TableField("course_type") + private String courseType; + + /** + * 排序 + */ + @TableField("sort") + private Integer sort; + + /** + * 状态(1正常 0停用) + */ + @TableField("in_use") + private String inUse; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessClaTimeRuleService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessClaTimeRuleService.java new file mode 100644 index 0000000..460b089 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessClaTimeRuleService.java @@ -0,0 +1,182 @@ +package cn.xluobo.business.sc.course.service; + +import cn.xluobo.business.sc.base.repo.model.ScRoom; +import cn.xluobo.business.sc.base.service.IScRoomService; +import cn.xluobo.business.sc.course.domain.req.time.ReqSearchScClaTimeRule; +import cn.xluobo.business.sc.course.domain.resp.time.RespClaTimeRule; +import cn.xluobo.business.sc.course.repo.mapper.ScClaTimeRuleMapper; +import cn.xluobo.business.sc.course.repo.model.ScClaTime; +import cn.xluobo.business.sc.course.repo.model.ScClaTimeRule; +import cn.xluobo.business.sc.course.repo.model.ScCourseCla; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/9/18 15:38 + */ +@Service +@Transactional +public class BusinessClaTimeRuleService { + + @Autowired + private IScClaTimeService claTimeService; + @Autowired + private IScClaTimeRuleService claTimeRuleService; + @Autowired + private ScClaTimeRuleMapper claTimeRuleMapper; + @Autowired + private IScCourseClaService courseClaService; + @Autowired + private IScRoomService roomService; + + /** + * 查询 + * + * @param reqSearchScClaTimeRule + * @return + */ + public APIResponse searchList(ReqSearchScClaTimeRule reqSearchScClaTimeRule) { + RespPage respPage = new RespPage<>(reqSearchScClaTimeRule.getPageNum(),reqSearchScClaTimeRule.getPageSize()); + List claTimeRuleList = claTimeRuleMapper.selectByCondition(reqSearchScClaTimeRule, respPage); + respPage.setRows(claTimeRuleList); + return APIResponse.toAPIResponse(respPage); + } + + /** + * 添加 + * + * @param claTimeRule + * @return + */ + public APIResponse addClaTimeRule(ScClaTimeRule claTimeRule) { + if (!claTimeRule.checkParam()) { + return APIResponse.toExceptionResponse(ApiResEnums.PARAM_FAIL); + } + // 教室 + if(null != claTimeRule.getRoomId()) { + ScRoom room = roomService.getById(claTimeRule.getRoomId()); + claTimeRule.setRoomName(room.getRoomName()); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + claTimeRule.setCreateUser(loginUser.getUserId()); + claTimeRule.setCreateTime(new Date()); + claTimeRuleService.save(claTimeRule); + saveBatchClaTime(claTimeRule); + return APIResponse.toOkResponse(); + } + + /** + * 详情 + * + * @param ruleId + * @return + */ + public APIResponse detailById(Long ruleId) { + if (null == ruleId) { + return APIResponse.toAPIResponse(null); + } + ScClaTimeRule claTimeRule = claTimeRuleService.getById(ruleId); + // 设置deptId + Long claId = claTimeRule.getClaId(); + ScCourseCla courseCla = courseClaService.getById(claId); + claTimeRule.setDeptId(courseCla.getDepartId()); + + return APIResponse.toAPIResponse(claTimeRule); + } + + + /** + * 更新 + * + * @param claTimeRule + * @return + */ + public APIResponse updateClaTimeRule(ScClaTimeRule claTimeRule) { + if (null == claTimeRule.getRuleId()) { + return APIResponse.toExceptionResponse(ApiResEnums.PARAM_FAIL); + } + if (!claTimeRule.checkParam()) { + return APIResponse.toExceptionResponse(ApiResEnums.PARAM_FAIL); + } + // 教室 + if(null != claTimeRule.getRoomId()) { + ScRoom room = roomService.getById(claTimeRule.getRoomId()); + claTimeRule.setRoomName(room.getRoomName()); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + claTimeRule.setLastUpdateUser(loginUser.getUserId()); + claTimeRule.setLastUpdateTime(new Date()); + boolean updateScCourseType = claTimeRuleService.updateById(claTimeRule); + //claTimeService.deleteUnBeginTime(claTimeRule.getRuleId(), claTimeRule.getClaId(), loginUser.getNowTenantId()); + + saveBatchClaTime(claTimeRule); + return APIResponse.toOkResponse(); + } + + /** + * 删除 + * + * @param ruleId + * @return + */ + public APIResponse deleteById(Long ruleId) { + if (null == ruleId) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + ScClaTimeRule claTimeRule = claTimeRuleService.getById(ruleId); + + claTimeRuleService.removeById(ruleId); + + LoginUser loginUser = SecurityUtils.getLoginUser(); + //claTimeService.deleteUnBeginTime(claTimeRule.getRuleId(), claTimeRule.getClaId(), loginUser.getNowTenantId()); + + return APIResponse.toOkResponse(); + } + + /** + * 保存 具体上课日期 + * + * @param claTimeRule + */ + private void saveBatchClaTime(ScClaTimeRule claTimeRule) { + Long claId = claTimeRule.getClaId(); + ScCourseCla courseCla = courseClaService.getById(claId); + BigDecimal everyStuLoseHour = courseCla.getEveryStuLoseHour(); + + List claTimeList = claTimeRuleService.getClaTimeListByRule(claTimeRule, null); + + List timeList = claTimeList.stream().map(item -> { + ScClaTime claTime = new ScClaTime(); + claTime.setRuleId(claTimeRule.getRuleId()); + claTime.setClaId(claTimeRule.getClaId()); + claTime.setClaDate(item.getClaDate()); + claTime.setStartTime(item.getClaTimeBegin()); + claTime.setEndTime(item.getClaTimeEnd()); + claTime.setPayHour(everyStuLoseHour); + // 排课 + claTime.setSource("1"); + // 待上课 + claTime.setStatus("1"); + claTime.setRoomId(claTimeRule.getRoomId()); + claTime.setRoomName(claTimeRule.getRoomName()); + claTime.setClassTheme(claTimeRule.getClassTheme()); + claTime.setTeacherId(claTimeRule.getTeacherId()); + claTime.setCreateUser(claTimeRule.getCreateUser()); + return claTime; + }).collect(Collectors.toList()); + claTimeService.saveBatch(timeList); + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessClaTimeService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessClaTimeService.java new file mode 100644 index 0000000..35c0dd0 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessClaTimeService.java @@ -0,0 +1,433 @@ +package cn.xluobo.business.sc.course.service; + +import cn.xluobo.business.sc.base.repo.model.ScRoom; +import cn.xluobo.business.sc.base.service.IScRoomService; +import cn.xluobo.business.sc.course.domain.req.time.ReqSearchClaTime; +import cn.xluobo.business.sc.course.domain.resp.time.*; +import cn.xluobo.business.sc.course.repo.enums.ClaTimeStatusEnums; +import cn.xluobo.business.sc.course.repo.mapper.ScClaTimeMapper; +import cn.xluobo.business.sc.course.repo.model.ScClaTime; +import cn.xluobo.business.sc.course.repo.model.ScClaTimeAttend; +import cn.xluobo.business.sc.course.repo.model.ScCourse; +import cn.xluobo.business.sc.course.repo.model.ScCourseCla; +import cn.xluobo.business.sc.student.domain.req.ReqClaTimeAttend; +import cn.xluobo.business.sc.student.service.BusinessScStudentCourseService; +import cn.xluobo.business.sc.student.service.IScStudentCourseService; +import cn.xluobo.business.sys.admin.service.ISysDeptService; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.constants.SysConstant; +import cn.xluobo.core.page.RespPage; +import cn.xluobo.core.utils.DateUtil; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/9/16 17:05 + */ +@Service +@Transactional +public class BusinessClaTimeService { + + @Autowired + private IScClaTimeService claTimeService; + @Autowired + private ScClaTimeMapper claTimeMapper; + @Autowired + private IScRoomService roomService; + @Autowired + private IScCourseClaService claService; + @Autowired + private IScCourseService courseService; + @Autowired + private ISysDeptService deptService; + @Autowired + private IScClaTimeAttendService claTimeAttendService; + @Autowired + private IScStudentCourseService studentCourseService; + @Autowired + private BusinessScStudentCourseService businessScStudentCourseService; + + /** + * 按周获取课表 + * + * @param reqSearchClaTime + * @return + */ + public APIResponse searchListForCalendar(ReqSearchClaTime reqSearchClaTime) { + String beginDate = reqSearchClaTime.getBeginDate(); + String endDate = reqSearchClaTime.getEndDate(); + Long deptId = reqSearchClaTime.getDeptId(); + + if (StringUtils.isAnyEmpty(beginDate, endDate)) { + return APIResponse.toOkResponse(); + } + + DateTime cycleBegin = DateUtil.yyyMMddDayBegin(beginDate); + DateTime cycleEnd = DateUtil.yyyMMddDayEnd(endDate); + + if (1 != cycleBegin.getDayOfWeek() || 7 != cycleEnd.getDayOfWeek()) { + return APIResponse.toOkResponse(); + } + + // 日历数据 格式为:时间->星期->课程 + Map>> claTimeCalendarMap = Maps.newHashMap(); + SysConstant.CLA_TIME_MAP.forEach((claTimeKey, claTimeValue) -> { + Map> weekDayMap = Maps.newHashMap(); + SysConstant.WEEK_DAY_MAP.forEach((weekDayKey, weekDay) -> { + List claTimeArrayList = Lists.newArrayList(); + weekDayMap.put(weekDayKey, claTimeArrayList); + }); + claTimeCalendarMap.put(claTimeKey, weekDayMap); + }); + + // 获取排课信息 + List respClaTimeList = claTimeMapper.selectListForCalendar(reqSearchClaTime); + + // 将排课信息 入到 claTimeCalendarMap + respClaTimeList.forEach(item -> { + Integer weekDay = item.getWeekDay(); + Integer startHour = item.getStartHour(); + + if (claTimeCalendarMap.containsKey(startHour)) { + claTimeCalendarMap.get(startHour).get(weekDay).add(item); + } else if (claTimeCalendarMap.containsKey(startHour - 1)) { + // 每两个小时 一个上课时段,所以-1 + claTimeCalendarMap.get(startHour - 1).get(weekDay).add(item); + } + }); + + + RespBusinessClaTimeCalendar timeCalendar = new RespBusinessClaTimeCalendar(); + // 每行数据 + List claTimeContainerList = Lists.newArrayList(); + // 星期排课数量 + Map columnTitleTimeCountMap = Maps.newHashMap(); + + // 每行数据 + claTimeCalendarMap.forEach((claTimeKey, claTimeMap) -> { + ClaTimeContainer claTimeContainer = new ClaTimeContainer(); + claTimeContainer.setTime(SysConstant.CLA_TIME_MAP.get(claTimeKey)); + + Map> claTimeWeekDayMap = Maps.newHashMap(); + claTimeMap.forEach((weekDayKey, list) -> { + + // 排课数量 + if (columnTitleTimeCountMap.containsKey(weekDayKey)) { + columnTitleTimeCountMap.put(weekDayKey, columnTitleTimeCountMap.get(weekDayKey) + list.size()); + } else { + columnTitleTimeCountMap.put(weekDayKey, list.size()); + } + + List timeItemList = list.stream().map(item -> { + ClaTimeCalendarItem claTimeItem = new ClaTimeCalendarItem(); + claTimeItem.transfer(item); + return claTimeItem; + }).collect(Collectors.toList()); + claTimeWeekDayMap.put(weekDayKey, timeItemList); + }); + claTimeContainer.setClaTimeWeekDayMap(claTimeWeekDayMap); + claTimeContainerList.add(claTimeContainer); + }); + Collections.sort(claTimeContainerList, (o1, o2) -> { + int a = Integer.parseInt(o1.getTime().substring(0, 2)); + int b = Integer.parseInt(o2.getTime().substring(0, 2)); + if (a > b) { + return 1; + } else if (a < b) { + return -1; + } else { + return 0; + } + }); + timeCalendar.setClaTimeContainer(claTimeContainerList); + + + // 标题 + List columnTitles = Lists.newArrayList(); + while (cycleBegin.isBefore(cycleEnd)) { + int dayOfWeek = cycleBegin.getDayOfWeek(); + + ClaTimeColumnTitle claTimeColumnTitle = new ClaTimeColumnTitle(); + claTimeColumnTitle.setWeekName(SysConstant.WEEK_DAY_MAP.get(dayOfWeek)); + claTimeColumnTitle.setDay(cycleBegin.toString("MM-dd")); + claTimeColumnTitle.setCount(columnTitleTimeCountMap.get(dayOfWeek)); + + columnTitles.add(claTimeColumnTitle); + cycleBegin = cycleBegin.plusDays(1); + } + timeCalendar.setColumnTitles(columnTitles); + + return APIResponse.toAPIResponse(timeCalendar); + } + + /** + * 获取最近几天的排课 + * + * @param reqSearchClaTime + * @return + */ + public List searchRecentDayTimeList(ReqSearchClaTime reqSearchClaTime) { + return claTimeMapper.selectListForCalendar(reqSearchClaTime); + } + + /** + * 获取上课记录 + * + * @param searchClaTime + * @return + */ + public RespPage selectListForAttend(ReqSearchClaTime searchClaTime) { + RespPage page = new RespPage<>(searchClaTime.getPageNum(), searchClaTime.getPageSize()); + List claTimeList = claTimeMapper.selectListForAttend(searchClaTime, page); + page.setRows(claTimeList); + return page; + } + + /** + * 添加 + * + * @param claTime + * @return + */ + public APIResponse addClaTime(ScClaTime claTime) { + if (!claTime.checkAddParam()) { + return APIResponse.toExceptionResponse(ApiResEnums.PARAM_FAIL); + } + // 教室 + if (null != claTime.getRoomId()) { + ScRoom room = roomService.getById(claTime.getRoomId()); + claTime.setRoomName(room.getRoomName()); + } + + ScCourseCla courseCla = claService.getById(claTime.getClaId()); + claTime.setPayHour(courseCla.getEveryStuLoseHour()); + claTime.setSource("3"); + LoginUser loginUser = SecurityUtils.getLoginUser(); + claTime.setCreateUser(loginUser.getUserId()); + claTime.setCreateTime(new Date()); + claTimeService.save(claTime); + return APIResponse.toOkResponse(); + } + + /** + * 详情 + * + * @param courseTimeId + * @return + */ + public APIResponse detailById(Long courseTimeId) { + if (null == courseTimeId) { + return APIResponse.toAPIResponse(null); + } + ScClaTime claTime = claTimeService.getById(courseTimeId); + Long claId = claTime.getClaId(); + if (null != claId) { + ScCourseCla courseCla = claService.getById(claId); + if (null != courseCla) { + claTime.setDeptId(courseCla.getDepartId()); + } + } + + return APIResponse.toAPIResponse(claTime); + } + + /** + * 更新 + * + * @param claTime + * @return + */ + public APIResponse updateClaTime(ScClaTime claTime) { + if (null == claTime.getCourseTimeId()) { + return APIResponse.toExceptionResponse(ApiResEnums.PARAM_FAIL); + } + if (!claTime.checkUpdateParam()) { + return APIResponse.toExceptionResponse(ApiResEnums.PARAM_FAIL); + } + + ScCourseCla courseCla = claService.getById(claTime.getClaId()); + + LoginUser loginUser = SecurityUtils.getLoginUser(); + + UpdateWrapper uw = new UpdateWrapper(); + uw.eq("course_time_id", claTime.getCourseTimeId()); + uw.eq("status", ClaTimeStatusEnums.WAIT_CLASS.getStatus()); + // 教室 + if (null != claTime.getRoomId()) { + ScRoom room = roomService.getById(claTime.getRoomId()); + uw.set("room_name", room.getRoomName()); + } + uw.set("cla_date", claTime.getClaDate()); + uw.set("start_time", claTime.getStartTime()); + uw.set("end_time", claTime.getEndTime()); + uw.set("teacher_id", claTime.getTeacherId()); + uw.set("room_id", claTime.getRoomId()); + uw.set("pay_hour", courseCla.getEveryStuLoseHour()); + uw.set("class_theme", claTime.getClassTheme()); + uw.set("last_update_user", loginUser.getUserId()); + uw.set("last_update_time", new Date()); + + boolean update = claTimeService.update(uw); + if(!update) { + return APIResponse.toExceptionResponse("调课失败,请稍后重试"); + } + + return APIResponse.toOkResponse(); + } + + /** + * 删除 + * + * @param courseTimeId + * @return + */ + public APIResponse deleteById(Long courseTimeId) { + if (null == courseTimeId) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + ScClaTime claTime = claTimeService.getById(courseTimeId); + String status = claTime.getStatus(); + if ("2".equals(status)) { + return APIResponse.toExceptionResponse("已上课,无法删除"); + } + + claTimeService.removeById(courseTimeId); + + return APIResponse.toOkResponse(); + } + + /** + * 变更 已记上课 信息 + * @param reqClaTimeAttend + * @return + */ + public APIResponse changeHadClaTimeAttend(ReqClaTimeAttend reqClaTimeAttend) { + APIResponse checkParam = reqClaTimeAttend.checkParamForUpdateHadClaTime(); + if (!checkParam.isSuccess()) { + return checkParam; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + + Long courseTimeId = reqClaTimeAttend.getCourseTimeId(); + ScClaTime claTime = claTimeService.getById(courseTimeId); + if (!ClaTimeStatusEnums.HAD_CLASS.getStatus().equals(claTime.getStatus())) { + return APIResponse.toExceptionResponse("非已上课排课,无法变更!"); + } + + // 变更状态为待上课 + ScClaTime updateClaTime = new ScClaTime(); + updateClaTime.setCourseTimeId(courseTimeId); + updateClaTime.setStatus(ClaTimeStatusEnums.WAIT_CLASS.getStatus()); + claTimeService.updateById(updateClaTime); + + Long claId = claTime.getClaId(); + ScCourseCla courseCla = claService.getById(claId); + if(null == courseCla) { + return APIResponse.toExceptionResponse("无法获取班级,无法删除"); + } + Long courseId = courseCla.getCourseId(); + ScCourse scCourse = courseService.getById(courseId); + if(null == scCourse) { + return APIResponse.toExceptionResponse("无法获取课程,无法删除"); + } + SysDept sysDept = deptService.getById(courseCla.getDepartId()); + if (null == sysDept) { + return APIResponse.toExceptionResponse("无法获取校区信息,请稍后重试"); + } + + + List dbAttendList = claTimeAttendService.getAttendList(courseTimeId); + + // 删除原上课记录 + for (ScClaTimeAttend claTimeAttend : dbAttendList) { + // 学员日志 使用 + claTime.setCourseName(scCourse.getCourseName()); + claTime.setClaName(courseCla.getClaName()); + claTime.setDeptName(sysDept.getDeptName()); + // 恢复学员课时 + studentCourseService.recoverStudentCourseHour(claTimeAttend, claTime, loginUser); + } + + // 删除上课记录明细 cla_time_attend + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("course_time_id", courseTimeId); + claTimeAttendService.remove(uw); + + // 重新记上课 + return businessScStudentCourseService.claTimeAttend(reqClaTimeAttend); + } + + /** + * 删除已上课记录 + * + * @param courseTimeId + * @return + */ + public APIResponse deleteHadClaTimeAttend(Long courseTimeId) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + ScClaTime claTime = claTimeService.getById(courseTimeId); + if (null == claTime) { + return APIResponse.toExceptionResponse("无法获取上课信息"); + } + String status = claTime.getStatus(); + if (!"2".equals(status)) { + return APIResponse.toExceptionResponse("暂未上课,无法删除"); + } + + Long claId = claTime.getClaId(); + ScCourseCla courseCla = claService.getById(claId); + if(null == courseCla) { + return APIResponse.toExceptionResponse("无法获取班级,无法删除"); + } + Long courseId = courseCla.getCourseId(); + ScCourse scCourse = courseService.getById(courseId); + if(null == scCourse) { + return APIResponse.toExceptionResponse("无法获取课程,无法删除"); + } + SysDept sysDept = deptService.getById(courseCla.getDepartId()); + if (null == sysDept) { + return APIResponse.toExceptionResponse("无法获取校区信息,请稍后重试"); + } + + // 上课明细 + List claTimeAttendList = claTimeAttendService.getAttendList(courseTimeId); + + for (ScClaTimeAttend claTimeAttend : claTimeAttendList) { + // 学员日志 使用 + claTime.setCourseName(scCourse.getCourseName()); + claTime.setClaName(courseCla.getClaName()); + claTime.setDeptName(sysDept.getDeptName()); + + // 恢复学员课时 + studentCourseService.recoverStudentCourseHour(claTimeAttend, claTime, loginUser); + } + + // 删除上课记录明细 cla_time_attend + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("course_time_id", courseTimeId); + claTimeAttendService.remove(uw); + + // 删除上课记录 cla_time + claTimeService.removeById(courseTimeId); + + return APIResponse.toOkResponse(); + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScClaTimeAttendService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScClaTimeAttendService.java new file mode 100644 index 0000000..e26ddae --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScClaTimeAttendService.java @@ -0,0 +1,129 @@ +package cn.xluobo.business.sc.course.service; + +import cn.xluobo.business.sc.course.domain.req.time.ReqSearchScClaTimeAttend; +import cn.xluobo.business.sc.course.domain.resp.time.RespClaTimeAttend; +import cn.xluobo.business.sc.course.repo.mapper.ScClaTimeAttendMapper; +import cn.xluobo.business.sc.course.repo.model.ScClaTimeAttend; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.List; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessScClaTimeAttendService { + + @Autowired + private IScClaTimeAttendService scClaTimeAttendService; + + @Autowired + private ScClaTimeAttendMapper attendMapper; + + /** + * 查询 + * + * @param reqSearchScClaTimeAttend + * @return + */ + public RespPage searchList(ReqSearchScClaTimeAttend reqSearchScClaTimeAttend) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + //reqSearchScClaTimeAttend.setTenantId(loginUser.getNowTenantId()); + RespPage page = new RespPage(reqSearchScClaTimeAttend.getPageNum(), reqSearchScClaTimeAttend.getPageSize()); + List attendList = attendMapper.selectTimeAttendList(reqSearchScClaTimeAttend, page); + page.setRows(attendList); + return page; + } + + /** + * 已上课 出席详情 + * + * @param courseTimeId + * @return + */ + public APIResponse hadClaTimeAttendDetail(Long courseTimeId) { + QueryWrapper qwAttend = new QueryWrapper<>(); + qwAttend.select("student_course_id", "attend_status", "memo", "pay_hour"); + qwAttend.eq("course_time_id", courseTimeId); + List claTimeAttendList = scClaTimeAttendService.list(qwAttend); + return APIResponse.toAPIResponse(claTimeAttendList); + } + + /** + * 详情 + * + * @param attendId + * @return + */ + public APIResponse detailById(Long attendId) { + if (null == attendId) { + return APIResponse.toAPIResponse(null); + } + ScClaTimeAttend detailInfo = scClaTimeAttendService.getById(attendId); + return APIResponse.toAPIResponse(detailInfo); + } + + /** + * 添加 + * + * @param scClaTimeAttend + * @return + */ + public APIResponse addScClaTimeAttend(ScClaTimeAttend scClaTimeAttend) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + scClaTimeAttend.setCreateUser(loginUser.getUserId()); + boolean addScClaTimeAttend = scClaTimeAttendService.save(scClaTimeAttend); + if (addScClaTimeAttend) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 更新 + * + * @param scClaTimeAttend + * @return + */ + public APIResponse updateScClaTimeAttend(ScClaTimeAttend scClaTimeAttend) { + if (null == scClaTimeAttend.getAttendId()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + boolean updateScClaTimeAttend = scClaTimeAttendService.updateById(scClaTimeAttend); + if (updateScClaTimeAttend) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 删除 + * + * @param attendIds + * @return + */ + public APIResponse deleteById(Long[] attendIds) { + if (null == attendIds || attendIds.length == 0) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + boolean deleteScClaTimeAttend = scClaTimeAttendService.removeByIds(Arrays.asList(attendIds)); + if (deleteScClaTimeAttend) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScCourseClaService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScCourseClaService.java new file mode 100644 index 0000000..8ec3029 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScCourseClaService.java @@ -0,0 +1,275 @@ +package cn.xluobo.business.sc.course.service; + +import cn.xluobo.business.sc.course.domain.req.ReqAddScCourseCla; +import cn.xluobo.business.sc.course.domain.req.ReqSearchScCourseCla; +import cn.xluobo.business.sc.course.domain.resp.RespBusinessChooseCourseCharge; +import cn.xluobo.business.sc.course.domain.resp.RespCourseClaInfo; +import cn.xluobo.business.sc.course.domain.resp.cla.RespClaAllDetailInfo; +import cn.xluobo.business.sc.course.repo.mapper.ScCourseClaMapper; +import cn.xluobo.business.sc.course.repo.model.ScClaTime; +import cn.xluobo.business.sc.course.repo.model.ScCourse; +import cn.xluobo.business.sc.course.repo.model.ScCourseCla; +import cn.xluobo.business.sc.student.repo.mapper.ScStudentMapper; +import cn.xluobo.business.sc.student.repo.model.ScStudentCourse; +import cn.xluobo.business.sc.student.service.IScStudentCourseService; +import cn.xluobo.business.sc.student.service.IScStudentService; +import cn.xluobo.business.sys.admin.service.ISysDeptService; +import cn.xluobo.business.sys.staff.repo.model.SysStaff; +import cn.xluobo.business.sys.staff.service.ISysStaffService; +import cn.xluobo.core.api.APIBaseResponse; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.google.common.collect.Maps; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessScCourseClaService { + + @Autowired + private IScCourseClaService scCourseClaService; + @Autowired + private IScCourseService courseService; + @Autowired + private IScCourseChargeService courseChargeService; + @Autowired + private ISysStaffService teacherService; + @Autowired + private ScCourseClaMapper scCourseClaMapper; + @Autowired + private ScStudentMapper studentMapper; + @Autowired + private IScStudentService studentService; + @Autowired + private IScStudentCourseService studentCourseService; + @Autowired + private ISysDeptService deptService; + @Autowired + private IScClaTimeRuleService claTimeRuleService; + @Autowired + private IScClaTimeService claTimeService; + + /** + * 查询 + * + * @param reqSearchScCourseCla + * @return + */ + public APIResponse searchList(ReqSearchScCourseCla reqSearchScCourseCla) { + RespPage page = new RespPage(reqSearchScCourseCla.getPageNum(), reqSearchScCourseCla.getPageSize()); + List claList = scCourseClaMapper.selectClaList(reqSearchScCourseCla, page); + page.setRows(claList); + return APIResponse.toAPIResponse(page); + } + + /** + * 详情 + * + * @param claId + * @return + */ + public APIResponse detailById(Long claId) { + if (null == claId) { + return APIResponse.toAPIResponse(null); + } + Map resultMap = Maps.newHashMap(); + // 班级信息 + ScCourseCla detailInfo = scCourseClaService.getById(claId); + if (null == detailInfo) { + return APIResponse.toAPIResponse(null); + } + // 课程信息 + ScCourse scCourse = courseService.getById(detailInfo.getCourseId()); + // 是否允许变更课程,有报名不允许变更课程 + APIBaseResponse canChangeCourse = scCourseClaService.canChangeCourse(claId); + resultMap.put("canChangeCourse", canChangeCourse.isSuccess()); + + resultMap.put("claInfo", detailInfo); + resultMap.put("claCourseInfo", scCourse); + + return APIResponse.toAPIResponse(resultMap); + } + + /** + * 班级详情 + * + * @param claId + * @return + */ + public RespClaAllDetailInfo allDetailInfoById(Long claId) { + if (null == claId) { + return null; + } + // 班级信息 + ScCourseCla courseCla = scCourseClaService.getById(claId); + if (null == courseCla) { + return null; + } + + // 班级当前学员数量 + Integer studentCnt = scCourseClaService.selectStudentCnt(claId); + courseCla.setStudentCnt(studentCnt); + + // 课程信息 + ScCourse scCourse = courseService.getById(courseCla.getCourseId()); + + + // 课程收费信息 + List courseChargeList = courseChargeService.courseChargeList(scCourse.getCourseId(), null); + + // 校区 + if (null != courseCla.getDepartId()) { + SysDept sysDept = deptService.getById(courseCla.getDepartId()); + courseCla.setDeptName(sysDept.getDeptName()); + } + + // 教师 + if (null != courseCla.getStaffId()) { + SysStaff staff = teacherService.getById(courseCla.getStaffId()); + courseCla.setTeacherName(staff.getStaffName()); + } + + // 上课时间 + List claTimeInfo = claTimeRuleService.selectClaTimeInfo(claId); + + return RespClaAllDetailInfo.builder() + .courseCla(courseCla) + .course(scCourse) + .courseChargeList(courseChargeList) + .claTimeList(claTimeInfo) + .build(); + } + + /** + * 添加 + * + * @param scCourseCla + * @return + */ + public APIResponse addScCourseCla(ReqAddScCourseCla scCourseCla) { + + LoginUser loginUser = SecurityUtils.getLoginUser(); + + // 课程编号是否存在 + ScCourse course = courseService.getById(scCourseCla.getCourseId()); + if (null == course) { + return APIResponse.toExceptionResponse("课程不存在,请重新选择后提交。"); + } + + // 教师是否存在 + SysStaff teacher = teacherService.getById(scCourseCla.getStaffId()); + if (null == teacher) { + return APIResponse.toExceptionResponse("教师不存在,请重新选择后提交。"); + } + + // 新建班级 + ScCourseCla cla = scCourseCla.getScCourseCla(loginUser); + APIBaseResponse checkParam = cla.checkParam(); + if (!checkParam.isSuccess()) { + return APIResponse.toExceptionResponse(checkParam.getRespMsg()); + } + boolean addScCourseCla = scCourseClaService.save(cla); + if (addScCourseCla) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 更新 + * + * @param scCourseCla + * @return + */ + public APIResponse updateScCourseCla(ScCourseCla scCourseCla) { + if (null == scCourseCla.getClaId()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + + ScCourseCla dbClaInfo = scCourseClaService.getById(scCourseCla.getClaId()); + Long dbCourseId = dbClaInfo.getCourseId(); + + // 课程编号是否存在 + ScCourse course = courseService.getById(scCourseCla.getCourseId()); + if (null == course) { + return APIResponse.toExceptionResponse("课程不存在,请重新选择后提交。"); + } + + // 教师是否存在 + SysStaff teacher = teacherService.getById(scCourseCla.getStaffId()); + if (null == teacher) { + return APIResponse.toExceptionResponse("教师不存在,请重新选择后提交。"); + } + + // 修改课程,校验是否允许修改所属课程 + if (!dbCourseId.equals(scCourseCla.getCourseId())) { + APIBaseResponse canChangeCourse = scCourseClaService.canChangeCourse(scCourseCla.getClaId()); + if (!canChangeCourse.isSuccess()) { + return APIResponse.toExceptionResponse(canChangeCourse.getRespMsg()); + } + } + + LoginUser loginUser = SecurityUtils.getLoginUser(); + scCourseCla.setLastUpdateUser(loginUser.getUserId()); + scCourseCla.setLastUpdateTime(new Date()); + boolean updateScCourseCla = scCourseClaService.updateById(scCourseCla); + if (updateScCourseCla) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 删除 + * + * @param claIds + * @return + */ + public APIResponse deleteById(Long[] claIds) { + if (null == claIds || claIds.length == 0) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + + // 有学员无法 删除 + QueryWrapper qwSc = new QueryWrapper<>(); + qwSc.in("cla_id", claIds); + int studentCourseCount = studentCourseService.count(qwSc); + if (studentCourseCount != 0) { + return APIResponse.toExceptionResponse("该班级内有学员,无法删除班级"); + } + + // 已排课不允许删除 + QueryWrapper qwSct = new QueryWrapper<>(); + qwSct.in("cla_id", claIds); + int claTimeCount = claTimeService.count(qwSct); + if (claTimeCount != 0) { + return APIResponse.toExceptionResponse("该班级已排课,无法删除班级"); + } + + boolean deleteScCourseCla = scCourseClaService.removeByIds(Arrays.asList(claIds)); + + if (deleteScCourseCla) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScCourseService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScCourseService.java new file mode 100644 index 0000000..5deb5e0 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScCourseService.java @@ -0,0 +1,537 @@ +package cn.xluobo.business.sc.course.service; + +import cn.xluobo.business.sc.course.domain.export.ExpCourse; +import cn.xluobo.business.sc.course.domain.req.ReqBusinessOrderCourseDetail; +import cn.xluobo.business.sc.course.domain.req.ReqSearchScCourse; +import cn.xluobo.business.sc.course.domain.req.ReqSelect; +import cn.xluobo.business.sc.course.domain.req.course.ReqAddScCourse; +import cn.xluobo.business.sc.course.domain.req.course.ReqAddScCourseChargeItem; +import cn.xluobo.business.sc.course.domain.req.course.ReqChangeScCourse; +import cn.xluobo.business.sc.course.domain.resp.RespBusinessChooseCourseCharge; +import cn.xluobo.business.sc.course.domain.resp.RespBusinessChooseCourseInfo; +import cn.xluobo.business.sc.course.domain.resp.course.RespScCourseDetail; +import cn.xluobo.business.sc.course.domain.resp.course.RespSearchCourse; +import cn.xluobo.business.sc.course.repo.mapper.ScCourseMapper; +import cn.xluobo.business.sc.course.repo.model.ScCourse; +import cn.xluobo.business.sc.course.repo.model.ScCourseCharge; +import cn.xluobo.business.sc.course.repo.model.ScCourseCla; +import cn.xluobo.business.sc.course.repo.model.ScCourseType; +import cn.xluobo.business.sc.student.repo.model.ScStudentCourse; +import cn.xluobo.business.sc.student.service.IScStudentCourseService; +import cn.xluobo.business.sys.admin.domain.resp.RespTreeSelect; +import cn.xluobo.business.sys.admin.service.BusinessSysDeptService; +import cn.xluobo.business.sys.admin.service.BusinessSysDictDataService; +import cn.xluobo.business.sys.admin.service.ISysDeptService; +import cn.xluobo.business.tool.export.strategy.CourseExportMergeStrategy; +import cn.xluobo.config.properties.UploadConfigProperties; +import cn.xluobo.core.api.APIBaseResponse; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessScCourseService { + + @Autowired + private IScCourseService scCourseService; + @Autowired + private IScCourseClaService courseClaService; + @Autowired + private ScCourseMapper courseMapper; + @Autowired + private IScCourseChargeService courseChargeService; + @Autowired + private BusinessSysDeptService deptService; + @Autowired + private ISysDeptService sysDeptService; + @Autowired + private UploadConfigProperties uploadConfigProperties; + @Autowired + private BusinessSysDictDataService dictDataService; + @Autowired + private IScStudentCourseService studentCourseService; + @Autowired + private IScCourseTypeService courseTypeService; + + /** + * 查询 + * + * @param reqSearchScCourse + * @return + */ + public APIResponse searchList(ReqSearchScCourse reqSearchScCourse) { + RespPage searchCourseRespPage = scCourseService.searchCourse(reqSearchScCourse); + return APIResponse.toAPIResponse(searchCourseRespPage); + } + + /** + * 查询课程列表 + * 含有学生报读状态 + * + * @param reqSearchScCourse + * @return + */ + public APIResponse selectCourseListWithStudentCourse(ReqSearchScCourse reqSearchScCourse) { + RespPage respPage = new RespPage(reqSearchScCourse.getPageNum(), reqSearchScCourse.getPageSize()); + List courseList = courseMapper.selectCourseListWithStudentCourse(reqSearchScCourse, respPage); + respPage.setRows(courseList); + return APIResponse.toAPIResponse(respPage); + } + + /** + * 前端select + * + * @return + */ + public APIResponse select(ReqSelect reqSelect) { + QueryWrapper qw = new QueryWrapper(); + qw.select("course_name", "course_id"); + + if (StringUtils.isNotEmpty(reqSelect.getSearch())) { + qw.like("course_name", reqSelect.getSearch()); + } + + qw.orderByDesc("create_time"); + List list = scCourseService.list(qw); + return APIResponse.toAPIResponse(list); + } + + /** + * 详情 + * + * @param courseId + * @return + */ + public APIResponse detailById(Long courseId) { + if (null == courseId) { + return APIResponse.toAPIResponse(ApiResEnums.PARAM_FAIL); + } + + // 课程详情 + ScCourse detailInfo = scCourseService.getById(courseId); + + + RespScCourseDetail respScCourseDetail = new RespScCourseDetail(); + respScCourseDetail.setCourseId(detailInfo.getCourseId()); + respScCourseDetail.setCourseName(detailInfo.getCourseName()); + respScCourseDetail.setCourseTypeId(detailInfo.getCourseTypeId()); + respScCourseDetail.setTeachingMode(detailInfo.getTeachingMode()); + respScCourseDetail.setCourseIntro(detailInfo.getCourseIntro()); + respScCourseDetail.setCourseCampus("part"); + respScCourseDetail.setPartCampus(new String[]{}); + + if(null != detailInfo.getCourseTypeId()) { + ScCourseType courseType = courseTypeService.getById(detailInfo.getCourseTypeId()); + respScCourseDetail.setCourseTypeName(courseType.getCourseType()); + } + + + + List feeModeHourList = Lists.newArrayList(); + List feeModeDateList = Lists.newArrayList(); + List feeModeCycleList = Lists.newArrayList(); + + // 上课校区 + List partCampusList = Lists.newArrayList(); + + // 所有校区id 对应名称 map + Map campusMap = Maps.newHashMap(); + List campusList = deptService.campusList(); + for (RespTreeSelect respTreeSelect : campusList) { + campusMap.put(respTreeSelect.getId(), respTreeSelect.getLabel()); + } + campusMap.put(-1L, "全部校区"); + + // 课程收费配置信息 + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("course_id", detailInfo.getCourseId()); + List courseChargeList = courseChargeService.list(qw); + for (ScCourseCharge courseCharge : courseChargeList) { + ReqAddScCourseChargeItem chargeItem = new ReqAddScCourseChargeItem(); + Long departId = courseCharge.getDepartId(); + if (!partCampusList.contains(departId.toString()) && departId.compareTo(-1L) != 0) { + partCampusList.add(departId.toString()); + } + String chargeType = courseCharge.getChargeType(); + chargeItem.setChargeId(courseCharge.getChargeId()); + chargeItem.setCampusId(courseCharge.getDepartId()); + chargeItem.setCampusName(campusMap.get(courseCharge.getDepartId().toString())); + if ("hour".equals(chargeType)) { + chargeItem.setCnt(courseCharge.getCount()); + chargeItem.setTotalFee(courseCharge.getTotalFee()); + feeModeHourList.add(chargeItem); + } else if ("date".equals(chargeType)) { + chargeItem.setCnt(courseCharge.getCount()); + chargeItem.setTotalFee(courseCharge.getTotalFee()); + chargeItem.setDateType(courseCharge.getDateUnit()); + feeModeDateList.add(chargeItem); + } else if ("cycle".equals(chargeType)) { + chargeItem.setCnt(courseCharge.getCount()); + chargeItem.setTotalFee(courseCharge.getTotalFee()); + feeModeCycleList.add(chargeItem); + } + } + + // 上课校区 所有或部分校区 + if (partCampusList.size() == 0) { + respScCourseDetail.setCourseCampus("all"); + } else { + respScCourseDetail.setCourseCampus("part"); + respScCourseDetail.setPartCampus(partCampusList.toArray(new String[partCampusList.size()])); + } + + respScCourseDetail.setFeeModeHourList(feeModeHourList); + respScCourseDetail.setFeeModeDateList(feeModeDateList); + respScCourseDetail.setFeeModeCycleList(feeModeCycleList); + if (!feeModeHourList.isEmpty()) { + respScCourseDetail.setFeeModeHour(true); + } + if (!feeModeDateList.isEmpty()) { + respScCourseDetail.setFeeModeDate(true); + } + if (!feeModeCycleList.isEmpty()) { + respScCourseDetail.setFeeModeCycle(true); + } + + return APIResponse.toAPIResponse(respScCourseDetail); + } + + /** + * 添加课程 + * + * @param reqAddScCourse + * @return + */ + public APIResponse addScCourse(ReqAddScCourse reqAddScCourse) { + APIBaseResponse checkParam = reqAddScCourse.checkParam(); + if (!checkParam.isSuccess()) { + return APIResponse.toExceptionResponse(checkParam.getRespMsg()); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + + // course 表保存 + ScCourse scCourse = new ScCourse(); + scCourse.setCourseName(reqAddScCourse.getCourseName()); + scCourse.setCourseTypeId(reqAddScCourse.getCourseTypeId()); + scCourse.setTeachingMode(reqAddScCourse.getTeachingMode()); + scCourse.setCourseIntro(reqAddScCourse.getCourseIntro()); + scCourse.setCreateUser(loginUser.getUserId()); + scCourse.setLastUpdateUser(loginUser.getUserId()); + boolean addScCourse = scCourseService.save(scCourse); + + // course_charge保存 + + // 按课时收费 + if (reqAddScCourse.isFeeModeHour()) { + List feeModeHourList = reqAddScCourse.getFeeModeHourList(); + feeModeHourList.forEach(item -> { + ScCourseCharge courseCharge = new ScCourseCharge(); + courseCharge.setCourseId(scCourse.getCourseId()); + courseCharge.setDepartId(item.getCampusId()); + courseCharge.setChargeType("hour"); + courseCharge.setCount(item.getCnt()); + courseCharge.setTotalFee(item.getTotalFee()); + courseChargeService.save(courseCharge); + }); + } + + // 按时间收费 + if (reqAddScCourse.isFeeModeDate()) { + List feeModeDateList = reqAddScCourse.getFeeModeDateList(); + feeModeDateList.forEach(item -> { + ScCourseCharge courseCharge = new ScCourseCharge(); + courseCharge.setCourseId(scCourse.getCourseId()); + courseCharge.setDepartId(item.getCampusId()); + courseCharge.setChargeType("date"); + courseCharge.setCount(item.getCnt()); + courseCharge.setTotalFee(item.getTotalFee()); + courseCharge.setDateUnit(item.getDateType()); + courseChargeService.save(courseCharge); + }); + } + + // 按期收费 + if (reqAddScCourse.isFeeModeCycle()) { + List feeModeCycleList = reqAddScCourse.getFeeModeCycleList(); + feeModeCycleList.forEach(item -> { + ScCourseCharge courseCharge = new ScCourseCharge(); + courseCharge.setCourseId(scCourse.getCourseId()); + courseCharge.setDepartId(item.getCampusId()); + courseCharge.setChargeType("cycle"); + courseCharge.setCount(item.getCnt()); + courseCharge.setTotalFee(item.getTotalFee()); + courseChargeService.save(courseCharge); + }); + } + + return APIResponse.toOkResponse(); + } + + /** + * 更新 + * + * @param reqChangeScCourse + * @return + */ + public APIResponse updateScCourse(ReqChangeScCourse reqChangeScCourse) { + APIBaseResponse checkParam = reqChangeScCourse.checkParam(); + if (!checkParam.isSuccess()) { + return APIResponse.toExceptionResponse(checkParam.getRespMsg()); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + + // 更新课程信息 + ScCourse updateCourse = new ScCourse(); + updateCourse.setCourseId(reqChangeScCourse.getCourseId()); + updateCourse.setCourseName(reqChangeScCourse.getCourseName()); + updateCourse.setCourseTypeId(reqChangeScCourse.getCourseTypeId()); + updateCourse.setTeachingMode(reqChangeScCourse.getTeachingMode()); + updateCourse.setCourseIntro(reqChangeScCourse.getCourseIntro()); + updateCourse.setLastUpdateUser(loginUser.getUserId()); + updateCourse.setLastUpdateTime(new Date()); + boolean updateScCourse = scCourseService.updateById(updateCourse); + + // course_charge 删除 + UpdateWrapper uw = new UpdateWrapper(); + uw.eq("course_id", updateCourse.getCourseId()); + courseChargeService.remove(uw); + + // course_charge 新增 + + // 按课时收费 + if (reqChangeScCourse.isFeeModeHour()) { + List feeModeHourList = reqChangeScCourse.getFeeModeHourList(); + feeModeHourList.forEach(item -> { + ScCourseCharge courseCharge = new ScCourseCharge(); + courseCharge.setCourseId(updateCourse.getCourseId()); + courseCharge.setDepartId(item.getCampusId()); + courseCharge.setChargeType("hour"); + courseCharge.setCount(item.getCnt()); + courseCharge.setTotalFee(item.getTotalFee()); + courseChargeService.save(courseCharge); + }); + } + + // 按时间收费 + if (reqChangeScCourse.isFeeModeDate()) { + List feeModeDateList = reqChangeScCourse.getFeeModeDateList(); + feeModeDateList.forEach(item -> { + ScCourseCharge courseCharge = new ScCourseCharge(); + courseCharge.setCourseId(updateCourse.getCourseId()); + courseCharge.setDepartId(item.getCampusId()); + courseCharge.setChargeType("date"); + courseCharge.setCount(item.getCnt()); + courseCharge.setTotalFee(item.getTotalFee()); + courseCharge.setDateUnit(item.getDateType()); + courseChargeService.save(courseCharge); + }); + } + + // 按期收费 + if (reqChangeScCourse.isFeeModeCycle()) { + List feeModeCycleList = reqChangeScCourse.getFeeModeCycleList(); + feeModeCycleList.forEach(item -> { + ScCourseCharge courseCharge = new ScCourseCharge(); + courseCharge.setCourseId(updateCourse.getCourseId()); + courseCharge.setDepartId(item.getCampusId()); + courseCharge.setChargeType("cycle"); + courseCharge.setCount(item.getCnt()); + courseCharge.setTotalFee(item.getTotalFee()); + courseChargeService.save(courseCharge); + }); + } + + return APIResponse.toOkResponse(); + } + + /** + * 删除 + * + * @param courseIds + * @return + */ + public APIResponse deleteById(List courseIds) { + if (null == courseIds || courseIds.isEmpty()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + + // 如课程对应在用班级,不允许删除 + QueryWrapper qw = new QueryWrapper<>(); + qw.in("course_id", courseIds); + int courseClaCount = courseClaService.count(qw); + if (courseClaCount != 0) { + return APIResponse.toExceptionResponse("该课程下存在在用班级,无法删除课程"); + } + + // 有报读记录 不允许删除 + QueryWrapper qwSc = new QueryWrapper<>(); + qwSc.in("course_id", courseIds); + int studentCourseCount = studentCourseService.count(qwSc); + if (studentCourseCount != 0) { + return APIResponse.toExceptionResponse("该课程已报读,无法删除课程"); + } + + boolean deleteScCourse = scCourseService.removeByIds(courseIds); + if (deleteScCourse) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 变更是否开售 + * + * @param scCourse + * @return + */ + public APIResponse changeCourseSale(ScCourse scCourse) { + if (null == scCourse.getCourseId()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + if (StringUtils.isEmpty(scCourse.getSale())) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + UpdateWrapper uw = new UpdateWrapper(); + uw.set("sale", scCourse.getSale()); + uw.eq("course_id", scCourse.getCourseId()); + boolean updateScCourse = scCourseService.update(uw); + if (updateScCourse) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 导出课程 + * + * @param reqSearchScCourse + * @return + */ + public APIResponse exportCourse(ReqSearchScCourse reqSearchScCourse) { + try { + List courseList = courseMapper.selectCourseForExport(reqSearchScCourse); + String fileName = "exportCourse_" + System.currentTimeMillis() + UUID.randomUUID().toString(); + String fullPath = uploadConfigProperties.getTempSaveExportPath() + "/" + fileName + ".xlsx"; + CourseExportMergeStrategy mergeStrategy = new CourseExportMergeStrategy<>(courseList, 0, 6); + EasyExcel.write(fullPath, ExpCourse.class) + .registerWriteHandler(mergeStrategy) + .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) + .sheet("课程列表").doWrite(courseList); + return APIResponse.toAPIResponse(fileName); + } catch (Exception e) { + return APIResponse.toExceptionResponse("下载文件失败" + e.getMessage()); + } + } + + /** + * 报名-课程详情 + * + * @param orderCourseDetail + * @return + */ + public APIResponse orderCourseDetail(ReqBusinessOrderCourseDetail orderCourseDetail) { + Long[] courseIds = orderCourseDetail.getCourseIds(); + Long deptId = orderCourseDetail.getDeptId(); + Long studentId = orderCourseDetail.getStudentId(); + + if (null == courseIds || courseIds.length == 0) { + return APIResponse.toExceptionResponse("请选择课程"); + } + + if (null == deptId) { + return APIResponse.toExceptionResponse("请选择校区"); + } + + // 校验学生是否可报读 课程 + APIBaseResponse studentCanSignUpCourse = studentCourseService.checkStudentCanSignUpCourse(studentId, courseIds, deptId); + if (!studentCanSignUpCourse.isSuccess()) { + return APIResponse.toExceptionResponse(studentCanSignUpCourse.getRespMsg()); + } + + // 学生已报名课程收费模式 + Map studentCourseChargeTypeMap = Maps.newHashMap(); + if (null != studentId) { + QueryWrapper qw = new QueryWrapper(); + qw.select("course_id", "charge_type"); + qw.eq("student_id", studentId); + List studentCourseList = studentCourseService.list(qw); + studentCourseChargeTypeMap = studentCourseList.stream().collect(Collectors.toMap(ScStudentCourse::getCourseId, ScStudentCourse::getChargeType)); + } + + // 部门信息 + SysDept sysDept = sysDeptService.getById(deptId); + + List courseInfoList = Lists.newArrayList(); + for (Long courseId : courseIds) { + ScCourse scCourse = scCourseService.getById(courseId); + if (null == scCourse) { + continue; + } + RespBusinessChooseCourseInfo chooseCourseInfo = RespBusinessChooseCourseInfo.builder() + .courseId(scCourse.getCourseId()) + .courseName(scCourse.getCourseName()) + .deptId(sysDept.getDeptId()) + .deptName(sysDept.getDeptName()) + .teachingMode(scCourse.getTeachingMode()) + .build(); + + // 已报读的 收费方式 + String studentCourseChargeType = studentCourseChargeTypeMap.get(courseId); + + // 转换对象 + List chooseCourseChargeList = courseChargeService.courseChargeList(courseId, studentCourseChargeType); + + chooseCourseInfo.setCourseChargeList(chooseCourseChargeList); + // 是否为续报 + chooseCourseInfo.setContinueCourse(StringUtils.isNotEmpty(studentCourseChargeType)); + courseInfoList.add(chooseCourseInfo); + } + return APIResponse.toAPIResponse(courseInfoList); + } + + /** + * 学生是否可报名 课程 + * + * @param orderCourseDetail + * @return + */ + public APIResponse studentCanSignUpCourse(ReqBusinessOrderCourseDetail orderCourseDetail) { + Long[] courseIds = orderCourseDetail.getCourseIds(); + Long studentId = orderCourseDetail.getStudentId(); + if (null == studentId) { + return APIResponse.toExceptionResponse("studentId 不能为空"); + } + if (null == courseIds || courseIds.length == 0) { + return APIResponse.toOkResponse(); + } + APIBaseResponse studentCanSignUpCourse = studentCourseService.checkStudentCanSignUpCourse(studentId, courseIds, null); + if (!studentCanSignUpCourse.isSuccess()) { + return APIResponse.toExceptionResponse(studentCanSignUpCourse.getRespMsg()); + } + + return APIResponse.toOkResponse(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScCourseTypeService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScCourseTypeService.java new file mode 100644 index 0000000..4c27a46 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/BusinessScCourseTypeService.java @@ -0,0 +1,140 @@ +package cn.xluobo.business.sc.course.service; + +import cn.xluobo.business.sc.course.domain.req.ReqSearchScCourseType; +import cn.xluobo.business.sc.course.repo.model.ScCourse; +import cn.xluobo.business.sc.course.repo.model.ScCourseType; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.List; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessScCourseTypeService { + + @Autowired + private IScCourseTypeService scCourseTypeService; + @Autowired + private IScCourseService courseService; + + /** + * 查询 + * + * @param reqSearchScCourseType + * @return + */ + public APIResponse searchList(ReqSearchScCourseType reqSearchScCourseType) { + QueryWrapper qw = new QueryWrapper(); + if (StringUtils.isNotEmpty(reqSearchScCourseType.getCourseType())) { + qw.eq("course_type", reqSearchScCourseType.getCourseType()); + } + RespPage page = new RespPage(reqSearchScCourseType.getPageNum(), reqSearchScCourseType.getPageSize()); + RespPage listPage = scCourseTypeService.page(page, qw); + return APIResponse.toAPIResponse(listPage); + } + + /** + * select + * @param reqSearchScCourseType + * @return + */ + public APIResponse select(ReqSearchScCourseType reqSearchScCourseType) { + QueryWrapper qw = new QueryWrapper(); + qw.select("course_type", "course_type_id"); + if (StringUtils.isNotEmpty(reqSearchScCourseType.getCourseType())) { + qw.like("course_type", reqSearchScCourseType.getCourseType()); + } + qw.eq("in_use", "1"); + qw.orderByDesc("create_time"); + List list = scCourseTypeService.list(qw); + return APIResponse.toAPIResponse(list); + } + + /** + * 详情 + * + * @param courseTypeId + * @return + */ + public APIResponse detailById(Long courseTypeId) { + if (null == courseTypeId) { + return APIResponse.toAPIResponse(null); + } + ScCourseType detailInfo = scCourseTypeService.getById(courseTypeId); + return APIResponse.toAPIResponse(detailInfo); + } + + /** + * 添加 + * + * @param scCourseType + * @return + */ + public APIResponse addScCourseType(ScCourseType scCourseType) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + scCourseType.setCreateUser(loginUser.getUserId()); + boolean addScCourseType = scCourseTypeService.save(scCourseType); + if (addScCourseType) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 更新 + * + * @param scCourseType + * @return + */ + public APIResponse updateScCourseType(ScCourseType scCourseType) { + if (null == scCourseType.getCourseTypeId()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + boolean updateScCourseType = scCourseTypeService.updateById(scCourseType); + if (updateScCourseType) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 删除 + * + * @param courseTypeIds + * @return + */ + public APIResponse deleteById(Long[] courseTypeIds) { + if (null == courseTypeIds || courseTypeIds.length == 0) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("course_type_id", courseTypeIds); + int courseCount = courseService.count(qw); + if (courseCount != 0) { + return APIResponse.toExceptionResponse("已有课程使用,无法删除"); + } + + boolean deleteScCourseType = scCourseTypeService.removeByIds(Arrays.asList(courseTypeIds)); + if (deleteScCourseType) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScClaTimeAttendService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScClaTimeAttendService.java new file mode 100644 index 0000000..0f7e702 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScClaTimeAttendService.java @@ -0,0 +1,69 @@ +package cn.xluobo.business.sc.course.service; + +import cn.xluobo.business.sc.course.domain.req.time.ReqClaTimeCount; +import cn.xluobo.business.sc.course.repo.model.ScClaTimeAttend; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 上课出勤表 服务类 + *

+ * + * @author zhangby + * @since 2020-09-30 02:33:26 + */ +public interface IScClaTimeAttendService extends com.baomidou.mybatisplus.extension.service.IService { + + /** + * 学生报的的课程,指定日期 上课记录 数量 + * @param studentCourseId + * @param beginDate + * @param endDate + * @return + */ + int studentCourseAttendCount(Long studentCourseId, String beginDate, String endDate); + + /** + * 指定时间段内应出席人次 + * @param beginDate + * @param endDate + * @return + */ + Integer getNeedAttendCount(String beginDate, String endDate); + + /** + * 指定时间段内上课人次 + * @param beginDate + * @param endDate + * @param attendStatus 到课状态 + * @return + */ + Integer getAttendCount(String beginDate, String endDate, String[] attendStatus); + + /** + * 消耗课时 + * @param beginDate + * @param endDate + * @param needAttend 是否应消 + * @return + */ + BigDecimal getAttendCostHour(String beginDate, String endDate, boolean needAttend); + + /** + * 教师获得课时数量 + * 只统计按课时收费 + * + * @param reqClaTimeCount + * @return + */ + BigDecimal getTeacherGetHour(ReqClaTimeCount reqClaTimeCount); + + /** + * 上课记录 + * @param courseTimeId + * @return + */ + List getAttendList(Long courseTimeId); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScClaTimeRuleService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScClaTimeRuleService.java new file mode 100644 index 0000000..ef6afc0 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScClaTimeRuleService.java @@ -0,0 +1,80 @@ +package cn.xluobo.business.sc.course.service; + +import cn.xluobo.business.sc.course.domain.req.time.ReqSearchScClaTimeRule; +import cn.xluobo.business.sc.course.domain.resp.time.RespClaTimeRule; +import cn.xluobo.business.sc.course.repo.model.ScClaTimeRule; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 上课时间配置规则 服务类 + *

+ * + * @author zhangby + * @since 2020-09-14 + */ +public interface IScClaTimeRuleService extends IService { + + /** + * 获取具体上课时间 + * 已排序 + * @param reqSearchScClaTimeRule + * @return 排序后的上课日期 列表 + */ + List getClaTimeList(ReqSearchScClaTimeRule reqSearchScClaTimeRule); + + /** + * 根据 规则获取上课时间 + * 未排序 + * @param ruleId + * @return + */ + List getClaTimeListByRuleId(Long ruleId); + + /** + * 根据 规则获取上课时间 + * 未排序 + * @param itemTime + * @param holidayMap 节假日信息 + * @return + */ + List getClaTimeListByRule(RespClaTimeRule itemTime, Map holidayMap); + + /** + * 根据 规则获取上课时间 + * 未排序 + * @param claTimeRule + * @param holidayMap 节假日信息 + * @return + */ + List getClaTimeListByRule(ScClaTimeRule claTimeRule, Map holidayMap); + + /** + * 校验是否排课 + * 与 sc_cla_time 待上课进行对比 + * @param claId + * @param day 日期 yyyy-MM-dd + * @param notEqRuleId + * @return 重复日期 + */ + List checkDayRepeat(Long claId, String[] day, Long notEqRuleId); + + /** + * 校验排课是否重复 + * 与 sc_cla_time 待上课进行对比 + * @param claTimeRule + * @return 重复日期 + */ + List checkDayRepeat(ScClaTimeRule claTimeRule); + + /** + * 获取上课时间 + * @param claId + * @return + */ + List selectClaTimeInfo(Long claId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScClaTimeService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScClaTimeService.java new file mode 100644 index 0000000..fb717f9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScClaTimeService.java @@ -0,0 +1,32 @@ +package cn.xluobo.business.sc.course.service; + +import cn.xluobo.business.sc.course.domain.req.time.ReqClaTimeCount; +import cn.xluobo.business.sc.course.repo.model.ScClaTime; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 排课信息 服务类 + *

+ * + * @author zhangby + * @since 2020-09-16 + */ +public interface IScClaTimeService extends IService { + + /** + * 删除 状态为 待上课 的排课信息 + * @param ruleId + * @param claId + * @param tenantId + * @return + */ + boolean deleteUnBeginTime(Long ruleId, Long claId, String tenantId); + + /** + * 排课总数量 + * @param reqClaTimeCount + * @return + */ + Integer claTimeCount(ReqClaTimeCount reqClaTimeCount); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseChargeService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseChargeService.java new file mode 100644 index 0000000..abfd781 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseChargeService.java @@ -0,0 +1,33 @@ +package cn.xluobo.business.sc.course.service; + +import cn.xluobo.business.sc.course.domain.resp.RespBusinessChooseCourseCharge; +import cn.xluobo.business.sc.course.repo.model.ScCourseCharge; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 课程收费模式 服务类 + *

+ * + * @author zhangby + * @since 2020-07-08 + */ +public interface IScCourseChargeService extends IService { + + /** + * 收费模式转换 + * @param courseChargeList + * @return + */ + List transferCourseChargeList(List courseChargeList); + + /** + * 课程收费模式 + * @param courseId + * @param chargeType + * @return + */ + List courseChargeList(Long courseId, String chargeType); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseClaService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseClaService.java new file mode 100644 index 0000000..a5f543b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseClaService.java @@ -0,0 +1,31 @@ +package cn.xluobo.business.sc.course.service; + +import cn.xluobo.business.sc.course.repo.model.ScCourseCla; +import cn.xluobo.core.api.APIBaseResponse; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 课程班级信息 服务类 + *

+ * + * @author zhangby + * @since 2020-03-17 01:11:06 + */ +public interface IScCourseClaService extends IService { + + /** + * 班级在读学员数量 + * @param claId + * @return + */ + Integer selectStudentCnt(Long claId); + + /** + * 是否允许变更 班级所属课程 + * @param claId + * @return + */ + APIBaseResponse canChangeCourse(Long claId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseService.java new file mode 100644 index 0000000..da2c799 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseService.java @@ -0,0 +1,25 @@ +package cn.xluobo.business.sc.course.service; + +import cn.xluobo.business.sc.course.domain.req.ReqSearchScCourse; +import cn.xluobo.business.sc.course.domain.resp.course.RespSearchCourse; +import cn.xluobo.business.sc.course.repo.model.ScCourse; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 课程信息 服务类 + *

+ * + * @author zhangby + * @since 2020-03-17 11:25:55 + */ +public interface IScCourseService extends IService { + + /** + * 查询课程列表 + * @param reqSearchScCourse + * @return + */ + RespPage searchCourse(ReqSearchScCourse reqSearchScCourse); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseTypeService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseTypeService.java new file mode 100644 index 0000000..2b5c92c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/IScCourseTypeService.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.sc.course.service; + +import cn.xluobo.business.sc.course.repo.model.ScCourseType; + +/** + *

+ * 课程类型 服务类 + *

+ * + * @author zhangby + * @since 2020-07-09 08:10:25 + */ +public interface IScCourseTypeService extends com.baomidou.mybatisplus.extension.service.IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScClaTimeAttendServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScClaTimeAttendServiceImpl.java new file mode 100644 index 0000000..c7ae33f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScClaTimeAttendServiceImpl.java @@ -0,0 +1,60 @@ +package cn.xluobo.business.sc.course.service.impl; + +import cn.xluobo.business.sc.course.domain.req.time.ReqClaTimeCount; +import cn.xluobo.business.sc.course.repo.mapper.ScClaTimeAttendMapper; +import cn.xluobo.business.sc.course.repo.model.ScClaTimeAttend; +import cn.xluobo.business.sc.course.service.IScClaTimeAttendService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 上课出勤表 服务实现类 + *

+ * + * @author zhangby + * @since 2020-09-30 02:33:26 + */ +@Service +public class ScClaTimeAttendServiceImpl extends ServiceImpl implements IScClaTimeAttendService { + + @Override + public int studentCourseAttendCount(Long studentCourseId, String beginDate, String endDate) { + return baseMapper.selectStudentAttendCount(studentCourseId, beginDate, endDate); + } + + @Override + public Integer getNeedAttendCount(String beginDate, String endDate) { + return baseMapper.selectNeedAttendCount(beginDate, endDate); + } + + @Override + public Integer getAttendCount(String beginDate, String endDate, String[] attendStatus) { + return baseMapper.selectAttendCount(beginDate, endDate, attendStatus); + } + + @Override + public BigDecimal getAttendCostHour(String beginDate, String endDate, boolean needAttend) { + if(needAttend) { + return baseMapper.selectNeedAttendCostHour(beginDate, endDate); + } else { + return baseMapper.selectAttendCostHour(beginDate, endDate); + } + } + + @Override + public BigDecimal getTeacherGetHour(ReqClaTimeCount reqClaTimeCount) { + return baseMapper.selectTeacherSumGetHour(reqClaTimeCount); + } + + @Override + public List getAttendList(Long courseTimeId) { + QueryWrapper qwAttend = new QueryWrapper<>(); + qwAttend.eq("course_time_id", courseTimeId); + return this.list(qwAttend); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScClaTimeRuleServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScClaTimeRuleServiceImpl.java new file mode 100644 index 0000000..85c7ee9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScClaTimeRuleServiceImpl.java @@ -0,0 +1,300 @@ +package cn.xluobo.business.sc.course.service.impl; + +import cn.xluobo.business.sc.course.domain.req.time.ReqSearchScClaTimeRule; +import cn.xluobo.business.sc.course.domain.resp.time.RespClaTimeRule; +import cn.xluobo.business.sc.course.repo.enums.ClaTimeRepeatTypeEnums; +import cn.xluobo.business.sc.course.repo.enums.ClaTimeRuleTypeEnums; +import cn.xluobo.business.sc.course.repo.mapper.ScClaTimeRuleMapper; +import cn.xluobo.business.sc.course.repo.model.ScClaTime; +import cn.xluobo.business.sc.course.repo.model.ScClaTimeRule; +import cn.xluobo.business.sc.course.service.IScClaTimeRuleService; +import cn.xluobo.business.sc.course.service.IScClaTimeService; +import cn.xluobo.business.sys.holiday.service.ISysHolidayService; +import cn.xluobo.core.utils.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.common.collect.Lists; +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + *

+ * 上课时间配置规则 服务实现类 + *

+ * + * @author zhangby + * @since 2020-09-14 + */ +@Service +public class ScClaTimeRuleServiceImpl extends ServiceImpl implements IScClaTimeRuleService { + + @Autowired + private ISysHolidayService holidayService; + @Autowired + private IScClaTimeService claTimeService; + + @Override + public List getClaTimeList(ReqSearchScClaTimeRule reqSearchScClaTimeRule) { + List resultClaTimeList = Lists.newArrayList(); + + // 节假日缓存 + Map holidayMap = holidayService.getHolidayMap(); + + // 获取满足条件的配置 + List ruleList = baseMapper.selectByCondition(reqSearchScClaTimeRule, null); + + DateTime searchBegin = DateUtil.yyyMMddDayBegin(reqSearchScClaTimeRule.getBeginDate()); + DateTime searchEnd = DateUtil.yyyMMddDayEnd(reqSearchScClaTimeRule.getEndDate()); + + for (RespClaTimeRule itemTime : ruleList) { + List claTimeListByRuleId = this.getClaTimeListByRule(itemTime, holidayMap); + resultClaTimeList.addAll(claTimeListByRuleId); + } + + Collections.sort(resultClaTimeList, (o1, o2) -> { + int a = Integer.parseInt(o1.getClaDate().replaceAll("-", "")); + int b = Integer.parseInt(o2.getClaDate().replaceAll("-", "")); + if (a > b) { + return 1; + } else if (a < b) { + return -1; + } else { + return 0; + } + }); + return resultClaTimeList; + } + + @Override + public List getClaTimeListByRuleId(Long ruleId) { + RespClaTimeRule itemTime = baseMapper.selectByRuleId(ruleId); + return this.getClaTimeListByRule(itemTime, null); + } + + @Override + public List getClaTimeListByRule(RespClaTimeRule itemTime, Map holidayMap) { + List resultClaTimeList = Lists.newArrayList(); + + // 节假日缓存 + if (null == holidayMap) { + holidayMap = holidayService.getHolidayMap(); + } + + + String ruleType = itemTime.getRuleType(); + String repeatType = itemTime.getRepeatType(); + String weekDay = itemTime.getWeekDay(); + boolean filterHoliday = itemTime.isFilterHoliday(); + String[] chooseDate = itemTime.getChooseDate(); + + DateTime beginDate = DateUtil.yyyMMddDayBegin(itemTime.getBeginDate()); + DateTime endDate = DateUtil.yyyMMddDayEnd(itemTime.getEndDate()); + + if (ClaTimeRuleTypeEnums.ONCE_RULE.getRuleType().equals(ruleType)) { + + for (String date : chooseDate) { + RespClaTimeRule respClaTime = RespClaTimeRule.builder() + .claName(itemTime.getClaName()) + .courseName(itemTime.getCourseName()) + .staffName(itemTime.getStaffName()) + .claDate(date) + .claTimeBegin(itemTime.getClaTimeBegin()) + .claTimeEnd(itemTime.getClaTimeEnd()) + .build(); + respClaTime.setRuleId(itemTime.getRuleId()); + respClaTime.setClassTheme(itemTime.getClassTheme()); + + resultClaTimeList.add(respClaTime); + } + + return resultClaTimeList; + } + + // 周几上课 + List weekDayList = Lists.newArrayList(); + if (ClaTimeRepeatTypeEnums.EVERY_WEEK.getRepeatType().equals(repeatType) + || ClaTimeRepeatTypeEnums.EVERY_SECOND_WEEK.getRepeatType().equals(repeatType)) { + if (StringUtils.isEmpty(weekDay)) { + return resultClaTimeList; + } + weekDayList = Lists.newArrayList(weekDay.split(",")); + } + + // 非单次排课 计算所有上课日期 + DateTime cycleBeginDate = beginDate; + DateTime cycleEndDate = endDate; + + if (ClaTimeRepeatTypeEnums.EVERY_WEEK.getRepeatType().equals(repeatType)) { + while (cycleBeginDate.isBefore(cycleEndDate)) { + + // 每周重复 + int dayOfWeek = cycleBeginDate.getDayOfWeek(); + boolean contains = weekDayList.contains(String.valueOf(dayOfWeek)); + + if (!contains) { + // 不上课 + cycleBeginDate = cycleBeginDate.plusDays(1); + continue; + } + + if (filterHoliday && holidayMap.containsKey(cycleBeginDate.toString("yyyyMMdd"))) { + // 过滤节假日 + cycleBeginDate = cycleBeginDate.plusDays(1); + continue; + } + + RespClaTimeRule respClaTime = RespClaTimeRule.builder() + .claName(itemTime.getClaName()) + .courseName(itemTime.getCourseName()) + .staffName(itemTime.getStaffName()) + .claDate(cycleBeginDate.toString("yyyy-MM-dd")) + .claTimeBegin(itemTime.getClaTimeBegin()) + .claTimeEnd(itemTime.getClaTimeEnd()) + .build(); + respClaTime.setRuleId(itemTime.getRuleId()); + respClaTime.setClassTheme(itemTime.getClassTheme()); + + resultClaTimeList.add(respClaTime); + + cycleBeginDate = cycleBeginDate.plusDays(1); + } + } else if (ClaTimeRepeatTypeEnums.EVERY_SECOND_WEEK.getRepeatType().equals(repeatType)) { + while (cycleBeginDate.isBefore(cycleEndDate)) { + int dayOfWeek = cycleBeginDate.getDayOfWeek(); + + boolean contains = weekDayList.contains(String.valueOf(dayOfWeek)); + + if (!contains) { + // 不上课 + if (dayOfWeek == 7) { + cycleBeginDate = cycleBeginDate.plusDays(8); + } else { + cycleBeginDate = cycleBeginDate.plusDays(1); + } + continue; + } + + if (filterHoliday && holidayMap.containsKey(cycleBeginDate.toString("yyyyMMdd"))) { + // 过滤节假日 + if (dayOfWeek == 7) { + cycleBeginDate = cycleBeginDate.plusDays(8); + } else { + cycleBeginDate = cycleBeginDate.plusDays(1); + } + continue; + } + + RespClaTimeRule respClaTime = RespClaTimeRule.builder() + .claName(itemTime.getClaName()) + .courseName(itemTime.getCourseName()) + .staffName(itemTime.getStaffName()) + .claDate(cycleBeginDate.toString("yyyy-MM-dd")) + .claTimeBegin(itemTime.getClaTimeBegin()) + .claTimeEnd(itemTime.getClaTimeEnd()) + .build(); + respClaTime.setRuleId(itemTime.getRuleId()); + respClaTime.setClassTheme(itemTime.getClassTheme()); + + resultClaTimeList.add(respClaTime); + + if (dayOfWeek == 7) { + cycleBeginDate = cycleBeginDate.plusDays(8); + } else { + cycleBeginDate = cycleBeginDate.plusDays(1); + } + } + } else if (ClaTimeRepeatTypeEnums.EVERY_SECOND_DAY.getRepeatType().equals(repeatType)) { + while (cycleBeginDate.isBefore(cycleEndDate)) { + + if (filterHoliday && holidayMap.containsKey(cycleBeginDate.toString("yyyyMMdd"))) { + // 过滤节假日 + cycleBeginDate = cycleBeginDate.plusDays(2); + continue; + } + + RespClaTimeRule respClaTime = RespClaTimeRule.builder() + .claName(itemTime.getClaName()) + .courseName(itemTime.getCourseName()) + .staffName(itemTime.getStaffName()) + .claDate(cycleBeginDate.toString("yyyy-MM-dd")) + .claTimeBegin(itemTime.getClaTimeBegin()) + .claTimeEnd(itemTime.getClaTimeEnd()) + .build(); + respClaTime.setRuleId(itemTime.getRuleId()); + respClaTime.setClassTheme(itemTime.getClassTheme()); + + resultClaTimeList.add(respClaTime); + + cycleBeginDate = cycleBeginDate.plusDays(2); + } + } + return resultClaTimeList; + } + + @Override + public List getClaTimeListByRule(ScClaTimeRule claTimeRule, Map holidayMap) { + RespClaTimeRule respClaTime = RespClaTimeRule.builder() + .claTimeBegin(claTimeRule.getStartTime()) + .claTimeEnd(claTimeRule.getEndTime()) + .build(); + + BeanUtils.copyProperties(claTimeRule, respClaTime); + + return this.getClaTimeListByRule(respClaTime, holidayMap); + } + + @Override + public List checkDayRepeat(Long claId, String[] day, Long notEqRuleId) { + if (null == claId || null == day || day.length == 0) { + return null; + } + + QueryWrapper qw = new QueryWrapper<>(); + qw.select("cla_date"); + qw.eq("cla_id", claId); + qw.eq("status", "1"); + qw.in("cla_date", day); + if (null != notEqRuleId) { + qw.ne("rule_id", notEqRuleId); + } + List list = claTimeService.list(qw); + return list.stream().map(ScClaTime::getClaDate).collect(Collectors.toList()); + } + + @Override + public List checkDayRepeat(ScClaTimeRule claTimeRule) { + Long claId = claTimeRule.getClaId(); + String repeatType = claTimeRule.getRepeatType(); + String ruleType = claTimeRule.getRuleType(); + String[] chooseDate = claTimeRule.getChooseDate(); + if (null == claId) { + return null; + } + if (StringUtils.isAnyEmpty(repeatType, ruleType)) { + return null; + } + + if (ClaTimeRuleTypeEnums.ONCE_RULE.getRuleType().equals(ruleType)) { + if (null == chooseDate || chooseDate.length == 0) { + return null; + } + return this.checkDayRepeat(claId, chooseDate, claTimeRule.getRuleId()); + } + // 非单次排课 计算所有上课日期 + List claTimeListByRule = this.getClaTimeListByRule(claTimeRule, null); + return this.checkDayRepeat(claId, claTimeListByRule.stream().map(RespClaTimeRule::getClaDate).toArray(String[]::new), claTimeRule.getRuleId()); + } + + @Override + public List selectClaTimeInfo(Long claId) { + return baseMapper.selectClaTimeInfo(claId); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScClaTimeServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScClaTimeServiceImpl.java new file mode 100644 index 0000000..ae6d015 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScClaTimeServiceImpl.java @@ -0,0 +1,36 @@ +package cn.xluobo.business.sc.course.service.impl; + +import cn.xluobo.business.sc.course.domain.req.time.ReqClaTimeCount; +import cn.xluobo.business.sc.course.repo.mapper.ScClaTimeMapper; +import cn.xluobo.business.sc.course.repo.model.ScClaTime; +import cn.xluobo.business.sc.course.service.IScClaTimeService; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 排课信息 服务实现类 + *

+ * + * @author zhangby + * @since 2020-09-16 + */ +@Service +public class ScClaTimeServiceImpl extends ServiceImpl implements IScClaTimeService { + + @Override + public boolean deleteUnBeginTime(Long ruleId, Long claId, String tenantId) { + UpdateWrapper uw = new UpdateWrapper(); + uw.eq("rule_id", ruleId); + uw.eq("cla_id", claId); + uw.in("status", "1"); + uw.exists("select 1 from sc_course_cla b where sc_cla_time.cla_id = b.cla_id and b.tenant_id='" + tenantId + "'"); + return this.remove(uw); + } + + @Override + public Integer claTimeCount(ReqClaTimeCount reqClaTimeCount) { + return baseMapper.selectClaTimeCount(reqClaTimeCount); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseChargeServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseChargeServiceImpl.java new file mode 100644 index 0000000..80bdc08 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseChargeServiceImpl.java @@ -0,0 +1,77 @@ +package cn.xluobo.business.sc.course.service.impl; + +import cn.xluobo.business.sc.course.domain.resp.RespBusinessChooseCourseCharge; +import cn.xluobo.business.sc.course.enums.CourseChargeTypeEnum; +import cn.xluobo.business.sc.course.repo.mapper.ScCourseChargeMapper; +import cn.xluobo.business.sc.course.repo.model.ScCourseCharge; +import cn.xluobo.business.sc.course.service.IScCourseChargeService; +import cn.xluobo.business.sys.admin.service.ISysDictDataService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.common.core.domain.entity.SysDictData; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + *

+ * 课程收费模式 服务实现类 + *

+ * + * @author zhangby + * @since 2020-07-08 + */ +@Service +public class ScCourseChargeServiceImpl extends ServiceImpl implements IScCourseChargeService { + + @Autowired + private ISysDictDataService sysDictDataService; + + @Override + public List transferCourseChargeList(List courseChargeList) { + List dateUnitList = sysDictDataService.dictTypeDataList("date_unit"); + Map dictUnitMap = dateUnitList.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel)); + + List chargeTypeList = sysDictDataService.dictTypeDataList("charge_type"); + Map chargeTypeMap = chargeTypeList.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel)); + + return courseChargeList.stream().map(item -> { + String label = ""; + String chargeType = item.getChargeType(); + String chargeTypeName = chargeTypeMap.get(chargeType); + if (CourseChargeTypeEnum.DATE.getChargeType().equals(chargeType)) { + // 按时间 100元/月 + label = "(" + chargeTypeName + ")" + item.getTotalFee().toString() + dictUnitMap.get(item.getDateUnit()); + } else if (CourseChargeTypeEnum.HOUR.getChargeType().equals(chargeType)) { + // 按课时 10课时:100元 + label = "(" + chargeTypeName + ")" + item.getCount().toString() + "课时 " + item.getTotalFee().toString() + "元"; + } else if (CourseChargeTypeEnum.CYCLE.getChargeType().equals(chargeType)) { + // 按期 100元/月 + label = "(" + chargeTypeName + ")" + item.getCount().toString() + "课时/期 " + item.getTotalFee().toString() + "元"; + } + return RespBusinessChooseCourseCharge.builder() + .chargeId(item.getChargeId()) + .totalFee(item.getTotalFee()) + .label(label) + .chargeType(item.getChargeType()) + .count(item.getCount()) + .dateUnit(item.getDateUnit()) + .build(); + }).collect(Collectors.toList()); + } + + @Override + public List courseChargeList(Long courseId, String chargeType) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("course_id", courseId); + if (StringUtils.isNotEmpty(chargeType)) { + qw.eq("charge_type", chargeType); + } + List courseChargeList = this.list(qw); + return transferCourseChargeList(courseChargeList); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseClaServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseClaServiceImpl.java new file mode 100644 index 0000000..d3699d4 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseClaServiceImpl.java @@ -0,0 +1,56 @@ +package cn.xluobo.business.sc.course.service.impl; + +import cn.xluobo.business.sc.course.repo.enums.ClaTimeStatusEnums; +import cn.xluobo.business.sc.course.repo.mapper.ScCourseClaMapper; +import cn.xluobo.business.sc.course.repo.model.ScClaTime; +import cn.xluobo.business.sc.course.repo.model.ScCourseCla; +import cn.xluobo.business.sc.course.service.IScClaTimeService; +import cn.xluobo.business.sc.course.service.IScCourseClaService; +import cn.xluobo.business.sc.student.repo.model.ScStudentCourse; +import cn.xluobo.business.sc.student.service.IScStudentCourseService; +import cn.xluobo.core.api.APIBaseResponse; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + *

+ * 课程班级信息 服务实现类 + *

+ * + * @author zhangby + * @since 2020-03-17 01:11:06 + */ +@Service +public class ScCourseClaServiceImpl extends ServiceImpl implements IScCourseClaService { + + @Autowired + private IScStudentCourseService studentCourseService; + @Autowired + private IScClaTimeService claTimeService; + + @Override + public Integer selectStudentCnt(Long claId) { + return baseMapper.selectStudentCnt(claId); + } + + @Override + public APIBaseResponse canChangeCourse(Long claId) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("cla_id", claId); + int count = studentCourseService.count(qw); + if (count != 0) { + return APIBaseResponse.fail("当前班级有报读学员,无法变更所属课程."); + } + + QueryWrapper qwClaTime = new QueryWrapper<>(); + qwClaTime.eq("cla_id", claId); + qwClaTime.eq("status", ClaTimeStatusEnums.HAD_CLASS.getStatus()); + int hadClaTimeCount = claTimeService.count(qwClaTime); + if (hadClaTimeCount != 0) { + return APIBaseResponse.fail("当前班级已有上课记录,无法变更所属课程."); + } + return APIBaseResponse.success(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseServiceImpl.java new file mode 100644 index 0000000..8311bd6 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseServiceImpl.java @@ -0,0 +1,39 @@ +package cn.xluobo.business.sc.course.service.impl; + +import cn.xluobo.business.sc.course.domain.req.ReqSearchScCourse; +import cn.xluobo.business.sc.course.domain.resp.course.RespSearchCourse; +import cn.xluobo.business.sc.course.repo.mapper.ScCourseChargeMapper; +import cn.xluobo.business.sc.course.repo.mapper.ScCourseMapper; +import cn.xluobo.business.sc.course.repo.model.ScCourse; +import cn.xluobo.business.sc.course.service.IScCourseService; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 课程信息 服务实现类 + *

+ * + * @author zhangby + * @since 2020-03-17 11:25:55 + */ +@Service +public class ScCourseServiceImpl extends ServiceImpl implements IScCourseService { + + @Autowired + private ScCourseMapper courseMapper; + @Autowired + private ScCourseChargeMapper courseChargeMapper; + + @Override + public RespPage searchCourse(ReqSearchScCourse reqSearchScCourse) { + RespPage respPage = new RespPage(reqSearchScCourse.getPageNum(),reqSearchScCourse.getPageSize()); + List courseList = baseMapper.selectCourseList(reqSearchScCourse, respPage); + respPage.setRows(courseList); + return respPage; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseTypeServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseTypeServiceImpl.java new file mode 100644 index 0000000..387c5ba --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/service/impl/ScCourseTypeServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.sc.course.service.impl; + +import cn.xluobo.business.sc.course.repo.mapper.ScCourseTypeMapper; +import cn.xluobo.business.sc.course.repo.model.ScCourseType; +import cn.xluobo.business.sc.course.service.IScCourseTypeService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 课程类型 服务实现类 + *

+ * + * @author zhangby + * @since 2020-07-09 08:10:25 + */ +@Service +public class ScCourseTypeServiceImpl extends ServiceImpl implements IScCourseTypeService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/controller/ScStudentCourseLogController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/controller/ScStudentCourseLogController.java new file mode 100644 index 0000000..9beca78 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/controller/ScStudentCourseLogController.java @@ -0,0 +1,33 @@ +package cn.xluobo.business.sc.log.controller; + +import cn.xluobo.business.sc.log.domain.req.ReqSearchStuCourseLog; +import cn.xluobo.business.sc.log.service.BusinessScStudentCourseLogService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 日志 + * @author :zhangbaoyu + * @date :Created in 2020/12/21 14:45 + */ +@RestController +@RequestMapping("/api/sc/student/log") +public class ScStudentCourseLogController { + + @Autowired + private BusinessScStudentCourseLogService studentCourseLogService; + + /** + * 列表 + * + * @param reqSearchStuCourseLog + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchStuCourseLog reqSearchStuCourseLog) { + return studentCourseLogService.searchList(reqSearchStuCourseLog); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/domain/req/ReqSearchStuCourseLog.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/domain/req/ReqSearchStuCourseLog.java new file mode 100644 index 0000000..24ec346 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/domain/req/ReqSearchStuCourseLog.java @@ -0,0 +1,27 @@ +package cn.xluobo.business.sc.log.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/12/21 14:44 + */ +@Data +public class ReqSearchStuCourseLog extends ReqPageBase implements Serializable { + + private Long studentId; + + private Long courseId; + + private Long claId; + + private String logType; + + private String beginDate; + + private String endDate; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/enums/LogTypeEnum.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/enums/LogTypeEnum.java new file mode 100644 index 0000000..1a59d7d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/enums/LogTypeEnum.java @@ -0,0 +1,34 @@ +package cn.xluobo.business.sc.log.enums; + +/** + * 学生日志类型 + * @author :zhangbaoyu + * @date :Created in 2020/12/19 10:15 + */ +public enum LogTypeEnum { + + PAY_FEE("1","缴费"), + ATTEND_CLA("2","上课"), + DELETE_ATTEND_CLA("3","删除上课记录"), + INVALID_ORDER("4","作废订单"), + OUT_CLA("5","退出班级"), + IN_CLA("6","进入班级"), + ; + + private final String logType; + + private final String logTypeName; + + LogTypeEnum(String logType, String logTypeName) { + this.logType = logType; + this.logTypeName = logTypeName; + } + + public String getLogType() { + return logType; + } + + public String getLogTypeName() { + return logTypeName; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/repo/mapper/ScStudentCourseLogMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/repo/mapper/ScStudentCourseLogMapper.java new file mode 100644 index 0000000..9ad56a5 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/repo/mapper/ScStudentCourseLogMapper.java @@ -0,0 +1,22 @@ +package cn.xluobo.business.sc.log.repo.mapper; + +import cn.xluobo.business.sc.log.domain.req.ReqSearchStuCourseLog; +import cn.xluobo.business.sc.log.repo.model.ScStudentCourseLog; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 课程缴费扣费记录 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-12-17 + */ +public interface ScStudentCourseLogMapper extends BaseMapper { + + List selectForSearchTable(@Param("reqSearchStuCourseLog") ReqSearchStuCourseLog reqSearchStuCourseLog, @Param("page") Page page); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/repo/mapping/ScStudentCourseLogMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/repo/mapping/ScStudentCourseLogMapper.xml new file mode 100644 index 0000000..070e6e8 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/repo/mapping/ScStudentCourseLogMapper.xml @@ -0,0 +1,28 @@ + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/repo/model/ScStudentCourseLog.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/repo/model/ScStudentCourseLog.java new file mode 100644 index 0000000..78d8c16 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/repo/model/ScStudentCourseLog.java @@ -0,0 +1,127 @@ +package cn.xluobo.business.sc.log.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 课程缴费扣费记录 + *

+ * + * @author zhangby + * @since 2020-12-17 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_student_course_log") +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ScStudentCourseLog implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(value = "log_id", type = IdType.ASSIGN_ID) + private Long logId; + + /** + * 学生 + */ + @TableField("student_id") + private Long studentId; + + /** + * 日志类型 参照 LogTypeEnum + */ + @TableField("log_type") + private String logType; + + /** + * 课程 + */ + @TableField("course_id") + private Long courseId; + + /** + * 课程名称 + */ + @TableField("course_name") + private String courseName; + + /** + * 班级 + */ + @TableField("cla_id") + private Long claId; + + /** + * 班级名称 + */ + @TableField("cla_name") + private String claName; + + /** + * 经办校区 + */ + @TableField("dept_name") + private String deptName; + + /** + * 变更课时 + */ + @TableField("change_hour") + private BigDecimal changeHour; + + /** + * 变更后剩余课时 + */ + @TableField("after_balance_hour") + private BigDecimal afterBalanceHour; + + /** + * 变更金额 + */ + @TableField("change_fee") + private BigDecimal changeFee; + + /** + * 备注 + */ + @TableField("memo") + private String memo; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建者 + */ + @TableField("create_user_name") + private String createUserName; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + // 学生姓名 + @TableField(exist = false) + private String studentName; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/service/BusinessScStudentCourseLogService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/service/BusinessScStudentCourseLogService.java new file mode 100644 index 0000000..fe07564 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/service/BusinessScStudentCourseLogService.java @@ -0,0 +1,39 @@ +package cn.xluobo.business.sc.log.service; + +import cn.xluobo.business.sc.log.domain.req.ReqSearchStuCourseLog; +import cn.xluobo.business.sc.log.repo.mapper.ScStudentCourseLogMapper; +import cn.xluobo.business.sc.log.repo.model.ScStudentCourseLog; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.page.RespPage; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/12/21 14:46 + */ +@Service +@Transactional +@Slf4j +public class BusinessScStudentCourseLogService { + + @Autowired + private ScStudentCourseLogMapper studentCourseLogMapper; + + /** + * 查询 + * + * @param reqSearchStuCourseLog + * @return + */ + public APIResponse searchList(ReqSearchStuCourseLog reqSearchStuCourseLog) { + RespPage page = new RespPage<>(reqSearchStuCourseLog.getPageNum(), reqSearchStuCourseLog.getPageSize()); + List orderList = studentCourseLogMapper.selectForSearchTable(reqSearchStuCourseLog, page); + page.setRows(orderList); + return APIResponse.toAPIResponse(page); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/service/IScStudentCourseLogService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/service/IScStudentCourseLogService.java new file mode 100644 index 0000000..1857ca4 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/service/IScStudentCourseLogService.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sc.log.service; + +import cn.xluobo.business.sc.log.repo.model.ScStudentCourseLog; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 课程缴费扣费记录 服务类 + *

+ * + * @author zhangby + * @since 2020-12-17 + */ +public interface IScStudentCourseLogService extends IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/service/impl/ScStudentCourseLogServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/service/impl/ScStudentCourseLogServiceImpl.java new file mode 100644 index 0000000..f311b8c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/log/service/impl/ScStudentCourseLogServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.sc.log.service.impl; + +import cn.xluobo.business.sc.log.repo.mapper.ScStudentCourseLogMapper; +import cn.xluobo.business.sc.log.repo.model.ScStudentCourseLog; +import cn.xluobo.business.sc.log.service.IScStudentCourseLogService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 课程缴费扣费记录 服务实现类 + *

+ * + * @author zhangby + * @since 2020-12-17 + */ +@Service +public class ScStudentCourseLogServiceImpl extends ServiceImpl implements IScStudentCourseLogService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/controller/ScOrderController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/controller/ScOrderController.java new file mode 100644 index 0000000..a98a387 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/controller/ScOrderController.java @@ -0,0 +1,67 @@ +package cn.xluobo.business.sc.order.controller; + +import cn.xluobo.business.sc.order.domain.req.ReqBusinessSignUp; +import cn.xluobo.business.sc.order.domain.req.ReqSearchScOrder; +import cn.xluobo.business.sc.order.service.BusinessScOrderService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 订单 Controller + *

+ * + * @author zhangby + * @since 2020-08-24 10:22:19 + */ +@RestController +@RequestMapping("/api/sc/order") +public class ScOrderController { + @Autowired + private BusinessScOrderService scOrderService; + + /** + * 列表 + * + * @param reqSearchScOrder + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchScOrder reqSearchScOrder) { + return scOrderService.searchList(reqSearchScOrder); + } + + /** + * 详情 + * + * @param orderId + * @return + */ + @GetMapping("/info/detailById/{orderId}") + public APIResponse detailById(@PathVariable("orderId") Long orderId) { + return scOrderService.detailById(orderId); + } + + /** + * 新办 + * + * @param reqBusinessSignUp + * @return + */ + @PostMapping("/add/signUp") + public APIResponse signUp(@RequestBody ReqBusinessSignUp reqBusinessSignUp) { + return scOrderService.signUp(reqBusinessSignUp); + } + + /** + * 作废订单 + * + * @param orderIds + * @return + */ + @PostMapping("/delete/invalidById/{orderIds}") + public APIResponse invalidById(@PathVariable("orderIds") Long[] orderIds) { + return scOrderService.invalidById(orderIds); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqBusinessSignUp.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqBusinessSignUp.java new file mode 100644 index 0000000..984c0f6 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqBusinessSignUp.java @@ -0,0 +1,102 @@ +package cn.xluobo.business.sc.order.domain.req; + +import cn.xluobo.core.api.APIResponse; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +import java.math.BigDecimal; +import java.util.List; + +/** + * 新办 + * + * @author :zhangbaoyu + * @date :Created in 2020/9/3 15:56 + */ +@Data +public class ReqBusinessSignUp { + + private Long studentId; + + // 经办校区 + private Long handleDepartId; + + // 是否使用余额支付 + private boolean useBalancePay; + // 余额支付金额 + private BigDecimal balancePayValue; + + // 订单标签 + private String[] orderTag; + + // 销售员工 + private Long saleStaffId; + + // 经办日期 + private String handleDate; + + // 办理备注 + private String memo; + + // 销售来源 + private String[] saleSourceTag; + + // 实收金额 + private BigDecimal receiptWaySumMoney; + + // 应收金额 + private BigDecimal needReceiptFee; + + // 报读课程 + List signUpItemList; + + // 收款方式 + List signUpReceiptList; + + public APIResponse checkParam() { + if (null == signUpItemList || signUpItemList.size() == 0) { + return APIResponse.toExceptionResponse("请选择报读课程"); + } else if (null == studentId) { + return APIResponse.toExceptionResponse("请选择学生"); + } else if (null == handleDepartId) { + return APIResponse.toExceptionResponse("请选择经办校区"); + } else if (useBalancePay && null == balancePayValue) { + return APIResponse.toExceptionResponse("余额支付时,请填写余额支付金额"); + } else if (null == needReceiptFee) { + return APIResponse.toExceptionResponse("无应收金额"); + } else if (null == receiptWaySumMoney) { + return APIResponse.toExceptionResponse("未填写实收金额"); + } + for (ReqBusinessSignUpItem item : signUpItemList) { + if(null == item.getCourseId()) { + return APIResponse.toExceptionResponse("请选择课程"); + } else if (null == item.getDepartId()) { + return APIResponse.toExceptionResponse("无法获取报读课程所属校区,请重试"); + } else if (null == item.getChargeId()) { + return APIResponse.toExceptionResponse("请选择收费方式"); + } else if (StringUtils.isEmpty(item.getChargeType())) { + return APIResponse.toExceptionResponse("请选择收费方式"); + } else if (null == item.getBuyCount() || 0 == item.getBuyCount()) { + return APIResponse.toExceptionResponse("请填写购买数量"); + } else if (item.isOpenExpire() && null == item.getExpireDate()) { + return APIResponse.toExceptionResponse("设置有效期但未填写失效时间"); + } else if ("date".equals(item.getChargeType()) && null == item.getBeginDate()) { + return APIResponse.toExceptionResponse("按时间收费 但未填写生效时间"); + } else if ("date".equals(item.getChargeType()) && null == item.getEndDate()) { + return APIResponse.toExceptionResponse("按时间收费 但未填写失效时间"); + } else if (item.isOpenDiscount() && null == item.getDiscount()) { + return APIResponse.toExceptionResponse("启学费折扣,但未填写折扣"); + } else if (item.isOpenDiscountFee() && null == item.getDiscountFee()) { + return APIResponse.toExceptionResponse("启学费折扣,但未填写优惠金额"); + } + } + for (ReqBusinessSignUpReceipt signUpReceipt : signUpReceiptList) { + if(null == signUpReceipt.getAccountId()){ + return APIResponse.toExceptionResponse("收款方式未填写,请选择填写已添加的收款方式"); + } else if(null == signUpReceipt.getReceiptMoney()) { + return APIResponse.toExceptionResponse("请填写已选择收款方式的收款金额"); + } + } + return APIResponse.toOkResponse(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqBusinessSignUpItem.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqBusinessSignUpItem.java new file mode 100644 index 0000000..311d2c1 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqBusinessSignUpItem.java @@ -0,0 +1,58 @@ +package cn.xluobo.business.sc.order.domain.req; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 报名详情 + * + * @author :zhangbaoyu + * @date :Created in 2020/9/3 16:06 + */ +@Data +public class ReqBusinessSignUpItem { + + private Long courseId; + + private Long claId; + + // 报读校区 + private Long departId; + + private Long chargeId; + + private String chargeType; + + // 购买数量 + private Integer buyCount; + + // 按课时收费 是否设置有效期 + private boolean openExpire; + + // 失效时间 + private String expireDate; + + // 按时间收费 生效时间 + private String beginDate; + // 按时间收费 失效时间 + private String endDate; + + // 是否学费折扣 + private boolean openDiscount; + // 是否学费优惠 + private boolean openDiscountFee; + // 折扣 0-10之间 + private BigDecimal discount; + // 优惠 + private BigDecimal discountFee; + + // 内部备注 + private String insideMemo; + // 外部备注 + private String outsideMemo; + + // 类型 1新报 2续报 + private String detailTag; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqBusinessSignUpReceipt.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqBusinessSignUpReceipt.java new file mode 100644 index 0000000..fae2a1f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqBusinessSignUpReceipt.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.sc.order.domain.req; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 新报收款信息 + * @author :zhangbaoyu + * @date :Created in 2020/9/4 16:46 + */ +@Data +public class ReqBusinessSignUpReceipt { + + private Long accountId; + + // 收款金额 + private BigDecimal receiptMoney; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqReportMonthCourseIncome.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqReportMonthCourseIncome.java new file mode 100644 index 0000000..bb6419f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqReportMonthCourseIncome.java @@ -0,0 +1,24 @@ +package cn.xluobo.business.sc.order.domain.req; + +import lombok.Data; + +/** + * 月份、课程 营收情况 + * + * @author :zhangbaoyu + * @date :Created in 2020/12/24 19:57 + */ +@Data +public class ReqReportMonthCourseIncome { + + private String beginMonth; + + private String endMonth; + + private Long deptId; + + private Long[] deptIds; + + private Long[] courseIds; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqSearchScOrder.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqSearchScOrder.java new file mode 100644 index 0000000..34ebdc6 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/req/ReqSearchScOrder.java @@ -0,0 +1,60 @@ +package cn.xluobo.business.sc.order.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchScOrder extends ReqPageBase implements Serializable { + + // 学员 + private Long studentId; + + // 经办日期 + private String[] handleDate; + + private String handleDateBegin; + private String handleDateEnd; + + // 是否欠费 + private Boolean arrears; + + // 校区 + private Long deptId; + + // 课程 + private Long courseId; + + // 销售员工 + private Long saleStaffId; + + // 订单类型 + private String orderType; + + // 订单状态 + private String orderStatus; + + // 经办人 + private Long createUser; + + // 经办校区 + private Long handleDeptId; + + // 销售来源 + private String saleSourceTag; + + public void setHandleDate(String[] handleDate) { + this.handleDate = handleDate; + if (null != handleDate && handleDate.length == 2 && StringUtils.isAnyEmpty(handleDateBegin, handleDateEnd)) { + this.handleDateBegin = handleDate[0]; + this.handleDateEnd = handleDate[1]; + } + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/resp/RespOrder.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/resp/RespOrder.java new file mode 100644 index 0000000..970b466 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/resp/RespOrder.java @@ -0,0 +1,44 @@ +package cn.xluobo.business.sc.order.domain.resp; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/9/8 13:47 + */ +@Data +public class RespOrder { + + private Long orderId; + + private String orderType; + + private BigDecimal actualTotalFee; + + private BigDecimal receiptFee; + + private BigDecimal balanceFee; + + private String saleStaffName; + + private String orderTag; + + private String handleDeptName; + + private String handleDate; + + private String createUserName; + + private String memo; + + private String studentName; + + private String phone; + + private String orderDetail; + + private String orderStatus; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/resp/RespReportMonthCourseIncome.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/resp/RespReportMonthCourseIncome.java new file mode 100644 index 0000000..465d2ab --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/domain/resp/RespReportMonthCourseIncome.java @@ -0,0 +1,24 @@ +package cn.xluobo.business.sc.order.domain.resp; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 月份、课程 营收情况 + * + * @author :zhangbaoyu + * @date :Created in 2020/12/24 19:52 + */ +@Data +public class RespReportMonthCourseIncome { + + private String month; + + private Long courseId; + + private String courseName; + + private BigDecimal fee; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/enums/OrderDetailTagEnum.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/enums/OrderDetailTagEnum.java new file mode 100644 index 0000000..e40453c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/enums/OrderDetailTagEnum.java @@ -0,0 +1,30 @@ +package cn.xluobo.business.sc.order.enums; + +/** + * 订单明细 标签 + * @author :zhangbaoyu + * @date :Created in 2020/10/12 15:13 + */ +public enum OrderDetailTagEnum { + + NEW_COURSE("1", "新报"), + CONTINUE_COURSE("2", "续报"), + EXTEND_COURSE("3", "扩科"), + ; + + private String tag; + private String tagName; + + OrderDetailTagEnum(String tag, String tagName) { + this.tag = tag; + this.tagName = tagName; + } + + public String getTag() { + return tag; + } + + public String getTagName() { + return tagName; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/enums/OrderStatusEnum.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/enums/OrderStatusEnum.java new file mode 100644 index 0000000..5e003ac --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/enums/OrderStatusEnum.java @@ -0,0 +1,32 @@ +package cn.xluobo.business.sc.order.enums; + +/** + * 订单状态 + * @author :zhangbaoyu + * @date :Created in 2020/9/13 21:11 + */ +public enum OrderStatusEnum { + + WAIT_PAY("1", "待支付"), + HAD_PAY("2", "已支付"), + INVALID("3", "已作废"), + ; + + private String orderStatus; + + private String statusTxt; + + OrderStatusEnum(String orderStatus, String statusTxt) { + this.orderStatus = orderStatus; + this.statusTxt = statusTxt; + } + + + public String getOrderStatus() { + return orderStatus; + } + + public String getStatusTxt() { + return statusTxt; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/enums/OrderTypeEnum.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/enums/OrderTypeEnum.java new file mode 100644 index 0000000..92d3bb6 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/enums/OrderTypeEnum.java @@ -0,0 +1,28 @@ +package cn.xluobo.business.sc.order.enums; + +/** + * 订单类型 + * @author :zhangbaoyu + * @date :Created in 2020/10/12 15:13 + */ +public enum OrderTypeEnum { + + SIGN_UP("1", "报名"), + ; + + private String orderType; + private String orderTypeName; + + OrderTypeEnum(String orderType, String orderTypeName) { + this.orderType = orderType; + this.orderTypeName = orderTypeName; + } + + public String getOrderType() { + return orderType; + } + + public String getOrderTypeName() { + return orderTypeName; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/OrderReportMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/OrderReportMapper.java new file mode 100644 index 0000000..636b67c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/OrderReportMapper.java @@ -0,0 +1,23 @@ +package cn.xluobo.business.sc.order.repo.mapper; + +import cn.xluobo.business.sc.order.domain.req.ReqReportMonthCourseIncome; +import cn.xluobo.business.sc.order.domain.resp.RespReportMonthCourseIncome; + +import java.util.List; + +/** + * 订单报表相关 + * + * @author :zhangbaoyu + * @date :Created in 2020/12/24 19:50 + */ +public interface OrderReportMapper { + + /** + * 月份、课程 营收情况 + * @param reqReportMonthCourseIncome + * @return + */ + List selectMonthCourseIncomeList(ReqReportMonthCourseIncome reqReportMonthCourseIncome); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/ScOrderAccountMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/ScOrderAccountMapper.java new file mode 100644 index 0000000..2bce3b0 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/ScOrderAccountMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sc.order.repo.mapper; + +import cn.xluobo.business.sc.order.repo.model.ScOrderAccount; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 订单收款账户 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface ScOrderAccountMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/ScOrderDetailMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/ScOrderDetailMapper.java new file mode 100644 index 0000000..30bf1bc --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/ScOrderDetailMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sc.order.repo.mapper; + +import cn.xluobo.business.sc.order.repo.model.ScOrderDetail; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 订单详情 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface ScOrderDetailMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/ScOrderMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/ScOrderMapper.java new file mode 100644 index 0000000..21c146a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapper/ScOrderMapper.java @@ -0,0 +1,28 @@ +package cn.xluobo.business.sc.order.repo.mapper; + +import cn.xluobo.business.sc.order.domain.req.ReqSearchScOrder; +import cn.xluobo.business.sc.order.domain.resp.RespOrder; +import cn.xluobo.business.sc.order.repo.model.ScOrder; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 订单 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-08-24 10:22:19 + */ +public interface ScOrderMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + + List selectFroSearchTable(@Param("reqSearchScOrder")ReqSearchScOrder reqSearchScOrder, @Param("page")Page page); + + /** + * 获取欠费学员数量 + * @return + */ + Integer selectArrearsStudentCount(); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/OrderReportMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/OrderReportMapper.xml new file mode 100644 index 0000000..da9e01a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/OrderReportMapper.xml @@ -0,0 +1,32 @@ + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/ScOrderAccountMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/ScOrderAccountMapper.xml new file mode 100644 index 0000000..fa86e83 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/ScOrderAccountMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/ScOrderDetailMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/ScOrderDetailMapper.xml new file mode 100644 index 0000000..ff0a37e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/ScOrderDetailMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/ScOrderMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/ScOrderMapper.xml new file mode 100644 index 0000000..677654f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/mapping/ScOrderMapper.xml @@ -0,0 +1,59 @@ + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/model/ScOrder.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/model/ScOrder.java new file mode 100644 index 0000000..d408bf4 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/model/ScOrder.java @@ -0,0 +1,175 @@ +package cn.xluobo.business.sc.order.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 订单 + *

+ * + * @author zhangby + * @since 2020-08-24 10:22:19 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_order") +public class ScOrder implements Serializable { + + + /** + * 订单编号 + */ + @TableId(value = "order_id", type = IdType.ASSIGN_ID) + private Long orderId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 学员编号 + */ + @TableField("student_id") + private Long studentId; + + /** + * 学员名称 + */ + @TableField("student_name") + private String studentName; + + /** + * 联系电话 + */ + @TableField("phone") + private String phone; + + /** + * 订单类型 1报名 + */ + @TableField("order_type") + private String orderType; + + /** + * 原价 + */ + @TableField("original_total_fee") + private BigDecimal originalTotalFee; + + /** + * 实际价格 + */ + @TableField("actual_total_fee") + private BigDecimal actualTotalFee; + + /** + * 收款金额 receipt_fee+balance_fee=actual_total_fee + */ + @TableField("receipt_fee") + private BigDecimal receiptFee; + + /** + * 使用余额支付金额 + */ + @TableField("balance_fee") + private BigDecimal balanceFee; + + /** + * 订单标签 + */ + @TableField("order_tag") + private String orderTag; + + /** + * 销售来源标签 + */ + @TableField("sale_source_tag") + private String saleSourceTag; + + /** + * 销售员工 + */ + @TableField("sale_staff_id") + private Long saleStaffId; + + /** + * 销售员工 + */ + @TableField("sale_staff_name") + private String saleStaffName; + + /** + * 订单状态 1待支付 2已支付 3已作废 + */ + @TableField("order_status") + private String orderStatus; + + /** + * 内部备注 + */ + @TableField("memo") + private String memo; + + /** + * 经办校区 + */ + @TableField("handle_dept_id") + private Long handleDeptId; + + /** + * 经办校区 + */ + @TableField("handle_dept_name") + private String handleDeptName; + + /** + * 经办日期 + */ + @TableField("handle_date") + private String handleDate; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + /** + * 办理人员姓名 + */ + @TableField(exist = false) + private String handleStaffName; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/model/ScOrderAccount.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/model/ScOrderAccount.java new file mode 100644 index 0000000..3bbdd94 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/model/ScOrderAccount.java @@ -0,0 +1,61 @@ +package cn.xluobo.business.sc.order.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + *

+ * 订单收款账户 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_order_account") +public class ScOrderAccount implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(value = "order_account_id", type = IdType.ASSIGN_ID) + private Long orderAccountId; + + /** + * 订单编号 + */ + @TableField("order_id") + private Long orderId; + + /** + * 收款账户 + */ + @TableField("account_id") + private Long accountId; + + /** + * 账户名称 + */ + @TableField("account_name") + private String accountName; + + /** + * 实收 + */ + @TableField("fee") + private BigDecimal fee; + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/model/ScOrderDetail.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/model/ScOrderDetail.java new file mode 100644 index 0000000..319683f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/repo/model/ScOrderDetail.java @@ -0,0 +1,244 @@ +package cn.xluobo.business.sc.order.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 订单详情 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Data +@Builder +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_order_detail") +public class ScOrderDetail implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 详单编号 + */ + @TableId(value = "order_detail_id", type = IdType.ASSIGN_ID) + private Long orderDetailId; + + /** + * 订单编号 + */ + @TableField("order_id") + private Long orderId; + + /** + * 课程 + */ + @TableField("course_id") + private Long courseId; + + /** + * 课程 + */ + @TableField("course_name") + private String courseName; + + /** + * 班级 + */ + @TableField("cla_id") + private Long claId; + + /** + * 班级 + */ + @TableField("cla_name") + private String claName; + + /** + * 校区 + */ + @TableField("dept_id") + private Long deptId; + + /** + * 校区 + */ + @TableField("dept_name") + private String deptName; + + /** + * 类型 1新报 2续报 3扩科 + */ + @TableField("detail_tag") + private String detailTag; + + /** + * 收费方式名称 + */ + @TableField("charge_name") + private String chargeName; + + /** + * 收费模式 + */ + @TableField("charge_type") + private String chargeType; + + /** + * 收费方式包含课时数量 + */ + @TableField("charge_count") + private BigDecimal chargeCount; + + /** + * 收费方式金额 + */ + @TableField("charge_fee") + private BigDecimal chargeFee; + + /** + * 时间周期 + */ + @TableField("date_unit") + private String dateUnit; + + /** + * 购买数量 + */ + @TableField("buy_count") + private BigDecimal buyCount; + + /** + * 原价 buy_count*charge_fee + */ + @TableField("original_fee") + private BigDecimal originalFee; + + /** + * 生效时间 + */ + @TableField("begin_date") + private String beginDate; + + /** + * 失效时间 + */ + @TableField("end_date") + private String endDate; + + /** + * 过期时间 + */ + @TableField("expire_date") + private String expireDate; + + /** + * 优惠编号 + */ + @TableField("discount_id") + private Long discountId; + + /** + * 活动名称 + */ + @TableField("activity_name") + private String activityName; + + /** + * 折扣类型 + */ + @TableField("discount_type") + private String discountType; + + /** + * 优惠明细编号 + */ + @TableField("discount_detail_id") + private Long discountDetailId; + + /** + * 满足条件 金额/课时 + */ + @TableField("meet_condition") + private BigDecimal meetCondition; + + /** + * 赠送 金额/折扣/课时 + */ + @TableField("gift") + private BigDecimal gift; + + /** + * 直接折扣 + */ + @TableField("direct_discount") + private BigDecimal directDiscount; + + /** + * 直接减免金额 + */ + @TableField("direct_reduce_fee") + private BigDecimal directReduceFee; + + /** + * 实际价格 original_fee-满减-直接减免 + */ + @TableField("actual_fee") + private BigDecimal actualFee; + + /** + * 内部备注 + */ + @TableField("inside_memo") + private String insideMemo; + + /** + * 外部订单备注 + */ + @TableField("outside_memo") + private String outsideMemo; + + /** + * 订单状态 1待支付 2已支付 3已作废 + */ + @TableField("order_detail_status") + private String orderDetailStatus; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/BusinessScOrderService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/BusinessScOrderService.java new file mode 100644 index 0000000..33f557e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/BusinessScOrderService.java @@ -0,0 +1,757 @@ +package cn.xluobo.business.sc.order.service; + +import cn.xluobo.business.sc.course.enums.CourseChargeTypeEnum; +import cn.xluobo.business.sc.course.repo.model.ScCourse; +import cn.xluobo.business.sc.course.repo.model.ScCourseCharge; +import cn.xluobo.business.sc.course.repo.model.ScCourseCla; +import cn.xluobo.business.sc.course.service.IScClaTimeAttendService; +import cn.xluobo.business.sc.course.service.IScCourseChargeService; +import cn.xluobo.business.sc.course.service.IScCourseClaService; +import cn.xluobo.business.sc.course.service.IScCourseService; +import cn.xluobo.business.sc.log.enums.LogTypeEnum; +import cn.xluobo.business.sc.log.repo.model.ScStudentCourseLog; +import cn.xluobo.business.sc.log.service.IScStudentCourseLogService; +import cn.xluobo.business.sc.order.domain.req.ReqBusinessSignUp; +import cn.xluobo.business.sc.order.domain.req.ReqBusinessSignUpItem; +import cn.xluobo.business.sc.order.domain.req.ReqBusinessSignUpReceipt; +import cn.xluobo.business.sc.order.domain.req.ReqSearchScOrder; +import cn.xluobo.business.sc.order.domain.resp.RespOrder; +import cn.xluobo.business.sc.order.enums.OrderStatusEnum; +import cn.xluobo.business.sc.order.repo.mapper.ScOrderMapper; +import cn.xluobo.business.sc.order.repo.model.ScOrder; +import cn.xluobo.business.sc.order.repo.model.ScOrderAccount; +import cn.xluobo.business.sc.order.repo.model.ScOrderDetail; +import cn.xluobo.business.sc.student.repo.model.ScStudent; +import cn.xluobo.business.sc.student.repo.model.ScStudentCourse; +import cn.xluobo.business.sc.student.repo.model.ScStudentCourseOrder; +import cn.xluobo.business.sc.student.service.IScStudentAccountService; +import cn.xluobo.business.sc.student.service.IScStudentCourseOrderService; +import cn.xluobo.business.sc.student.service.IScStudentCourseService; +import cn.xluobo.business.sc.student.service.IScStudentService; +import cn.xluobo.business.sys.admin.service.ISysDeptService; +import cn.xluobo.business.sys.admin.service.ISysUserService; +import cn.xluobo.business.sys.receipt.repo.model.SysReceiptAccount; +import cn.xluobo.business.sys.receipt.service.ISysReceiptAccountService; +import cn.xluobo.business.sys.staff.repo.model.SysStaff; +import cn.xluobo.business.sys.staff.service.ISysStaffService; +import cn.xluobo.business.sys.tag.service.ISysTagService; +import cn.xluobo.config.exception.BusinessException; +import cn.xluobo.core.api.APIBaseResponse; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import cn.xluobo.core.utils.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.google.common.collect.Maps; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import lombok.extern.slf4j.Slf4j; +import org.joda.time.DateTime; +import org.joda.time.Period; +import org.joda.time.PeriodType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +@Slf4j +public class BusinessScOrderService { + + @Autowired + private IScOrderService scOrderService; + @Autowired + private IScOrderDetailService orderDetailService; + @Autowired + private ISysReceiptAccountService receiptAccountService; + @Autowired + private IScOrderAccountService orderAccountService; + @Autowired + private IScStudentCourseService studentCourseService; + @Autowired + private IScStudentCourseOrderService courseOrderService; + @Autowired + private IScCourseService scCourseService; + @Autowired + private IScCourseClaService courseClaService; + @Autowired + private IScCourseChargeService courseChargeService; + @Autowired + private IScStudentService studentService; + @Autowired + private ISysDeptService deptService; + @Autowired + private IScStudentAccountService studentAccountService; + @Autowired + private ISysTagService tagService; + @Autowired + private ScOrderMapper orderMapper; + @Autowired + private ISysStaffService staffService; + @Autowired + private ISysUserService userService; + @Autowired + private IScClaTimeAttendService claTimeAttendService; + @Autowired + private IScStudentCourseLogService scStudentCourseLogService; + + /** + * 查询 + * + * @param reqSearchScOrder + * @return + */ + public APIResponse searchList(ReqSearchScOrder reqSearchScOrder) { + RespPage page = new RespPage<>(reqSearchScOrder.getPageNum(), reqSearchScOrder.getPageSize()); + List orderList = orderMapper.selectFroSearchTable(reqSearchScOrder, page); + page.setRows(orderList); + return APIResponse.toAPIResponse(page); + } + + /** + * 详情 + * + * @param orderId + * @return + */ + public APIResponse detailById(Long orderId) { + if (null == orderId) { + return APIResponse.toAPIResponse(null); + } + Map detailMap = Maps.newHashMap(); + + // 订单信息 + ScOrder order = scOrderService.getById(orderId); + // 经办人姓名 + if (null != order.getCreateUser()) { + SysUser user = userService.getById(order.getCreateUser()); + order.setHandleStaffName(user.getUserName()); + } + detailMap.put("orderInfo", order); + + // 订单明细 + List orderDetail = orderDetailService.getByOrderDetail(orderId); + detailMap.put("orderDetail", orderDetail); + + // 收款账户 + List orderAccountList = orderAccountService.getOrderAccountList(orderId); + detailMap.put("orderAccountList", orderAccountList); + + return APIResponse.toAPIResponse(detailMap); + } + + /** + * 新办 + * + * @param reqBusinessSignUp + * @return + */ + public APIResponse signUp(ReqBusinessSignUp reqBusinessSignUp) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + APIResponse checkParam = reqBusinessSignUp.checkParam(); + if (!checkParam.isSuccess()) { + return checkParam; + } + Long studentId = reqBusinessSignUp.getStudentId(); + Long handleDepartId = reqBusinessSignUp.getHandleDepartId(); + + ScStudent student = studentService.getById(studentId); + if (null == student) { + return APIResponse.toExceptionResponse("无法获取学生信息,请重试!"); + } + SysDept handleDept = deptService.getById(handleDepartId); + if (null == handleDept) { + return APIResponse.toExceptionResponse("无法获取经办校区信息,请重试!"); + } + + BigDecimal reqReceiptWaySumMoney = reqBusinessSignUp.getReceiptWaySumMoney(); + List signUpReceiptList = reqBusinessSignUp.getSignUpReceiptList(); + List signUpItemList = reqBusinessSignUp.getSignUpItemList(); + for (ReqBusinessSignUpItem signUpItem : signUpItemList) { + // 校验学生是否可报读 课程 + APIBaseResponse studentCanSignUpCourse = studentCourseService.checkStudentCanSignUpCourse(studentId, signUpItem.getCourseId(), signUpItem.getDepartId(), null); + if (!studentCanSignUpCourse.isSuccess()) { + return APIResponse.toExceptionResponse(studentCanSignUpCourse.getRespMsg()); + } + } + + // 原价 + BigDecimal originalTotalFee = BigDecimal.ZERO; + // 实际价格 + BigDecimal actualTotalFee = BigDecimal.ZERO; + // 应收 + BigDecimal needReceiptFee = BigDecimal.ZERO; + // 实收 + BigDecimal receiptWaySumMoney = BigDecimal.ZERO; + + // 计算实收 + for (ReqBusinessSignUpReceipt signUpReceipt : signUpReceiptList) { + receiptWaySumMoney = receiptWaySumMoney.add(signUpReceipt.getReceiptMoney()); + } + if (reqReceiptWaySumMoney.compareTo(receiptWaySumMoney) != 0) { + return APIResponse.toExceptionResponse("实收金额不一致,请重试"); + } + + // 课程信息、收费模式缓存 + Map courseCacheMap = Maps.newHashMap(); + Map chargeCacheMap = Maps.newHashMap(); + + // 计算原价 实际价格 应收 + for (ReqBusinessSignUpItem signUpItem : signUpItemList) { + Long courseId = signUpItem.getCourseId(); + Long chargeId = signUpItem.getChargeId(); + boolean openDiscount = signUpItem.isOpenDiscount(); + boolean openDiscountFee = signUpItem.isOpenDiscountFee(); + ScCourse scCourse = scCourseService.getById(courseId); + ScCourseCharge courseCharge = courseChargeService.getById(chargeId); + if (!signUpItem.getChargeType().equals(courseCharge.getChargeType())) { + throw new BusinessException(scCourse.getCourseName() + "收费方式不一致,请重试"); + } + + courseCacheMap.put(courseId, scCourse); + chargeCacheMap.put(chargeId, courseCharge); + + Integer buyCount = signUpItem.getBuyCount(); + BigDecimal chargeTotalFee = courseCharge.getTotalFee(); + BigDecimal courseOriginalTotalFee = chargeTotalFee.multiply(new BigDecimal(buyCount)); + BigDecimal courseActualTotalFee = courseOriginalTotalFee; + + // 折扣 + if (openDiscount) { + // 实际价格= 实际价格 * 折扣(9.8/10) + courseActualTotalFee = courseActualTotalFee.multiply(signUpItem.getDiscount()).divide(new BigDecimal(10)); + } + // 优惠金额 + if (openDiscountFee) { + courseActualTotalFee = courseActualTotalFee.subtract(signUpItem.getDiscountFee()); + } + + // 原价 + originalTotalFee = originalTotalFee.add(courseOriginalTotalFee); + actualTotalFee = actualTotalFee.add(courseActualTotalFee); + } + // 实收 = 应收 - 余额支付 + needReceiptFee = actualTotalFee.subtract(reqBusinessSignUp.getBalancePayValue()); + if (needReceiptFee.compareTo(reqBusinessSignUp.getNeedReceiptFee()) != 0) { + throw new BusinessException("应收金额不一致,请重试"); + } + + // 入 sc_order 表 + Long orderId = null; + { + ScOrder order = ScOrder.builder() + .studentId(studentId) + .studentName(student.getStudentName()) + .phone(student.getPhone()) + .orderType("1") + .originalTotalFee(originalTotalFee) + .actualTotalFee(actualTotalFee) + .receiptFee(receiptWaySumMoney) + .balanceFee(reqBusinessSignUp.getBalancePayValue()) + .orderStatus(OrderStatusEnum.HAD_PAY.getOrderStatus()) + .memo(reqBusinessSignUp.getMemo()) + .handleDeptId(handleDept.getDeptId()) + .handleDeptName(handleDept.getDeptName()) + .handleDate(reqBusinessSignUp.getHandleDate()) + .createUser(loginUser.getUserId()) + .lastUpdateUser(loginUser.getUserId()) + .build(); + + if (null != reqBusinessSignUp.getOrderTag()) { + order.setOrderTag(String.join(",", reqBusinessSignUp.getOrderTag())); + } + if (null != reqBusinessSignUp.getSaleSourceTag()) { + order.setSaleSourceTag(String.join(",", reqBusinessSignUp.getSaleSourceTag())); + } + if (null != reqBusinessSignUp.getSaleStaffId()) { + SysStaff saleStaff = staffService.getById(reqBusinessSignUp.getSaleStaffId()); + if (null == saleStaff) { + throw new BusinessException("无法获取销售员工信息"); + } + order.setSaleStaffId(saleStaff.getStaffId()); + order.setSaleStaffName(saleStaff.getStaffName()); + } + + scOrderService.save(order); + orderId = order.getOrderId(); + log.info("save order success,orderId={}", orderId); + + if (null != reqBusinessSignUp.getOrderTag()) { + tagService.autoCreateTag(reqBusinessSignUp.getOrderTag(), "2", loginUser.getNowTenantId(), loginUser.getUserId()); + } + if (null != reqBusinessSignUp.getSaleSourceTag()) { + tagService.autoCreateTag(reqBusinessSignUp.getSaleSourceTag(), "1", loginUser.getNowTenantId(), loginUser.getUserId()); + } + } + + // 入sc_order_account + for (ReqBusinessSignUpReceipt signUpReceipt : signUpReceiptList) { + SysReceiptAccount receiptAccount = receiptAccountService.getById(signUpReceipt.getAccountId()); + if (null == receiptAccount) { + throw new BusinessException("无发获取收款账户,请核查后重试!"); + } + ScOrderAccount orderAccount = new ScOrderAccount(); + orderAccount.setOrderId(orderId); + orderAccount.setAccountId(signUpReceipt.getAccountId()); + orderAccount.setAccountName(receiptAccount.getAccountName()); + orderAccount.setFee(signUpReceipt.getReceiptMoney()); + orderAccountService.save(orderAccount); + } + + // 报读课程 + for (ReqBusinessSignUpItem signUpItem : signUpItemList) { + Long courseId = signUpItem.getCourseId(); + Long departId = signUpItem.getDepartId(); + Long claId = signUpItem.getClaId(); + Long chargeId = signUpItem.getChargeId(); + boolean openDiscount = signUpItem.isOpenDiscount(); + boolean openDiscountFee = signUpItem.isOpenDiscountFee(); + ScCourse scCourse = courseCacheMap.get(courseId); + ScCourseCla scCourseCla = new ScCourseCla(); + if (null != claId) { + scCourseCla = courseClaService.getById(claId); + if (null == scCourseCla) { + throw new BusinessException("无法获取" + scCourse.getCourseName() + "对应的班级,请重试"); + } + } + ScCourseCharge courseCharge = chargeCacheMap.get(chargeId); + if (!signUpItem.getChargeType().equals(courseCharge.getChargeType())) { + throw new BusinessException(scCourse.getCourseName() + "收费方式不一致,请重试"); + } + + Integer buyCount = signUpItem.getBuyCount(); + BigDecimal chargeTotalFee = courseCharge.getTotalFee(); + BigDecimal courseOriginalTotalFee = chargeTotalFee.multiply(new BigDecimal(buyCount)); + BigDecimal courseActualTotalFee = courseOriginalTotalFee; + + // 折扣 + if (openDiscount) { + // 实际价格= 实际价格 * 折扣(9.8/10) + courseActualTotalFee = courseActualTotalFee.multiply(signUpItem.getDiscount()).divide(new BigDecimal(10)); + } + // 优惠金额 + if (openDiscountFee) { + courseActualTotalFee = courseActualTotalFee.subtract(signUpItem.getDiscountFee()); + } + + // 已报读本课程信息 + ScStudentCourse dbStudentCourse = studentCourseService.selectByStudentIdCourseId(studentId, courseId); + + BigDecimal addedHour = BigDecimal.ZERO; + int addedDays = 0; + + if (CourseChargeTypeEnum.HOUR.getChargeType().equals(courseCharge.getChargeType())) { + // 新增课时 + addedHour = courseCharge.getCount().multiply(new BigDecimal(buyCount)); + } else if (CourseChargeTypeEnum.DATE.getChargeType().equals(courseCharge.getChargeType())) { + // 校验报读时间段是否重复 + boolean checkDateCover = courseOrderService.checkDateCover(studentId, courseId, signUpItem.getBeginDate(), signUpItem.getEndDate()); + if (checkDateCover) { + throw new BusinessException(scCourse.getCourseName() + "报读日期存在覆盖,请重新选择报读日期范围!"); + } + // 新增天数 + DateTime beginDate = DateUtil.yyyMMddDayBegin(signUpItem.getBeginDate()); + DateTime endDate = DateUtil.yyyMMddDayBegin(signUpItem.getEndDate()); + Period period = new Period(beginDate, endDate, PeriodType.days()); + addedDays = period.getDays() + 1; + } else if (CourseChargeTypeEnum.CYCLE.getChargeType().equals(courseCharge.getChargeType())) { + // 新增课时 + addedHour = courseCharge.getCount().multiply(new BigDecimal(buyCount)); + } + + // 插入 sc_order_detail + Long orderDetailId = null; + { + SysDept dept = deptService.getById(departId); + ScOrderDetail orderDetail = ScOrderDetail.builder() + .orderId(orderId) + .courseId(courseId) + .courseName(scCourse.getCourseName()) + .claId(claId) + .claName(scCourseCla.getClaName()) + .deptId(dept.getDeptId()) + .deptName(dept.getDeptName()) + .detailTag(signUpItem.getDetailTag()) + .chargeName(courseCharge.getChargeName()) + .chargeType(courseCharge.getChargeType()) + .chargeCount(courseCharge.getCount()) + .chargeFee(courseCharge.getTotalFee()) + .dateUnit(courseCharge.getDateUnit()) + .buyCount(new BigDecimal(buyCount)) + .originalFee(courseOriginalTotalFee) + .actualFee(courseActualTotalFee) + .insideMemo(signUpItem.getInsideMemo()) + .outsideMemo(signUpItem.getOutsideMemo()) + .orderDetailStatus(OrderStatusEnum.HAD_PAY.getOrderStatus()) + .createUser(loginUser.getUserId()) + .lastUpdateUser(loginUser.getUserId()) + .build(); + if (openDiscount) { + orderDetail.setDirectDiscount(signUpItem.getDiscount()); + } + if (openDiscountFee) { + orderDetail.setDirectReduceFee(signUpItem.getDiscountFee()); + } + if (signUpItem.isOpenExpire()) { + orderDetail.setExpireDate(signUpItem.getExpireDate()); + } + if (CourseChargeTypeEnum.DATE.getChargeType().equals(courseCharge.getChargeType())) { + orderDetail.setBeginDate(signUpItem.getBeginDate()); + orderDetail.setEndDate(signUpItem.getEndDate()); + } + orderDetailService.save(orderDetail); + orderDetailId = orderDetail.getOrderDetailId(); + } + + // 插入/更新 sc_student_course表 + Long studentCourseId = null; + { + // db中包含 + if (null != dbStudentCourse) { + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("student_course_id", dbStudentCourse.getStudentCourseId()); + uw.eq("total_fee", dbStudentCourse.getTotalFee()); + + if (CourseChargeTypeEnum.HOUR.getChargeType().equals(courseCharge.getChargeType())) { + uw.eq("balance_hour", dbStudentCourse.getBalanceHour()); + uw.eq("total_hour", dbStudentCourse.getTotalHour()); + uw.set("balance_hour", dbStudentCourse.getBalanceHour().add(addedHour)); + uw.set("total_hour", dbStudentCourse.getTotalHour().add(addedHour)); + } else if (CourseChargeTypeEnum.DATE.getChargeType().equals(courseCharge.getChargeType())) { + uw.eq("total_day", dbStudentCourse.getTotalDay()); + uw.set("total_day", dbStudentCourse.getTotalDay().add(new BigDecimal(addedDays))); + } else if (CourseChargeTypeEnum.CYCLE.getChargeType().equals(courseCharge.getChargeType())) { + uw.eq("balance_hour", dbStudentCourse.getBalanceHour()); + uw.eq("total_hour", dbStudentCourse.getTotalHour()); + uw.set("balance_hour", dbStudentCourse.getBalanceHour().add(addedHour)); + uw.set("total_hour", dbStudentCourse.getTotalHour().add(addedHour)); + } + uw.set("total_fee", dbStudentCourse.getTotalFee().add(courseActualTotalFee)); + uw.set("last_update_user", loginUser.getUserId()); + uw.set("last_update_time", new Date()); + + boolean update = studentCourseService.update(uw); + if (!update) { + throw new BusinessException("学员新增课时失败,请稍后重试"); + } + studentCourseId = dbStudentCourse.getStudentCourseId(); + } else { + ScStudentCourse addStudentCourse = new ScStudentCourse(); + addStudentCourse.setStudentId(studentId); + addStudentCourse.setCourseId(courseId); + addStudentCourse.setCourseName(scCourse.getCourseName()); + addStudentCourse.setDeptId(departId); + if (null != claId) { + addStudentCourse.setClaId(scCourseCla.getClaId()); + addStudentCourse.setClaName(scCourseCla.getClaName()); + } + addStudentCourse.setChargeType(courseCharge.getChargeType()); + if (CourseChargeTypeEnum.HOUR.getChargeType().equals(courseCharge.getChargeType())) { + addStudentCourse.setTotalHour(addedHour); + addStudentCourse.setBalanceHour(addedHour); + } else if (CourseChargeTypeEnum.DATE.getChargeType().equals(courseCharge.getChargeType())) { + addStudentCourse.setTotalDay(new BigDecimal(addedDays)); + } else if (CourseChargeTypeEnum.CYCLE.getChargeType().equals(courseCharge.getChargeType())) { + addStudentCourse.setTotalHour(addedHour); + addStudentCourse.setBalanceHour(addedHour); + } + addStudentCourse.setTotalFee(courseActualTotalFee); + addStudentCourse.setStatus("1"); + addStudentCourse.setCreateUser(loginUser.getUserId()); + addStudentCourse.setLastUpdateUser(loginUser.getUserId()); + studentCourseService.save(addStudentCourse); + studentCourseId = addStudentCourse.getStudentCourseId(); + } + } + + // 插入sc_student_course_order + { + ScStudentCourseOrder studentCourseOrder = ScStudentCourseOrder.builder() + .studentCourseId(studentCourseId) + .orderId(orderId) + .orderDetailId(orderDetailId) + .totalHour(addedHour) + .balanceHour(addedHour) + .totalDay(new BigDecimal(addedDays)) + .totalFee(courseActualTotalFee) + .createUser(loginUser.getUserId()) + .lastUpdateUser(loginUser.getUserId()) + .build(); + if (signUpItem.isOpenExpire()) { + studentCourseOrder.setExpireDate(signUpItem.getExpireDate()); + } + if (CourseChargeTypeEnum.DATE.getChargeType().equals(courseCharge.getChargeType())) { + studentCourseOrder.setBeginDate(signUpItem.getBeginDate()); + studentCourseOrder.setEndDate(signUpItem.getEndDate()); + + // 单价 = 总价/天 + studentCourseOrder.setUnitFee(courseActualTotalFee.divide(new BigDecimal(addedDays), 2, BigDecimal.ROUND_HALF_UP)); + } else { + // 单价 = 总价/课时数 + studentCourseOrder.setUnitFee(courseActualTotalFee.divide(addedHour, 2, BigDecimal.ROUND_HALF_UP)); + } + courseOrderService.save(studentCourseOrder); + } + + // 学生报读 日志 + StringBuffer sb = new StringBuffer(""); + if ("1".equals(signUpItem.getDetailTag())) { + sb.append("新报,"); + } else if ("2".equals(signUpItem.getDetailTag())) { + sb.append("续报,"); + } + sb.append("课程'").append(scCourse.getCourseName()).append("',"); + sb.append("金额").append(courseActualTotalFee.toString()).append("元,"); + ScStudentCourseLog studentCourseLog = ScStudentCourseLog.builder() + .studentId(studentId) + .logType(LogTypeEnum.PAY_FEE.getLogType()) + .courseId(courseId) + .courseName(scCourse.getCourseName()) + .claId(claId) + .claName(scCourseCla.getClaName()) + .deptName(handleDept.getDeptName()) + .changeFee(courseActualTotalFee) + .createUser(loginUser.getUserId()) + .createUserName(loginUser.getUsername()) + .createTime(new Date()) + .build(); + if (CourseChargeTypeEnum.DATE.getChargeType().equals(courseCharge.getChargeType())) { + sb.append("增加'").append(addedDays).append("'天"); + sb.append("(").append(signUpItem.getBeginDate()).append("~").append(signUpItem.getEndDate()).append(")."); + } else { + sb.append("增加'").append(addedHour.toString()).append("'课时,"); + studentCourseLog.setChangeHour(addedHour); + // 增加后剩余 + if (null != dbStudentCourse) { + studentCourseLog.setAfterBalanceHour(dbStudentCourse.getBalanceHour().add(addedHour)); + sb.append("增加后剩余").append(dbStudentCourse.getBalanceHour().add(addedHour).toString()).append("'课时").append("."); + } else { + studentCourseLog.setAfterBalanceHour(addedHour); + sb.append("增加后剩余").append(addedHour.toString()).append("'课时").append("."); + } + } + studentCourseLog.setMemo(sb.toString()); + scStudentCourseLogService.save(studentCourseLog); + } + + // 实收 > 应收, 增加 学生账户余额 + if (receiptWaySumMoney.compareTo(needReceiptFee) > 0) { + BigDecimal addBalanceFee = receiptWaySumMoney.subtract(needReceiptFee); + studentAccountService.addBalance(studentId, addBalanceFee, loginUser.getUserId()); + } + + return APIResponse.toOkResponse(); + } + + /** + * 作废订单 + * + * @param orderIds + * @return + */ + public APIResponse invalidById(Long[] orderIds) { + if (null == orderIds || orderIds.length == 0) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + + LoginUser loginUser = SecurityUtils.getLoginUser(); + + Integer dealSuccessCnt = 0; + Integer dealFailCnt = 0; + StringBuffer errorSb = new StringBuffer(); + + for (Long orderId : orderIds) { + ScOrder order = scOrderService.getById(orderId); + if (null == order) { + errorSb.append("订单'").append(orderId).append("',"); + errorSb.append("无法获取订单信息,请稍后重试;"); + dealFailCnt++; + continue; + } + if (OrderStatusEnum.INVALID.getOrderStatus().equals(order.getOrderStatus())) { + errorSb.append("订单'").append(orderId).append("',"); + errorSb.append("该订单已作废,无法再次作废;"); + dealFailCnt++; + continue; + } + + // 所有未作废的订单明细 + List orderDetailList = orderDetailService.getByOrderDetail(orderId, new String[]{OrderStatusEnum.INVALID.getOrderStatus()}); + + // 订单明细map + Map orderDetailMap = Maps.newHashMap(); + for (ScOrderDetail orderDetail : orderDetailList) { + orderDetailMap.put(orderDetail.getOrderDetailId(), orderDetail); + } + + // 所有关联的课程订单 + List orderDetailIdList = orderDetailList.stream().map(ScOrderDetail::getOrderDetailId).collect(Collectors.toList()); + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("order_id", orderId); + qw.in("order_detail_id", orderDetailIdList); + List courseOrderList = courseOrderService.list(qw); + + // 校验 如果消耗课时 不允许作废 + for (ScStudentCourseOrder courseOrder : courseOrderList) { + ScOrderDetail orderDetail = orderDetailMap.get(courseOrder.getOrderDetailId()); + if (CourseChargeTypeEnum.DATE.getChargeType().equals(orderDetail.getChargeType())) { + String beginDate = courseOrder.getBeginDate(); + String endDate = courseOrder.getEndDate(); + Long studentCourseId = courseOrder.getStudentCourseId(); + int studentCourseAttendCount = claTimeAttendService.studentCourseAttendCount(studentCourseId, beginDate, endDate); + if (0 != studentCourseAttendCount) { + // 订单日期范围内 有上课记录,不允许作废 + ScStudentCourse studentCourse = studentCourseService.getById(studentCourseId); + ScCourse scCourse = scCourseService.getById(studentCourse.getCourseId()); + errorSb.append("订单'").append(order.getOrderId()).append("',"); + errorSb.append(scCourse.getCourseName()).append(",在").append(beginDate).append("~").append(endDate).append(",有上课记录(").append(studentCourseAttendCount).append("次),无发作废;"); + dealFailCnt++; + continue; + } + } else { + if (null != courseOrder.getBalanceHour() && courseOrder.getBalanceHour().compareTo(courseOrder.getTotalHour()) < 0) { + // 按课时收费 并且 剩余课时<总课时 已消耗,不允许作废 + ScStudentCourse studentCourse = studentCourseService.getById(courseOrder.getStudentCourseId()); + ScCourse scCourse = scCourseService.getById(studentCourse.getCourseId()); + errorSb.append("订单:").append(order.getOrderId()).append(","); + errorSb.append(scCourse.getCourseName()).append(",已消耗课时,无法作废;"); + dealFailCnt++; + continue; + } else if (null != courseOrder.getBalanceHour() && courseOrder.getBalanceHour().compareTo(courseOrder.getTotalHour()) > 0) { + // 按课时收费 并且 剩余课时>总课时 删除上课记录 恢复课时后,剩余课时>总课时,不允许作废 + ScStudentCourse studentCourse = studentCourseService.getById(courseOrder.getStudentCourseId()); + ScCourse scCourse = scCourseService.getById(studentCourse.getCourseId()); + errorSb.append("订单:").append(order.getOrderId()).append(","); + errorSb.append(scCourse.getCourseName()).append(",剩余课时大于总课时,无法作废"); + dealFailCnt++; + continue; + } + } + dealSuccessCnt++; + } + + if(dealFailCnt != 0) { + return APIResponse.toExceptionResponse("操作失败,成功:" + dealSuccessCnt + ",失败:" + dealFailCnt + ",原因如下:" + errorSb.toString()); + } + + // 订单作废、订单明细作废 + scOrderService.invalidOrder(orderId); + orderDetailService.invalidOrder(orderId, orderDetailIdList); + + // 课程订单 失效、 剩余课时、时间 作废 + for (ScStudentCourseOrder courseOrder : courseOrderList) { + // 课程订单 失效 + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("course_order_id", courseOrder.getCourseOrderId()); + uw.set("valid", false); + courseOrderService.update(uw); + + // 学生课程信息 + ScStudentCourse studentCourse = studentCourseService.getById(courseOrder.getStudentCourseId()); + + ScOrderDetail orderDetail = orderDetailMap.get(courseOrder.getOrderDetailId()); + // 收费方式 + String chargeType = orderDetail.getChargeType(); + // 实际价格 + BigDecimal actualFee = orderDetail.getActualFee(); + + Long studentCourseId = courseOrder.getStudentCourseId(); + BigDecimal totalDay = courseOrder.getTotalDay(); + BigDecimal totalHour = courseOrder.getTotalHour(); + + // 学生日志 + StringBuffer sb = new StringBuffer("作废订单,"); + ScStudentCourseLog studentCourseLog = ScStudentCourseLog.builder() + .studentId(order.getStudentId()) + .logType(LogTypeEnum.INVALID_ORDER.getLogType()) + .courseId(orderDetail.getCourseId()) + .courseName(orderDetail.getCourseName()) + .claId(orderDetail.getClaId()) + .claName(orderDetail.getClaName()) + .deptName(orderDetail.getDeptName()) + .changeFee(actualFee.negate()) + .createUser(loginUser.getUserId()) + .createUserName(loginUser.getUsername()) + .createTime(new Date()) + .build(); + + if (CourseChargeTypeEnum.DATE.getChargeType().equals(chargeType)) { + + // 总天数 = 总天数 - 作废天数 + // 总学费 = 总学费 - 作废学费 + UpdateWrapper uwStudentCourse = new UpdateWrapper<>(); + uwStudentCourse + .eq("student_course_id", studentCourseId) + .eq("total_day", studentCourse.getTotalDay()) + .eq("total_fee", studentCourse.getTotalFee()) + .eq("charge_type", "date") + .set("total_day", studentCourse.getTotalDay().subtract(totalDay)) + .set("total_fee", studentCourse.getTotalFee().subtract(actualFee)) + .set("last_update_user", loginUser.getUserId()) + .set("last_update_time", new Date()); + boolean update = studentCourseService.update(uwStudentCourse); + if (!update) { + throw new BusinessException("学员报读恢复失败,请重试!"); + } + + // 当总天数、总费用为0时,删除报读 + studentCourseService.deleteWhenTotalDayZeroForInvalid(studentCourseId); + + sb.append("作废").append(totalDay.toString()).append("天,") + .append(actualFee.toString()).append("元"); + } else { + + // 剩余课时 = 剩余课时 - 作废课时 + // 总学费 = 总学费 - 作废学费 + UpdateWrapper uwStudentCourse = new UpdateWrapper<>(); + uwStudentCourse + .eq("student_course_id", studentCourseId) + .eq("total_hour", studentCourse.getTotalHour()) + .eq("balance_hour", studentCourse.getBalanceHour()) + .eq("total_fee", studentCourse.getTotalFee()) + .ne("charge_type", "date") + .set("total_hour", studentCourse.getTotalHour().subtract(totalHour)) + .set("balance_hour", studentCourse.getBalanceHour().subtract(totalHour)) + .set("total_fee", studentCourse.getTotalFee().subtract(actualFee)) + .set("last_update_user", loginUser.getUserId()) + .set("last_update_time", new Date()); + boolean update = studentCourseService.update(uwStudentCourse); + if (!update) { + throw new BusinessException("学员报读恢复失败,请重试!"); + } + + // 当总课时、总费用为0时,删除报读 + studentCourseService.deleteWhenTotalHourZeroForInvalid(studentCourseId); + + studentCourseLog.setChangeHour(totalHour.negate()); + studentCourseLog.setAfterBalanceHour(studentCourse.getBalanceHour().subtract(totalHour)); + sb.append("作废").append(totalHour.toString()).append("课时,") + .append(actualFee.toString()).append("元"); + } + studentCourseLog.setMemo(sb.toString()); + scStudentCourseLogService.save(studentCourseLog); + } + } + + if (dealFailCnt == 0) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse("操作失败,成功:" + dealSuccessCnt + ",失败:" + dealFailCnt + ",原因如下:" + errorSb.toString()); + } + + + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/IScOrderAccountService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/IScOrderAccountService.java new file mode 100644 index 0000000..d022959 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/IScOrderAccountService.java @@ -0,0 +1,25 @@ +package cn.xluobo.business.sc.order.service; + +import cn.xluobo.business.sc.order.repo.model.ScOrderAccount; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 订单收款账户 服务类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface IScOrderAccountService extends IService { + + /** + * 根据订单 获取收款账户 + * @param orderId + * @return + */ + List getOrderAccountList(Long orderId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/IScOrderDetailService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/IScOrderDetailService.java new file mode 100644 index 0000000..48b03ac --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/IScOrderDetailService.java @@ -0,0 +1,49 @@ +package cn.xluobo.business.sc.order.service; + +import cn.xluobo.business.sc.order.repo.model.ScOrderDetail; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 订单详情 服务类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface IScOrderDetailService extends IService { + + /** + * 根据单号获取 订单明细 + * @param orderId + * @return + */ + List getByOrderDetail(Long orderId); + + /** + * 获取订单明细 + * @param orderId + * @param notEqOrderStatus 不包含的状态 + * @return + */ + List getByOrderDetail(Long orderId, String[] notEqOrderStatus); + + /** + * 获取订单明细 + * @param orderId + * @param orderStatus + * @return + */ + List getByOrderDetail(Long orderId, String orderStatus); + + /** + * 作废订单明细 + * @param orderId + * @param orderDetailId + * @return + */ + boolean invalidOrder(Long orderId, List orderDetailId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/IScOrderService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/IScOrderService.java new file mode 100644 index 0000000..ccf3fcf --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/IScOrderService.java @@ -0,0 +1,38 @@ +package cn.xluobo.business.sc.order.service; + +import cn.xluobo.business.sc.order.repo.model.ScOrder; + +/** + *

+ * 订单 服务类 + *

+ * + * @author zhangby + * @since 2020-08-24 10:22:19 + */ +public interface IScOrderService extends com.baomidou.mybatisplus.extension.service.IService { + + /** + * 订单作废 + * @param orderId + * @return + */ + boolean invalidOrder(Long orderId); + + /** + * 订单数量 + * @param beginDate 经办日期开始时间 + * @param endDate 经办日期结束时间 + * @param orderType + * @return + */ + Integer orderCount(String beginDate, String endDate, String orderType); + + /** + * 欠费学员数量 + * 收款金额 + 余额支付金额 < 应收金额 + * @return + */ + Integer arrearsStudentCount(); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/impl/ScOrderAccountServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/impl/ScOrderAccountServiceImpl.java new file mode 100644 index 0000000..0edbd37 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/impl/ScOrderAccountServiceImpl.java @@ -0,0 +1,30 @@ +package cn.xluobo.business.sc.order.service.impl; + +import cn.xluobo.business.sc.order.repo.mapper.ScOrderAccountMapper; +import cn.xluobo.business.sc.order.repo.model.ScOrderAccount; +import cn.xluobo.business.sc.order.service.IScOrderAccountService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 订单收款账户 服务实现类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Service +public class ScOrderAccountServiceImpl extends ServiceImpl implements IScOrderAccountService { + + @Override + public List getOrderAccountList(Long orderId) { + QueryWrapper qw = new QueryWrapper<>(); + qw.select("account_name", "fee"); + qw.eq("order_id", orderId); + return this.list(qw); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/impl/ScOrderDetailServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/impl/ScOrderDetailServiceImpl.java new file mode 100644 index 0000000..2bf5bc1 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/impl/ScOrderDetailServiceImpl.java @@ -0,0 +1,56 @@ +package cn.xluobo.business.sc.order.service.impl; + +import cn.xluobo.business.sc.order.enums.OrderStatusEnum; +import cn.xluobo.business.sc.order.repo.mapper.ScOrderDetailMapper; +import cn.xluobo.business.sc.order.repo.model.ScOrderDetail; +import cn.xluobo.business.sc.order.service.IScOrderDetailService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 订单详情 服务实现类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Service +public class ScOrderDetailServiceImpl extends ServiceImpl implements IScOrderDetailService { + + @Override + public List getByOrderDetail(Long orderId) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("order_id", orderId); + return this.list(qw); + } + + @Override + public List getByOrderDetail(Long orderId, String[] notEqOrderStatus) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("order_id", orderId); + qw.notIn("order_detail_status", notEqOrderStatus); + return this.list(qw); + } + + @Override + public List getByOrderDetail(Long orderId, String orderStatus) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("order_id", orderId); + qw.eq("order_detail_status", orderStatus); + return this.list(qw); + } + + @Override + public boolean invalidOrder(Long orderId, List orderDetailId) { + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("order_id", orderId); + uw.in("order_detail_id", orderDetailId); + uw.set("order_detail_status", OrderStatusEnum.INVALID.getOrderStatus()); + return this.update(uw); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/impl/ScOrderServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/impl/ScOrderServiceImpl.java new file mode 100644 index 0000000..fa202ee --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/order/service/impl/ScOrderServiceImpl.java @@ -0,0 +1,43 @@ +package cn.xluobo.business.sc.order.service.impl; + +import cn.xluobo.business.sc.order.enums.OrderStatusEnum; +import cn.xluobo.business.sc.order.repo.mapper.ScOrderMapper; +import cn.xluobo.business.sc.order.repo.model.ScOrder; +import cn.xluobo.business.sc.order.service.IScOrderService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 订单 服务实现类 + *

+ * + * @author zhangby + * @since 2020-08-24 10:22:19 + */ +@Service +public class ScOrderServiceImpl extends ServiceImpl implements IScOrderService { + + @Override + public boolean invalidOrder(Long orderId) { + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("order_id", orderId); + uw.set("order_status", OrderStatusEnum.INVALID.getOrderStatus()); + return this.update(uw); + } + + @Override + public Integer orderCount(String beginDate, String endDate, String orderType) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("order_type", orderType); + qw.between("handle_date", beginDate, endDate); + return this.count(qw); + } + + @Override + public Integer arrearsStudentCount() { + return baseMapper.selectArrearsStudentCount(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/controller/ScStudentAccountController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/controller/ScStudentAccountController.java new file mode 100644 index 0000000..f23b88b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/controller/ScStudentAccountController.java @@ -0,0 +1,35 @@ +package cn.xluobo.business.sc.student.controller; + +import cn.xluobo.business.sc.student.service.BusinessScStudentAccountService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 学生账户 + * + * @author :zhangbaoyu + * @date :Created in 2020/9/2 14:03 + */ +@RestController +@RequestMapping("/api/sc/studentAccount") +public class ScStudentAccountController { + + @Autowired + private BusinessScStudentAccountService accountService; + + /** + * 学生账户余额 + * + * @param studentId + * @return + */ + @GetMapping("/info/studentAccountBalance/{studentId}") + public APIResponse studentAccountBalance(@PathVariable("studentId") Long studentId) { + return accountService.studentAccountBalance(studentId); + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/controller/ScStudentController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/controller/ScStudentController.java new file mode 100644 index 0000000..c8f1bb2 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/controller/ScStudentController.java @@ -0,0 +1,89 @@ +package cn.xluobo.business.sc.student.controller; + +import cn.xluobo.business.sc.student.domain.req.ReqSearchScStudent; +import cn.xluobo.business.sc.student.domain.req.ReqStudentSelect; +import cn.xluobo.business.sc.student.repo.model.ScStudent; +import cn.xluobo.business.sc.student.service.BusinessScStudentService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 学生基本信息 Controller + *

+ * + * @author zhangby + * @since 2020-04-27 07:13:40 + */ +@RestController +@RequestMapping("/api/sc/student") +public class ScStudentController { + @Autowired + private BusinessScStudentService scStudentService; + + /** + * 列表 + * + * @param reqSearchScStudent + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchScStudent reqSearchScStudent) { + return scStudentService.searchList(reqSearchScStudent); + } + + /** + * 前端select + * + * @return + */ + @GetMapping("/list/select") + public APIResponse select(ReqStudentSelect studentSelect) { + return scStudentService.select(studentSelect); + } + + /** + * 详情 + * + * @param studentId + * @return + */ + @GetMapping("/info/detailById/{studentId}") + public APIResponse detailById(@PathVariable("studentId") Long studentId) { + return scStudentService.detailById(studentId); + } + + /** + * 添加 + * + * @param scStudent + * @return + */ + @PostMapping("/add/addScStudent") + public APIResponse addScStudent(@RequestBody ScStudent scStudent) { + return scStudentService.addScStudent(scStudent); + } + + /** + * 修改 + * + * @param scStudent + * @return + */ + @PutMapping("/update/updateScStudent") + public APIResponse updateScStudent(@RequestBody ScStudent scStudent) { + return scStudentService.updateScStudent(scStudent); + } + + /** + * 删除 + * + * @param studentIds + * @return + */ + @DeleteMapping("/delete/deleteById/{studentIds}") + public APIResponse deleteById(@PathVariable("studentIds") Long[] studentIds) { + return scStudentService.deleteById(studentIds); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/controller/ScStudentCourseController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/controller/ScStudentCourseController.java new file mode 100644 index 0000000..2fa0c88 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/controller/ScStudentCourseController.java @@ -0,0 +1,119 @@ +package cn.xluobo.business.sc.student.controller; + +import cn.xluobo.business.sc.student.domain.req.*; +import cn.xluobo.business.sc.student.domain.resp.RespCourseClaStudent; +import cn.xluobo.business.sc.student.domain.resp.RespStuCourseSignUpStudent; +import cn.xluobo.business.sc.student.domain.resp.RespStudentCourse; +import cn.xluobo.business.sc.student.service.BusinessScStudentCourseService; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.page.RespPage; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 学生课程 + * + * @author :zhangbaoyu + * @date :Created in 2020/9/2 15:05 + */ +@RestController +@RequestMapping("/api/sc/studentCourse") +public class ScStudentCourseController { + + @Autowired + private BusinessScStudentCourseService studentCourseService; + + /** + * 学生课程相关信息 + * @param studentId + * @return 报读课程、校区、联系人信息 + */ + @GetMapping("/info/studentCourseInfo/{studentId}") + public APIResponse studentCourseInfo(@PathVariable("studentId") Long studentId){ + return studentCourseService.studentCourseInfo(studentId); + } + + /** + * 课程、班级 学生列表 + * @param reqSearchStudentCourseCla + * @return + */ + @GetMapping("/list/searchCourseClaStudent") + public APIResponse searchCourseClaStudent(ReqSearchStudentCourseCla reqSearchStudentCourseCla){ + RespPage respPage = studentCourseService.searchCourseClaStudent(reqSearchStudentCourseCla); + return APIResponse.toAPIResponse(respPage); + } + + /** + * 已报名未选择班级 选择班级 + * @return + */ + @PostMapping("/update/studentCourseChooseCla") + public APIResponse studentCourseChooseCla(@RequestBody ReqStudentCourseChooseCla studentCourseChooseCla){ + return studentCourseService.studentCourseChooseCla(studentCourseChooseCla); + } + + /** + * 记上课 + * @param reqClaTimeAttend + * @return + */ + @PostMapping("/update/claTimeAttend") + public APIResponse claTimeAttend(@RequestBody ReqClaTimeAttend reqClaTimeAttend){ + return studentCourseService.claTimeAttend(reqClaTimeAttend); + } + + /** + * 学生停课 + * @param studentCourseId + * @return + */ + @PostMapping("/update/stopStudentCourseStatus/{studentCourseId}") + public APIResponse stopStudentCourseStatus(@PathVariable("studentCourseId") Long studentCourseId) { + return studentCourseService.stopStudentCourseStatus(studentCourseId); + } + + /** + * 变更学生状态为在读 + * @param studentCourseId + * @return + */ + @PostMapping("/update/atClaStudentCourseStatus/{studentCourseId}") + public APIResponse atClaStudentCourseStatus(@PathVariable("studentCourseId") Long studentCourseId) { + return studentCourseService.atClaStudentCourseStatus(studentCourseId); + } + + /** + * 学生报读课程列表 + * @param reqSearchStudentCourse + * @return + */ + @GetMapping("/list/searchStudentCourse") + public APIResponse searchStudentCourse(ReqSearchStudentCourse reqSearchStudentCourse){ + List respStudentCourses = studentCourseService.searchStudentCourse(reqSearchStudentCourse); + return APIResponse.toAPIResponse(respStudentCourses); + } + + /** + * 报读列表 + * @param reqSearchStuCourseSignUp + * @return + */ + @GetMapping("/list/searchStuCourseSignUpList") + public APIResponse searchStuCourseSignUpList(ReqSearchStuCourseSignUp reqSearchStuCourseSignUp){ + RespPage respPage = studentCourseService.searchStuCourseSignUpList(reqSearchStuCourseSignUp); + return APIResponse.toAPIResponse(respPage); + } + + /** + * 报读信息中 将学员从班级中移除 + * @param studentCourseId + * @return + */ + @PostMapping("/update/removeStuFromCla/{studentCourseId}") + public APIResponse removeStuFromCla(@PathVariable("studentCourseId") Long studentCourseId) { + return studentCourseService.removeStuFromCla(studentCourseId); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqClaTimeAttend.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqClaTimeAttend.java new file mode 100644 index 0000000..cf2ff1f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqClaTimeAttend.java @@ -0,0 +1,106 @@ +package cn.xluobo.business.sc.student.domain.req; + +import cn.xluobo.core.api.APIResponse; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +/** + * 记上课请求参数 + * 修改上课记录请求参数 + * @author :zhangbaoyu + * @date :Created in 2020/10/1 19:44 + */ +@Data +public class ReqClaTimeAttend { + + // 上课方式 排课记上课rule、自定义上课custom + private String attendType; + + // 排课编号 + private Long courseTimeId; + + private Long claId; + + private Long teacherId; + + private Long roomId; + + private String claDate; + + private String startTime; + + private String endTime; + + private String classTheme; + + private String memo; + + List studentAttendList; + + /** + * 参数校验 + * @return + */ + public APIResponse checkParam() { + if(null == studentAttendList || studentAttendList.size() ==0) { + return APIResponse.toExceptionResponse("排课记上课,请选择上课学生"); + } + for (ReqClaTimeAttendItem attendItem : studentAttendList) { + if(StringUtils.isAnyEmpty(attendItem.getAttendStatus())) { + return APIResponse.toExceptionResponse("请选择学员到课状态"); + } else if(null == attendItem.getStudentCourseId()) { + return APIResponse.toExceptionResponse("请选择学员"); + } else if(null == attendItem.getStuLoseHour()) { + return APIResponse.toExceptionResponse("请选择扣减课时"); + } + } + if("rule".equals(attendType)) { + // 排课记上课 + if(null == courseTimeId) { + return APIResponse.toExceptionResponse("排课记上课,未选择上课日期!"); + } else if(StringUtils.isAnyEmpty(startTime,endTime)) { + return APIResponse.toExceptionResponse("排课记上课,未选择上下课时间!"); + } + + } else if ("custom".equals(attendType)) { + // 自定义记上课 + if(StringUtils.isAnyEmpty(claDate,startTime,endTime)) { + return APIResponse.toExceptionResponse("自定义记上课,未选择上课日期,上下课时间!"); + } else if( null == teacherId) { + return APIResponse.toExceptionResponse("自定义记上课,请选择上课教师!"); + } + } + return APIResponse.toOkResponse(); + } + + /** + * 已上课修改 + * 参数校验 + * @return + */ + public APIResponse checkParamForUpdateHadClaTime() { + if(null == studentAttendList || studentAttendList.size() ==0) { + return APIResponse.toExceptionResponse("排课记上课,请选择上课学生"); + } + for (ReqClaTimeAttendItem attendItem : studentAttendList) { + if(StringUtils.isAnyEmpty(attendItem.getAttendStatus())) { + return APIResponse.toExceptionResponse("请选择学员到课状态"); + } else if(null == attendItem.getStudentCourseId()) { + return APIResponse.toExceptionResponse("请选择学员"); + } else if(null == attendItem.getStuLoseHour()) { + return APIResponse.toExceptionResponse("请选择扣减课时"); + } + } + + // 自定义记上课 + if(StringUtils.isAnyEmpty(claDate,startTime,endTime)) { + return APIResponse.toExceptionResponse("自定义记上课,未选择上课日期,上下课时间!"); + } else if( null == teacherId) { + return APIResponse.toExceptionResponse("自定义记上课,请选择上课教师!"); + } + return APIResponse.toOkResponse(); + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqClaTimeAttendItem.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqClaTimeAttendItem.java new file mode 100644 index 0000000..bf7a7c1 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqClaTimeAttendItem.java @@ -0,0 +1,26 @@ +package cn.xluobo.business.sc.student.domain.req; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/10/1 19:47 + */ +@Data +public class ReqClaTimeAttendItem { + + // 学生 + private Long studentCourseId; + + // 1:到课 2:请假 3:缺勤 + private String attendStatus; + + // 备注 + private String memo; + + // 学生消耗课时 + private BigDecimal stuLoseHour; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchScStudent.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchScStudent.java new file mode 100644 index 0000000..7039fb5 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchScStudent.java @@ -0,0 +1,22 @@ +package cn.xluobo.business.sc.student.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchScStudent extends ReqPageBase implements Serializable { + + private String schoolId; + + private String studentName; + + private String sex; + + private String phone; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchStuCourseSignUp.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchStuCourseSignUp.java new file mode 100644 index 0000000..229b3ad --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchStuCourseSignUp.java @@ -0,0 +1,29 @@ +package cn.xluobo.business.sc.student.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * 报读列表 请求参数 + * @author :zhangbaoyu + * @date :Created in 2020/12/21 20:28 + */ +@Data +public class ReqSearchStuCourseSignUp extends ReqPageBase implements Serializable { + + private Long claId; + + // 所属校区 + private Long departId; + + // 所属课程 + private Long courseId; + + // 剩余最大天数 + private Integer minBalanceDay; + + // 剩余最大课时 + private Integer minBalanceHour; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchStudentCourse.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchStudentCourse.java new file mode 100644 index 0000000..c5368a8 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchStudentCourse.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sc.student.domain.req; + +import cn.xluobo.core.page.ReqDeptCondition; +import lombok.Data; + +/** + * 查询学生报读的课程信息 + * @author :zhangbaoyu + * @date :Created in 2020/10/8 22:03 + */ +@Data +public class ReqSearchStudentCourse extends ReqDeptCondition { + + private Long studentId; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchStudentCourseCla.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchStudentCourseCla.java new file mode 100644 index 0000000..8a3fb72 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqSearchStudentCourseCla.java @@ -0,0 +1,28 @@ +package cn.xluobo.business.sc.student.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * 查询学生课程、班级 + * @author :zhangbaoyu + * @date :Created in 2020-06-20 12:30 + */ +@Data +public class ReqSearchStudentCourseCla extends ReqPageBase implements Serializable { + + private Long claId; + + // 所属校区 + private Long departId; + + // 所属课程 + private Long courseId; + + private Boolean unChooseCla; + + // 是否生效 + private Boolean effect; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqStudentCourseChooseCla.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqStudentCourseChooseCla.java new file mode 100644 index 0000000..246c8c0 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqStudentCourseChooseCla.java @@ -0,0 +1,35 @@ +package cn.xluobo.business.sc.student.domain.req; + +import lombok.Data; + +/** + * 学生选择班级 + * 报读课程未选择班级 选择班级 + * + * @author :zhangbaoyu + * @date :Created in 2020/9/30 09:53 + */ +@Data +public class ReqStudentCourseChooseCla { + + // 报读编号 sc_student_course.student_course_id + private Long[] chooseStudentCourseIds; + + // 选择的班级 + private Long claId; + + // 所属课程 + private Long courseId; + + public boolean checkParam() { + if (null == chooseStudentCourseIds || chooseStudentCourseIds.length == 0) { + return false; + } else if (null == claId) { + return false; + } else if (null == courseId) { + return false; + } + return true; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqStudentSelect.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqStudentSelect.java new file mode 100644 index 0000000..ffa4d73 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/req/ReqStudentSelect.java @@ -0,0 +1,19 @@ +package cn.xluobo.business.sc.student.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +/** + * 学生 select + * + * @author :zhangbaoyu + * @date :Created in 2020-06-19 08:41 + */ +@Data +public class ReqStudentSelect extends ReqPageBase { + + private String search; + + private String schoolId; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespBusinessStudentCourseInfo.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespBusinessStudentCourseInfo.java new file mode 100644 index 0000000..b9e5748 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespBusinessStudentCourseInfo.java @@ -0,0 +1,23 @@ +package cn.xluobo.business.sc.student.domain.resp; + +import lombok.Builder; +import lombok.Data; + +/** + * 学生报读课程信息 + * @author :zhangbaoyu + * @date :Created in 2020/9/2 15:48 + */ +@Data +@Builder +public class RespBusinessStudentCourseInfo { + + // 联系电话 + private String contactPhone; + // 联系电话明细 + private String contactPhoneDetail; + // 报读课程名称列表 + private String courseNames; + // 报读校区名称列表 + private String deptNames; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespCourseClaStudent.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespCourseClaStudent.java new file mode 100644 index 0000000..3855fb4 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespCourseClaStudent.java @@ -0,0 +1,113 @@ +package cn.xluobo.business.sc.student.domain.resp; + +import cn.xluobo.business.sc.course.enums.CourseChargeTypeEnum; +import lombok.Data; +import org.joda.time.DateTime; +import org.joda.time.Period; +import org.joda.time.PeriodType; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 班级学员 + * 用于 班级下学生列表 + * @author :zhangbaoyu + * @date :Created in 2020/9/28 16:51 + */ +@Data +public class RespCourseClaStudent { + + private Long studentCourseId; + + private Long claId; + + private Long courseId; + + // 报读校区 + private String deptName; + + private Long studentId; + + private String studentName; + + private String sex; + + private String phone; + + // 联系人信息 + private String contactInfo; + + private String chargeType; + + private BigDecimal totalDay; + private BigDecimal totalHour; + private BigDecimal balanceHour; + // 过期课时 + private BigDecimal expireHour; + + // 即将生效的 总天数 + private BigDecimal comingEffectDay; + + /** + * 按时间收费 当期 到期时间 + * 当前生效周期到期时间 + */ + private Date endDate; + + // 状态 + private String status; + + // 首次报名时间 + private Date firstSignTime; + + // 最后一次续费时间 + private Date lastSignTime; + + /** + * 获取剩余天数 + * @return + */ + public BigDecimal getBalanceDays() { + try { + if(CourseChargeTypeEnum.DATE.getChargeType().equals(chargeType)) { + if(null == this.endDate) { + // 无生效周期 + return comingEffectDay; + } else { + // 有生效周期 + Period period = new Period(DateTime.now(), new DateTime(this.endDate), PeriodType.days()); + return new BigDecimal(period.getDays() + 1).add(comingEffectDay); + } + } else { + return BigDecimal.ZERO; + } + } catch (Exception e) { + e.printStackTrace(); + return BigDecimal.ZERO; + } + } + + /** + * 按时间收费 当前时间 是否在缴费周期内(是否有效) + * @return + */ + public boolean isEffect() { + try{ + if(CourseChargeTypeEnum.DATE.getChargeType().equals(chargeType)) { + if(null == this.endDate) { + // 未生效 + return false; + } else { + return true; + } + } else { + return true; + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespSearchStudent.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespSearchStudent.java new file mode 100644 index 0000000..434804b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespSearchStudent.java @@ -0,0 +1,44 @@ +package cn.xluobo.business.sc.student.domain.resp; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 学生基本信息 + *

+ * + * @author zhangby + * @since 2020-04-27 07:13:40 + */ +@Data +public class RespSearchStudent implements Serializable { + + + + private Long studentId; + + private Long schoolId; + + private String schoolName; + + private String studentName; + + @JsonFormat(pattern="yyyy-MM-dd") + private Date birthDay; + + private Integer age; + + private String sex; + + private String phone; + + @JsonFormat(pattern="yyyy-MM-dd") + private Date inTime; + + // 联系人信息 + private String contactInfo; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespStuCourseSignUpStudent.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespStuCourseSignUpStudent.java new file mode 100644 index 0000000..876a0a8 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespStuCourseSignUpStudent.java @@ -0,0 +1,120 @@ +package cn.xluobo.business.sc.student.domain.resp; + +import cn.xluobo.business.sc.course.enums.CourseChargeTypeEnum; +import lombok.Data; +import org.joda.time.DateTime; +import org.joda.time.Period; +import org.joda.time.PeriodType; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 学员报读列表 + * @author :zhangbaoyu + * @date :Created in 2020/12/21 20:28 + */ +@Data +public class RespStuCourseSignUpStudent { + + private Long studentCourseId; + + private Long claId; + + private String claName; + + private Long courseId; + + private String courseName; + + // 报读校区 + private String deptName; + + private Long studentId; + + private String studentName; + + private String sex; + + private String phone; + + // 联系人信息 + private String contactInfo; + + private String chargeType; + + private BigDecimal totalHour; + private BigDecimal balanceHour; + // 过期课时 + private BigDecimal expireHour; + + // 总学费 + private BigDecimal totalFee; + // 剩余学费 + private BigDecimal balanceFee; + // 过期学费 + private BigDecimal expireFee; + + private BigDecimal totalDay; + + private String orderDetail; + + // 即将生效的 总天数 + private BigDecimal comingEffectDay; + + /** + * 按时间收费 当期 到期时间 + * 当前生效周期到期时间 + */ + private Date endDate; + + // 状态 + private String status; + + /** + * 获取剩余天数 + * @return + */ + public BigDecimal getBalanceDays() { + try { + if(CourseChargeTypeEnum.DATE.getChargeType().equals(chargeType)) { + if(null == this.endDate) { + // 无生效周期 + return comingEffectDay; + } else { + // 有生效周期 + Period period = new Period(DateTime.now(), new DateTime(this.endDate), PeriodType.days()); + return new BigDecimal(period.getDays() + 1).add(comingEffectDay); + } + } else { + return BigDecimal.ZERO; + } + } catch (Exception e) { + e.printStackTrace(); + return BigDecimal.ZERO; + } + } + + /** + * 按时间收费 当前时间 是否在缴费周期内(是否有效) + * @return + */ + public boolean isEffect() { + try{ + if(CourseChargeTypeEnum.DATE.getChargeType().equals(chargeType)) { + if(null == this.endDate) { + // 未生效 + return false; + } else { + return true; + } + } else { + return true; + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespStudentCourse.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespStudentCourse.java new file mode 100644 index 0000000..c7a81b0 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/domain/resp/RespStudentCourse.java @@ -0,0 +1,103 @@ +package cn.xluobo.business.sc.student.domain.resp; + +import cn.xluobo.business.sc.course.enums.CourseChargeTypeEnum; +import lombok.Data; +import org.joda.time.DateTime; +import org.joda.time.Period; +import org.joda.time.PeriodType; + +import java.math.BigDecimal; + +/** + * 学生 报读 课程列表 + * @author :zhangbaoyu + * @date :Created in 2020/10/8 22:02 + */ +@Data +public class RespStudentCourse { + + private Long studentCourseId; + + private String courseName; + + private String chargeType; + + private BigDecimal totalDay; + + private BigDecimal totalHour; + + private BigDecimal balanceHour; + + // 过期课时 + private BigDecimal expireHour; + + private BigDecimal totalFee; + + private String status; + + private Long studentId; + + private String studentName; + + private String deptName; + + private String claName; + + private String orderDetail; + + // 即将生效的 总天数 + private BigDecimal comingEffectDay; + + /** + * 按时间收费 当期 到期时间 + * 当前生效周期到期时间 + */ + private String endDate; + + /** + * 获取剩余天数 + * @return + */ + public BigDecimal getBalanceDays() { + try { + if(CourseChargeTypeEnum.DATE.getChargeType().equals(chargeType)) { + if(null == this.endDate) { + // 无生效周期 + return comingEffectDay; + } else { + // 有生效周期 + Period period = new Period(DateTime.now(), new DateTime(this.endDate), PeriodType.days()); + return new BigDecimal(period.getDays() + 1).add(comingEffectDay); + } + } else { + return BigDecimal.ZERO; + } + } catch (Exception e) { + e.printStackTrace(); + return BigDecimal.ZERO; + } + } + + /** + * 按时间收费 当前时间 是否在缴费周期内(是否有效) + * @return + */ + public boolean isEffect() { + try{ + if(CourseChargeTypeEnum.DATE.getChargeType().equals(chargeType)) { + if(null == this.endDate) { + // 未生效 + return false; + } else { + return true; + } + } else { + return true; + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/enums/StudentCourseStatusEnum.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/enums/StudentCourseStatusEnum.java new file mode 100644 index 0000000..23a47ad --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/enums/StudentCourseStatusEnum.java @@ -0,0 +1,29 @@ +package cn.xluobo.business.sc.student.enums; + +/** + * 上课状态 + * + * @author :zhangbaoyu + * @date :Created in 2020/10/3 09:32 + */ +public enum StudentCourseStatusEnum { + + AT_CLA("1","在读"), + STOP_CLA("2","停课"); + + private final String studentCourseStatus; + private final String studentCourseStatusName; + + StudentCourseStatusEnum(String studentCourseStatus, String studentCourseStatusName) { + this.studentCourseStatus = studentCourseStatus; + this.studentCourseStatusName = studentCourseStatusName; + } + + public String getStudentCourseStatus() { + return studentCourseStatus; + } + + public String getStudentCourseStatusName() { + return studentCourseStatusName; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentAccountLogMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentAccountLogMapper.java new file mode 100644 index 0000000..e3c94f5 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentAccountLogMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sc.student.repo.mapper; + +import cn.xluobo.business.sc.student.repo.model.ScStudentAccountLog; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 账户变更日志 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface ScStudentAccountLogMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentAccountMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentAccountMapper.java new file mode 100644 index 0000000..0dbc27e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentAccountMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sc.student.repo.mapper; + +import cn.xluobo.business.sc.student.repo.model.ScStudentAccount; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 学生余额账户 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface ScStudentAccountMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentContactMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentContactMapper.java new file mode 100644 index 0000000..9a87bd1 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentContactMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sc.student.repo.mapper; + +import cn.xluobo.business.sc.student.repo.model.ScStudentContact; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 联系人 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-09-27 + */ +public interface ScStudentContactMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentCourseMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentCourseMapper.java new file mode 100644 index 0000000..ad82f60 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentCourseMapper.java @@ -0,0 +1,101 @@ +package cn.xluobo.business.sc.student.repo.mapper; + +import cn.xluobo.business.sc.student.domain.req.ReqSearchStuCourseSignUp; +import cn.xluobo.business.sc.student.domain.req.ReqSearchStudentCourse; +import cn.xluobo.business.sc.student.domain.req.ReqSearchStudentCourseCla; +import cn.xluobo.business.sc.student.domain.resp.RespCourseClaStudent; +import cn.xluobo.business.sc.student.domain.resp.RespStuCourseSignUpStudent; +import cn.xluobo.business.sc.student.domain.resp.RespStudentCourse; +import cn.xluobo.business.sc.student.repo.model.ScStudentCourse; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 学生课程 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface ScStudentCourseMapper extends BaseMapper { + + /** + * 学生在读课程名称 + * @param studentId + * @return + */ + List selectStudentCourseNameList(Long studentId); + + /** + * 学生报读校区 + * @param studentId + * @return + */ + List selectStudentDeptNameList(Long studentId); + + /** + * 课程、班级 学生列表 + * + * @param reqSearchStudentCourseCla + * @param page + * @return + */ + List selectStudentList(@Param("reqSearchStudentCourseCla")ReqSearchStudentCourseCla reqSearchStudentCourseCla, @Param("page")Page page); + + /** + * 应到人数 + * @param claId + * @return + */ + int selectClaNeedAttendCnt(Long claId); + + /** + * 学生报读课程列表 + * @param searchStudentCourse + * @return + */ + List selectStudentCourseList(ReqSearchStudentCourse searchStudentCourse); + + /** + * 当报读课程总课时、总费用 为0时,删除报读 + * @param studentCourseId + * @return + */ + int deleteWhenTotalHourZeroForInvalid(Long studentCourseId); + + /** + * 当报读课程总天数、总费用 为0时,删除报读 + * @param studentCourseId + * @return + */ + int deleteWhenTotalDayZeroForInvalid(Long studentCourseId); + + /** + * 在读学生 剩余天数 小于 minBalanceDay 的数量 + * 未生效天数 + 生效剩余天数 < minBalanceDay + * @param minBalanceDay 最小剩余天数 + * @return + */ + Integer selectWillExpireDateCount(Integer minBalanceDay); + + /** + * 在读学生 剩余课时 小于 minBalanceHour 的数量 + * 剩余课时 - 过期课时 < minBalanceHour + * @param minBalanceHour 最小剩余课时数 + * @return + */ + Integer selectWillExpireHourCount(Integer minBalanceHour); + + /** + * 学生报读列表 + * + * @param reqSearchStuCourseSignUp + * @param page + * @return + */ + List selectStudentSignUpList(@Param("reqSearchStuCourseSignUp") ReqSearchStuCourseSignUp reqSearchStuCourseSignUp, @Param("page")Page page); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentCourseOrderMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentCourseOrderMapper.java new file mode 100644 index 0000000..05e9fbf --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentCourseOrderMapper.java @@ -0,0 +1,71 @@ +package cn.xluobo.business.sc.student.repo.mapper; + +import cn.xluobo.business.sc.student.repo.model.ScStudentCourseOrder; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 学生课程关联订单 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface ScStudentCourseOrderMapper extends BaseMapper { + + + /** + * 校验按时间收费 收费日期是否存在覆盖 + * + * @param studentId + * @param courseId + * @param beginDate + * @param endDate + * @return + */ + int checkDateCover(@Param("studentId") Long studentId, @Param("courseId") Long courseId, + @Param("beginDate") String beginDate, @Param("endDate") String endDate); + + /** + * 获取需扣减课时的订单 + * @param studentCourseId + * @return + */ + ScStudentCourseOrder selectSubtractHourOrder(Long studentCourseId); + + /** + * 当前生效 按时间 缴费订单 + * @param studentCourseId + * @return + */ + ScStudentCourseOrder selectNowValidDateOrder(Long studentCourseId); + + /** + * 获取可扣减课时的订单列表 + * @param studentCourseId + * @return + */ + List selectSubtractHourOrderList(Long studentCourseId); + + /** + * 按课时收费 订单列表,按时间倒叙 + * @param studentCourseId + * @return + */ + List selectRecoverHourOrderList(Long studentCourseId); + + /** + * 扣减课时 + * @param courseOrderId + * @param newHour + * @param oldHour + * @return + */ + int updateSubtractHour(@Param("courseOrderId") Long courseOrderId, + @Param("newHour") BigDecimal newHour, + @Param("oldHour") BigDecimal oldHour); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentMapper.java new file mode 100644 index 0000000..2e73c42 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapper/ScStudentMapper.java @@ -0,0 +1,49 @@ +package cn.xluobo.business.sc.student.repo.mapper; + +import cn.xluobo.business.sc.student.domain.req.ReqSearchScStudent; +import cn.xluobo.business.sc.student.domain.req.ReqStudentSelect; +import cn.xluobo.business.sc.student.domain.resp.RespSearchStudent; +import cn.xluobo.business.sc.student.repo.model.ScStudent; +import cn.xluobo.core.page.ReqDeptCondition; +import com.baomidou.mybatisplus.annotation.SqlParser; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 学生基本信息 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-04-27 07:13:40 + */ +public interface ScStudentMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + + List selectForSearchTable(@Param("reqSearchScStudent")ReqSearchScStudent reqSearchScStudent, @Param("page")Page page); + + List selectForSelect(@Param("studentSelect") ReqStudentSelect studentSelect, @Param("page") Page page); + + /** + * 全部学生 + * @param reqSearchScStudent + * @return + */ + List selectAllStudent(ReqSearchScStudent reqSearchScStudent); + + /** + * 学员数量 + * @param reqDeptCondition + * @return + */ + Integer selectStudentCount(ReqDeptCondition reqDeptCondition); + + /** + * 租户下学生数量 + * @param tenantId + * @return + */ + @SqlParser(filter = true) + Integer selectTenantStudentCount(String tenantId); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentAccountLogMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentAccountLogMapper.xml new file mode 100644 index 0000000..2f1b247 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentAccountLogMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentAccountMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentAccountMapper.xml new file mode 100644 index 0000000..5c34b48 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentAccountMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentContactMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentContactMapper.xml new file mode 100644 index 0000000..93248e6 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentContactMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentCourseMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentCourseMapper.xml new file mode 100644 index 0000000..e301f3b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentCourseMapper.xml @@ -0,0 +1,194 @@ + + + + + + + + + + + delete from sc_student_course where student_course_id=#{studentCourseId} and charge_type ]]> 'date' and total_hour=0 and total_fee=0 + + + delete from sc_student_course where student_course_id=#{studentCourseId} and charge_type = 'date' and total_day=0 and total_fee=0 + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentCourseOrderMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentCourseOrderMapper.xml new file mode 100644 index 0000000..d033202 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentCourseOrderMapper.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + update sc_student_course_order set balance_hour = #{newHour} where course_order_id=#{courseOrderId} and balance_hour = #{oldHour} + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentMapper.xml new file mode 100644 index 0000000..85e6e0a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/mapping/ScStudentMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudent.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudent.java new file mode 100644 index 0000000..fb006d7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudent.java @@ -0,0 +1,131 @@ +package cn.xluobo.business.sc.student.repo.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.joda.time.DateTime; +import org.joda.time.Period; +import org.joda.time.PeriodType; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + *

+ * 学生基本信息 + *

+ * + * @author zhangby + * @since 2020-04-27 07:13:40 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_student") +public class ScStudent implements Serializable { + + + /** + * 学生id + */ + @TableId(value = "student_id") + private Long studentId; + + /** + * 所属机构 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 所属学校 + */ + @TableField("school_id") + private Long schoolId; + + /** + * 学生姓名 + */ + @TableField("student_name") + private String studentName; + + /** + * 出生日期 + */ + @TableField("birth_day") + @JsonFormat(pattern="yyyy-MM-dd") + private Date birthDay; + + /** + * 性别 M男 F女 + */ + @TableField("sex") + private String sex; + + /** + * 监护人联系电话 + */ + @TableField("phone") + private String phone; + + /** + * 入校时间 + */ + @TableField("in_time") + private String inTime; + + /** + * 删除标志(1删除 0在用) + */ + @TableField("delete_flag") + @TableLogic + private String deleteFlag; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + @TableField(exist = false) + private String schoolName; + @TableField(exist = false) + private Integer age; + @TableField(exist = false) + List contactList; + + public Integer getAge() { + if(null == age && null != birthDay) { + DateTime now = new DateTime(); + DateTime birthDateTime = new DateTime(birthDay); + Period period = new Period(birthDateTime, now, PeriodType.years()); + return period.getYears(); + } else { + return age; + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentAccount.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentAccount.java new file mode 100644 index 0000000..71471d8 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentAccount.java @@ -0,0 +1,74 @@ +package cn.xluobo.business.sc.student.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 学生余额账户 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_student_account") +public class ScStudentAccount implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 账户编号 + */ + @TableId(value = "account_id", type = IdType.ASSIGN_ID) + private Long accountId; + + /** + * 学生 + */ + @TableField("student_id") + private Long studentId; + + /** + * 账户余额 + */ + @TableField("balance_fee") + private BigDecimal balanceFee; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentAccountLog.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentAccountLog.java new file mode 100644 index 0000000..1128d74 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentAccountLog.java @@ -0,0 +1,77 @@ +package cn.xluobo.business.sc.student.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 账户变更日志 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_student_account_log") +public class ScStudentAccountLog implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "account_log_id", type = IdType.ASSIGN_ID) + private String accountLogId; + + /** + * 账户id + */ + @TableField("account_id") + private String accountId; + + /** + * 学生 + */ + @TableField("student_id") + private Long studentId; + + /** + * 1储值 2消费 + */ + @TableField("log_type") + private String logType; + + /** + * 变更金额 + */ + @TableField("change_fee") + private BigDecimal changeFee; + + /** + * 变更时间 + */ + @TableField("change_time") + private Date changeTime; + + /** + * 变更备注 + */ + @TableField("change_memo") + private String changeMemo; + + /** + * 变更人 + */ + @TableField("last_update_user") + private String lastUpdateUser; + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentContact.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentContact.java new file mode 100644 index 0000000..98957b3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentContact.java @@ -0,0 +1,71 @@ +package cn.xluobo.business.sc.student.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 联系人 + *

+ * + * @author zhangby + * @since 2020-09-27 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_student_contact") +public class ScStudentContact implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 联系人编号 + */ + @TableId(value = "contact_id", type = IdType.ASSIGN_ID) + private Long contactId; + + /** + * 学生 + */ + @TableField("student_id") + private Long studentId; + + /** + * 联系人称呼 + */ + @TableField("contact_nick") + private String contactNick; + + /** + * 与学生关系 + */ + @TableField("contact_relation") + private String contactRelation; + + /** + * 联系电话 + */ + @TableField("contact_phone") + private String contactPhone; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentCourse.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentCourse.java new file mode 100644 index 0000000..bfd4cfe --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentCourse.java @@ -0,0 +1,134 @@ +package cn.xluobo.business.sc.student.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 学生课程 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_student_course") +public class ScStudentCourse implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(value = "student_course_id", type = IdType.ASSIGN_ID) + private Long studentCourseId; + + /** + * 学生 + */ + @TableField("student_id") + private Long studentId; + + /** + * 课程 + */ + @TableField("course_id") + private Long courseId; + + /** + * 课程 + */ + @TableField("course_name") + private String courseName; + + /** + * 报读校区 + */ + @TableField("dept_id") + private Long deptId; + + /** + * 班级 + */ + @TableField("cla_id") + private Long claId; + + /** + * 班级 + */ + @TableField("cla_name") + private String claName; + + /** + * 收费模式 hour:课时 date:时间 cycle:期 + */ + @TableField("charge_type") + private String chargeType; + + /** + * 总天数 + */ + @TableField("total_day") + private BigDecimal totalDay; + + /** + * 总课时 + */ + @TableField("total_hour") + private BigDecimal totalHour; + + /** + * 剩余课时 + */ + @TableField("balance_hour") + private BigDecimal balanceHour; + + /** + * 总学费 + */ + @TableField("total_fee") + private BigDecimal totalFee; + + /** + * 状态 1在读 2停课 + */ + @TableField("status") + private String status; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentCourseOrder.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentCourseOrder.java new file mode 100644 index 0000000..d1ec09e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/repo/model/ScStudentCourseOrder.java @@ -0,0 +1,133 @@ +package cn.xluobo.business.sc.student.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 学生课程关联订单 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Data +@Builder +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sc_student_course_order") +public class ScStudentCourseOrder implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(value = "course_order_id", type = IdType.ASSIGN_ID) + private Long courseOrderId; + + @TableField("student_course_id") + private Long studentCourseId; + + /** + * 订单 + */ + @TableField("order_id") + private Long orderId; + + /** + * 购买课程订单 + */ + @TableField("order_detail_id") + private Long orderDetailId; + + /** + * 购买课时数量 + */ + @TableField("total_hour") + private BigDecimal totalHour; + + /** + * 剩余课时数量 + */ + @TableField("balance_hour") + private BigDecimal balanceHour; + + /** + * 购买天数 + */ + @TableField("total_day") + private BigDecimal totalDay; + + /** + * 开始时间 按时间收费 + */ + @TableField("begin_date") + private String beginDate; + + /** + * 结束时间 按时间收费 + */ + @TableField("end_date") + private String endDate; + + /** + * 失效时间 + */ + @TableField("expire_date") + private String expireDate; + + /** + * 总金额 + */ + @TableField("total_fee") + private BigDecimal totalFee; + + /** + * 单价 + */ + @TableField("unit_fee") + private BigDecimal unitFee; + + /** + * 是否有效 1有效 0失效 + */ + @TableField("valid") + private Boolean valid; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentAccountService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentAccountService.java new file mode 100644 index 0000000..bee23be --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentAccountService.java @@ -0,0 +1,34 @@ +package cn.xluobo.business.sc.student.service; + +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/9/2 14:04 + */ +@Service +@Transactional +public class BusinessScStudentAccountService { + + @Autowired + private IScStudentAccountService accountService; + + /** + * 学生账户信息 + * + * @param studentId + * @return + */ + public APIResponse studentAccountBalance(Long studentId) { + if (null == studentId) { + return APIResponse.toAPIResponse(BigDecimal.ZERO); + } + BigDecimal accountBalance = accountService.selectStudentAccountBalance(studentId); + return APIResponse.toAPIResponse(accountBalance); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentCourseService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentCourseService.java new file mode 100644 index 0000000..e9ab08e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentCourseService.java @@ -0,0 +1,578 @@ +package cn.xluobo.business.sc.student.service; + +import cn.xluobo.business.sc.base.repo.model.ScRoom; +import cn.xluobo.business.sc.base.service.IScRoomService; +import cn.xluobo.business.sc.course.enums.CourseChargeTypeEnum; +import cn.xluobo.business.sc.course.repo.enums.ClaTimeAttendStatusEnums; +import cn.xluobo.business.sc.course.repo.enums.ClaTimeSourceEnums; +import cn.xluobo.business.sc.course.repo.enums.ClaTimeStatusEnums; +import cn.xluobo.business.sc.course.repo.model.ScClaTime; +import cn.xluobo.business.sc.course.repo.model.ScClaTimeAttend; +import cn.xluobo.business.sc.course.repo.model.ScCourse; +import cn.xluobo.business.sc.course.repo.model.ScCourseCla; +import cn.xluobo.business.sc.course.service.IScClaTimeAttendService; +import cn.xluobo.business.sc.course.service.IScClaTimeService; +import cn.xluobo.business.sc.course.service.IScCourseClaService; +import cn.xluobo.business.sc.course.service.IScCourseService; +import cn.xluobo.business.sc.log.enums.LogTypeEnum; +import cn.xluobo.business.sc.log.repo.model.ScStudentCourseLog; +import cn.xluobo.business.sc.log.service.IScStudentCourseLogService; +import cn.xluobo.business.sc.student.domain.req.*; +import cn.xluobo.business.sc.student.domain.resp.RespBusinessStudentCourseInfo; +import cn.xluobo.business.sc.student.domain.resp.RespCourseClaStudent; +import cn.xluobo.business.sc.student.domain.resp.RespStuCourseSignUpStudent; +import cn.xluobo.business.sc.student.domain.resp.RespStudentCourse; +import cn.xluobo.business.sc.student.enums.StudentCourseStatusEnum; +import cn.xluobo.business.sc.student.repo.mapper.ScStudentCourseMapper; +import cn.xluobo.business.sc.student.repo.model.ScStudent; +import cn.xluobo.business.sc.student.repo.model.ScStudentContact; +import cn.xluobo.business.sc.student.repo.model.ScStudentCourse; +import cn.xluobo.business.sc.student.repo.model.ScStudentCourseOrder; +import cn.xluobo.business.sys.admin.service.ISysDeptService; +import cn.xluobo.business.sys.staff.repo.model.SysStaff; +import cn.xluobo.business.sys.staff.service.ISysStaffService; +import cn.xluobo.config.exception.BusinessException; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.google.common.collect.Lists; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/9/2 15:06 + */ +@Service +@Transactional +public class BusinessScStudentCourseService { + + @Autowired + private ScStudentCourseMapper studentCourseMapper; + @Autowired + private IScStudentService studentService; + @Autowired + private IScStudentContactService contactService; + @Autowired + private IScCourseClaService claService; + @Autowired + private IScCourseService courseService; + @Autowired + private IScStudentCourseService studentCourseService; + @Autowired + private IScClaTimeService claTimeService; + @Autowired + private ISysDeptService deptService; + @Autowired + private IScRoomService roomService; + @Autowired + private IScClaTimeAttendService attendService; + @Autowired + private ISysStaffService staffService; + @Autowired + private IScStudentCourseOrderService courseOrderService; + @Autowired + private IScStudentCourseLogService scStudentCourseLogService; + + /** + * 学生课程信息 + * + * @param studentId + * @return + */ + public APIResponse studentCourseInfo(Long studentId) { + if (null == studentId) { + return APIResponse.toExceptionResponse(ApiResEnums.PARAM_FAIL); + } + ScStudent student = studentService.getById(studentId); + // 联系人信息 + List contactList = contactService.getStudentContactList(studentId); + List contactPhoneList = contactList.stream().map(item -> item.getContactPhone() + "(" + item.getContactNick() + ")").collect(Collectors.toList()); + // 报读课程 + List courseNameList = studentCourseMapper.selectStudentCourseNameList(studentId); + // 报读校区 + List deptNameList = studentCourseMapper.selectStudentDeptNameList(studentId); + RespBusinessStudentCourseInfo studentCourseInfo = RespBusinessStudentCourseInfo.builder() + .contactPhone(student.getPhone()) + .contactPhoneDetail(String.join(",", contactPhoneList)) + .courseNames(String.join(",", courseNameList)) + .deptNames(String.join(",", deptNameList)) + .build(); + return APIResponse.toAPIResponse(studentCourseInfo); + } + + /** + * 课程、班级 学生列表 + * + * @param reqSearchStudentCourseCla + * @return + */ + public RespPage searchCourseClaStudent(ReqSearchStudentCourseCla reqSearchStudentCourseCla) { + RespPage page = new RespPage<>(reqSearchStudentCourseCla.getPageNum(), reqSearchStudentCourseCla.getPageSize()); + List claStudentList = studentCourseMapper.selectStudentList(reqSearchStudentCourseCla, page); + page.setRows(claStudentList); + return page; + } + + /** + * 已报名未选择班级 选择班级 + * + * @param studentCourseChooseCla + * @return + */ + public APIResponse studentCourseChooseCla(ReqStudentCourseChooseCla studentCourseChooseCla) { + if (!studentCourseChooseCla.checkParam()) { + return APIResponse.toExceptionResponse(ApiResEnums.PARAM_FAIL); + } + Long courseId = studentCourseChooseCla.getCourseId(); + Long claId = studentCourseChooseCla.getClaId(); + Long[] studentCourseIds = studentCourseChooseCla.getChooseStudentCourseIds(); + if (null == studentCourseIds || studentCourseIds.length == 0) { + return APIResponse.toExceptionResponse("未选择学生,请稍后重试"); + } + ScCourseCla courseCla = claService.getById(claId); + if (null == courseCla) { + return APIResponse.toExceptionResponse("无法获取班级,请稍后重试"); + } + + // 更新 + UpdateWrapper uw = new UpdateWrapper<>(); + uw.set("cla_id", claId); + uw.set("cla_name", courseCla.getClaName()); + + uw.in("student_course_id", studentCourseIds); + uw.isNull("cla_id"); + uw.eq("course_id", courseId); + studentCourseService.update(uw); + + + // 日志 + LoginUser loginUser = SecurityUtils.getLoginUser(); + SysDept sysDept = deptService.getById(courseCla.getDepartId()); + + List courseLogList = Lists.newArrayList(); + for (Long studentCourseId : studentCourseIds) { + ScStudentCourse studentCourse = studentCourseService.getById(studentCourseId); + ScStudentCourseLog studentCourseLog = ScStudentCourseLog.builder() + .studentId(studentCourse.getStudentId()) + .logType(LogTypeEnum.IN_CLA.getLogType()) + .courseId(studentCourse.getCourseId()) + .courseName(studentCourse.getCourseName()) + .claId(courseCla.getClaId()) + .claName(courseCla.getClaName()) + .deptName(sysDept.getDeptName()) + .memo("进入班级,进入班级'" + studentCourse.getClaName() + "'") + .createUser(loginUser.getUserId()) + .createUserName(loginUser.getUsername()) + .build(); + courseLogList.add(studentCourseLog); + } + scStudentCourseLogService.saveBatch(courseLogList); + + return APIResponse.toOkResponse(); + } + + /** + * 记上课 + * + * @param reqClaTimeAttend + * @return + */ + public APIResponse claTimeAttend(ReqClaTimeAttend reqClaTimeAttend) { + APIResponse checkParam = reqClaTimeAttend.checkParam(); + if (!checkParam.isSuccess()) { + return checkParam; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + String attendType = reqClaTimeAttend.getAttendType(); + String startTime = reqClaTimeAttend.getStartTime(); + String endTime = reqClaTimeAttend.getEndTime(); + Long teacherId = reqClaTimeAttend.getTeacherId(); + Long courseTimeId = reqClaTimeAttend.getCourseTimeId(); + Long claId = reqClaTimeAttend.getClaId(); + ScCourseCla dbCla = claService.getById(claId); + if (null == dbCla) { + return APIResponse.toExceptionResponse("无法获取班级信息,请稍后重试"); + } + Long courseId = dbCla.getCourseId(); + ScCourse scCourse = courseService.getById(courseId); + if (null == scCourse) { + return APIResponse.toExceptionResponse("无法获取班级信息,请稍后重试"); + } + + Long departId = dbCla.getDepartId(); + SysDept sysDept = deptService.getById(departId); + if (null == sysDept) { + return APIResponse.toExceptionResponse("无法获取校区信息,请稍后重试"); + } + + List studentAttendList = reqClaTimeAttend.getStudentAttendList(); + + // 总消耗课时金额 + BigDecimal totalPayFee = BigDecimal.ZERO; + // 可课时消耗 + BigDecimal totalPayHour = BigDecimal.ZERO; + // 实到人数 + Long realAttendCnt = studentAttendList.stream().filter(item -> item.getAttendStatus().equals(ClaTimeAttendStatusEnums.AT_CLASS.getAttendStatus())).count(); + // 请假人数 + Long leaveCnt = studentAttendList.stream().filter(item -> item.getAttendStatus().equals(ClaTimeAttendStatusEnums.LEAVE_CLASS.getAttendStatus())).count(); + // 旷课人数 + Long outCnt = studentAttendList.stream().filter(item -> item.getAttendStatus().equals(ClaTimeAttendStatusEnums.OUT_CLASS.getAttendStatus())).count(); + // 应到人数 + int needAttendCnt = studentCourseMapper.selectClaNeedAttendCnt(dbCla.getClaId()); + + + if ("rule".equals(attendType)) { + // 排课记上课 + + ScClaTime claTime = claTimeService.getById(courseTimeId); + if (!ClaTimeStatusEnums.WAIT_CLASS.getStatus().equals(claTime.getStatus())) { + return APIResponse.toExceptionResponse("选择计划上课日期,非待上课状态,无法重复上课!"); + } + teacherId = claTime.getTeacherId(); + // 变更状态为已上课 + ScClaTime updateClaTime = new ScClaTime(); + updateClaTime.setCourseTimeId(courseTimeId); + updateClaTime.setRealClaDate(claTime.getClaDate()); + updateClaTime.setRealStartTime(startTime); + updateClaTime.setRealEndTime(endTime); + updateClaTime.setStatus(ClaTimeStatusEnums.HAD_CLASS.getStatus()); + updateClaTime.setNeedAttendCnt(needAttendCnt); + updateClaTime.setRealAttendCnt(realAttendCnt.intValue()); + updateClaTime.setMemo(reqClaTimeAttend.getMemo()); + updateClaTime.setLastUpdateUser(loginUser.getUserId()); + updateClaTime.setLastUpdateTime(new Date()); + claTimeService.updateById(updateClaTime); + } else if ("change".equals(attendType)) { + // 变更上课记录 + + ScClaTime claTime = claTimeService.getById(courseTimeId); + if (!ClaTimeStatusEnums.WAIT_CLASS.getStatus().equals(claTime.getStatus())) { + return APIResponse.toExceptionResponse("选择计划上课日期,非待上课状态,无法重复上课!"); + } + // 变更状态为已上课 + ScClaTime updateClaTime = new ScClaTime(); + updateClaTime.setCourseTimeId(courseTimeId); + updateClaTime.setRealClaDate(reqClaTimeAttend.getClaDate()); + updateClaTime.setTeacherId(reqClaTimeAttend.getTeacherId()); + updateClaTime.setClassTheme(reqClaTimeAttend.getClassTheme()); + updateClaTime.setRealStartTime(startTime); + updateClaTime.setRealEndTime(endTime); + updateClaTime.setStatus(ClaTimeStatusEnums.HAD_CLASS.getStatus()); + updateClaTime.setNeedAttendCnt(needAttendCnt); + updateClaTime.setRealAttendCnt(realAttendCnt.intValue()); + updateClaTime.setMemo(reqClaTimeAttend.getMemo()); + updateClaTime.setLastUpdateUser(loginUser.getUserId()); + updateClaTime.setLastUpdateTime(new Date()); + claTimeService.updateById(updateClaTime); + } else if ("custom".equals(attendType)) { + // 记录自定义上课信息 + + ScClaTime addClaTime = new ScClaTime(); + addClaTime.setClaId(reqClaTimeAttend.getClaId()); + addClaTime.setClaDate(reqClaTimeAttend.getClaDate()); + addClaTime.setTeacherId(reqClaTimeAttend.getTeacherId()); + addClaTime.setClassTheme(reqClaTimeAttend.getClassTheme()); + addClaTime.setStartTime(reqClaTimeAttend.getStartTime()); + addClaTime.setEndTime(reqClaTimeAttend.getEndTime()); + addClaTime.setRealClaDate(reqClaTimeAttend.getClaDate()); + addClaTime.setRealStartTime(reqClaTimeAttend.getStartTime()); + addClaTime.setRealEndTime(reqClaTimeAttend.getEndTime()); + addClaTime.setSource(ClaTimeSourceEnums.UN_PLAN_CLA_TIME.getSource()); + addClaTime.setStatus(ClaTimeStatusEnums.HAD_CLASS.getStatus()); + addClaTime.setPayHour(dbCla.getEveryStuLoseHour()); + addClaTime.setNeedAttendCnt(needAttendCnt); + addClaTime.setRealAttendCnt(realAttendCnt.intValue()); + addClaTime.setMemo(reqClaTimeAttend.getMemo()); + addClaTime.setCreateUser(loginUser.getUserId()); + addClaTime.setCreateTime(new Date()); + addClaTime.setLastUpdateUser(loginUser.getUserId()); + addClaTime.setLastUpdateTime(new Date()); + + // 教室不为空 设置教室 + if (null != reqClaTimeAttend.getRoomId()) { + ScRoom room = roomService.getById(reqClaTimeAttend.getRoomId()); + addClaTime.setRoomId(reqClaTimeAttend.getRoomId()); + addClaTime.setRoomName(room.getRoomName()); + } + + claTimeService.save(addClaTime); + courseTimeId = addClaTime.getCourseTimeId(); + } + + // 教师信息 + SysStaff sysStaff = staffService.getById(teacherId); + + // 保存上课记录 + List saveAttendList = Lists.newArrayList(); + // 保存学生日志 + List studentCourseLogList = Lists.newArrayList(); + + for (ReqClaTimeAttendItem attendItem : studentAttendList) { + Long studentCourseId = attendItem.getStudentCourseId(); + String attendStatus = attendItem.getAttendStatus(); + String memo = attendItem.getMemo(); + BigDecimal stuLoseHour = attendItem.getStuLoseHour(); + + // 如果是请假,消耗课时0 + if (ClaTimeAttendStatusEnums.LEAVE_CLASS.getAttendStatus().equals(attendStatus)) { + stuLoseHour = BigDecimal.ZERO; + } + + // 获取学生报读班级信息 + ScStudentCourse studentCourse = studentCourseService.getById(studentCourseId); + String studentDbChargeType = studentCourse.getChargeType(); + + // 消耗金额 + BigDecimal payFee; + // 上课后剩余课时 + BigDecimal changeAfterBalanceHour = null; + // 本次上课对应的订单 + Long courseOrderId = null; + + if (CourseChargeTypeEnum.DATE.getChargeType().equals(studentDbChargeType)) { + // 按时间上课,不扣减课时 + + // 获取 消耗金额 + ScStudentCourseOrder courseOrder = courseOrderService.getNowValidDateOrder(studentCourseId); + payFee = courseOrder.getUnitFee(); + courseOrderId = courseOrder.getCourseOrderId(); + + } else { + // 本次上课对应的订单 + ScStudentCourseOrder courseOrder = courseOrderService.getSubtractHourOrder(studentCourseId); + if (null == courseOrder) { + throw new BusinessException("无法获取对应课时订单,无法扣减课时,id=" + studentCourseId); + } + courseOrderId = courseOrder.getCourseOrderId(); + + BigDecimal balanceHour = studentCourse.getBalanceHour(); + balanceHour = balanceHour.subtract(stuLoseHour); + + changeAfterBalanceHour = balanceHour; + + // 课时不足 不允许上课 + if (balanceHour.compareTo(BigDecimal.ZERO) < 0) { + throw new BusinessException("学员课时不足,不允许上课!"); + } + + // 更新剩余课时 cas + UpdateWrapper uwStudentCourse = new UpdateWrapper<>(); + uwStudentCourse + .eq("student_course_id", studentCourseId) + .eq("balance_hour", studentCourse.getBalanceHour()) + .set("balance_hour", balanceHour) + .set("last_update_user", loginUser.getUserId()) + .set("last_update_time", new Date()); + boolean update = studentCourseService.update(uwStudentCourse); + if (!update) { + throw new BusinessException("学员课时余额扣减失败,请重试!"); + } + + // 订单扣减课时,获取 消耗金额 + payFee = courseOrderService.subtractCourseOrderBalanceHour(studentCourseId, stuLoseHour); + } + + // 消耗总金额 + totalPayFee = totalPayFee.add(payFee); + + // 每个上课记录 + ScClaTimeAttend addClaTimeAttend = new ScClaTimeAttend(); + addClaTimeAttend.setStudentCourseId(studentCourseId); + addClaTimeAttend.setCourseOrderId(courseOrderId); + addClaTimeAttend.setCourseTimeId(courseTimeId); + addClaTimeAttend.setStudentId(studentCourse.getStudentId()); + addClaTimeAttend.setClaId(studentCourse.getClaId()); + addClaTimeAttend.setCourseId(studentCourse.getCourseId()); + addClaTimeAttend.setTeacherId(teacherId); + addClaTimeAttend.setTeacherName(sysStaff.getStaffName()); + addClaTimeAttend.setChargeType(studentDbChargeType); + if (CourseChargeTypeEnum.DATE.getChargeType().equals(studentDbChargeType)) { + addClaTimeAttend.setTeacherGetHour(null); + addClaTimeAttend.setPayHour(null); + } else { + addClaTimeAttend.setTeacherGetHour(stuLoseHour); + addClaTimeAttend.setPayHour(stuLoseHour); + totalPayHour = totalPayHour.add(stuLoseHour); + } + addClaTimeAttend.setAttendStatus(attendStatus); + addClaTimeAttend.setMemo(memo); + addClaTimeAttend.setCreateUser(loginUser.getUserId()); + addClaTimeAttend.setPayFee(payFee); + saveAttendList.add(addClaTimeAttend); + + // 上课日志 + StringBuffer sb = new StringBuffer(""); + sb.append("上课[").append(ClaTimeAttendStatusEnums.getNameByStatus(attendStatus)).append("],上课时间").append(reqClaTimeAttend.getClaDate()).append(" ") + .append(reqClaTimeAttend.getStartTime()).append("~").append(reqClaTimeAttend.getEndTime()).append(","); + ScStudentCourseLog studentCourseLog = ScStudentCourseLog.builder() + .studentId(studentCourse.getStudentId()) + .logType(LogTypeEnum.ATTEND_CLA.getLogType()) + .courseId(scCourse.getCourseId()) + .courseName(scCourse.getCourseName()) + .claId(dbCla.getClaId()) + .claName(dbCla.getClaName()) + .deptName(sysDept.getDeptName()) + .changeFee(payFee.negate()) + .createUser(loginUser.getUserId()) + .createUserName(loginUser.getUsername()) + .createTime(new Date()) + .build(); + if (!CourseChargeTypeEnum.DATE.getChargeType().equals(studentDbChargeType)) { + studentCourseLog.setChangeHour(stuLoseHour.negate()); + studentCourseLog.setAfterBalanceHour(changeAfterBalanceHour); + sb.append("扣减").append(stuLoseHour.toString()).append("课时,"); + sb.append("消耗").append(payFee).append("元."); + } + studentCourseLog.setMemo(sb.toString()); + studentCourseLogList.add(studentCourseLog); + } + // 保存上课记录 + attendService.saveBatch(saveAttendList); + // 保存学生日志 + scStudentCourseLogService.saveBatch(studentCourseLogList); + + // 更新上课总课时 人数信息 + ScClaTime updateClaTime = new ScClaTime(); + updateClaTime.setCourseTimeId(courseTimeId); + updateClaTime.setPayTotalHour(totalPayHour); + updateClaTime.setPayTotalFee(totalPayFee); + updateClaTime.setAtClassCnt(realAttendCnt.intValue()); + updateClaTime.setLeaveCnt(leaveCnt.intValue()); + updateClaTime.setOutCnt(outCnt.intValue()); + claTimeService.updateById(updateClaTime); + + return APIResponse.toOkResponse(); + } + + /** + * 停课 + * + * @param studentCourseId + * @return + */ + public APIResponse stopStudentCourseStatus(Long studentCourseId) { + if (null == studentCourseId) { + return APIResponse.toExceptionResponse(ApiResEnums.PARAM_FAIL); + } + ScStudentCourse studentCourse = studentCourseService.getById(studentCourseId); + if (null == studentCourse) { + return APIResponse.toExceptionResponse("无法获取停课信息,请稍后重试!"); + } + if (StudentCourseStatusEnum.STOP_CLA.getStudentCourseStatus().equals(studentCourse.getStatus())) { + return APIResponse.toExceptionResponse("当前状态为停课,无需停课!"); + } + ScStudentCourse update = new ScStudentCourse(); + update.setStudentCourseId(studentCourseId); + update.setStatus(StudentCourseStatusEnum.STOP_CLA.getStudentCourseStatus()); + studentCourseService.updateById(update); + return APIResponse.toOkResponse(); + } + + /** + * 在读 + * + * @param studentCourseId + * @return + */ + public APIResponse atClaStudentCourseStatus(Long studentCourseId) { + if (null == studentCourseId) { + return APIResponse.toExceptionResponse(ApiResEnums.PARAM_FAIL); + } + ScStudentCourse studentCourse = studentCourseService.getById(studentCourseId); + if (null == studentCourse) { + return APIResponse.toExceptionResponse("无法获取课程信息,请稍后重试!"); + } + if (StudentCourseStatusEnum.AT_CLA.getStudentCourseStatus().equals(studentCourse.getStatus())) { + return APIResponse.toExceptionResponse("当前状态为在读,无需变更!"); + } + ScStudentCourse update = new ScStudentCourse(); + update.setStudentCourseId(studentCourseId); + update.setStatus(StudentCourseStatusEnum.AT_CLA.getStudentCourseStatus()); + studentCourseService.updateById(update); + return APIResponse.toOkResponse(); + } + + /** + * 学生报读课程 + * + * @return + */ + public List searchStudentCourse(ReqSearchStudentCourse reqSearchStudentCourse) { + return studentCourseMapper.selectStudentCourseList(reqSearchStudentCourse); + } + + + /** + * 报读列表 + * + * @param reqSearchStuCourseSignUp + * @return + */ + public RespPage searchStuCourseSignUpList(ReqSearchStuCourseSignUp reqSearchStuCourseSignUp) { + RespPage page = new RespPage<>(reqSearchStuCourseSignUp.getPageNum(), reqSearchStuCourseSignUp.getPageSize()); + List signUpStudents = studentCourseMapper.selectStudentSignUpList(reqSearchStuCourseSignUp, page); + page.setRows(signUpStudents); + return page; + } + + /** + * 报读信息中 将学员从班级中移除 + * + * @param studentCourseId + * @return + */ + public APIResponse removeStuFromCla(Long studentCourseId) { + if (null == studentCourseId) { + return APIResponse.toExceptionResponse(ApiResEnums.PARAM_FAIL); + } + ScStudentCourse studentCourse = studentCourseService.getById(studentCourseId); + if (null == studentCourse) { + return APIResponse.toExceptionResponse("无法获取班级学员信息,请稍后重试"); + } + Long claId = studentCourse.getClaId(); + if (null == claId) { + return APIResponse.toExceptionResponse("未报读班级,无需移除"); + } + + LoginUser loginUser = SecurityUtils.getLoginUser(); + SysDept sysDept = deptService.getById(studentCourse.getDeptId()); + + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("student_course_id", studentCourse.getStudentCourseId()); + uw.isNotNull("cla_id"); + uw.set("cla_id", null); + uw.set("cla_name", null); + uw.set("last_update_user", loginUser.getUserId()); + uw.set("last_update_time", new Date()); + boolean update = studentCourseService.update(uw); + if (!update) { + return APIResponse.toExceptionResponse("从班级中移除失败,请稍后重试"); + } + + // 日志 + ScStudentCourseLog studentCourseLog = ScStudentCourseLog.builder() + .studentId(studentCourse.getStudentId()) + .logType(LogTypeEnum.OUT_CLA.getLogType()) + .courseId(studentCourse.getCourseId()) + .courseName(studentCourse.getCourseName()) + .deptName(sysDept.getDeptName()) + .memo("退出班级,从'" + studentCourse.getClaName() + "'班级删除") + .createUser(loginUser.getUserId()) + .createUserName(loginUser.getUsername()) + .build(); + scStudentCourseLogService.save(studentCourseLog); + + return APIResponse.toOkResponse(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentService.java new file mode 100644 index 0000000..b9fd89a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentService.java @@ -0,0 +1,222 @@ +package cn.xluobo.business.sc.student.service; + +import cn.xluobo.business.sc.base.repo.model.ScSchool; +import cn.xluobo.business.sc.base.service.IScSchoolService; +import cn.xluobo.business.sc.student.domain.req.ReqSearchScStudent; +import cn.xluobo.business.sc.student.domain.req.ReqStudentSelect; +import cn.xluobo.business.sc.student.domain.resp.RespSearchStudent; +import cn.xluobo.business.sc.student.repo.mapper.ScStudentMapper; +import cn.xluobo.business.sc.student.repo.model.ScStudent; +import cn.xluobo.business.sc.student.repo.model.ScStudentAccount; +import cn.xluobo.business.sc.student.repo.model.ScStudentContact; +import cn.xluobo.business.sc.student.repo.model.ScStudentCourse; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessScStudentService { + + @Autowired + private IScStudentService scStudentService; + + @Autowired + private IScStudentContactService contactService; + + @Autowired + private ScStudentMapper studentMapper; + @Autowired + private IScSchoolService schoolService; + @Autowired + private IScStudentCourseService studentCourseService; + @Autowired + private IScStudentAccountService accountService; + + /** + * 查询 + * + * @param reqSearchScStudent + * @return + */ + public APIResponse searchList(ReqSearchScStudent reqSearchScStudent) { + RespPage page = new RespPage(reqSearchScStudent.getPageNum(), reqSearchScStudent.getPageSize()); + List respSearchStudents = studentMapper.selectForSearchTable(reqSearchScStudent, page); + page.setRows(respSearchStudents); + return APIResponse.toAPIResponse(page); + } + + /** + * 前端select + * + * @return + */ + public APIResponse select(ReqStudentSelect studentSelect) { + RespPage page = new RespPage(studentSelect.getPageNum(), studentSelect.getPageSize()); + List list = scStudentService.selectStudentSelect(studentSelect, page); + return APIResponse.toAPIResponse(list); + } + + /** + * 详情 + * + * @param studentId + * @return + */ + public APIResponse detailById(Long studentId) { + if (null == studentId) { + return APIResponse.toAPIResponse(null); + } + ScStudent detailInfo = scStudentService.getById(studentId); + + // 联系人信息 + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("student_id", studentId); + List contactList = contactService.list(qw); + detailInfo.setContactList(contactList); + + // 学校名称 + if (null != detailInfo.getSchoolId()) { + ScSchool scSchool = schoolService.getById(detailInfo.getSchoolId()); + detailInfo.setSchoolName(scSchool.getSchoolName()); + } + + return APIResponse.toAPIResponse(detailInfo); + } + + /** + * 添加 + * + * @param scStudent + * @return + */ + public APIResponse addScStudent(ScStudent scStudent) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + + if (StringUtils.isNotEmpty(scStudent.getSchoolName())) { + Long schoolId = schoolService.getSchoolId(scStudent.getSchoolName()); + scStudent.setSchoolId(schoolId); + } + + // 保存学生信息 + List contactList = scStudent.getContactList(); + if (null != contactList && contactList.size() > 0) { + scStudent.setPhone(contactList.get(0).getContactPhone()); + } + scStudent.setCreateUser(loginUser.getUserId()); + scStudentService.save(scStudent); + + // 删除联系人信息 + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("student_id", scStudent.getStudentId()); + contactService.remove(uw); + + // 保存联系人信息 + if (null != contactList && contactList.size() > 0) { + contactList.forEach(item -> { + item.setStudentId(scStudent.getStudentId()); + item.setCreateUser(loginUser.getUserId()); + }); + contactService.saveBatch(contactList); + + scStudent.setPhone(contactList.get(0).getContactPhone()); + } + + return APIResponse.toOkResponse(); + } + + /** + * 更新 + * + * @param scStudent + * @return + */ + public APIResponse updateScStudent(ScStudent scStudent) { + if (null == scStudent.getStudentId()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + + if (StringUtils.isNotEmpty(scStudent.getSchoolName())) { + Long schoolId = schoolService.getSchoolId(scStudent.getSchoolName()); + scStudent.setSchoolId(schoolId); + } + + // 删除联系人信息 + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("student_id", scStudent.getStudentId()); + contactService.remove(uw); + + // 保存联系人信息 + List contactList = scStudent.getContactList(); + if (null != contactList && contactList.size() > 0) { + contactList.forEach(item -> { + item.setStudentId(scStudent.getStudentId()); + item.setCreateUser(loginUser.getUserId()); + }); + contactService.saveBatch(contactList); + + scStudent.setPhone(contactList.get(0).getContactPhone()); + } + + // 更新学生信息 + scStudent.setLastUpdateUser(loginUser.getUserId()); + scStudent.setLastUpdateTime(new Date()); + boolean updateScStudent = scStudentService.updateById(scStudent); + + return APIResponse.toOkResponse(); + } + + /** + * 删除 + * + * @param studentIds + * @return + */ + public APIResponse deleteById(Long[] studentIds) { + if (null == studentIds || studentIds.length == 0) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + + // 如果已报读 不允许删除 + QueryWrapper qwSc = new QueryWrapper<>(); + qwSc.in("student_id", studentIds); + int studentCourseCount = studentCourseService.count(qwSc); + if (studentCourseCount != 0) { + return APIResponse.toExceptionResponse("学生已报读课程,无法删除"); + } + + QueryWrapper qwSsa = new QueryWrapper<>(); + qwSsa.in("student_id", studentIds); + List accountList = accountService.list(qwSsa); + for (ScStudentAccount account : accountList) { + if(account.getBalanceFee().compareTo(BigDecimal.ZERO) != 0) { + return APIResponse.toExceptionResponse("学生账户尚有余额'"+account.getBalanceFee().toString()+"元',无法删除"); + } + } + + boolean deleteScStudent = scStudentService.removeByIds(Arrays.asList(studentIds)); + if (deleteScStudent) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentAccountLogService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentAccountLogService.java new file mode 100644 index 0000000..16899f1 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentAccountLogService.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sc.student.service; + +import cn.xluobo.business.sc.student.repo.model.ScStudentAccountLog; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 账户变更日志 服务类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface IScStudentAccountLogService extends IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentAccountService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentAccountService.java new file mode 100644 index 0000000..4beec36 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentAccountService.java @@ -0,0 +1,32 @@ +package cn.xluobo.business.sc.student.service; + +import cn.xluobo.business.sc.student.repo.model.ScStudentAccount; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.math.BigDecimal; + +/** + *

+ * 学生余额账户 服务类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface IScStudentAccountService extends IService { + + /** + * 学生账户余额 + * @param studentId + * @return + */ + BigDecimal selectStudentAccountBalance(Long studentId); + + /** + * 增加学生账户余额 + * @param studentId + * @param addBalance + * @param userId + */ + void addBalance(Long studentId, BigDecimal addBalance,Long userId); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentContactService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentContactService.java new file mode 100644 index 0000000..518f537 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentContactService.java @@ -0,0 +1,24 @@ +package cn.xluobo.business.sc.student.service; + +import cn.xluobo.business.sc.student.repo.model.ScStudentContact; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 联系人 服务类 + *

+ * + * @author zhangby + * @since 2020-09-27 + */ +public interface IScStudentContactService extends IService { + + /** + * 获取学生练习方式 + * @param studentId + * @return + */ + List getStudentContactList(Long studentId); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentCourseOrderService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentCourseOrderService.java new file mode 100644 index 0000000..759c255 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentCourseOrderService.java @@ -0,0 +1,70 @@ +package cn.xluobo.business.sc.student.service; + +import cn.xluobo.business.sc.student.repo.model.ScStudentCourseOrder; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.math.BigDecimal; + +/** + *

+ * 学生课程关联订单 服务类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface IScStudentCourseOrderService extends IService { + + /** + * 校验按时间收费 收费日期是否存在覆盖 + * + * @param studentId + * @param courseId + * @param beginDate + * @param endDate + * @return + */ + boolean checkDateCover(Long studentId, Long courseId, + String beginDate, String endDate); + + /** + * 获取应扣课时订单信息 + * @param studentCourseId + * @return + */ + ScStudentCourseOrder getSubtractHourOrder(Long studentCourseId); + + /** + * 当前生效 按时间 缴费订单 + * @param studentCourseId + * @return + */ + ScStudentCourseOrder getNowValidDateOrder(Long studentCourseId); + + + /** + * 课程订单扣减课时 + * @param studentCourseId + * @param loseHour + * @return 扣减总课时费用 + */ + BigDecimal subtractCourseOrderBalanceHour(Long studentCourseId, BigDecimal loseHour); + + /** + * 课程订单 恢复课时 + * 当删除上课记录时调用 + * @param studentCourseId + * @param recoverHour 恢复课时数量 + * @return + */ + void recoverOrderLoseHour(Long studentCourseId, BigDecimal recoverHour); + + /** + * 更新订单 剩余课时 + * @param courseOrderId + * @param newBalanceHour + * @param oldBalanceHour + */ + void updateBalanceHour(Long courseOrderId, BigDecimal newBalanceHour, BigDecimal oldBalanceHour); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentCourseService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentCourseService.java new file mode 100644 index 0000000..3e7b51c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentCourseService.java @@ -0,0 +1,89 @@ +package cn.xluobo.business.sc.student.service; + +import cn.xluobo.business.sc.course.repo.model.ScClaTime; +import cn.xluobo.business.sc.course.repo.model.ScClaTimeAttend; +import cn.xluobo.business.sc.student.repo.model.ScStudentCourse; +import cn.xluobo.core.api.APIBaseResponse; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.common.core.domain.model.LoginUser; + +import java.util.Map; + +/** + *

+ * 学生课程 服务类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +public interface IScStudentCourseService extends IService { + + /** + * 校验学生是否可报读课程 + * + * @param studentId + * @param courseIds + * @param deptId + * @return + */ + APIBaseResponse checkStudentCanSignUpCourse(Long studentId, Long[] courseIds, Long deptId); + + /** + * 校验学生是否可报读课程 + * + * @param studentId + * @param courseId + * @param deptId + * @param studentCourseChargeTypeMap 已报读信息 传null即可 + * @return + */ + APIBaseResponse checkStudentCanSignUpCourse(Long studentId, + Long courseId, + Long deptId, + Map studentCourseChargeTypeMap); + + /** + * 根据学生、 课程获取报读信息 + * @param studentId + * @param courseId + * @return + */ + ScStudentCourse selectByStudentIdCourseId(Long studentId, Long courseId); + + /** + * 作废订单时,当报读课程总课时、总费用 为0时,删除报读 + * @param studentCourseId + * @return + */ + int deleteWhenTotalHourZeroForInvalid(Long studentCourseId); + + /** + * 作废订单时,当报读课程总天数、总费用 为0时,删除报读 + * @param studentCourseId + * @return + */ + int deleteWhenTotalDayZeroForInvalid(Long studentCourseId); + + /** + * 即将过期人员数量 + * @return + */ + Integer getWillExpireDateCount(Integer minBalanceDay); + + /** + * 剩余课时小于 最小 数量 + * @param minBalanceHour 最小剩余课时数量 + * @return + */ + Integer getWillExpireHourCount(Integer minBalanceHour); + + /** + * 根据上课记录 恢复学员课时 + * @param claTimeAttend + * @param claTime + * @param loginUser + */ + void recoverStudentCourseHour(ScClaTimeAttend claTimeAttend, ScClaTime claTime, LoginUser loginUser); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentService.java new file mode 100644 index 0000000..71d9358 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/IScStudentService.java @@ -0,0 +1,32 @@ +package cn.xluobo.business.sc.student.service; + +import cn.xluobo.business.sc.student.domain.req.ReqStudentSelect; +import cn.xluobo.business.sc.student.domain.resp.RespSearchStudent; +import cn.xluobo.business.sc.student.repo.model.ScStudent; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +import java.util.List; + +/** + *

+ * 学生基本信息 服务类 + *

+ * + * @author zhangby + * @since 2020-04-27 07:13:40 + */ +public interface IScStudentService extends com.baomidou.mybatisplus.extension.service.IService { + + List selectStudentSelect(ReqStudentSelect studentSelect, Page page); + + Long selectIdByName(String studentName); + + /** + * 学生列表 + * @param max 最大数量 + * @return 学生姓名、学生ID + */ + RespPage selectStudentList(Integer max); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentAccountLogServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentAccountLogServiceImpl.java new file mode 100644 index 0000000..ca03d28 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentAccountLogServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.sc.student.service.impl; + +import cn.xluobo.business.sc.student.repo.mapper.ScStudentAccountLogMapper; +import cn.xluobo.business.sc.student.repo.model.ScStudentAccountLog; +import cn.xluobo.business.sc.student.service.IScStudentAccountLogService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 账户变更日志 服务实现类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Service +public class ScStudentAccountLogServiceImpl extends ServiceImpl implements IScStudentAccountLogService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentAccountServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentAccountServiceImpl.java new file mode 100644 index 0000000..c1a08cf --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentAccountServiceImpl.java @@ -0,0 +1,70 @@ +package cn.xluobo.business.sc.student.service.impl; + +import cn.xluobo.business.sc.student.repo.mapper.ScStudentAccountMapper; +import cn.xluobo.business.sc.student.repo.model.ScStudentAccount; +import cn.xluobo.business.sc.student.service.IScStudentAccountService; +import cn.xluobo.config.exception.BusinessException; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 学生余额账户 服务实现类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Service +public class ScStudentAccountServiceImpl extends ServiceImpl implements IScStudentAccountService { + + @Override + public BigDecimal selectStudentAccountBalance(Long studentId) { + QueryWrapper qw = new QueryWrapper(); + qw.eq("student_id", studentId); + ScStudentAccount studentAccount = baseMapper.selectOne(qw); + if (null == studentAccount) { + return BigDecimal.ZERO; + } else { + return studentAccount.getBalanceFee(); + } + } + + @Override + public void addBalance(Long studentId, BigDecimal addBalance, Long userId) { + if (null == studentId) { + return; + } + if (null == addBalance || addBalance.compareTo(BigDecimal.ZERO) == 0) { + return; + } + + QueryWrapper qw = new QueryWrapper(); + qw.eq("student_id", studentId); + ScStudentAccount studentAccount = this.getOne(qw); + if (null == studentAccount) { + studentAccount = new ScStudentAccount(); + studentAccount.setStudentId(studentId); + studentAccount.setBalanceFee(addBalance); + studentAccount.setCreateUser(userId); + studentAccount.setLastUpdateUser(userId); + this.save(studentAccount); + } else { + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("student_id",studentId); + uw.eq("balance_fee",studentAccount.getBalanceFee()); + uw.set("balance_fee", addBalance.add(studentAccount.getBalanceFee())); + uw.set("last_update_user", userId); + uw.set("last_update_time", new Date()); + boolean update = this.update(uw); + if(!update) { + throw new BusinessException("余额增加失败,请重试!"); + } + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentContactServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentContactServiceImpl.java new file mode 100644 index 0000000..950064c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentContactServiceImpl.java @@ -0,0 +1,31 @@ +package cn.xluobo.business.sc.student.service.impl; + +import cn.xluobo.business.sc.student.repo.mapper.ScStudentContactMapper; +import cn.xluobo.business.sc.student.repo.model.ScStudentContact; +import cn.xluobo.business.sc.student.service.IScStudentContactService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 联系人 服务实现类 + *

+ * + * @author zhangby + * @since 2020-09-27 + */ +@Service +public class ScStudentContactServiceImpl extends ServiceImpl implements IScStudentContactService { + + @Override + public List getStudentContactList(Long studentId) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("student_id", studentId); + qw.orderByAsc("create_time"); + List contacts = this.list(qw); + return contacts; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentCourseOrderServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentCourseOrderServiceImpl.java new file mode 100644 index 0000000..cb1607d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentCourseOrderServiceImpl.java @@ -0,0 +1,154 @@ +package cn.xluobo.business.sc.student.service.impl; + +import cn.xluobo.business.sc.student.repo.mapper.ScStudentCourseMapper; +import cn.xluobo.business.sc.student.repo.mapper.ScStudentCourseOrderMapper; +import cn.xluobo.business.sc.student.repo.mapper.ScStudentMapper; +import cn.xluobo.business.sc.student.repo.model.ScStudent; +import cn.xluobo.business.sc.student.repo.model.ScStudentCourse; +import cn.xluobo.business.sc.student.repo.model.ScStudentCourseOrder; +import cn.xluobo.business.sc.student.service.IScStudentCourseOrderService; +import cn.xluobo.config.exception.BusinessException; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 学生课程关联订单 服务实现类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Service +public class ScStudentCourseOrderServiceImpl extends ServiceImpl implements IScStudentCourseOrderService { + + @Autowired + private ScStudentCourseMapper studentCourseMapper; + @Autowired + private ScStudentMapper studentMapper; + + @Override + public boolean checkDateCover(Long studentId, Long courseId, String beginDate, String endDate) { + int checkDateCover = baseMapper.checkDateCover(studentId, courseId, beginDate, endDate); + if (checkDateCover == 0) { + return false; + } else { + return true; + } + } + + @Override + public ScStudentCourseOrder getSubtractHourOrder(Long studentCourseId) { + return baseMapper.selectSubtractHourOrder(studentCourseId); + } + + @Override + public ScStudentCourseOrder getNowValidDateOrder(Long studentCourseId) { + return baseMapper.selectNowValidDateOrder(studentCourseId); + } + + @Override + public BigDecimal subtractCourseOrderBalanceHour(Long studentCourseId, BigDecimal loseHour) { + List studentCourseOrderList = baseMapper.selectSubtractHourOrderList(studentCourseId); + BigDecimal payFee = BigDecimal.ZERO; + for (ScStudentCourseOrder courseOrder : studentCourseOrderList) { + if (loseHour.compareTo(BigDecimal.ZERO) == 0) { + break; + } + BigDecimal balanceHour = courseOrder.getBalanceHour(); + + // 订单剩余课时不足扣减 + if (balanceHour.compareTo(loseHour) < 0) { + payFee = payFee.add(balanceHour.multiply(courseOrder.getUnitFee())); + + // 剩余课时不足扣减, 将剩余课时扣减完毕 + int updateSubtractHour = baseMapper.updateSubtractHour(courseOrder.getCourseOrderId(), BigDecimal.ZERO, balanceHour); + if (updateSubtractHour == 0) { + throw new BusinessException("订单扣减课时失败,请重试!"); + } + + loseHour = loseHour.subtract(balanceHour); + + } else { + payFee = payFee.add(loseHour.multiply(courseOrder.getUnitFee())); + + // 直接扣减课时 + BigDecimal newHour = balanceHour.subtract(loseHour); + int updateSubtractHour = baseMapper.updateSubtractHour(courseOrder.getCourseOrderId(), newHour, balanceHour); + if (updateSubtractHour == 0) { + throw new BusinessException("订单扣减课时失败,请重试!"); + } + } + } + return payFee; + } + + @Override + public void recoverOrderLoseHour(Long studentCourseId, BigDecimal recoverHour) { + if(recoverHour.compareTo(BigDecimal.ZERO) == 0) { + return; + } + List recoverHourOrderList = baseMapper.selectRecoverHourOrderList(studentCourseId); + if (recoverHourOrderList.size() == 0) { + ScStudentCourse studentCourse = studentCourseMapper.selectById(studentCourseId); + ScStudent student = studentMapper.selectById(studentCourse.getStudentId()); + throw new BusinessException("学员:" + student.getStudentName() + ",无生效订单,无法恢复课时!"); + } + + for (int i = 0; i < recoverHourOrderList.size(); i++) { + + if(recoverHour.compareTo(BigDecimal.ZERO) == 0) { + return; + } + + // 是否为最后一条记录 + boolean lastRecord = (i == (recoverHourOrderList.size() - 1)); + ScStudentCourseOrder studentCourseOrder = recoverHourOrderList.get(i); + BigDecimal balanceHour = studentCourseOrder.getBalanceHour(); + BigDecimal totalHour = studentCourseOrder.getTotalHour(); + if(lastRecord) { + BigDecimal newBalanceHour = studentCourseOrder.getBalanceHour().add(recoverHour); + this.updateBalanceHour(studentCourseOrder.getCourseOrderId(), newBalanceHour, balanceHour); + break; + } else { + if(balanceHour.compareTo(totalHour) < 0) { + // 可恢复课时数量 + BigDecimal canRecoverHour = totalHour.subtract(balanceHour); + + if(canRecoverHour.compareTo(recoverHour) > 0) { + // 订单可恢复课时数量canRecoverHour > 需要恢复的课时数量recoverHour,直接全部恢复 + + BigDecimal newBalanceHour = studentCourseOrder.getBalanceHour().add(recoverHour); + this.updateBalanceHour(studentCourseOrder.getCourseOrderId(), newBalanceHour, balanceHour); + recoverHour = BigDecimal.ZERO; + } else { + // 订单可恢复课时数量canRecoverHour <= 需要恢复的课时数量recoverHour + + BigDecimal newBalanceHour = studentCourseOrder.getBalanceHour().add(canRecoverHour); + this.updateBalanceHour(studentCourseOrder.getCourseOrderId(), newBalanceHour, balanceHour); + + // 剩余需恢复课时 + recoverHour = recoverHour.subtract(canRecoverHour); + } + } + } + } + } + + @Override + public void updateBalanceHour(Long courseOrderId, BigDecimal newBalanceHour, BigDecimal oldBalanceHour) { + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("course_order_id", courseOrderId); + uw.eq("balance_hour", oldBalanceHour); + uw.set("balance_hour", newBalanceHour); + boolean update = this.update(uw); + if (!update) { + throw new BusinessException("订单恢复课时失败,请重试!"); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentCourseServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentCourseServiceImpl.java new file mode 100644 index 0000000..db87fe6 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentCourseServiceImpl.java @@ -0,0 +1,208 @@ +package cn.xluobo.business.sc.student.service.impl; + +import cn.xluobo.business.sc.course.enums.CourseChargeTypeEnum; +import cn.xluobo.business.sc.course.repo.mapper.ScCourseChargeMapper; +import cn.xluobo.business.sc.course.repo.mapper.ScCourseMapper; +import cn.xluobo.business.sc.course.repo.model.ScClaTime; +import cn.xluobo.business.sc.course.repo.model.ScClaTimeAttend; +import cn.xluobo.business.sc.course.repo.model.ScCourse; +import cn.xluobo.business.sc.course.repo.model.ScCourseCharge; +import cn.xluobo.business.sc.log.enums.LogTypeEnum; +import cn.xluobo.business.sc.log.repo.model.ScStudentCourseLog; +import cn.xluobo.business.sc.log.service.IScStudentCourseLogService; +import cn.xluobo.business.sc.student.repo.mapper.ScStudentCourseMapper; +import cn.xluobo.business.sc.student.repo.model.ScStudentCourse; +import cn.xluobo.business.sc.student.service.IScStudentCourseOrderService; +import cn.xluobo.business.sc.student.service.IScStudentCourseService; +import cn.xluobo.business.sys.admin.repo.mapper.ISysDeptMapper; +import cn.xluobo.config.exception.BusinessException; +import cn.xluobo.core.api.APIBaseResponse; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.model.LoginUser; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + *

+ * 学生课程 服务实现类 + *

+ * + * @author zhangby + * @since 2020-08-21 + */ +@Service +public class ScStudentCourseServiceImpl extends ServiceImpl implements IScStudentCourseService { + + @Autowired + private ScCourseChargeMapper courseChargeMapper; + @Autowired + private ScCourseMapper courseMapper; + @Autowired + private ISysDeptMapper deptMapper; + @Autowired + private IScStudentCourseOrderService courseOrderService; + @Autowired + private IScStudentCourseLogService scStudentCourseLogService; + + @Override + public APIBaseResponse checkStudentCanSignUpCourse(Long studentId, Long[] courseIds, Long deptId) { + // 学生已报名课程收费模式 + QueryWrapper qw = new QueryWrapper<>(); + qw.select("course_id", "charge_type"); + qw.eq("student_id", studentId); + List studentCourseList = this.list(qw); + Map studentCourseChargeTypeMap = studentCourseList.stream().collect(Collectors.toMap(ScStudentCourse::getCourseId, ScStudentCourse::getChargeType)); + for (Long courseId : courseIds) { + APIBaseResponse response = this.checkStudentCanSignUpCourse(studentId, courseId, deptId, studentCourseChargeTypeMap); + if(!response.isSuccess()) { + return response; + } + } + + return APIBaseResponse.success(); + } + + @Override + public APIBaseResponse checkStudentCanSignUpCourse(Long studentId, Long courseId, Long deptId,Map studentCourseChargeTypeMap) { + if (null == studentCourseChargeTypeMap) { + QueryWrapper qw = new QueryWrapper<>(); + qw.select("course_id", "charge_type"); + qw.eq("student_id", studentId); + List studentCourseList = this.list(qw); + studentCourseChargeTypeMap = studentCourseList.stream().collect(Collectors.toMap(ScStudentCourse::getCourseId, ScStudentCourse::getChargeType)); + } + ScCourse scCourse = courseMapper.selectById(courseId); + if( null == scCourse) { + return APIBaseResponse.fail("无法获取课程信息,请重试"); + } + // 已报读的 收费方式 + String studentCourseChargeType = studentCourseChargeTypeMap.get(courseId); + if("cycle".equals(studentCourseChargeType)) { + return APIBaseResponse.fail("该学生 已" + CourseChargeTypeEnum.getChargeType(studentCourseChargeType) + "报读'" + scCourse.getCourseName() + "',无法重复报读!"); + } + // 课程收费配置信息 + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("course_id", courseId); + if (StringUtils.isNotEmpty(studentCourseChargeType)) { + qw.eq("charge_type", studentCourseChargeType); + } + List courseChargeList = courseChargeMapper.selectList(qw); + + // 校验学生是否可选择课程 (是否含 已报读的 收费方式) + if (studentCourseChargeTypeMap.containsKey(courseId)) { + // 是否包含 + boolean checkHasStudentCourseChargeType = courseChargeList.stream().anyMatch(item -> item.getChargeType().equals(studentCourseChargeType)); + if (!checkHasStudentCourseChargeType) { + return APIBaseResponse.fail("该学生 已" + CourseChargeTypeEnum.getChargeType(studentCourseChargeType) + "报读'" + scCourse.getCourseName() + "',目前该课程暂无此收费模式,请核查!"); + } + } + + if (null != deptId) { + // 校验是否配置了本校区 + boolean checkChargeDept = courseChargeList.stream().anyMatch(item -> item.getDepartId().compareTo(deptId) == 0 || item.getDepartId().compareTo(-1L) == 0); + if (!checkChargeDept) { + SysDept sysDept = deptMapper.selectById(deptId); + return APIBaseResponse.fail(scCourse.getCourseName() + "(" + CourseChargeTypeEnum.getChargeType(studentCourseChargeType) + ")未在'" + sysDept.getDeptName() + "'开课"); + } + } + return APIBaseResponse.success(); + } + + @Override + public ScStudentCourse selectByStudentIdCourseId(Long studentId, Long courseId) { + QueryWrapper qw = new QueryWrapper(); + qw.eq("student_id",studentId); + qw.eq("course_id",courseId); + return this.getOne(qw); + } + + @Override + public int deleteWhenTotalHourZeroForInvalid(Long studentCourseId) { + return baseMapper.deleteWhenTotalHourZeroForInvalid(studentCourseId); + } + + @Override + public int deleteWhenTotalDayZeroForInvalid(Long studentCourseId) { + return baseMapper.deleteWhenTotalDayZeroForInvalid(studentCourseId); + } + + @Override + public Integer getWillExpireDateCount(Integer minBalanceDay) { + return baseMapper.selectWillExpireDateCount(minBalanceDay); + } + + @Override + public Integer getWillExpireHourCount(Integer minBalanceHour) { + return baseMapper.selectWillExpireHourCount(minBalanceHour); + } + + @Override + public void recoverStudentCourseHour(ScClaTimeAttend claTimeAttend, ScClaTime claTime, LoginUser loginUser) { + Long studentCourseId = claTimeAttend.getStudentCourseId(); + String chargeType = claTimeAttend.getChargeType(); + BigDecimal payHour = claTimeAttend.getPayHour(); + + // 学员日志 + StringBuffer sb = new StringBuffer(""); + sb.append("恢复课时[编辑/删除上课记录],").append("上课时间").append(claTime.getRealClaDate()).append(" ") + .append(claTime.getRealStartTime()).append("~").append(claTime.getRealEndTime()).append(","); + ScStudentCourseLog studentCourseLog = ScStudentCourseLog.builder() + .studentId(claTimeAttend.getStudentId()) + .logType(LogTypeEnum.DELETE_ATTEND_CLA.getLogType()) + .courseId(claTimeAttend.getCourseId()) + .courseName(claTime.getCourseName()) + .claId(claTimeAttend.getClaId()) + .claName(claTime.getClaName()) + .deptName(claTime.getDeptName()) + .changeHour(claTimeAttend.getPayHour()) + .changeFee(claTimeAttend.getPayFee()) + .createUser(loginUser.getUserId()) + .createUserName(loginUser.getUsername()) + .createTime(new Date()) + .build(); + + if (!CourseChargeTypeEnum.DATE.getChargeType().equals(chargeType)) { + ScStudentCourse studentCourse = this.getById(studentCourseId); + if (null == studentCourse) { + throw new BusinessException("恢复学生课时失败,无法获取学生课时信息!"); + } + // 消耗课时> 0 , 恢复课时 + if (payHour.compareTo(BigDecimal.ZERO) > 0) { + UpdateWrapper uwStudentCourse = new UpdateWrapper<>(); + uwStudentCourse + .eq("student_course_id", studentCourseId) + .eq("balance_hour", studentCourse.getBalanceHour()) + .set("balance_hour", studentCourse.getBalanceHour().add(payHour)) + .set("last_update_user", loginUser.getUserId()) + .set("last_update_time", new Date()); + boolean update = this.update(uwStudentCourse); + if (!update) { + throw new BusinessException("学员剩余课时恢复失败,请重试!"); + } + + studentCourseLog.setAfterBalanceHour(studentCourse.getBalanceHour().add(payHour)); + } else { + studentCourseLog.setAfterBalanceHour(studentCourse.getBalanceHour().add(payHour)); + } + + sb.append("恢复").append(payHour.toString()).append("课时"); + + // 恢复订单课时 + courseOrderService.recoverOrderLoseHour(studentCourse.getStudentCourseId(), payHour); + } + + studentCourseLog.setMemo(sb.toString()); + scStudentCourseLogService.save(studentCourseLog); + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentServiceImpl.java new file mode 100644 index 0000000..59e3ec6 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/impl/ScStudentServiceImpl.java @@ -0,0 +1,52 @@ +package cn.xluobo.business.sc.student.service.impl; + +import cn.xluobo.business.sc.student.domain.req.ReqStudentSelect; +import cn.xluobo.business.sc.student.domain.resp.RespSearchStudent; +import cn.xluobo.business.sc.student.repo.mapper.ScStudentMapper; +import cn.xluobo.business.sc.student.repo.model.ScStudent; +import cn.xluobo.business.sc.student.service.IScStudentService; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 学生基本信息 服务实现类 + *

+ * + * @author zhangby + * @since 2020-04-27 07:13:40 + */ +@Service +public class ScStudentServiceImpl extends ServiceImpl implements IScStudentService { + + @Override + public List selectStudentSelect(ReqStudentSelect studentSelect, Page page) { + return baseMapper.selectForSelect(studentSelect, page); + } + + @Override + public Long selectIdByName(String studentName) { + QueryWrapper qw = new QueryWrapper<>(); + qw.select("student_id"); + qw.eq("student_name", studentName); + List studentList = this.list(qw); + if (null != studentList && studentList.size() > 0) { + return studentList.get(0).getStudentId(); + } + return null; + } + + @Override + public RespPage selectStudentList(Integer max) { + QueryWrapper qw = new QueryWrapper<>(); + qw.select("student_id","student_name"); + qw.orderByDesc("create_time"); + RespPage respPage = new RespPage(1,max); + return this.page(respPage,qw); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/domain/req/ReqSearchStockCategory.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/domain/req/ReqSearchStockCategory.java new file mode 100644 index 0000000..5846f7f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/domain/req/ReqSearchStockCategory.java @@ -0,0 +1,12 @@ +package cn.xluobo.business.stock.category.domain.req; + +import cn.xluobo.business.stock.category.repo.model.StockCategory; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +public class ReqSearchStockCategory extends StockCategory implements Serializable { +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/domain/req/ReqSearchStockCategoryProperty.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/domain/req/ReqSearchStockCategoryProperty.java new file mode 100644 index 0000000..dce0cd4 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/domain/req/ReqSearchStockCategoryProperty.java @@ -0,0 +1,18 @@ +package cn.xluobo.business.stock.category.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchStockCategoryProperty extends ReqPageBase implements Serializable { + private String categoryId; + private String categoryName; + private String propertyCode; + private String propertyName; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/domain/resp/RespLazyLoadCategory.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/domain/resp/RespLazyLoadCategory.java new file mode 100644 index 0000000..903623c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/domain/resp/RespLazyLoadCategory.java @@ -0,0 +1,18 @@ +package cn.xluobo.business.stock.category.domain.resp; + +import cn.xluobo.business.stock.category.repo.model.StockCategory; +import lombok.Data; + +/** + * @author :zhangbaoyu + * @date :Created in 2021/1/14 21:53 + */ +@Data +public class RespLazyLoadCategory extends StockCategory { + + private boolean hasChildren; + + public void setHasChildren(Integer hasChildren) { + this.hasChildren = hasChildren > 0; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/enums/StockCategoryPropertyEnum.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/enums/StockCategoryPropertyEnum.java new file mode 100644 index 0000000..b6be343 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/enums/StockCategoryPropertyEnum.java @@ -0,0 +1,52 @@ +package cn.xluobo.business.stock.category.enums; + +/** + * 商品类型属性类型枚举 + * 2022/3/24 5:15 下午 + * + * @author zhangby + **/ +public enum StockCategoryPropertyEnum { + + INPUT("input"), + RADIO("radio", true), + CHECKBOX("checkbox", true), + SELECT("select", true), + + ; + + private String propertyType; + + private boolean dictPropertyType; + + StockCategoryPropertyEnum(String propertyType) { + this.propertyType = propertyType; + } + + StockCategoryPropertyEnum(String propertyType, boolean dictPropertyType) { + this.propertyType = propertyType; + this.dictPropertyType = dictPropertyType; + } + + public String getPropertyType() { + return propertyType; + } + + public boolean isDictPropertyType() { + return dictPropertyType; + } + + /** + * 是否需要查询字典 + * @param propertyType + * @return + */ + public static boolean needSearchDict(String propertyType) { + for (StockCategoryPropertyEnum value : StockCategoryPropertyEnum.values()) { + if (value.getPropertyType().equals(propertyType)) { + return value.isDictPropertyType(); + } + } + return false; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapper/StockCategoryMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapper/StockCategoryMapper.java new file mode 100644 index 0000000..7bb0330 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapper/StockCategoryMapper.java @@ -0,0 +1,25 @@ +package cn.xluobo.business.stock.category.repo.mapper; + +import cn.xluobo.business.stock.category.domain.resp.RespLazyLoadCategory; +import cn.xluobo.business.stock.category.repo.model.StockCategory; + +import java.util.List; + +/** + *

+ * 商品类型 Mapper 接口 + *

+ * + * @author zhangby + * @since 2021-01-12 08:08:51 + */ +public interface StockCategoryMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + + /** + * 获取子节点,以及是否有子节点 + * @param parentId + * @return + */ + List selectCategoryByParentId(Long parentId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapper/StockCategoryPropertyMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapper/StockCategoryPropertyMapper.java new file mode 100644 index 0000000..7b46add --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapper/StockCategoryPropertyMapper.java @@ -0,0 +1,29 @@ +package cn.xluobo.business.stock.category.repo.mapper; + +import cn.xluobo.business.stock.category.domain.req.ReqSearchStockCategoryProperty; +import cn.xluobo.business.stock.category.repo.model.StockCategoryProperty; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品类型属性配置 Mapper 接口 + *

+ * + * @author zhangby + * @since 2021-01-12 07:30:24 + */ +public interface StockCategoryPropertyMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + + /** + * 查询 + * @param reqSearchStockCategoryProperty + * @param page + * @return + */ + List selectByCondition(@Param("reqSearchStockCategoryProperty") ReqSearchStockCategoryProperty reqSearchStockCategoryProperty, + @Param("page") Page page); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapping/StockCategoryMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapping/StockCategoryMapper.xml new file mode 100644 index 0000000..9756e55 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapping/StockCategoryMapper.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapping/StockCategoryPropertyMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapping/StockCategoryPropertyMapper.xml new file mode 100644 index 0000000..89bd12e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/mapping/StockCategoryPropertyMapper.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/model/StockCategory.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/model/StockCategory.java new file mode 100644 index 0000000..3567b4d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/model/StockCategory.java @@ -0,0 +1,112 @@ +package cn.xluobo.business.stock.category.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.google.common.collect.Lists; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + *

+ * 商品类型 + *

+ * + * @author zhangby + * @since 2021-01-12 08:08:51 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("stock_category") +public class StockCategory implements Serializable { + + + /** + * 类型编码 + */ + @TableId(value = "category_id", type = IdType.ASSIGN_ID) + private Long categoryId; + + /** + * 父编码 + */ + @TableField("parent_id") + private Long parentId; + + /** + * 祖级列表 + */ + @TableField("ancestors") + private String ancestors; + + /** + * 类型名称 + */ + @TableField("category_name") + private String categoryName; + + /** + * 排序 + */ + @TableField("sort") + private Integer sort; + + + + @TableField(exist = false) + private List children; + + private static Map> subTreeMap = new HashMap<>(); + + /** + * 树转换 + * @param stockCategoryList + */ + public void converterTree(List stockCategoryList) { + subTreeMap.clear(); + for (StockCategory menu : stockCategoryList) { + List subTreeList = subTreeMap.get(menu.getParentId()); + if (null == subTreeList) { + subTreeList = new LinkedList<>(); + subTreeMap.put(menu.getParentId(),subTreeList); + } + subTreeList.add(menu); + } + + this.children = treecategory(this).getChildren(); + if(this.children.isEmpty()){ + this.children = stockCategoryList; + } + } + + /** + * 深度优先 遍历树 + * @param stockCategory + * @return + */ + private StockCategory treecategory(StockCategory stockCategory) { + Long deptId = stockCategory.getCategoryId(); + List childMenuList = subTreeMap.get(deptId); + if(null != childMenuList){ + List childList = Lists.newLinkedList(); + for (StockCategory childcategory : childMenuList) { + StockCategory child = treecategory(childcategory); + childList.add(child); + } + stockCategory.setChildren(childList); + return stockCategory; + }else{ + stockCategory.setChildren(Lists.newLinkedList()); + return stockCategory; + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/model/StockCategoryProperty.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/model/StockCategoryProperty.java new file mode 100644 index 0000000..facdab0 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/repo/model/StockCategoryProperty.java @@ -0,0 +1,81 @@ +package cn.xluobo.business.stock.category.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * 商品类型属性配置 + *

+ * + * @author zhangby + * @since 2021-01-12 07:30:24 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("stock_category_property") +public class StockCategoryProperty implements Serializable { + + + /** + * 属性id + */ + @TableId(value = "property_id", type = IdType.ASSIGN_ID) + private Long propertyId; + + /** + * 商品类型属性 + */ + @TableField("category_id") + private Long categoryId; + + /** + * 属性code + */ + @TableField("property_code") + private String propertyCode; + + /** + * 属性名称 + */ + @TableField("property_name") + private String propertyName; + + /** + * input radio checkbox select + */ + @TableField("property_type") + private String propertyType; + + /** + * 字典类型 radio checkbox select + */ + @TableField("dict_type") + private String dictType; + + /** + * 是否必填 + */ + @TableField("necessary") + private Integer necessary; + + /** + * 排序 + */ + @TableField("sort") + private Integer sort; + + /** + * 商品类型名称 + */ + @TableField(exist = false) + private String categoryName; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/IStockCategoryPropertyService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/IStockCategoryPropertyService.java new file mode 100644 index 0000000..f8aca20 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/IStockCategoryPropertyService.java @@ -0,0 +1,31 @@ +package cn.xluobo.business.stock.category.service; + +import cn.xluobo.business.stock.category.repo.model.StockCategoryProperty; + +import java.util.List; + +/** + *

+ * 商品类型属性配置 服务类 + *

+ * + * @author zhangby + * @since 2021-01-12 07:30:24 + */ +public interface IStockCategoryPropertyService extends com.baomidou.mybatisplus.extension.service.IService { + + /** + * 根据商品类型查询属性数量 + * @param categoryId + * @return + */ + Integer selectCntByCategoryId(String categoryId); + + /** + * 获取 商品类型 属性配置 + * @param categoryId + * @return + */ + List selectCategoryPropertyList(String categoryId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/IStockCategoryService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/IStockCategoryService.java new file mode 100644 index 0000000..8ca94c7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/IStockCategoryService.java @@ -0,0 +1,42 @@ +package cn.xluobo.business.stock.category.service; + +import cn.xluobo.business.stock.category.repo.model.StockCategory; + +/** + *

+ * 商品类型 服务类 + *

+ * + * @author zhangby + * @since 2021-01-12 08:08:51 + */ +public interface IStockCategoryService extends com.baomidou.mybatisplus.extension.service.IService { + /** + * 是否存在子节点 + * @param categoryId + * @return + */ + boolean hadChild(String categoryId); + + /** + * 修改子元素关系 + * @param categoryId 被修改的ID + * @param newAncestors 新的父ID集合 + * @param oldAncestors 旧的父ID集合 + */ + void updateStockCategoryChildren(String categoryId, String newAncestors, String oldAncestors); + + /** + * 根据ID 获取详情 + * @param categoryId + * @return + */ + StockCategory getCategoryInfoById(String categoryId); + + /** + * 删除缓存 + * @param categoryId + * @return + */ + boolean removeCache(String categoryId); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/impl/StockCategoryPropertyServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/impl/StockCategoryPropertyServiceImpl.java new file mode 100644 index 0000000..16291f9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/impl/StockCategoryPropertyServiceImpl.java @@ -0,0 +1,36 @@ +package cn.xluobo.business.stock.category.service.impl; + +import cn.xluobo.business.stock.category.repo.mapper.StockCategoryPropertyMapper; +import cn.xluobo.business.stock.category.repo.model.StockCategoryProperty; +import cn.xluobo.business.stock.category.service.IStockCategoryPropertyService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 商品类型属性配置 服务实现类 + *

+ * + * @author zhangby + * @since 2021-01-12 07:30:24 + */ +@Service +public class StockCategoryPropertyServiceImpl extends ServiceImpl implements IStockCategoryPropertyService { + + @Override + public Integer selectCntByCategoryId(String categoryId) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("category_id", categoryId); + return this.count(qw); + } + + @Override + public List selectCategoryPropertyList(String categoryId) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("category_id", categoryId); + return this.list(qw); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/impl/StockCategoryServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/impl/StockCategoryServiceImpl.java new file mode 100644 index 0000000..d322d34 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/category/service/impl/StockCategoryServiceImpl.java @@ -0,0 +1,65 @@ +package cn.xluobo.business.stock.category.service.impl; + +import cn.xluobo.business.stock.category.repo.mapper.StockCategoryMapper; +import cn.xluobo.business.stock.category.repo.model.StockCategory; +import cn.xluobo.business.stock.category.service.IStockCategoryService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 商品类型 服务实现类 + *

+ * + * @author zhangby + * @since 2021-01-12 08:08:51 + */ +@Service +public class StockCategoryServiceImpl extends ServiceImpl implements IStockCategoryService { + + /** + * 是否存在子节点 + * @param categoryId + * @return + */ + public boolean hadChild(String categoryId){ + QueryWrapper qw = new QueryWrapper(); + qw.eq("parent_id",categoryId); + List list = list(qw); + if(list.isEmpty()){ + return false; + }else { + return true; + } + } + + @Override + public void updateStockCategoryChildren(String categoryId, String newAncestors, String oldAncestors) { + QueryWrapper qw = new QueryWrapper(); + qw.eq("category_id",categoryId); + List childrenList = list(qw); + if(!childrenList.isEmpty()){ + for (StockCategory children : childrenList) { + children.setAncestors(children.getAncestors().replace(oldAncestors, newAncestors)); + } + updateBatchById(childrenList); + } + } + + @Override + @Cacheable(value = "STOCK_CATEGORY", key = "#categoryId", sync = true) + public StockCategory getCategoryInfoById(String categoryId) { + return this.getById(categoryId); + } + + @Override + @CacheEvict(value = "STOCK_CATEGORY", key = "#categoryId") + public boolean removeCache(String categoryId) { + return true; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/domain/req/ReqSearchStockGoods.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/domain/req/ReqSearchStockGoods.java new file mode 100644 index 0000000..d1cc2d7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/domain/req/ReqSearchStockGoods.java @@ -0,0 +1,17 @@ +package cn.xluobo.business.stock.goods.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchStockGoods extends ReqPageBase implements Serializable { + private String categoryId; + private String goodsName; + private String sale; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/domain/req/ReqSearchStockGoodsProperty.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/domain/req/ReqSearchStockGoodsProperty.java new file mode 100644 index 0000000..03144cd --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/domain/req/ReqSearchStockGoodsProperty.java @@ -0,0 +1,17 @@ +package cn.xluobo.business.stock.goods.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchStockGoodsProperty extends ReqPageBase implements Serializable { + + private String goodsId; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/domain/req/ReqSearchStockInfoChange.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/domain/req/ReqSearchStockInfoChange.java new file mode 100644 index 0000000..581aa43 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/domain/req/ReqSearchStockInfoChange.java @@ -0,0 +1,27 @@ +package cn.xluobo.business.stock.goods.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchStockInfoChange extends ReqPageBase implements Serializable { + private String changeType; + private String changeCount; + private String changeDate; + private String changeStaffId; + private String changeStaffName; + private String goodsName; + private String costPrice; + private String salePrice; + private String studentId; + private String studentName; + private String orderId; + private String orderDetailId; + private String memo; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapper/StockGoodsMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapper/StockGoodsMapper.java new file mode 100644 index 0000000..145fadf --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapper/StockGoodsMapper.java @@ -0,0 +1,29 @@ +package cn.xluobo.business.stock.goods.repo.mapper; + +import cn.xluobo.business.stock.goods.domain.req.ReqSearchStockGoods; +import cn.xluobo.business.stock.goods.repo.model.StockGoods; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 库存-商品 Mapper 接口 + *

+ * + * @author zhangby + * @since 2021-01-09 01:55:13 + */ +public interface StockGoodsMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + + /** + * 查询列表 + * @param reqSearchStockGoods + * @param page + * @return + */ + List selectByCondition(@Param("reqSearchStockGoods") ReqSearchStockGoods reqSearchStockGoods, + @Param("page") Page page); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapper/StockGoodsPropertyMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapper/StockGoodsPropertyMapper.java new file mode 100644 index 0000000..d7b4460 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapper/StockGoodsPropertyMapper.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.stock.goods.repo.mapper; + +import cn.xluobo.business.stock.goods.repo.model.StockGoodsProperty; + +/** + *

+ * 商品属性 Mapper 接口 + *

+ * + * @author zhangby + * @since 2021-01-12 07:46:39 + */ +public interface StockGoodsPropertyMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapper/StockInfoChangeMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapper/StockInfoChangeMapper.java new file mode 100644 index 0000000..4ed4929 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapper/StockInfoChangeMapper.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.stock.goods.repo.mapper; + +import cn.xluobo.business.stock.goods.repo.model.StockInfoChange; + +/** + *

+ * 库存变动 Mapper 接口 + *

+ * + * @author zhangby + * @since 2021-01-09 02:10:14 + */ +public interface StockInfoChangeMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapping/StockGoodsMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapping/StockGoodsMapper.xml new file mode 100644 index 0000000..5878462 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapping/StockGoodsMapper.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapping/StockGoodsPropertyMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapping/StockGoodsPropertyMapper.xml new file mode 100644 index 0000000..7d84850 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapping/StockGoodsPropertyMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapping/StockInfoChangeMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapping/StockInfoChangeMapper.xml new file mode 100644 index 0000000..66dee89 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/mapping/StockInfoChangeMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockGoods.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockGoods.java new file mode 100644 index 0000000..d3c80ec --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockGoods.java @@ -0,0 +1,100 @@ +package cn.xluobo.business.stock.goods.repo.model; + +import com.baomidou.mybatisplus.annotation.*; +import com.google.common.collect.Lists; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + *

+ * 库存-商品 + *

+ * + * @author zhangby + * @since 2021-01-09 01:55:13 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("stock_goods") +public class StockGoods implements Serializable { + + + /** + * 商品编号 + */ + @TableId(value = "goods_id", type = IdType.ASSIGN_ID) + private Long goodsId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 类型编码 + */ + @TableField("category_id") + private Long categoryId; + + /** + * 商品名称 + */ + @TableField("goods_name") + private String goodsName; + + /** + * 展示价格 + */ + @TableField("sale_price") + private BigDecimal salePrice; + + /** + * 销售状态 1:销售 0:下架 + */ + @TableField("sale") + private String sale; + + /** + * 删除标志(1删除 0在用) + */ + @TableField("delete_flag") + @TableLogic + private String deleteFlag; + + /** + * 创建者 + */ + @TableField("create_user") + private String createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private String lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + @TableField(exist = false) + private String categoryName; + @TableField(exist = false) + private List extendValues = Lists.newArrayList(); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockGoodsProperty.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockGoodsProperty.java new file mode 100644 index 0000000..c65ccaf --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockGoodsProperty.java @@ -0,0 +1,50 @@ +package cn.xluobo.business.stock.goods.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * 商品属性 + *

+ * + * @author zhangby + * @since 2021-01-12 07:46:39 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("stock_goods_property") +public class StockGoodsProperty implements Serializable { + + /** + * 商品编号 + */ + @TableId(value = "goods_id", type = IdType.INPUT) + private Long goodsId; + + /** + * 属性code + */ + @TableId(value = "property_code", type = IdType.INPUT) + private String propertyCode; + + /** + * 属性名称 + */ + @TableField("property_name") + private String propertyName; + + /** + * 属性值 + */ + @TableField("property_value") + private String propertyValue; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockInfoChange.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockInfoChange.java new file mode 100644 index 0000000..25ac343 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockInfoChange.java @@ -0,0 +1,143 @@ +package cn.xluobo.business.stock.goods.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 库存变动 + *

+ * + * @author zhangby + * @since 2021-01-09 02:10:14 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("stock_info_change") +public class StockInfoChange implements Serializable { + + + /** + * 库存编号 + */ + @TableId(value = "stock_change_id", type = IdType.AUTO) + private Long stockChangeId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 库存编号 + */ + @TableField("stock_id") + private Long stockId; + + /** + * 商品编号 + */ + @TableField("goods_id") + private Long goodsId; + + /** + * 校区 + */ + @TableField("dept_id") + private Long deptId; + + /** + * 1:入库 2:出库 3:转库 + */ + @TableField("change_type") + private String changeType; + + /** + * 变动数量 + */ + @TableField("change_count") + private Integer changeCount; + + /** + * 变动日期 + */ + @TableField("change_date") + private Date changeDate; + + /** + * 经办人 + */ + @TableField("change_staff_id") + private Date changeStaffId; + + /** + * 经办人 + */ + @TableField("change_staff_name") + private Date changeStaffName; + + /** + * 商品名称 + */ + @TableField("goods_name") + private String goodsName; + + /** + * 成本价格 + */ + @TableField("cost_price") + private BigDecimal costPrice; + + /** + * 销售价格 + */ + @TableField("sale_price") + private BigDecimal salePrice; + + /** + * 学生 + */ + @TableField("student_id") + private Long studentId; + + /** + * 学生 + */ + @TableField("student_name") + private String studentName; + + /** + * 订单 + */ + @TableField("order_id") + private Long orderId; + + /** + * 订单明细 + */ + @TableField("order_detail_id") + private Long orderDetailId; + + /** + * 备注 + */ + @TableField("memo") + private String memo; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/IStockGoodsPropertyService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/IStockGoodsPropertyService.java new file mode 100644 index 0000000..ed58f1a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/IStockGoodsPropertyService.java @@ -0,0 +1,24 @@ +package cn.xluobo.business.stock.goods.service; + +import cn.xluobo.business.stock.goods.repo.model.StockGoodsProperty; + +import java.util.List; + +/** + *

+ * 商品属性 服务类 + *

+ * + * @author zhangby + * @since 2021-01-12 07:46:39 + */ +public interface IStockGoodsPropertyService extends com.baomidou.mybatisplus.extension.service.IService { + + /** + * 获取商品自定义属性值 + * @param goodsId + * @return + */ + List selectPropertyListByGoodsId(String goodsId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/IStockGoodsService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/IStockGoodsService.java new file mode 100644 index 0000000..1323fca --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/IStockGoodsService.java @@ -0,0 +1,22 @@ +package cn.xluobo.business.stock.goods.service; + +import cn.xluobo.business.stock.goods.repo.model.StockGoods; + +/** + *

+ * 库存-商品 服务类 + *

+ * + * @author zhangby + * @since 2021-01-09 01:55:13 + */ +public interface IStockGoodsService extends com.baomidou.mybatisplus.extension.service.IService { + + /** + * 根据商品类型查询数量 + * @param categoryId + * @return + */ + Integer selectCntByCategoryId(String categoryId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/IStockInfoChangeService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/IStockInfoChangeService.java new file mode 100644 index 0000000..77ea9b2 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/IStockInfoChangeService.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.stock.goods.service; + +import cn.xluobo.business.stock.goods.repo.model.StockInfoChange; + +/** + *

+ * 库存变动 服务类 + *

+ * + * @author zhangby + * @since 2021-01-09 02:10:14 + */ +public interface IStockInfoChangeService extends com.baomidou.mybatisplus.extension.service.IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/impl/StockGoodsPropertyServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/impl/StockGoodsPropertyServiceImpl.java new file mode 100644 index 0000000..1e6d237 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/impl/StockGoodsPropertyServiceImpl.java @@ -0,0 +1,29 @@ +package cn.xluobo.business.stock.goods.service.impl; + +import cn.xluobo.business.stock.goods.repo.mapper.StockGoodsPropertyMapper; +import cn.xluobo.business.stock.goods.repo.model.StockGoodsProperty; +import cn.xluobo.business.stock.goods.service.IStockGoodsPropertyService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 商品属性 服务实现类 + *

+ * + * @author zhangby + * @since 2021-01-12 07:46:39 + */ +@Service +public class StockGoodsPropertyServiceImpl extends ServiceImpl implements IStockGoodsPropertyService { + + @Override + public List selectPropertyListByGoodsId(String goodsId) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("goods_id", goodsId); + return this.list(qw); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/impl/StockGoodsServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/impl/StockGoodsServiceImpl.java new file mode 100644 index 0000000..21f60db --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/impl/StockGoodsServiceImpl.java @@ -0,0 +1,27 @@ +package cn.xluobo.business.stock.goods.service.impl; + +import cn.xluobo.business.stock.goods.repo.mapper.StockGoodsMapper; +import cn.xluobo.business.stock.goods.repo.model.StockGoods; +import cn.xluobo.business.stock.goods.service.IStockGoodsService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 库存-商品 服务实现类 + *

+ * + * @author zhangby + * @since 2021-01-09 01:55:13 + */ +@Service +public class StockGoodsServiceImpl extends ServiceImpl implements IStockGoodsService { + + @Override + public Integer selectCntByCategoryId(String categoryId) { + QueryWrapper qw = new QueryWrapper(); + qw.eq("category_id",categoryId); + return this.count(qw); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/impl/StockInfoChangeServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/impl/StockInfoChangeServiceImpl.java new file mode 100644 index 0000000..91e13e5 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/service/impl/StockInfoChangeServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.stock.goods.service.impl; + +import cn.xluobo.business.stock.goods.repo.mapper.StockInfoChangeMapper; +import cn.xluobo.business.stock.goods.repo.model.StockInfoChange; +import cn.xluobo.business.stock.goods.service.IStockInfoChangeService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 库存变动 服务实现类 + *

+ * + * @author zhangby + * @since 2021-01-09 02:10:14 + */ +@Service +public class StockInfoChangeServiceImpl extends ServiceImpl implements IStockInfoChangeService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/domain/req/ReqSearchStockInfo.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/domain/req/ReqSearchStockInfo.java new file mode 100644 index 0000000..a075e3c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/domain/req/ReqSearchStockInfo.java @@ -0,0 +1,21 @@ +package cn.xluobo.business.stock.info.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchStockInfo extends ReqPageBase implements Serializable { + + private String categoryId; + + private String goodsId; + + private Integer maxStockCnt; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/repo/mapper/StockInfoMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/repo/mapper/StockInfoMapper.java new file mode 100644 index 0000000..03feba5 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/repo/mapper/StockInfoMapper.java @@ -0,0 +1,29 @@ +package cn.xluobo.business.stock.info.repo.mapper; + +import cn.xluobo.business.stock.info.domain.req.ReqSearchStockInfo; +import cn.xluobo.business.stock.info.repo.model.StockInfo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 当前库存 Mapper 接口 + *

+ * + * @author zhangby + * @since 2021-01-09 02:05:31 + */ +public interface StockInfoMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + + /** + * 查询 + * @param reqSearchStockInfo + * @param page + * @return + */ + List selectByCondition(@Param("reqSearchStockInfo") ReqSearchStockInfo reqSearchStockInfo, + @Param("page") Page page); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/repo/mapping/StockInfoMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/repo/mapping/StockInfoMapper.xml new file mode 100644 index 0000000..4a612a7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/repo/mapping/StockInfoMapper.xml @@ -0,0 +1,27 @@ + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/repo/model/StockInfo.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/repo/model/StockInfo.java new file mode 100644 index 0000000..16931e7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/repo/model/StockInfo.java @@ -0,0 +1,110 @@ +package cn.xluobo.business.stock.info.repo.model; + +import com.baomidou.mybatisplus.annotation.*; +import com.google.common.collect.Lists; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + *

+ * 当前库存 + *

+ * + * @author zhangby + * @since 2021-01-09 02:05:31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("stock_info") +public class StockInfo implements Serializable { + + + /** + * 库存编号 + */ + @TableId(value = "stock_id", type = IdType.ASSIGN_ID) + private Long stockId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 商品编号 + */ + @TableField("goods_id") + private Long goodsId; + + /** + * 校区 + */ + @TableField("dept_id") + private Long deptId; + + /** + * 成本价格 + */ + @TableField("cost_price") + private BigDecimal costPrice; + + /** + * 销售价格 + */ + @TableField("sale_price") + private BigDecimal salePrice; + + /** + * 库存数量 + */ + @TableField("stock_cnt") + private Integer stockCnt; + + /** + * 删除标志(1删除 0在用) + */ + @TableField("delete_flag") + @TableLogic + private String deleteFlag; + + /** + * 创建者 + */ + @TableField("create_user") + private String createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private String lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + @TableField(exist = false) + private String goodsName; + @TableField(exist = false) + private String deptName; + @TableField(exist = false) + private String categoryName; + @TableField(exist = false) + private List extendValues = Lists.newArrayList(); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/service/IStockInfoService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/service/IStockInfoService.java new file mode 100644 index 0000000..11b0a13 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/service/IStockInfoService.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.stock.info.service; + +import cn.xluobo.business.stock.info.repo.model.StockInfo; + +/** + *

+ * 当前库存 服务类 + *

+ * + * @author zhangby + * @since 2021-01-09 02:05:31 + */ +public interface IStockInfoService extends com.baomidou.mybatisplus.extension.service.IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/service/impl/StockInfoServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/service/impl/StockInfoServiceImpl.java new file mode 100644 index 0000000..7af31d9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/info/service/impl/StockInfoServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.stock.info.service.impl; + +import cn.xluobo.business.stock.info.repo.mapper.StockInfoMapper; +import cn.xluobo.business.stock.info.repo.model.StockInfo; +import cn.xluobo.business.stock.info.service.IStockInfoService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 当前库存 服务实现类 + *

+ * + * @author zhangby + * @since 2021-01-09 02:05:31 + */ +@Service +public class StockInfoServiceImpl extends ServiceImpl implements IStockInfoService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqPageSelect.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqPageSelect.java new file mode 100644 index 0000000..7779a6c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqPageSelect.java @@ -0,0 +1,18 @@ +package cn.xluobo.business.sys.admin.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +/** + * 异步查询select + * @author :zhangbaoyu + * @date :Created in 2021/1/16 15:37 + */ +@Data +public class ReqPageSelect extends ReqPageBase { + // 默认值 + private String defaultValue; + + // 查询 + private String search; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchOnlineUser.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchOnlineUser.java new file mode 100644 index 0000000..4ac118b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchOnlineUser.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.sys.admin.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchOnlineUser extends ReqPageBase implements Serializable { + private String username; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysDept.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysDept.java new file mode 100644 index 0000000..9c37591 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysDept.java @@ -0,0 +1,13 @@ +package cn.xluobo.business.sys.admin.domain.req; + + +import com.ruoyi.common.core.domain.entity.SysDept; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +public class ReqSearchSysDept extends SysDept implements Serializable { +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysDictData.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysDictData.java new file mode 100644 index 0000000..3fe59ca --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysDictData.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.sys.admin.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchSysDictData extends ReqPageBase implements Serializable { + + private String dictLabel; + + private String dictType; + + private String status; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysDictType.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysDictType.java new file mode 100644 index 0000000..556d9b2 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysDictType.java @@ -0,0 +1,24 @@ +package cn.xluobo.business.sys.admin.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchSysDictType extends ReqPageBase implements Serializable { + + private String dictName; + + private String dictType; + + private String status; + + private String beginTime; + + private String endTime; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysMenu.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysMenu.java new file mode 100644 index 0000000..a0793d8 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysMenu.java @@ -0,0 +1,13 @@ +package cn.xluobo.business.sys.admin.domain.req; + + +import com.ruoyi.common.core.domain.entity.SysMenu; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +public class ReqSearchSysMenu extends SysMenu implements Serializable { +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysRole.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysRole.java new file mode 100644 index 0000000..aaa61da --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysRole.java @@ -0,0 +1,13 @@ +package cn.xluobo.business.sys.admin.domain.req; + + +import com.ruoyi.common.core.domain.entity.SysRole; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +public class ReqSearchSysRole extends SysRole implements Serializable { +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysTenant.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysTenant.java new file mode 100644 index 0000000..d5e8b82 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysTenant.java @@ -0,0 +1,22 @@ +package cn.xluobo.business.sys.admin.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchSysTenant extends ReqPageBase implements Serializable { + + private String tenantName; + private String contactName; + private String inUse; + //过期开始时间 + private String beginTime; + //过期结束 + private String endTime; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysUser.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysUser.java new file mode 100644 index 0000000..6f03733 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqSearchSysUser.java @@ -0,0 +1,18 @@ +package cn.xluobo.business.sys.admin.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchSysUser extends ReqPageBase implements Serializable { + private String username; + private String name; + private String phone; + private Long deptId; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUpdateUserPwd.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUpdateUserPwd.java new file mode 100644 index 0000000..9baa2e7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUpdateUserPwd.java @@ -0,0 +1,21 @@ +package cn.xluobo.business.sys.admin.domain.req; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 修改当前用户密码 + * @author :zhangbaoyu + * @date :Created in 2020-02-19 22:14 + */ +@Data +public class ReqUpdateUserPwd implements Serializable { + + private String oldPassword; + + private String newPassword; + + private String confirmPassword; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUpdateUserRole.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUpdateUserRole.java new file mode 100644 index 0000000..778823e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUpdateUserRole.java @@ -0,0 +1,24 @@ +package cn.xluobo.business.sys.admin.domain.req; + +import com.baomidou.mybatisplus.annotation.TableField; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-02-06 11:45 + */ +@Data +public class ReqUpdateUserRole implements Serializable { + + private Long userId; + + private Long tenantId; + + /** + * 角色Id + */ + @TableField(exist = false) + private Long[] roleIds; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUpdateUserTenant.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUpdateUserTenant.java new file mode 100644 index 0000000..89733cc --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUpdateUserTenant.java @@ -0,0 +1,18 @@ +package cn.xluobo.business.sys.admin.domain.req; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-02-06 11:45 + */ +@Data +public class ReqUpdateUserTenant implements Serializable { + + private String userId; + + private String[] tenantIds; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUploadFile.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUploadFile.java new file mode 100644 index 0000000..f16455b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/req/ReqUploadFile.java @@ -0,0 +1,19 @@ +package cn.xluobo.business.sys.admin.domain.req; + +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +/** + * 上传文件 + * @author :zhangbaoyu + * @date :Created in 2020-03-01 09:46 + */ +@Data +public class ReqUploadFile { + + private MultipartFile file; + + private String fileType; + + private String fileIndex; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespTreeSelect.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespTreeSelect.java new file mode 100644 index 0000000..56a2912 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespTreeSelect.java @@ -0,0 +1,38 @@ +package cn.xluobo.business.sys.admin.domain.resp; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.ruoyi.common.core.domain.entity.SysDept; +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +/** + * 前端select + * @author :zhangbaoyu + * @date :Created in 2020-01-14 22:07 + */ +@Data +@Builder +public class RespTreeSelect { + + private Long id; + + private String label; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List children; + + public RespTreeSelect() { + } + + public RespTreeSelect(Long id, String label, List children) { + this.id = id; + this.label = label; + this.children = children; + } + + public RespTreeSelect(SysDept dept){ + + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespTreeSelectMenu.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespTreeSelectMenu.java new file mode 100644 index 0000000..41e7350 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespTreeSelectMenu.java @@ -0,0 +1,67 @@ +package cn.xluobo.business.sys.admin.domain.resp; + +import com.google.common.collect.Lists; +import com.ruoyi.common.core.domain.entity.SysMenu; + +import java.util.*; + +/** + * 菜单select + * @author :zhangbaoyu + * @date :Created in 2020-01-14 22:14 + */ +public class RespTreeSelectMenu extends RespTreeSelect { + + private static Map> subTreeMap = new HashMap<>(); + + public RespTreeSelectMenu() { + super(); + } + + /** + * 转换菜单为tree select + * @param sysMenuList + */ + public void converterMenu(List sysMenuList){ + subTreeMap.clear(); + for (SysMenu menu : sysMenuList) { + List subTreeList = subTreeMap.get(menu.getParentId()); + if (null == subTreeList) { + subTreeList = new LinkedList<>(); + subTreeMap.put(menu.getParentId(), subTreeList); + } + + RespTreeSelect item = RespTreeSelect.builder() + .id(menu.getMenuId()) + .label(menu.getMenuName()) + .children(new ArrayList<>()) + .build(); + + subTreeList.add(item); + } + + super.setChildren(treeDepth(this).getChildren()); + } + + /** + * 深度优先 遍历菜单树 + * + * @param userMenu + * @return + */ + private RespTreeSelect treeDepth(RespTreeSelect userMenu) { + Long id = userMenu.getId(); + List childMenuList = subTreeMap.get(id); + if (null != childMenuList) { + List childList = Lists.newLinkedList(); + for (RespTreeSelect childMenu : childMenuList) { + RespTreeSelect child = treeDepth(childMenu); + childList.add(child); + } + userMenu.setChildren(childList); + return userMenu; + } else { + return userMenu; + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespUserInfo.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespUserInfo.java new file mode 100644 index 0000000..2c76473 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespUserInfo.java @@ -0,0 +1,25 @@ +package cn.xluobo.business.sys.admin.domain.resp; + +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 用户信息 + * @author :zhangbaoyu + * @date :Created in 2020-01-13 20:28 + */ +@Data +@Builder +public class RespUserInfo implements Serializable { + + private List roles; + private List permissions; + private String introduction; + private String avatar; + private String name; + private String username; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespUserMenu.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespUserMenu.java new file mode 100644 index 0000000..4634ff7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/domain/resp/RespUserMenu.java @@ -0,0 +1,49 @@ +package cn.xluobo.business.sys.admin.domain.resp; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.google.common.collect.Lists; +import com.ruoyi.common.core.domain.entity.SysMenu; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; +import java.util.*; + +/** + * 用户菜单 + * + * @author :zhangbaoyu + * @date :Created in 2020-01-14 10:35 + */ +@Data +@Builder +public class RespUserMenu implements Serializable { + + private static Map> subTreeMap = new HashMap<>(); + + @JsonIgnore + private String id; + + @JsonIgnore + private String parentId; + + private boolean hidden; + + private String path; + private String component; + private String name; + private Meta meta; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List children; + + @Data + class Meta implements Serializable { + private String title; + private String icon; + } + + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/enums/RoleEnum.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/enums/RoleEnum.java new file mode 100644 index 0000000..18cf5e3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/enums/RoleEnum.java @@ -0,0 +1,34 @@ +package cn.xluobo.business.sys.admin.enums; + +/** + * 角色枚举 + * @author :zhangbaoyu + * @date :Created in 2020/10/17 12:09 + */ +public enum RoleEnum { + + ADMIN("admin","系统管理员"), + TENANT_MANAGER("tenantManager","租户管理"), + SCHOOL("school","学校"), + SCHOOL_MANAGER("schoolManager","校长"), + TEACHING_MANAGER("teachingManager","教务管理"), + TEACHER("teacher","教师") + ; + + private String roleCode; + + private String roleName; + + RoleEnum(String roleCode, String roleName) { + this.roleCode = roleCode; + this.roleName = roleName; + } + + public String getRoleCode() { + return roleCode; + } + + public String getRoleName() { + return roleName; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/model/SysUserDept.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/model/SysUserDept.java new file mode 100644 index 0000000..995f591 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/model/SysUserDept.java @@ -0,0 +1,35 @@ +package cn.xluobo.business.sys.admin.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sys_user_dept") +public class SysUserDept { + + /** + * 用户id + */ + @TableId(value = "user_id", type = IdType.ASSIGN_ID) + private Long userId; + + /** + * 校区id + */ + @TableField("dept_id") + private Long deptId; + + /** + * 租户 + */ + @TableField("tenant_id") + private Long tenantId; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/model/SysUserTenant.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/model/SysUserTenant.java new file mode 100644 index 0000000..f0e5094 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/model/SysUserTenant.java @@ -0,0 +1,23 @@ +package cn.xluobo.business.sys.admin.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sys_user_tenant") +public class SysUserTenant implements Serializable { + + @TableId("user_id") + private Long userId; + + @TableField("tenant_id") + private Long tenantId; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysDeptMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysDeptMapper.java new file mode 100644 index 0000000..d9b6c4f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysDeptMapper.java @@ -0,0 +1,37 @@ +package cn.xluobo.business.sys.admin.repo.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.common.core.domain.entity.SysDept; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 部门表 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-01-18 + */ +public interface ISysDeptMapper extends BaseMapper { + + /** + * 获取用户 有权限的校区列表 + * + * @param userId + * @param deptType + * @return + */ + List selectUserCampusList(@Param("userId") Long userId, @Param("deptType") String deptType); + + + /** + * 用户对应的校区是否在用 + * + * @param userId + * @param deptId + * @return + */ + SysDept selectUserDeptInUse(@Param("userId") Long userId, @Param("deptId") Long deptId); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysDictDataMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysDictDataMapper.java new file mode 100644 index 0000000..57abbcc --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysDictDataMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sys.admin.repo.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.common.core.domain.entity.SysDictData; + +/** + *

+ * 字典数据表 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-01-15 + */ +public interface ISysDictDataMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysDictTypeMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysDictTypeMapper.java new file mode 100644 index 0000000..47b41ed --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysDictTypeMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sys.admin.repo.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.common.core.domain.entity.SysDictType; + +/** + *

+ * 字典类型表 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-01-15 + */ +public interface ISysDictTypeMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysFileMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysFileMapper.java new file mode 100644 index 0000000..ee7d2a9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysFileMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sys.admin.repo.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.framework.web.domain.server.SysFile; + +/** + *

+ * 附件表 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-03-01 10:09:44 + */ +public interface ISysFileMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysMenuMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysMenuMapper.java new file mode 100644 index 0000000..6b7b415 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysMenuMapper.java @@ -0,0 +1,59 @@ +package cn.xluobo.business.sys.admin.repo.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.common.core.domain.entity.SysMenu; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 菜单权限表 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-01-12 + */ +public interface ISysMenuMapper extends BaseMapper { + + /** + * 用户 权限标识 + * + * 角色对应菜单固定 未通过租户进行区分 + * @param userId + * @param tenantId + * @return + */ + List selectUserMenuPermissionMeta(@Param("userId") String userId, @Param("tenantId") String tenantId); + + /** + * 系统所有需鉴权url + * @return + */ + List selectAllMenuPermissionUrl(); + + /** + * 用户菜单 + * + * 角色对应菜单固定 未通过租户进行区分 + * @param userId + * @param tenantId + * @return + */ + List selectUserMenuList(@Param("userId") String userId, @Param("tenantId") String tenantId); + + /** + * 超级管理员用户菜单 + * @return + */ + List selectSuperUserMenuList(); + + /** + * 角色对应的菜单Id列表 + * + * @param roleId + * @return + */ + List selectRoleMenuTreeIdList(@Param("roleId")Long roleId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysRoleMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysRoleMapper.java new file mode 100644 index 0000000..b9839a3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysRoleMapper.java @@ -0,0 +1,29 @@ +package cn.xluobo.business.sys.admin.repo.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.common.core.domain.entity.SysRole; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 角色表 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-01-30 11:15:50 + */ +public interface ISysRoleMapper extends BaseMapper { + + List selectUserRoleList(@Param("userId")Long userId, @Param("tenantId")Long tenantId); + + /** + * 角色对应的菜单Id列表 + * + * @param userId + * @param tenantId + * @return + */ + List selectUserRoleTreeIdList(@Param("userId")Long userId, @Param("tenantId")Long tenantId); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysRoleMenuMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysRoleMenuMapper.java new file mode 100644 index 0000000..861107a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysRoleMenuMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sys.admin.repo.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.system.domain.SysRoleMenu; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-01-12 + */ +public interface ISysRoleMenuMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserDeptMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserDeptMapper.java new file mode 100644 index 0000000..c25e912 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserDeptMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sys.admin.repo.mapper; + +import cn.xluobo.business.sys.admin.model.SysUserDept; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 用户拥有的校区权限 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-08-07 + */ +public interface ISysUserDeptMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserMapper.java new file mode 100644 index 0000000..e4b6aac --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserMapper.java @@ -0,0 +1,40 @@ +package cn.xluobo.business.sys.admin.repo.mapper; + +import cn.xluobo.business.sys.admin.domain.req.ReqSearchSysUser; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.common.core.domain.entity.SysUser; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 用户表 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-01-12 + */ +public interface ISysUserMapper extends BaseMapper { + + List selectUserList(@Param("reqSearchSysUser") ReqSearchSysUser reqSearchSysUser, @Param("page") RespPage page); + + /** + * 用户角色count + * + * @param userId + * @param roleCode + * @return + */ + int selectSuperTenantUserRoleCount(@Param("userId") Long userId, @Param("roleCode") String roleCode); + + /** + * 用户角色count + * @param userId + * @param tenantId + * @param roleCodes + * @return + */ + int selectUserHasAnyRoleCount(@Param("userId") String userId, @Param("tenantId") String tenantId, @Param("roleCodes") String[] roleCodes); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserRoleMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserRoleMapper.java new file mode 100644 index 0000000..dbf991a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserRoleMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sys.admin.repo.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.system.domain.SysUserRole; + +/** + *

+ * 用户角色表 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-01-12 + */ +public interface ISysUserRoleMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserTenantMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserTenantMapper.java new file mode 100644 index 0000000..39ae3a8 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapper/ISysUserTenantMapper.java @@ -0,0 +1,19 @@ +package cn.xluobo.business.sys.admin.repo.mapper; + +import cn.xluobo.business.sys.admin.model.SysUserTenant; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 用户所属租户 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-01-12 + */ +public interface ISysUserTenantMapper extends BaseMapper { + + Long selectUserDefaultTenant(@Param("userId") Long userId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysDeptMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysDeptMapper.xml new file mode 100644 index 0000000..a9374b9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysDeptMapper.xml @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysDictDataMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysDictDataMapper.xml new file mode 100644 index 0000000..3ba1525 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysDictDataMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysDictTypeMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysDictTypeMapper.xml new file mode 100644 index 0000000..25184d4 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysDictTypeMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysFileMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysFileMapper.xml new file mode 100644 index 0000000..ccf8f92 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysFileMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysMenuMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysMenuMapper.xml new file mode 100644 index 0000000..7a4cb68 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysMenuMapper.xml @@ -0,0 +1,51 @@ + + + + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysRoleMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysRoleMapper.xml new file mode 100644 index 0000000..9b462e4 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysRoleMapper.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysRoleMenuMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysRoleMenuMapper.xml new file mode 100644 index 0000000..0c9ff19 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysRoleMenuMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysTenantMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysTenantMapper.xml new file mode 100644 index 0000000..eaff5fa --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysTenantMapper.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserDeptMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserDeptMapper.xml new file mode 100644 index 0000000..4e75e90 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserDeptMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserMapper.xml new file mode 100644 index 0000000..2346e58 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserRoleMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserRoleMapper.xml new file mode 100644 index 0000000..b10e7c5 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserRoleMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserTenantMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserTenantMapper.xml new file mode 100644 index 0000000..780aa7f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserTenantMapper.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDeptService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDeptService.java new file mode 100644 index 0000000..d21f4a1 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDeptService.java @@ -0,0 +1,132 @@ +package cn.xluobo.business.sys.admin.service; + +import cn.xluobo.business.sc.student.repo.model.ScStudentCourse; +import cn.xluobo.business.sc.student.service.IScStudentCourseService; +import cn.xluobo.business.sys.admin.domain.req.ReqSearchSysDept; +import cn.xluobo.business.sys.admin.domain.resp.RespTreeSelect; +import cn.xluobo.business.sys.admin.model.SysUserDept; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.google.common.collect.Lists; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessSysDeptService { + + @Autowired + private ISysDeptService sysDeptService; + @Autowired + private ISysUserDeptService userDeptService; + @Autowired + private IScStudentCourseService studentCourseService; + + /** + * 查询树 + * + * @param reqSearchSysDept + * @return + */ + public APIResponse searchList(ReqSearchSysDept reqSearchSysDept) { + QueryWrapper qw = new QueryWrapper(); + qw.eq("delete_flag", "0"); + if (StringUtils.isNotEmpty(reqSearchSysDept.getDeptName())) { + qw.like("dept_name", reqSearchSysDept.getDeptName()); + } +// if (StringUtils.isNotEmpty(reqSearchSysDept.getInUse())) { +// qw.eq("in_use", reqSearchSysDept.getInUse()); +// } +// qw.orderByAsc("sort"); +// List list = sysDeptService.list(qw); +// SysDept sysDept = new SysDept(); +// sysDept.setDeptId(-1L); +// sysDept.converterTree(list); +// List respPage = sysDept.getChildren(); + return APIResponse.toAPIResponse(null); + } + + /** + * 详情 + * + * @param deptId + * @return + */ + public APIResponse detailById(Long deptId) { + if (null == deptId) { + return APIResponse.toAPIResponse(null); + } + SysDept detailInfo = sysDeptService.getById(deptId); + return APIResponse.toAPIResponse(detailInfo); + } + + + /** + * 删除 + * + * @param deptIds + * @return + */ + public APIResponse deleteById(List deptIds) { + if (null == deptIds || deptIds.isEmpty()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + + for (Long deptId : deptIds) { + if (sysDeptService.hadChild(deptId)) { + return APIResponse.toExceptionResponse("存在子部门不能删除"); + } + if (sysDeptService.hadUser(deptId)) { + return APIResponse.toExceptionResponse("存在用户不能删除"); + } + } + + // 如果已报读 不允许删除 + QueryWrapper qwSc = new QueryWrapper<>(); + qwSc.in("dept_id", deptIds); + int studentCourseCount = studentCourseService.count(qwSc); + if (studentCourseCount != 0) { + return APIResponse.toExceptionResponse("该校区已有报读学员,无法删除"); + } + + boolean deleteDept = sysDeptService.removeByIds(deptIds); + if (deleteDept) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 前端select + * + * @return + */ + public List campusList() { + SysDept sysDept = new SysDept(); +// sysDept.setInUse("1"); +// sysDept.setDeleteFlag("0"); +// sysDept.setDeptType("2"); + QueryWrapper qw = new QueryWrapper(sysDept); + qw.orderByAsc("sort"); + List list = sysDeptService.list(qw); + List respTreeSelects = list.stream().map(RespTreeSelect::new).collect(Collectors.toList()); + return respTreeSelects; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDictDataService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDictDataService.java new file mode 100644 index 0000000..c172a1a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDictDataService.java @@ -0,0 +1,168 @@ +package cn.xluobo.business.sys.admin.service; + +import cn.xluobo.business.sys.admin.domain.req.ReqPageSelect; +import cn.xluobo.business.sys.admin.domain.req.ReqSearchSysDictData; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.domain.entity.SysDictType; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessSysDictDataService { + + @Autowired + private ISysDictDataService sysDictDataService; + @Autowired + private ISysDictTypeService sysDictTypeService; + + /** + * 查询列表 + * + * @param reqSearchDictData + * @return + */ + public RespPage searchList(ReqSearchSysDictData reqSearchDictData) { + QueryWrapper qw = new QueryWrapper(); + if (StringUtils.isNotEmpty(reqSearchDictData.getDictLabel())) { + qw.like("dict_label", reqSearchDictData.getDictLabel()); + } + if (StringUtils.isNotEmpty(reqSearchDictData.getDictType())) { + qw.eq("dict_type", reqSearchDictData.getDictType()); + } + if (StringUtils.isNotEmpty(reqSearchDictData.getStatus())) { + qw.eq("status", reqSearchDictData.getStatus()); + } + RespPage page = new RespPage(reqSearchDictData.getPageNum(), reqSearchDictData.getPageSize()); + RespPage listPage = sysDictDataService.page(page, qw); + return listPage; + } + + /** + * 详情 + * + * @param dictTypeId + * @return + */ + public SysDictData detailById(String dictTypeId) { + if (StringUtils.isEmpty(dictTypeId)) { + return null; + } + return sysDictDataService.getById(dictTypeId); + } + + /** + * 添加 + * + * @param sysDictData + * @return + */ + @CacheEvict(value = "SYS_DICT_DATA", key = "#sysDictData.dictType") + public boolean addDictData(SysDictData sysDictData) { + LoginUser loginUser = SecurityUtils.getLoginUser(); +// sysDictData.setCreateUser(loginUser.getUserId()); + return sysDictDataService.save(sysDictData); + } + + /** + * 更新 + * + * @param sysDictData + * @return + */ + @CacheEvict(value = "SYS_DICT_DATA", key = "#sysDictData.dictType") + public APIResponse updateDictData(SysDictData sysDictData) { +// if (StringUtils.isEmpty(sysDictData.getDictDataId())) { +// return APIResponse.toExceptionResponse(ApiResEnums.BUSINESS_FAILURE); +// } + SysDictType dbDictType = sysDictTypeService.selectByDictType(sysDictData.getDictType()); +// if (!dbDictType.modifiable()) { +// return APIResponse.toExceptionResponse("本数据不允许修改"); +// } + + LoginUser loginUser = SecurityUtils.getLoginUser(); +// sysDictData.setLastUpdateUser(loginUser.getUserId()); +// sysDictData.setLastUpdateTime(new Date()); + boolean update = sysDictDataService.updateById(sysDictData); + if (update) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 删除 + * + * @param dictTypeIds + * @return + */ + public APIResponse deleteById(String[] dictTypeIds) { + if (null == dictTypeIds || dictTypeIds.length == 0) { + return APIResponse.toExceptionResponse(ApiResEnums.BUSINESS_FAILURE); + } + List dictData = sysDictDataService.listByIds(Arrays.asList(dictTypeIds)); + for (SysDictData dictDatum : dictData) { + SysDictType dbDictType = sysDictTypeService.selectByDictType(dictDatum.getDictType()); +// if (!dbDictType.modifiable()) { +// return APIResponse.toExceptionResponse("本数据不允许修改"); +// } + sysDictDataService.removeCache(dbDictType.getDictType()); + } + + boolean remove = sysDictDataService.removeByIds(Arrays.asList(dictTypeIds)); + if (remove) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 某字典数据 + * + * @param dictType + * @return + */ + public List dictTypeDataList(String dictType) { + return sysDictDataService.dictTypeDataList(dictType); + } + + /** + * 某字典数据 + * 异步分页查询 + * + * @param dictType + * @return + */ + public RespPage dictTypeDataList(String dictType, ReqPageSelect reqPageSelect) { + return sysDictDataService.dictTypeDataList(dictType, reqPageSelect); + } + + /** + * 某字典数据 + * + * @param dictType + * @return + */ + public List dictTypeDataListByParentValue(String dictType, String parentValue) { + return sysDictDataService.dictTypeDataListByParentValue(dictType, parentValue); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysDeptService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysDeptService.java new file mode 100644 index 0000000..3d86382 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysDeptService.java @@ -0,0 +1,55 @@ +package cn.xluobo.business.sys.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.common.core.domain.entity.SysDept; + +import java.util.List; + +/** + *

+ * 部门表 服务类 + *

+ * + * @author zhangby + * @since 2020-01-18 + */ +public interface ISysDeptService extends IService { + + /** + * 是否存在子部门 + * @param departId + * @return + */ + boolean hadChild(Long departId); + + /** + * 是否存在用户 + * @param departId + * @return + */ + boolean hadUser(Long departId); + + /** + * 修改子元素关系 + * @param deptId 被修改的部门ID + * @param newAncestors 新的父ID集合 + * @param oldAncestors 旧的父ID集合 + */ + void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors); + + /** + * 获取用户有权限的校区列表 + * @return + */ + List selectUserCampusList(Long userId); + + /** + * 校验 用户dept 是否在用 + * 如校区 + * + * @param userId + * @param deptId + * @return + */ + boolean checkUserDeptInUse(Long userId, Long deptId); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysDictDataService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysDictDataService.java new file mode 100644 index 0000000..5d58ca7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysDictDataService.java @@ -0,0 +1,41 @@ +package cn.xluobo.business.sys.admin.service; + +import cn.xluobo.business.sys.admin.domain.req.ReqPageSelect; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.common.core.domain.entity.SysDictData; + +import java.util.List; + +/** + *

+ * 字典数据表 服务类 + *

+ * + * @author zhangby + * @since 2020-01-15 + */ +public interface ISysDictDataService extends IService { + + List dictTypeDataList(String dictType); + + RespPage dictTypeDataList(String dictType, ReqPageSelect reqPageSelect); + + List dictTypeDataListByParentValue(String dictType,String parentValue); + + /** + * 删除缓存 + * @param dictType + * @return + */ + boolean removeCache(String dictType); + + /** + * 获取字典label + * @param dictType + * @param dictValue + * @return + */ + SysDictData getDictLabel(String dictType, String dictValue); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysDictTypeService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysDictTypeService.java new file mode 100644 index 0000000..0dc171d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysDictTypeService.java @@ -0,0 +1,17 @@ +package cn.xluobo.business.sys.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.common.core.domain.entity.SysDictType; + +/** + *

+ * 字典类型表 服务类 + *

+ * + * @author zhangby + * @since 2020-01-15 + */ +public interface ISysDictTypeService extends IService { + + SysDictType selectByDictType(String dictType); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysFileService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysFileService.java new file mode 100644 index 0000000..16047e2 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysFileService.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sys.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.framework.web.domain.server.SysFile; + +/** + *

+ * 附件表 服务类 + *

+ * + * @author zhangby + * @since 2020-03-01 10:09:44 + */ +public interface ISysFileService extends IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysMenuService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysMenuService.java new file mode 100644 index 0000000..9ebe8d4 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysMenuService.java @@ -0,0 +1,58 @@ +package cn.xluobo.business.sys.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.common.core.domain.entity.SysMenu; +import org.springframework.cache.annotation.Cacheable; + +import java.util.List; + +/** + *

+ * 菜单权限表 服务类 + *

+ * + * @author zhangby + * @since 2020-01-12 + */ +public interface ISysMenuService extends IService { + + /** + * 用户所有权限 + * + * @param userId + * @param tenantId + * @return + */ + @Cacheable(value = "USER_PERMISSION_META", key = "#userId+':'+#tenantId", sync = true) + List selectUserPermissions(String userId, String tenantId); + + /** + * 系统所有需限制的请求路径 + * + * @return + */ + List selectAllPermissionUrl(); + + /** + * 用户菜单 + * + * @param userId + * @param tenantId + * @return + */ + List selectUserMenuList(String userId, String tenantId); + + /** + * 超级用户菜单 + * @return + */ + List selectSuperUserMenuList(); + + /** + * 角色对应的菜单Id列表 + * + * @param roleId + * @return + */ + List selectRoleMenuTreeIdList(Long roleId); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysRoleMenuService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysRoleMenuService.java new file mode 100644 index 0000000..8735edd --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysRoleMenuService.java @@ -0,0 +1,29 @@ +package cn.xluobo.business.sys.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.system.domain.SysRoleMenu; +import org.springframework.cache.annotation.CacheEvict; + +/** + *

+ * 服务类 + *

+ * + * @author zhangby + * @since 2020-01-12 + */ +public interface ISysRoleMenuService extends IService { + + + /** + * 更新角色对应的菜单 + * + * @param sysRole + * @param nowTenantId + * @return + */ + @CacheEvict(value = "USER_PERMISSION_META", allEntries = true) + void updateRoleMenu(SysRole sysRole, Long nowTenantId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysRoleService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysRoleService.java new file mode 100644 index 0000000..e9ba358 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysRoleService.java @@ -0,0 +1,54 @@ +package cn.xluobo.business.sys.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.common.core.domain.entity.SysRole; + +import java.util.List; + +/** + *

+ * 角色表 服务类 + *

+ * + * @author zhangby + * @since 2020-01-30 11:51:28 + */ +public interface ISysRoleService extends IService { + + List selectUserRoleList(Long userId, Long tenantId); + + /** + * 是否存在子节点 + * @param roleId + * @return + */ + boolean hadChild(Long roleId); + + boolean hadUser(Long roleId); + + + + /** + * 修改子元素关系 + * @param roleId 被修改的ID + * @param newAncestors 新的父ID集合 + * @param oldAncestors 旧的父ID集合 + */ + void updateSysRoleChildren(Long roleId, String newAncestors, String oldAncestors); + + /** + * 用户对应的角色Id列表 + * + * @param userId + * @param tenantId + * @return + */ + List selectUserRoleTreeIdList(Long userId, Long tenantId); + + /** + * 根据编码 获取角色 + * @param roleCode + * @return + */ + SysRole selectByRoleCode(String roleCode); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserDeptService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserDeptService.java new file mode 100644 index 0000000..db44f2e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserDeptService.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sys.admin.service; + +import cn.xluobo.business.sys.admin.model.SysUserDept; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 用户拥有的校区权限 服务类 + *

+ * + * @author zhangby + * @since 2020-08-07 + */ +public interface ISysUserDeptService extends IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserRoleService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserRoleService.java new file mode 100644 index 0000000..9b81a2a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserRoleService.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sys.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.system.domain.SysUserRole; + +/** + *

+ * 用户角色表 服务类 + *

+ * + * @author zhangby + * @since 2020-01-12 + */ +public interface ISysUserRoleService extends IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserService.java new file mode 100644 index 0000000..f7e35a0 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserService.java @@ -0,0 +1,62 @@ +package cn.xluobo.business.sys.admin.service; + +import cn.xluobo.business.sys.admin.domain.req.ReqSearchSysUser; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.List; + +/** + *

+ * 用户表 服务类 + *

+ * + * @author zhangby + * @since 2020-01-12 + */ +public interface ISysUserService extends IService { + + UserDetails loadUserDetailByUserName(String userName); + + List selectUserList(ReqSearchSysUser reqSearchSysUser, RespPage page); + + /** + * 校验用户名是否唯一 + * @param username + * @return + */ + boolean checkUsernameUnique(String username); + + /** + * 获取绑定用户 + * @param wechatUserId wechat_user_info.wechat_user_id + * @return + */ + SysUser getByBindByWechatUserId(Long wechatUserId); + + /** + * 根据用户名 获取用户信息 + * @param username + * @return + */ + SysUser getByUserName(String username); + + /** + * 校验用户是否拥有某角色 + * @param roleCode + * @return + */ + boolean checkSuperTenantUserHasRole(Long userId, String roleCode); + + /** + * 校验用户是否拥有 指定的任意一个角色 + * @param userId + * @param tenantId + * @param roleCodes + * @return + */ + boolean checkUserHasAnyRole(String userId, String tenantId, String[] roleCodes); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserTenantService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserTenantService.java new file mode 100644 index 0000000..daabc6c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/ISysUserTenantService.java @@ -0,0 +1,18 @@ +package cn.xluobo.business.sys.admin.service; + +import cn.xluobo.business.sys.admin.model.SysUserTenant; +import com.baomidou.mybatisplus.extension.service.IService; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 用户所属租户 服务类 + *

+ * + * @author zhangby + * @since 2020-01-12 + */ +public interface ISysUserTenantService extends IService { + + Long selectUserDefaultTenant(@Param("userId") Long userId); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysDeptServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysDeptServiceImpl.java new file mode 100644 index 0000000..2f47c30 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysDeptServiceImpl.java @@ -0,0 +1,69 @@ +package cn.xluobo.business.sys.admin.service.impl; + +import cn.xluobo.business.sys.admin.repo.mapper.ISysDeptMapper; +import cn.xluobo.business.sys.admin.service.ISysDeptService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.common.core.domain.entity.SysDept; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 部门表 服务实现类 + *

+ * + * @author zhangby + * @since 2020-01-18 + */ +@Service +public class ISysDeptServiceImpl extends ServiceImpl implements ISysDeptService { + + /** + * 是否存在子部门 + * @param departId + * @return + */ + public boolean hadChild(Long departId){ + QueryWrapper qw = new QueryWrapper(); + qw.eq("parent_id",departId); + List list = list(qw); + if(list.isEmpty()){ + return false; + }else { + return true; + } + } + + @Override + public boolean hadUser(Long departId) { + // TODO: 2020-01-18 是否存在用户 + return false; + } + + @Override + public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) { + QueryWrapper qw = new QueryWrapper(); + qw.eq("parent_id",deptId); + List childrenList = list(qw); + if(!childrenList.isEmpty()){ + for (SysDept children : childrenList) { + children.setAncestors(children.getAncestors().replace(oldAncestors, newAncestors)); + } + updateBatchById(childrenList); + } + + } + + @Override + public List selectUserCampusList(Long userId) { + return baseMapper.selectUserCampusList(userId, "2"); + } + + @Override + public boolean checkUserDeptInUse(Long userId, Long deptId) { + SysDept sysDept = baseMapper.selectUserDeptInUse(userId, deptId); + return null != sysDept; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysDictDataServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysDictDataServiceImpl.java new file mode 100644 index 0000000..5f199b1 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysDictDataServiceImpl.java @@ -0,0 +1,90 @@ +package cn.xluobo.business.sys.admin.service.impl; + +import cn.xluobo.business.sys.admin.domain.req.ReqPageSelect; +import cn.xluobo.business.sys.admin.repo.mapper.ISysDictDataMapper; +import cn.xluobo.business.sys.admin.service.ISysDictDataService; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.common.collect.Lists; +import com.ruoyi.common.core.domain.entity.SysDictData; +import org.apache.commons.lang3.StringUtils; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 字典数据表 服务实现类 + *

+ * + * @author zhangby + * @since 2020-01-15 + */ +@Service +public class ISysDictDataServiceImpl extends ServiceImpl implements ISysDictDataService { + + @Override + @Cacheable(value = "SYS_DICT_DATA", key = "#dictType", sync = true) + public List dictTypeDataList(String dictType) { + if (StringUtils.isEmpty(dictType)) { + return Lists.newArrayList(); + } + QueryWrapper qw = new QueryWrapper<>(); + qw.select("dict_label", "dict_value") + .eq("dict_type", dictType); + qw.orderByAsc("dict_sort"); + return this.list(qw); + } + + @Override + public RespPage dictTypeDataList(String dictType, ReqPageSelect reqPageSelect) { + if (StringUtils.isEmpty(dictType)) { + return null; + } + RespPage page = new RespPage<>(reqPageSelect.getPageNum(), reqPageSelect.getPageSize()); + QueryWrapper qw = new QueryWrapper<>(); + if(StringUtils.isNotEmpty(reqPageSelect.getSearch())) { + qw.like("dict_label", reqPageSelect.getSearch()); + } + if(StringUtils.isNotEmpty(reqPageSelect.getDefaultValue())) { + qw.eq("dict_value", reqPageSelect.getDefaultValue()); + } + qw.select("dict_label", "dict_value") + .eq("dict_type", dictType); + qw.orderByAsc("dict_sort"); + return this.page(page,qw); + } + + @Override + public List dictTypeDataListByParentValue(String dictType, String parentValue) { + if (StringUtils.isAnyEmpty(dictType, parentValue)) { + return Lists.newArrayList(); + } + QueryWrapper qw = new QueryWrapper<>(); + qw.select("dict_label", "dict_value") + .eq("dict_type", dictType) + .eq("parent_value", parentValue); + qw.orderByAsc("dict_sort"); + return this.list(qw); + } + + @Override + @CacheEvict(value = "SYS_DICT_DATA", key = "#dictType") + public boolean removeCache(String dictType) { + return true; + } + + @Override + public SysDictData getDictLabel(String dictType, String dictValue) { + List dictTypeDataList = this.dictTypeDataList(dictType); + for (SysDictData sysDictData : dictTypeDataList) { + if (dictValue.equals(sysDictData.getDictValue())) { + return sysDictData; + } + } + return new SysDictData(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysDictTypeServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysDictTypeServiceImpl.java new file mode 100644 index 0000000..fa12856 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysDictTypeServiceImpl.java @@ -0,0 +1,27 @@ +package cn.xluobo.business.sys.admin.service.impl; + +import cn.xluobo.business.sys.admin.repo.mapper.ISysDictTypeMapper; +import cn.xluobo.business.sys.admin.service.ISysDictTypeService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.common.core.domain.entity.SysDictType; +import org.springframework.stereotype.Service; + +/** + *

+ * 字典类型表 服务实现类 + *

+ * + * @author zhangby + * @since 2020-01-15 + */ +@Service +public class ISysDictTypeServiceImpl extends ServiceImpl implements ISysDictTypeService { + + @Override + public SysDictType selectByDictType(String dictType) { + QueryWrapper qw = new QueryWrapper(); + qw.eq("dict_type",dictType); + return baseMapper.selectOne(qw); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysFileServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysFileServiceImpl.java new file mode 100644 index 0000000..bbf24fa --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysFileServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.sys.admin.service.impl; + +import cn.xluobo.business.sys.admin.repo.mapper.ISysFileMapper; +import cn.xluobo.business.sys.admin.service.ISysFileService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.framework.web.domain.server.SysFile; +import org.springframework.stereotype.Service; + +/** + *

+ * 附件表 服务实现类 + *

+ * + * @author zhangby + * @since 2020-03-01 10:09:44 + */ +@Service +public class ISysFileServiceImpl extends ServiceImpl implements ISysFileService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysMenuServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysMenuServiceImpl.java new file mode 100644 index 0000000..21aac12 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysMenuServiceImpl.java @@ -0,0 +1,47 @@ +package cn.xluobo.business.sys.admin.service.impl; + +import cn.xluobo.business.sys.admin.repo.mapper.ISysMenuMapper; +import cn.xluobo.business.sys.admin.service.ISysMenuService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.common.core.domain.entity.SysMenu; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 菜单权限表 服务实现类 + *

+ * + * @author zhangby + * @since 2020-01-12 + */ +@Service +public class ISysMenuServiceImpl extends ServiceImpl implements ISysMenuService { + + + @Override + public List selectUserPermissions(String userId, String tenantId) { + return baseMapper.selectUserMenuPermissionMeta(userId, tenantId); + } + + @Override + public List selectAllPermissionUrl() { + return baseMapper.selectAllMenuPermissionUrl(); + } + + @Override + public List selectUserMenuList(String userId, String tenantId) { + return baseMapper.selectUserMenuList(userId, tenantId); + } + + @Override + public List selectSuperUserMenuList() { + return baseMapper.selectSuperUserMenuList(); + } + + @Override + public List selectRoleMenuTreeIdList(Long roleId) { + return baseMapper.selectRoleMenuTreeIdList(roleId); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysRoleMenuServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysRoleMenuServiceImpl.java new file mode 100644 index 0000000..ec14aba --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysRoleMenuServiceImpl.java @@ -0,0 +1,43 @@ +package cn.xluobo.business.sys.admin.service.impl; + +import cn.xluobo.business.sys.admin.repo.mapper.ISysRoleMenuMapper; +import cn.xluobo.business.sys.admin.service.ISysRoleMenuService; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.common.collect.Lists; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.system.domain.SysRoleMenu; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author zhangby + * @since 2020-01-12 + */ +@Service +public class ISysRoleMenuServiceImpl extends ServiceImpl implements ISysRoleMenuService { + + @Override + public void updateRoleMenu(SysRole sysRole, Long nowTenantId) { + //角色菜单关系 + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("role_id",sysRole.getRoleId()); + this.remove(uw); + if(null != sysRole.getMenuIds() && sysRole.getMenuIds().length>0){ + List sysRoleMenuList = Lists.newArrayList(); + for (Long menuId : sysRole.getMenuIds()) { + SysRoleMenu sysRoleMenu = new SysRoleMenu(); + sysRoleMenu.setRoleId(sysRole.getRoleId()); + sysRoleMenu.setMenuId(menuId); +// sysRoleMenu.setTenantId(nowTenantId); + sysRoleMenuList.add(sysRoleMenu); + } + this.saveBatch(sysRoleMenuList); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysRoleServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysRoleServiceImpl.java new file mode 100644 index 0000000..e7f7e8c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysRoleServiceImpl.java @@ -0,0 +1,75 @@ +package cn.xluobo.business.sys.admin.service.impl; + +import cn.xluobo.business.sys.admin.repo.mapper.ISysRoleMapper; +import cn.xluobo.business.sys.admin.service.ISysRoleService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.common.core.domain.entity.SysRole; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 角色表 服务实现类 + *

+ * + * @author zhangby + * @since 2020-01-30 11:51:28 + */ +@Service +public class ISysRoleServiceImpl extends ServiceImpl implements ISysRoleService { + + @Override + public List selectUserRoleList(Long userId, Long tenantId) { + return baseMapper.selectUserRoleList(userId, tenantId); + } + + /** + * 是否存在子节点 + * + * @param roleId + * @return + */ + @Override + public boolean hadChild(Long roleId) { + QueryWrapper qw = new QueryWrapper(); + qw.eq("parent_id", roleId); + List list = list(qw); + if (list.isEmpty()) { + return false; + } else { + return true; + } + } + + @Override + public boolean hadUser(Long roleId) { + return false; + } + + @Override + public void updateSysRoleChildren(Long roleId, String newAncestors, String oldAncestors) { + QueryWrapper qw = new QueryWrapper(); + qw.eq("role_id", roleId); + List childrenList = list(qw); + if (!childrenList.isEmpty()) { +// for (SysRole children : childrenList) { +// children.setAncestors(children.getAncestors().replace(oldAncestors, newAncestors)); +// } + updateBatchById(childrenList); + } + } + + @Override + public List selectUserRoleTreeIdList(Long userId, Long tenantId) { + return baseMapper.selectUserRoleTreeIdList(userId, tenantId); + } + + @Override + public SysRole selectByRoleCode(String roleCode) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("role_code", roleCode); + return this.getOne(qw); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserDeptServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserDeptServiceImpl.java new file mode 100644 index 0000000..acc90af --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserDeptServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.sys.admin.service.impl; + +import cn.xluobo.business.sys.admin.model.SysUserDept; +import cn.xluobo.business.sys.admin.repo.mapper.ISysUserDeptMapper; +import cn.xluobo.business.sys.admin.service.ISysUserDeptService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 用户拥有的校区权限 服务实现类 + *

+ * + * @author zhangby + * @since 2020-08-07 + */ +@Service +public class ISysUserDeptServiceImpl extends ServiceImpl implements ISysUserDeptService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserRoleServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserRoleServiceImpl.java new file mode 100644 index 0000000..c32bd84 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserRoleServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.sys.admin.service.impl; + +import cn.xluobo.business.sys.admin.repo.mapper.ISysUserRoleMapper; +import cn.xluobo.business.sys.admin.service.ISysUserRoleService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.system.domain.SysUserRole; +import org.springframework.stereotype.Service; + +/** + *

+ * 用户角色表 服务实现类 + *

+ * + * @author zhangby + * @since 2020-01-12 + */ +@Service +public class ISysUserRoleServiceImpl extends ServiceImpl implements ISysUserRoleService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserServiceImpl.java new file mode 100644 index 0000000..ee80e65 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserServiceImpl.java @@ -0,0 +1,89 @@ +package cn.xluobo.business.sys.admin.service.impl; + +import cn.hutool.core.util.ObjectUtil; +import cn.xluobo.business.sys.admin.domain.req.ReqSearchSysUser; +import cn.xluobo.business.sys.admin.repo.mapper.ISysUserMapper; +import cn.xluobo.business.sys.admin.service.ISysUserService; +import cn.xluobo.business.sys.admin.service.ISysUserTenantService; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AccountExpiredException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional +public class ISysUserServiceImpl extends ServiceImpl implements ISysUserService { + @Autowired + private ISysUserTenantService userTenantService; + + @Override + public UserDetails loadUserDetailByUserName(String userName) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("username",userName); + SysUser sysUser = baseMapper.selectOne(qw); + if(null == sysUser){ + throw new UsernameNotFoundException("username: " + userName + " do not exist!"); + } + Long tenantId = userTenantService.selectUserDefaultTenant(sysUser.getUserId()); + if(ObjectUtil.isEmpty(tenantId)) { + throw new AccountExpiredException("账户无关联机构或机构已过期!"); + } +// LoginUser loginUser = LoginUser.buildBySysUser(sysUser); +// loginUser.setAuthorities(new ArrayList<>()); + return null; +// return loadUserExtendInfo(sysUser,null); + } + + @Override + public List selectUserList(ReqSearchSysUser reqSearchSysUser, RespPage page) { + return baseMapper.selectUserList(reqSearchSysUser, page); + } + + @Override + public boolean checkUsernameUnique(String username) { + QueryWrapper qw = new QueryWrapper(); + qw.eq("username",username); + int count = this.count(qw); + if(count == 0) { + return true; + } else { + return false; + } + } + + @Override + public SysUser getByBindByWechatUserId(Long wechatUserId) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("wechat_user_id",wechatUserId); + return this.getOne(qw); + } + + @Override + public SysUser getByUserName(String username) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("username",username); + SysUser sysUser = baseMapper.selectOne(qw); + return sysUser; + } + + @Override + public boolean checkSuperTenantUserHasRole(Long userId, String roleCode) { + int userRoleCount = baseMapper.selectSuperTenantUserRoleCount(userId, roleCode); + return userRoleCount > 0; + } + + @Override + public boolean checkUserHasAnyRole(String userId, String tenantId, String[] roleCodes) { + int hasAnyRoleCount = baseMapper.selectUserHasAnyRoleCount(userId, tenantId, roleCodes); + return hasAnyRoleCount > 0; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserTenantServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserTenantServiceImpl.java new file mode 100644 index 0000000..5512ce3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/impl/ISysUserTenantServiceImpl.java @@ -0,0 +1,24 @@ +package cn.xluobo.business.sys.admin.service.impl; + +import cn.xluobo.business.sys.admin.model.SysUserTenant; +import cn.xluobo.business.sys.admin.repo.mapper.ISysUserTenantMapper; +import cn.xluobo.business.sys.admin.service.ISysUserTenantService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 用户所属租户 服务实现类 + *

+ * + * @author zhangby + * @since 2020-01-12 + */ +@Service +public class ISysUserTenantServiceImpl extends ServiceImpl implements ISysUserTenantService { + + @Override + public Long selectUserDefaultTenant(Long userId) { + return baseMapper.selectUserDefaultTenant(userId); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/repo/mapper/SysHolidayMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/repo/mapper/SysHolidayMapper.java new file mode 100644 index 0000000..473d95c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/repo/mapper/SysHolidayMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sys.holiday.repo.mapper; + +import cn.xluobo.business.sys.holiday.repo.model.SysHoliday; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 节假日表 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-09-15 + */ +public interface SysHolidayMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/repo/mapping/SysHolidayMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/repo/mapping/SysHolidayMapper.xml new file mode 100644 index 0000000..4534e49 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/repo/mapping/SysHolidayMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/repo/model/SysHoliday.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/repo/model/SysHoliday.java new file mode 100644 index 0000000..d16139e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/repo/model/SysHoliday.java @@ -0,0 +1,48 @@ +package cn.xluobo.business.sys.holiday.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * 节假日表 + *

+ * + * @author zhangby + * @since 2020-09-15 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sys_holiday") +public class SysHoliday implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 日期 格式yyyy-MM-dd + */ + @TableId(value = "day", type = IdType.INPUT) + private String day; + + /** + * 日期类型 0工作日 1 假日 2节日 + */ + @TableField("day_type") + private String dayType; + + public SysHoliday() { + } + + public SysHoliday(String day, String dayType) { + this.day = day; + this.dayType = dayType; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/service/ISysHolidayService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/service/ISysHolidayService.java new file mode 100644 index 0000000..70b4db9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/service/ISysHolidayService.java @@ -0,0 +1,39 @@ +package cn.xluobo.business.sys.holiday.service; + +import cn.xluobo.business.sys.holiday.repo.model.SysHoliday; +import cn.xluobo.core.api.APIBaseResponse; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 节假日表 服务类 + *

+ * + * @author zhangby + * @since 2020-09-15 + */ +public interface ISysHolidayService extends IService { + + /** + * 获取今年及之后的 节假日 + * @param year + * @return + */ + List selectYearOrLaterHoliday(String year); + + /** + * 节假日map + * @return key:yyyyMMdd 日期 value: 1 + */ + Map getHolidayMap(); + + /** + * 调用接口 节假日 自动入库 + * @param year 年 + */ + APIBaseResponse autoInsertHoliday(String year); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/service/impl/SysHolidayServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/service/impl/SysHolidayServiceImpl.java new file mode 100644 index 0000000..08e7eb3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/holiday/service/impl/SysHolidayServiceImpl.java @@ -0,0 +1,98 @@ +package cn.xluobo.business.sys.holiday.service.impl; + +import cn.xluobo.business.sys.holiday.repo.mapper.SysHolidayMapper; +import cn.xluobo.business.sys.holiday.repo.model.SysHoliday; +import cn.xluobo.business.sys.holiday.service.ISysHolidayService; +import cn.xluobo.core.api.APIBaseResponse; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.benmanes.caffeine.cache.Cache; +import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.joda.time.DateTime; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + *

+ * 节假日表 服务实现类 + *

+ * + * @author zhangby + * @since 2020-09-15 + */ +@Service +@Slf4j +public class SysHolidayServiceImpl extends ServiceImpl implements ISysHolidayService { + + @Resource(name = "holidayCache") + private Cache> holidayCache; + + @Override + public List selectYearOrLaterHoliday(String year) { + QueryWrapper qw = new QueryWrapper<>(); + qw.ge("day", year); + qw.in("day_type", "1","2"); + return this.list(qw); + } + + @Override + public Map getHolidayMap() { + Map holidayMap = holidayCache.get("holidayCache", k -> { + String now = DateTime.now().toString("yyyy"); + List sysHolidays = this.selectYearOrLaterHoliday(now); + Map collect = sysHolidays.stream().collect(Collectors.toMap(SysHoliday::getDay, SysHoliday::getDayType)); + return collect; + }); + return holidayMap; + } + + @Override + public APIBaseResponse autoInsertHoliday(String year) { + JSONObject resultMap = new JSONObject(); + try { + HttpGet httpGet = new HttpGet("http://tool.bitefu.net/jiari/?d=" + year); + CloseableHttpClient httpClient = HttpClients.createDefault(); + HttpEntity entity = httpClient.execute(httpGet).getEntity(); + String resultJson = EntityUtils.toString(entity, Charset.forName("UTF-8")); + resultMap = JSON.parseObject(resultJson); + } catch (IOException e) { + e.printStackTrace(); + } + Object object = resultMap.get(year); + if (object instanceof Boolean) { + log.error("can not get {} year holiday,interface result={}", year, object); + return APIBaseResponse.fail("can not get year holiday,interface result = " + object); + } + JSONObject holidayMap = resultMap.getJSONObject(year); + + List holidayList = Lists.newArrayList(); + + holidayMap.forEach((key, value) -> { + holidayList.add(new SysHoliday(year + key, holidayMap.getString(key))); + }); + + // 删除对应年份所有数据 + UpdateWrapper uw = new UpdateWrapper(); + uw.likeRight("day", year); + this.remove(uw); + + // 入库 + this.saveBatch(holidayList); + return APIBaseResponse.success(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapper/SysOperateLogMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapper/SysOperateLogMapper.java new file mode 100644 index 0000000..1855ddc --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapper/SysOperateLogMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sys.log.repo.mapper; + +import cn.xluobo.business.sys.log.repo.model.SysOperateLog; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 操作日志记录 Mapper 接口 + *

+ * + * @author zhangby + * @since 2021-04-20 + */ +public interface SysOperateLogMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapper/SysUserLoginLogMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapper/SysUserLoginLogMapper.java new file mode 100644 index 0000000..9104a39 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapper/SysUserLoginLogMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sys.log.repo.mapper; + +import cn.xluobo.business.sys.log.repo.model.SysUserLoginLog; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 登录日志 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-11-13 + */ +public interface SysUserLoginLogMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapping/SysOperateLogMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapping/SysOperateLogMapper.xml new file mode 100644 index 0000000..7893cb9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapping/SysOperateLogMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapping/SysUserLoginLogMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapping/SysUserLoginLogMapper.xml new file mode 100644 index 0000000..d26ae94 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/mapping/SysUserLoginLogMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/model/SysOperateLog.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/model/SysOperateLog.java new file mode 100644 index 0000000..cbe2831 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/model/SysOperateLog.java @@ -0,0 +1,127 @@ +package cn.xluobo.business.sys.log.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 操作日志记录 + *

+ * + * @author zhangby + * @since 2021-04-20 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sys_operate_log") +public class SysOperateLog implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 操作模块 + */ + @TableId(value = "operate_id", type = IdType.ASSIGN_ID) + private String operateId; + + /** + * 操作模块 + */ + @TableField("operate_module") + private String operateModule; + + /** + * 业务类型 + */ + @TableField("business_type") + private String businessType; + + /** + * 方法名称 + */ + @TableField("method") + private String method; + + /** + * 请求方式 + */ + @TableField("request_method") + private String requestMethod; + + /** + * 客户端 pc app + */ + @TableField("client_type") + private String clientType; + + /** + * 操作人员 + */ + @TableField("user_id") + private Long userId; + + /** + * 操作人员 + */ + @TableField("user_name") + private String userName; + + /** + * 请求URL + */ + @TableField("operate_url") + private String operateUrl; + + /** + * 主机地址 + */ + @TableField("operate_ip") + private String operateIp; + + /** + * 操作地点 + */ + @TableField("operate_location") + private String operateLocation; + + /** + * 请求参数 + */ + @TableField("req_param") + private String reqParam; + + /** + * 返回参数 + */ + @TableField("resp_result") + private String respResult; + + /** + * 是否异常(0正常 1异常) + */ + @TableField("error") + private Integer error; + + /** + * 错误消息 + */ + @TableField("error_msg") + private String errorMsg; + + /** + * 操作时间 + */ + @TableField("operate_time") + private Date operateTime; + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/model/SysUserLoginLog.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/model/SysUserLoginLog.java new file mode 100644 index 0000000..5bbdd2d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/repo/model/SysUserLoginLog.java @@ -0,0 +1,67 @@ +package cn.xluobo.business.sys.log.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 登录日志 + *

+ * + * @author zhangby + * @since 2020-11-13 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sys_user_login_log") +public class SysUserLoginLog implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "login_log_id", type = IdType.ASSIGN_ID) + private Long loginLogId; + + @TableField("user_id") + private Long userId; + + /** + * 用户名 + */ + @TableField("username") + private String username; + + /** + * 姓名 + */ + @TableField("name") + private String name; + + /** + * 登录时间 + */ + @TableField("login_time") + private Date loginTime; + + /** + * 登录IP + */ + @TableField("login_ip") + private String loginIp; + + /** + * 登录浏览器 + */ + @TableField("browser_info") + private String browserInfo; + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/ISysOperateLogService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/ISysOperateLogService.java new file mode 100644 index 0000000..286584a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/ISysOperateLogService.java @@ -0,0 +1,22 @@ +package cn.xluobo.business.sys.log.service; + +import cn.xluobo.business.sys.log.repo.model.SysOperateLog; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 操作日志记录 服务类 + *

+ * + * @author zhangby + * @since 2021-04-20 + */ +public interface ISysOperateLogService extends IService { + + /** + * 异步保存日志 + * @param sysOperateLog + */ + void asyncSaveLog(SysOperateLog sysOperateLog); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/ISysUserLoginLogService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/ISysUserLoginLogService.java new file mode 100644 index 0000000..20641c6 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/ISysUserLoginLogService.java @@ -0,0 +1,26 @@ +package cn.xluobo.business.sys.log.service; + +import cn.xluobo.business.sys.log.repo.model.SysUserLoginLog; +import com.baomidou.mybatisplus.extension.service.IService; +import org.springframework.security.core.Authentication; + +import javax.servlet.http.HttpServletRequest; + +/** + *

+ * 登录日志 服务类 + *

+ * + * @author zhangby + * @since 2020-11-13 + */ +public interface ISysUserLoginLogService extends IService { + + /** + * 保存登录日志 + * @param request + * @param authentication + */ + void saveLoginLog(HttpServletRequest request, Authentication authentication); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/impl/SysOperateLogServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/impl/SysOperateLogServiceImpl.java new file mode 100644 index 0000000..091a857 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/impl/SysOperateLogServiceImpl.java @@ -0,0 +1,26 @@ +package cn.xluobo.business.sys.log.service.impl; + +import cn.xluobo.business.sys.log.repo.mapper.SysOperateLogMapper; +import cn.xluobo.business.sys.log.repo.model.SysOperateLog; +import cn.xluobo.business.sys.log.service.ISysOperateLogService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +/** + *

+ * 操作日志记录 服务实现类 + *

+ * + * @author zhangby + * @since 2021-04-20 + */ +@Service +public class SysOperateLogServiceImpl extends ServiceImpl implements ISysOperateLogService { + + @Override + @Async + public void asyncSaveLog(SysOperateLog sysOperateLog) { + this.save(sysOperateLog); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/impl/SysUserLoginLogServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/impl/SysUserLoginLogServiceImpl.java new file mode 100644 index 0000000..d24b1ee --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/log/service/impl/SysUserLoginLogServiceImpl.java @@ -0,0 +1,73 @@ +package cn.xluobo.business.sys.log.service.impl; + +import cn.xluobo.business.sys.log.repo.mapper.SysUserLoginLogMapper; +import cn.xluobo.business.sys.log.repo.model.SysUserLoginLog; +import cn.xluobo.business.sys.log.service.ISysUserLoginLogService; +import cn.xluobo.core.utils.ip.IpUtils; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.common.core.domain.model.LoginUser; +import eu.bitwalker.useragentutils.Browser; +import eu.bitwalker.useragentutils.OperatingSystem; +import eu.bitwalker.useragentutils.UserAgent; +import eu.bitwalker.useragentutils.Version; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; + +/** + *

+ * 登录日志 服务实现类 + *

+ * + * @author zhangby + * @since 2020-11-13 + */ +@Service +@Slf4j +public class SysUserLoginLogServiceImpl extends ServiceImpl implements ISysUserLoginLogService { + + @Override + public void saveLoginLog(HttpServletRequest request, Authentication authentication) { + try { + String ipAddress = IpUtils.getIpAddr(request); + //获取浏览器信息 + UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent")); + OperatingSystem operatingSystem = userAgent.getOperatingSystem(); + String operatingSystemName = operatingSystem.getName(); + Browser browser = userAgent.getBrowser(); + + StringBuffer info = new StringBuffer(operatingSystemName); + + if (null == browser) { + log.error("userAgent.getBrowser() is null"); + } else { + info.append(",").append(browser.getName()); + //获取浏览器版本号 + Version version = browser.getVersion(request.getHeader("User-Agent")); + if (null == version) { + log.error("browser.getVersion(request.getHeader(\"User-Agent\")) is null"); + } else { + info.append("/").append(version.getVersion()); + } + } + + log.info("login success ipAddress={},infoStr={}", ipAddress, info.toString()); + + Object principal = authentication.getPrincipal(); + if(principal instanceof LoginUser) { + LoginUser loginUser = (LoginUser)principal; + SysUserLoginLog loginLog = new SysUserLoginLog(); + loginLog.setUserId(loginUser.getUserId()); + loginLog.setUsername(loginUser.getUsername()); + loginLog.setName(loginUser.getUsername()); + loginLog.setLoginIp(ipAddress); + loginLog.setBrowserInfo(info.toString()); + this.save(loginLog); + } + } catch (Exception e) { + log.error("saveLoginLog error",e); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/controller/SysReceiptAccountController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/controller/SysReceiptAccountController.java new file mode 100644 index 0000000..5261faf --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/controller/SysReceiptAccountController.java @@ -0,0 +1,88 @@ +package cn.xluobo.business.sys.receipt.controller; + +import cn.xluobo.business.sys.receipt.domain.req.ReqSearchSysReceiptAccount; +import cn.xluobo.business.sys.receipt.repo.model.SysReceiptAccount; +import cn.xluobo.business.sys.receipt.service.BusinessSysReceiptAccountService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 收款账户 Controller + *

+ * + * @author zhangby + * @since 2020-09-05 05:36:25 + */ +@RestController +@RequestMapping("/api/sys/receipt") +public class SysReceiptAccountController { + @Autowired + private BusinessSysReceiptAccountService sysReceiptAccountService; + + /** + * 列表 + * + * @param reqSearchSysReceiptAccount + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchSysReceiptAccount reqSearchSysReceiptAccount) { + return sysReceiptAccountService.searchList(reqSearchSysReceiptAccount); + } + + /** + * 列表 + * + * @return + */ + @GetMapping("/list/select") + public APIResponse select() { + return sysReceiptAccountService.select(); + } + + /** + * 详情 + * + * @param accountId + * @return + */ + @GetMapping("/info/detailById/{accountId}") + public APIResponse detailById(@PathVariable("accountId") Long accountId) { + return sysReceiptAccountService.detailById(accountId); + } + + /** + * 添加 + * + * @param sysReceiptAccount + * @return + */ + @PostMapping("/add/addSysReceiptAccount") + public APIResponse addSysReceiptAccount(@RequestBody SysReceiptAccount sysReceiptAccount) { + return sysReceiptAccountService.addSysReceiptAccount(sysReceiptAccount); + } + + /** + * 修改 + * + * @param sysReceiptAccount + * @return + */ + @PutMapping("/update/updateSysReceiptAccount") + public APIResponse updateSysReceiptAccount(@RequestBody SysReceiptAccount sysReceiptAccount) { + return sysReceiptAccountService.updateSysReceiptAccount(sysReceiptAccount); + } + + /** + * 删除 + * + * @param accountIds + * @return + */ + @DeleteMapping("/delete/deleteById/{accountIds}") + public APIResponse deleteById(@PathVariable("accountIds") Long[] accountIds) { + return sysReceiptAccountService.deleteById(accountIds); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/domain/req/ReqSearchSysReceiptAccount.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/domain/req/ReqSearchSysReceiptAccount.java new file mode 100644 index 0000000..80f4ad6 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/domain/req/ReqSearchSysReceiptAccount.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.sys.receipt.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchSysReceiptAccount extends ReqPageBase implements Serializable { + private String accountName; + private String memo; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/repo/mapper/SysReceiptAccountMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/repo/mapper/SysReceiptAccountMapper.java new file mode 100644 index 0000000..b2ae0fb --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/repo/mapper/SysReceiptAccountMapper.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.sys.receipt.repo.mapper; + +import cn.xluobo.business.sys.receipt.repo.model.SysReceiptAccount; + +/** + *

+ * 收款账户 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-09-05 05:36:25 + */ +public interface SysReceiptAccountMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/repo/mapping/SysReceiptAccountMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/repo/mapping/SysReceiptAccountMapper.xml new file mode 100644 index 0000000..3e30d97 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/repo/mapping/SysReceiptAccountMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/repo/model/SysReceiptAccount.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/repo/model/SysReceiptAccount.java new file mode 100644 index 0000000..1bc94bf --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/repo/model/SysReceiptAccount.java @@ -0,0 +1,76 @@ +package cn.xluobo.business.sys.receipt.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 收款账户 + *

+ * + * @author zhangby + * @since 2020-09-05 05:36:25 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sys_receipt_account") +public class SysReceiptAccount implements Serializable { + + + /** + * 主键 + */ + @TableId(value = "account_id", type = IdType.ASSIGN_ID) + private Long accountId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 账户名称 + */ + @TableField("account_name") + private String accountName; + + /** + * 备注 + */ + @TableField("memo") + private String memo; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/service/BusinessSysReceiptAccountService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/service/BusinessSysReceiptAccountService.java new file mode 100644 index 0000000..64a8025 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/service/BusinessSysReceiptAccountService.java @@ -0,0 +1,130 @@ +package cn.xluobo.business.sys.receipt.service; + +import cn.xluobo.business.sys.receipt.domain.req.ReqSearchSysReceiptAccount; +import cn.xluobo.business.sys.receipt.repo.model.SysReceiptAccount; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessSysReceiptAccountService { + + @Autowired + private ISysReceiptAccountService sysReceiptAccountService; + + /** + * 查询 + * + * @param reqSearchSysReceiptAccount + * @return + */ + public APIResponse searchList(ReqSearchSysReceiptAccount reqSearchSysReceiptAccount) { + QueryWrapper qw = new QueryWrapper(); + if(StringUtils.isNotEmpty(reqSearchSysReceiptAccount.getAccountName())){ + qw.like("account_name",reqSearchSysReceiptAccount.getAccountName()); + } + if(StringUtils.isNotEmpty(reqSearchSysReceiptAccount.getMemo())){ + qw.eq("memo",reqSearchSysReceiptAccount.getMemo()); + } + RespPage page = new RespPage(reqSearchSysReceiptAccount.getPageNum(), reqSearchSysReceiptAccount.getPageSize()); + RespPage listPage = sysReceiptAccountService.page(page, qw); + return APIResponse.toAPIResponse(listPage); + } + + /** + * 前端select + * + * @return + */ + public APIResponse select() { + List receiptAccounts = sysReceiptAccountService.select(); + return APIResponse.toAPIResponse(receiptAccounts); + } + + + /** + * 详情 + * + * @param accountId + * @return + */ + public APIResponse detailById(Long accountId) { + if (null == accountId) { + return APIResponse.toAPIResponse(null); + } + SysReceiptAccount detailInfo = sysReceiptAccountService.getById(accountId); + return APIResponse.toAPIResponse(detailInfo); + } + + /** + * 添加 + * + * @param sysReceiptAccount + * @return + */ + public APIResponse addSysReceiptAccount(SysReceiptAccount sysReceiptAccount) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + sysReceiptAccount.setCreateUser(loginUser.getUserId()); + boolean addSysReceiptAccount = sysReceiptAccountService.save(sysReceiptAccount); + if (addSysReceiptAccount) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 更新 + * + * @param sysReceiptAccount + * @return + */ + public APIResponse updateSysReceiptAccount(SysReceiptAccount sysReceiptAccount) { + if (null == sysReceiptAccount.getAccountId()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + sysReceiptAccount.setLastUpdateUser(loginUser.getUserId()); + sysReceiptAccount.setLastUpdateTime(new Date()); + boolean updateSysReceiptAccount = sysReceiptAccountService.updateById(sysReceiptAccount); + if (updateSysReceiptAccount) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 删除 + * + * @param accountIds + * @return + */ + public APIResponse deleteById(Long[] accountIds) { + if (null == accountIds || accountIds.length == 0) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + boolean deleteSysReceiptAccount = sysReceiptAccountService.removeByIds(Arrays.asList(accountIds)); + if (deleteSysReceiptAccount) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/service/ISysReceiptAccountService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/service/ISysReceiptAccountService.java new file mode 100644 index 0000000..ee998fa --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/service/ISysReceiptAccountService.java @@ -0,0 +1,19 @@ +package cn.xluobo.business.sys.receipt.service; + +import cn.xluobo.business.sys.receipt.repo.model.SysReceiptAccount; + +import java.util.List; + +/** + *

+ * 收款账户 服务类 + *

+ * + * @author zhangby + * @since 2020-09-05 05:36:25 + */ +public interface ISysReceiptAccountService extends com.baomidou.mybatisplus.extension.service.IService { + + List select(); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/service/impl/SysReceiptAccountServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/service/impl/SysReceiptAccountServiceImpl.java new file mode 100644 index 0000000..7882ec8 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/receipt/service/impl/SysReceiptAccountServiceImpl.java @@ -0,0 +1,30 @@ +package cn.xluobo.business.sys.receipt.service.impl; + +import cn.xluobo.business.sys.receipt.repo.mapper.SysReceiptAccountMapper; +import cn.xluobo.business.sys.receipt.repo.model.SysReceiptAccount; +import cn.xluobo.business.sys.receipt.service.ISysReceiptAccountService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 收款账户 服务实现类 + *

+ * + * @author zhangby + * @since 2020-09-05 05:36:25 + */ +@Service +public class SysReceiptAccountServiceImpl extends ServiceImpl implements ISysReceiptAccountService { + + @Override + public List select() { + QueryWrapper qw = new QueryWrapper<>(); + qw.select("account_name", "account_id"); + qw.orderByDesc("account_id"); + return this.list(qw); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/controller/SysStaffController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/controller/SysStaffController.java new file mode 100644 index 0000000..eb9caf4 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/controller/SysStaffController.java @@ -0,0 +1,91 @@ +package cn.xluobo.business.sys.staff.controller; + +import cn.xluobo.business.sc.course.domain.req.ReqSelect; +import cn.xluobo.business.sys.staff.domain.req.ReqBusinessAddStaff; +import cn.xluobo.business.sys.staff.domain.req.ReqSearchStaff; +import cn.xluobo.business.sys.staff.service.BusinessSysStaffService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + *

+ * 教师信息 Controller + *

+ * + * @author zhangby + * @since 2020-03-17 11:27:37 + */ +@RestController +@RequestMapping("/api/sys/staff") +public class SysStaffController { + @Autowired + private BusinessSysStaffService sysStaffService; + + /** + * 列表 + * + * @param reqSearchSysStaff + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchStaff reqSearchSysStaff) { + return sysStaffService.searchList(reqSearchSysStaff); + } + + /** + * 前端select + * + * @return + */ + @GetMapping("/list/teacherSelect") + public APIResponse teacherSelect(ReqSelect reqSelect) { + return sysStaffService.teacherSelect(reqSelect); + } + + /** + * 详情 + * + * @param staffId + * @return + */ + @GetMapping("/info/detailById/{staffId}") + public APIResponse detailById(@PathVariable("staffId") Long staffId) { + return sysStaffService.detailById(staffId); + } + + /** + * 添加 + * + * @param reqBusinessAddStaff + * @return + */ + @PostMapping("/add/addSysStaff") + public APIResponse addSysStaff(@RequestBody ReqBusinessAddStaff reqBusinessAddStaff) { + return sysStaffService.addSysStaff(reqBusinessAddStaff); + } + + /** + * 修改 + * + * @param sysStaff + * @return + */ + @PutMapping("/update/updateSysStaff") + public APIResponse updateSysStaff(@RequestBody ReqBusinessAddStaff sysStaff) { + return sysStaffService.updateSysStaff(sysStaff); + } + + /** + * 删除 + * + * @param staffIds + * @return + */ + @DeleteMapping("/delete/deleteById/{staffIds}") + public APIResponse deleteById(@PathVariable("staffIds") List staffIds) { + return sysStaffService.deleteById(staffIds); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/req/ReqBusinessAddStaff.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/req/ReqBusinessAddStaff.java new file mode 100644 index 0000000..6943b02 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/req/ReqBusinessAddStaff.java @@ -0,0 +1,65 @@ +package cn.xluobo.business.sys.staff.domain.req; + +import cn.xluobo.business.sys.staff.repo.model.SysStaff; +import cn.xluobo.core.api.APIBaseResponse; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +/** + * 新增员工 + * + * @author :zhangbaoyu + * @date :Created in 2020/8/18 08:44 + */ +@Data +public class ReqBusinessAddStaff extends SysStaff { + + /** + * 是否为登录用户 + */ + private boolean loginUser; + + /** + * 是否允许登录 + */ + private String locked; + + /** + * 角色Id + */ + private Long[] roleIds; + + private String username; + + private String password; + + private String checkPass; + + /** + * 校区权限 所有 或 部分 all part + */ + private String belongCampus; + + /** + * 具体校区 + */ + private String[] partCampus; + + public APIBaseResponse checkParam() { + if (StringUtils.isAnyEmpty(getStaffName(), getPhone(), getSex())) { + return APIBaseResponse.fail("请求参数错误,请完善后重试"); + } + if (loginUser) { + if (StringUtils.isEmpty(belongCampus)) { + return APIBaseResponse.fail("请选择所属校区"); + } + if ("part".equals(belongCampus) && null == partCampus) { + return APIBaseResponse.fail("请选择所属校区"); + } + if ("part".equals(belongCampus) && partCampus.length == 0) { + return APIBaseResponse.fail("请选择所属校区"); + } + } + return APIBaseResponse.success(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/req/ReqSearchStaff.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/req/ReqSearchStaff.java new file mode 100644 index 0000000..6c78cd2 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/req/ReqSearchStaff.java @@ -0,0 +1,19 @@ +package cn.xluobo.business.sys.staff.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchStaff extends ReqPageBase implements Serializable { + private String staffName; + private String sex; + private String personnelStatus; + private Integer teacher; + private Long deptId; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/resp/RespBusinessStaffDetail.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/resp/RespBusinessStaffDetail.java new file mode 100644 index 0000000..5c314d5 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/resp/RespBusinessStaffDetail.java @@ -0,0 +1,34 @@ +package cn.xluobo.business.sys.staff.domain.resp; + +import cn.xluobo.business.sys.staff.repo.model.SysStaff; +import com.ruoyi.common.core.domain.entity.SysUser; +import lombok.Data; + +import java.util.List; + +/** + * 员工详情 + * @author :zhangbaoyu + * @date :Created in 2020/10/25 20:19 + */ +@Data +public class RespBusinessStaffDetail { + + // 所属校区 全部、部分 + private String belongCampus; + + // 所属校区 + private List partCampus; + + // 所属校区名称 + private List partCampusName; + + // 员工信息 + private SysStaff staffInfo; + + // 关联用户信息 + private SysUser userInfo; + + // 用户角色 + private List roleTreeIdList; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/resp/RespStaffInfo.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/resp/RespStaffInfo.java new file mode 100644 index 0000000..2da8770 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/domain/resp/RespStaffInfo.java @@ -0,0 +1,21 @@ +package cn.xluobo.business.sys.staff.domain.resp; + +import cn.xluobo.business.sys.staff.repo.model.SysStaff; +import lombok.Data; + +/** + * 员工信息 + * @author :zhangbaoyu + * @date :Created in 2020/8/18 11:03 + */ +@Data +public class RespStaffInfo extends SysStaff { + + private String username; + + private String locked; + + private String personnelStatusName; + + private String deptName; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/repo/mapper/SysStaffMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/repo/mapper/SysStaffMapper.java new file mode 100644 index 0000000..a01640c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/repo/mapper/SysStaffMapper.java @@ -0,0 +1,38 @@ +package cn.xluobo.business.sys.staff.repo.mapper; + +import cn.xluobo.business.sys.staff.domain.req.ReqSearchStaff; +import cn.xluobo.business.sys.staff.domain.resp.RespStaffInfo; +import cn.xluobo.business.sys.staff.repo.model.SysStaff; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.annotation.SqlParser; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 教师信息 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-03-17 11:27:37 + */ +public interface SysStaffMapper extends BaseMapper { + + /** + * 查询员工列表 + * @param reqSearchStaff + * @param page + * @return + */ + List selectStaffList(@Param("reqSearchStaff") ReqSearchStaff reqSearchStaff, @Param("page") RespPage page); + + /** + * 租户下员工数量 + * @param tenantId + * @return + */ + @SqlParser(filter = true) + Integer selectTenantStaffCount(String tenantId); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/repo/mapping/SysStaffMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/repo/mapping/SysStaffMapper.xml new file mode 100644 index 0000000..0136b64 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/repo/mapping/SysStaffMapper.xml @@ -0,0 +1,32 @@ + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/repo/model/SysStaff.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/repo/model/SysStaff.java new file mode 100644 index 0000000..1cfd455 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/repo/model/SysStaff.java @@ -0,0 +1,134 @@ +package cn.xluobo.business.sys.staff.repo.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 员工信息 + *

+ * + * @author zhangby + * @since 2020-03-17 11:27:37 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sys_staff") +public class SysStaff implements Serializable { + + + /** + * 教师id + */ + @TableId(value = "staff_id") + private Long staffId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + @TableField("user_id") + private Long userId; + + /** + * 机构管理者 + */ + @TableField("super_staff") + private Boolean superStaff; + + /** + * 员工姓名 + */ + @TableField("staff_name") + private String staffName; + + /** + * 联系电话 + */ + @TableField("phone") + private String phone; + + /** + * 邮箱 + */ + @TableField("email_address") + private String emailAddress; + + /** + * 性别 M男 F女 + */ + @TableField("sex") + private String sex; + + /** + * 入职日期 + */ + @TableField("entry_date") + private String entryDate; + + /** + * 人事状态 1正式员工 2实习员工 3试用期 4兼职员工 5停薪留职 6主动离职 7解聘 + */ + @TableField("personnel_status") + private String personnelStatus; + + /** + * 是否为教师 + */ + @TableField("teacher") + private Boolean teacher; + + /** + * 头像 + */ + @TableField("avatar_img") + private String avatarImg; + + /** + * 部门编号 + */ + @TableField("dept_id") + private Long deptId; + + /** + * 删除标志(1删除 0在用) + */ + @TableField("delete_flag") + @TableLogic + private String deleteFlag; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/service/BusinessSysStaffService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/service/BusinessSysStaffService.java new file mode 100644 index 0000000..71e98f7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/service/BusinessSysStaffService.java @@ -0,0 +1,384 @@ +package cn.xluobo.business.sys.staff.service; + +import cn.hutool.core.util.ObjectUtil; +import cn.xluobo.business.sc.course.domain.req.ReqSelect; +import cn.xluobo.business.sc.course.repo.model.ScClaTime; +import cn.xluobo.business.sc.course.repo.model.ScCourseCla; +import cn.xluobo.business.sc.course.service.IScClaTimeService; +import cn.xluobo.business.sc.course.service.IScCourseClaService; +import cn.xluobo.business.sys.admin.domain.req.ReqUpdateUserRole; +import cn.xluobo.business.sys.admin.model.SysUserDept; +import cn.xluobo.business.sys.admin.model.SysUserTenant; +import cn.xluobo.business.sys.admin.service.*; +import cn.xluobo.business.sys.staff.domain.req.ReqBusinessAddStaff; +import cn.xluobo.business.sys.staff.domain.req.ReqSearchStaff; +import cn.xluobo.business.sys.staff.domain.resp.RespBusinessStaffDetail; +import cn.xluobo.business.sys.staff.domain.resp.RespStaffInfo; +import cn.xluobo.business.sys.staff.repo.model.SysStaff; +import cn.xluobo.core.api.APIBaseResponse; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.apache.commons.compress.utils.Lists; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessSysStaffService { + + @Autowired + private ISysStaffService sysStaffService; + @Autowired + private ISysUserService userService; + @Autowired + private ISysRoleService sysRoleService; + @Autowired + private IScClaTimeService claTimeService; + @Autowired + private IScCourseClaService courseClaService; + @Autowired + private ISysUserDeptService userDeptService; + @Autowired + private ISysUserTenantService userTenantService; + + /** + * 查询 + * + * @param reqSearchSysStaff + * @return + */ + public APIResponse searchList(ReqSearchStaff reqSearchSysStaff) { + RespPage page = new RespPage(reqSearchSysStaff.getPageNum(), reqSearchSysStaff.getPageSize()); + List staffList = sysStaffService.searchStaffList(reqSearchSysStaff, page); + page.setRows(staffList); + return APIResponse.toAPIResponse(page); + } + + /** + * 前端select + * + * @return + */ + public APIResponse teacherSelect(ReqSelect reqSelect) { + List list = sysStaffService.teacherList(reqSelect.getSearch()); + return APIResponse.toAPIResponse(list); + } + + + /** + * 详情 + * + * @param teacherId + * @return + */ + public APIResponse detailById(Long teacherId) { + if (null == teacherId) { + return APIResponse.toAPIResponse(null); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + + RespBusinessStaffDetail respBusinessStaffDetail = new RespBusinessStaffDetail(); + + // 员工信息 + SysStaff staffInfo = sysStaffService.getById(teacherId); + respBusinessStaffDetail.setStaffInfo(staffInfo); + + // 用户名 + if (ObjectUtil.isNotEmpty(staffInfo.getUserId())) { + QueryWrapper qw = new QueryWrapper<>(); + qw.select("username", "locked"); + qw.eq("user_id", staffInfo.getUserId()); + SysUser sysUser = userService.getOne(qw); + if (null == sysUser) { + staffInfo.setUserId(null); + } + respBusinessStaffDetail.setUserInfo(sysUser); + + // 员工所属校区 + QueryWrapper qwUserDept = new QueryWrapper<>(); + qwUserDept.eq("user_id", staffInfo.getUserId()); + qwUserDept.eq("tenant_id", loginUser.getNowTenantId()); + List userDeptList = userDeptService.list(qwUserDept); + boolean allCampus = userDeptList.stream().anyMatch(item -> item.getDeptId() == -1L); + if (allCampus) { + respBusinessStaffDetail.setBelongCampus("all"); + respBusinessStaffDetail.setPartCampus(Lists.newArrayList()); + } else { + respBusinessStaffDetail.setBelongCampus("part"); + + List deptIdList = userDeptList.stream().map(SysUserDept::getDeptId).collect(Collectors.toList()); + respBusinessStaffDetail.setPartCampus(deptIdList); + } + + + // 用户角色 + List roleTreeIdList = sysRoleService.selectUserRoleTreeIdList(staffInfo.getUserId(), loginUser.getNowTenantId()); + respBusinessStaffDetail.setRoleTreeIdList(roleTreeIdList); + } else { + respBusinessStaffDetail.setUserInfo(null); + respBusinessStaffDetail.setRoleTreeIdList(Lists.newArrayList()); + respBusinessStaffDetail.setBelongCampus("all"); + respBusinessStaffDetail.setPartCampus(Lists.newArrayList()); + } + + return APIResponse.toAPIResponse(respBusinessStaffDetail); + } + + /** + * 添加员工 + * + * @param staff + * @return + */ + public APIResponse addSysStaff(ReqBusinessAddStaff staff) { + APIBaseResponse checkParam = staff.checkParam(); + if (!checkParam.isSuccess()) { + return APIResponse.toExceptionResponse(checkParam.getRespMsg()); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + boolean isLoginUser = staff.isLoginUser(); + // 保存用户信息 + if (isLoginUser) { + + if (StringUtils.isAnyEmpty(staff.getUsername(), staff.getPassword())) { + return APIResponse.toExceptionResponse(("请求参数错误,请完善后重试")); + } else if (!staff.getPassword().equals(staff.getCheckPass())) { + return APIResponse.toExceptionResponse(("新旧密码输入不一致,请稍后重试")); + } + // 校验账号是否已被注册 + boolean usernameUnique = userService.checkUsernameUnique(staff.getUsername()); + if (!usernameUnique) { + return APIResponse.toExceptionResponse(("用户名已被注册,请修改后重新提交")); + } + + // 添加用户 + SysUser sysUser = new SysUser(); + sysUser.setUserName(staff.getUsername()); + sysUser.setPassword(staff.getPassword()); + sysUser.setNickName(staff.getStaffName()); + sysUser.setPhonenumber(staff.getPhone()); + sysUser.setEmail(staff.getEmailAddress()); + sysUser.setDeptId(staff.getDeptId()); + + // 关联当前租户 + SysUserTenant sysUserTenant = new SysUserTenant(); + sysUserTenant.setUserId(sysUser.getUserId()); + sysUserTenant.setTenantId(loginUser.getNowTenantId()); + userTenantService.save(sysUserTenant); + + staff.setUserId(sysUser.getUserId()); + + // 保存角色信息 + ReqUpdateUserRole reqUpdateUserRole = new ReqUpdateUserRole(); + reqUpdateUserRole.setTenantId(loginUser.getNowTenantId()); + reqUpdateUserRole.setUserId(sysUser.getUserId()); + reqUpdateUserRole.setRoleIds(staff.getRoleIds()); + + // 所属校区 + String belongCampus = staff.getBelongCampus(); + if ("all".equals(belongCampus)) { + SysUserDept sysUserDept = new SysUserDept(); + sysUserDept.setUserId(sysUser.getUserId()); + sysUserDept.setDeptId(-1L); + sysUserDept.setTenantId(loginUser.getNowTenantId()); + userDeptService.save(sysUserDept); + } else if ("part".equals(belongCampus)) { + String[] partCampus = staff.getPartCampus(); + List userDeptList = Lists.newArrayList(); + for (String campus : partCampus) { + SysUserDept sysUserDept = new SysUserDept(); + sysUserDept.setUserId(sysUser.getUserId()); + sysUserDept.setDeptId(Long.valueOf(campus)); + sysUserDept.setTenantId(loginUser.getNowTenantId()); + userDeptList.add(sysUserDept); + } + if (userDeptList.size() > 0) { + userDeptService.saveBatch(userDeptList); + } + } + } + + // 保存员工信息 + staff.setCreateUser(loginUser.getUserId()); + boolean addSysStaff = sysStaffService.save(staff); + if (addSysStaff) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 更新 + * + * @param staff + * @return + */ + public APIResponse updateSysStaff(ReqBusinessAddStaff staff) { + if (null == staff.getStaffId()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + APIBaseResponse checkParam = staff.checkParam(); + if (!checkParam.isSuccess()) { + return APIResponse.toExceptionResponse(checkParam.getRespMsg()); + } + + LoginUser loginUser = SecurityUtils.getLoginUser(); + // 可登陆信息 + boolean isLoginUser = staff.isLoginUser(); + + SysStaff dbStaffInfo = sysStaffService.getById(staff.getStaffId()); + + if (ObjectUtil.isEmpty(dbStaffInfo.getUserId()) && isLoginUser) { + if (StringUtils.isAnyEmpty(staff.getUsername(), staff.getPassword())) { + return APIResponse.toExceptionResponse(("请求参数错误,请完善后重试")); + } else if (!staff.getPassword().equals(staff.getCheckPass())) { + return APIResponse.toExceptionResponse(("新旧密码输入不一致,请稍后重试")); + } + // 校验账号是否已被注册 + boolean usernameUnique = userService.checkUsernameUnique(staff.getUsername()); + if (!usernameUnique) { + return APIResponse.toExceptionResponse(("用户名已被注册,请修改后重新提交")); + } + } + + boolean addUser = false; + if (ObjectUtil.isNotEmpty(dbStaffInfo.getUserId())) { + addUser = true; + // 如果有关联用户 + + // 变更用户相关信息 + SysUser sysUser = new SysUser(); + sysUser.setUserId(dbStaffInfo.getUserId()); + sysUser.setUserName(staff.getStaffName()); + sysUser.setPhonenumber(staff.getPhone()); + sysUser.setEmail(staff.getEmailAddress()); + sysUser.setDeptId(staff.getDeptId()); + + // 变更角色信息 + ReqUpdateUserRole reqUpdateUserRole = new ReqUpdateUserRole(); + reqUpdateUserRole.setUserId(sysUser.getUserId()); + reqUpdateUserRole.setTenantId(loginUser.getNowTenantId()); + reqUpdateUserRole.setRoleIds(staff.getRoleIds()); + + // 不变更关联用户ID + staff.setUserId(dbStaffInfo.getUserId()); + } else if (ObjectUtil.isEmpty(dbStaffInfo.getUserId()) && isLoginUser) { + addUser = true; + // 没有关联用户 并且允许登录 + SysUser sysUser = new SysUser(); + sysUser.setUserName(staff.getUsername()); + sysUser.setPassword(staff.getPassword()); + sysUser.setNickName(staff.getStaffName()); + sysUser.setPhonenumber(staff.getPhone()); + sysUser.setEmail(staff.getEmailAddress()); + sysUser.setDeptId(staff.getDeptId()); + staff.setUserId(sysUser.getUserId()); + + // 保存角色信息 + ReqUpdateUserRole reqUpdateUserRole = new ReqUpdateUserRole(); + reqUpdateUserRole.setUserId(sysUser.getUserId()); + reqUpdateUserRole.setTenantId(loginUser.getNowTenantId()); + reqUpdateUserRole.setRoleIds(staff.getRoleIds()); + } + + if (addUser) { + // 删除原校区 + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("user_id", staff.getUserId()); + userDeptService.remove(uw); + // 所属校区 + String belongCampus = staff.getBelongCampus(); + if ("all".equals(belongCampus)) { + SysUserDept sysUserDept = new SysUserDept(); + sysUserDept.setUserId(staff.getUserId()); + sysUserDept.setDeptId(-1L); + sysUserDept.setTenantId(loginUser.getNowTenantId()); + userDeptService.save(sysUserDept); + } else if ("part".equals(belongCampus)) { + String[] partCampus = staff.getPartCampus(); + List userDeptList = Lists.newArrayList(); + for (String campus : partCampus) { + SysUserDept sysUserDept = new SysUserDept(); + sysUserDept.setUserId(staff.getUserId()); + sysUserDept.setDeptId(Long.valueOf(campus)); + sysUserDept.setTenantId(loginUser.getNowTenantId()); + userDeptList.add(sysUserDept); + } + if (userDeptList.size() > 0) { + userDeptService.saveBatch(userDeptList); + } + } + } + + + // 变更员工信息 + staff.setLastUpdateUser(loginUser.getUserId()); + staff.setLastUpdateTime(new Date()); + boolean updateSysStaff = sysStaffService.updateById(staff); + if (updateSysStaff) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 删除 + * + * @param teacherIds + * @return + */ + public APIResponse deleteById(List teacherIds) { + if (null == teacherIds || teacherIds.isEmpty()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + + // 已排课不允许删除 + QueryWrapper qwSct = new QueryWrapper<>(); + qwSct.in("teacher_id", teacherIds); + qwSct.eq("status", "1"); + int claTimeCount = claTimeService.count(qwSct); + if (claTimeCount != 0) { + return APIResponse.toExceptionResponse("员工有待上课程,无法删除"); + } + + // 是否为班级班主任 + QueryWrapper qw = new QueryWrapper<>(); + qw.in("staff_id", teacherIds); + int courseClaCount = courseClaService.count(qw); + if (courseClaCount != 0) { + return APIResponse.toExceptionResponse("员工当前为班级任课教师,无法删除"); + } + + + // 用户禁用 + List userIds = sysStaffService.getUserIds(teacherIds); + if (null != userIds && !userIds.isEmpty()) { + UpdateWrapper uw = new UpdateWrapper<>(); + uw.in("user_id", userIds); + uw.set("enable", "0"); + userService.update(uw); + } + + // 逻辑删除员工 + sysStaffService.removeByIds(teacherIds); + return APIResponse.toOkResponse(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/service/ISysStaffService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/service/ISysStaffService.java new file mode 100644 index 0000000..c878fa2 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/service/ISysStaffService.java @@ -0,0 +1,46 @@ +package cn.xluobo.business.sys.staff.service; + +import cn.xluobo.business.sys.staff.domain.req.ReqSearchStaff; +import cn.xluobo.business.sys.staff.domain.resp.RespStaffInfo; +import cn.xluobo.business.sys.staff.repo.model.SysStaff; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 教师信息 服务类 + *

+ * + * @author zhangby + * @since 2020-03-17 11:27:37 + */ +public interface ISysStaffService extends IService { + + List searchStaffList(ReqSearchStaff reqSearchStaff, RespPage page); + + /** + * 教师列表 + * @param teacherName + * @return + */ + List teacherList(String teacherName); + + /** + * 员工列表 + * @param staffName + * @return + */ + List staffList(String staffName); + + /** + * 获取关联用户id + * @param staffIds + * @return + */ + List getUserIds(List staffIds); + + // 根据用户获取 + Long getStaffIdByUserId(Long userId); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/service/impl/SysStaffServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/service/impl/SysStaffServiceImpl.java new file mode 100644 index 0000000..e4cd433 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/staff/service/impl/SysStaffServiceImpl.java @@ -0,0 +1,77 @@ +package cn.xluobo.business.sys.staff.service.impl; + +import cn.xluobo.business.sys.staff.domain.req.ReqSearchStaff; +import cn.xluobo.business.sys.staff.domain.resp.RespStaffInfo; +import cn.xluobo.business.sys.staff.repo.mapper.SysStaffMapper; +import cn.xluobo.business.sys.staff.repo.model.SysStaff; +import cn.xluobo.business.sys.staff.service.ISysStaffService; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 教师信息 服务实现类 + *

+ * + * @author zhangby + * @since 2020-03-17 11:27:37 + */ +@Service +public class SysStaffServiceImpl extends ServiceImpl implements ISysStaffService { + + @Override + public List searchStaffList(ReqSearchStaff reqSearchStaff, RespPage page) { + return baseMapper.selectStaffList(reqSearchStaff, page); + } + + @Override + public List teacherList(String teacherName) { + QueryWrapper qw = new QueryWrapper<>(); + qw.select("staff_name", "staff_id"); + qw.eq("teacher", "1"); + if (StringUtils.isNotEmpty(teacherName)) { + qw.like("staff_name", teacherName); + } + qw.orderByAsc("staff_name"); + return this.list(qw); + } + + @Override + public List staffList(String staffName) { + QueryWrapper qw = new QueryWrapper<>(); + qw.select("staff_name", "staff_id"); + if (StringUtils.isNotEmpty(staffName)) { + qw.like("staff_name", staffName); + } + qw.orderByAsc("staff_name"); + return this.list(qw); + } + + @Override + public List getUserIds(List staffIds) { + QueryWrapper qw = new QueryWrapper<>(); + qw.select("user_id"); + qw.in("staff_id", staffIds); + qw.isNotNull("user_id"); + List staffList = this.list(qw); + List userIds = staffList.stream().map(SysStaff::getUserId).collect(Collectors.toList()); + return userIds; + } + + @Override + public Long getStaffIdByUserId(Long userId) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("user_id", userId); + SysStaff sysStaff = this.getOne(qw); + if (null != sysStaff) { + return sysStaff.getStaffId(); + } + return null; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/controller/SysTagController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/controller/SysTagController.java new file mode 100644 index 0000000..569862e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/controller/SysTagController.java @@ -0,0 +1,78 @@ +package cn.xluobo.business.sys.tag.controller; + +import cn.xluobo.business.sys.tag.domain.req.ReqSearchSysTag; +import cn.xluobo.business.sys.tag.repo.model.SysTag; +import cn.xluobo.business.sys.tag.service.BusinessSysTagService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 标签 Controller + *

+ * + * @author zhangby + * @since 2020-09-03 03:08:13 + */ +@RestController +@RequestMapping("/api/sys/tag") +public class SysTagController { + @Autowired + private BusinessSysTagService sysTagService; + + /** + * 列表 + * + * @param reqSearchSysTag + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchSysTag reqSearchSysTag) { + return sysTagService.searchList(reqSearchSysTag); + } + + /** + * 详情 + * + * @param tagId + * @return + */ + @GetMapping("/info/detailById/{tagId}") + public APIResponse detailById(@PathVariable("tagId") Long tagId) { + return sysTagService.detailById(tagId); + } + + /** + * 添加 + * + * @param sysTag + * @return + */ + @PostMapping("/add/addSysTag") + public APIResponse addSysTag(@RequestBody SysTag sysTag) { + return sysTagService.addSysTag(sysTag); + } + + /** + * 修改 + * + * @param sysTag + * @return + */ + @PutMapping("/update/updateSysTag") + public APIResponse updateSysTag(@RequestBody SysTag sysTag) { + return sysTagService.updateSysTag(sysTag); + } + + /** + * 删除 + * + * @param tagIds + * @return + */ + @DeleteMapping("/delete/deleteById/{tagIds}") + public APIResponse deleteById(@PathVariable("tagIds") Long[] tagIds) { + return sysTagService.deleteById(tagIds); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/domain/req/ReqSearchSysTag.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/domain/req/ReqSearchSysTag.java new file mode 100644 index 0000000..e7bb89a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/domain/req/ReqSearchSysTag.java @@ -0,0 +1,17 @@ +package cn.xluobo.business.sys.tag.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchSysTag extends ReqPageBase implements Serializable { + private String tenantId; + private String tagName; + private String tagType; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/repo/mapper/SysTagMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/repo/mapper/SysTagMapper.java new file mode 100644 index 0000000..3d07eac --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/repo/mapper/SysTagMapper.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.sys.tag.repo.mapper; + +import cn.xluobo.business.sys.tag.repo.model.SysTag; + +/** + *

+ * 标签 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-09-03 03:08:13 + */ +public interface SysTagMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/repo/mapping/SysTagMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/repo/mapping/SysTagMapper.xml new file mode 100644 index 0000000..2342c2e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/repo/mapping/SysTagMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/repo/model/SysTag.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/repo/model/SysTag.java new file mode 100644 index 0000000..511aefb --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/repo/model/SysTag.java @@ -0,0 +1,76 @@ +package cn.xluobo.business.sys.tag.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 标签 + *

+ * + * @author zhangby + * @since 2020-09-03 03:08:13 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("sys_tag") +public class SysTag implements Serializable { + + + /** + * 主键 + */ + @TableId(value = "tag_id", type = IdType.ASSIGN_ID) + private Long tagId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 标签名称 + */ + @TableField("tag_name") + private String tagName; + + /** + * 标签类型 + */ + @TableField("tag_type") + private String tagType; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/service/BusinessSysTagService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/service/BusinessSysTagService.java new file mode 100644 index 0000000..75fd78a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/service/BusinessSysTagService.java @@ -0,0 +1,122 @@ +package cn.xluobo.business.sys.tag.service; + +import cn.xluobo.business.sys.tag.domain.req.ReqSearchSysTag; +import cn.xluobo.business.sys.tag.repo.model.SysTag; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.Date; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessSysTagService { + + @Autowired + private ISysTagService sysTagService; + + /** + * 查询 + * + * @param reqSearchSysTag + * @return + */ + public APIResponse searchList(ReqSearchSysTag reqSearchSysTag) { + QueryWrapper qw = new QueryWrapper(); + qw.select("tag_id", "tag_name", "tag_type", "create_time"); + if (StringUtils.isNotEmpty(reqSearchSysTag.getTenantId())) { + qw.eq("tenant_id", reqSearchSysTag.getTenantId()); + } + if (StringUtils.isNotEmpty(reqSearchSysTag.getTagName())) { + qw.like("tag_name", reqSearchSysTag.getTagName()); + } + if (StringUtils.isNotEmpty(reqSearchSysTag.getTagType())) { + qw.eq("tag_type", reqSearchSysTag.getTagType()); + } + RespPage page = new RespPage(reqSearchSysTag.getPageNum(), reqSearchSysTag.getPageSize()); + RespPage listPage = sysTagService.page(page, qw); + return APIResponse.toAPIResponse(listPage); + } + + /** + * 详情 + * + * @param tagId + * @return + */ + public APIResponse detailById(Long tagId) { + if (null == tagId) { + return APIResponse.toAPIResponse(null); + } + SysTag detailInfo = sysTagService.getById(tagId); + return APIResponse.toAPIResponse(detailInfo); + } + + /** + * 添加 + * + * @param sysTag + * @return + */ + public APIResponse addSysTag(SysTag sysTag) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + sysTag.setCreateUser(loginUser.getUserId()); + boolean addSysTag = sysTagService.save(sysTag); + if (addSysTag) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 更新 + * + * @param sysTag + * @return + */ + public APIResponse updateSysTag(SysTag sysTag) { + if (null == sysTag.getTagId()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + sysTag.setLastUpdateUser(loginUser.getUserId()); + sysTag.setLastUpdateTime(new Date()); + boolean updateSysTag = sysTagService.updateById(sysTag); + if (updateSysTag) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 删除 + * + * @param tagIds + * @return + */ + public APIResponse deleteById(Long[] tagIds) { + if (null == tagIds || tagIds.length == 0) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + boolean deleteSysTag = sysTagService.removeByIds(Arrays.asList(tagIds)); + if (deleteSysTag) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/service/ISysTagService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/service/ISysTagService.java new file mode 100644 index 0000000..28b8cc9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/service/ISysTagService.java @@ -0,0 +1,25 @@ +package cn.xluobo.business.sys.tag.service; + +import cn.xluobo.business.sys.tag.repo.model.SysTag; + +/** + *

+ * 标签 服务类 + *

+ * + * @author zhangby + * @since 2020-09-03 03:08:13 + */ +public interface ISysTagService extends com.baomidou.mybatisplus.extension.service.IService { + + /** + * 校验是否存在 如果不存在则创建 + * + * @param tags + * @param tagType + * @param tenantId + * @param userId + */ + void autoCreateTag(String[] tags, String tagType, Long tenantId, Long userId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/service/impl/SysTagServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/service/impl/SysTagServiceImpl.java new file mode 100644 index 0000000..a9cadec --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/tag/service/impl/SysTagServiceImpl.java @@ -0,0 +1,38 @@ +package cn.xluobo.business.sys.tag.service.impl; + +import cn.xluobo.business.sys.tag.repo.mapper.SysTagMapper; +import cn.xluobo.business.sys.tag.repo.model.SysTag; +import cn.xluobo.business.sys.tag.service.ISysTagService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 标签 服务实现类 + *

+ * + * @author zhangby + * @since 2020-09-03 03:08:13 + */ +@Service +public class SysTagServiceImpl extends ServiceImpl implements ISysTagService { + + @Override + public void autoCreateTag(String[] tags, String tagType, Long tenantId, Long userId) { + for (String tag : tags) { + QueryWrapper qw = new QueryWrapper(); + qw.eq("tenant_id", tenantId); + qw.eq("tag_name", tag); + qw.eq("tag_type", tagType); + int count = this.count(qw); + if (count == 0 ){ + SysTag sysTag = new SysTag(); + sysTag.setTagName(tag); + sysTag.setTagType(tagType); + sysTag.setCreateUser(userId); + this.save(sysTag); + } + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/domain/ExportBaseBean.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/domain/ExportBaseBean.java new file mode 100644 index 0000000..da2a328 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/domain/ExportBaseBean.java @@ -0,0 +1,11 @@ +package cn.xluobo.business.tool.export.domain; + +/** + * 导出excel 一对多 一合并 + * @author :zhangbaoyu + * @date :Created in 2020/7/30 13:41 + */ +public abstract class ExportBaseBean { + + public abstract String getPrimaryId(); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/handler/SelectWriteHandler.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/handler/SelectWriteHandler.java new file mode 100644 index 0000000..9fb277a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/handler/SelectWriteHandler.java @@ -0,0 +1,74 @@ +package cn.xluobo.business.tool.export.handler; + +import cn.xluobo.business.tool.export.handler.bean.SelectValidationData; +import com.alibaba.excel.write.handler.SheetWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; +import com.google.common.collect.Maps; +import org.apache.poi.ss.usermodel.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationConstraint; +import org.apache.poi.ss.usermodel.DataValidationHelper; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.util.CellRangeAddressList; + +import java.util.List; +import java.util.Map; + +/** + * 下拉菜单 + * + * @author :zhangbaoyu + * @date :Created in 2020/8/2 18:23 + */ +public class SelectWriteHandler implements SheetWriteHandler { + + /** + * 单元格 下拉配置 + */ + private List validationDataList; + + public SelectWriteHandler(List validationDataList) { + this.validationDataList = validationDataList; + } + + @Override + public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { + + } + + @Override + public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { + + if (null != validationDataList && validationDataList.size() > 0) { + + Map createRowCacheMap = Maps.newHashMap(); + + Sheet shtDictionary = writeWorkbookHolder.getWorkbook().createSheet("ShtDictionary"); + for (SelectValidationData selectValidationData : validationDataList) { + String[] selectDataArray = selectValidationData.getSelectDataArray(); + if(selectDataArray.length == 0) { + continue; + } + int firstCol = selectValidationData.getFirstCol(); + for (int i = 0; i < selectDataArray.length; i++) { + if (createRowCacheMap.containsKey(i)) { + shtDictionary.getRow(i).createCell(firstCol).setCellValue(selectDataArray[i]); + } else { + shtDictionary.createRow(i).createCell(firstCol).setCellValue(selectDataArray[i]); + createRowCacheMap.put(i,i); + } + } + CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(selectValidationData.getFirstRow(), selectValidationData.getLastRow(), selectValidationData.getFirstCol(), selectValidationData.getLastCol()); + + String letterIndex = String.valueOf((char) (65 + firstCol)); + String formula = "ShtDictionary!$" + letterIndex + "$1:$" + letterIndex + "$" + selectDataArray.length; + DataValidationHelper dvHelper = writeWorkbookHolder.getWorkbook().getSheet("ShtDictionary").getDataValidationHelper(); + DataValidationConstraint formulaListConstraint = dvHelper.createFormulaListConstraint(formula); + DataValidation columnValidation = dvHelper.createValidation(formulaListConstraint, cellRangeAddressList); + writeSheetHolder.getSheet().addValidationData(columnValidation); + } + writeWorkbookHolder.getWorkbook().setSheetHidden(writeWorkbookHolder.getWorkbook().getSheetIndex("ShtDictionary"), true); + + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/handler/bean/SelectValidationData.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/handler/bean/SelectValidationData.java new file mode 100644 index 0000000..37e48ec --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/handler/bean/SelectValidationData.java @@ -0,0 +1,47 @@ +package cn.xluobo.business.tool.export.handler.bean; + +import lombok.Builder; +import lombok.Data; + +/** + * 单元格增加下拉菜单 参数 + * @author :zhangbaoyu + * @date :Created in 2020/8/2 18:46 + */ +@Data +@Builder +public class SelectValidationData { + + /** + * 从第几行开始 + */ + private int firstRow; + + /** + * 到第几行 + */ + private int lastRow; + + /** + * 第几列开始 + */ + private int firstCol; + + /** + * 到第几列 + */ + private int lastCol; + + /** + * 下拉菜单数据 + */ + private String[] selectDataArray; + + public SelectValidationData(int firstRow, int lastRow, int firstCol, int lastCol, String[] selectDataArray) { + this.firstRow = firstRow; + this.lastRow = lastRow; + this.firstCol = firstCol; + this.lastCol = lastCol; + this.selectDataArray = selectDataArray; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/strategy/CourseExportMergeStrategy.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/strategy/CourseExportMergeStrategy.java new file mode 100644 index 0000000..f52c0f5 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/export/strategy/CourseExportMergeStrategy.java @@ -0,0 +1,72 @@ +package cn.xluobo.business.tool.export.strategy; + +import cn.xluobo.business.tool.export.domain.ExportBaseBean; +import com.alibaba.excel.write.handler.AbstractRowWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.util.CellRangeAddress; + +import java.util.List; + +/** + * 导出合并单元格策略 + * 一对多 合并时需要 + * + * @author :zhangbaoyu + * @date :Created in 2020/7/30 13:37 + */ +public class CourseExportMergeStrategy extends AbstractRowWriteHandler { + + private List exportBeanList; + + private int startColumn = 0; + + private int endColumn = 0; + + public CourseExportMergeStrategy(List exportBeanList, int startColumn, int endColumn) { + this.exportBeanList = exportBeanList; + this.startColumn = startColumn; + this.endColumn = endColumn; + } + + @Override + public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) { + if (exportBeanList.isEmpty() || startColumn < 0 || endColumn < 0){ + return; + } + if(isHead){ + return; + } + if(relativeRowIndex firstRow) { + while (startColumn <= endColumn) { + writeSheetHolder.getSheet().addMergedRegionUnsafe(new CellRangeAddress(firstRow + headRows, endRow + headRows, startColumn, startColumn)); + startColumn ++; + } + startColumn = 0; + } + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/gen/domain/req/ReqSearchToolGenTable.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/gen/domain/req/ReqSearchToolGenTable.java new file mode 100644 index 0000000..9b12139 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/gen/domain/req/ReqSearchToolGenTable.java @@ -0,0 +1,19 @@ +package cn.xluobo.business.tool.gen.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchToolGenTable extends ReqPageBase implements Serializable { + + private String tableName; + private String tableComment; + private String beginTime; + private String endTime; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/controller/ImportController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/controller/ImportController.java new file mode 100644 index 0000000..66960be --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/controller/ImportController.java @@ -0,0 +1,61 @@ +package cn.xluobo.business.tool.impt.controller; + +import cn.xluobo.business.tool.impt.domain.ReqDownImplTemplate; +import cn.xluobo.business.tool.impt.domain.ReqUploadImplData; +import cn.xluobo.business.tool.impt.service.BusinessImportService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; + +/** + * 导入 + * @author :zhangbaoyu + * @date :Created in 2020/8/2 17:41 + */ +@RestController +@RequestMapping("/api/tool/import") +public class ImportController { + + @Autowired + private BusinessImportService importService; + + + /** + * 下载导入模板 + * @param downImplTemplate + * @return + */ + @GetMapping("/downImportTemplate") + public void downImportTemplate(ReqDownImplTemplate downImplTemplate) throws IOException { + importService.downImportTemplate(downImplTemplate); + } + + /** + * 导入文件 + * @param uploadImplData + */ + @PostMapping("/uploadForImportData") + public APIResponse uploadForImportData(ReqUploadImplData uploadImplData){ + return importService.uploadForImportData(uploadImplData); + } + + /** + * 校验文件 + * @param uploadImplData + */ + @PostMapping("/uploadForCheckData") + public APIResponse uploadForCheckData(ReqUploadImplData uploadImplData){ + return importService.uploadForCheckData(uploadImplData); + } + + /** + * 校验文件 + * @param uploadImplData + */ + @PostMapping("/uploadForImportDataByFileId") + public APIResponse uploadForImportDataByFileId(@RequestBody ReqUploadImplData uploadImplData){ + return importService.uploadForImportDataByFileId(uploadImplData); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportBase.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportBase.java new file mode 100644 index 0000000..d29e369 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportBase.java @@ -0,0 +1,12 @@ +package cn.xluobo.business.tool.impt.domain; + +import lombok.Data; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/10/11 10:31 + */ +@Data +public class ImportBase { + private String failMsg; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportCourse.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportCourse.java new file mode 100644 index 0000000..f4f3bf6 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportCourse.java @@ -0,0 +1,54 @@ +package cn.xluobo.business.tool.impt.domain; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 导入课程 + * @author :zhangbaoyu + * @date :Created in 2020/8/3 21:43 + */ +@Data +@ExcelIgnoreUnannotated +public class ImportCourse { + + // A列 课程名称 + @ExcelProperty(index = 0) + private String courseName; + + @ExcelProperty(index = 1) + private String courseTypeName; + + @ExcelProperty(index = 2) + private String teachingMode; + + @ExcelProperty(index = 3) + private String courseIntro; + + // E列 是否开售 + @ExcelProperty(index = 4) + private String sale; + + // F列 开课校区 + @ExcelProperty(index = 5) + private String departName; + + // 收费模式 + @ExcelProperty(index = 6) + private String chargeType; + + // H 包含课时数 + @ExcelProperty(index = 7) + private BigDecimal count; + + // I 学费标准 + @ExcelProperty(index = 8) + private BigDecimal totalFee; + + // J 时间周期 + @ExcelProperty(index = 9) + private String dateUnit; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportCourseCla.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportCourseCla.java new file mode 100644 index 0000000..6247f82 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportCourseCla.java @@ -0,0 +1,90 @@ +package cn.xluobo.business.tool.impt.domain; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 导入班级 + * @author :zhangbaoyu + * @date :Created in 2020/10/10 16:46 + */ +@Data +@ExcelIgnoreUnannotated +public class ImportCourseCla extends ImportBase{ + + // A列 班级名称 + @ExcelProperty(index = 0) + private String claName; + + // B列 课程名称 + @ExcelProperty(index = 1) + private String courseName; + + // C列 校区名 + @ExcelProperty(index = 2) + private String deptName; + + // D列 任课教师 + @ExcelProperty(index = 3) + private String teacherName; + + // E列 满班人数 + @ExcelProperty(index = 4) + private String capacity; + + // F列 招生状态 + @ExcelProperty(index = 5) + private String recruitStatus; + + // G列 每次上课学员扣除课时 + @ExcelProperty(index = 6) + private String everyStuLoseHour; + + // H列 开班日期 + @ExcelProperty(index = 7) + private String openDate; + + // I列 结班日期 + @ExcelProperty(index = 8) + private String closeDate; + + // J列 备注 + @ExcelProperty(index = 9) + private String memo; + + // K列 排课开始日期 + @ExcelProperty(index = 10) + private String beginDate; + + // L列 排课结束日期 + @ExcelProperty(index = 11) + private String endDate; + + // M列 排课重复方式 + @ExcelProperty(index = 12) + private String repeatType; + + // N列 上课星期 + @ExcelProperty(index = 13) + private String weekDay; + + // O列 是否过滤节假日 + @ExcelProperty(index = 14) + private String filterHoliday; + + // P列 上课时间 + @ExcelProperty(index = 15) + private String startTime; + + // Q列 下课时间 + @ExcelProperty(index = 16) + private String endTime; + + // R列 上课教室 + @ExcelProperty(index = 17) + private String roomName; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportStudentOrder.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportStudentOrder.java new file mode 100644 index 0000000..7959867 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ImportStudentOrder.java @@ -0,0 +1,103 @@ +package cn.xluobo.business.tool.impt.domain; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +/** + * 学生订单导入 + * @author :zhangbaoyu + * @date :Created in 2020/10/12 16:08 + */ +@Data +@ExcelIgnoreUnannotated +public class ImportStudentOrder extends ImportBase{ + + // A列 学生姓名 + @ExcelProperty(index = 0) + private String studentName; + + // B列 主要联系人关系 + @ExcelProperty(index = 1) + private String contactRelation; + + // C列 联系电话 + @ExcelProperty(index = 2) + private String contactPhone; + + // D列 性别 + @ExcelProperty(index = 3) + private String sex; + + // E列 学校 + @ExcelProperty(index = 4) + private String schoolName; + + // F列 入校时间 + @ExcelProperty(index = 5) + private String inTime; + + // G列 订单类型 + @ExcelProperty(index = 6) + private String orderDetailTag; + + // H列 报读校区 + @ExcelProperty(index = 7) + private String deptName; + + // I列 报读课程 + @ExcelProperty(index = 8) + private String courseName; + + // J列 报读班级 + @ExcelProperty(index = 9) + private String claName; + + // K列 购买课时 + @ExcelProperty(index = 10) + private String buyHour; + + // L列 剩余课时 + @ExcelProperty(index = 11) + private String balanceHour; + + // M列 按时间缴费开始日期 + @ExcelProperty(index = 12) + private String beginDate; + + // N列 按时间缴费 购买数量 + @ExcelProperty(index = 13) + private String buyCount; + + // O列 实缴学费(收款金额) + @ExcelProperty(index = 14) + private String receiptFee; + + // P列 应收学费 + @ExcelProperty(index = 15) + private String actualFee; + + // Q列 经办校区 + @ExcelProperty(index = 16) + private String handleDeptName; + + // R列 经办日期 + @ExcelProperty(index = 17) + private String handleDate; + + // S列 课程到期日期 + @ExcelProperty(index = 18) + private String expireDate; + + // T列 收款账户 + @ExcelProperty(index = 19) + private String accountName; + + // U列 销售员工 + @ExcelProperty(index = 20) + private String saleStaffName; + + // V列 订单备注 + @ExcelProperty(index = 21) + private String memo; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ReqDownImplTemplate.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ReqDownImplTemplate.java new file mode 100644 index 0000000..61756b1 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ReqDownImplTemplate.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.tool.impt.domain; + +import lombok.Data; + +/** + * 下载导入模板 + * @author :zhangbaoyu + * @date :Created in 2020/8/2 17:42 + */ +@Data +public class ReqDownImplTemplate { + + private String templateName; + + /** + * 导出文件名 + */ + private String logicFileName; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ReqUploadImplData.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ReqUploadImplData.java new file mode 100644 index 0000000..bfe9f9c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/domain/ReqUploadImplData.java @@ -0,0 +1,27 @@ +package cn.xluobo.business.tool.impt.domain; + +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +/** + * 上传导入数据 + * @author :zhangbaoyu + * @date :Created in 2020/8/3 21:16 + */ +@Data +public class ReqUploadImplData { + + /** + * 模板名称 + */ + private String templateName; + + /** + * 文件 + */ + private MultipartFile file; + + private Long importId; + + private String fileId; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/listener/ImportCourseClaListener.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/listener/ImportCourseClaListener.java new file mode 100644 index 0000000..7dee584 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/listener/ImportCourseClaListener.java @@ -0,0 +1,258 @@ +package cn.xluobo.business.tool.impt.listener; + +import cn.hutool.core.util.ObjectUtil; +import cn.xluobo.business.sc.course.repo.enums.ClaTimeRepeatTypeEnums; +import cn.xluobo.business.sc.course.repo.enums.ClaTimeRuleTypeEnums; +import cn.xluobo.business.sc.course.repo.model.ScClaTimeRule; +import cn.xluobo.business.sc.course.repo.model.ScCourseCla; +import cn.xluobo.business.sc.course.service.BusinessClaTimeRuleService; +import cn.xluobo.business.sc.course.service.IScCourseClaService; +import cn.xluobo.business.tool.impt.domain.ImportCourseCla; +import cn.xluobo.core.api.APIBaseResponse; +import cn.xluobo.core.utils.DateUtil; +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.google.common.collect.Lists; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/8/3 22:02 + */ +@Slf4j +@Data +public class ImportCourseClaListener extends AnalysisEventListener { + + private IScCourseClaService courseClaService; + + private BusinessClaTimeRuleService businessClaTimeRuleService; + + /** + * 是否需要保存 + */ + private Boolean needSave; + + private Map courseMap; + private Map campusMap; + private Map teacherMap; + private Map recruitStatusMap; + private Map claTimeRepeatTypeMap; + private Map roomMap; + private Map weekDayMap; + + // 登录用户id + private Long loginUserId = 0L; + + // 导入id + private Long importId; + + // 需保存的saveCourseClaList + private List saveCourseClaList = Lists.newArrayList(); + + // 校验失败的列表 + private List failCourseClaList = Lists.newArrayList(); + + /** + * 最多读取多少行 + */ + int maxRecord = 100; + + /** + * 当前已读取 + */ + int hadReadRecord = 0; + + public ImportCourseClaListener(IScCourseClaService courseClaService, BusinessClaTimeRuleService businessClaTimeRuleService) { + this.courseClaService = courseClaService; + this.businessClaTimeRuleService = businessClaTimeRuleService; + } + + @Override + public void invoke(ImportCourseCla data, AnalysisContext context) { + APIBaseResponse checkParam = checkParam(data); + if (!checkParam.isSuccess()) { + data.setFailMsg(checkParam.getRespMsg()); + failCourseClaList.add(data); + return; + } + saveCourseClaList.add(data); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + if (needSave) { + saveCourseCla(); + } + log.info("doAfterAllAnalysed"); + } + + @Override + public boolean hasNext(AnalysisContext context) { + if (hadReadRecord++ < maxRecord) { + return true; + } + return false; + } + + /** + * 保存班级信息 + */ + public void saveCourseCla() { + for (ImportCourseCla courseCla : saveCourseClaList) { + + Long courseId = courseMap.get(courseCla.getCourseName()); + Long deptId = campusMap.get(courseCla.getDeptName()); + Long teacherId = teacherMap.get(courseCla.getTeacherName()); + String recruitStatus = recruitStatusMap.get(courseCla.getRecruitStatus()); + + // 保存课程信息 + ScCourseCla cla = new ScCourseCla(); + cla.setCourseId(courseId); + cla.setDepartId(Long.valueOf(deptId)); + cla.setStaffId(teacherId); + cla.setClaName(courseCla.getClaName()); + cla.setCapacity(Integer.parseInt(courseCla.getCapacity())); + cla.setRecruitStatus(recruitStatus); + cla.setEveryStuLoseHour(new BigDecimal(courseCla.getEveryStuLoseHour())); + cla.setOpenDate(courseCla.getOpenDate()); + cla.setCloseDate(courseCla.getCloseDate()); + cla.setMemo(courseCla.getMemo()); + cla.setCreateUser(loginUserId); + courseClaService.save(cla); + + // 规则排课 + if (StringUtils.isNoneEmpty(courseCla.getBeginDate(), courseCla.getEndDate())) { + Long roomId = null; + if (StringUtils.isNotEmpty(courseCla.getRoomName())) { + roomId = teacherMap.get(courseCla.getRoomName()); + } + String repeatType = claTimeRepeatTypeMap.get(courseCla.getRepeatType()); + // 保存规则排课信息 并生成排课信息 + ScClaTimeRule claTimeRule = new ScClaTimeRule(); + claTimeRule.setClaId(cla.getClaId()); + claTimeRule.setRuleType(ClaTimeRuleTypeEnums.REPEAT_RULE.getRuleType()); + claTimeRule.setBeginDate(courseCla.getBeginDate()); + claTimeRule.setEndDate(courseCla.getEndDate()); + claTimeRule.setRepeatType(repeatType); + + if (ClaTimeRepeatTypeEnums.EVERY_WEEK.getRepeatType().equals(repeatType) + || ClaTimeRepeatTypeEnums.EVERY_SECOND_WEEK.getRepeatType().equals(repeatType)) { + List weekDayKeyList = Lists.newArrayList(); + String weekDay = courseCla.getWeekDay(); + String[] weekDayArray = weekDay.split(","); + for (String item : weekDayArray) { + String weekDayKey = weekDayMap.get(item); + weekDayKeyList.add(weekDayKey); + } + claTimeRule.setWeekDay(String.join(",", weekDayKeyList)); + } + + claTimeRule.setFilterHoliday("过滤".equals(courseCla.getFilterHoliday())); + claTimeRule.setStartTime(courseCla.getStartTime()); + claTimeRule.setEndTime(courseCla.getEndTime()); + claTimeRule.setTeacherId(teacherId); + claTimeRule.setRoomId(roomId); + businessClaTimeRuleService.addClaTimeRule(claTimeRule); + + } + + } + } + + /** + * 校验导入参数 + * + * @param data + * @return + */ + public APIBaseResponse checkParam(ImportCourseCla data) { + if (StringUtils.isAnyEmpty(data.getClaName(), data.getCourseName(), + data.getDeptName(), data.getTeacherName(), data.getOpenDate())) { + return APIBaseResponse.fail("请填写班级名称、课程名称、校区、任课教师、开班日期"); + } else if (StringUtils.isEmpty(data.getEveryStuLoseHour())) { + return APIBaseResponse.fail("请填写每次上课学员扣除课时数"); + } else if (data.getClaName().length() > 30) { + return APIBaseResponse.fail("班级名称过长,最长30!"); + } else if (StringUtils.isNotEmpty(data.getMemo()) && data.getMemo().length() > 200) { + return APIBaseResponse.fail("备注过长,最长200!"); + } + try { + new BigDecimal(data.getEveryStuLoseHour()); + }catch (NumberFormatException numberFormatException) { + return APIBaseResponse.fail("每次上课学员扣除课时数 需填写两位小数"); + } + if(StringUtils.isNotEmpty(data.getCapacity())){ + try { + Integer.parseInt(data.getCapacity()); + }catch (NumberFormatException numberFormatException) { + return APIBaseResponse.fail("满班人数需为正整数"); + } + } + Long courseId = courseMap.get(data.getCourseName()); + Long deptId = campusMap.get(data.getDeptName()); + Long teacherId = teacherMap.get(data.getTeacherName()); + String recruitStatus = recruitStatusMap.get(data.getRecruitStatus()); + + if (null == courseId || null == teacherId) { + return APIBaseResponse.fail("根据课程名称、任课教师名称无法获取对应信息,请核对填写信息或重新下载导入模板进行导入"); + } else if (ObjectUtil.isEmpty(deptId)) { + return APIBaseResponse.fail("根据校区名称无法获取对应信息,请核对填写信息或重新下载导入模板进行导入"); + } else if (StringUtils.isEmpty(recruitStatus)) { + return APIBaseResponse.fail("根据招生状态无法获取对应信息,请核对填写信息或重新下载导入模板进行导入"); + } + + if (StringUtils.isNoneEmpty(data.getBeginDate(), data.getEndDate())) { + + try { + DateUtil.yyyMMddDayBegin(data.getBeginDate()); + DateUtil.yyyMMddDayBegin(data.getEndDate()); + }catch (Exception e) { + return APIBaseResponse.fail("请按照正确格式填写排课开始日期、排课结束日期"); + } + + if (StringUtils.isAnyEmpty(data.getRepeatType(), data.getStartTime(), data.getEndTime())) { + return APIBaseResponse.fail("导入排课时,请填写重复方式、上课时间、下课时间。如无需导入排课信息,请删除填写的排课开始日期、排课结束日期"); + } else if (!"过滤".equals(data.getFilterHoliday()) && !"不过滤".equals(data.getFilterHoliday())) { + return APIBaseResponse.fail("导入排课时,是否过滤节假日只可填写过滤/不过滤"); + } + String repeatType = claTimeRepeatTypeMap.get(data.getRepeatType()); + if (StringUtils.isEmpty(repeatType)) { + return APIBaseResponse.fail("根据重复方式无法获取对应信息,请核对填写信息或重新下载导入模板进行导入"); + } else if (!ClaTimeRepeatTypeEnums.EVERY_SECOND_DAY.getRepeatType().equals(data.getRepeatType())) { + if (StringUtils.isEmpty(data.getWeekDay())) { + return APIBaseResponse.fail("导入排课时,每周重复、隔周重复时需填写上课星期"); + } + String weekDay = data.getWeekDay(); + String[] weekDayArray = weekDay.split(","); + for (String item : weekDayArray) { + if (StringUtils.isEmpty(weekDayMap.get(item))) { + return APIBaseResponse.fail("请重新填写上课星期'" + item + "',使用英文,号分隔"); + } + } + } + if (StringUtils.isNotEmpty(data.getRoomName())) { + Long roomId = roomMap.get(data.getRoomName()); + if (null == roomId) { + return APIBaseResponse.fail("根据教室名称无法获取对应信息,请核对填写信息或重新下载导入模板进行导入"); + } + } + } + + + return APIBaseResponse.success(); + } + + public int getSuccessRecord() { + return this.saveCourseClaList.size(); + } + + public int getFailRecord() { + return this.failCourseClaList.size(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/listener/ImportCourseListener.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/listener/ImportCourseListener.java new file mode 100644 index 0000000..0c7da61 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/listener/ImportCourseListener.java @@ -0,0 +1,208 @@ +package cn.xluobo.business.tool.impt.listener; + +import cn.xluobo.business.sc.course.enums.CourseChargeTypeEnum; +import cn.xluobo.business.sc.course.repo.model.ScCourse; +import cn.xluobo.business.sc.course.repo.model.ScCourseCharge; +import cn.xluobo.business.sc.course.service.IScCourseChargeService; +import cn.xluobo.business.sc.course.service.IScCourseService; +import cn.xluobo.business.tool.impt.domain.ImportCourse; +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.fastjson.JSON; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/8/3 22:02 + */ +@Slf4j +@Data +public class ImportCourseListener extends AnalysisEventListener { + + private IScCourseService courseService; + + private IScCourseChargeService courseChargeService; + + // 课程类型key value + private Map courseTypeMap; + // 校区key value + private Map campusMap; + // 收费模式 + private Map chargeTypeMap; + // 时间段 + private Map dateUnitMap; + // 是否开售 + private Map saleMap; + // 教学木事 + private Map teachingModeMap; + + // 登录用户id + private Long loginUserId = 0L; + + // 导入id + private Long importId; + + // 需保存的saveCourseList + private List saveCourseList = Lists.newArrayList(); + + /** + * 最多读取多少行 + */ + int maxRecord = 200; + + /** + * 当前已读取 + */ + int hadReadRecord = 0; + + private int successRecord = 0; + private int failRecord = 0; + + public ImportCourseListener(IScCourseService courseService, IScCourseChargeService courseChargeService) { + this.courseService = courseService; + this.courseChargeService = courseChargeService; + } + + @Override + public void invoke(ImportCourse data, AnalysisContext context) { + boolean checkParam = checkParam(data); + if (!checkParam) { + failRecord++; + return; + } + successRecord++; + + saveCourseList.add(data); + log.info(JSON.toJSONString(data)); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + saveCourse(); + log.info("doAfterAllAnalysed"); + } + + @Override + public boolean hasNext(AnalysisContext context) { + if (hadReadRecord++ < maxRecord) { + return true; + } + return false; + } + + /** + * 保存课程信息 + */ + public void saveCourse() { + // 缓存以保存的课程 + Map hadSaveCache = Maps.newHashMap(); + + for (ImportCourse importCourse : saveCourseList) { + if (!hadSaveCache.containsKey(importCourse.getCourseName())) { + // 保存课程信息 + ScCourse course = new ScCourse(); + course.setCourseName(importCourse.getCourseName()); + Long courseTypeId = courseTypeMap.get(importCourse.getCourseTypeName()); + course.setCourseTypeId(courseTypeId); + String teachingMode = teachingModeMap.get(importCourse.getTeachingMode()); + course.setTeachingMode(teachingMode); + course.setCourseIntro(importCourse.getCourseIntro()); + String sale = saleMap.get(importCourse.getSale()); + course.setSale(sale); + course.setCreateUser(loginUserId); + course.setImportId(importId); + courseService.save(course); + hadSaveCache.put(importCourse.getCourseName(), course.getCourseId()); + } + // 获取以保存课程ID + Long courseId = hadSaveCache.get(importCourse.getCourseName()); + + // 保存收费 + String chargeTypeName = importCourse.getChargeType(); + String chargeType = chargeTypeMap.get(chargeTypeName); + + if (chargeType.equals(CourseChargeTypeEnum.HOUR.getChargeType())) { + // 按课时收费 + ScCourseCharge courseCharge = new ScCourseCharge(); + courseCharge.setCourseId(courseId); + Long departId = campusMap.get(importCourse.getDepartName()); + courseCharge.setDepartId(departId); + courseCharge.setChargeType("hour"); + courseCharge.setCount(importCourse.getCount()); + courseCharge.setTotalFee(importCourse.getTotalFee()); + courseChargeService.save(courseCharge); + } else if (chargeType.equals(CourseChargeTypeEnum.DATE.getChargeType())) { + // 按时间收费 + ScCourseCharge courseCharge = new ScCourseCharge(); + courseCharge.setCourseId(courseId); + Long departId = campusMap.get(importCourse.getDepartName()); + courseCharge.setDepartId(departId); + courseCharge.setChargeType("date"); + courseCharge.setCount(new BigDecimal(1)); + courseCharge.setTotalFee(importCourse.getTotalFee()); + String dateUnit = dateUnitMap.get(importCourse.getDateUnit()); + courseCharge.setDateUnit(dateUnit); + courseChargeService.save(courseCharge); + } else if (chargeType.equals(CourseChargeTypeEnum.CYCLE.getChargeType())) { + // 按周期收费 + ScCourseCharge courseCharge = new ScCourseCharge(); + courseCharge.setCourseId(courseId); + Long departId = campusMap.get(importCourse.getDepartName()); + courseCharge.setDepartId(departId); + courseCharge.setChargeType("cycle"); + courseCharge.setCount(importCourse.getCount()); + courseCharge.setTotalFee(importCourse.getTotalFee()); + courseChargeService.save(courseCharge); + } + } + } + + /** + * 校验导入参数 + * + * @param data + * @return + */ + public boolean checkParam(ImportCourse data) { + if (StringUtils.isAnyEmpty(data.getCourseName(), data.getTeachingMode(), data.getSale())) { + return false; + } else if (StringUtils.isAnyEmpty(data.getDepartName(), data.getChargeType())) { + return false; + } else if (null == data.getTotalFee()) { + return false; + } + + String teachingMode = teachingModeMap.get(data.getTeachingMode()); + String sale = saleMap.get(data.getSale()); + Long departId = campusMap.get(data.getDepartName()); + String dateUnit = dateUnitMap.get(data.getDateUnit()); + String chargeType = chargeTypeMap.get(data.getChargeType()); + if (null == departId) { + return false; + } + if(StringUtils.isNotEmpty(data.getCourseTypeName())) { + Long courseTypeId = courseTypeMap.get(data.getCourseTypeName()); + if(null == courseTypeId) { + return false; + } + } + if (StringUtils.isAnyEmpty(teachingMode, sale, chargeType)) { + return false; + } + if (StringUtils.isEmpty(dateUnit) && CourseChargeTypeEnum.DATE.getChargeType().equals(chargeType)) { + return false; + } + if (null == data.getCount() && !CourseChargeTypeEnum.DATE.getChargeType().equals(chargeType)) { + return false; + } + return true; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/listener/ImportStudentOrderListener.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/listener/ImportStudentOrderListener.java new file mode 100644 index 0000000..1346f9e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/listener/ImportStudentOrderListener.java @@ -0,0 +1,782 @@ +package cn.xluobo.business.tool.impt.listener; + +import cn.hutool.core.util.ObjectUtil; +import cn.xluobo.business.sc.base.domain.req.ReqSchoolSelect; +import cn.xluobo.business.sc.base.domain.resp.RespSchoolSelect; +import cn.xluobo.business.sc.base.repo.model.ScSchool; +import cn.xluobo.business.sc.base.service.IScSchoolService; +import cn.xluobo.business.sc.course.domain.export.ExpCourse; +import cn.xluobo.business.sc.course.domain.req.ReqCourseClaSelect; +import cn.xluobo.business.sc.course.domain.req.ReqSearchScCourse; +import cn.xluobo.business.sc.course.domain.resp.RespCourseClaSelectInfo; +import cn.xluobo.business.sc.course.enums.ChargeDateUnitEnum; +import cn.xluobo.business.sc.course.enums.CourseChargeTypeEnum; +import cn.xluobo.business.sc.course.repo.mapper.ScCourseClaMapper; +import cn.xluobo.business.sc.course.repo.mapper.ScCourseMapper; +import cn.xluobo.business.sc.course.repo.model.ScCourseCharge; +import cn.xluobo.business.sc.course.service.IScCourseChargeService; +import cn.xluobo.business.sc.log.enums.LogTypeEnum; +import cn.xluobo.business.sc.log.repo.model.ScStudentCourseLog; +import cn.xluobo.business.sc.log.service.IScStudentCourseLogService; +import cn.xluobo.business.sc.order.enums.OrderStatusEnum; +import cn.xluobo.business.sc.order.repo.model.ScOrder; +import cn.xluobo.business.sc.order.repo.model.ScOrderAccount; +import cn.xluobo.business.sc.order.repo.model.ScOrderDetail; +import cn.xluobo.business.sc.order.service.IScOrderAccountService; +import cn.xluobo.business.sc.order.service.IScOrderDetailService; +import cn.xluobo.business.sc.order.service.IScOrderService; +import cn.xluobo.business.sc.student.repo.model.ScStudent; +import cn.xluobo.business.sc.student.repo.model.ScStudentContact; +import cn.xluobo.business.sc.student.repo.model.ScStudentCourse; +import cn.xluobo.business.sc.student.repo.model.ScStudentCourseOrder; +import cn.xluobo.business.sc.student.service.IScStudentContactService; +import cn.xluobo.business.sc.student.service.IScStudentCourseOrderService; +import cn.xluobo.business.sc.student.service.IScStudentCourseService; +import cn.xluobo.business.sc.student.service.IScStudentService; +import cn.xluobo.business.sys.admin.domain.resp.RespTreeSelect; +import cn.xluobo.business.sys.admin.service.BusinessSysDeptService; +import cn.xluobo.business.sys.admin.service.BusinessSysDictDataService; +import cn.xluobo.business.sys.receipt.repo.model.SysReceiptAccount; +import cn.xluobo.business.sys.receipt.service.ISysReceiptAccountService; +import cn.xluobo.business.sys.staff.repo.model.SysStaff; +import cn.xluobo.business.sys.staff.service.ISysStaffService; +import cn.xluobo.business.tool.impt.domain.ImportStudentOrder; +import cn.xluobo.core.api.APIBaseResponse; +import cn.xluobo.core.page.RespPage; +import cn.xluobo.core.utils.DateUtil; +import cn.xluobo.utils.ContextUtils; +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.domain.model.LoginUser; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.joda.time.Period; +import org.joda.time.PeriodType; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/10/12 17:12 + */ +@Slf4j +@Data +public class ImportStudentOrderListener extends AnalysisEventListener { + + private IScStudentService studentService; + private IScOrderService orderService; + private IScOrderDetailService orderDetailService; + private IScSchoolService schoolService; + private IScStudentContactService studentContactService; + private IScStudentCourseService studentCourseService; + private IScStudentCourseOrderService courseOrderService; + private IScOrderAccountService orderAccountService; + private BusinessSysDictDataService dictDataService; + private BusinessSysDeptService deptService; + private ScCourseMapper courseMapper; + private ScCourseClaMapper claMapper; + private ISysReceiptAccountService receiptAccountService; + private ISysStaffService staffService; + private IScCourseChargeService courseChargeService; + private IScStudentCourseLogService scStudentCourseLogService; + + /** + * 是否需要保存 + */ + private Boolean needSave; + + // key=value value=contactRelationId + private Map contactRelationMap = Maps.newHashMap(); + // key=value value=sexId + private Map sexMap = Maps.newHashMap(); + // key=schoolName value=schoolId + private Map schoolMap = Maps.newHashMap(); + // key=detailTagName value=detailTagId + private Map orderDetailTagMap = Maps.newHashMap(); + // key=deptName value=deptId + private Map campusMap = Maps.newHashMap(); + // key=courseChargeName value=chargeId + private Map courseChargeMap = Maps.newHashMap(); + private Map claMap = Maps.newHashMap(); + // key=courseId value=value + private Map courseMap = Maps.newHashMap(); + // key=name value=receiptAccountId + private Map receiptAccountMap = Maps.newHashMap(); + // key=staffName value=staffId + private Map staffMap = Maps.newHashMap(); + private Map chargeCacheMap = Maps.newHashMap(); + // key=studentName value=studentId + private Map studentMap = Maps.newHashMap(); + private boolean hadMoreStudent; + + // 登录用户id + private Long loginUserId = 0L; + private LoginUser loginUser; + + // 导入id + private Long importId; + + // 需保存的successRecordList + private List successRecordList = Lists.newArrayList(); + + // 校验失败的列表 + private List failRecordList = Lists.newArrayList(); + + /** + * 最多读取多少行 + */ + int maxRecord = 200; + + /** + * 当前已读取 + */ + int hadReadRecord = 0; + + public ImportStudentOrderListener() { + studentService = ContextUtils.getBean(IScStudentService.class); + orderService = ContextUtils.getBean(IScOrderService.class); + orderDetailService = ContextUtils.getBean(IScOrderDetailService.class); + schoolService = ContextUtils.getBean(IScSchoolService.class); + studentContactService = ContextUtils.getBean(IScStudentContactService.class); + studentCourseService = ContextUtils.getBean(IScStudentCourseService.class); + courseOrderService = ContextUtils.getBean(IScStudentCourseOrderService.class); + orderAccountService = ContextUtils.getBean(IScOrderAccountService.class); + dictDataService = ContextUtils.getBean(BusinessSysDictDataService.class); + deptService = ContextUtils.getBean(BusinessSysDeptService.class); + courseMapper = ContextUtils.getBean(ScCourseMapper.class); + claMapper = ContextUtils.getBean(ScCourseClaMapper.class); + receiptAccountService = ContextUtils.getBean(ISysReceiptAccountService.class); + staffService = ContextUtils.getBean(ISysStaffService.class); + courseChargeService = ContextUtils.getBean(IScCourseChargeService.class); + scStudentCourseLogService = ContextUtils.getBean(IScStudentCourseLogService.class); + this.initCacheMap(); + } + + @Override + public void invoke(ImportStudentOrder data, AnalysisContext context) { + APIBaseResponse checkParam = checkParam(data); + if (!checkParam.isSuccess()) { + data.setFailMsg(checkParam.getRespMsg()); + failRecordList.add(data); + return; + } + successRecordList.add(data); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + if (needSave) { + saveStudentOrder(); + } + log.info("doAfterAllAnalysed"); + } + + @Override + public boolean hasNext(AnalysisContext context) { + if (hadReadRecord++ < maxRecord) { + return true; + } + return false; + } + + /** + * 保存班级信息 + */ + public void saveStudentOrder() { + for (ImportStudentOrder studentOrder : successRecordList) { + String studentName = studentOrder.getStudentName(); + Long studentId = studentMap.get(studentName); + + if (null == studentId && hadMoreStudent) { + studentId = studentService.selectIdByName(studentName); + } + + // 如无学生信息,新建学生信息 + if (null == studentId) { + ScStudent student = new ScStudent(); + student.setStudentName(studentName); + if (StringUtils.isNotEmpty(studentOrder.getSchoolName())) { + Long schoolId = schoolMap.get(studentOrder.getSchoolName()); + if (null == schoolId) { + // 无学校信息 保存学校信息 + ScSchool saveSchool = new ScSchool(); + saveSchool.setSchoolName(studentOrder.getSchoolName()); + saveSchool.setCreateUser(loginUserId); + schoolService.save(saveSchool); + schoolId = saveSchool.getSchoolId(); + schoolMap.put(studentOrder.getSchoolName(), schoolId); + } + student.setSchoolId(schoolId); + } + if (StringUtils.isNotEmpty(studentOrder.getSex())) { + student.setSex(sexMap.get(studentOrder.getSex())); + } + student.setPhone(studentOrder.getContactPhone()); + if (StringUtils.isNotEmpty(studentOrder.getInTime())) { + student.setInTime(studentOrder.getInTime()); + } + student.setCreateUser(loginUserId); + studentService.save(student); + studentId = student.getStudentId(); + + // 保存联系人信息 + ScStudentContact studentContact = new ScStudentContact(); + String contactRelation = contactRelationMap.get(studentOrder.getContactRelation()); + studentContact.setContactRelation(contactRelation); + studentContact.setContactPhone(studentOrder.getContactPhone()); + studentContact.setContactNick(studentOrder.getContactRelation()); + studentContact.setCreateUser(loginUserId); + studentContact.setStudentId(student.getStudentId()); + studentContactService.save(studentContact); + } + + // 订单信息 + BigDecimal receiptFee = new BigDecimal(studentOrder.getReceiptFee()); + BigDecimal actualFee = new BigDecimal(studentOrder.getActualFee()); + Long handleDeptId = campusMap.get(studentOrder.getHandleDeptName()); + ScOrder order = ScOrder.builder() + .studentId(studentId) + .studentName(studentOrder.getStudentName()) + .phone(studentOrder.getContactPhone()) + .orderType("1") + .originalTotalFee(actualFee) + .actualTotalFee(actualFee) + .receiptFee(receiptFee) + .balanceFee(BigDecimal.ZERO) + .orderStatus(OrderStatusEnum.HAD_PAY.getOrderStatus()) + .memo(studentOrder.getMemo()) + .handleDeptId(Long.valueOf(handleDeptId)) + .handleDeptName(studentOrder.getHandleDeptName()) + .handleDate(studentOrder.getHandleDate()) + .createUser(loginUserId) + .lastUpdateUser(loginUserId) + .build(); + if (StringUtils.isNotEmpty(studentOrder.getSaleStaffName())) { + Long saleStaffId = staffMap.get(studentOrder.getSaleStaffName()); + order.setSaleStaffId(saleStaffId); + order.setSaleStaffName(studentOrder.getSaleStaffName()); + } + orderService.save(order); + + + // 订单明细 + Long deptId = campusMap.get(studentOrder.getDeptName()); + Long chargeId = courseChargeMap.get(studentOrder.getCourseName()); + ScCourseCharge courseCharge = chargeCacheMap.get(chargeId); + RespCourseClaSelectInfo claInfo = claMap.get(studentOrder.getClaName()); + String detailTagId = orderDetailTagMap.get(studentOrder.getOrderDetailTag()); + String buyCount = studentOrder.getBuyCount(); + if (StringUtils.isEmpty(buyCount)) { + buyCount = "1"; + } + Integer buyCountInt = Integer.parseInt(buyCount); + + ScOrderDetail orderDetail = ScOrderDetail.builder() + .orderId(order.getOrderId()) + .courseId(courseCharge.getCourseId()) + .courseName("导入:" + courseMap.get(courseCharge.getCourseId())) + .deptId(Long.valueOf(deptId)) + .deptName(studentOrder.getDeptName()) + .detailTag(detailTagId) + .chargeName(courseCharge.getChargeName()) + .chargeType(courseCharge.getChargeType()) + .chargeCount(courseCharge.getCount()) + .chargeFee(actualFee) + .dateUnit(courseCharge.getDateUnit()) + .buyCount(new BigDecimal(buyCount)) + .originalFee(actualFee) + .actualFee(receiptFee) + .insideMemo(null == studentOrder.getMemo() ? "导入" : "导入" + studentOrder.getMemo()) + .outsideMemo("") + .orderDetailStatus(OrderStatusEnum.HAD_PAY.getOrderStatus()) + .createUser(loginUserId) + .lastUpdateUser(loginUserId) + .build(); + if (StringUtils.isNotEmpty(studentOrder.getExpireDate())) { + orderDetail.setExpireDate(studentOrder.getExpireDate()); + } + if (null != claInfo) { + orderDetail.setClaId(claInfo.getClaId()); + orderDetail.setClaName(claInfo.getClaName()); + } + String beginDate = studentOrder.getBeginDate(); + DateTime beginDateTime = DateUtil.yyyMMddDayBegin(beginDate); + DateTime endDateTime = DateUtil.yyyMMddDayEnd(beginDate); + if (CourseChargeTypeEnum.DATE.getChargeType().equals(courseCharge.getChargeType())) { + if (ChargeDateUnitEnum.DAY.getDateUnit().equals(courseCharge.getDateUnit())) { + endDateTime = beginDateTime.plusDays(buyCountInt).minusDays(1); + } else if (ChargeDateUnitEnum.MONTH.getDateUnit().equals(courseCharge.getDateUnit())) { + endDateTime = beginDateTime.plusMonths(buyCountInt).minusDays(1); + } else if (ChargeDateUnitEnum.SEASON.getDateUnit().equals(courseCharge.getDateUnit())) { + endDateTime = beginDateTime.plusMonths(buyCountInt * 3).minusDays(1); + } else if (ChargeDateUnitEnum.YEAR.getDateUnit().equals(courseCharge.getDateUnit())) { + endDateTime = beginDateTime.plusYears(buyCountInt).minusDays(1); + } + orderDetail.setBeginDate(studentOrder.getBeginDate()); + orderDetail.setEndDate(endDateTime.toString("yyyy-MM-dd")); + } else { + // 收费方式按课时收费,实际课时数量 + orderDetail.setChargeCount(new BigDecimal(studentOrder.getBuyHour())); + } + orderDetailService.save(orderDetail); + + // 收款账户 + Long accountId = receiptAccountMap.get(studentOrder.getAccountName()); + ScOrderAccount orderAccount = new ScOrderAccount(); + orderAccount.setOrderId(order.getOrderId()); + orderAccount.setAccountId(accountId); + orderAccount.setAccountName(studentOrder.getAccountName()); + orderAccount.setFee(receiptFee); + orderAccountService.save(orderAccount); + + // sc_student_course表 + ScStudentCourse dbStudentCourse = studentCourseService.selectByStudentIdCourseId(studentId, courseCharge.getCourseId()); + BigDecimal buyHour = BigDecimal.ZERO; + BigDecimal addedHour = BigDecimal.ZERO; + int addedDays = 0; + if (CourseChargeTypeEnum.DATE.getChargeType().equals(courseCharge.getChargeType())) { + Period period = new Period(beginDateTime, endDateTime, PeriodType.days()); + addedDays = period.getDays() + 1; + } else { + // 新增课时 + buyHour = new BigDecimal(studentOrder.getBuyHour()); + addedHour = new BigDecimal(studentOrder.getBalanceHour()); + } + Long studentCourseId = null; + { + // db中包含 + if (null != dbStudentCourse) { + ScStudentCourse updateStudentCourse = new ScStudentCourse(); + updateStudentCourse.setStudentCourseId(dbStudentCourse.getStudentCourseId()); + if (CourseChargeTypeEnum.DATE.getChargeType().equals(courseCharge.getChargeType())) { + updateStudentCourse.setTotalDay(dbStudentCourse.getTotalDay().add(new BigDecimal(addedDays))); + } else { + updateStudentCourse.setTotalHour(dbStudentCourse.getTotalHour().add(new BigDecimal(studentOrder.getBuyHour()))); + updateStudentCourse.setBalanceHour(dbStudentCourse.getBalanceHour().add(addedHour)); + } + updateStudentCourse.setTotalFee(dbStudentCourse.getTotalFee().add(receiptFee)); + updateStudentCourse.setLastUpdateUser(loginUserId); + updateStudentCourse.setLastUpdateTime(new Date()); + studentCourseService.updateById(updateStudentCourse); + studentCourseId = updateStudentCourse.getStudentCourseId(); + } else { + ScStudentCourse addStudentCourse = new ScStudentCourse(); + addStudentCourse.setStudentId(studentId); + addStudentCourse.setCourseId(courseCharge.getCourseId()); + addStudentCourse.setCourseName(courseMap.get(courseCharge.getCourseId())); + addStudentCourse.setDeptId(Long.valueOf(deptId)); + if (null != claInfo) { + addStudentCourse.setClaId(claInfo.getClaId()); + addStudentCourse.setClaName(claInfo.getClaName()); + } + addStudentCourse.setChargeType(courseCharge.getChargeType()); + if (CourseChargeTypeEnum.HOUR.getChargeType().equals(courseCharge.getChargeType())) { + addStudentCourse.setTotalHour(new BigDecimal(studentOrder.getBuyHour())); + addStudentCourse.setBalanceHour(addedHour); + } else if (CourseChargeTypeEnum.DATE.getChargeType().equals(courseCharge.getChargeType())) { + addStudentCourse.setTotalDay(new BigDecimal(addedDays)); + } else if (CourseChargeTypeEnum.CYCLE.getChargeType().equals(courseCharge.getChargeType())) { + addStudentCourse.setTotalHour(new BigDecimal(studentOrder.getBuyHour())); + addStudentCourse.setBalanceHour(addedHour); + } + addStudentCourse.setTotalFee(receiptFee); + addStudentCourse.setStatus("1"); + addStudentCourse.setCreateUser(loginUserId); + addStudentCourse.setLastUpdateUser(loginUserId); + studentCourseService.save(addStudentCourse); + studentCourseId = addStudentCourse.getStudentCourseId(); + } + } + + // 插入sc_student_course_order + { + ScStudentCourseOrder studentCourseOrder = ScStudentCourseOrder.builder() + .studentCourseId(studentCourseId) + .orderId(order.getOrderId()) + .orderDetailId(orderDetail.getOrderDetailId()) + .totalFee(actualFee) + .createUser(loginUserId) + .lastUpdateUser(loginUserId) + .build(); + if (CourseChargeTypeEnum.DATE.getChargeType().equals(courseCharge.getChargeType())) { + studentCourseOrder.setTotalDay(new BigDecimal(addedDays)); + studentCourseOrder.setBeginDate(beginDateTime.toString("yyyy-MM-dd")); + studentCourseOrder.setEndDate(endDateTime.toString("yyyy-MM-dd")); + if (StringUtils.isNotEmpty(studentOrder.getExpireDate())) { + studentCourseOrder.setExpireDate(studentOrder.getExpireDate()); + } + + // 单价 = 总价/天 + studentCourseOrder.setUnitFee(actualFee.divide(new BigDecimal(addedDays), 2, BigDecimal.ROUND_HALF_UP)); + } else { + studentCourseOrder.setTotalHour(new BigDecimal(studentOrder.getBuyHour())); + studentCourseOrder.setBalanceHour(addedHour); + + // 按课时收费 如果 学生 剩余课时<0,表示欠课时 + if (null != dbStudentCourse && dbStudentCourse.getBalanceHour().compareTo(BigDecimal.ZERO) < 0) { + // 剩余课时 = 购买课时 - 欠课时 + studentCourseOrder.setBalanceHour(addedHour.add(dbStudentCourse.getBalanceHour())); + } + + // 单价 = 总价/课时数 + studentCourseOrder.setUnitFee(actualFee.divide(buyHour, 2, BigDecimal.ROUND_HALF_UP)); + } + courseOrderService.save(studentCourseOrder); + } + + // 学生报读 日志 + StringBuffer sb = new StringBuffer(""); + if ("1".equals(detailTagId)) { + sb.append("[导入]新报,"); + } else if ("2".equals(detailTagId)) { + sb.append("[导入]续报,"); + } + sb.append("课程'").append(courseMap.get(courseCharge.getCourseId())).append("',"); + sb.append("金额").append(receiptFee.toString()).append("元,"); + ScStudentCourseLog studentCourseLog = ScStudentCourseLog.builder() + .studentId(studentId) + .logType(LogTypeEnum.PAY_FEE.getLogType()) + .courseId(courseCharge.getCourseId()) + .courseName(courseMap.get(courseCharge.getCourseId())) + .deptName(studentOrder.getDeptName()) + .changeFee(receiptFee) + .createUser(loginUser.getUserId()) + .createUserName(loginUser.getUsername()) + .createTime(new Date()) + .build(); + if (null != claInfo) { + studentCourseLog.setClaId(claInfo.getClaId()); + studentCourseLog.setClaName(claInfo.getClaName()); + } + if (CourseChargeTypeEnum.DATE.getChargeType().equals(courseCharge.getChargeType())) { + sb.append("增加'").append(addedDays).append("'天"); + sb.append("(").append(beginDateTime.toString("yyyy-MM-dd")).append("~").append(endDateTime.toString("yyyy-MM-dd")).append(")."); + } else { + sb.append("增加'").append(addedHour.toString()).append("'课时,"); + studentCourseLog.setChangeHour(addedHour); + // 增加后剩余 + if (null != dbStudentCourse) { + studentCourseLog.setAfterBalanceHour(dbStudentCourse.getBalanceHour().add(addedHour)); + sb.append("增加后剩余").append(dbStudentCourse.getBalanceHour().add(addedHour).toString()).append("'课时").append("."); + } else { + studentCourseLog.setAfterBalanceHour(addedHour); + sb.append("增加后剩余").append(addedHour.toString()).append("'课时").append("."); + } + } + studentCourseLog.setMemo(sb.toString()); + scStudentCourseLogService.save(studentCourseLog); + } + } + + /** + * 校验导入参数 + * + * @param data + * @return + */ + public APIBaseResponse checkParam(ImportStudentOrder data) { + if(receiptAccountMap.isEmpty()) { + return APIBaseResponse.fail("系统未配置收款账户,请配置收款账户"); + } + String studentName = data.getStudentName(); + if (StringUtils.isEmpty(data.getStudentName())) { + return APIBaseResponse.fail("学生姓名未填写"); + } else if (studentName.length() > 20) { + return APIBaseResponse.fail("学生姓名最多20个字符"); + } else if (StringUtils.isEmpty(data.getContactPhone())) { + return APIBaseResponse.fail("联系电话未填写"); + } else if (data.getContactPhone().length() > 30) { + return APIBaseResponse.fail("联系电话最多30个字符"); + } else if (StringUtils.isEmpty(data.getDeptName())) { + return APIBaseResponse.fail("报读校区未填写"); + } else if (StringUtils.isEmpty(data.getCourseName())) { + return APIBaseResponse.fail("报读课程未填写"); + } else if (StringUtils.isEmpty(data.getReceiptFee())) { + return APIBaseResponse.fail("实缴学费未填写"); + } else if (StringUtils.isEmpty(data.getActualFee())) { + return APIBaseResponse.fail("应收学费未填写"); + } else if (StringUtils.isEmpty(data.getHandleDeptName())) { + return APIBaseResponse.fail("经办校区未填写"); + } + + try { + new BigDecimal(data.getReceiptFee()); + new BigDecimal(data.getActualFee()); + } catch (Exception e) { + return APIBaseResponse.fail("实缴、应收学费格式错误,请按照正确格式填写"); + } + + if (new BigDecimal(data.getReceiptFee()).compareTo(new BigDecimal(data.getActualFee())) > 0) { + return APIBaseResponse.fail("实缴应大于应收,应小于等于应收"); + } + + Long chargeId = courseChargeMap.get(data.getCourseName()); + if (null == chargeId) { + return APIBaseResponse.fail("根据课程无法获取对应信息,请核对填写信息或重新下载导入模板进行导入"); + } + + ScCourseCharge courseCharge = chargeCacheMap.get(chargeId); + if (CourseChargeTypeEnum.DATE.getChargeType().equals(courseCharge.getChargeType())) { + if (StringUtils.isEmpty(data.getBeginDate())) { + return APIBaseResponse.fail("按时间收费,开始日期未填写"); + } else if (StringUtils.isEmpty(data.getBuyCount())) { + return APIBaseResponse.fail("按时间收费,购买数量未填写"); + } + try { + DateUtil.yyyMMddDayBegin(data.getBeginDate()); + } catch (Exception e) { + return APIBaseResponse.fail("按时间收费开始日期格式错误,请按照正确格式填写开始日期"); + } + try { + Integer.parseInt(data.getBuyCount()); + if (Integer.parseInt(data.getBuyCount()) == 0) { + return APIBaseResponse.fail("按时间收费购买数量不能为0"); + } + } catch (Exception e) { + return APIBaseResponse.fail("按时间收费购买数量格式错误,请按照正确格式填写购买数量"); + } + } else { + if (StringUtils.isEmpty(data.getBuyHour())) { + return APIBaseResponse.fail("购买课时未填写"); + } else if (StringUtils.isEmpty(data.getBalanceHour())) { + return APIBaseResponse.fail("剩余课时未填写"); + } + + try { + new BigDecimal(data.getBuyHour()); + new BigDecimal(data.getBalanceHour()); + } catch (Exception e) { + return APIBaseResponse.fail("购买课时、剩余课时格式错误,请按照正确格式填写"); + } + + if (new BigDecimal(data.getBuyHour()).compareTo(new BigDecimal(data.getBalanceHour())) < 0) { + return APIBaseResponse.fail("购买课时小于剩余课时,请核对后重新填写"); + } + if (new BigDecimal(data.getBuyHour()).compareTo(BigDecimal.ZERO) < 0) { + return APIBaseResponse.fail("购买课时小于0"); + } else if (new BigDecimal(data.getBalanceHour()).compareTo(BigDecimal.ZERO) < 0) { + return APIBaseResponse.fail("剩余课时小于0"); + } + + if (StringUtils.isNotEmpty(data.getExpireDate())) { + try { + DateUtil.yyyMMddDayBegin(data.getExpireDate()); + } catch (Exception e) { + return APIBaseResponse.fail("按课时、周期收费,请按照正确格式填写课程到期日期"); + } + } + } + + + if (StringUtils.isNotEmpty(data.getContactRelation())) { + String contactRelationId = contactRelationMap.get(data.getContactRelation()); + if (StringUtils.isEmpty(contactRelationId)) { + return APIBaseResponse.fail("根据主要联系人无法获取对应信息,请核对填写信息或重新下载导入模板进行导入"); + } + } else { + // 如未填,默认为其他 + data.setContactRelation("其他"); + } + + if (StringUtils.isNotEmpty(data.getSex())) { + String sexId = sexMap.get(data.getSex()); + if (StringUtils.isEmpty(sexId)) { + return APIBaseResponse.fail("根据性别无法获取对应信息,请核对填写信息或重新下载导入模板进行导入"); + } + } else { + // 如未填,默认为男 + data.setSex("男"); + } + + if (StringUtils.isNotEmpty(data.getOrderDetailTag())) { + String detailTagId = orderDetailTagMap.get(data.getOrderDetailTag()); + if (StringUtils.isEmpty(detailTagId)) { + return APIBaseResponse.fail("根据订单类型无法获取对应信息,请核对填写信息或重新下载导入模板进行导入"); + } + } else { + // 如未填,默认为新报 + data.setOrderDetailTag("新报"); + } + + Long deptId = campusMap.get(data.getDeptName()); + if (ObjectUtil.isEmpty(deptId)) { + return APIBaseResponse.fail("根据报读校区无法获取对应信息,请核对填写信息或重新下载导入模板进行导入"); + } + + if (courseCharge.getDepartId() != -1 && courseCharge.getDepartId().compareTo(Long.valueOf(deptId)) != 0) { + return APIBaseResponse.fail("报读校区与报读课程不匹配,请核对后重新导入"); + } + + if (StringUtils.isNotEmpty(data.getClaName())) { + RespCourseClaSelectInfo claInfo = claMap.get(data.getClaName()); + if (null == claInfo) { + return APIBaseResponse.fail("根据报读班级无法获取对应信息,请核对填写信息或重新下载导入模板进行导入"); + } else if (claInfo.getCourseId().compareTo(courseCharge.getCourseId()) != 0) { + return APIBaseResponse.fail("报读班级与报读课程不匹配,请核对后重新导入"); + } else if (claInfo.getDeptId().compareTo(Long.valueOf(deptId)) != 0) { + return APIBaseResponse.fail("报读班级与报读课程不匹配,请核对后重新导入"); + } + + } + + Long handleDeptId = campusMap.get(data.getHandleDeptName()); + if (ObjectUtil.isEmpty(handleDeptId)) { + return APIBaseResponse.fail("根据经办校区无法获取对应信息,请核对填写信息或重新下载导入模板进行导入"); + } + + if (StringUtils.isNotEmpty(data.getHandleDate())) { + try { + DateUtil.yyyMMddDayBegin(data.getHandleDate()); + } catch (Exception e) { + return APIBaseResponse.fail("请按照正确格式填写经办日期"); + } + } else { + data.setHandleDate(DateTime.now().toString("yyyy-MM-dd")); + } + + if (StringUtils.isNotEmpty(data.getAccountName())) { + Long accountId = receiptAccountMap.get(data.getAccountName()); + if (null == accountId) { + return APIBaseResponse.fail("根据收款账户无法获取对应信息,请核对填写信息或重新下载导入模板进行导入"); + } + } else if (!receiptAccountMap.isEmpty()) { + String key = receiptAccountMap.keySet().iterator().next(); + // 如未填,默认第一个 + data.setAccountName(key); + } + + if (StringUtils.isNotEmpty(data.getSaleStaffName())) { + Long staffId = staffMap.get(data.getSaleStaffName()); + if (null == staffId) { + return APIBaseResponse.fail("根据销售员工无法获取对应信息,请核对填写信息或重新下载导入模板进行导入"); + } + } + + // 校验学生报读方式 是否与老报读方式一致 + Long studentId = studentMap.get(studentName); + if (null == studentId && hadMoreStudent) { + studentId = studentService.selectIdByName(studentName); + } + if (null != studentId) { + ScStudentCourse studentCourse = studentCourseService.selectByStudentIdCourseId(studentId, courseCharge.getCourseId()); + if (null != studentCourse && !studentCourse.getChargeType().equals(courseCharge.getChargeType())) { + return APIBaseResponse.fail("该学生 已" + CourseChargeTypeEnum.getChargeType(studentCourse.getChargeType()) + "报读,无法按" + courseCharge.getChargeType() + "重复报读!"); + } + } + + + // 按时间报读,报读日期是否存在覆盖 + if (CourseChargeTypeEnum.DATE.getChargeType().equals(courseCharge.getChargeType())) { + String beginDate = data.getBeginDate(); + DateTime beginDateTime = DateUtil.yyyMMddDayBegin(beginDate); + DateTime endDateTime = DateUtil.yyyMMddDayEnd(beginDate); + if (ChargeDateUnitEnum.DAY.getDateUnit().equals(courseCharge.getDateUnit())) { + endDateTime = beginDateTime.plusDays(Integer.parseInt(data.getBuyCount())).minusDays(1); + } else if (ChargeDateUnitEnum.MONTH.getDateUnit().equals(courseCharge.getDateUnit())) { + endDateTime = beginDateTime.plusMonths(Integer.parseInt(data.getBuyCount())).minusDays(1); + } else if (ChargeDateUnitEnum.SEASON.getDateUnit().equals(courseCharge.getDateUnit())) { + endDateTime = beginDateTime.plusMonths(Integer.parseInt(data.getBuyCount()) * 3).minusDays(1); + } else if (ChargeDateUnitEnum.YEAR.getDateUnit().equals(courseCharge.getDateUnit())) { + endDateTime = beginDateTime.plusYears(Integer.parseInt(data.getBuyCount())).minusDays(1); + } + boolean checkDateCover = courseOrderService.checkDateCover(studentId, courseCharge.getCourseId(), beginDateTime.toString("yyyy-MM-dd"), endDateTime.toString("yyyy-MM-dd")); + if (checkDateCover) { + return APIBaseResponse.fail("按时间收费,报读日期存在覆盖,请重新选择开始日期!"); + } + } + + return APIBaseResponse.success(); + } + + public void initCacheMap() { + // 联系人关系 + List contactRelationList = dictDataService.dictTypeDataList("contact_relation"); + // 性别 + List sexList = dictDataService.dictTypeDataList("sex"); + // 学校 + List schoolList = schoolService.selectSchoolSelect(new ReqSchoolSelect()); + // 订单类型 + List orderDetailTagList = dictDataService.dictTypeDataList("order_detail_tag"); + // 报读校区 + List campusList = deptService.campusList(); + // 报读课程 课程-收费方式(校区) + ReqSearchScCourse reqSearchScCourse = new ReqSearchScCourse(); + reqSearchScCourse.setSale("1"); + List courseList = courseMapper.selectCourseForExport(reqSearchScCourse); + // 报读班级 班级(教师)-课程 + List claList = claMapper.selectForSelect(new ReqCourseClaSelect()); + // 收款账户 + List receiptAccountList = receiptAccountService.select(); + // 销售员工 + List staffList = staffService.staffList(null); + // 收费模式 + QueryWrapper qw = new QueryWrapper<>(); + List courseChargeList = courseChargeService.list(qw); + + contactRelationList.forEach(item -> { + contactRelationMap.put(item.getDictLabel(), item.getDictValue()); + }); + sexList.forEach(item -> { + sexMap.put(item.getDictLabel(), item.getDictValue()); + }); + schoolList.forEach(item -> { + schoolMap.put(item.getSchoolName(), item.getSchoolId()); + }); + orderDetailTagList.forEach(item -> { + orderDetailTagMap.put(item.getDictLabel(), item.getDictValue()); + }); + campusList.forEach(item -> { + campusMap.put(item.getLabel(), item.getId()); + }); + courseList.forEach(item -> { + String courseName = item.getCourseName() + "(" + item.getDepartName() + ")-" + item.getChargeTypeName(); + if (CourseChargeTypeEnum.DATE.getChargeType().equals(item.getChargeType())) { + courseName = courseName + "(" + item.getTotalFee().toString() + item.getDateUnitName() + ")"; + } else { + courseName = courseName + "(" + item.getCount().toString() + "课时," + item.getTotalFee().toString() + "元)"; + } + courseChargeMap.put(courseName, item.getChargeId()); + }); + courseList.forEach(item -> { + courseMap.put(item.getCourseId(), item.getCourseName()); + }); + claList.forEach(item -> { + String key = item.getDeptName() + "-" + item.getClaName() + "(" + item.getStaffName() + ")" + "-" + item.getCourseName(); + claMap.put(key, item); + }); + receiptAccountList.forEach(item -> { + receiptAccountMap.put(item.getAccountName(), item.getAccountId()); + }); + staffList.forEach(item -> { + staffMap.put(item.getStaffName(), item.getStaffId()); + }); + courseChargeList.forEach(item -> { + chargeCacheMap.put(item.getChargeId(), item); + }); + + RespPage scStudentRespPage = studentService.selectStudentList(500); + long pages = scStudentRespPage.getPages(); + hadMoreStudent = pages > 1; + // 学生信息 + scStudentRespPage.getRows().forEach(item -> { + studentMap.put(item.getStudentName(), item.getStudentId()); + }); + } + + public int getSuccessRecordSize() { + return this.successRecordList.size(); + } + + public int getFailRecordSize() { + return this.failRecordList.size(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/mapper/ToolImportMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/mapper/ToolImportMapper.java new file mode 100644 index 0000000..7f24fbb --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/mapper/ToolImportMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.tool.impt.repo.mapper; + +import cn.xluobo.business.tool.impt.repo.model.ToolImport; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 导入 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-08-04 + */ +public interface ToolImportMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/mapping/ToolImportMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/mapping/ToolImportMapper.xml new file mode 100644 index 0000000..c570de3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/mapping/ToolImportMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/model/ToolImport.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/model/ToolImport.java new file mode 100644 index 0000000..cf8f205 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/model/ToolImport.java @@ -0,0 +1,69 @@ +package cn.xluobo.business.tool.impt.repo.model; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import java.util.Date; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableField; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 导入 + *

+ * + * @author zhangby + * @since 2020-08-04 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("tool_import") +public class ToolImport implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "import_id", type = IdType.AUTO) + private Long importId; + + /** + * 导入 类型 + */ + @TableField("import_type") + private String importType; + + /** + * 文件大小 + */ + @TableField("file_size") + private Long fileSize; + + /** + * 导入结果 + */ + @TableField("import_result") + private String importResult; + + /** + * 导入结果说明 + */ + @TableField("result_memo") + private String resultMemo; + + /** + * 导入人 + */ + @TableField("create_user") + private Long createUser; + + /** + * 导入时间 + */ + @TableField("create_time") + private Date createTime; + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/service/IToolImportService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/service/IToolImportService.java new file mode 100644 index 0000000..f25537a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/service/IToolImportService.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.tool.impt.repo.service; + +import cn.xluobo.business.tool.impt.repo.model.ToolImport; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 导入 服务类 + *

+ * + * @author zhangby + * @since 2020-08-04 + */ +public interface IToolImportService extends IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/service/impl/ToolImportServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/service/impl/ToolImportServiceImpl.java new file mode 100644 index 0000000..df1ff71 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/repo/service/impl/ToolImportServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.tool.impt.repo.service.impl; + +import cn.xluobo.business.tool.impt.repo.model.ToolImport; +import cn.xluobo.business.tool.impt.repo.mapper.ToolImportMapper; +import cn.xluobo.business.tool.impt.repo.service.IToolImportService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 导入 服务实现类 + *

+ * + * @author zhangby + * @since 2020-08-04 + */ +@Service +public class ToolImportServiceImpl extends ServiceImpl implements IToolImportService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/BusinessImportService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/BusinessImportService.java new file mode 100644 index 0000000..f73da9b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/BusinessImportService.java @@ -0,0 +1,115 @@ +package cn.xluobo.business.tool.impt.service; + +import cn.xluobo.business.tool.export.handler.SelectWriteHandler; +import cn.xluobo.business.tool.export.handler.bean.SelectValidationData; +import cn.xluobo.business.tool.impt.domain.ReqDownImplTemplate; +import cn.xluobo.business.tool.impt.domain.ReqUploadImplData; +import cn.xluobo.business.tool.impt.service.strategy.ImportContext; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.file.FileUtils; +import cn.xluobo.core.utils.ServletUtils; +import com.alibaba.excel.EasyExcel; +import org.apache.commons.compress.utils.Lists; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +/** + * 导入 + * + * @author :zhangbaoyu + * @date :Created in 2020/8/2 17:44 + */ +@Service +@Transactional +public class BusinessImportService { + + @Autowired + private ImportContext selectValidateContext; + + /** + * 下载导入模板 + * + * @param downImplTemplate + * @return + */ + public void downImportTemplate(ReqDownImplTemplate downImplTemplate) throws IOException { + if (StringUtils.isAnyEmpty(downImplTemplate.getTemplateName(), downImplTemplate.getLogicFileName())) { + return; + } + HttpServletRequest request = ServletUtils.getRequest(); + HttpServletResponse response = ServletUtils.getResponse(); + String agent = request.getHeader("USER-AGENT"); + String encodeFileName = FileUtils.encodeDownloadFileName(agent, downImplTemplate.getLogicFileName()); + + response.setContentType("application/vnd.ms-excel"); + response.setCharacterEncoding("utf-8"); + response.setHeader("Content-disposition", "attachment;filename=" + encodeFileName + ".xlsx"); + + String templateFileName = "import/" + downImplTemplate.getTemplateName() + ".xlsx"; + + InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(templateFileName); + + List validateConfig = selectValidateContext.selectValidateConfig(downImplTemplate.getTemplateName()); + + EasyExcel.write(response.getOutputStream()) + .autoCloseStream(Boolean.FALSE) + .withTemplate(inputStream) + .registerWriteHandler(new SelectWriteHandler(validateConfig)) + .sheet().doWrite(Lists.newArrayList()); + } + + /** + * 上传 导入数据 + * + * @param uploadImplData + * @return + */ + public APIResponse uploadForImportData(ReqUploadImplData uploadImplData) { + MultipartFile file = uploadImplData.getFile(); + String templateName = uploadImplData.getTemplateName(); + if (null == file || StringUtils.isEmpty(templateName)) { + return APIResponse.toExceptionResponse(ApiResEnums.PARAM_FAIL); + } + return selectValidateContext.importData(uploadImplData); + } + + /** + * 上传 校验数据 + * + * @param uploadImplData + * @return + */ + public APIResponse uploadForCheckData(ReqUploadImplData uploadImplData) { + MultipartFile file = uploadImplData.getFile(); + String templateName = uploadImplData.getTemplateName(); + if (null == file || StringUtils.isEmpty(templateName)) { + return APIResponse.toExceptionResponse(ApiResEnums.PARAM_FAIL); + } + return selectValidateContext.checkData(uploadImplData); + } + + /** + * 上传 导入数据 + * + * @param uploadImplData + * @return + */ + public APIResponse uploadForImportDataByFileId(ReqUploadImplData uploadImplData) { + String templateName = uploadImplData.getTemplateName(); + String fileId = uploadImplData.getFileId(); + if (StringUtils.isEmpty(fileId) || StringUtils.isEmpty(templateName)) { + return APIResponse.toExceptionResponse(ApiResEnums.PARAM_FAIL); + } + return selectValidateContext.importDataByFileId(uploadImplData); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/AbstractImportStrategy.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/AbstractImportStrategy.java new file mode 100644 index 0000000..6e1471a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/AbstractImportStrategy.java @@ -0,0 +1,36 @@ +package cn.xluobo.business.tool.impt.service.strategy; + +import cn.xluobo.business.tool.export.handler.bean.SelectValidationData; +import cn.xluobo.core.api.APIResponse; +import com.google.common.collect.Lists; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.List; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/10/11 11:19 + */ +public abstract class AbstractImportStrategy implements IImportStrategy { + + @Override + public List selectValidateConfig(){ + return Lists.newArrayList(); + } + + @Override + public APIResponse importData(Long importId, MultipartFile multipartFile) throws IOException{ + return APIResponse.toOkResponse(); + } + + @Override + public APIResponse importDataByFileId(Long importId, String fileId) throws IOException{ + return APIResponse.toOkResponse(); + } + + @Override + public APIResponse checkData(MultipartFile multipartFile) throws IOException { + return APIResponse.toOkResponse(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/IImportStrategy.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/IImportStrategy.java new file mode 100644 index 0000000..cb74465 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/IImportStrategy.java @@ -0,0 +1,46 @@ +package cn.xluobo.business.tool.impt.service.strategy; + +import cn.xluobo.business.tool.export.handler.bean.SelectValidationData; +import cn.xluobo.core.api.APIResponse; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.List; + +/** + * 导出模板 导入数据策略 + * @author :zhangbaoyu + * @date :Created in 2020/8/2 18:53 + */ +public interface IImportStrategy { + + /** + * excel 下拉数据校验 配置 + * @return + */ + List selectValidateConfig(); + + /** + * 导入数据 + * @return + */ + APIResponse importData(Long importId, MultipartFile multipartFile) throws IOException; + + /** + * 导入数据 + * @param importId + * @param fileId + * @return + * @throws IOException + */ + APIResponse importDataByFileId(Long importId, String fileId) throws IOException; + + /** + * 校验数据 + * @param multipartFile + * @return + * @throws IOException + */ + APIResponse checkData(MultipartFile multipartFile) throws IOException; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/ImportContext.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/ImportContext.java new file mode 100644 index 0000000..a98186a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/ImportContext.java @@ -0,0 +1,144 @@ +package cn.xluobo.business.tool.impt.service.strategy; + +import cn.xluobo.business.tool.export.handler.bean.SelectValidationData; +import cn.xluobo.business.tool.impt.domain.ReqUploadImplData; +import cn.xluobo.business.tool.impt.repo.model.ToolImport; +import cn.xluobo.business.tool.impt.repo.service.IToolImportService; +import cn.xluobo.config.properties.UploadConfigProperties; +import cn.xluobo.core.api.APIResponse; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.File; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 策略上下文 + */ +@Service +@Transactional +@Slf4j +public class ImportContext { + + private final Map strategyMap = new ConcurrentHashMap<>(); + @Autowired + private IToolImportService importService; + @Autowired + private UploadConfigProperties uploadConfigProperties; + + @Autowired + public ImportContext(Map strategyMap) { + this.strategyMap.clear(); + strategyMap.forEach((k, v) -> this.strategyMap.put(k, v)); + } + + /** + * 获取excel select下拉 校验配置 + * + * @param beanName + * @return + */ + public List selectValidateConfig(String beanName) { + return strategyMap.get(beanName).selectValidateConfig(); + } + + /** + * 导入数据 + * + * @param uploadImplData + * @return + */ + @Transactional + public APIResponse importData(ReqUploadImplData uploadImplData) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + // 保存导入记录 + ToolImport toolImport = new ToolImport(); + toolImport.setImportType(uploadImplData.getTemplateName()); + toolImport.setFileSize(uploadImplData.getFile().getSize()); + toolImport.setCreateUser(loginUser.getUserId()); + toolImport.setCreateTime(new Date()); + importService.save(toolImport); + // 执行导入操作 + APIResponse apiResponse = null; + try { + apiResponse = strategyMap.get(uploadImplData.getTemplateName()).importData(toolImport.getImportId(),uploadImplData.getFile()); + } catch (Exception e) { + log.error("importData error",e); + apiResponse = APIResponse.toExceptionResponse(e.getMessage()); + } + // 更新导入结果 + ToolImport update = new ToolImport(); + update.setImportId(toolImport.getImportId()); + update.setImportResult(apiResponse.getRespCode()); + update.setResultMemo(apiResponse.getRespMsg()); + importService.updateById(update); + return apiResponse; + } + + /** + * 导入数据 + * + * @param uploadImplData + * @return + */ + @Transactional + public APIResponse importDataByFileId(ReqUploadImplData uploadImplData) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + + String path = uploadConfigProperties.getTempSaveImportPath(); + path = path + "/" + uploadImplData.getTemplateName(); + File file = new File(path, uploadImplData.getFileId()); + if (!file.exists()) { + return APIResponse.toExceptionResponse("无法获取文件,请重试"); + } + + // 保存导入记录 + ToolImport toolImport = new ToolImport(); + toolImport.setImportType(uploadImplData.getTemplateName()); + toolImport.setFileSize(file.length()); + toolImport.setCreateUser(loginUser.getUserId()); + toolImport.setCreateTime(new Date()); + importService.save(toolImport); + // 执行导入操作 + APIResponse apiResponse = null; + try { + apiResponse = strategyMap.get(uploadImplData.getTemplateName()).importDataByFileId(toolImport.getImportId(),uploadImplData.getFileId()); + } catch (Exception e) { + log.error("importDataByFileId error",e); + apiResponse = APIResponse.toExceptionResponse(e.getMessage()); + } + // 更新导入结果 + ToolImport update = new ToolImport(); + update.setImportId(toolImport.getImportId()); + update.setImportResult(apiResponse.getRespCode()); + update.setResultMemo(apiResponse.getRespMsg()); + importService.updateById(update); + return apiResponse; + } + + /** + * 校验数据 + * @param uploadImplData + * @return + */ + public APIResponse checkData(ReqUploadImplData uploadImplData) { + // 执行导入操作 + APIResponse apiResponse = null; + try { + apiResponse = strategyMap.get(uploadImplData.getTemplateName()).checkData(uploadImplData.getFile()); + } catch (Exception e) { + log.error("checkData error",e); + apiResponse = APIResponse.toExceptionResponse(e.getMessage()); + } + return apiResponse; + } + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/impl/ImportCourseClaImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/impl/ImportCourseClaImpl.java new file mode 100644 index 0000000..51346a9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/impl/ImportCourseClaImpl.java @@ -0,0 +1,296 @@ +package cn.xluobo.business.tool.impt.service.strategy.impl; + +import cn.xluobo.business.sc.base.domain.req.ReqRoomSelect; +import cn.xluobo.business.sc.base.domain.resp.RespRoomSelect; +import cn.xluobo.business.sc.base.service.IScRoomService; +import cn.xluobo.business.sc.course.repo.model.ScCourse; +import cn.xluobo.business.sc.course.service.BusinessClaTimeRuleService; +import cn.xluobo.business.sc.course.service.IScCourseClaService; +import cn.xluobo.business.sc.course.service.IScCourseService; +import cn.xluobo.business.sys.admin.domain.resp.RespTreeSelect; +import cn.xluobo.business.sys.admin.service.BusinessSysDeptService; +import cn.xluobo.business.sys.admin.service.BusinessSysDictDataService; +import cn.xluobo.business.sys.staff.repo.model.SysStaff; +import cn.xluobo.business.sys.staff.service.ISysStaffService; +import cn.xluobo.business.tool.export.handler.bean.SelectValidationData; +import cn.xluobo.business.tool.impt.domain.ImportCourseCla; +import cn.xluobo.business.tool.impt.listener.ImportCourseClaListener; +import cn.xluobo.business.tool.impt.service.strategy.AbstractImportStrategy; +import cn.xluobo.config.properties.UploadConfigProperties; +import cn.xluobo.core.api.APIResponse; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; +import java.util.List; +import java.util.Map; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/10/10 16:45 + */ +@Service("import_course_cla") +@Slf4j +public class ImportCourseClaImpl extends AbstractImportStrategy { + + @Autowired + private IScCourseService courseService; + @Autowired + private IScCourseClaService claService; + @Autowired + private BusinessSysDeptService deptService; + @Autowired + private ISysStaffService staffService; + @Autowired + private BusinessSysDictDataService dictDataService; + @Autowired + private BusinessClaTimeRuleService businessClaTimeRuleService; + @Autowired + private IScRoomService roomService; + @Autowired + private UploadConfigProperties uploadConfigProperties; + + private static final String FILE_TYPE = "import_course_cla"; + + @Override + public List selectValidateConfig() { + // 课程 + QueryWrapper qwCourse = new QueryWrapper<>(); + qwCourse.select("course_name"); + qwCourse.eq("sale", "1"); + qwCourse.eq("delete_flag", "0"); + List courseList = courseService.list(qwCourse); + String[] courseNameStringArray = courseList.stream().map(ScCourse::getCourseName).toArray(String[]::new); + + // 全部校区 + List campusList = deptService.campusList(); + String[] campusNameStringArray = campusList.stream().map(RespTreeSelect::getLabel).toArray(String[]::new); + + // 教师列表 + List teacherList = staffService.teacherList(""); + String[] teacherNameStringArray = teacherList.stream().map(SysStaff::getStaffName).toArray(String[]::new); + + // 招生状态 + List recruitStatusList = dictDataService.dictTypeDataList("recruit_status"); + String[] chargeTypeStringArray = recruitStatusList.stream().map(SysDictData::getDictLabel).toArray(String[]::new); + + // 排课重复方式 + List claTimeRepeatTypeList = dictDataService.dictTypeDataList("cla_time_repeat_type"); + String[] claTimeRepeatTypeStringArray = claTimeRepeatTypeList.stream().map(SysDictData::getDictLabel).toArray(String[]::new); + + // 所有教室 + List roomList = roomService.selectRoomSelect(new ReqRoomSelect()); + String[] roomNameStringArray = roomList.stream().map(RespRoomSelect::getRoomName).toArray(String[]::new); + + return Lists.newArrayList( + SelectValidationData.builder().firstCol(1).lastCol(1).firstRow(1).lastRow(106).selectDataArray(courseNameStringArray).build(), + SelectValidationData.builder().firstCol(2).lastCol(2).firstRow(1).lastRow(106).selectDataArray(campusNameStringArray).build(), + SelectValidationData.builder().firstCol(3).lastCol(3).firstRow(1).lastRow(106).selectDataArray(teacherNameStringArray).build(), + SelectValidationData.builder().firstCol(5).lastCol(5).firstRow(1).lastRow(106).selectDataArray(chargeTypeStringArray).build(), + SelectValidationData.builder().firstCol(12).lastCol(12).firstRow(1).lastRow(106).selectDataArray(claTimeRepeatTypeStringArray).build(), + SelectValidationData.builder().firstCol(14).lastCol(14).firstRow(1).lastRow(106).selectDataArray(new String[]{"过滤", "不过滤"}).build(), + SelectValidationData.builder().firstCol(17).lastCol(17).firstRow(1).lastRow(106).selectDataArray(roomNameStringArray).build() + ); + } + + @Override + @Transactional(propagation = Propagation.REQUIRES_NEW) + public APIResponse importDataByFileId(Long importId, String fileId) throws IOException { + + String path = uploadConfigProperties.getTempSaveImportPath(); + path = path + "/" + FILE_TYPE; + File file = new File(path, fileId); + if (!file.exists()) { + return APIResponse.toExceptionResponse("无法获取文件,请重试"); + } + + // 课程 + QueryWrapper qwCourse = new QueryWrapper<>(); + qwCourse.select("course_name", "course_id"); + qwCourse.eq("sale", "1"); + qwCourse.eq("delete_flag", "0"); + List courseList = courseService.list(qwCourse); + // 全部校区 + List campusList = deptService.campusList(); + // 教师列表 + List teacherList = staffService.teacherList(""); + // 招生状态 + List recruitStatusList = dictDataService.dictTypeDataList("recruit_status"); + // 排课重复方式 + List claTimeRepeatTypeList = dictDataService.dictTypeDataList("cla_time_repeat_type"); + // 所有教室 + List roomList = roomService.selectRoomSelect(new ReqRoomSelect()); + // 上课星期 + List weekDayList = dictDataService.dictTypeDataList("week_day"); + + + Map courseMap = Maps.newHashMap(); + Map campusMap = Maps.newHashMap(); + Map teacherMap = Maps.newHashMap(); + Map recruitStatusMap = Maps.newHashMap(); + Map claTimeRepeatTypeMap = Maps.newHashMap(); + Map roomMap = Maps.newHashMap(); + Map weekDayMap = Maps.newHashMap(); + + courseList.forEach(item -> { + courseMap.put(item.getCourseName(), item.getCourseId()); + }); + campusList.forEach(item -> { + campusMap.put(item.getLabel(), item.getId()); + }); + teacherList.forEach(item -> { + teacherMap.put(item.getStaffName(), item.getStaffId()); + }); + recruitStatusList.forEach(item -> { + recruitStatusMap.put(item.getDictLabel(), item.getDictValue()); + }); + claTimeRepeatTypeList.forEach(item -> { + claTimeRepeatTypeMap.put(item.getDictLabel(), item.getDictValue()); + }); + roomList.forEach(item -> { + roomMap.put(item.getRoomName(), item.getRoomId()); + }); + weekDayList.forEach(item -> { + weekDayMap.put(item.getDictLabel(), item.getDictValue()); + }); + + LoginUser loginUser = SecurityUtils.getLoginUser(); + + ImportCourseClaListener importListener = new ImportCourseClaListener(claService, businessClaTimeRuleService); + importListener.setNeedSave(true); + importListener.setCourseMap(courseMap); + importListener.setCampusMap(campusMap); + importListener.setTeacherMap(teacherMap); + importListener.setRecruitStatusMap(recruitStatusMap); + importListener.setClaTimeRepeatTypeMap(claTimeRepeatTypeMap); + importListener.setRoomMap(roomMap); + importListener.setWeekDayMap(weekDayMap); + importListener.setLoginUserId(loginUser.getUserId()); + importListener.setImportId(importId); + + InputStream is = new FileInputStream(file); + EasyExcel.read(is, ImportCourseCla.class, importListener).sheet().autoTrim(true).headRowNumber(5).doRead(); + + int successRecord = importListener.getSuccessRecord(); + int failRecord = importListener.getFailRecord(); + file.delete(); + return APIResponse.toAPIResponse("导入成功" + successRecord + "条,导入失败:" + failRecord); + } + + @Override + public APIResponse checkData(MultipartFile multipartFile) throws IOException { + long fileSize = multipartFile.getSize(); + if (fileSize > 1024 * 1024 * 2) { + return APIResponse.toExceptionResponse("导入文件需小于2M"); + } + // 课程 + QueryWrapper qwCourse = new QueryWrapper<>(); + qwCourse.select("course_name", "course_id"); + qwCourse.eq("sale", "1"); + qwCourse.eq("delete_flag", "0"); + List courseList = courseService.list(qwCourse); + // 全部校区 + List campusList = deptService.campusList(); + // 教师列表 + List teacherList = staffService.teacherList(""); + // 招生状态 + List recruitStatusList = dictDataService.dictTypeDataList("recruit_status"); + // 排课重复方式 + List claTimeRepeatTypeList = dictDataService.dictTypeDataList("cla_time_repeat_type"); + // 所有教室 + List roomList = roomService.selectRoomSelect(new ReqRoomSelect()); + // 上课星期 + List weekDayList = dictDataService.dictTypeDataList("week_day"); + + + Map courseMap = Maps.newHashMap(); + Map campusMap = Maps.newHashMap(); + Map teacherMap = Maps.newHashMap(); + Map recruitStatusMap = Maps.newHashMap(); + Map claTimeRepeatTypeMap = Maps.newHashMap(); + Map roomMap = Maps.newHashMap(); + Map weekDayMap = Maps.newHashMap(); + + courseList.forEach(item -> { + courseMap.put(item.getCourseName(), item.getCourseId()); + }); + campusList.forEach(item -> { + campusMap.put(item.getLabel(), item.getId()); + }); + teacherList.forEach(item -> { + teacherMap.put(item.getStaffName(), item.getStaffId()); + }); + recruitStatusList.forEach(item -> { + recruitStatusMap.put(item.getDictLabel(), item.getDictValue()); + }); + claTimeRepeatTypeList.forEach(item -> { + claTimeRepeatTypeMap.put(item.getDictLabel(), item.getDictValue()); + }); + roomList.forEach(item -> { + roomMap.put(item.getRoomName(), item.getRoomId()); + }); + weekDayList.forEach(item -> { + weekDayMap.put(item.getDictLabel(), item.getDictValue()); + }); + + LoginUser loginUser = SecurityUtils.getLoginUser(); + + ImportCourseClaListener importListener = new ImportCourseClaListener(claService, businessClaTimeRuleService); + importListener.setNeedSave(false); + importListener.setCourseMap(courseMap); + importListener.setCampusMap(campusMap); + importListener.setTeacherMap(teacherMap); + importListener.setRecruitStatusMap(recruitStatusMap); + importListener.setClaTimeRepeatTypeMap(claTimeRepeatTypeMap); + importListener.setRoomMap(roomMap); + importListener.setWeekDayMap(weekDayMap); + importListener.setLoginUserId(loginUser.getUserId()); + + // 保存文件 + String fileId = IdWorker.getIdStr(); + String fileName = DateTime.now().toString("yyyyMMddHHmmss") + "_" + fileId; + String originalFileName = multipartFile.getOriginalFilename(); + String suffix = FilenameUtils.getExtension(originalFileName); + if (StringUtils.isNotEmpty(suffix)) { + fileName = fileName + "." + suffix; + } + + String path = uploadConfigProperties.getTempSaveImportPath(); + //上传文件夹 + path = path + "/" + FILE_TYPE; + File uploadFileDir = new File(path); + if (!uploadFileDir.exists()) { + uploadFileDir.mkdir(); + } + File uploadFile = new File(uploadFileDir, fileName); + FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), uploadFile); + + InputStream is = new FileInputStream(uploadFile); + EasyExcel.read(is, ImportCourseCla.class, importListener).sheet().autoTrim(true).headRowNumber(5).doRead(); + + List saveCourseClaList = importListener.getSaveCourseClaList(); + List failCourseClaList = importListener.getFailCourseClaList(); + Map resultMap = Maps.newHashMap(); + resultMap.put("successList", saveCourseClaList); + resultMap.put("failList", failCourseClaList); + resultMap.put("fileId", fileName); + + return APIResponse.toAPIResponse(resultMap); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/impl/ImportCourseImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/impl/ImportCourseImpl.java new file mode 100644 index 0000000..3f66b83 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/impl/ImportCourseImpl.java @@ -0,0 +1,159 @@ +package cn.xluobo.business.tool.impt.service.strategy.impl; + +import cn.xluobo.business.sc.course.repo.model.ScCourseType; +import cn.xluobo.business.sc.course.service.IScCourseChargeService; +import cn.xluobo.business.sc.course.service.IScCourseService; +import cn.xluobo.business.sc.course.service.IScCourseTypeService; +import cn.xluobo.business.sys.admin.domain.resp.RespTreeSelect; +import cn.xluobo.business.sys.admin.service.BusinessSysDeptService; +import cn.xluobo.business.sys.admin.service.BusinessSysDictDataService; +import cn.xluobo.business.tool.export.handler.bean.SelectValidationData; +import cn.xluobo.business.tool.impt.domain.ImportCourse; +import cn.xluobo.business.tool.impt.listener.ImportCourseListener; +import cn.xluobo.business.tool.impt.service.strategy.AbstractImportStrategy; +import cn.xluobo.core.api.APIResponse; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 导入课程select限制配置 + * + * @author :zhangbaoyu + * @date :Created in 2020/8/2 18:56 + */ +@Service("import_course") +@Slf4j +public class ImportCourseImpl extends AbstractImportStrategy { + + @Autowired + private BusinessSysDeptService deptService; + @Autowired + private IScCourseTypeService scCourseTypeService; + @Autowired + private BusinessSysDictDataService dictDataService; + @Autowired + private IScCourseService courseService; + @Autowired + private IScCourseChargeService courseChargeService; + + @Override + public List selectValidateConfig() { + // 全部校区 + List campusList = deptService.campusList(); + List campusNameList = Lists.newArrayList("全部校区"); + List allDbCampusList = campusList.stream().map(RespTreeSelect::getLabel).collect(Collectors.toList()); + campusNameList.addAll(allDbCampusList); + String[] campusNameStringArray = campusNameList.toArray(new String[allDbCampusList.size()]); + + // 课程类型 + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("in_use", "1"); + qw.orderByDesc("create_time"); + List courseTypeList = scCourseTypeService.list(qw); + String[] courseTypeStringArray = courseTypeList.stream().map(ScCourseType::getCourseType).toArray(String[]::new); + + // 收费模式 + List chargeTypeList = dictDataService.dictTypeDataList("charge_type"); + String[] chargeTypeStringArray = chargeTypeList.stream().map(SysDictData::getDictLabel).toArray(String[]::new); + + // 时间段 + List dateUnitList = dictDataService.dictTypeDataList("date_unit"); + String[] dateUnitListStringArray = dateUnitList.stream().map(SysDictData::getDictLabel).toArray(String[]::new); + + + return Lists.newArrayList( + SelectValidationData.builder().firstCol(1).lastCol(1).firstRow(1).lastRow(206).selectDataArray(courseTypeStringArray).build(), + SelectValidationData.builder().firstCol(2).lastCol(2).firstRow(1).lastRow(206).selectDataArray(new String[]{"班课", "一对一"}).build(), + SelectValidationData.builder().firstCol(4).lastCol(4).firstRow(1).lastRow(206).selectDataArray(new String[]{"开售", "不开售"}).build(), + SelectValidationData.builder().firstCol(5).lastCol(5).firstRow(1).lastRow(206).selectDataArray(campusNameStringArray).build(), + SelectValidationData.builder().firstCol(6).lastCol(6).firstRow(1).lastRow(206).selectDataArray(chargeTypeStringArray).build(), + SelectValidationData.builder().firstCol(9).lastCol(9).firstRow(1).lastRow(206).selectDataArray(dateUnitListStringArray).build() + ); + } + + @Override + @Transactional(propagation = Propagation.REQUIRES_NEW) + public APIResponse importData(Long importId, MultipartFile multipartFile) throws IOException { + long fileSize = multipartFile.getSize(); + if (fileSize > 1024 * 1024 * 2) { + return APIResponse.toExceptionResponse("导入文件需小于2M"); + } + + LoginUser loginUser = SecurityUtils.getLoginUser(); + + + // 课程类型 + QueryWrapper qw = new QueryWrapper(); + qw.eq("in_use", "1"); + qw.orderByDesc("create_time"); + List courseTypeList = scCourseTypeService.list(qw); + // 全部校区 + List campusList = deptService.campusList(); + campusList.add(RespTreeSelect.builder().id(-1L).label("全部校区").build()); + // 收费模式 + List chargeTypeList = dictDataService.dictTypeDataList("charge_type"); + // 时间段 + List dateUnitList = dictDataService.dictTypeDataList("date_unit"); + + // 课程类型key value key为名称 value为ID + Map courseTypeMap = Maps.newHashMap(); + for (ScCourseType scCourseType : courseTypeList) { + courseTypeMap.put(scCourseType.getCourseType(), scCourseType.getCourseTypeId()); + } + // 校区key value + Map campusMap = Maps.newHashMap(); + for (RespTreeSelect respTreeSelect : campusList) { + campusMap.put(respTreeSelect.getLabel(), Long.valueOf(respTreeSelect.getId())); + } + // 收费模式 + Map chargeTypeMap = Maps.newHashMap(); + for (SysDictData sysDictData : chargeTypeList) { + chargeTypeMap.put(sysDictData.getDictLabel(), sysDictData.getDictValue()); + } + // 时间段 + Map dateUnitMap = Maps.newHashMap(); + for (SysDictData sysDictData : dateUnitList) { + dateUnitMap.put(sysDictData.getDictLabel(), sysDictData.getDictValue()); + } + + Map saleMap = Maps.newHashMap(); + saleMap.put("开售", "1"); + saleMap.put("不开售", "2"); + + Map teachingModeMap = Maps.newHashMap(); + teachingModeMap.put("班课", "1"); + teachingModeMap.put("一对一", "2"); + + + ImportCourseListener importCourseListener = new ImportCourseListener(courseService, courseChargeService); + importCourseListener.setCourseTypeMap(courseTypeMap); + importCourseListener.setCampusMap(campusMap); + importCourseListener.setChargeTypeMap(chargeTypeMap); + importCourseListener.setDateUnitMap(dateUnitMap); + importCourseListener.setSaleMap(saleMap); + importCourseListener.setTeachingModeMap(teachingModeMap); + importCourseListener.setLoginUserId(loginUser.getUserId()); + importCourseListener.setImportId(importId); + EasyExcel.read(multipartFile.getInputStream(), ImportCourse.class, importCourseListener).sheet().autoTrim(true).headRowNumber(7).doRead(); + + int successRecord = importCourseListener.getSuccessRecord(); + int failRecord = importCourseListener.getFailRecord(); + return APIResponse.toAPIResponse("导入成功" + successRecord + "条,导入失败:" + failRecord); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/impl/ImportStudentOrderImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/impl/ImportStudentOrderImpl.java new file mode 100644 index 0000000..b667aca --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/tool/impt/service/strategy/impl/ImportStudentOrderImpl.java @@ -0,0 +1,214 @@ +package cn.xluobo.business.tool.impt.service.strategy.impl; + +import cn.xluobo.business.sc.base.domain.req.ReqSchoolSelect; +import cn.xluobo.business.sc.base.domain.resp.RespSchoolSelect; +import cn.xluobo.business.sc.base.service.IScSchoolService; +import cn.xluobo.business.sc.course.domain.export.ExpCourse; +import cn.xluobo.business.sc.course.domain.req.ReqCourseClaSelect; +import cn.xluobo.business.sc.course.domain.req.ReqSearchScCourse; +import cn.xluobo.business.sc.course.domain.resp.RespCourseClaSelectInfo; +import cn.xluobo.business.sc.course.enums.CourseChargeTypeEnum; +import cn.xluobo.business.sc.course.repo.mapper.ScCourseClaMapper; +import cn.xluobo.business.sc.course.repo.mapper.ScCourseMapper; +import cn.xluobo.business.sys.admin.domain.resp.RespTreeSelect; +import cn.xluobo.business.sys.admin.service.BusinessSysDeptService; +import cn.xluobo.business.sys.admin.service.BusinessSysDictDataService; +import cn.xluobo.business.sys.receipt.repo.model.SysReceiptAccount; +import cn.xluobo.business.sys.receipt.service.ISysReceiptAccountService; +import cn.xluobo.business.sys.staff.repo.model.SysStaff; +import cn.xluobo.business.sys.staff.service.ISysStaffService; +import cn.xluobo.business.tool.export.handler.bean.SelectValidationData; +import cn.xluobo.business.tool.impt.domain.ImportStudentOrder; +import cn.xluobo.business.tool.impt.listener.ImportStudentOrderListener; +import cn.xluobo.business.tool.impt.service.strategy.AbstractImportStrategy; +import cn.xluobo.config.properties.UploadConfigProperties; +import cn.xluobo.core.api.APIResponse; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +/** + * 学生导入 + * + * @author :zhangbaoyu + * @date :Created in 2020/10/12 16:24 + */ +@Service("import_student_order") +@Slf4j +public class ImportStudentOrderImpl extends AbstractImportStrategy { + + @Autowired + private BusinessSysDictDataService dictDataService; + @Autowired + private IScSchoolService schoolService; + @Autowired + private BusinessSysDeptService deptService; + @Autowired + private ScCourseMapper courseMapper; + @Autowired + private ScCourseClaMapper claMapper; + @Autowired + private ISysReceiptAccountService receiptAccountService; + @Autowired + private ISysStaffService staffService; + @Autowired + private UploadConfigProperties uploadConfigProperties; + + private static final String FILE_TYPE = "import_student_order"; + + @Override + public List selectValidateConfig() { + // 联系人关系 + List contactRelationList = dictDataService.dictTypeDataList("contact_relation"); + String[] contactRelationArray = contactRelationList.stream().map(SysDictData::getDictLabel).toArray(String[]::new); + + // 性别 + List sexList = dictDataService.dictTypeDataList("sex"); + String[] sexArray = sexList.stream().map(SysDictData::getDictLabel).toArray(String[]::new); + + // 学校 + List schoolList = schoolService.selectSchoolSelect(new ReqSchoolSelect()); + String[] schoolArray = schoolList.stream().map(RespSchoolSelect::getSchoolName).toArray(String[]::new); + + // 订单类型 + List orderDetailTagList = dictDataService.dictTypeDataList("order_detail_tag"); + String[] orderDetailTagArray = orderDetailTagList.stream().map(SysDictData::getDictLabel).toArray(String[]::new); + + // 报读校区 + List campusList = deptService.campusList(); + String[] campusNameArray = campusList.stream().map(RespTreeSelect::getLabel).toArray(String[]::new); + + // 报读课程 课程-收费方式(校区) + ReqSearchScCourse reqSearchScCourse = new ReqSearchScCourse(); + reqSearchScCourse.setSale("1"); + List courseList = courseMapper.selectCourseForExport(reqSearchScCourse); + + String[] courseNameArray = courseList.stream().map(item -> { + String courseName = item.getCourseName() + "(" + item.getDepartName() + ")-" + item.getChargeTypeName(); + if (CourseChargeTypeEnum.DATE.getChargeType().equals(item.getChargeType())) { + courseName = courseName + "(" + item.getTotalFee().toString() + item.getDateUnitName() + ")"; + } else { + courseName = courseName + "(" + item.getCount().toString() + "课时," + item.getTotalFee().toString() + "元)"; + } + return courseName; + }).toArray(String[]::new); + + // 报读班级 班级(教师)-课程 + List claList = claMapper.selectForSelect(new ReqCourseClaSelect()); + String[] claNameArray = claList.stream().map(item -> item.getDeptName() + "-" + item.getClaName() + "(" + item.getStaffName() + ")" + "-" + item.getCourseName()).toArray(String[]::new); + + // 收款账户 + List receiptAccountList = receiptAccountService.select(); + String[] receiptAccountNameArray = receiptAccountList.stream().map(SysReceiptAccount::getAccountName).toArray(String[]::new); + + // 销售员工 + List staffList = staffService.staffList(null); + String[] staffNameArray = staffList.stream().map(SysStaff::getStaffName).toArray(String[]::new); + + return Lists.newArrayList( + SelectValidationData.builder().firstCol(1).lastCol(1).firstRow(2).lastRow(206).selectDataArray(contactRelationArray).build(), + SelectValidationData.builder().firstCol(3).lastCol(3).firstRow(2).lastRow(206).selectDataArray(sexArray).build(), + SelectValidationData.builder().firstCol(4).lastCol(4).firstRow(2).lastRow(206).selectDataArray(schoolArray).build(), + SelectValidationData.builder().firstCol(6).lastCol(6).firstRow(2).lastRow(206).selectDataArray(orderDetailTagArray).build(), + SelectValidationData.builder().firstCol(7).lastCol(7).firstRow(2).lastRow(206).selectDataArray(campusNameArray).build(), + SelectValidationData.builder().firstCol(8).lastCol(8).firstRow(2).lastRow(206).selectDataArray(courseNameArray).build(), + SelectValidationData.builder().firstCol(9).lastCol(9).firstRow(2).lastRow(206).selectDataArray(claNameArray).build(), + SelectValidationData.builder().firstCol(16).lastCol(16).firstRow(2).lastRow(206).selectDataArray(campusNameArray).build(), + SelectValidationData.builder().firstCol(19).lastCol(19).firstRow(2).lastRow(206).selectDataArray(receiptAccountNameArray).build(), + SelectValidationData.builder().firstCol(20).lastCol(20).firstRow(2).lastRow(206).selectDataArray(staffNameArray).build() + ); + } + + @Override + @Transactional(propagation = Propagation.REQUIRES_NEW) + public APIResponse importDataByFileId(Long importId, String fileId) throws IOException { + String path = uploadConfigProperties.getTempSaveImportPath(); + path = path + "/" + FILE_TYPE; + File file = new File(path, fileId); + if (!file.exists()) { + return APIResponse.toExceptionResponse("无法获取文件,请重试"); + } + + + LoginUser loginUser = SecurityUtils.getLoginUser(); + ImportStudentOrderListener importListener = new ImportStudentOrderListener(); + importListener.setNeedSave(true); + importListener.setLoginUserId(loginUser.getUserId()); + importListener.setLoginUser(loginUser); + importListener.setImportId(importId); + + InputStream is = new FileInputStream(file); + EasyExcel.read(is, ImportStudentOrder.class, importListener).sheet().autoTrim(true).headRowNumber(5).doRead(); + + int successRecord = importListener.getSuccessRecordSize(); + int failRecord = importListener.getFailRecordSize(); + file.delete(); + return APIResponse.toAPIResponse("导入成功" + successRecord + "条,导入失败:" + failRecord); + } + + @Override + public APIResponse checkData(MultipartFile multipartFile) throws IOException { + long fileSize = multipartFile.getSize(); + if (fileSize > 1024 * 1024 * 4) { + return APIResponse.toExceptionResponse("导入文件需小于4M"); + } + + LoginUser loginUser = SecurityUtils.getLoginUser(); + + ImportStudentOrderListener importListener = new ImportStudentOrderListener(); + importListener.setNeedSave(false); + importListener.setLoginUserId(loginUser.getUserId()); + + // 保存文件 + String fileId = IdWorker.getIdStr(); + String fileName = DateTime.now().toString("yyyyMMddHHmmss") + "_" + fileId; + String originalFileName = multipartFile.getOriginalFilename(); + String suffix = FilenameUtils.getExtension(originalFileName); + if (StringUtils.isNotEmpty(suffix)) { + fileName = fileName + "." + suffix; + } + + String path = uploadConfigProperties.getTempSaveImportPath(); + //上传文件夹 + path = path + "/" + FILE_TYPE; + File uploadFileDir = new File(path); + if (!uploadFileDir.exists()) { + uploadFileDir.mkdir(); + } + File uploadFile = new File(uploadFileDir, fileName); + FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), uploadFile); + + InputStream is = new FileInputStream(uploadFile); + EasyExcel.read(is, ImportStudentOrder.class, importListener).sheet().autoTrim(true).headRowNumber(5).doRead(); + + List saveStudentOrderList = importListener.getSuccessRecordList(); + List failStudentList = importListener.getFailRecordList(); + Map resultMap = Maps.newHashMap(); + resultMap.put("successList", saveStudentOrderList); + resultMap.put("failList", failStudentList); + resultMap.put("fileId", fileName); + + return APIResponse.toAPIResponse(resultMap); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpAccountController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpAccountController.java new file mode 100644 index 0000000..a2b7437 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpAccountController.java @@ -0,0 +1,78 @@ +package cn.xluobo.business.wechat.cp.controller; + +import cn.xluobo.business.wechat.cp.domain.req.ReqSearchWechatCpAccount; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpAccount; +import cn.xluobo.business.wechat.cp.service.BusinessWechatCpAccountService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 企业应用信息 Controller + *

+ * + * @author zhangby + * @since 2024-01-23 06:59:58 + */ +@RestController +@RequestMapping("/api/wechat/cp/account") +public class WechatCpAccountController { + @Autowired + private BusinessWechatCpAccountService wechatCpAccountService; + + /** + * 列表 + * + * @param reqSearchWechatCpAccount + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchWechatCpAccount reqSearchWechatCpAccount) { + return wechatCpAccountService.searchList(reqSearchWechatCpAccount); + } + + /** + * 详情 + * + * @param cpAccountId + * @return + */ + @GetMapping("/info/detailById/{cpAccountId}") + public APIResponse detailById(@PathVariable("cpAccountId") String cpAccountId) { + return wechatCpAccountService.detailById(cpAccountId); + } + + /** + * 添加 + * + * @param wechatCpAccount + * @return + */ + @PostMapping("/add") + public APIResponse addWechatCpAccount(@RequestBody WechatCpAccount wechatCpAccount) { + return wechatCpAccountService.addWechatCpAccount(wechatCpAccount); + } + + /** + * 修改 + * + * @param wechatCpAccount + * @return + */ + @PutMapping("/update") + public APIResponse updateWechatCpAccount(@RequestBody WechatCpAccount wechatCpAccount) { + return wechatCpAccountService.updateWechatCpAccount(wechatCpAccount); + } + + /** + * 删除 + * + * @param cpAccountIds + * @return + */ + @DeleteMapping("/delete/deleteById/{cpAccountIds}") + public APIResponse deleteById(@PathVariable("cpAccountIds") String[] cpAccountIds) { + return wechatCpAccountService.deleteById(cpAccountIds); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpContactController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpContactController.java new file mode 100644 index 0000000..7ca2164 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpContactController.java @@ -0,0 +1,78 @@ +package cn.xluobo.business.wechat.cp.controller; + +import cn.xluobo.business.wechat.cp.domain.req.ReqSearchWechatCpContact; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContact; +import cn.xluobo.business.wechat.cp.service.BusinessWechatCpContactService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 企业微信客户信息 Controller + *

+ * + * @author xluobo + * @since 2024-01-25 05:53:20 + */ +@RestController +@RequestMapping("/api/wechat/cp/contact") +public class WechatCpContactController { + @Autowired + private BusinessWechatCpContactService wechatCpContactService; + + /** + * 列表 + * + * @param reqSearchWechatCpContact + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchWechatCpContact reqSearchWechatCpContact) { + return wechatCpContactService.searchList(reqSearchWechatCpContact); + } + + /** + * 详情 + * + * @param externalUserId + * @return + */ + @GetMapping("/info/detailById/{externalUserId}") + public APIResponse detailById(@PathVariable("externalUserId") String externalUserId) { + return wechatCpContactService.detailById(externalUserId); + } + + /** + * 添加 + * + * @param wechatCpContact + * @return + */ + @PostMapping("/add") + public APIResponse addWechatCpContact(@RequestBody WechatCpContact wechatCpContact) { + return wechatCpContactService.addWechatCpContact(wechatCpContact); + } + + /** + * 修改 + * + * @param wechatCpContact + * @return + */ + @PutMapping("/update") + public APIResponse updateWechatCpContact(@RequestBody WechatCpContact wechatCpContact) { + return wechatCpContactService.updateWechatCpContact(wechatCpContact); + } + + /** + * 删除 + * + * @param externalUserIds + * @return + */ + @DeleteMapping("/delete/deleteById/{externalUserIds}") + public APIResponse deleteById(@PathVariable("externalUserIds") String[] externalUserIds) { + return wechatCpContactService.deleteById(externalUserIds); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpContactWayController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpContactWayController.java new file mode 100644 index 0000000..67ea8ef --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpContactWayController.java @@ -0,0 +1,78 @@ +package cn.xluobo.business.wechat.cp.controller; + +import cn.xluobo.business.wechat.cp.domain.req.ReqSearchWechatCpContactWay; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContactWay; +import cn.xluobo.business.wechat.cp.service.BusinessWechatCpContactWayService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 客户联系我方式 Controller + *

+ * + * @author xluobo + * @since 2024-01-26 07:13:01 + */ +@RestController +@RequestMapping("/api/wechat/cp/contactWay") +public class WechatCpContactWayController { + @Autowired + private BusinessWechatCpContactWayService wechatCpContactWayService; + + /** + * 列表 + * + * @param reqSearchWechatCpContactWay + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchWechatCpContactWay reqSearchWechatCpContactWay) { + return wechatCpContactWayService.searchList(reqSearchWechatCpContactWay); + } + + /** + * 详情 + * + * @param configId + * @return + */ + @GetMapping("/info/detailById/{configId}") + public APIResponse detailById(@PathVariable("configId") String configId) { + return wechatCpContactWayService.detailById(configId); + } + + /** + * 添加 + * + * @param wechatCpContactWay + * @return + */ + @PostMapping("/add") + public APIResponse addWechatCpContactWay(@RequestBody WechatCpContactWay wechatCpContactWay) { + return wechatCpContactWayService.addWechatCpContactWay(wechatCpContactWay); + } + + /** + * 修改 + * + * @param wechatCpContactWay + * @return + */ + @PutMapping("/update") + public APIResponse updateWechatCpContactWay(@RequestBody WechatCpContactWay wechatCpContactWay) { + return wechatCpContactWayService.updateWechatCpContactWay(wechatCpContactWay); + } + + /** + * 删除 + * + * @param configIds + * @return + */ + @DeleteMapping("/delete/deleteById/{configIds}") + public APIResponse deleteById(@PathVariable("configIds") String[] configIds) { + return wechatCpContactWayService.deleteById(configIds); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpCustomerController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpCustomerController.java new file mode 100644 index 0000000..49a81ff --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpCustomerController.java @@ -0,0 +1,37 @@ +package cn.xluobo.business.wechat.cp.controller; + +import cn.xluobo.business.wechat.cp.domain.req.ReqSearchCpCustomer; +import cn.xluobo.business.wechat.cp.service.BusinessWechatCpCustomerService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @projectName: qyxt + * @package: cn.xluobo.business.wechat.cp.controller + * @className: WechatCpCustomerController + * @author: xluobo + * @description: TODO + * @date: 2024/1/25 08:13 + */ +@RestController +@RequestMapping("/api/wechat/cp/customer") +public class WechatCpCustomerController { + + @Autowired + private BusinessWechatCpCustomerService businessWechatCpCustomerService; + + @GetMapping("/list/searchList") + /** + * 客户列表 + * + * @param reqSearchWechatCpAccount + * @return + */ + public APIResponse searchList(ReqSearchCpCustomer reqSearchCpCustomer) { + return businessWechatCpCustomerService.searchList(reqSearchCpCustomer); + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpGroupTagController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpGroupTagController.java new file mode 100644 index 0000000..5c25ad3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpGroupTagController.java @@ -0,0 +1,88 @@ +package cn.xluobo.business.wechat.cp.controller; + +import cn.xluobo.business.wechat.cp.domain.req.ReqSearchWechatCpGroupTag; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpGroupTag; +import cn.xluobo.business.wechat.cp.service.BusinessWechatCpGroupTagService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 企业微信标签 Controller + *

+ * + * @author xluobo + * @since 2024-01-25 05:55:40 + */ +@RestController +@RequestMapping("/api/wechat/cp/tag") +public class WechatCpGroupTagController { + @Autowired + private BusinessWechatCpGroupTagService wechatCpGroupTagService; + + /** + * 列表 + * + * @param reqSearchWechatCpGroupTag + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchWechatCpGroupTag reqSearchWechatCpGroupTag) { + return wechatCpGroupTagService.searchList(reqSearchWechatCpGroupTag); + } + + /** + * group select + * + * @return + */ + @GetMapping("/list/groupSelect") + public APIResponse groupSelect() { + return wechatCpGroupTagService.groupSelect(); + } + + /** + * 详情 + * + * @param tagId + * @return + */ + @GetMapping("/info/detailById/{tagId}") + public APIResponse detailById(@PathVariable("tagId") String tagId) { + return wechatCpGroupTagService.detailById(tagId); + } + + /** + * 添加 + * + * @param wechatCpGroupTag + * @return + */ + @PostMapping("/add") + public APIResponse addWechatCpGroupTag(@RequestBody WechatCpGroupTag wechatCpGroupTag) { + return wechatCpGroupTagService.addWechatCpGroupTag(wechatCpGroupTag); + } + + /** + * 修改 + * + * @param wechatCpGroupTag + * @return + */ + @PutMapping("/update") + public APIResponse updateWechatCpGroupTag(@RequestBody WechatCpGroupTag wechatCpGroupTag) { + return wechatCpGroupTagService.updateWechatCpGroupTag(wechatCpGroupTag); + } + + /** + * 删除 + * + * @param tagIds + * @return + */ + @DeleteMapping("/delete/deleteById/{tagIds}") + public APIResponse deleteById(@PathVariable("tagIds") String[] tagIds) { + return wechatCpGroupTagService.deleteById(tagIds); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpUserController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpUserController.java new file mode 100644 index 0000000..e6fcb8c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/controller/WechatCpUserController.java @@ -0,0 +1,36 @@ +package cn.xluobo.business.wechat.cp.controller; + +import cn.xluobo.business.sc.course.domain.req.ReqSelect; +import cn.xluobo.business.wechat.cp.service.BusinessWechatCpUserService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 企业微信通讯录 + * @projectName: qyxt + * @package: cn.xluobo.business.wechat.cp.controller + * @className: WechatCpUserController + * @author: xluobo + * @description: TODO + * @date: 2024/1/30 00:29 + */ +@RestController +@RequestMapping("/api/wechat/cp/user") +public class WechatCpUserController { + + @Autowired + private BusinessWechatCpUserService businessWechatCpUserService; + + /** + * 前端select + * + * @return + */ + @GetMapping("/list/userSelect") + public APIResponse cpUserSelect(ReqSelect reqSelect) { + return businessWechatCpUserService.cpUserSelect(reqSelect); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpBase.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpBase.java new file mode 100644 index 0000000..d6488af --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpBase.java @@ -0,0 +1,17 @@ +package cn.xluobo.business.wechat.cp.domain.cp; + +import lombok.Data; + +/** + * @projectName: qyxt + * @package: cn.xluobo.business.wechat.cp.domain.cp + * @className: ReqCpBase + * @author: xluobo + * @description: TODO + * @date: 2024/1/25 18:50 + */ +@Data +public class ReqCpBase { + private String corpId; + private Integer agentId; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpExternalContact.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpExternalContact.java new file mode 100644 index 0000000..0d43735 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpExternalContact.java @@ -0,0 +1,21 @@ +package cn.xluobo.business.wechat.cp.domain.cp; + + +import lombok.Data; + +import java.util.List; + +/** + * @projectName: qyxt + * @package: cn.xluobo.business.wechat.cp.domain.cp + * @className: ReqCpExternalContact + * @author: xluobo + * @description: TODO + * @date: 2024/1/25 18:50 + */ +@Data +public class ReqCpExternalContact extends ReqCpBase { + private List userIdList; + private String cursor; + private Integer limit; +} \ No newline at end of file diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpUserDetail.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpUserDetail.java new file mode 100644 index 0000000..1b58527 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpUserDetail.java @@ -0,0 +1,18 @@ +package cn.xluobo.business.wechat.cp.domain.cp; + +import lombok.Data; + +/** + * @projectName: qyxt + * @package: cn.xluobo.business.wechat.cp.domain.cp + * @className: ReqCpUser + * @author: xluobo + * @description: TODO + * @date: 2024/1/27 18:41 + */ +@Data +public class ReqCpUserDetail extends ReqCpBase{ + + private String userId; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpUserList.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpUserList.java new file mode 100644 index 0000000..46642bd --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/cp/ReqCpUserList.java @@ -0,0 +1,27 @@ +package cn.xluobo.business.wechat.cp.domain.cp; + +import lombok.Data; + +import static cn.xluobo.business.wechat.cp.repo.enums.WechatCpAgentSecretTypeEnum.ADDRESS_BOOK_SECRET_AGENT; + +/** + * @projectName: qyxt + * @package: cn.xluobo.business.wechat.cp.domain.cp + * @className: ReqCpUser + * @author: xluobo + * @description: TODO + * @date: 2024/1/27 18:41 + */ +@Data +public class ReqCpUserList extends ReqCpBase { + + /** + * 企业通讯录应用id + */ + private Integer addressBookAgentId = ADDRESS_BOOK_SECRET_AGENT.getAgentId(); + + private String cursor; + + private Integer limit; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchCpCustomer.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchCpCustomer.java new file mode 100644 index 0000000..7f36e36 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchCpCustomer.java @@ -0,0 +1,27 @@ +package cn.xluobo.business.wechat.cp.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +/** + * 获取客户列表 + * @projectName: qyxt + * @package: cn.xluobo.business.wechat.cp.dmain.req + * @className: ReqSearchCustomer + * @author: xluobo + * @description: TODO + * @date: 2024/1/25 10:20 + */ +@Data +public class ReqSearchCpCustomer extends ReqPageBase { + + /** + * 企业微信员工id + */ + private String cpUserIds; + + /** + * 用于分页查询的游标 + */ + private String cpCursor; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpAccount.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpAccount.java new file mode 100644 index 0000000..6d32cd6 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpAccount.java @@ -0,0 +1,17 @@ +package cn.xluobo.business.wechat.cp.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchWechatCpAccount extends ReqPageBase implements Serializable { + private String companyName; + private String corpId; + private String agentId; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpContact.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpContact.java new file mode 100644 index 0000000..b521ef8 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpContact.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.wechat.cp.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchWechatCpContact extends ReqPageBase implements Serializable { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpContactFollowTag.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpContactFollowTag.java new file mode 100644 index 0000000..a70ee2b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpContactFollowTag.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.wechat.cp.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchWechatCpContactFollowTag extends ReqPageBase implements Serializable { + private String externalUserId; + private String cpUserId; + private String groupName; + private String tagName; + private String type; + private String tagId; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpContactWay.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpContactWay.java new file mode 100644 index 0000000..38846fc --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpContactWay.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.wechat.cp.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchWechatCpContactWay extends ReqPageBase implements Serializable { + private String scene; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpGroupTag.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpGroupTag.java new file mode 100644 index 0000000..17a259c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpGroupTag.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.wechat.cp.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchWechatCpGroupTag extends ReqPageBase implements Serializable { + private String groupId; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpUser.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpUser.java new file mode 100644 index 0000000..7770fc3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/ReqSearchWechatCpUser.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.wechat.cp.domain.req; + +import cn.xluobo.core.page.ReqPageBase; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:30 + */ +@Data +public class ReqSearchWechatCpUser extends ReqPageBase implements Serializable { + private String status; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/RespWechatCpContactWay.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/RespWechatCpContactWay.java new file mode 100644 index 0000000..b0b1a46 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/domain/req/RespWechatCpContactWay.java @@ -0,0 +1,21 @@ +package cn.xluobo.business.wechat.cp.domain.req; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContactWay; +import lombok.Data; + +/** + * @projectName: qyxt + * @package: cn.xluobo.business.wechat.cp.domain.req + * @className: RespWechatCpContactWay + * @author: xluobo + * @description: TODO + * @date: 2024/1/31 13:37 + */ +@Data +public class RespWechatCpContactWay extends WechatCpContactWay { + + private String userNames; + + private String addTagNames; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/enums/WechatCpAgentSecretTypeEnum.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/enums/WechatCpAgentSecretTypeEnum.java new file mode 100644 index 0000000..5f8561b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/enums/WechatCpAgentSecretTypeEnum.java @@ -0,0 +1,24 @@ +package cn.xluobo.business.wechat.cp.repo.enums; + +import lombok.Getter; + +/** + * 企业微信秘钥类型 + * @projectName: qyxt + * @package: cn.xluobo.business.wechat.cp.repo.enums + * @className: WechatCpAgentTypeEnum + * @author: xluobo + * @description: TODO + * @date: 2024/1/28 23:12 + */ +@Getter +public enum WechatCpAgentSecretTypeEnum { + + ADDRESS_BOOK_SECRET_AGENT(1); + + private final Integer agentId; + + WechatCpAgentSecretTypeEnum(Integer agentId) { + this.agentId = agentId; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpAccountMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpAccountMapper.java new file mode 100644 index 0000000..97c02be --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpAccountMapper.java @@ -0,0 +1,25 @@ +package cn.xluobo.business.wechat.cp.repo.mapper; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpAccount; +import com.baomidou.mybatisplus.annotation.SqlParser; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 企业应用信息 Mapper 接口 + *

+ * + * @author zhangby + * @since 2024-01-23 06:59:58 + */ +public interface WechatCpAccountMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + + @SqlParser(filter = true) + List selectAllInUserCpAccount(); + + @SqlParser(filter = true) + WechatCpAccount selectByCropIdAgentIdIgnoreTenant(@Param("corpId") String corpId, @Param("agentId") String agentId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactFollowMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactFollowMapper.java new file mode 100644 index 0000000..387a57d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactFollowMapper.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.wechat.cp.repo.mapper; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContactFollow; + +/** + *

+ * 外部联系人对应大员工信息 Mapper 接口 + *

+ * + * @author xluobo + * @since 2024-01-25 05:53:25 + */ +public interface WechatCpContactFollowMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactFollowTagMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactFollowTagMapper.java new file mode 100644 index 0000000..8c57778 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactFollowTagMapper.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.wechat.cp.repo.mapper; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContactFollowTag; + +/** + *

+ * 员工给外部联系人添加的标签 Mapper 接口 + *

+ * + * @author xluobo + * @since 2024-01-25 10:46:17 + */ +public interface WechatCpContactFollowTagMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactMapper.java new file mode 100644 index 0000000..f1aadfc --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactMapper.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.wechat.cp.repo.mapper; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContact; + +/** + *

+ * 企业微信客户信息 Mapper 接口 + *

+ * + * @author xluobo + * @since 2024-01-25 05:53:20 + */ +public interface WechatCpContactMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactWayMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactWayMapper.java new file mode 100644 index 0000000..b26f145 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpContactWayMapper.java @@ -0,0 +1,23 @@ +package cn.xluobo.business.wechat.cp.repo.mapper; + +import cn.xluobo.business.wechat.cp.domain.req.ReqSearchWechatCpContactWay; +import cn.xluobo.business.wechat.cp.domain.req.RespWechatCpContactWay; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContactWay; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 客户联系我方式 Mapper 接口 + *

+ * + * @author xluobo + * @since 2024-01-26 07:13:01 + */ +public interface WechatCpContactWayMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + + List selectForSearchTable(@Param("reqSearchWechatCpContactWay") ReqSearchWechatCpContactWay reqSearchWechatCpContactWay, Page page); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpGroupMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpGroupMapper.java new file mode 100644 index 0000000..494f4e3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpGroupMapper.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.wechat.cp.repo.mapper; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpGroup; + +/** + *

+ * 企业微信标签组 Mapper 接口 + *

+ * + * @author xluobo + * @since 2024-01-25 05:53:33 + */ +public interface WechatCpGroupMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpGroupTagMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpGroupTagMapper.java new file mode 100644 index 0000000..3e71e92 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpGroupTagMapper.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.wechat.cp.repo.mapper; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpGroupTag; + +/** + *

+ * 企业微信标签 Mapper 接口 + *

+ * + * @author xluobo + * @since 2024-01-25 05:55:40 + */ +public interface WechatCpGroupTagMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpUserMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpUserMapper.java new file mode 100644 index 0000000..e47743c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpUserMapper.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.wechat.cp.repo.mapper; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpUser; + +/** + *

+ * 企业微信成员 Mapper 接口 + *

+ * + * @author xluobo + * @since 2024-01-26 08:08:32 + */ +public interface WechatCpUserMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpAccountMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpAccountMapper.xml new file mode 100644 index 0000000..90a651d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpAccountMapper.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactFollowMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactFollowMapper.xml new file mode 100644 index 0000000..3df7ba2 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactFollowMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactFollowTagMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactFollowTagMapper.xml new file mode 100644 index 0000000..2a126f0 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactFollowTagMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactMapper.xml new file mode 100644 index 0000000..1f6783a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactWayMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactWayMapper.xml new file mode 100644 index 0000000..010b2ca --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpContactWayMapper.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpGroupMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpGroupMapper.xml new file mode 100644 index 0000000..c49e3dc --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpGroupMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpGroupTagMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpGroupTagMapper.xml new file mode 100644 index 0000000..3715702 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpGroupTagMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpUserMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpUserMapper.xml new file mode 100644 index 0000000..b87c5cd --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapping/WechatCpUserMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpAccount.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpAccount.java new file mode 100644 index 0000000..e1c2d63 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpAccount.java @@ -0,0 +1,109 @@ +package cn.xluobo.business.wechat.cp.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 企业应用信息 + *

+ * + * @author zhangby + * @since 2024-01-23 06:59:58 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("wechat_cp_account") +public class WechatCpAccount implements Serializable { + + + @TableId(value = "cp_account_id", type = IdType.AUTO) + private Integer cpAccountId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private Long tenantId; + + /** + * 企业名称 + */ + @TableField("company_name") + private String companyName; + + /** + * 企业ID + */ + @TableField("corp_id") + private String corpId; + + /** + * 应用id + */ + @TableField("agent_id") + private Integer agentId; + + /** + * 应用密钥 + */ + @TableField("agent_secret") + private String agentSecret; + + /** + * 回调url + */ + @TableField("call_back_url") + private String callBackUrl; + + /** + * 回调token + */ + @TableField("call_back_token") + private String callBackToken; + + /** + * 回调Key + */ + @TableField("call_back_key") + private String callBackKey; + + /** + * 状态 1在用 0停用 + */ + @TableField("in_use") + private String inUse; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContact.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContact.java new file mode 100644 index 0000000..6c8973f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContact.java @@ -0,0 +1,145 @@ +package cn.xluobo.business.wechat.cp.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.bean.external.contact.ExternalContact; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 企业微信客户信息 + *

+ * + * @author xluobo + * @since 2024-01-25 05:53:20 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("wechat_cp_contact") +public class WechatCpContact implements Serializable { + + + /** + * 外部联系人的userid + */ + @TableId(value = "external_user_id", type = IdType.INPUT) + private String externalUserId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 企业ID + */ + @TableField("corp_id") + private String corpId; + + /** + * 外部联系人的名称 + */ + @TableField("name") + private String name; + + /** + * 外部联系人头像 + */ + @TableField("avatar") + private String avatar; + + /** + * 外部联系人的类型,1表示该外部联系人是微信用户,2表示该外部联系人是企业微信用户 + */ + @TableField("type") + private Integer type; + + /** + * 外部联系人性别 0-未知 1-男性 2-女性 + */ + @TableField("gender") + private Integer gender; + + /** + * 外部联系人在微信开放平台的唯一身份标识(微信unionid) + */ + @TableField("unionid") + private String unionid; + + /** + * 外部联系人的职位 + */ + @TableField("position") + private String position; + + /** + * 外部联系人所在企业的简称 + */ + @TableField("corp_name") + private String corpName; + + /** + * 外部联系人所在企业的主体名称 + */ + @TableField("corp_full_name") + private String corpFullName; + + /** + * 删除标志(1删除 0在用) + */ + @TableField("delete_flag") + private String deleteFlag; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + /** + * 接口返回信息转换为数据库存储信息 + * @param externalContact + * @return + */ + public static WechatCpContact transferByCpBean(ExternalContact externalContact) { + WechatCpContact wechatCpContact = new WechatCpContact(); + wechatCpContact.setExternalUserId(externalContact.getExternalUserId()); + wechatCpContact.setName(externalContact.getName()); + wechatCpContact.setAvatar(externalContact.getAvatar()); + wechatCpContact.setType(externalContact.getType()); + wechatCpContact.setGender(externalContact.getGender()); + wechatCpContact.setUnionid(externalContact.getUnionId()); + wechatCpContact.setPosition(externalContact.getPosition()); + wechatCpContact.setCorpName(externalContact.getCorpName()); + wechatCpContact.setCorpFullName(externalContact.getCorpFullName()); + wechatCpContact.setDeleteFlag("0"); + return wechatCpContact; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactFollow.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactFollow.java new file mode 100644 index 0000000..adcd812 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactFollow.java @@ -0,0 +1,110 @@ +package cn.xluobo.business.wechat.cp.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.bean.external.contact.FollowedUser; + +import java.io.Serializable; + +/** + *

+ * 外部联系人对应大员工信息 + *

+ * + * @author xluobo + * @since 2024-01-25 05:53:25 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("wechat_cp_contact_follow") +public class WechatCpContactFollow implements Serializable { + + + /** + * 外部联系人的userid + */ + @TableId(value = "external_user_id", type = IdType.INPUT) + private String externalUserId; + + /** + * 添加了此外部联系人的企业成员userid + */ + @TableId(value = "cp_user_id", type = IdType.INPUT) + private String cpUserId; + + /** + * 此外部联系人的备注 + */ + @TableField("remark") + private String remark; + + /** + * 外部联系人的描述 + */ + @TableField("description") + private String description; + + /** + * 外部联系人的描述 + */ + @TableField("create_time") + private Long createTime; + + /** + * 该成员对此微信客户备注的企业名称(仅微信客户有该字段) + */ + @TableField("remark_corp_name") + private String remarkCorpName; + + /** + * 该成员对此客户备注的手机号码 + */ + @TableField("remark_mobiles") + private String remarkMobiles; + + /** + * 该成员添加此客户的来源 + */ + @TableField("add_way") + private String addWay; + + /** + * 发起添加的userid,如果成员主动添加,为成员的userid;如果是客户主动添加,则为客户的外部联系人userid;如果是内部成员共享/管理员分配,则为对应的成员/管理员userid + */ + @TableField("oper_userid") + private String operUserid; + + /** + * 企业自定义的state参数,用于区分客户具体是通过哪个「联系我」或获客链接添加 + */ + @TableField("state") + private String state; + + /** + * 接口返回信息转换为数据库存储信息 + * @param externalUserId + * @param followedUser + * @return + */ + public static WechatCpContactFollow transferByCpBean(String externalUserId, + FollowedUser followedUser) { + WechatCpContactFollow wechatCpContactFollow = new WechatCpContactFollow(); + wechatCpContactFollow.setExternalUserId(externalUserId); + wechatCpContactFollow.setCpUserId(followedUser.getUserId()); + wechatCpContactFollow.setRemark(followedUser.getRemark()); + wechatCpContactFollow.setDescription(followedUser.getDescription()); + wechatCpContactFollow.setCreateTime(followedUser.getCreateTime()); + wechatCpContactFollow.setRemarkCorpName(followedUser.getRemarkCorpName()); + wechatCpContactFollow.setRemarkMobiles(String.join(",",followedUser.getRemarkMobiles())); + wechatCpContactFollow.setAddWay(followedUser.getAddWay()); + wechatCpContactFollow.setOperUserid(followedUser.getOperatorUserId()); + wechatCpContactFollow.setState(followedUser.getState()); + return wechatCpContactFollow; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactFollowTag.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactFollowTag.java new file mode 100644 index 0000000..65cea8a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactFollowTag.java @@ -0,0 +1,102 @@ +package cn.xluobo.business.wechat.cp.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.google.common.collect.Lists; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.bean.external.contact.FollowedUser; + +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 员工给外部联系人添加的标签 + *

+ * + * @author xluobo + * @since 2024-01-25 10:46:17 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("wechat_cp_contact_follow_tag") +public class WechatCpContactFollowTag implements Serializable { + + + /** + * 逐渐 + */ + @TableId(value = "follow_tag_id", type = IdType.ASSIGN_ID) + private Long followTagId; + + /** + * 外部联系人的userid + */ + @TableField("external_user_id") + private String externalUserId; + + /** + * 添加了此外部联系人的企业成员userid + */ + @TableField("cp_user_id") + private String cpUserId; + + /** + * 该成员添加此外部联系人所打标签的分组名称 + */ + @TableField("group_name") + private String groupName; + + /** + * 该成员添加此外部联系人所打标签名称 + */ + @TableField("tag_name") + private String tagName; + + /** + * 该成员添加此外部联系人所打标签类型, 1-企业设置,2-用户自定义,3-规则组标签 + */ + @TableField("type") + private Integer type; + + /** + * 该成员添加此外部联系人所打企业标签的id,用户自定义类型标签(type=2)不返回 + */ + @TableField("tag_id") + private String tagId; + + /** + * 接口返回信息转换为数据库存储信息 + * @param externalUserId + * @param followedUser + * @return + */ + public static List transferByCpBean(String externalUserId, + FollowedUser followedUser) { + List followTagList = Lists.newArrayList(); + + FollowedUser.Tag[] userTags = followedUser.getTags(); + if (null == userTags) { + return followTagList; + } + for (FollowedUser.Tag userTag : userTags) { + WechatCpContactFollowTag followTag = new WechatCpContactFollowTag(); + followTag.setExternalUserId(externalUserId); + followTag.setCpUserId(followedUser.getUserId()); + followTag.setGroupName(userTag.getGroupName()); + followTag.setTagName(userTag.getTagName()); + followTag.setType(userTag.getType()); + followTag.setTagId(userTag.getTagId()); + + followTagList.add(followTag); + } + + + return followTagList; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactWay.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactWay.java new file mode 100644 index 0000000..0a6497a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactWay.java @@ -0,0 +1,259 @@ +package cn.xluobo.business.wechat.cp.repo.model; + +import cn.xluobo.core.api.APIResponse; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.bean.external.WxCpContactWayInfo; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Date; + +/** + *

+ * 客户联系我方式 + *

+ * + * @author xluobo + * @since 2024-01-26 07:13:01 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("wechat_cp_contact_way") +public class WechatCpContactWay implements Serializable { + + + /** + * 新增联系方式的配置id + */ + @TableId(value = "config_id", type = IdType.INPUT) + private String configId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 联系我二维码链接,仅在scene为2时返回 + */ + @TableField("qr_code") + private String qrCode; + + /** + * 名称 + */ + @TableField("contact_way_name") + private String contactWayName; + + /** + * 联系方式类型,1-单人, 2-多人 + */ + @TableField("type") + private Integer type; + + /** + * 场景,1-在小程序中联系,2-通过二维码联系 + */ + @TableField("scene") + private Integer scene; + + /** + * 在小程序中联系时使用的控件样式 + */ + @TableField("style") + private Integer style; + + /** + * 联系方式的备注信息,用于助记,不超过30个字符 + */ + @TableField("remark") + private String remark; + + /** + * 外部客户添加时是否无需验证,默认为true + */ + @TableField("skip_verify") + private Boolean skipVerify; + + /** + * 企业自定义的state参数,用于区分不同的添加渠道 + */ + @TableField("state") + private String state; + + /** + * 使用该联系方式的用户userID列表,在type为1时为必填,且只能有一个 + */ + @TableField("user") + private String user; + + /** + * 使用该联系方式的部门id列表,只在type为2时有效 + */ + @TableField("party") + private String party; + + /** + * 需要自动添加的标签id + */ + @TableField("add_tag") + private String addTag; + + /** + * 是否临时会话模式,true表示使用临时会话模式,默认为false + */ + @TableField("is_temp") + private Boolean isTemp; + + /** + * 临时会话二维码有效期,以秒为单位。该参数仅在is_temp为true时有效,默认7天,最多为14天 + */ + @TableField("expires_in") + private Integer expiresIn; + + /** + * 临时会话有效期,以秒为单位。该参数仅在is_temp为true时有效,默认为添加好友后24小时,最多为14天 + */ + @TableField("chat_expires_in") + private Integer chatExpiresIn; + + /** + * 可进行临时会话的客户unionid,该参数仅在is_temp为true时有效,如不指定则不进行限制 + */ + @TableField("unionid") + private String unionid; + + /** + * 是否开启同一外部企业客户只能添加同一个员工,默认为否,开启后,同一个企业的客户会优先添加到同一个跟进人 + */ + @TableField("unionidis_exclusive") + private Boolean unionidisExclusive; + + /** + * 结束语,会话结束时自动发送给客户,可参考“结束语定义”,仅在is_temp为true时有效 + */ + @TableField("conclusions") + private String conclusions; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + public void setAddTags(String[] addTag) { + if (null != addTag && addTag.length > 0) { + this.addTag = String.join(",", addTag); + } + } + + public void setUsers(String[] user) { + if (null != user && user.length > 0) { + this.user = String.join(",", user); + } + } + + public String[] getUsers() { + if(StringUtils.isNotEmpty(user)) { + return user.split(","); + } + return new String[]{}; + } + + public String[] getAddTags() { + if(StringUtils.isNotEmpty(addTag)) { + return addTag.split(","); + } + return new String[]{}; + } + + /** + * 校验参数 + * + * @return + */ + public APIResponse checkParam() { + if (null == type) { + return APIResponse.toExceptionResponse("请选择联系方式类型"); + } else if (null == scene) { + return APIResponse.toExceptionResponse("请选择联系场景"); + } else if (StringUtils.isAnyEmpty(remark, state)) { + return APIResponse.toExceptionResponse("请填写必要参数"); + } else if (StringUtils.isAllEmpty(user, party)) { + return APIResponse.toExceptionResponse("请选择可添加的联系人或部门"); + } + return APIResponse.toOkResponse(); + } + + /** + * db实体类 转换为 企业微信接口 + * + * @return + */ + public WxCpContactWayInfo transferWxCpContactWay() { + WxCpContactWayInfo wxCpContactWayInfo = new WxCpContactWayInfo(); + WxCpContactWayInfo.ContactWay contactWay = new WxCpContactWayInfo.ContactWay(); + contactWay.setConfigId(this.configId); + if (1 == this.type) { + contactWay.setType(WxCpContactWayInfo.TYPE.SINGLE); + } else if (2 == this.type) { + contactWay.setType(WxCpContactWayInfo.TYPE.MULTI); + } + if (1 == this.scene) { + contactWay.setScene(WxCpContactWayInfo.SCENE.MINIPROGRAM); + } else if (2 == this.scene) { + contactWay.setScene(WxCpContactWayInfo.SCENE.QRCODE); + } + contactWay.setStyle(this.type); + contactWay.setRemark(this.contactWayName); + contactWay.setSkipVerify(this.skipVerify); + contactWay.setState(this.state); + if (StringUtils.isNotEmpty(this.user)) { + contactWay.setUsers(Arrays.asList(this.user.split(","))); + } + if (StringUtils.isNotEmpty(this.party)) { + contactWay.setParties(Arrays.asList(this.party.split(","))); + } + + contactWay.setIsTemp(this.isTemp); + if (this.isTemp) { + contactWay.setExpiresIn(this.expiresIn); + contactWay.setChatExpiresIn(this.chatExpiresIn); + contactWay.setUnionId(this.unionid); + if (StringUtils.isNotEmpty(this.conclusions)) { + contactWay.setConclusions(JSONObject.parseObject(this.conclusions, WxCpContactWayInfo.ContactWay.Conclusion.class)); + } + } + + wxCpContactWayInfo.setContactWay(contactWay); + return wxCpContactWayInfo; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpGroup.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpGroup.java new file mode 100644 index 0000000..c580ea4 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpGroup.java @@ -0,0 +1,104 @@ +package cn.xluobo.business.wechat.cp.repo.model; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.bean.external.WxCpUserExternalTagGroupList; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 企业微信标签组 + *

+ * + * @author xluobo + * @since 2024-01-25 05:53:33 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("wechat_cp_group") +public class WechatCpGroup implements Serializable { + + + /** + * 标签组id + */ + @TableId(value = "group_id", type = IdType.INPUT) + private String groupId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 标签组名 + */ + @TableField("group_name") + private String groupName; + + /** + * 标签分组类型(1:客户企业标签;2:群标签;3:客户个人标签) + */ + @TableField("group_tag_type") + private Integer groupTagType; + + /** + * 标签组排序的次序值,order值大的排序靠前,有效的值范围是[0, 2^32) + */ + @TableField("group_order") + private Long groupOrder; + + /** + * 标签组是否已经被删除,只在指定tag_id进行查询时返回 + */ + @TableField("delete_flag") + @TableLogic + private String deleteFlag; + + /** + * 创建者 + */ + @TableField("create_user") + private String createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Long createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private String lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + /** + * 接口返回信息转换为数据库存储信息 + * + * @param tagGroup + * @return + */ + public static WechatCpGroup transferByCpBean(WxCpUserExternalTagGroupList.TagGroup tagGroup) { + WechatCpGroup wxCpGroup = new WechatCpGroup(); + wxCpGroup.setGroupId(tagGroup.getGroupId()); + wxCpGroup.setGroupName(tagGroup.getGroupName()); + wxCpGroup.setGroupOrder(tagGroup.getOrder()); + wxCpGroup.setDeleteFlag((null != tagGroup.getDeleted() && tagGroup.getDeleted()) ? "1" : "0"); + wxCpGroup.setCreateTime(tagGroup.getCreateTime()); + + return wxCpGroup; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpGroupTag.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpGroupTag.java new file mode 100644 index 0000000..51aea33 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpGroupTag.java @@ -0,0 +1,116 @@ +package cn.xluobo.business.wechat.cp.repo.model; + +import cn.xluobo.core.domain.select.GroupSelect; +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.bean.external.WxCpUserExternalTagGroupList; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 企业微信标签 + *

+ * + * @author xluobo + * @since 2024-01-25 05:55:40 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("wechat_cp_group_tag") +public class WechatCpGroupTag implements Serializable { + + + /** + * 微信端返回的id + */ + @TableId(value = "tag_id", type = IdType.INPUT) + private String tagId; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 标签组id + */ + @TableField("group_id") + private String groupId; + + /** + * 标签名 + */ + @TableField("name") + private String name; + + /** + * 标签组排序的次序值,order值大的排序靠前,有效的值范围是[0, 2^32) + */ + @TableField("tag_order") + private Long tagOrder; + + /** + * 标签组是否已经被删除,只在指定tag_id进行查询时返回 + */ + @TableField("delete_flag") + @TableLogic + private String deleteFlag; + + /** + * 创建者 + */ + @TableField("create_user") + private Long createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Long createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private Long lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + /** + * 接口返回信息转换为数据库存储信息 + * + * @param tag + * @return + */ + public static WechatCpGroupTag transferByCpBean(String groupId, WxCpUserExternalTagGroupList.TagGroup.Tag tag) { + WechatCpGroupTag groupTag = new WechatCpGroupTag(); + groupTag.setTagId(tag.getId()); + groupTag.setGroupId(groupId); + groupTag.setName(tag.getName()); + groupTag.setTagOrder(tag.getOrder()); + groupTag.setDeleteFlag((null != tag.getDeleted() && tag.getDeleted()) ? "1" : "0"); + groupTag.setCreateTime(tag.getCreateTime()); + return groupTag; + } + + /** + * 转换为group select item + * @return GroupSelect.GroupItem + */ + public GroupSelect.GroupItem transferGroupSelectItem() { + GroupSelect.GroupItem groupItem = new GroupSelect.GroupItem(); + groupItem.setItemId(this.tagId); + groupItem.setItemName(this.name); + return groupItem; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpUser.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpUser.java new file mode 100644 index 0000000..1970b47 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpUser.java @@ -0,0 +1,153 @@ +package cn.xluobo.business.wechat.cp.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.bean.WxCpUser; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 企业微信成员 + *

+ * + * @author xluobo + * @since 2024-01-26 08:08:32 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("wechat_cp_user") +public class WechatCpUser implements Serializable { + + + /** + * 成员UserID + */ + @TableId(value = "userid", type = IdType.INPUT) + private String userid; + + /** + * 所属租户 + */ + @TableField("tenant_id") + private String tenantId; + + /** + * 成员名称 + */ + @TableField("name") + private String name; + + /** + * 手机号码 + */ + @TableField("mobile") + private String mobile; + + /** + * 成员所属部门id列表 + */ + @TableField("department") + private String department; + + /** + * 部门内的排序值,默认为0。数量必须和department一致,数值越大排序越前面。值范围是[0, 2^32) + */ + @TableField("user_order") + private String userOrder; + + /** + * 职务信息 + */ + @TableField("position") + private String position; + + /** + * 性别 0表示未定义,1表示男性,2表示女性 + */ + @TableField("gender") + private String gender; + + /** + * 邮箱 + */ + @TableField("email") + private String email; + + /** + * 企业邮箱 + */ + @TableField("biz_mail") + private String bizMail; + + /** + * 头像url + */ + @TableField("avatar") + private String avatar; + + /** + * 激活状态: 1=已激活,2=已禁用,4=未激活,5=退出企业 + */ + @TableField("status") + private String status; + + /** + * 主部门,仅当应用对主部门有查看权限时返回 + */ + @TableField("main_department") + private String mainDepartment; + + /** + * 创建者 + */ + @TableField("create_user") + private String createUser; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新者 + */ + @TableField("last_update_user") + private String lastUpdateUser; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + public static WechatCpUser transferByCpBean(WxCpUser wxCpUser) { + WechatCpUser wechatCpUser = new WechatCpUser(); + wechatCpUser.setUserid(wxCpUser.getUserId()); + wechatCpUser.setName(wxCpUser.getName()); + wechatCpUser.setMobile(wxCpUser.getMobile()); + + wechatCpUser.setDepartment(StringUtils.join(wxCpUser.getDepartIds(), ",")); + wechatCpUser.setUserOrder(StringUtils.join(wxCpUser.getOrders(), ",")); + wechatCpUser.setPosition(wxCpUser.getPosition()); + if (null != wxCpUser.getGender()) { + wechatCpUser.setGender(wxCpUser.getGender().getCode()); + } + wechatCpUser.setEmail(wxCpUser.getEmail()); + wechatCpUser.setBizMail(wxCpUser.getBizMail()); + wechatCpUser.setAvatar(wxCpUser.getAvatar()); + if (null != wxCpUser.getStatus()) { + wechatCpUser.setStatus(wxCpUser.getStatus().toString()); + } + return wechatCpUser; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpAccountService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpAccountService.java new file mode 100644 index 0000000..eb00388 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpAccountService.java @@ -0,0 +1,121 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.domain.req.ReqSearchWechatCpAccount; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpAccount; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.Date; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessWechatCpAccountService { + + @Autowired + private IWechatCpAccountService wechatCpAccountService; + + /** + * 查询 + * + * @param reqSearchWechatCpAccount + * @return + */ + public APIResponse searchList(ReqSearchWechatCpAccount reqSearchWechatCpAccount) { + QueryWrapper qw = new QueryWrapper(); + if(StringUtils.isNotEmpty(reqSearchWechatCpAccount.getCompanyName())){ + qw.like("company_name",reqSearchWechatCpAccount.getCompanyName()); + } + if(StringUtils.isNotEmpty(reqSearchWechatCpAccount.getCorpId())){ + qw.eq("corp_id",reqSearchWechatCpAccount.getCorpId()); + } + if(StringUtils.isNotEmpty(reqSearchWechatCpAccount.getAgentId())){ + qw.eq("agent_id",reqSearchWechatCpAccount.getAgentId()); + } + RespPage page = new RespPage(reqSearchWechatCpAccount.getPageNum(), reqSearchWechatCpAccount.getPageSize()); + RespPage listPage = wechatCpAccountService.page(page, qw); + return APIResponse.toAPIResponse(listPage); + } + + /** + * 详情 + * + * @param cpAccountId + * @return + */ + public APIResponse detailById(String cpAccountId) { + if (null == cpAccountId) { + return APIResponse.toAPIResponse(null); + } + WechatCpAccount detailInfo = wechatCpAccountService.getById(cpAccountId); + return APIResponse.toAPIResponse(detailInfo); + } + + /** + * 添加 + * + * @param wechatCpAccount + * @return + */ + public APIResponse addWechatCpAccount(WechatCpAccount wechatCpAccount) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + wechatCpAccount.setCreateUser(loginUser.getUserId()); + boolean addWechatCpAccount = wechatCpAccountService.save(wechatCpAccount); + if (addWechatCpAccount) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 更新 + * + * @param wechatCpAccount + * @return + */ + public APIResponse updateWechatCpAccount(WechatCpAccount wechatCpAccount) { + if (null == wechatCpAccount.getCpAccountId()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + wechatCpAccount.setLastUpdateUser(loginUser.getUserId()); + wechatCpAccount.setLastUpdateTime(new Date()); + boolean updateWechatCpAccount = wechatCpAccountService.updateById(wechatCpAccount); + if (updateWechatCpAccount) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 删除 + * + * @param cpAccountIds + * @return + */ + public APIResponse deleteById(String[] cpAccountIds) { + if (null == cpAccountIds || cpAccountIds.length == 0) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + boolean deleteWechatCpAccount = wechatCpAccountService.removeByIds(Arrays.asList(cpAccountIds)); + if (deleteWechatCpAccount) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpContactService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpContactService.java new file mode 100644 index 0000000..db44391 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpContactService.java @@ -0,0 +1,111 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.domain.req.ReqSearchWechatCpContact; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContact; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.Date; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessWechatCpContactService { + + @Autowired + private IWechatCpContactService wechatCpContactService; + + /** + * 查询 + * + * @param reqSearchWechatCpContact + * @return + */ + public APIResponse searchList(ReqSearchWechatCpContact reqSearchWechatCpContact) { + QueryWrapper qw = new QueryWrapper(); + RespPage page = new RespPage(reqSearchWechatCpContact.getPageNum(), reqSearchWechatCpContact.getPageSize()); + RespPage listPage = wechatCpContactService.page(page, qw); + return APIResponse.toAPIResponse(listPage); + } + + /** + * 详情 + * + * @param externalUserId + * @return + */ + public APIResponse detailById(String externalUserId) { + if (null == externalUserId) { + return APIResponse.toAPIResponse(null); + } + WechatCpContact detailInfo = wechatCpContactService.getById(externalUserId); + return APIResponse.toAPIResponse(detailInfo); + } + + /** + * 添加 + * + * @param wechatCpContact + * @return + */ + public APIResponse addWechatCpContact(WechatCpContact wechatCpContact) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + wechatCpContact.setCreateUser(loginUser.getUserId()); + boolean addWechatCpContact = wechatCpContactService.save(wechatCpContact); + if (addWechatCpContact) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 更新 + * + * @param wechatCpContact + * @return + */ + public APIResponse updateWechatCpContact(WechatCpContact wechatCpContact) { + if (null == wechatCpContact.getExternalUserId()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + wechatCpContact.setLastUpdateUser(loginUser.getUserId()); + wechatCpContact.setLastUpdateTime(new Date()); + boolean updateWechatCpContact = wechatCpContactService.updateById(wechatCpContact); + if (updateWechatCpContact) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 删除 + * + * @param externalUserIds + * @return + */ + public APIResponse deleteById(String[] externalUserIds) { + if (null == externalUserIds || externalUserIds.length == 0) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + boolean deleteWechatCpContact = wechatCpContactService.removeByIds(Arrays.asList(externalUserIds)); + if (deleteWechatCpContact) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpContactWayService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpContactWayService.java new file mode 100644 index 0000000..c319d68 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpContactWayService.java @@ -0,0 +1,147 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.domain.req.ReqSearchWechatCpContactWay; +import cn.xluobo.business.wechat.cp.domain.req.RespWechatCpContactWay; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpAccount; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContactWay; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.page.RespPage; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.external.WxCpContactWayInfo; +import me.chanjar.weixin.cp.bean.external.WxCpContactWayResult; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessWechatCpContactWayService { + + @Autowired + private IWechatCpContactWayService wechatCpContactWayService; + @Autowired + private ThirdWechatCpContactService cpContactService; + @Autowired + private IWechatCpAccountService wechatCpAccountService; + + /** + * 查询 + * + * @param reqSearchWechatCpContactWay + * @return + */ + public APIResponse searchList(ReqSearchWechatCpContactWay reqSearchWechatCpContactWay) { + RespPage page = new RespPage(reqSearchWechatCpContactWay.getPageNum(), reqSearchWechatCpContactWay.getPageSize()); + List listPage = wechatCpContactWayService.selectForSearchTable(reqSearchWechatCpContactWay, page); + page.setRows(listPage); + return APIResponse.toAPIResponse(page); + } + + /** + * 详情 + * + * @param configId + * @return + */ + public APIResponse detailById(String configId) { + if (null == configId) { + return APIResponse.toAPIResponse(null); + } + WechatCpContactWay detailInfo = wechatCpContactWayService.getById(configId); + return APIResponse.toAPIResponse(detailInfo); + } + + /** + * 添加 + * + * @param wechatCpContactWay + * @return + */ + public APIResponse addWechatCpContactWay(WechatCpContactWay wechatCpContactWay) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + wechatCpContactWay.setCreateUser(loginUser.getUserId()); + wechatCpContactWay.setRemark(wechatCpContactWay.getContactWayName()); + + WxCpContactWayInfo wxCpContactWayInfo = wechatCpContactWay.transferWxCpContactWay(); + WechatCpAccount wechatCpAccount = wechatCpAccountService.selectDefaultCpAccount(); + WxCpContactWayResult wxCpContactWayResult = null; + try { + wxCpContactWayResult = cpContactService.addContactWay(wechatCpAccount.getCorpId(), wechatCpAccount.getAgentId(), wxCpContactWayInfo); + } catch (WxErrorException e) { + return APIResponse.toExceptionResponse(e.toString()); + } + + wechatCpContactWay.setConfigId(wxCpContactWayResult.getConfigId()); + wechatCpContactWay.setQrCode(wxCpContactWayResult.getQrCode()); + boolean addWechatCpContactWay = wechatCpContactWayService.save(wechatCpContactWay); + if (addWechatCpContactWay) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 更新 + * + * @param wechatCpContactWay + * @return + */ + public APIResponse updateWechatCpContactWay(WechatCpContactWay wechatCpContactWay) { + if (null == wechatCpContactWay.getConfigId()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + wechatCpContactWay.setLastUpdateUser(loginUser.getUserId()); + wechatCpContactWay.setLastUpdateTime(new Date()); + wechatCpContactWay.setRemark(wechatCpContactWay.getContactWayName()); + + WxCpContactWayInfo wxCpContactWayInfo = wechatCpContactWay.transferWxCpContactWay(); + WechatCpAccount wechatCpAccount = wechatCpAccountService.selectDefaultCpAccount(); + try { + cpContactService.updateContactWay(wechatCpAccount.getCorpId(), wechatCpAccount.getAgentId(), wxCpContactWayInfo); + } catch (WxErrorException e) { + return APIResponse.toExceptionResponse(e.toString()); + } + + boolean updateWechatCpContactWay = wechatCpContactWayService.updateById(wechatCpContactWay); + if (updateWechatCpContactWay) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 删除 + * + * @param configIds + * @return + */ + public APIResponse deleteById(String[] configIds) { + if (null == configIds || configIds.length == 0) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + WechatCpAccount wechatCpAccount = wechatCpAccountService.selectDefaultCpAccount(); + for (String configId : configIds) { + try { + cpContactService.deleteContactWay(wechatCpAccount.getCorpId(), wechatCpAccount.getAgentId(), configId); + } catch (WxErrorException e) { + return APIResponse.toExceptionResponse(e.toString()); + } + wechatCpContactWayService.removeByIds(Arrays.asList(configIds)); + } + return APIResponse.toOkResponse(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpCustomerService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpCustomerService.java new file mode 100644 index 0000000..9ba45a5 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpCustomerService.java @@ -0,0 +1,41 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.domain.req.ReqSearchCpCustomer; +import cn.xluobo.core.api.APIResponse; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @projectName: qyxt + * @package: cn.xluobo.business.wechat.cp.service + * @className: BusinessWechatCpCustomerService + * @author: xluobo + * @description: TODO + * @date: 2024/1/25 08:15 + */ +@Service +@Transactional +public class BusinessWechatCpCustomerService { + + @Autowired + private ThirdWechatCpContactService thirdWechatCpContactService; + + /** + * 查询客户列表 + * @param reqSearchCpCustomer + * @return + */ + public APIResponse searchList(ReqSearchCpCustomer reqSearchCpCustomer) { + String cpUserIds = reqSearchCpCustomer.getCpUserIds(); + if (StringUtils.isEmpty(cpUserIds)) { + return APIResponse.toExceptionResponse("请选择员工"); + } + String[] userIds = cpUserIds.split(","); + long pageSize = reqSearchCpCustomer.getPageSize(); + +// wechatCpCustomerService.getContactDetailBatch(userIds, reqSearchCpCustomer.getCpCursor(), ); + return null; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpGroupTagService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpGroupTagService.java new file mode 100644 index 0000000..9e41697 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpGroupTagService.java @@ -0,0 +1,170 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.domain.req.ReqSearchWechatCpGroupTag; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpGroup; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpGroupTag; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.api.ApiResEnums; +import cn.xluobo.core.domain.select.GroupSelect; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-14 17:24 + */ +@Service +@Transactional +public class BusinessWechatCpGroupTagService { + + @Autowired + private IWechatCpGroupService wechatCpGroupService; + @Autowired + private IWechatCpGroupTagService wechatCpGroupTagService; + + /** + * 查询 + * + * @param reqSearchWechatCpGroupTag + * @return + */ + public APIResponse searchList(ReqSearchWechatCpGroupTag reqSearchWechatCpGroupTag) { + QueryWrapper qw = new QueryWrapper(); + if(StringUtils.isNotEmpty(reqSearchWechatCpGroupTag.getGroupId())){ + qw.eq("group_id",reqSearchWechatCpGroupTag.getGroupId()); + } + RespPage page = new RespPage(reqSearchWechatCpGroupTag.getPageNum(), reqSearchWechatCpGroupTag.getPageSize()); + RespPage listPage = wechatCpGroupTagService.page(page, qw); + return APIResponse.toAPIResponse(listPage); + } + + /** + * group select + * + * @return + */ + public APIResponse groupSelect() { + // 全部group + QueryWrapper qwGroup = new QueryWrapper<>(); + qwGroup.eq("delete_flag", "0"); + List groupList = wechatCpGroupService.list(qwGroup); + + // group id name map + Map groupMap = Maps.newHashMap(); + for (WechatCpGroup wechatCpGroup : groupList) { + groupMap.put(wechatCpGroup.getGroupId(), wechatCpGroup.getGroupName()); + } + + // 全部tag + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("delete_flag", "0"); + List groupTagList = wechatCpGroupTagService.list(qw); + + // 转换为map + Map> groupTagMap = Maps.newHashMap(); + for (WechatCpGroupTag groupTag : groupTagList) { + if (!groupTagMap.containsKey(groupTag.getGroupId())) { + groupTagMap.put(groupTag.getGroupId(), Lists.newArrayList()); + } + groupTagMap.get(groupTag.getGroupId()).add(groupTag); + } + + // 转换为前段需要的格式 + List groupSelectList = groupTagMap.keySet().stream().map(groupKey -> { + GroupSelect groupSelect = new GroupSelect(); + groupSelect.setGroupName(groupMap.get(groupKey)); + + List groupItemList = groupTagMap.get(groupKey).stream().map(WechatCpGroupTag::transferGroupSelectItem).collect(Collectors.toList()); + groupSelect.setItemList(groupItemList); + + return groupSelect; + }).collect(Collectors.toList()); + + + return APIResponse.toAPIResponse(groupSelectList); + } + + /** + * 详情 + * + * @param tagId + * @return + */ + public APIResponse detailById(String tagId) { + if (null == tagId) { + return APIResponse.toAPIResponse(null); + } + WechatCpGroupTag detailInfo = wechatCpGroupTagService.getById(tagId); + return APIResponse.toAPIResponse(detailInfo); + } + + /** + * 添加 + * + * @param wechatCpGroupTag + * @return + */ + public APIResponse addWechatCpGroupTag(WechatCpGroupTag wechatCpGroupTag) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + wechatCpGroupTag.setCreateUser(loginUser.getUserId()); + boolean addWechatCpGroupTag = wechatCpGroupTagService.save(wechatCpGroupTag); + if (addWechatCpGroupTag) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 更新 + * + * @param wechatCpGroupTag + * @return + */ + public APIResponse updateWechatCpGroupTag(WechatCpGroupTag wechatCpGroupTag) { + if (null == wechatCpGroupTag.getTagId()) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + wechatCpGroupTag.setLastUpdateUser(loginUser.getUserId()); + wechatCpGroupTag.setLastUpdateTime(new Date()); + boolean updateWechatCpGroupTag = wechatCpGroupTagService.updateById(wechatCpGroupTag); + if (updateWechatCpGroupTag) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } + + /** + * 删除 + * + * @param tagIds + * @return + */ + public APIResponse deleteById(String[] tagIds) { + if (null == tagIds || tagIds.length == 0) { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + boolean deleteWechatCpGroupTag = wechatCpGroupTagService.removeByIds(Arrays.asList(tagIds)); + if (deleteWechatCpGroupTag) { + return APIResponse.toOkResponse(); + } else { + return APIResponse.toExceptionResponse(ApiResEnums.FAIL_WAIT_A_MINUTE); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpUserService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpUserService.java new file mode 100644 index 0000000..3d45008 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/BusinessWechatCpUserService.java @@ -0,0 +1,43 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.sc.course.domain.req.ReqSelect; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpUser; +import cn.xluobo.core.api.APIResponse; +import cn.xluobo.core.page.RespPage; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @projectName: qyxt + * @package: cn.xluobo.business.wechat.cp.service + * @className: BusinessWechatCpUserService + * @author: xluobo + * @description: TODO + * @date: 2024/1/30 00:30 + */ +@Service +@Transactional +public class BusinessWechatCpUserService { + + @Autowired + private IWechatCpUserService cpUserService; + + /** + * 企业微信用户select + * + * @param reqSelect + * @return + */ + public APIResponse cpUserSelect(ReqSelect reqSelect) { + RespPage page = new RespPage(reqSelect.getPageNum(), reqSelect.getPageSize()); + + QueryWrapper qw = new QueryWrapper<>(); + /*if (StringUtils.isNotEmpty(reqSelect.getSearch())) { + qw.and(i -> i.like("userid", reqSelect.getSearch()).or().like("name", reqSelect.getSearch())); + }*/ + RespPage respPage = cpUserService.page(page, qw); + return APIResponse.toAPIResponse(respPage); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpAccountService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpAccountService.java new file mode 100644 index 0000000..f7ca9b5 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpAccountService.java @@ -0,0 +1,48 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpAccount; + +import java.util.List; + +/** + *

+ * 企业应用信息 服务类 + *

+ * + * @author zhangby + * @since 2024-01-23 06:59:58 + */ +public interface IWechatCpAccountService extends com.baomidou.mybatisplus.extension.service.IService { + + List selectAllInUseCpAccount(); + + /** + * 获取租户 应用信息 + * @param agentId + * @return + */ + WechatCpAccount selectByAgentId(Integer agentId); + + /** + * 获取租户 应用信息 + * + * @param corpId + * @return + */ + WechatCpAccount selectByCropId(String corpId); + + /** + * 获取租户 应用信息 + * + * @param corpId + * @return + */ + WechatCpAccount selectByCropIdAgentIdIgnoreTenant(String corpId, String agentId); + + /** + * 获取租户默认应用信息 + * @return + */ + WechatCpAccount selectDefaultCpAccount(); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactFollowService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactFollowService.java new file mode 100644 index 0000000..26f54b7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactFollowService.java @@ -0,0 +1,22 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContactFollow; + +/** + *

+ * 外部联系人对应大员工信息 服务类 + *

+ * + * @author xluobo + * @since 2024-01-25 05:53:25 + */ +public interface IWechatCpContactFollowService extends com.baomidou.mybatisplus.extension.service.IService { + + /** + * 删除标签 + * @param externalUserId + * @param cpUserId + */ + void deleteContactFollow(String externalUserId, String cpUserId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactFollowTagService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactFollowTagService.java new file mode 100644 index 0000000..8cca62f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactFollowTagService.java @@ -0,0 +1,22 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContactFollowTag; + +/** + *

+ * 员工给外部联系人添加的标签 服务类 + *

+ * + * @author xluobo + * @since 2024-01-25 10:46:17 + */ +public interface IWechatCpContactFollowTagService extends com.baomidou.mybatisplus.extension.service.IService { + + /** + * 删除标签 + * @param externalUserId + * @param cpUserId + */ + void deleteTag(String externalUserId, String cpUserId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactService.java new file mode 100644 index 0000000..57a234c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactService.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContact; + +/** + *

+ * 企业微信客户信息 服务类 + *

+ * + * @author xluobo + * @since 2024-01-25 05:53:20 + */ +public interface IWechatCpContactService extends com.baomidou.mybatisplus.extension.service.IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactWayService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactWayService.java new file mode 100644 index 0000000..4928471 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpContactWayService.java @@ -0,0 +1,23 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.domain.req.ReqSearchWechatCpContactWay; +import cn.xluobo.business.wechat.cp.domain.req.RespWechatCpContactWay; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContactWay; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +import java.util.List; + +/** + *

+ * 客户联系我方式 服务类 + *

+ * + * @author xluobo + * @since 2024-01-26 07:13:01 + */ +public interface IWechatCpContactWayService extends com.baomidou.mybatisplus.extension.service.IService { + + List selectForSearchTable(ReqSearchWechatCpContactWay reqSearchWechatCpContactWay, Page page); + + WechatCpContactWay selectByState(String state); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpGroupService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpGroupService.java new file mode 100644 index 0000000..f493070 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpGroupService.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpGroup; + +/** + *

+ * 企业微信标签组 服务类 + *

+ * + * @author xluobo + * @since 2024-01-25 05:53:33 + */ +public interface IWechatCpGroupService extends com.baomidou.mybatisplus.extension.service.IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpGroupTagService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpGroupTagService.java new file mode 100644 index 0000000..cec906b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpGroupTagService.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpGroupTag; + +/** + *

+ * 企业微信标签 服务类 + *

+ * + * @author xluobo + * @since 2024-01-25 05:55:40 + */ +public interface IWechatCpGroupTagService extends com.baomidou.mybatisplus.extension.service.IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpUserService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpUserService.java new file mode 100644 index 0000000..9ba25f3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/IWechatCpUserService.java @@ -0,0 +1,15 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpUser; + +/** + *

+ * 企业微信成员 服务类 + *

+ * + * @author xluobo + * @since 2024-01-26 08:08:32 + */ +public interface IWechatCpUserService extends com.baomidou.mybatisplus.extension.service.IService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/ThirdWechatCpContactService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/ThirdWechatCpContactService.java new file mode 100644 index 0000000..2c746b6 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/ThirdWechatCpContactService.java @@ -0,0 +1,163 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.domain.cp.ReqCpExternalContact; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpAccount; +import cn.xluobo.config.exception.BusinessException; +import cn.xluobo.config.wechat.cp.WechatCpConfiguration; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.api.WxCpExternalContactService; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.external.WxCpContactWayInfo; +import me.chanjar.weixin.cp.bean.external.WxCpContactWayResult; +import me.chanjar.weixin.cp.bean.external.WxCpUserExternalTagGroupList; +import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactBatchInfo; +import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 企业微信 客户管理服务类 + * @author zhangbaoyu + */ +@Service +@Transactional +public class ThirdWechatCpContactService { + + @Autowired + private IWechatCpAccountService cpAccountService; + + /** + * 获取配置了客户联系功能的成员列表 + * @param corpId + * @param agentId + * @return + * @throws WxErrorException + */ + public List getFlowUserList(String corpId, Integer agentId) throws WxErrorException { + WxCpService cpService = WechatCpConfiguration.getCpService(corpId, agentId); + WxCpExternalContactService externalContactService = cpService.getExternalContactService(); + return externalContactService.listFollowers(); + } + + /** + * 获取企业微信客户信息 + * @param corpId + * @param agentId + * @param externalUserId + * @return + * @throws WxErrorException + */ + public WxCpExternalContactInfo getContactDetail(String corpId, Integer agentId, String externalUserId) throws WxErrorException { + WxCpService cpService = WechatCpConfiguration.getCpService(corpId, agentId); + WxCpExternalContactService externalContactService = cpService.getExternalContactService(); + + return externalContactService.getContactDetail(externalUserId,null); + } + + /** + * 批量获取企业微信客户信息 + * @param reqCpExternalContact + * @return + * @throws WxErrorException + */ + public WxCpExternalContactBatchInfo getContactDetailBatch(ReqCpExternalContact reqCpExternalContact) throws WxErrorException { + WechatCpAccount wechatCpAccount = cpAccountService.selectDefaultCpAccount(); + if (wechatCpAccount == null) { + throw new BusinessException("can not find default cp account config"); + } + WxCpService cpService = WechatCpConfiguration.getCpService(wechatCpAccount.getCorpId(), wechatCpAccount.getAgentId()); + WxCpExternalContactService externalContactService = cpService.getExternalContactService(); + + List userIdList = reqCpExternalContact.getUserIdList(); + String[] userIds = userIdList.toArray(new String[0]); + return externalContactService.getContactDetailBatch(userIds, reqCpExternalContact.getCursor(), reqCpExternalContact.getLimit()); + } + + + /** + * 编辑客户企业标签 + * @param corpId + * @param agentId + * @param userid + * @param externalUserid + * @param addTag + * @param removeTag + * @return + * @throws WxErrorException + */ + public WxCpBaseResp externalContactMarkTag(String corpId, + Integer agentId, + String userid, + String externalUserid, + String[] addTag, + String[] removeTag) throws WxErrorException { + WxCpService cpService = WechatCpConfiguration.getCpService(corpId, agentId); + WxCpExternalContactService externalContactService = cpService.getExternalContactService(); + return externalContactService.markTag(userid, externalUserid, addTag, removeTag); + + } + + /** + * 获取客户 标签 tag + * @param corpId + * @param agentId + * @param tagId + * @param groupId + * @throws WxErrorException + */ + public WxCpUserExternalTagGroupList getExternalTagGroupList(String corpId, Integer agentId, + String[] tagId, String[] groupId) throws WxErrorException { + WxCpService cpService = WechatCpConfiguration.getCpService(corpId, agentId); + WxCpExternalContactService externalContactService = cpService.getExternalContactService(); + return externalContactService.getCorpTagList(tagId, groupId); + } + + /** + * 配置客户联系「联系我」方式 + * @param corpId + * @param agentId + * @param contactWayInfo + * @return + * @throws WxErrorException + */ + public WxCpContactWayResult addContactWay(String corpId, Integer agentId, WxCpContactWayInfo contactWayInfo) throws WxErrorException { + WxCpService cpService = WechatCpConfiguration.getCpService(corpId, agentId); + WxCpExternalContactService externalContactService = cpService.getExternalContactService(); + return externalContactService.addContactWay(contactWayInfo); + } + + /** + * 更新客户联系我方式 + * @param corpId + * @param agentId + * @param contactWayInfo + * @return + * @throws WxErrorException + */ + public WxCpBaseResp updateContactWay(String corpId, Integer agentId, WxCpContactWayInfo contactWayInfo) throws WxErrorException { + WxCpService cpService = WechatCpConfiguration.getCpService(corpId, agentId); + WxCpExternalContactService externalContactService = cpService.getExternalContactService(); + return externalContactService.updateContactWay(contactWayInfo); + } + + /** + * 删除客户联系我方式 + * @param corpId + * @param agentId + * @param configId + * @return + * @throws WxErrorException + */ + public WxCpBaseResp deleteContactWay(String corpId, Integer agentId, String configId) throws WxErrorException { + WxCpService cpService = WechatCpConfiguration.getCpService(corpId, agentId); + WxCpExternalContactService externalContactService = cpService.getExternalContactService(); + return externalContactService.deleteContactWay(configId); + } + + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/ThirdWechatCpUserService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/ThirdWechatCpUserService.java new file mode 100644 index 0000000..0bf91b1 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/ThirdWechatCpUserService.java @@ -0,0 +1,49 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.domain.cp.ReqCpUserDetail; +import cn.xluobo.business.wechat.cp.domain.cp.ReqCpUserList; +import cn.xluobo.config.wechat.cp.WechatCpConfiguration; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.api.WxCpUserService; +import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.bean.user.WxCpDeptUserResult; +import org.springframework.stereotype.Service; + +/** + * 企业微信通讯录管理 + * @projectName: qyxt + * @package: cn.xluobo.business.wechat.cp.service + * @className: WechatCpUserService + * @author: xluobo + * @description: 通讯录管理 + * @date: 2024/1/25 18:31 + */ +@Service +public class ThirdWechatCpUserService { + + /** + * 获取企业成员的userid与对应的部门ID列表,预计于2022年8月8号发布。若需要获取其他字段,参见「适配建议」。 + * @param reqCpUserList + * @return + * @throws WxErrorException + */ + public WxCpDeptUserResult getUserListId(ReqCpUserList reqCpUserList) throws WxErrorException { + WxCpService cpService = WechatCpConfiguration.getCpService(reqCpUserList.getCorpId(), reqCpUserList.getAddressBookAgentId()); + WxCpUserService userService = cpService.getUserService(); + return userService.getUserListId(reqCpUserList.getCursor(), reqCpUserList.getLimit()); + } + + /** + * 读取成员详情 + * @param reqCpUserDetail + * @return + * @throws WxErrorException + */ + public WxCpUser getById(ReqCpUserDetail reqCpUserDetail) throws WxErrorException { + WxCpService cpService = WechatCpConfiguration.getCpService(reqCpUserDetail.getCorpId(), reqCpUserDetail.getAgentId()); + WxCpUserService userService = cpService.getUserService(); + return userService.getById(reqCpUserDetail.getUserId()); + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/WechatCpSyncService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/WechatCpSyncService.java new file mode 100644 index 0000000..77e6055 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/WechatCpSyncService.java @@ -0,0 +1,353 @@ +package cn.xluobo.business.wechat.cp.service; + +import cn.xluobo.business.wechat.cp.domain.cp.ReqCpExternalContact; +import cn.xluobo.business.wechat.cp.domain.cp.ReqCpUserDetail; +import cn.xluobo.business.wechat.cp.domain.cp.ReqCpUserList; +import cn.xluobo.business.wechat.cp.repo.model.*; +import cn.xluobo.config.exception.BusinessException; +import cn.xluobo.config.tenant.TenantContextHolder; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.google.common.collect.Lists; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.bean.external.WxCpUserExternalTagGroupList; +import me.chanjar.weixin.cp.bean.external.contact.ExternalContact; +import me.chanjar.weixin.cp.bean.external.contact.FollowedUser; +import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactBatchInfo; +import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo; +import me.chanjar.weixin.cp.bean.user.WxCpDeptUserResult; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * 企业微信数据同步服务 + * + * @projectName: qyxt + * @package: cn.xluobo.business.wechat.cp.service + * @className: WechatCpSyncService + * @author: xluobo + * @description: 企业微信数据同步服务 + * @date: 2024/1/25 18:22 + */ +@Service +@Transactional +public class WechatCpSyncService { + + @Autowired + private ThirdWechatCpContactService thirdWechatCpContactService; + @Autowired + private ThirdWechatCpUserService thirdWechatCpUserService; + @Autowired + private IWechatCpAccountService dbCpAccountService; + @Autowired + private IWechatCpContactService dbCpContactService; + @Autowired + private IWechatCpContactFollowService dbCpContactFollowService; + @Autowired + private IWechatCpContactFollowTagService dbCpContactFollowTagService; + @Autowired + private IWechatCpGroupService groupService; + @Autowired + private IWechatCpGroupTagService groupTagService; + @Autowired + private IWechatCpUserService dbCpUserService; + @Autowired + private IWechatCpContactWayService dbCpContactWayService; + + + /** + * 内部应用同步联系人信息 + */ + @Async + public void syncSelfWechatCpContact(Long tenantId) { + try { + TenantContextHolder.setTenant(tenantId); + + WechatCpAccount wechatCpAccount = dbCpAccountService.selectDefaultCpAccount(); + if (null == wechatCpAccount) { + return; + } + + List userList = thirdWechatCpContactService.getFlowUserList(wechatCpAccount.getCorpId(), wechatCpAccount.getAgentId()); + + ReqCpExternalContact reqCpExternalContact = new ReqCpExternalContact(); + reqCpExternalContact.setUserIdList(userList); + reqCpExternalContact.setCursor(""); + reqCpExternalContact.setLimit(100); + reqCpExternalContact.setCorpId(wechatCpAccount.getCorpId()); + reqCpExternalContact.setAgentId(wechatCpAccount.getAgentId()); + this.getContactAndSave(reqCpExternalContact); + } catch (WxErrorException e) { + throw new BusinessException(e.getMessage()); + } finally { + TenantContextHolder.remove(); + } + } + + /** + * 内部应用同步企业标签信息 + */ + @Async + public void syncSelfWechatCpTag(Long tenantId) { + try { + TenantContextHolder.setTenant(tenantId); + + WechatCpAccount wechatCpAccount = dbCpAccountService.selectDefaultCpAccount(); + if (null == wechatCpAccount) { + return; + } + + WxCpUserExternalTagGroupList externalTagGroupList = thirdWechatCpContactService.getExternalTagGroupList(wechatCpAccount.getCorpId(), wechatCpAccount.getAgentId(), null, null); + List tagGroupList = externalTagGroupList.getTagGroupList(); + + List groupList = Lists.newArrayList(); + List groupTagList = Lists.newArrayList(); + + for (WxCpUserExternalTagGroupList.TagGroup tagGroup : tagGroupList) { + groupList.add(WechatCpGroup.transferByCpBean(tagGroup)); + + List tagList = tagGroup.getTag(); + List list = tagList.stream().map(item -> WechatCpGroupTag.transferByCpBean(tagGroup.getGroupId(), item)).collect(Collectors.toList()); + groupTagList.addAll(list); + } + if (!groupList.isEmpty()) { + groupService.saveOrUpdateBatch(groupList); + } + if (!groupTagList.isEmpty()) { + groupTagService.saveOrUpdateBatch(groupTagList); + } + } catch (WxErrorException e) { + throw new BusinessException(e.getMessage()); + } finally { + TenantContextHolder.remove(); + } + } + + /** + * 同步企业成员 + * @param tenantId + */ + @Async + public void syncSelfWechatCpUser(Long tenantId) { + try { + TenantContextHolder.setTenant(tenantId); + + WechatCpAccount wechatCpAccount = dbCpAccountService.selectDefaultCpAccount(); + if (null == wechatCpAccount) { + return; + } + + ReqCpUserList reqCpUserList = new ReqCpUserList(); + reqCpUserList.setCorpId(wechatCpAccount.getCorpId()); + reqCpUserList.setAgentId(wechatCpAccount.getAgentId()); + reqCpUserList.setCursor(""); + reqCpUserList.setLimit(100); + this.getUserAndSave(reqCpUserList); + } catch (WxErrorException e) { + throw new BusinessException(e.getMessage()); + } finally { + TenantContextHolder.remove(); + } + } + + /** + * 获取并存储联系人信息 + * + * @param reqCpExternalContact + * @throws WxErrorException + */ + private void getContactAndSave(ReqCpExternalContact reqCpExternalContact) throws WxErrorException { + WxCpExternalContactBatchInfo contactDetailBatch = thirdWechatCpContactService.getContactDetailBatch(reqCpExternalContact); + List externalContactList = contactDetailBatch.getExternalContactList(); + + List wechatCpContactList = Lists.newArrayList(); + List contactFollowList = Lists.newArrayList(); + + // 批量获取联系人详情时,不返回个人标签信息 + // List followTagList = Lists.newArrayList(); + + for (WxCpExternalContactBatchInfo.ExternalContactInfo externalContactInfo : externalContactList) { + ExternalContact externalContact = externalContactInfo.getExternalContact(); + FollowedUser followInfo = externalContactInfo.getFollowInfo(); + + wechatCpContactList.add(WechatCpContact.transferByCpBean(externalContact)); + contactFollowList.add(WechatCpContactFollow.transferByCpBean(externalContact.getExternalUserId(), followInfo)); + // followTagList.addAll(WechatCpContactFollowTag.transferByCpBean(externalContact.getExternalUserId(), followInfo)); + + dbCpContactFollowTagService.deleteTag(externalContact.getExternalUserId(), followInfo.getUserId()); + } + if (!wechatCpContactList.isEmpty()) { + dbCpContactService.saveOrUpdateBatch(wechatCpContactList); + } + + if (!contactFollowList.isEmpty()) { + dbCpContactFollowService.saveOrUpdateBatch(contactFollowList); + } + + /*if (!followTagList.isEmpty()) { + dbCpContactFollowTagService.saveOrUpdateBatch(followTagList); + }*/ + + String nextCursor = contactDetailBatch.getNextCursor(); + if (StringUtils.isNotEmpty(nextCursor)) { + reqCpExternalContact.setCursor(nextCursor); + this.getContactAndSave(reqCpExternalContact); + } + } + + /** + * 获取并存储用户信息 + * @param reqCpUserList + * @throws WxErrorException + */ + private void getUserAndSave(ReqCpUserList reqCpUserList) throws WxErrorException { + WxCpDeptUserResult wxCpDeptUserResult = thirdWechatCpUserService.getUserListId(reqCpUserList); + String nextCursor = wxCpDeptUserResult.getNextCursor(); + + List deptUserList = wxCpDeptUserResult.getDeptUser(); + Set userIdSet = deptUserList.stream().map(WxCpDeptUserResult.DeptUserList::getUserId).collect(Collectors.toSet()); + + List cpUserList = Lists.newArrayList(); + + // 获取详情,并转换为 WechatCpUser + ReqCpUserDetail reqCpUserDetail = new ReqCpUserDetail(); + reqCpUserDetail.setCorpId(reqCpUserList.getCorpId()); + reqCpUserDetail.setAgentId(reqCpUserList.getAgentId()); + for (String userId : userIdSet) { + reqCpUserDetail.setUserId(userId); + WxCpUser wxCpUser = thirdWechatCpUserService.getById(reqCpUserDetail); + WechatCpUser wechatCpUser = WechatCpUser.transferByCpBean(wxCpUser); + cpUserList.add(wechatCpUser); + } + + // 存储 + dbCpUserService.saveOrUpdateBatch(cpUserList); + + if (StringUtils.isNotEmpty(nextCursor)) { + reqCpUserList.setCursor(nextCursor); + this.getUserAndSave(reqCpUserList); + } + } + + /** + * 事件处理 + * 添加企业客户事件、编辑企业客户事件、外部联系人免验证添加成员事件 + * 存储客户信息并打标签 + * + * @param cropId + * @param externalUserId + * @param userId + * @param state + */ + public void saveExternalUserAndMargTag(String cropId, + String agentId, + String externalUserId, + String userId, + String state) throws WxErrorException { + WechatCpAccount wechatCpAccount = dbCpAccountService.selectByCropIdAgentIdIgnoreTenant(cropId, agentId); + if (null == wechatCpAccount) { + return; + } + try { + TenantContextHolder.setTenant(wechatCpAccount.getTenantId()); + + // 存储客户信息 + WxCpExternalContactInfo externalContactInfo = thirdWechatCpContactService.getContactDetail(wechatCpAccount.getCorpId(), wechatCpAccount.getAgentId(), externalUserId); + WechatCpContact wechatCpContact = WechatCpContact.transferByCpBean(externalContactInfo.getExternalContact()); + + List followedUserList = externalContactInfo.getFollowedUsers(); + List cpContactFollowList = followedUserList.stream().map(item -> WechatCpContactFollow.transferByCpBean(wechatCpContact.getExternalUserId(), item)).collect(Collectors.toList()); + + List followTagList = Lists.newArrayList(); + for (FollowedUser followedUser : followedUserList) { + List itemList = WechatCpContactFollowTag.transferByCpBean(wechatCpContact.getExternalUserId(), followedUser); + followTagList.addAll(itemList); + + dbCpContactFollowTagService.deleteTag(wechatCpContact.getExternalUserId(), followedUser.getUserId()); + } + + dbCpContactService.saveOrUpdate(wechatCpContact); + dbCpContactFollowService.saveOrUpdateBatch(cpContactFollowList); + dbCpContactFollowTagService.saveBatch(followTagList); + + + if (StringUtils.isEmpty(state)) { + return; + } + // 获取需要打哪些标签 + WechatCpContactWay wechatCpContactWay = dbCpContactWayService.selectByState(state); + if (null == wechatCpContactWay) { + return; + } + // 打标签 + String[] addTags = wechatCpContactWay.getAddTags(); + if (null == addTags || addTags.length == 0) { + return; + } + thirdWechatCpContactService.externalContactMarkTag(cropId, + wechatCpAccount.getAgentId(), + userId, + externalUserId, + addTags, + null); + + } finally { + TenantContextHolder.remove(); + } + } + + /** + * 配置了客户联系功能的成员被外部联系人删除时 + * @param cropId + * @param agentId + * @param externalUserId + * @param userId + */ + public void delExternalFollowUser(String cropId, + String agentId, + String externalUserId, + String userId) { + WechatCpAccount wechatCpAccount = dbCpAccountService.selectByCropIdAgentIdIgnoreTenant(cropId, agentId); + if (null == wechatCpAccount) { + return; + } + try { + TenantContextHolder.setTenant(wechatCpAccount.getTenantId()); + + dbCpContactFollowService.deleteContactFollow(externalUserId, userId); + } finally { + TenantContextHolder.remove(); + } + } + + /** + * 配置了客户联系功能的成员删除外部联系人时 + * @param cropId + * @param agentId + * @param externalUserId + */ + public void delExternalContact(String cropId, + String agentId, + String externalUserId) { + WechatCpAccount wechatCpAccount = dbCpAccountService.selectByCropIdAgentIdIgnoreTenant(cropId, agentId); + if (null == wechatCpAccount) { + return; + } + try { + TenantContextHolder.setTenant(wechatCpAccount.getTenantId()); + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("external_user_id", externalUserId).set("delete_flag", "1"); + dbCpContactService.update(uw); + } finally { + TenantContextHolder.remove(); + } + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpAccountServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpAccountServiceImpl.java new file mode 100644 index 0000000..41fa50d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpAccountServiceImpl.java @@ -0,0 +1,53 @@ +package cn.xluobo.business.wechat.cp.service.impl; + +import cn.xluobo.business.wechat.cp.repo.mapper.WechatCpAccountMapper; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpAccount; +import cn.xluobo.business.wechat.cp.service.IWechatCpAccountService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 企业应用信息 服务实现类 + *

+ * + * @author zhangby + * @since 2024-01-23 06:59:58 + */ +@Service +public class WechatCpAccountServiceImpl extends ServiceImpl implements IWechatCpAccountService { + + @Override + public List selectAllInUseCpAccount() { + return baseMapper.selectAllInUserCpAccount(); + } + + @Override + public WechatCpAccount selectByAgentId(Integer agentId) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("agent_id", agentId).last("limit 1"); + return this.getOne(qw); + } + + @Override + public WechatCpAccount selectByCropId(String corpId) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("corp_id", corpId).last("limit 1"); + return this.getOne(qw); + } + + @Override + public WechatCpAccount selectByCropIdAgentIdIgnoreTenant(String corpId, String agentId) { + return baseMapper.selectByCropIdAgentIdIgnoreTenant(corpId, agentId); + } + + @Override + public WechatCpAccount selectDefaultCpAccount() { + QueryWrapper qw = new QueryWrapper<>(); + qw.orderByAsc("create_time").last("limit 1"); + return this.getOne(qw); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactFollowServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactFollowServiceImpl.java new file mode 100644 index 0000000..dc29fc3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactFollowServiceImpl.java @@ -0,0 +1,27 @@ +package cn.xluobo.business.wechat.cp.service.impl; + +import cn.xluobo.business.wechat.cp.repo.mapper.WechatCpContactFollowMapper; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContactFollow; +import cn.xluobo.business.wechat.cp.service.IWechatCpContactFollowService; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 外部联系人对应大员工信息 服务实现类 + *

+ * + * @author xluobo + * @since 2024-01-25 05:53:25 + */ +@Service +public class WechatCpContactFollowServiceImpl extends ServiceImpl implements IWechatCpContactFollowService { + + @Override + public void deleteContactFollow(String externalUserId, String cpUserId) { + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("external_user_id", externalUserId).eq("cp_user_id", cpUserId); + this.remove(uw); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactFollowTagServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactFollowTagServiceImpl.java new file mode 100644 index 0000000..46cd578 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactFollowTagServiceImpl.java @@ -0,0 +1,29 @@ +package cn.xluobo.business.wechat.cp.service.impl; + +import cn.xluobo.business.wechat.cp.repo.mapper.WechatCpContactFollowTagMapper; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContactFollowTag; +import cn.xluobo.business.wechat.cp.service.IWechatCpContactFollowTagService; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 员工给外部联系人添加的标签 服务实现类 + *

+ * + * @author xluobo + * @since 2024-01-25 10:46:17 + */ +@Service +public class WechatCpContactFollowTagServiceImpl extends ServiceImpl implements IWechatCpContactFollowTagService { + + @Override + public void deleteTag(String externalUserId, String cpUserId) { + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("external_user_id", externalUserId) + .eq("cp_user_id", cpUserId); + + this.remove(uw); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactServiceImpl.java new file mode 100644 index 0000000..797f778 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.wechat.cp.service.impl; + +import cn.xluobo.business.wechat.cp.repo.mapper.WechatCpContactMapper; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContact; +import cn.xluobo.business.wechat.cp.service.IWechatCpContactService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 企业微信客户信息 服务实现类 + *

+ * + * @author xluobo + * @since 2024-01-25 05:53:20 + */ +@Service +public class WechatCpContactServiceImpl extends ServiceImpl implements IWechatCpContactService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactWayServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactWayServiceImpl.java new file mode 100644 index 0000000..0ab874f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpContactWayServiceImpl.java @@ -0,0 +1,37 @@ +package cn.xluobo.business.wechat.cp.service.impl; + +import cn.xluobo.business.wechat.cp.domain.req.ReqSearchWechatCpContactWay; +import cn.xluobo.business.wechat.cp.domain.req.RespWechatCpContactWay; +import cn.xluobo.business.wechat.cp.repo.mapper.WechatCpContactWayMapper; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpContactWay; +import cn.xluobo.business.wechat.cp.service.IWechatCpContactWayService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 客户联系我方式 服务实现类 + *

+ * + * @author xluobo + * @since 2024-01-26 07:13:01 + */ +@Service +public class WechatCpContactWayServiceImpl extends ServiceImpl implements IWechatCpContactWayService { + + @Override + public List selectForSearchTable(ReqSearchWechatCpContactWay reqSearchWechatCpContactWay, Page page) { + return baseMapper.selectForSearchTable(reqSearchWechatCpContactWay, page); + } + + @Override + public WechatCpContactWay selectByState(String state) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("state", state).last("limit 1"); + return this.getOne(qw); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpGroupServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpGroupServiceImpl.java new file mode 100644 index 0000000..8ce8616 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpGroupServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.wechat.cp.service.impl; + +import cn.xluobo.business.wechat.cp.repo.mapper.WechatCpGroupMapper; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpGroup; +import cn.xluobo.business.wechat.cp.service.IWechatCpGroupService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 企业微信标签组 服务实现类 + *

+ * + * @author xluobo + * @since 2024-01-25 05:53:33 + */ +@Service +public class WechatCpGroupServiceImpl extends ServiceImpl implements IWechatCpGroupService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpGroupTagServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpGroupTagServiceImpl.java new file mode 100644 index 0000000..1f53167 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpGroupTagServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.wechat.cp.service.impl; + +import cn.xluobo.business.wechat.cp.repo.mapper.WechatCpGroupTagMapper; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpGroupTag; +import cn.xluobo.business.wechat.cp.service.IWechatCpGroupTagService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 企业微信标签 服务实现类 + *

+ * + * @author xluobo + * @since 2024-01-25 05:55:40 + */ +@Service +public class WechatCpGroupTagServiceImpl extends ServiceImpl implements IWechatCpGroupTagService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpUserServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpUserServiceImpl.java new file mode 100644 index 0000000..19c7360 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/service/impl/WechatCpUserServiceImpl.java @@ -0,0 +1,20 @@ +package cn.xluobo.business.wechat.cp.service.impl; + +import cn.xluobo.business.wechat.cp.repo.mapper.WechatCpUserMapper; +import cn.xluobo.business.wechat.cp.repo.model.WechatCpUser; +import cn.xluobo.business.wechat.cp.service.IWechatCpUserService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 企业微信成员 服务实现类 + *

+ * + * @author xluobo + * @since 2024-01-26 08:08:32 + */ +@Service +public class WechatCpUserServiceImpl extends ServiceImpl implements IWechatCpUserService { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/server/controller/WechatCpJsController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/server/controller/WechatCpJsController.java new file mode 100644 index 0000000..964ddc0 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/server/controller/WechatCpJsController.java @@ -0,0 +1,71 @@ +package cn.xluobo.business.wechat.server.controller; + +import cn.xluobo.config.wechat.cp.WechatCpConfiguration; +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.bean.WxJsapiSignature; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.api.WxCpService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.nio.charset.StandardCharsets; +import java.util.Formatter; +import java.util.HashMap; +import java.util.Map; + + +/** + * @author zhangbaoyu + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/server/check/wechat/cp/js/{corpId}/{agentId}") +public class WechatCpJsController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final StringRedisTemplate stringRedisTemplate; + + @PostMapping("/getJsConf") + public Map getJsConf( + @PathVariable String corpId, + @PathVariable Integer agentId, + String uri) throws WxErrorException { + + final WxCpService wxCpService = WechatCpConfiguration.getCpService(corpId, agentId); + if (wxCpService == null) { + throw new IllegalArgumentException(String.format("未找到对应agentId=[%d]的配置,请核实!", agentId)); + } + + WxJsapiSignature wxJsapiSignature = wxCpService.createJsapiSignature(uri); + String signature = wxJsapiSignature.getSignature(); + String nonceStr = wxJsapiSignature.getNonceStr(); + long timestamp = wxJsapiSignature.getTimestamp(); + + Map res = new HashMap(); + res.put("appId", corpId); // 必填,企业微信的corpID + res.put("timestamp", timestamp); // 必填,生成签名的时间戳 + res.put("nonceStr", nonceStr); // 必填,生成签名的随机串 + res.put("signature", signature); // 必填,签名,见 附录-JS-SDK使用权限签名算法 + return res; + } + + + public static String genNonce() { + return bytesToHex(Long.toString(System.nanoTime()).getBytes(StandardCharsets.UTF_8)); + } + + public static String bytesToHex(final byte[] hash) { + Formatter formatter = new Formatter(); + for (byte b : hash) { + formatter.format("%02x", b); + } + String result = formatter.toString(); + formatter.close(); + return result; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/server/controller/WechatCpServerCheckController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/server/controller/WechatCpServerCheckController.java new file mode 100644 index 0000000..aded8ee --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/server/controller/WechatCpServerCheckController.java @@ -0,0 +1,111 @@ +package cn.xluobo.business.wechat.server.controller; + +import cn.xluobo.config.wechat.cp.WechatCpConfiguration; +import cn.xluobo.utils.JsonUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + + +/** + * @author zhangbaoyu + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/server/check/wechat/cp/{corpId}/{agentId}") +@Slf4j +public class WechatCpServerCheckController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final StringRedisTemplate stringRedisTemplate; + + @PostMapping("/test") + public String test(@PathVariable String corpId, + @RequestParam(name = "userId", required = true) String userId) throws WxErrorException { + + String s = stringRedisTemplate.opsForValue().get("test"); + logger.info("data is {}", s); + + final val wxCpService = WechatCpConfiguration.getCpService(corpId,10001); + List list = wxCpService.getExternalContactService().listExternalContacts(userId); + + return list.toString(); + } + + @GetMapping(produces = "text/plain;charset=utf-8") + public String authGet(@PathVariable String corpId, + @PathVariable Integer agentId, + @RequestParam(name = "msg_signature", required = false) String signature, + @RequestParam(name = "timestamp", required = false) String timestamp, + @RequestParam(name = "nonce", required = false) String nonce, + @RequestParam(name = "echostr", required = false) String echostr) { + log.info("\n接收到来自微信服务器的认证消息:signature = [{}], timestamp = [{}], nonce = [{}], echostr = [{}]", + signature, timestamp, nonce, echostr); + + if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) { + throw new IllegalArgumentException("请求参数非法,请核实!"); + } + + final WxCpService wxCpService = WechatCpConfiguration.getCpService(corpId, agentId); + if (wxCpService == null) { + throw new IllegalArgumentException(String.format("未找到对应agentId=[%d]的配置,请核实!", agentId)); + } + + if (wxCpService.checkSignature(signature, timestamp, nonce, echostr)) { + return new WxCpCryptUtil(wxCpService.getWxCpConfigStorage()).decrypt(echostr); + } + + return "非法请求"; + } + + @PostMapping(produces = "application/xml; charset=UTF-8") + public String post(@PathVariable String corpId, + @PathVariable Integer agentId, + @RequestBody String requestBody, + @RequestParam("msg_signature") String signature, + @RequestParam("timestamp") String timestamp, + @RequestParam("nonce") String nonce) { + log.info("\n接收微信请求:[signature=[{}], timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", + signature, timestamp, nonce, requestBody); + + final WxCpService wxCpService = WechatCpConfiguration.getCpService(corpId, agentId); + if (wxCpService == null) { + throw new IllegalArgumentException(String.format("未找到对应agentId=[%d]的配置,请核实!", agentId)); + } + + WxCpXmlMessage inMessage = WxCpXmlMessage.fromEncryptedXml(requestBody, wxCpService.getWxCpConfigStorage(), + timestamp, nonce, signature); + log.debug("\n消息解密后内容为:\n{} ", JsonUtils.toJson(inMessage)); + WxCpXmlOutMessage outMessage = this.route(corpId, agentId, inMessage); + if (outMessage == null) { + return ""; + } + + String out = outMessage.toEncryptedXml(wxCpService.getWxCpConfigStorage()); + log.debug("\n组装回复信息:{}", out); + return out; + } + + private WxCpXmlOutMessage route(String corpId, Integer agentId, WxCpXmlMessage message) { + try { + return WechatCpConfiguration.getRouters().get(corpId + agentId).route(message); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + + return null; + } + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/repo/mapper/WechatUserInfoMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/repo/mapper/WechatUserInfoMapper.java new file mode 100644 index 0000000..fa0574e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/repo/mapper/WechatUserInfoMapper.java @@ -0,0 +1,16 @@ +package cn.xluobo.business.wechat.user.repo.mapper; + +import cn.xluobo.business.wechat.user.repo.model.WechatUserInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 微信用户信息 Mapper 接口 + *

+ * + * @author zhangby + * @since 2020-10-15 + */ +public interface WechatUserInfoMapper extends BaseMapper { + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/repo/mapping/WechatUserInfoMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/repo/mapping/WechatUserInfoMapper.xml new file mode 100644 index 0000000..78742fd --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/repo/mapping/WechatUserInfoMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/repo/model/WechatUserInfo.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/repo/model/WechatUserInfo.java new file mode 100644 index 0000000..913ba0e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/repo/model/WechatUserInfo.java @@ -0,0 +1,109 @@ +package cn.xluobo.business.wechat.user.repo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 微信用户信息 + *

+ * + * @author zhangby + * @since 2020-10-15 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("wechat_user_info") +public class WechatUserInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "wechat_user_id", type = IdType.ASSIGN_ID) + private Long wechatUserId; + + /** + * 用户openId + */ + @TableField("open_id") + private String openId; + + /** + * 所属app + */ + @TableField("app_id") + private String appId; + + /** + * 是否关注 0 未关注,1 关注 + */ + @TableField("subscribe") + private String subscribe; + + /** + * 用户昵称 + */ + @TableField("nick_name") + private String nickName; + + /** + * 性别 0:未知、1:男、2:女 + */ + @TableField("sex") + private String sex; + + @TableField("city") + private String city; + + @TableField("country") + private String country; + + @TableField("province") + private String province; + + @TableField("language") + private String language; + + @TableField("avatar_url") + private String avatarUrl; + + @TableField("subscribe_time") + private String subscribeTime; + + /** + * 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 + */ + @TableField("union_id") + private String unionId; + + @TableField("remark") + private String remark; + + @TableField("groupid") + private String groupid; + + @TableField("tagid_list") + private String tagidList; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/service/IWechatUserInfoService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/service/IWechatUserInfoService.java new file mode 100644 index 0000000..d3b6d62 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/service/IWechatUserInfoService.java @@ -0,0 +1,27 @@ +package cn.xluobo.business.wechat.user.service; + +import cn.xluobo.business.wechat.user.repo.model.WechatUserInfo; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.common.core.domain.entity.SysUser; + +/** + *

+ * 微信用户信息 服务类 + *

+ * + * @author zhangby + * @since 2020-10-15 + */ +public interface IWechatUserInfoService extends IService { + + WechatUserInfo getWechatUser(String appId,String openId); + + /** + * 获取绑定的系统用户 + * @param appId + * @param openId + * @return + */ + SysUser getSysUser(String appId, String openId); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/service/impl/WechatUserInfoServiceImpl.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/service/impl/WechatUserInfoServiceImpl.java new file mode 100644 index 0000000..fecf3d8 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/user/service/impl/WechatUserInfoServiceImpl.java @@ -0,0 +1,44 @@ +package cn.xluobo.business.wechat.user.service.impl; + +import cn.xluobo.business.sys.admin.service.ISysUserService; +import cn.xluobo.business.wechat.user.repo.mapper.WechatUserInfoMapper; +import cn.xluobo.business.wechat.user.repo.model.WechatUserInfo; +import cn.xluobo.business.wechat.user.service.IWechatUserInfoService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + *

+ * 微信用户信息 服务实现类 + *

+ * + * @author zhangby + * @since 2020-10-15 + */ +@Service +public class WechatUserInfoServiceImpl extends ServiceImpl implements IWechatUserInfoService { + + @Autowired + private ISysUserService sysUserService; + + @Override + public WechatUserInfo getWechatUser(String appId, String openId) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("app_id", appId); + qw.eq("open_id", openId); + return this.getOne(qw); + } + + @Override + public SysUser getSysUser(String appId, String openId) { + WechatUserInfo wechatUser = this.getWechatUser(appId, openId); + if( null == wechatUser) { + return null; + } + SysUser sysUser = sysUserService.getByBindByWechatUserId(wechatUser.getWechatUserId()); + return sysUser; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/async/AsyncConfig.java b/ruoyi-admin/src/main/java/cn/xluobo/config/async/AsyncConfig.java new file mode 100644 index 0000000..23c1e5c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/async/AsyncConfig.java @@ -0,0 +1,30 @@ +package cn.xluobo.config.async; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; + +/** + * Created by zhangbaoyu on 18/11/25. + */ +@Configuration +@EnableAsync +public class AsyncConfig { + + private int corePoolSize = 10; + private int maxPoolSize = 200; + private int queueCapacity = 10; + + @Bean + public Executor taskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(corePoolSize); + executor.setMaxPoolSize(maxPoolSize); + executor.setQueueCapacity(queueCapacity); + executor.initialize(); + return executor; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/cache/CaffeineCacheConfig.java b/ruoyi-admin/src/main/java/cn/xluobo/config/cache/CaffeineCacheConfig.java new file mode 100644 index 0000000..c566eca --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/cache/CaffeineCacheConfig.java @@ -0,0 +1,30 @@ +package cn.xluobo.config.cache; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * Caffeine 缓存配置 + */ +@Configuration +public class CaffeineCacheConfig { + + /** + * 节假日缓存 + * @return + */ + @Bean(name = "holidayCache") + public Cache> holidayCache(){ + Cache> cache = Caffeine.newBuilder() + .expireAfterWrite(24 * 30, TimeUnit.HOURS) + .maximumSize(100) + .build(); + return cache; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/converter/CustomConverterConfig.java b/ruoyi-admin/src/main/java/cn/xluobo/config/converter/CustomConverterConfig.java new file mode 100644 index 0000000..470204b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/converter/CustomConverterConfig.java @@ -0,0 +1,31 @@ +package cn.xluobo.config.converter; + +import org.springframework.context.annotation.Configuration; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/8/18 19:43 + */ +@Configuration +public class CustomConverterConfig { + /** + * 解决前端js处理大数字丢失精度问题,将Long和BigInteger转换成string + * + * @return + */ + /*@Bean + @ConditionalOnMissingBean + public MappingJackson2HttpMessageConverter getMappingJackson2HttpMessageConverter() { + CustomMappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new CustomMappingJackson2HttpMessageConverter(); + ObjectMapper objectMapper = new ObjectMapper(); + SimpleModule simpleModule = new SimpleModule(); + // 序列换成json时,将所有的long变成string 因为js中得数字类型不能包含所有的java long值 + simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance); + simpleModule.addSerializer(Long.class, ToStringSerializer.instance); + simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); + objectMapper.registerModule(simpleModule); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + jackson2HttpMessageConverter.setObjectMapper(objectMapper); + return jackson2HttpMessageConverter; + }*/ +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/converter/CustomMappingJackson2HttpMessageConverter.java b/ruoyi-admin/src/main/java/cn/xluobo/config/converter/CustomMappingJackson2HttpMessageConverter.java new file mode 100644 index 0000000..4877e9d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/converter/CustomMappingJackson2HttpMessageConverter.java @@ -0,0 +1,61 @@ +package cn.xluobo.config.converter; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Type; + +/** + * 自定义的json转换器,匹配web api(以/web/开头的controller)中的接口方法的返回参数 + * + * @author zhangby + * + */ +public class CustomMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter { + + private final static Logger logger = LoggerFactory.getLogger(CustomMappingJackson2HttpMessageConverter.class); + + /** + * 判断该转换器是否能将请求内容转换成 Java 对象 + */ + @Override + public boolean canRead(Class clazz, MediaType mediaType) { + // 不需要反序列化 + return false; + } + + /** + * 判断该转换器是否能将请求内容转换成 Java 对象 + */ + @Override + public boolean canRead(Type type, Class contextClass, MediaType mediaType) { + // 不需要反序列化 + return false; + } + + /** + * 判断该转换器是否可以将 Java 对象转换成返回内容. + * 匹配web api(形如/web/xxxx)中的接口方法的返回参数 + */ + @Override + public boolean canWrite(Class clazz, MediaType mediaType) { + if (super.canWrite(clazz, mediaType)) { + ServletRequestAttributes ra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (null != ra) { // web请求 + HttpServletRequest request = ra.getRequest(); + String uri = request.getRequestURI(); + /*if (uri.startsWith("/api/")) { + return true; + }*/ + return true; + } + } + return false; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/exception/BusinessException.java b/ruoyi-admin/src/main/java/cn/xluobo/config/exception/BusinessException.java new file mode 100644 index 0000000..3684b5b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/exception/BusinessException.java @@ -0,0 +1,12 @@ +package cn.xluobo.config.exception; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/9/4 16:36 + */ +public class BusinessException extends RuntimeException{ + + public BusinessException(String message) { + super(message); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/http/RestTemplateConfig.java b/ruoyi-admin/src/main/java/cn/xluobo/config/http/RestTemplateConfig.java new file mode 100644 index 0000000..c041377 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/http/RestTemplateConfig.java @@ -0,0 +1,19 @@ +package cn.xluobo.config.http; + +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-05 09:34 + */ +@Configuration +public class RestTemplateConfig { + + @Bean + public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) { + return restTemplateBuilder.build(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/integration/IntegrationAuthentication.java b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/IntegrationAuthentication.java new file mode 100644 index 0000000..331dd33 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/IntegrationAuthentication.java @@ -0,0 +1,37 @@ +package cn.xluobo.config.integration; + +import lombok.Data; + +import java.util.Map; + +/** + * 授权参数 + * @author :zhangbaoyu + * @date :Created in 2020/7/7 09:36 + */ +@Data +public class IntegrationAuthentication { + + /** + * 授权类型 + */ + private String authType; + + /** + * 用户名 + */ + private String username; + + /** + * 参数 + */ + private Map authParameters; + + public String getAuthParameter(String parameter){ + String[] values = this.authParameters.get(parameter); + if(values != null && values.length > 0){ + return values[0]; + } + return null; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/integration/IntegrationAuthenticationContext.java b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/IntegrationAuthenticationContext.java new file mode 100644 index 0000000..3154e8c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/IntegrationAuthenticationContext.java @@ -0,0 +1,21 @@ +package cn.xluobo.config.integration; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/7/7 09:47 + */ +public class IntegrationAuthenticationContext { + private static ThreadLocal holder = new ThreadLocal<>(); + + public static void set(IntegrationAuthentication integrationAuthentication){ + holder.set(integrationAuthentication); + } + + public static IntegrationAuthentication get(){ + return holder.get(); + } + + public static void clear(){ + holder.remove(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/integration/IntegrationAuthenticationFilter.java b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/IntegrationAuthenticationFilter.java new file mode 100644 index 0000000..bc2d4cd --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/IntegrationAuthenticationFilter.java @@ -0,0 +1,120 @@ +package cn.xluobo.config.integration; + +import cn.xluobo.config.integration.authenticator.IntegrationAuthenticator; +import com.alibaba.fastjson.JSON; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.util.matcher.OrRequestMatcher; +import org.springframework.security.web.util.matcher.RequestMatcher; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +/** + * 集成 各登录方式过滤器 + * 适用于 grant_type password 模式 + * 请求中增加 auth_type 字段 + * @author :zhangbaoyu + * @date :Created in 2020/7/7 09:32 + */ +@Component +public class IntegrationAuthenticationFilter extends OncePerRequestFilter implements ApplicationContextAware { + + private static final String AUTH_TYPE_PARAM_NAME = "auth_type"; + + private static final String OAUTH_TOKEN_URL = "/oauth/token"; + + private Collection authenticators; + + private ApplicationContext applicationContext; + + private RequestMatcher requestMatcher; + + public IntegrationAuthenticationFilter(){ + this.requestMatcher = new OrRequestMatcher( + new AntPathRequestMatcher(OAUTH_TOKEN_URL, "GET"), + new AntPathRequestMatcher(OAUTH_TOKEN_URL, "POST") + ); + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + if(requestMatcher.matches(request)){ + System.out.println(request.getRequestURI()); + System.out.println(request.getMethod()); + System.out.println(JSON.toJSONString(request.getParameterMap())); + //设置集成登录信息 + IntegrationAuthentication integrationAuthentication = new IntegrationAuthentication(); + integrationAuthentication.setAuthType(request.getParameter(AUTH_TYPE_PARAM_NAME)); + integrationAuthentication.setAuthParameters(request.getParameterMap()); + IntegrationAuthenticationContext.set(integrationAuthentication); + try{ + //预处理 + this.prepare(integrationAuthentication); + + filterChain.doFilter(request,response); + + //后置处理 + this.complete(integrationAuthentication); + }finally { + IntegrationAuthenticationContext.clear(); + } + }else{ + filterChain.doFilter(request,response); + } + } + + /** + * 进行预处理 + * @param integrationAuthentication + */ + private void prepare(IntegrationAuthentication integrationAuthentication) { + + //延迟加载认证器 + if(this.authenticators == null){ + synchronized (this){ + Map integrationAuthenticatorMap = applicationContext.getBeansOfType(IntegrationAuthenticator.class); + if(integrationAuthenticatorMap != null){ + this.authenticators = integrationAuthenticatorMap.values(); + } + } + } + + if(this.authenticators == null){ + this.authenticators = new ArrayList<>(); + } + + for (IntegrationAuthenticator authenticator: authenticators) { + if(authenticator.support(integrationAuthentication)){ + authenticator.prepare(integrationAuthentication); + } + } + } + + /** + * 后置处理 + * @param integrationAuthentication + */ + private void complete(IntegrationAuthentication integrationAuthentication){ + for (IntegrationAuthenticator authenticator: authenticators) { + if(authenticator.support(integrationAuthentication)){ + authenticator.complete(integrationAuthentication); + } + } + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/AbstractPreparedIntegrationAuthenticator.java b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/AbstractPreparedIntegrationAuthenticator.java new file mode 100644 index 0000000..36cca5a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/AbstractPreparedIntegrationAuthenticator.java @@ -0,0 +1,25 @@ +package cn.xluobo.config.integration.authenticator; + +import cn.xluobo.config.integration.IntegrationAuthentication; +import com.ruoyi.common.core.domain.model.LoginUser; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/7/7 09:49 + */ +public abstract class AbstractPreparedIntegrationAuthenticator implements IntegrationAuthenticator { + + @Override + public abstract LoginUser authenticate(IntegrationAuthentication integrationAuthentication); + + @Override + public abstract boolean support(IntegrationAuthentication integrationAuthentication); + + @Override + public abstract void prepare(IntegrationAuthentication integrationAuthentication); + + @Override + public void complete(IntegrationAuthentication integrationAuthentication) { + + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/IntegrationAuthenticator.java b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/IntegrationAuthenticator.java new file mode 100644 index 0000000..97ddec9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/IntegrationAuthenticator.java @@ -0,0 +1,38 @@ +package cn.xluobo.config.integration.authenticator; + +import cn.xluobo.config.integration.IntegrationAuthentication; +import com.ruoyi.common.core.domain.model.LoginUser; + +/** + * 各项登录方式授权接口 + * @author :zhangbaoyu + * @date :Created in 2020/7/7 09:34 + */ +public interface IntegrationAuthenticator { + + /** + * 处理认证 + * @param integrationAuthentication + * @return + */ + LoginUser authenticate(IntegrationAuthentication integrationAuthentication); + + /** + * 是否支持认证类型 + * @param integrationAuthentication + * @return + */ + boolean support(IntegrationAuthentication integrationAuthentication); + + /** + * 预处理 + * @param integrationAuthentication + */ + void prepare(IntegrationAuthentication integrationAuthentication); + + /** + * 认证结束后执行 + * @param integrationAuthentication + */ + void complete(IntegrationAuthentication integrationAuthentication); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/UsernamePasswordAuthenticator.java b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/UsernamePasswordAuthenticator.java new file mode 100644 index 0000000..eb7f848 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/UsernamePasswordAuthenticator.java @@ -0,0 +1,37 @@ +package cn.xluobo.config.integration.authenticator; + +import cn.xluobo.business.sys.admin.service.ISysUserService; +import cn.xluobo.config.integration.IntegrationAuthentication; +import com.ruoyi.common.core.domain.model.LoginUser; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +/** + * 默认登录处理 + * @author :zhangbaoyu + * @date :Created in 2020/7/7 10:08 + */ +@Component +@Primary +public class UsernamePasswordAuthenticator extends AbstractPreparedIntegrationAuthenticator{ + + @Autowired + private ISysUserService sysUserService; + + @Override + public LoginUser authenticate(IntegrationAuthentication integrationAuthentication) { + return (LoginUser)sysUserService.loadUserDetailByUserName(integrationAuthentication.getUsername()); + } + + @Override + public boolean support(IntegrationAuthentication integrationAuthentication) { + return StringUtils.isEmpty(integrationAuthentication.getAuthType()); + } + + @Override + public void prepare(IntegrationAuthentication integrationAuthentication) { + + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/VerificationCodeIntegrationAuthenticator.java b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/VerificationCodeIntegrationAuthenticator.java new file mode 100644 index 0000000..599fc39 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/VerificationCodeIntegrationAuthenticator.java @@ -0,0 +1,30 @@ +package cn.xluobo.config.integration.authenticator; + +import cn.xluobo.config.integration.IntegrationAuthentication; +import org.springframework.stereotype.Component; + +/** + * 集成验证码认证 + **/ +@Component +public class VerificationCodeIntegrationAuthenticator extends UsernamePasswordAuthenticator { + + private final static String VERIFICATION_CODE_AUTH_TYPE = "vc"; + + @Override + public void prepare(IntegrationAuthentication integrationAuthentication) { + // 验证码token + String vcToken = integrationAuthentication.getAuthParameter("vc_token"); + // 验证码 + String vcCode = integrationAuthentication.getAuthParameter("vc_code"); + //todo 验证验证码是否正确 + + // todo 如果不正确抛出异常 + // throw new OAuth2Exception("验证码错误"); + } + + @Override + public boolean support(IntegrationAuthentication integrationAuthentication) { + return VERIFICATION_CODE_AUTH_TYPE.equals(integrationAuthentication.getAuthType()); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/sms/event/SmsAuthenticateBeforeEvent.java b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/sms/event/SmsAuthenticateBeforeEvent.java new file mode 100644 index 0000000..f484f6d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/sms/event/SmsAuthenticateBeforeEvent.java @@ -0,0 +1,17 @@ +package cn.xluobo.config.integration.authenticator.sms.event; + +import org.springframework.context.ApplicationEvent; + +/** + * 短信认证之前的事件,可以监听事件进行用户手机号自动注册 + **/ +public class SmsAuthenticateBeforeEvent extends ApplicationEvent { + /** + * Create a new ApplicationEvent. + * + * @param source the object on which the event initially occurred (never {@code null}) + */ + public SmsAuthenticateBeforeEvent(Object source) { + super(source); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/sms/event/SmsAuthenticateSuccessEvent.java b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/sms/event/SmsAuthenticateSuccessEvent.java new file mode 100644 index 0000000..71880f9 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/sms/event/SmsAuthenticateSuccessEvent.java @@ -0,0 +1,17 @@ +package cn.xluobo.config.integration.authenticator.sms.event; + +import org.springframework.context.ApplicationEvent; + +/** + * 短信认证成功事件 + **/ +public class SmsAuthenticateSuccessEvent extends ApplicationEvent { + /** + * Create a new ApplicationEvent. + * + * @param source the object on which the event initially occurred (never {@code null}) + */ + public SmsAuthenticateSuccessEvent(Object source) { + super(source); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/wechat/miniapp/WechatMiniAppToken.java b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/wechat/miniapp/WechatMiniAppToken.java new file mode 100644 index 0000000..9cf0946 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/integration/authenticator/wechat/miniapp/WechatMiniAppToken.java @@ -0,0 +1,20 @@ +package cn.xluobo.config.integration.authenticator.wechat.miniapp; + +import lombok.Data; + +@Data +public class WechatMiniAppToken { + + private String openId; + private String unionId; + private String sessionKey; + private String username; + private String encryptedData; + private String iv; + + public WechatMiniAppToken(String openId, String unionId, String sessionKey) { + this.openId = openId; + this.unionId = unionId; + this.sessionKey = sessionKey; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/login/LoginTypeEnum.java b/ruoyi-admin/src/main/java/cn/xluobo/config/login/LoginTypeEnum.java new file mode 100644 index 0000000..52f7162 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/login/LoginTypeEnum.java @@ -0,0 +1,26 @@ +package cn.xluobo.config.login; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/10/15 12:38 + */ +public enum LoginTypeEnum { + PC("Pc", "电脑端"), + WECHAT_MINI_APP("WechatMiniApp", "小程序端"), + ; + private String loginType; + private String loginTypeName; + + LoginTypeEnum(String loginType, String loginTypeName) { + this.loginType = loginType; + this.loginTypeName = loginTypeName; + } + + public String getLoginType() { + return loginType; + } + + public String getLoginTypeName() { + return loginTypeName; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/mybatis/MybatisConfiguration.java b/ruoyi-admin/src/main/java/cn/xluobo/config/mybatis/MybatisConfiguration.java new file mode 100644 index 0000000..692fa98 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/mybatis/MybatisConfiguration.java @@ -0,0 +1,55 @@ +package cn.xluobo.config.mybatis; + +import cn.xluobo.config.tenant.MyTenantHandler; +import cn.xluobo.config.tenant.MyTenantParser; +import com.baomidou.mybatisplus.core.parser.ISqlParser; +import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; +import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import java.util.ArrayList; +import java.util.List; + +@EnableTransactionManagement +@Configuration +@AutoConfigureAfter(DataSourceAutoConfiguration.class) +@MapperScan(value = {"cn.xluobo.*.*.*.repo.mapper"}) +public class MybatisConfiguration { + + /** + * 分页插件 + */ + @Bean + @ConditionalOnMissingBean(PaginationInterceptor.class) + public PaginationInterceptor paginationInterceptor() { + PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); + List sqlParserList = new ArrayList<>(); + + TenantSqlParser tenantSqlParser = new MyTenantParser(); + tenantSqlParser.setTenantHandler(new MyTenantHandler()); + sqlParserList.add(tenantSqlParser); + + paginationInterceptor.setSqlParserList(sqlParserList); + return paginationInterceptor; + } + + /** + * 乐观锁插件 + * 注解实体字段 @Version + * 仅支持 updateById(id) 与 update(entity, wrapper) 方法 + * 在 update(entity, wrapper) 方法下, wrapper 不能复用!!! + # + * @return + */ + @Bean + public OptimisticLockerInterceptor optimisticLockerInterceptor() { + return new OptimisticLockerInterceptor(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/properties/AddressProperties.java b/ruoyi-admin/src/main/java/cn/xluobo/config/properties/AddressProperties.java new file mode 100644 index 0000000..4fc2d2a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/properties/AddressProperties.java @@ -0,0 +1,21 @@ +package cn.xluobo.config.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-03-01 10:45 + */ +@ConfigurationProperties(prefix = "xluobo.address") +public class AddressProperties { + + private static boolean decodeIp; + + public void setDecodeIp(boolean decodeIp) { + AddressProperties.decodeIp = decodeIp; + } + + public static boolean isDecodeIp() { + return decodeIp; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/properties/OAuth2ClientDetail.java b/ruoyi-admin/src/main/java/cn/xluobo/config/properties/OAuth2ClientDetail.java new file mode 100644 index 0000000..4383652 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/properties/OAuth2ClientDetail.java @@ -0,0 +1,51 @@ +package cn.xluobo.config.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-07 15:19 + */ +@ConfigurationProperties(prefix = "security.oauth2.client") +public class OAuth2ClientDetail { + + private String clientId; + + private String clientSecret; + + private String accessTokenUri; + + private String redirectUri; + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + + public String getAccessTokenUri() { + return accessTokenUri; + } + + public void setAccessTokenUri(String accessTokenUri) { + this.accessTokenUri = accessTokenUri; + } + + public String getRedirectUri() { + return redirectUri; + } + + public void setRedirectUri(String redirectUri) { + this.redirectUri = redirectUri; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/properties/OAuth2SsoDetail.java b/ruoyi-admin/src/main/java/cn/xluobo/config/properties/OAuth2SsoDetail.java new file mode 100644 index 0000000..70d4249 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/properties/OAuth2SsoDetail.java @@ -0,0 +1,20 @@ +package cn.xluobo.config.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-07 15:19 + */ +@ConfigurationProperties(prefix = "security.oauth2.sso") +public class OAuth2SsoDetail { + private String ssoRedirectUrl; + + public String getSsoRedirectUrl() { + return ssoRedirectUrl; + } + + public void setSsoRedirectUrl(String ssoRedirectUrl) { + this.ssoRedirectUrl = ssoRedirectUrl; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/properties/UploadConfigProperties.java b/ruoyi-admin/src/main/java/cn/xluobo/config/properties/UploadConfigProperties.java new file mode 100644 index 0000000..f633bb1 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/properties/UploadConfigProperties.java @@ -0,0 +1,50 @@ +package cn.xluobo.config.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-03-01 10:45 + */ +@ConfigurationProperties(prefix = "xluobo.upload") +public class UploadConfigProperties { + + /** + * 文件存储路径 + */ + private String filePath; + + /** + * 临时存储下载文件 + */ + private String tempSaveExportPath; + + /** + * 临时存储导入文件 + */ + private String tempSaveImportPath; + + public String getFilePath() { + return filePath; + } + + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + public String getTempSaveExportPath() { + return tempSaveExportPath; + } + + public void setTempSaveExportPath(String tempSaveExportPath) { + this.tempSaveExportPath = tempSaveExportPath; + } + + public String getTempSaveImportPath() { + return tempSaveImportPath; + } + + public void setTempSaveImportPath(String tempSaveImportPath) { + this.tempSaveImportPath = tempSaveImportPath; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/properties/WechatOAuth2ClientProperties.java b/ruoyi-admin/src/main/java/cn/xluobo/config/properties/WechatOAuth2ClientProperties.java new file mode 100644 index 0000000..c37f19d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/properties/WechatOAuth2ClientProperties.java @@ -0,0 +1,17 @@ +package cn.xluobo.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/10/15 10:35 + */ +@Data +@ConfigurationProperties(prefix = "wechat.oauth2.client") +public class WechatOAuth2ClientProperties { + + private String clientId; + + private String clientSecret; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAccessDecisionManager.java b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAccessDecisionManager.java new file mode 100644 index 0000000..23ef2e4 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAccessDecisionManager.java @@ -0,0 +1,53 @@ +package cn.xluobo.config.security; + +import org.springframework.security.access.AccessDecisionManager; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.authentication.InsufficientAuthenticationException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.Iterator; + +/** + * Created by zhangbaoyu on 18/1/9. + */ +@Service +public class CustomAccessDecisionManager implements AccessDecisionManager { + + // decide 方法是判定是否拥有权限的决策方法, + //authentication 是释CustomUserService中循环添加到 GrantedAuthority 对象中的权限信息集合. + //object 包含客户端发起的请求的requset信息,可转换为 HttpServletRequest request = ((FilterInvocation) object).getHttpRequest(); + //configAttributes 为MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法返回的结果,此方法是为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。 + @Override + public void decide(Authentication authentication, Object o, Collection configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { + if(null== configAttributes || configAttributes.size() <=0) { + return; + } + ConfigAttribute c; + String needRole; + for(Iterator iter = configAttributes.iterator(); iter.hasNext(); ) { + c = iter.next(); + needRole = c.getAttribute(); + for(GrantedAuthority ga : authentication.getAuthorities()) {//authentication 为在注释1 中循环添加到 GrantedAuthority 对象中的权限信息集合 + String authority = ga.getAuthority(); + if(needRole.trim().equals(authority)) { + return; + } + } + } + throw new AccessDeniedException("no right"); + } + + @Override + public boolean supports(ConfigAttribute configAttribute) { + return true; + } + + @Override + public boolean supports(Class aClass) { + return true; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAuthenticationFailureHandler.java b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAuthenticationFailureHandler.java new file mode 100644 index 0000000..615f6c3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAuthenticationFailureHandler.java @@ -0,0 +1,39 @@ +package cn.xluobo.config.security; + +import cn.xluobo.core.api.APIBaseResponse; +import com.alibaba.fastjson.JSON; +import org.springframework.http.MediaType; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * 登录失败 + * + * @author :zhangbaoyu + * @date :Created in 2020-02-27 17:42 + */ +public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { + String xRequestedWith = request.getHeader("X-Requested-With"); + if (MediaType.APPLICATION_JSON_UTF8_VALUE.equals(request.getContentType()) + || MediaType.APPLICATION_JSON_VALUE.equals(request.getContentType()) + || "XMLHttpRequest".equalsIgnoreCase(xRequestedWith)) { + String message = exception.getMessage(); + String failJson = JSON.toJSONString(new APIBaseResponse("LOGIN0001", message)); + response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); + PrintWriter out = response.getWriter(); + out.write(failJson); + out.flush(); + out.close(); + } else { + super.onAuthenticationFailure(request, response, exception); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAuthenticationSuccessHandler.java b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAuthenticationSuccessHandler.java new file mode 100644 index 0000000..bbbcbf3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAuthenticationSuccessHandler.java @@ -0,0 +1,121 @@ +package cn.xluobo.config.security; + +import cn.xluobo.business.sys.log.service.ISysUserLoginLogService; +import cn.xluobo.core.api.APIBaseResponse; +import com.alibaba.fastjson.JSON; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.security.web.savedrequest.HttpSessionRequestCache; +import org.springframework.security.web.savedrequest.RequestCache; +import org.springframework.security.web.savedrequest.SavedRequest; +import org.springframework.security.web.util.UrlUtils; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * 登录成功 + * + * @author :zhangbaoyu + * @date :Created in 2020-02-27 17:41 + */ +@Component +public class CustomAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { + + private RequestCache requestCache = new HttpSessionRequestCache(); + private boolean contextRelative; + @Autowired + private ISysUserLoginLogService loginLogService; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + loginLogService.saveLoginLog(request, authentication); + + String xRequestedWith = request.getHeader("X-Requested-With"); + if (MediaType.APPLICATION_JSON_UTF8_VALUE.equals(request.getContentType()) + || MediaType.APPLICATION_JSON_VALUE.equals(request.getContentType()) + || "XMLHttpRequest".equalsIgnoreCase(xRequestedWith)) { + + //获取需要redirect的url + SavedRequest savedRequest = requestCache.getRequest(request, response); + + if (savedRequest == null) { + super.onAuthenticationSuccess(request, response, authentication); + + return; + } + String targetUrlParameter = getTargetUrlParameter(); + if (isAlwaysUseDefaultTargetUrl() + || (targetUrlParameter != null && StringUtils.hasText(request + .getParameter(targetUrlParameter)))) { + requestCache.removeRequest(request, response); + super.onAuthenticationSuccess(request, response, authentication); + + return; + } + + clearAuthenticationAttributes(request); + + // Use the DefaultSavedRequest URL + String targetUrl = savedRequest.getRedirectUrl(); + + String redirectUrl = calculateRedirectUrl(request.getContextPath(), targetUrl); + redirectUrl = response.encodeRedirectURL(redirectUrl); + + String failJson = JSON.toJSONString(new APIBaseResponse("0000", redirectUrl)); + response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); + PrintWriter out = response.getWriter(); + out.write(failJson); + out.flush(); + out.close(); + } else { + super.onAuthenticationSuccess(request, response, authentication); + } + } + + protected String calculateRedirectUrl(String contextPath, String url) { + if (!UrlUtils.isAbsoluteUrl(url)) { + if (isContextRelative()) { + return url; + } else { + return contextPath + url; + } + } + + // Full URL, including http(s):// + + if (!isContextRelative()) { + return url; + } + + // Calculate the relative URL from the fully qualified URL, minus the last + // occurrence of the scheme and base context. + url = url.substring(url.lastIndexOf("://") + 3); // strip off scheme + url = url.substring(url.indexOf(contextPath) + contextPath.length()); + + if (url.length() > 1 && url.charAt(0) == '/') { + url = url.substring(1); + } + + return url; + } + + /** + * If true, causes any redirection URLs to be calculated minus the protocol + * and context path (defaults to false). + */ + public void setContextRelative(boolean useRelativeContext) { + this.contextRelative = useRelativeContext; + } + + protected boolean isContextRelative() { + return contextRelative; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomFilterSecurityInterceptor.java b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomFilterSecurityInterceptor.java new file mode 100644 index 0000000..49d17ea --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomFilterSecurityInterceptor.java @@ -0,0 +1,59 @@ +package cn.xluobo.config.security; + +import cn.xluobo.utils.ContextUtils; +import org.springframework.security.access.SecurityMetadataSource; +import org.springframework.security.access.intercept.AbstractSecurityInterceptor; +import org.springframework.security.access.intercept.InterceptorStatusToken; +import org.springframework.security.web.FilterInvocation; + +import javax.servlet.*; +import java.io.IOException; + +/** + * Created by zhangbaoyu on 18/1/9. + */ +public class CustomFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { + + public CustomFilterSecurityInterceptor(CustomAccessDecisionManager myAccessDecisionManager) { + super.setAccessDecisionManager(myAccessDecisionManager); + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + FilterInvocation fi = new FilterInvocation(request, response, chain); + invoke(fi); + } + + public void invoke(FilterInvocation fi) throws IOException, ServletException { + //fi里面有一个被拦截的url + //里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限 + //再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够 + InterceptorStatusToken token = super.beforeInvocation(fi); + try { + //执行下一个拦截器 + fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); + } finally { + super.afterInvocation(token, null); + } + } + + @Override + public void destroy() { + + } + + @Override + public Class getSecureObjectClass() { + return FilterInvocation.class; + } + + @Override + public SecurityMetadataSource obtainSecurityMetadataSource() { + return ContextUtils.getBean(CustomSecurityMetadataSource.class); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomSecurityMetadataSource.java b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomSecurityMetadataSource.java new file mode 100644 index 0000000..957019a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomSecurityMetadataSource.java @@ -0,0 +1,75 @@ +package cn.xluobo.config.security; + +import cn.xluobo.business.sys.admin.service.ISysMenuService; +import cn.xluobo.utils.ContextUtils; +import com.ruoyi.common.core.domain.entity.SysMenu; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.access.SecurityConfig; +import org.springframework.security.web.FilterInvocation; +import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import java.util.*; + +/** + * Created by zhangbaoyu on 18/1/9. + */ +@Component +public class CustomSecurityMetadataSource implements FilterInvocationSecurityMetadataSource { + + private HashMap> map =null; + + public void loadResourceDefine(){ + ISysMenuService menuService = ContextUtils.getBean(ISysMenuService.class); + map = new HashMap<>(); + Collection array; + ConfigAttribute cfg; + List sysMenuList = menuService.selectAllPermissionUrl(); + for(SysMenu menu : sysMenuList) { + array = new ArrayList<>(); +// cfg = new SecurityConfig(menu.getPermissionMeta()); + //此处只添加了用户的名字,其实还可以添加更多权限的信息,例如请求方法到ConfigAttribute的集合中去。此处添加的信息将会作为MyAccessDecisionManager类的decide的第三个参数。 +// array.add(cfg); + //用权限的getUrl() 作为map的key,用ConfigAttribute的集合作为 value, +// map.put(menu.getRequestUrl(), array); + } + } + + @Override + public Collection getAttributes(Object object) throws IllegalArgumentException { + Collection configAttributeCollection = null; + if(map ==null){ + loadResourceDefine(); + } + + //object 中包含用户请求的request 信息 + HttpServletRequest request = ((FilterInvocation) object).getHttpRequest(); + AntPathRequestMatcher matcher; + String resUrl; + for(Iterator iter = map.keySet().iterator(); iter.hasNext(); ) { + resUrl = iter.next(); + matcher = new AntPathRequestMatcher(resUrl); + if(matcher.matches(request)) { + if(null == configAttributeCollection){ + configAttributeCollection= map.get(resUrl); + }else{ + configAttributeCollection.addAll(map.get(resUrl)); + } + } + } + return configAttributeCollection; + } + + @Override + public Collection getAllConfigAttributes() { + return null; + } + + @Override + public boolean supports(Class aClass) { + return true; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomUserService.java b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomUserService.java new file mode 100644 index 0000000..96df477 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomUserService.java @@ -0,0 +1,21 @@ +package cn.xluobo.config.security; + +import cn.xluobo.business.sys.admin.service.ISysUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +/** + * Created by zhangbaoyu on 18/1/9. + */ +public class CustomUserService implements UserDetailsService { + + @Autowired + private ISysUserService sysUserService; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + return sysUserService.loadUserDetailByUserName(username); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomUsernamePasswordAuthenticationFilter.java b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomUsernamePasswordAuthenticationFilter.java new file mode 100644 index 0000000..3f2b62a --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomUsernamePasswordAuthenticationFilter.java @@ -0,0 +1,60 @@ +package cn.xluobo.config.security; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.collections.MapUtils; +import org.springframework.http.MediaType; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +/** + * 自定义登录 + * 可增加 校验项,但不推荐,无法完成 remember me登录 + * @author :zhangbaoyu + * @date :Created in 2020-02-27 17:25 + */ +public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { + if (MediaType.APPLICATION_JSON_UTF8_VALUE.equals(request.getContentType()) + || MediaType.APPLICATION_JSON_VALUE.equals(request.getContentType())) { + + String username = ""; + String password = ""; + ObjectMapper mapper = new ObjectMapper(); + // 可增加 校验项,但不推荐,无法完成 remember me登录 + try (InputStream is = request.getInputStream()){ + Map reqParam = mapper.readValue(is, Map.class); + username = MapUtils.getString(reqParam,getUsernameParameter()); + password = MapUtils.getString(reqParam,getPasswordParameter()); + }catch (IOException e) { + logger.error("imageCode get error",e); + } + + if (username == null) { + username = ""; + } + + if (password == null) { + password = ""; + } + + username = username.trim(); + UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( + username, password); + setDetails(request, authRequest); + return this.getAuthenticationManager().authenticate(authRequest); + + } else { + return super.attemptAuthentication(request, response); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/security/LoginPwdDaoAuthenticationProvider.java b/ruoyi-admin/src/main/java/cn/xluobo/config/security/LoginPwdDaoAuthenticationProvider.java new file mode 100644 index 0000000..a95e01f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/security/LoginPwdDaoAuthenticationProvider.java @@ -0,0 +1,38 @@ +package cn.xluobo.config.security; + +import cn.xluobo.core.utils.aes.EncryptUtil; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/11/17 09:30 + */ +public class LoginPwdDaoAuthenticationProvider extends DaoAuthenticationProvider { + + @Override + protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { + if (authentication.getCredentials() == null) { + logger.debug("Authentication failed: no credentials provided"); + + throw new BadCredentialsException(messages.getMessage( + "AbstractUserDetailsAuthenticationProvider.badCredentials", + "Bad credentials")); + } + + String presentedPassword = authentication.getCredentials().toString(); + + String password = EncryptUtil.decryptBase64(presentedPassword,"d26171A30c9fe068"); + + if (!getPasswordEncoder().matches(password, userDetails.getPassword())) { + logger.debug("Authentication failed: password does not match stored value"); + + throw new BadCredentialsException(messages.getMessage( + "AbstractUserDetailsAuthenticationProvider.badCredentials", + "Bad credentials")); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/tenant/MyTenantHandler.java b/ruoyi-admin/src/main/java/cn/xluobo/config/tenant/MyTenantHandler.java new file mode 100644 index 0000000..e6b1368 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/tenant/MyTenantHandler.java @@ -0,0 +1,42 @@ +package cn.xluobo.config.tenant; + +import cn.xluobo.business.enums.BusinessTableEnums; +import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.LongValue; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class MyTenantHandler implements TenantHandler { + + private static final Map tenantDbTable = new ConcurrentHashMap(); + + static { + for (BusinessTableEnums businessTableEnums : BusinessTableEnums.values()) { + if(businessTableEnums.isTenant()){ + tenantDbTable.put(businessTableEnums.getTable(),businessTableEnums); + } + } + + } + + @Override + public Expression getTenantId(boolean where) { + return singleTenantIdCondition(); + } + + @Override + public String getTenantIdColumn() { + return "tenant_id"; + } + + @Override + public boolean doTableFilter(String tableName) { + return !tenantDbTable.containsKey(tableName); + } + + private Expression singleTenantIdCondition() { + return new LongValue(TenantContextHolder.getTenant()); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/tenant/MyTenantParser.java b/ruoyi-admin/src/main/java/cn/xluobo/config/tenant/MyTenantParser.java new file mode 100644 index 0000000..2658dbf --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/tenant/MyTenantParser.java @@ -0,0 +1,97 @@ +package cn.xluobo.config.tenant; + +import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser; +import net.sf.jsqlparser.expression.BinaryExpression; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.Parenthesis; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.expression.operators.conditional.OrExpression; +import net.sf.jsqlparser.expression.operators.relational.EqualsTo; +import net.sf.jsqlparser.expression.operators.relational.InExpression; +import net.sf.jsqlparser.expression.operators.relational.ItemsList; +import net.sf.jsqlparser.expression.operators.relational.SupportsOldOracleJoinSyntax; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.select.*; + +import java.util.List; + +public class MyTenantParser extends TenantSqlParser { + + /** + * 目前无法处理多租户的字段加上表别名 + * + * @param expression + * @param table + * @return + */ + protected Expression processTableAlias(Expression expression, Table table) { + return expression; + } + + /** + * 默认是按 tenant_id=1 按等于条件追加 + * + * @param currentExpression 现有的条件:比如你原来的sql查询条件 + * @param table + * @return + */ + @Override + protected Expression builderExpression(Expression currentExpression, Table table) { + final Expression tenantExpression = this.getTenantHandler().getTenantId(false); + Expression appendExpression; + if (!(tenantExpression instanceof SupportsOldOracleJoinSyntax)) { + appendExpression = new EqualsTo(); + ((EqualsTo) appendExpression).setLeftExpression(this.getAliasColumn(table)); + ((EqualsTo) appendExpression).setRightExpression(tenantExpression); + } else { + appendExpression = processTableAlias(tenantExpression, table); + } + if (currentExpression == null) { + return appendExpression; + } + if (currentExpression instanceof BinaryExpression) { + BinaryExpression binaryExpression = (BinaryExpression) currentExpression; + if (binaryExpression.getLeftExpression() instanceof FromItem) { + processFromItem((FromItem) binaryExpression.getLeftExpression()); + } + if (binaryExpression.getRightExpression() instanceof FromItem) { + processFromItem((FromItem) binaryExpression.getRightExpression()); + } + } else if (currentExpression instanceof InExpression) { + InExpression inExp = (InExpression) currentExpression; + ItemsList rightItems = inExp.getRightItemsList(); + if (rightItems instanceof SubSelect) { + processSelectBody(((SubSelect) rightItems).getSelectBody()); + } + } + if (currentExpression instanceof OrExpression) { + return new AndExpression(new Parenthesis(currentExpression), appendExpression); + } else { + return new AndExpression(currentExpression, appendExpression); + } + } + + @Override + protected void processPlainSelect(PlainSelect plainSelect, boolean addColumn) { + FromItem fromItem = plainSelect.getFromItem(); + if (fromItem instanceof Table) { + Table fromTable = (Table) fromItem; + if (!this.getTenantHandler().doTableFilter(fromTable.getName())) { + plainSelect.setWhere(builderExpression(plainSelect.getWhere(), fromTable)); + if (addColumn) { + plainSelect.getSelectItems().add(new SelectExpressionItem(new Column(this.getTenantHandler().getTenantIdColumn()))); + } + } + } else { + processFromItem(fromItem); + } + List joins = plainSelect.getJoins(); + if (joins != null && joins.size() > 0) { + joins.forEach(j -> { + processJoin(j); + processFromItem(j.getRightItem()); + }); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/tenant/TenantContextHolder.java b/ruoyi-admin/src/main/java/cn/xluobo/config/tenant/TenantContextHolder.java new file mode 100644 index 0000000..ff75e4e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/tenant/TenantContextHolder.java @@ -0,0 +1,34 @@ +package cn.xluobo.config.tenant; + +import cn.hutool.core.util.ObjectUtil; +import com.ruoyi.common.utils.SecurityUtils; +import org.apache.commons.lang3.StringUtils; + +/** + * 租户切换 + */ +public class TenantContextHolder { + private static ThreadLocal tenantThreadLocal = new ThreadLocal<>(); + + /** + * 注意:手动调用代码切换租户,处理完毕需调用remove() + * 由于getTenant()方法中。tenantThreadLocal 优先级 高于 用户当前的租户 + * 如不手动remove() , getTenant()时,有时候是从tenantThreadLocal取,有时候从用户中取。(因为处理线程不一致) + * @param scheme + */ + public static final void setTenant(Long scheme) { + tenantThreadLocal.set(scheme); + } + + public static final Long getTenant() { + Long tenantId = tenantThreadLocal.get(); + if (ObjectUtil.isEmpty(tenantId)) { + return SecurityUtils.getLoginUser().getNowTenantId(); + } + return tenantId; + } + + public static final void remove() { + tenantThreadLocal.remove(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/WechatCpConfiguration.java b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/WechatCpConfiguration.java new file mode 100644 index 0000000..246946f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/WechatCpConfiguration.java @@ -0,0 +1,91 @@ +package cn.xluobo.config.wechat.cp; + +import cn.xluobo.business.wechat.cp.repo.model.WechatCpAccount; +import cn.xluobo.business.wechat.cp.service.IWechatCpAccountService; +import cn.xluobo.config.wechat.cp.handler.ChangeExternalContactHandler; +import cn.xluobo.config.wechat.cp.handler.LogHandler; +import cn.xluobo.config.wechat.cp.handler.MsgHandler; +import com.google.common.collect.Maps; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.error.WxRuntimeException; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; +import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl; +import me.chanjar.weixin.cp.constant.WxCpConsts; +import me.chanjar.weixin.cp.message.WxCpMessageRouter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + + +@Configuration +public class WechatCpConfiguration { + + @Autowired + private LogHandler logHandler; + @Autowired + private MsgHandler msgHandler; + @Autowired + private ChangeExternalContactHandler changeExternalContactHandler; + @Autowired + private IWechatCpAccountService cpAccountService; + + private static Map routers = Maps.newHashMap(); + private static Map cpServices = Maps.newHashMap(); + + public static Map getRouters() { + return routers; + } + + public static WxCpService getCpService(String corpId, Integer agentId) { + WxCpService cpService = cpServices.get(corpId + agentId); + return Optional.ofNullable(cpService).orElseThrow(() -> new WxRuntimeException("未配置此service")); + } + + /** + * 初始化加载所有企业微信应用配置 + */ + @PostConstruct + public void initServices() { + List wechatCpAccountList = cpAccountService.selectAllInUseCpAccount(); + if (null !=wechatCpAccountList && !wechatCpAccountList.isEmpty()) { + cpServices = wechatCpAccountList.stream().map(item -> { + WxCpDefaultConfigImpl config = new WxCpDefaultConfigImpl(); + config.setCorpId(item.getCorpId()); + config.setAgentId(item.getAgentId()); + config.setCorpSecret(item.getAgentSecret()); + config.setToken(item.getCallBackToken()); + config.setAesKey(item.getCallBackKey()); + + WxCpServiceImpl service = new WxCpServiceImpl(); + service.setWxCpConfigStorage(config); + + routers.put(item.getCorpId() + item.getAgentId(), this.newRouter(service)); + return service; + }).collect(Collectors.toMap(service -> service.getWxCpConfigStorage().getCorpId() + service.getWxCpConfigStorage().getAgentId(), a -> a)); + } + } + + private WxCpMessageRouter newRouter(WxCpService wxCpService) { + final WxCpMessageRouter newRouter = new WxCpMessageRouter(wxCpService); + + // 记录所有事件的日志 (异步执行) + newRouter.rule().handler(this.logHandler).next(); + + // 外部联系人变更事件 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxCpConsts.EventType.CHANGE_EXTERNAL_CONTACT).handler(this.changeExternalContactHandler) + .end(); + + // 默认 + newRouter.rule().async(false).handler(this.msgHandler).end(); + + return newRouter; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/builder/AbstractBuilder.java b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/builder/AbstractBuilder.java new file mode 100644 index 0000000..d789209 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/builder/AbstractBuilder.java @@ -0,0 +1,14 @@ +package cn.xluobo.config.wechat.cp.builder; + +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; + +/** + * @author Binary Wang + */ +public abstract class AbstractBuilder { + + public abstract WxCpXmlOutMessage build(String content, WxCpXmlMessage wxMessage, WxCpService service); + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/builder/ImageBuilder.java b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/builder/ImageBuilder.java new file mode 100644 index 0000000..3d0d0c3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/builder/ImageBuilder.java @@ -0,0 +1,25 @@ +package cn.xluobo.config.wechat.cp.builder; + +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutImageMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; + + +/** + * @author Binary Wang + */ +public class ImageBuilder extends AbstractBuilder { + + @Override + public WxCpXmlOutMessage build(String content, WxCpXmlMessage wxMessage, + WxCpService service) { + + WxCpXmlOutImageMessage m = WxCpXmlOutMessage.IMAGE().mediaId(content) + .fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()) + .build(); + + return m; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/builder/TextBuilder.java b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/builder/TextBuilder.java new file mode 100644 index 0000000..abe580c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/builder/TextBuilder.java @@ -0,0 +1,22 @@ +package cn.xluobo.config.wechat.cp.builder; + +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutTextMessage; + +/** + * @author Binary Wang + */ +public class TextBuilder extends AbstractBuilder { + + @Override + public WxCpXmlOutMessage build(String content, WxCpXmlMessage wxMessage, + WxCpService service) { + WxCpXmlOutTextMessage m = WxCpXmlOutMessage.TEXT().content(content) + .fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()) + .build(); + return m; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/handler/ChangeExternalContactHandler.java b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/handler/ChangeExternalContactHandler.java new file mode 100644 index 0000000..6df7cdc --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/handler/ChangeExternalContactHandler.java @@ -0,0 +1,68 @@ +package cn.xluobo.config.wechat.cp.handler; + +import cn.xluobo.business.wechat.cp.service.WechatCpSyncService; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import me.chanjar.weixin.cp.constant.WxCpConsts; +import me.chanjar.weixin.cp.message.WxCpMessageHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * 新增外部联系人 + * + * @projectName: qyxt + * @package: cn.xluobo.config.wechat.cp.handler + * @className: AddExternalContactHandler + * @author: xluobo + * @description: 配置了客户联系功能的成员添加外部联系人时,回调该事件 + * @date: 2024/1/31 18:30 + */ +@Component +@Slf4j +public class ChangeExternalContactHandler implements WxCpMessageHandler { + + @Autowired + private WechatCpSyncService cpSyncService; + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map context, WxCpService wxCpService, WxSessionManager sessionManager) throws WxErrorException { + + // 企业微信CorpID + String cropId = wxMessage.getToUserName(); + String agentId = wxMessage.getAgentId(); + // 企业服务人员的UserID + String userId = wxMessage.getUserId(); + // 外部联系人的userid,注意不是企业成员的账号 + String externalUserId = wxMessage.getExternalUserId(); + // 添加此用户的「联系我」方式配置的state参数,或在获客链接中指定的customer_channel参数,可用于识别添加此用户的渠道 + String state = wxMessage.getState(); + + String changeType = wxMessage.getChangeType(); + + + if (changeType.equals(WxCpConsts.ExternalContactChangeType.ADD_EXTERNAL_CONTACT) + || changeType.equals(WxCpConsts.ExternalContactChangeType.EDIT_EXTERNAL_CONTACT) + || changeType.equals(WxCpConsts.ExternalContactChangeType.ADD_HALF_EXTERNAL_CONTACT) + ) { + // 添加企业客户事件、编辑企业客户事件、外部联系人免验证添加成员事件 + cpSyncService.saveExternalUserAndMargTag(cropId, agentId, externalUserId, userId, state); + } else if (changeType.equals(WxCpConsts.ExternalContactChangeType.DEL_FOLLOW_USER)) { + // 配置了客户联系功能的成员被外部联系人删除时,回调该事件 + cpSyncService.delExternalFollowUser(cropId, agentId, externalUserId, userId); + } else if (changeType.equals(WxCpConsts.ExternalContactChangeType.DEL_EXTERNAL_CONTACT)) { + // 配置了客户联系功能的成员删除外部联系人时,回调该事件 + cpSyncService.delExternalContact(cropId, agentId, externalUserId); + } + + return null; + } + + +} \ No newline at end of file diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/handler/LogHandler.java b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/handler/LogHandler.java new file mode 100644 index 0000000..3a96671 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/handler/LogHandler.java @@ -0,0 +1,25 @@ +package cn.xluobo.config.wechat.cp.handler; + +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import me.chanjar.weixin.cp.message.WxCpMessageHandler; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author Binary Wang + */ +@Component +@Slf4j +public class LogHandler implements WxCpMessageHandler { + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map context, WxCpService cpService, + WxSessionManager sessionManager) { + return null; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/handler/MsgHandler.java b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/handler/MsgHandler.java new file mode 100644 index 0000000..2c49246 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/handler/MsgHandler.java @@ -0,0 +1,40 @@ +package cn.xluobo.config.wechat.cp.handler; + +import cn.xluobo.config.wechat.cp.builder.TextBuilder; +import cn.xluobo.utils.JsonUtils; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import me.chanjar.weixin.cp.message.WxCpMessageHandler; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author Binary Wang + */ +@Component +public class MsgHandler implements WxCpMessageHandler { + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map context, WxCpService cpService, + WxSessionManager sessionManager) { + final String msgType = wxMessage.getMsgType(); + if (msgType == null) { + // 如果msgType没有,就自己根据具体报文内容做处理 + } + + if (!msgType.equals(WxConsts.XmlMsgType.EVENT)) { + //TODO 可以选择将消息保存到本地 + } + + //TODO 组装回复消息 + String content = "收到信息内容:" + JsonUtils.toJson(wxMessage); + + return new TextBuilder().build(content, wxMessage, cpService); + + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/api/APIBaseResponse.java b/ruoyi-admin/src/main/java/cn/xluobo/core/api/APIBaseResponse.java new file mode 100644 index 0000000..d234eb3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/api/APIBaseResponse.java @@ -0,0 +1,32 @@ +package cn.xluobo.core.api; + + +import lombok.Data; + +@Data +public class APIBaseResponse { + + String respCode; + + String respMsg; + + public APIBaseResponse() { + } + + public APIBaseResponse(String respCode, String respMsg) { + this.respCode = respCode; + this.respMsg = respMsg; + } + + public static APIBaseResponse success(){ + return new APIBaseResponse("0000","success"); + } + + public static APIBaseResponse fail(String failMsg){ + return new APIBaseResponse("9999",failMsg); + } + + public boolean isSuccess(){ + return "0000".equals(respCode); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/api/APIResponse.java b/ruoyi-admin/src/main/java/cn/xluobo/core/api/APIResponse.java new file mode 100644 index 0000000..158a9b0 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/api/APIResponse.java @@ -0,0 +1,92 @@ +package cn.xluobo.core.api; + + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = false) +public class APIResponse extends APIBaseResponse{ + + String respCode; + + + @Data + @EqualsAndHashCode(callSuper = false) + public static class ExceptionAPIResponse extends APIResponse { + Object msgDetail; + } + + @Data + @EqualsAndHashCode(callSuper = false) + public static class SuccessAPIResponse extends APIResponse { + Object data; + } + + public static APIResponse toOkResponse() { + return toAPIResponse(ApiResEnums.SUCCESS.getRespMsg()); + } + + public static APIResponse toAPIResponse(Object data) { + SuccessAPIResponse response = new SuccessAPIResponse(); + response.setData(data); + response.setRespCode(ApiResEnums.SUCCESS.getRespCode()); + response.setRespMsg(ApiResEnums.SUCCESS.getRespMsg()); + return response; + } + + public static APIResponse toFailResponse(){ + return toExceptionResponse(ApiResEnums.FAILURE); + } + + public static APIResponse toExceptionResponse(Object data) { + ExceptionAPIResponse response = new ExceptionAPIResponse(); + response.setMsgDetail(data); + response.setRespMsg(String.valueOf(data)); + response.setRespCode(ApiResEnums.BUSINESS_FAILURE.getRespCode()); + return response; + } + + public static APIResponse toExceptionResponse(ApiResEnums bizEnums){ + ExceptionAPIResponse response = new ExceptionAPIResponse(); + if (bizEnums != null) { + response.setMsgDetail(bizEnums.getRespMsg()); + response.setRespMsg(bizEnums.getRespMsg()); + response.setRespCode(bizEnums.getRespCode()); + } + return response; + } + + public static APIResponse toExceptionResponse(ApiResEnums bizEnums, Object msgDetail){ + ExceptionAPIResponse response = new ExceptionAPIResponse(); + if (bizEnums != null) { + response.setRespMsg(bizEnums.getRespMsg()); + response.setRespCode(bizEnums.getRespCode()); + } + response.setMsgDetail(msgDetail); + return response; + } + + @Override + public boolean isSuccess(){ + return this.respCode.equals(ApiResEnums.SUCCESS.getRespCode()); + } + + public SuccessAPIResponse toSuccessAPIResponse(){ + if(this instanceof SuccessAPIResponse){ + return (SuccessAPIResponse)this; + }else{ + return null; + } + + } + + public ExceptionAPIResponse toExceptionResponse(){ + if(this instanceof ExceptionAPIResponse){ + return (ExceptionAPIResponse)this; + }else{ + return null; + } + + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/api/ApiResEnums.java b/ruoyi-admin/src/main/java/cn/xluobo/core/api/ApiResEnums.java new file mode 100644 index 0000000..c2f2283 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/api/ApiResEnums.java @@ -0,0 +1,46 @@ +package cn.xluobo.core.api; + +public enum ApiResEnums { + SC_UNAUTHORIZED("0401","401"), + SC_FORCE_OFFLINE("0511","强制踢出,请重新登录"), + SC_INVALID_TOKEN("0513","登录信息失效,请重新登录"), + // token 失效后 刷新 + SC_INVALID_REFRESH_TOKEN("0512","token refresh success"), + SUCCESS("0000","success"), + FAILURE("9999","获取相关数据失败,请联系客服"), + BUSINESS_FAILURE("6666","业务异常"), + PARAM_FAIL("7777","请求参数错误,请重试"), + FAIL_WAIT_A_MINUTE("7777","操作失败,请稍后重试"), + INTF_FAIL("8888","调用接口失败,请联系管理员"), + + // 小程序 接口返回内容 + MINI_APP_UN_BIND_USER("M0001","暂未未绑定账号"), + MINI_APP_USER_HAD_BIND_BY_OTHER_USER("M0002","用户已被其他微信绑定"), + MINI_APP_WECHAT_HAD_BIND_USER("M0002","微信已绑定其他用户"), + ; + + + private String respCode; + private String respMsg; + + ApiResEnums(String respCode, String respMsg) { + this.respCode = respCode; + this.respMsg = respMsg; + } + + public String getRespCode() { + return respCode; + } + + public void setRespCode(String respCode) { + this.respCode = respCode; + } + + public String getRespMsg() { + return respMsg; + } + + public void setRespMsg(String respMsg) { + this.respMsg = respMsg; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/constants/SysConstant.java b/ruoyi-admin/src/main/java/cn/xluobo/core/constants/SysConstant.java new file mode 100644 index 0000000..79baa63 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/constants/SysConstant.java @@ -0,0 +1,44 @@ +package cn.xluobo.core.constants; + +import java.util.HashMap; +import java.util.Map; + +/** + * 常量 + * + * @author :zhangbaoyu + * @date :Created in 2020/9/24 14:44 + */ +public class SysConstant { + + /** + * 星期 与 中文 对应关系 + */ + public static final Map WEEK_DAY_MAP = new HashMap<>(); + + /** + * 上课时间 + * key:小时 + * value: 时间段 + */ + public static final Map CLA_TIME_MAP = new HashMap<>(); + + static { + WEEK_DAY_MAP.clear(); + WEEK_DAY_MAP.put(1, "星期一"); + WEEK_DAY_MAP.put(2, "星期二"); + WEEK_DAY_MAP.put(3, "星期三"); + WEEK_DAY_MAP.put(4, "星期四"); + WEEK_DAY_MAP.put(5, "星期五"); + WEEK_DAY_MAP.put(6, "星期六"); + WEEK_DAY_MAP.put(7, "星期日"); + + CLA_TIME_MAP.clear(); + CLA_TIME_MAP.put(8, "08:00 ~ 10:00"); + CLA_TIME_MAP.put(10, "10:00 ~ 12:00"); + CLA_TIME_MAP.put(12, "12:00 ~ 14:00"); + CLA_TIME_MAP.put(14, "14:00 ~ 16:00"); + CLA_TIME_MAP.put(16, "16:00 ~ 18:00"); + CLA_TIME_MAP.put(18, "18:00 ~ 20:00"); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/domain/select/GroupSelect.java b/ruoyi-admin/src/main/java/cn/xluobo/core/domain/select/GroupSelect.java new file mode 100644 index 0000000..27f4df7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/domain/select/GroupSelect.java @@ -0,0 +1,28 @@ +package cn.xluobo.core.domain.select; + +import lombok.Data; + +import java.util.List; + +/** + * @projectName: qyxt + * @package: cn.xluobo.core.domain.select + * @className: GroupSelect + * @author: xluobo + * @description: TODO + * @date: 2024/1/30 20:19 + */ +@Data +public class GroupSelect { + + private String groupName; + + private List itemList; + + @Data + public static class GroupItem { + private String itemId; + private String itemName; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/file/FileUtils.java b/ruoyi-admin/src/main/java/cn/xluobo/core/file/FileUtils.java new file mode 100644 index 0000000..462d3b7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/file/FileUtils.java @@ -0,0 +1,96 @@ +package cn.xluobo.core.file; + +import org.apache.commons.lang3.StringUtils; + +import java.io.*; +import java.net.URLEncoder; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-21 22:38 + */ +public class FileUtils { + + /** + * 创建文件 + * 如果目录不存在 依次创建目录 + * + * @param path 文件目录 + * @throws IOException + */ + public static void createFile(String path) throws IOException { + if (StringUtils.isNotEmpty(path)) { + File file = new File(path); + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + file.createNewFile(); + } + } + + public static File getFile(String full_name) throws Exception { + File file = new File(full_name); + if (!file.exists()) { + throw new Exception("文件 " + full_name + " 未找到!"); + } + return file; + } + + public static void writeInputToOutput(InputStream in, OutputStream out) throws Exception { + writeInputToOutput(in, out, false); + } + + public static void writeInputToOutput(InputStream in, OutputStream out, boolean ispersist) throws Exception { + int bufferSize = 1024; + byte[] buffer = new byte[bufferSize]; + int len = -1; + /* if no arrive the end(len is -1) in the data stream then write */ + while ((len = in.read(buffer)) != -1) { + out.write(buffer, 0, len); + out.flush(); + } + if (!ispersist) { + in.close(); + out.close(); + } + } + + /** + * delete file + * + * @param full_name + * @return boolean + * @throws Exception + */ + public static boolean deleteFile(String full_name) throws Exception { + File file = new File(full_name); + if (file.exists()) return file.delete(); + return false; + } + + /** + * 下载文件名 encode + * @param agent + * @param fileName + * @return + * @throws UnsupportedEncodingException + */ + public static String encodeDownloadFileName(String agent, String fileName) throws UnsupportedEncodingException { + String encodeFileName = ""; + if (agent.contains("MSIE")) { + // IE浏览器 + encodeFileName = URLEncoder.encode(fileName, "utf-8"); + encodeFileName = encodeFileName.replace("+", " "); + } else if (agent.contains("Firefox")) { + // 火狐浏览器 + encodeFileName = new String(fileName.getBytes(), "ISO8859-1"); + } else if (agent.contains("Chrome")) { + // google浏览器 + encodeFileName = URLEncoder.encode(fileName, "utf-8"); + } else { + // 其它浏览器 + encodeFileName = URLEncoder.encode(fileName, "utf-8"); + } + return encodeFileName; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/log/Log.java b/ruoyi-admin/src/main/java/cn/xluobo/core/log/Log.java new file mode 100644 index 0000000..2445b8c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/log/Log.java @@ -0,0 +1,38 @@ +package cn.xluobo.core.log; + +import cn.xluobo.core.log.enums.BusinessType; +import cn.xluobo.core.log.enums.ClientType; +import cn.xluobo.core.log.enums.OperateModule; + +import java.lang.annotation.*; + +/** + * 操作日志记录注解 + * @author zhangby + */ +@Target({ElementType.PARAMETER, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Log { + + /** + * 模块 + */ + OperateModule module() default OperateModule.SYS; + + /** + * 功能 + */ + BusinessType businessType() default BusinessType.OTHER; + + /** + * 操作人类别 + */ + ClientType clientType() default ClientType.PC; + + /** + * 是否保存请求的参数 + */ + boolean isSaveRequestData() default true; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/log/SysLogAspect.java b/ruoyi-admin/src/main/java/cn/xluobo/core/log/SysLogAspect.java new file mode 100644 index 0000000..5a3acb3 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/log/SysLogAspect.java @@ -0,0 +1,209 @@ +package cn.xluobo.core.log; + +import cn.xluobo.business.sys.log.repo.model.SysOperateLog; +import cn.xluobo.business.sys.log.service.ISysOperateLogService; +import cn.xluobo.core.utils.ServletUtils; +import cn.xluobo.core.utils.ip.IpUtils; +import com.alibaba.fastjson.JSON; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.HandlerMapping; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; + +/** + * @author :zhangbaoyu + * @date :Created in 2021/4/20 19:29 + */ +@Aspect +@Component +@Slf4j +public class SysLogAspect { + + @Autowired + private ISysOperateLogService operateLogService; + + // 配置织入点 + @Pointcut("@annotation(cn.xluobo.core.log.Log)") + public void logPointCut() { + } + + /** + * 处理完请求后执行 + * + * @param joinPoint 切点 + */ + @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult") + public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) { + handleLog(joinPoint, null, jsonResult); + } + + /** + * 拦截异常操作 + * + * @param joinPoint 切点 + * @param e 异常 + */ + @AfterThrowing(value = "logPointCut()", throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint, Exception e) { + handleLog(joinPoint, e, null); + } + + protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) { + try { + // 获得注解 + Log controllerLog = getAnnotationLog(joinPoint); + if (controllerLog == null) { + return; + } + + // 获取当前的用户 + LoginUser loginUser = SecurityUtils.getLoginUser(); + + // *========数据库日志=========*// + SysOperateLog operLog = new SysOperateLog(); + operLog.setError(0); + // 请求的地址 + String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); + operLog.setOperateIp(ip); + // 返回参数 + operLog.setRespResult(JSON.toJSONString(jsonResult)); + + operLog.setOperateUrl(ServletUtils.getRequest().getRequestURI()); + operLog.setUserId(loginUser.getUserId()); + operLog.setUserName(loginUser.getUsername()); + + if (e != null) { + operLog.setError(1); + operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); + } + // 设置方法名称 + String className = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName(); + operLog.setMethod(className + "." + methodName + "()"); + // 设置请求方式 + operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); + // 处理设置注解上的参数 + getControllerMethodDescription(joinPoint, controllerLog, operLog); + // 保存数据库 + operateLogService.asyncSaveLog(operLog); + } catch (Exception exp) { + // 记录本地异常日志 + log.error("==前置通知异常=="); + log.error("异常信息:{}", exp.getMessage()); + exp.printStackTrace(); + } + } + + /** + * 获取注解中对方法的描述信息 用于Controller层注解 + * + * @param log 日志 + * @param operLog 操作日志 + * @throws Exception + */ + public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperateLog operLog) throws Exception { + // 设置action动作 + operLog.setBusinessType(log.businessType().getValue()); + // 设置标题 + operLog.setOperateModule(log.module().getValue()); + // 设置操作人类别 + operLog.setClientType(log.clientType().getValue()); + // 是否需要保存request,参数和值 + if (log.isSaveRequestData()) { + // 获取参数的信息,传入到数据库中。 + setRequestValue(joinPoint, operLog); + } + } + + /** + * 获取请求的参数,放到log中 + * + * @param operLog 操作日志 + * @throws Exception 异常 + */ + private void setRequestValue(JoinPoint joinPoint, SysOperateLog operLog) throws Exception { + String requestMethod = operLog.getRequestMethod(); + if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) { + String params = argsArrayToString(joinPoint.getArgs()); + operLog.setReqParam(StringUtils.substring(params, 0, 2000)); + } else { + Map paramsMap = (Map) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); + operLog.setReqParam(StringUtils.substring(paramsMap.toString(), 0, 2000)); + } + } + + /** + * 是否存在注解,如果存在就获取 + */ + private Log getAnnotationLog(JoinPoint joinPoint) throws Exception { + Signature signature = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature) signature; + Method method = methodSignature.getMethod(); + + if (method != null) { + return method.getAnnotation(Log.class); + } + return null; + } + + /** + * 参数拼装 + */ + private String argsArrayToString(Object[] paramsArray) { + String params = ""; + if (paramsArray != null && paramsArray.length > 0) { + for (int i = 0; i < paramsArray.length; i++) { + if (!isFilterObject(paramsArray[i])) { + Object jsonObj = JSON.toJSON(paramsArray[i]); + params += jsonObj.toString() + " "; + } + } + } + return params.trim(); + } + + /** + * 判断是否需要过滤的对象。 + * + * @param o 对象信息。 + * @return 如果是需要过滤的对象,则返回true;否则返回false。 + */ + @SuppressWarnings("rawtypes") + public boolean isFilterObject(final Object o) { + Class clazz = o.getClass(); + if (clazz.isArray()) { + return clazz.getComponentType().isAssignableFrom(MultipartFile.class); + } else if (Collection.class.isAssignableFrom(clazz)) { + Collection collection = (Collection) o; + for (Iterator iter = collection.iterator(); iter.hasNext(); ) { + return iter.next() instanceof MultipartFile; + } + } else if (Map.class.isAssignableFrom(clazz)) { + Map map = (Map) o; + for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); ) { + Map.Entry entry = (Map.Entry) iter.next(); + return entry.getValue() instanceof MultipartFile; + } + } + return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/log/enums/BusinessType.java b/ruoyi-admin/src/main/java/cn/xluobo/core/log/enums/BusinessType.java new file mode 100644 index 0000000..fb0ec18 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/log/enums/BusinessType.java @@ -0,0 +1,30 @@ +package cn.xluobo.core.log.enums; + +/** + * 业务操作类型 + */ +public enum BusinessType { + + OTHER("其他", "other"), + INSERT("新增", "insert"), + UPDATE("修改","update"), + DELETE("删除","delete"), + ; + + private final String name; + + private final String value; + + BusinessType(String name, String value) { + this.name = name; + this.value = value; + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/log/enums/ClientType.java b/ruoyi-admin/src/main/java/cn/xluobo/core/log/enums/ClientType.java new file mode 100644 index 0000000..f33570c --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/log/enums/ClientType.java @@ -0,0 +1,28 @@ +package cn.xluobo.core.log.enums; + +/** + * 客户端 + */ +public enum ClientType { + + PC("PC", "pc"), + APP("APP","app"), + ; + + private final String name; + + private final String value; + + ClientType(String name, String value) { + this.name = name; + this.value = value; + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/log/enums/OperateModule.java b/ruoyi-admin/src/main/java/cn/xluobo/core/log/enums/OperateModule.java new file mode 100644 index 0000000..ea26742 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/log/enums/OperateModule.java @@ -0,0 +1,29 @@ +package cn.xluobo.core.log.enums; + +/** + * 操作模块 + */ +public enum OperateModule { + + OTHER("其他", "other"), + SYS("系统", "sys"), + USER("用户","user"), + ; + + private final String name; + + private final String value; + + OperateModule(String name, String value) { + this.name = name; + this.value = value; + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/page/ReqDeptCondition.java b/ruoyi-admin/src/main/java/cn/xluobo/core/page/ReqDeptCondition.java new file mode 100644 index 0000000..fd2fe71 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/page/ReqDeptCondition.java @@ -0,0 +1,17 @@ +package cn.xluobo.core.page; + +import lombok.Data; + +/** + * 校区查询条件 + * @author :zhangbaoyu + * @date :Created in 2020/10/24 09:25 + */ +@Data +public class ReqDeptCondition { + + private Long deptId; + + private String userId; + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/page/ReqPageBase.java b/ruoyi-admin/src/main/java/cn/xluobo/core/page/ReqPageBase.java new file mode 100644 index 0000000..9ffb5c7 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/page/ReqPageBase.java @@ -0,0 +1,18 @@ +package cn.xluobo.core.page; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 分页请求 + * @author :zhangbaoyu + * @date :Created in 2020-01-15 21:41 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ReqPageBase extends ReqDeptCondition{ + + private long pageNum = 1; + + private long pageSize = 10; +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/page/RespPage.java b/ruoyi-admin/src/main/java/cn/xluobo/core/page/RespPage.java new file mode 100644 index 0000000..f3aa524 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/page/RespPage.java @@ -0,0 +1,50 @@ +package cn.xluobo.core.page; + +import cn.xluobo.core.serializer.json.LongJsonSerializer; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.util.Collections; +import java.util.List; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-15 21:52 + */ +public class RespPage extends Page { + + private List rows = Collections.emptyList(); + + @JsonSerialize(using = LongJsonSerializer.class) + private long total; + + + public RespPage(long current, long size) { + super(current, size); + } + + @Override + public Page setRecords(List records) { + this.rows=records; + return this; + } + + @Override + public Page setTotal(long total) { + this.total=total; + return this; + } + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + @Override + public long getTotal() { + return total; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/serializer/json/LongJsonSerializer.java b/ruoyi-admin/src/main/java/cn/xluobo/core/serializer/json/LongJsonSerializer.java new file mode 100644 index 0000000..d67bbd6 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/serializer/json/LongJsonSerializer.java @@ -0,0 +1,20 @@ +package cn.xluobo.core.serializer.json; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/8/18 19:45 + */ +public class LongJsonSerializer extends JsonSerializer { + @Override + public void serialize(Long aLong, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + if (aLong != null) { + jsonGenerator.writeNumber(aLong); + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/utils/DateUtil.java b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/DateUtil.java new file mode 100644 index 0000000..1b1153b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/DateUtil.java @@ -0,0 +1,67 @@ +package cn.xluobo.core.utils; + +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; + +import java.text.SimpleDateFormat; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-01-18 17:22 + */ +public class DateUtil { + + private static final DateTimeFormatter yyyy_MM_dd = DateTimeFormat.forPattern("yyyy-MM-dd"); + private static final DateTimeFormatter yyyyMM = DateTimeFormat.forPattern("yyyyMM"); + + public interface DATE_PATTERN { + String HHMMSS = "HHmmss"; + String HH_MM_SS = "HH:mm:ss"; + String YYYYMMDD = "yyyyMMdd"; + String YYYYMMDDHH_MM = "yyyyMMddHH:mm"; + String YYYY_MM_DD = "yyyy-MM-dd"; + String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; + String YYYYMMDDHHMMSSSSS = "yyyyMMddHHmmssSSS"; + String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm"; + String YYYYMMDDHHMM = "yyyyMMddHHmm"; + String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; + } + + public static DateTime yyyMMddDayBegin(String dateStr){ + if(StringUtils.isEmpty(dateStr)){ + return null; + }else{ + return DateTime.parse(dateStr,yyyy_MM_dd) + .withHourOfDay(0) + .withMinuteOfHour(0) + .withSecondOfMinute(0) + .withMillisOfSecond(0); + } + } + + public static DateTime yyyMMddDayEnd(String dateStr){ + if(StringUtils.isEmpty(dateStr)){ + return null; + }else{ + return DateTime.parse(dateStr,yyyy_MM_dd) + .withHourOfDay(23) + .withMinuteOfHour(59) + .withSecondOfMinute(59) + .withMillisOfSecond(59); + } + } + + public static DateTime yyyMMDay(String dateStr){ + if(StringUtils.isEmpty(dateStr)){ + return null; + }else{ + return DateTime.parse(dateStr,yyyyMM); + } + } + + public static String format(Object date,String pattern) { + return new SimpleDateFormat(pattern).format(date); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/utils/MimeTypeUtils.java b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/MimeTypeUtils.java new file mode 100644 index 0000000..030acd2 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/MimeTypeUtils.java @@ -0,0 +1,55 @@ +package cn.xluobo.core.utils; + +/** + * 媒体类型工具类 + * + * @author ruoyi + */ +public class MimeTypeUtils +{ + public static final String IMAGE_PNG = "image/png"; + + public static final String IMAGE_JPG = "image/jpg"; + + public static final String IMAGE_JPEG = "image/jpeg"; + + public static final String IMAGE_BMP = "image/bmp"; + + public static final String IMAGE_GIF = "image/gif"; + + public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" }; + + public static final String[] FLASH_EXTENSION = { "swf", "flv" }; + + public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg", + "asf", "rm", "rmvb" }; + + public static final String[] DEFAULT_ALLOWED_EXTENSION = { + // 图片 + "bmp", "gif", "jpg", "jpeg", "png", + // word excel powerpoint + "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt", + // 压缩文件 + "rar", "zip", "gz", "bz2", + // pdf + "pdf" }; + + public static String getExtension(String prefix) + { + switch (prefix) + { + case IMAGE_PNG: + return "png"; + case IMAGE_JPG: + return "jpg"; + case IMAGE_JPEG: + return "jpeg"; + case IMAGE_BMP: + return "bmp"; + case IMAGE_GIF: + return "gif"; + default: + return ""; + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/utils/ServletUtils.java b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/ServletUtils.java new file mode 100644 index 0000000..f7de484 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/ServletUtils.java @@ -0,0 +1,59 @@ +package cn.xluobo.core.utils; + +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +/** + * 客户端工具类 + */ +public class ServletUtils { + + /** + * 获取request + */ + public static HttpServletRequest getRequest() { + return getRequestAttributes().getRequest(); + } + + /** + * 获取response + */ + public static HttpServletResponse getResponse() { + return getRequestAttributes().getResponse(); + } + + /** + * 获取session + */ + public static HttpSession getSession() { + return getRequest().getSession(); + } + + private static ServletRequestAttributes getRequestAttributes() { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + return (ServletRequestAttributes) attributes; + } + + /** + * 是否是Ajax异步请求 + * + * @param request + */ + public static boolean isAjaxRequest(HttpServletRequest request) { + String accept = request.getHeader("accept"); + if (accept != null && accept.contains("application/json")) { + return true; + } + + String xRequestedWith = request.getHeader("X-Requested-With"); + if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) { + return true; + } + return false; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/utils/aes/EncryptUtil.java b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/aes/EncryptUtil.java new file mode 100644 index 0000000..604d025 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/aes/EncryptUtil.java @@ -0,0 +1,320 @@ +package cn.xluobo.core.utils.aes; + + +import sun.misc.BASE64Decoder; +import sun.misc.BASE64Encoder; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.SecretKeySpec; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +/** + * @author :zhangbaoyu + * @date :Created in 2020-04-30 10:56 + */ +public class EncryptUtil { + + /** + * 加密算法 + */ + private static final String ENCRY_ALGORITHM = "AES"; + + /** + * 加密算法/加密模式/填充类型 + * 本例采用AES加密,ECB加密模式,PKCS5Padding填充 + */ + private static final String CIPHER_MODE = "AES/ECB/PKCS5Padding"; + + /** + * 设置iv偏移量 + * 本例采用ECB加密模式,不需要设置iv偏移量 + */ + private static final String IV_ = null; + + /** + * 设置加密字符集 + * 本例采用 UTF-8 字符集 + */ + private static final String CHARACTER = "UTF-8"; + + /** + * 设置加密密码处理长度。 + * 不足此长度补0; + */ + private static final int PWD_SIZE = 16; + + /** + * 密码处理方法 + * 如果加解密出问题, + * 请先查看本方法,排除密码长度不足填充0字节,导致密码不一致 + * + * @param password 待处理的密码 + * @return + * @throws UnsupportedEncodingException + */ + private static byte[] pwdHandler(String password) throws UnsupportedEncodingException { + byte[] data = null; + if (password != null) { + byte[] bytes = password.getBytes(CHARACTER); + if (password.length() < PWD_SIZE) { + System.arraycopy(bytes, 0, data = new byte[PWD_SIZE], 0, bytes.length); + } else { + data = bytes; + } + } + return data; + } + + //======================>原始加密<====================== + + /** + * 原始加密 + * + * @param clearTextBytes 明文字节数组,待加密的字节数组 + * @param pwdBytes 加密密码字节数组 + * @return 返回加密后的密文字节数组,加密错误返回null + */ + public static byte[] encrypt(byte[] clearTextBytes, byte[] pwdBytes) { + try { + // 1 获取加密密钥 + SecretKeySpec keySpec = new SecretKeySpec(pwdBytes, ENCRY_ALGORITHM); + + // 2 获取Cipher实例 + Cipher cipher = Cipher.getInstance(CIPHER_MODE); + + // 查看数据块位数 默认为16(byte) * 8 =128 bit +// System.out.println("数据块位数(byte):" + cipher.getBlockSize()); + + // 3 初始化Cipher实例。设置执行模式以及加密密钥 + cipher.init(Cipher.ENCRYPT_MODE, keySpec); + + // 4 执行 + byte[] cipherTextBytes = cipher.doFinal(clearTextBytes); + + // 5 返回密文字符集 + return cipherTextBytes; + + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 原始解密 + * + * @param cipherTextBytes 密文字节数组,待解密的字节数组 + * @param pwdBytes 解密密码字节数组 + * @return 返回解密后的明文字节数组,解密错误返回null + */ + public static byte[] decrypt(byte[] cipherTextBytes, byte[] pwdBytes) { + + try { + // 1 获取解密密钥 + SecretKeySpec keySpec = new SecretKeySpec(pwdBytes, ENCRY_ALGORITHM); + + // 2 获取Cipher实例 + Cipher cipher = Cipher.getInstance(CIPHER_MODE); + + // 查看数据块位数 默认为16(byte) * 8 =128 bit +// System.out.println("数据块位数(byte):" + cipher.getBlockSize()); + + // 3 初始化Cipher实例。设置执行模式以及加密密钥 + cipher.init(Cipher.DECRYPT_MODE, keySpec); + + // 4 执行 + byte[] clearTextBytes = cipher.doFinal(cipherTextBytes); + + // 5 返回明文字符集 + return clearTextBytes; + + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + // 解密错误 返回null + return null; + } + + //======================>BASE64<====================== + + /** + * BASE64加密 + * + * @param clearText 明文,待加密的内容 + * @param password 密码,加密的密码 + * @return 返回密文,加密后得到的内容。加密错误返回null + */ + public static String encryptBase64(String clearText, String password) { + try { + // 1 获取加密密文字节数组 + byte[] cipherTextBytes = encrypt(clearText.getBytes(CHARACTER), pwdHandler(password)); + + // 2 对密文字节数组进行BASE64 encoder 得到 BASE6输出的密文 + BASE64Encoder base64Encoder = new BASE64Encoder(); + String cipherText = base64Encoder.encode(cipherTextBytes); + + // 3 返回BASE64输出的密文 + return cipherText; + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + // 加密错误 返回null + return null; + } + + /** + * BASE64解密 + * + * @param cipherText 密文,带解密的内容 + * @param password 密码,解密的密码 + * @return 返回明文,解密后得到的内容。解密错误返回null + */ + public static String decryptBase64(String cipherText, String password) { + try { + // 1 对 BASE64输出的密文进行BASE64 decodebuffer 得到密文字节数组 + BASE64Decoder base64Decoder = new BASE64Decoder(); + byte[] cipherTextBytes = base64Decoder.decodeBuffer(cipherText); + + // 2 对密文字节数组进行解密 得到明文字节数组 + byte[] clearTextBytes = decrypt(cipherTextBytes, pwdHandler(password)); + + // 3 根据 CHARACTER 转码,返回明文字符串 + return new String(clearTextBytes, CHARACTER); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + // 解密错误返回null + return null; + } + + //======================>HEX<====================== + + /** + * HEX加密 + * + * @param clearText 明文,待加密的内容 + * @param password 密码,加密的密码 + * @return 返回密文,加密后得到的内容。加密错误返回null + */ + public static String encryptHex(String clearText, String password) { + try { + // 1 获取加密密文字节数组 + byte[] cipherTextBytes = encrypt(clearText.getBytes(CHARACTER), pwdHandler(password)); + + // 2 对密文字节数组进行 转换为 HEX输出密文 + String cipherText = byte2hex(cipherTextBytes); + + // 3 返回 HEX输出密文 + return cipherText; + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + // 加密错误返回null + return null; + } + + /** + * HEX解密 + * + * @param cipherText 密文,带解密的内容 + * @param password 密码,解密的密码 + * @return 返回明文,解密后得到的内容。解密错误返回null + */ + public static String decryptHex(String cipherText, String password) { + try { + // 1 将HEX输出密文 转为密文字节数组 + byte[] cipherTextBytes = hex2byte(cipherText); + + // 2 将密文字节数组进行解密 得到明文字节数组 + byte[] clearTextBytes = decrypt(cipherTextBytes, pwdHandler(password)); + + // 3 根据 CHARACTER 转码,返回明文字符串 + return new String(clearTextBytes, CHARACTER); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + // 解密错误返回null + return null; + } + + /*字节数组转成16进制字符串 */ + public static String byte2hex(byte[] bytes) { // 一个字节的数, + StringBuffer sb = new StringBuffer(bytes.length * 2); + String tmp = ""; + for (int n = 0; n < bytes.length; n++) { + // 整数转成十六进制表示 + tmp = (Integer.toHexString(bytes[n] & 0XFF)); + if (tmp.length() == 1) { + sb.append("0"); + } + sb.append(tmp); + } + return sb.toString().toUpperCase(); // 转成大写 + } + + /*将hex字符串转换成字节数组 */ + private static byte[] hex2byte(String str) { + if (str == null || str.length() < 2) { + return new byte[0]; + } + str = str.toLowerCase(); + int l = str.length() / 2; + byte[] result = new byte[l]; + for (int i = 0; i < l; ++i) { + String tmp = str.substring(2 * i, 2 * i + 2); + result[i] = (byte) (Integer.parseInt(tmp, 16) & 0xFF); + } + return result; + } + + // 测试类 + public static void main(String[] args) throws UnsupportedEncodingException { + // 密钥 16位 + String key = "0123456789ABCDEF"; + // 明文 + String word = "123456"; + String encodeWordHex = encryptHex(word, key); + String encodeWordBase64 = encryptBase64(word, key); + + // 输出内容 加密后 hex返回结果:BAE996B948645DA06922BE240FF3FEA1 + System.out.println("加密后 hex返回结果:" + encodeWordHex); + // 输出内容 加密后 base64返回结果:uumWuUhkXaBpIr4kD/P+oQ== + System.out.println("加密后 base64返回结果:" + encodeWordBase64); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/utils/bean/ExtendBeanUtils.java b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/bean/ExtendBeanUtils.java new file mode 100644 index 0000000..156fd2b --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/bean/ExtendBeanUtils.java @@ -0,0 +1,38 @@ +package cn.xluobo.core.utils.bean; + +import org.springframework.beans.BeanUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/7/30 11:25 + */ +public class ExtendBeanUtils extends BeanUtils { + + public static List copyListProperties(List sources, Supplier target) { + return copyListProperties(sources, target, null); + } + + /** + * 使用场景:Entity、Bo、Vo层数据的复制,因为BeanUtils.copyProperties只能给目标对象的属性赋值,却不能在List集合下循环赋值,因此添加该方法 + * 如:List 赋值到 List ,List中的 AdminVo 属性都会被赋予到值 + * S: 数据源类 ,T: 目标类::new(eg: AdminVo::new) + */ + public static List copyListProperties(List sources, Supplier target, ExtendBeanUtilsCallBack callBack) { + List list = new ArrayList<>(sources.size()); + for (S source : sources) { + T t = target.get(); + copyProperties(source, t); + list.add(t); + if (callBack != null) { + // 回调 + callBack.callBack(source, t); + } + } + return list; + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/utils/bean/ExtendBeanUtilsCallBack.java b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/bean/ExtendBeanUtilsCallBack.java new file mode 100644 index 0000000..2546c3e --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/bean/ExtendBeanUtilsCallBack.java @@ -0,0 +1,10 @@ +package cn.xluobo.core.utils.bean; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/7/30 11:26 + */ +@FunctionalInterface +public interface ExtendBeanUtilsCallBack { + void callBack(S t, T s); +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/utils/http/HttpClientConfig.java b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/http/HttpClientConfig.java new file mode 100644 index 0000000..bef7670 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/http/HttpClientConfig.java @@ -0,0 +1,94 @@ +package cn.xluobo.core.utils.http; + +import org.apache.http.HeaderElement; +import org.apache.http.HeaderElementIterator; +import org.apache.http.HttpResponse; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.conn.ConnectionKeepAliveStrategy; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.IdleConnectionEvictor; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.message.BasicHeaderElementIterator; +import org.apache.http.protocol.HTTP; +import org.apache.http.protocol.HttpContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.TimeUnit; + +@Configuration +public class HttpClientConfig { + private int maxTotal = 800; + + private int defaultMaxPerRoute = 80; + + private int validateAfterInactivity = 1000; + + /** + * connectionRequestTimout:指从连接池获取连接的timeout + */ + private int connectionRequestTimeout = 5000; + + /** + * connetionTimeout:指客户端和服务器建立连接的timeout + */ + private int connectTimeout = 30000; + + /** + * 指客户端从服务器读取数据的timeout + */ + private int socketTimeout = 60000; + + private int maxIdleTime = 30000; + + private int retryCount = 3; + + @Bean + public PoolingHttpClientConnectionManager createPoolingHttpClientConnectionManager() { + PoolingHttpClientConnectionManager poolmanager = new PoolingHttpClientConnectionManager(); + poolmanager.setMaxTotal(maxTotal); + poolmanager.setDefaultMaxPerRoute(defaultMaxPerRoute); + poolmanager.setValidateAfterInactivity(validateAfterInactivity); + return poolmanager; + } + + @Bean + public CloseableHttpClient createHttpClient(PoolingHttpClientConnectionManager poolManager) { + HttpClientBuilder httpClientBuilder = HttpClientBuilder.create().setConnectionManager(poolManager); + httpClientBuilder.setKeepAliveStrategy(new ConnectionKeepAliveStrategy() { + + @Override + public long getKeepAliveDuration(HttpResponse response, HttpContext context) { + HeaderElementIterator iterator = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE)); + while (iterator.hasNext()) { + HeaderElement headerElement = iterator.nextElement(); + String param = headerElement.getName(); + String value = headerElement.getValue(); + if (null != value && param.equalsIgnoreCase("timeout")) { + return Long.parseLong(value) * 1000; + } + } + return 30 * 1000; + } + }); + httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(retryCount, false)); + return httpClientBuilder.build(); + } + + @Bean + public RequestConfig createRequestConfig() { + return RequestConfig.custom() + .setConnectionRequestTimeout(connectionRequestTimeout) + .setConnectTimeout(connectTimeout) + .setSocketTimeout(socketTimeout) + .build(); + } + + @Bean + public IdleConnectionEvictor createIdleConnectionEvictor(PoolingHttpClientConnectionManager poolManager) { + IdleConnectionEvictor idleConnectionEvictor = new IdleConnectionEvictor(poolManager, maxIdleTime, TimeUnit.MILLISECONDS); + return idleConnectionEvictor; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/utils/http/HttpHelper.java b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/http/HttpHelper.java new file mode 100644 index 0000000..40114df --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/http/HttpHelper.java @@ -0,0 +1,56 @@ +package cn.xluobo.core.utils.http; + +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletRequest; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.Charset; + +/** + * 通用http工具封装 + * + * + */ +public class HttpHelper +{ + private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class); + + public static String getBodyString(ServletRequest request) + { + StringBuilder sb = new StringBuilder(); + BufferedReader reader = null; + try (InputStream inputStream = request.getInputStream()) + { + reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); + String line = ""; + while ((line = reader.readLine()) != null) + { + sb.append(line); + } + } + catch (IOException e) + { + LOGGER.warn("getBodyString出现问题!"); + } + finally + { + if (reader != null) + { + try + { + reader.close(); + } + catch (IOException e) + { + LOGGER.error(ExceptionUtils.getMessage(e)); + } + } + } + return sb.toString(); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/utils/http/HttpUtils.java b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/http/HttpUtils.java new file mode 100644 index 0000000..628b931 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/http/HttpUtils.java @@ -0,0 +1,282 @@ +package cn.xluobo.core.utils.http; + +import com.alibaba.fastjson.JSON; +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.net.ssl.*; +import java.io.*; +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.Charset; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 通用http发送方法 + */ +@Component +public class HttpUtils { + private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); + + @Autowired + private CloseableHttpClient httpClient; + + @Autowired + private RequestConfig requestConfig; + + /** + * post application/x-www-form-urlencoded + * + * @param url + * @param reqParams + * @return + */ + public Map doPost(String url, Map reqParams) { + HttpPost request = new HttpPost(url); + List params = new ArrayList<>(); + for (Map.Entry item : reqParams.entrySet()) { + params.add(new BasicNameValuePair(item.getKey(), item.getValue().toString())); + } + HttpEntity httpEntity = null; + httpEntity = new UrlEncodedFormEntity(params, Charset.forName("UTF-8")); + log.info("url = " + url); + log.info("req = " + JSON.toJSONString(reqParams)); + return requestPost(request, httpEntity); + } + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param) { + return sendGet(url, param, "UTF-8"); + } + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @param contentType 编码类型 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param, String contentType) { + StringBuilder result = new StringBuilder(); + BufferedReader in = null; + try { + String urlNameString = url + "?" + param; + log.info("sendGet - {}", urlNameString); + URL realUrl = new URL(urlNameString); + URLConnection connection = realUrl.openConnection(); + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + connection.connect(); + in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); + String line; + while ((line = in.readLine()) != null) { + result.append(line); + } + log.info("recv - {}", result); + } catch (ConnectException e) { + log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); + } catch (SocketTimeoutException e) { + log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); + } catch (IOException e) { + log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); + } catch (Exception e) { + log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (Exception ex) { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + /** + * 向指定 URL 发送POST方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendPost(String url, String param) { + PrintWriter out = null; + BufferedReader in = null; + StringBuilder result = new StringBuilder(); + try { + String urlNameString = url; + log.info("sendPost - {}", urlNameString); + URL realUrl = new URL(urlNameString); + URLConnection conn = realUrl.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + out = new PrintWriter(conn.getOutputStream()); + out.print(param); + out.flush(); + in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8")); + String line; + while ((line = in.readLine()) != null) { + result.append(line); + } + log.info("recv - {}", result); + } catch (ConnectException e) { + log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e); + } catch (SocketTimeoutException e) { + log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } catch (IOException e) { + log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e); + } catch (Exception e) { + log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); + } finally { + try { + if (out != null) { + out.close(); + } + if (in != null) { + in.close(); + } + } catch (IOException ex) { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + public static String sendSSLPost(String url, String param) { + StringBuilder result = new StringBuilder(); + String urlNameString = url + "?" + param; + try { + log.info("sendSSLPost - {}", urlNameString); + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom()); + URL console = new URL(urlNameString); + HttpsURLConnection conn = (HttpsURLConnection) console.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + + conn.setSSLSocketFactory(sc.getSocketFactory()); + conn.setHostnameVerifier(new TrustAnyHostnameVerifier()); + conn.connect(); + InputStream is = conn.getInputStream(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String ret = ""; + while ((ret = br.readLine()) != null) { + if (ret != null && !"".equals(ret.trim())) { + result.append(new String(ret.getBytes("ISO-8859-1"), "utf-8")); + } + } + log.info("recv - {}", result); + conn.disconnect(); + br.close(); + } catch (ConnectException e) { + log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e); + } catch (SocketTimeoutException e) { + log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } catch (IOException e) { + log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e); + } catch (Exception e) { + log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e); + } + return result.toString(); + } + + private static class TrustAnyTrustManager implements X509TrustManager { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[]{}; + } + } + + private static class TrustAnyHostnameVerifier implements HostnameVerifier { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + } + + private Map requestPost(HttpEntityEnclosingRequestBase request, HttpEntity httpEntity) { + request.setConfig(requestConfig); + CloseableHttpResponse response = null; + try { + request.setEntity(httpEntity); + System.out.println("request=" + request); + response = httpClient.execute(request); + HttpEntity entity = response.getEntity(); + String resultJson = EntityUtils.toString(entity, Charset.forName("UTF-8")); + log.info("response = " + resultJson); + Map resultMap = JSON.parseObject(resultJson, Map.class); + resultMap.put("respMsg", "success"); + resultMap.put("respCode", "0000"); + return resultMap; + } catch (Exception e) { + log.error("requestPost error url=" + request.getURI(), e); + Map errorMap = new HashMap<>(); + if (e instanceof SocketTimeoutException) { + errorMap.put("respCode", "9999"); + errorMap.put("respMsg", "调用接口超时"); + } else { + String errorMsg = e.getMessage(); + if (null != errorMsg && errorMsg.length() > 3000) { + errorMsg = errorMsg.substring(0, 3000); + } + errorMap.put("respCode", "9999"); + errorMap.put("respMsg", "调用接口失败" + errorMsg); + } + request.abort(); + return errorMap; + } finally { + try { + if (response != null) { + response.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/utils/ip/AddressUtils.java b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/ip/AddressUtils.java new file mode 100644 index 0000000..0a5c2fd --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/ip/AddressUtils.java @@ -0,0 +1,47 @@ +package cn.xluobo.core.utils.ip; + +import cn.xluobo.config.properties.AddressProperties; +import cn.xluobo.core.utils.http.HttpUtils; +import com.alibaba.fastjson.JSONObject; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 获取地址类 + * + * @author ruoyi + */ +public class AddressUtils { + private static final Logger log = LoggerFactory.getLogger(AddressUtils.class); + + // IP地址查询 + public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp"; + + // 未知地址 + public static final String UNKNOWN = "XX XX"; + + public static String getRealAddressByIP(String ip) { + String address = UNKNOWN; + // 内网不查询 + if (IpUtils.internalIp(ip)) { + return "内网IP"; + } + if (AddressProperties.isDecodeIp()) { + try { + String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", "GBK"); + if (StringUtils.isEmpty(rspStr)) { + log.error("获取地理位置异常 {}", ip); + return UNKNOWN; + } + JSONObject obj = JSONObject.parseObject(rspStr); + String region = obj.getString("pro"); + String city = obj.getString("city"); + return String.format("%s %s", region, city); + } catch (Exception e) { + log.error("获取地理位置异常 {}", ip); + } + } + return address; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/utils/ip/IpUtils.java b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/ip/IpUtils.java new file mode 100644 index 0000000..f909d79 --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/ip/IpUtils.java @@ -0,0 +1,164 @@ +package cn.xluobo.core.utils.ip; + +import javax.servlet.http.HttpServletRequest; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * 获取IP方法 + * + * @author ruoyi + */ +public class IpUtils { + public static String getIpAddr(HttpServletRequest request) { + if (request == null) { + return "unknown"; + } + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("X-Forwarded-For"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("X-Real-IP"); + } + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + + return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip; + } + + public static boolean internalIp(String ip) { + byte[] addr = textToNumericFormatV4(ip); + return internalIp(addr) || "127.0.0.1".equals(ip); + } + + private static boolean internalIp(byte[] addr) { + if (null == addr || addr.length < 2) { + return true; + } + final byte b0 = addr[0]; + final byte b1 = addr[1]; + // 10.x.x.x/8 + final byte SECTION_1 = 0x0A; + // 172.16.x.x/12 + final byte SECTION_2 = (byte) 0xAC; + final byte SECTION_3 = (byte) 0x10; + final byte SECTION_4 = (byte) 0x1F; + // 192.168.x.x/16 + final byte SECTION_5 = (byte) 0xC0; + final byte SECTION_6 = (byte) 0xA8; + switch (b0) { + case SECTION_1: + return true; + case SECTION_2: + if (b1 >= SECTION_3 && b1 <= SECTION_4) { + return true; + } + case SECTION_5: + switch (b1) { + case SECTION_6: + return true; + } + default: + return false; + } + } + + /** + * 将IPv4地址转换成字节 + * + * @param text IPv4地址 + * @return byte 字节 + */ + public static byte[] textToNumericFormatV4(String text) { + if (text.length() == 0) { + return null; + } + + byte[] bytes = new byte[4]; + String[] elements = text.split("\\.", -1); + try { + long l; + int i; + switch (elements.length) { + case 1: + l = Long.parseLong(elements[0]); + if ((l < 0L) || (l > 4294967295L)) { + return null; + } + bytes[0] = (byte) (int) (l >> 24 & 0xFF); + bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 2: + l = Integer.parseInt(elements[0]); + if ((l < 0L) || (l > 255L)) { + return null; + } + bytes[0] = (byte) (int) (l & 0xFF); + l = Integer.parseInt(elements[1]); + if ((l < 0L) || (l > 16777215L)) { + return null; + } + bytes[1] = (byte) (int) (l >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 3: + for (i = 0; i < 2; ++i) { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)) { + return null; + } + bytes[i] = (byte) (int) (l & 0xFF); + } + l = Integer.parseInt(elements[2]); + if ((l < 0L) || (l > 65535L)) { + return null; + } + bytes[2] = (byte) (int) (l >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 4: + for (i = 0; i < 4; ++i) { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)) { + return null; + } + bytes[i] = (byte) (int) (l & 0xFF); + } + break; + default: + return null; + } + } catch (NumberFormatException e) { + return null; + } + return bytes; + } + + public static String getHostIp() { + try { + return InetAddress.getLocalHost().getHostAddress(); + } catch (UnknownHostException e) { + } + return "127.0.0.1"; + } + + public static String getHostName() { + try { + return InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + } + return "未知"; + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/core/utils/pinyin/PinYinUtil.java b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/pinyin/PinYinUtil.java new file mode 100644 index 0000000..8aa1caf --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/core/utils/pinyin/PinYinUtil.java @@ -0,0 +1,94 @@ +package cn.xluobo.core.utils.pinyin; + +import net.sourceforge.pinyin4j.PinyinHelper; +import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; +import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; +import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; +import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType; +import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; +import org.apache.commons.lang3.StringUtils; + +public class PinYinUtil { + + /** + * 将汉字转换为全拼 + * + * @param src + * @return + */ + public static String getPinYin(String src) { + src = StringUtils.trim(src); + char[] hz = null; + hz = src.toCharArray();//该方法的作用是返回一个字符数组,该字符数组中存放了当前字符串中的所有字符 + String[] py = new String[hz.length];//该数组用来存储 + //设置汉子拼音输出的格式 + HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat(); + format.setCaseType(HanyuPinyinCaseType.LOWERCASE); + format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); + format.setVCharType(HanyuPinyinVCharType.WITH_V); + + String pys = ""; //存放拼音字符串 + int len = hz.length; + + try { + for (int i = 0; i < len; i++) { + //先判断是否为汉字字符 + if (Character.toString(hz[i]).matches("[\\u4E00-\\u9FA5]+")) { + //将汉字的几种全拼都存到py数组中 + py = PinyinHelper.toHanyuPinyinStringArray(hz[i], format); + //取出改汉字全拼的第一种读音,并存放到字符串pys后 + pys += py[0]; + } else { + //如果不是汉字字符,间接取出字符并连接到 pys 后 + pys += Character.toString(hz[i]); + } + } + } catch (BadHanyuPinyinOutputFormatCombination e) { + e.printStackTrace(); + } + return pys; + } + + /** + * 提取每个汉字的首字母 + * + * @param str + * @return + */ + public static String getPinYinHeadChar(String str) { + String convert = ""; + for (int i = 0; i < str.length(); i++) { + char word = str.charAt(i); + //提取汉字的首字母 + String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word); + if (pinyinArray != null) { + convert += pinyinArray[0].charAt(0); + } else { + convert += word; + } + } + return convert.toUpperCase(); + } + + /** + * 将字符串转换成ASCII码 + */ + public static String getCnASCII(String str) { + StringBuffer buf = new StringBuffer(); + //将字符串转换成字节序列 + byte[] bGBK = str.getBytes(); + for (int i = 0; i < bGBK.length; i++) { + //将每个字符转换成ASCII码 + buf.append(Integer.toHexString(bGBK[i] & 0xff)); + } + return buf.toString(); + } + + /** + * 测试 + */ + public static void main(String[] args) { + String str = "中国梦ChainDream2018"; + System.out.println(getPinYin(str)); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/scheduled/HolidayScheduled.java b/ruoyi-admin/src/main/java/cn/xluobo/scheduled/HolidayScheduled.java new file mode 100644 index 0000000..179f6fa --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/scheduled/HolidayScheduled.java @@ -0,0 +1,34 @@ +package cn.xluobo.scheduled; + +import cn.xluobo.business.sys.holiday.service.ISysHolidayService; +import lombok.extern.slf4j.Slf4j; +import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author :zhangbaoyu + * @date :Created in 2020/9/16 11:19 + */ +@Slf4j +@Component +public class HolidayScheduled { + + @Autowired + private ISysHolidayService holidayService; + + /** + * 12月20日 早6点 + */ + @Scheduled(cron = "0 0 6 20 12 ?") + @Transactional + public void autoInsertSysHoliday() throws Exception { + log.info("autoInsertSysHoliday begin"); + String year = DateTime.now().plusYears(1).toString("yyyy"); + holidayService.autoInsertHoliday(year); + log.info("autoInsertSysHoliday end"); + } + +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/utils/ContextUtils.java b/ruoyi-admin/src/main/java/cn/xluobo/utils/ContextUtils.java new file mode 100644 index 0000000..3964c5f --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/utils/ContextUtils.java @@ -0,0 +1,80 @@ +package cn.xluobo.utils; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.Validate; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * 以静态变量保存Spring ApplicationContext, + */ +@Component +@Slf4j +public class ContextUtils implements ApplicationContextAware, DisposableBean { + + private static ApplicationContext applicationContext = null; + + + /** + * 取得存储在静态变量中的ApplicationContext. + */ + public static ApplicationContext getApplicationContext() { + assertContextInjected(); + return applicationContext; + } + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) { + assertContextInjected(); + return (T) applicationContext.getBean(name); + } + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + public static T getBean(Class requiredType) { + assertContextInjected(); + return applicationContext.getBean(requiredType); + } + + /** + * 清除ContextUtils中的ApplicationContext为Null. + */ + public static void clearHolder() { + log.debug("清除ContextUtils中的ApplicationContext:" + + applicationContext); + applicationContext = null; + } + + /** + * 实现ApplicationContextAware接口, 注入Context到静态变量中. + */ + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + if (ContextUtils.applicationContext != null) { + log.warn("ContextUtils中的ApplicationContext被覆盖, 原有ApplicationContext为:" + ContextUtils.applicationContext); + } + + ContextUtils.applicationContext = applicationContext; // NOSONAR + } + + /** + * 实现DisposableBean接口, 在Context关闭时清理静态变量. + */ + @Override + public void destroy() throws Exception { + ContextUtils.clearHolder(); + } + + /** + * 检查ApplicationContext不为空. + */ + private static void assertContextInjected() { + Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义ContextUtils"); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/utils/JsonUtils.java b/ruoyi-admin/src/main/java/cn/xluobo/utils/JsonUtils.java new file mode 100644 index 0000000..a84dc3d --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/utils/JsonUtils.java @@ -0,0 +1,28 @@ +package cn.xluobo.utils; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + +/** + * @author Binary Wang + */ +public class JsonUtils { + private static final ObjectMapper JSON = new ObjectMapper(); + + static { + JSON.setSerializationInclusion(Include.NON_NULL); + JSON.configure(SerializationFeature.INDENT_OUTPUT, Boolean.TRUE); + } + + public static String toJson(Object obj) { + try { + return JSON.writeValueAsString(obj); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + + return null; + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java index 561404e..c0f3bd3 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java @@ -12,7 +12,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; */ @SpringBootApplication( exclude = {DataSourceAutoConfiguration.class}, - scanBasePackages = {"com.ruoyi"} + scanBasePackages = {"com.ruoyi","cn.xluobo"} ) @EnableScheduling public class RuoYiApplication { diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java index db4d2a5..d8d29b0 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java @@ -2,6 +2,9 @@ package com.ruoyi.common.core.domain.model; import java.util.Collection; import java.util.Set; + +import lombok.Getter; +import lombok.Setter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import com.alibaba.fastjson.annotation.JSONField; @@ -61,6 +64,10 @@ public class LoginUser implements UserDetails */ private String os; + @Getter + @Setter + private Long nowTenantId; + /** * 权限列表 */ diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CacheNameConstants.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CacheNameConstants.java new file mode 100644 index 0000000..fd7cb2d --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CacheNameConstants.java @@ -0,0 +1,14 @@ +package com.ruoyi.framework.config; + +import java.time.Duration; + +/** + * 缓存常量 + * @author :zhangbaoyu + * @date :Created in 2020-02-12 17:46 + */ +public class CacheNameConstants { + + public static final String cachePrefix = "Cache"; + public static final Duration defaultTtlSecond = Duration.parse("PT30M"); +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CacheNameEnums.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CacheNameEnums.java new file mode 100644 index 0000000..04c33f8 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CacheNameEnums.java @@ -0,0 +1,42 @@ +package com.ruoyi.framework.config; + +import java.time.Duration; + +/** + * 缓存存在时间 + * @author :zhangbaoyu + * @date :Created in 2020-02-11 14:01 + */ +public enum CacheNameEnums { + + // 在线用户 + ONLINE_USER(), + // 用户oauth2 refresh token + USER_REFRESH_TOKEN(), + // 用户权限缓存 + USER_PERMISSION_META(), + // 字典缓存 + SYS_DICT_DATA(), + // 图片验证码 + SYS_KAPTCHA(Duration.ofMinutes(2)), + ; + + private String keyPrefix = CacheNameConstants.cachePrefix; + + private Duration timeToLive = CacheNameConstants.defaultTtlSecond; + + CacheNameEnums() { + } + + CacheNameEnums(Duration timeToLive) { + this.timeToLive = timeToLive; + } + + public String getKeyPrefix() { + return keyPrefix; + } + + public Duration getTimeToLive() { + return timeToLive; + } +} From 6a8a813d7ccd7e36f3dd2170e48652a8bb27c2d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=A3=E5=93=B2=E5=A5=87?= <13840175730@139.com> Date: Thu, 23 Oct 2025 09:48:54 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-admin/pom.xml | 12 ++++++++++ .../goods/repo/model/StockGoodsProperty.java | 2 +- .../sys/admin/repo/mapping/ISysRoleMapper.xml | 2 +- .../admin/repo/mapping/ISysTenantMapper.xml | 23 ------------------- .../sys/admin/repo/mapping/ISysUserMapper.xml | 2 +- .../cp/repo/mapper/WechatCpAccountMapper.java | 2 ++ .../cp/repo/model/WechatCpContactFollow.java | 2 +- .../config/mybatis/MybatisConfiguration.java | 2 +- .../wechat/cp/WechatCpConfiguration.java | 2 +- .../src/main/resources/application.yml | 2 +- .../framework/config/ApplicationConfig.java | 2 +- .../cyl/h5/controller/H5CommonController.java | 10 ++++---- 12 files changed, 27 insertions(+), 36 deletions(-) delete mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysTenantMapper.xml diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml index 042973b..5e67ac4 100644 --- a/ruoyi-admin/pom.xml +++ b/ruoyi-admin/pom.xml @@ -168,6 +168,18 @@ + + + src/main/java + + **/*.xml + + true + + + src/main/resources + + org.springframework.boot diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockGoodsProperty.java b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockGoodsProperty.java index c65ccaf..6d2a60e 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockGoodsProperty.java +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/stock/goods/repo/model/StockGoodsProperty.java @@ -33,7 +33,7 @@ public class StockGoodsProperty implements Serializable { /** * 属性code */ - @TableId(value = "property_code", type = IdType.INPUT) + @TableField(value = "property_code") private String propertyCode; /** diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysRoleMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysRoleMapper.xml index 9b462e4..9a7fc1c 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysRoleMapper.xml +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysRoleMapper.xml @@ -2,7 +2,7 @@ - select * from sys_role a where a.delete_flag='0' and exists(select 1 from sys_user_role b where a.role_id=b.role_id and b.user_id=#{userId} and b.tenant_id=#{tenantId} ) diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysTenantMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysTenantMapper.xml deleted file mode 100644 index eaff5fa..0000000 --- a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysTenantMapper.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserMapper.xml index 2346e58..e15d758 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserMapper.xml +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/repo/mapping/ISysUserMapper.xml @@ -2,7 +2,7 @@ - select user_id,username,name,u.phone,email_address,enable,locked,account_expired,pwd_expired,u.dept_id,d.dept_name, (select group_concat(t.tenant_name) from sys_tenant t,sys_user_tenant ut where ut.user_id=u.user_id and t.tenant_id=ut.tenant_id) as tenant_names from sys_user u left join sys_dept d on u.dept_id=d.dept_id diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpAccountMapper.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpAccountMapper.java index 97c02be..afaedab 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpAccountMapper.java +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/mapper/WechatCpAccountMapper.java @@ -2,6 +2,7 @@ package cn.xluobo.business.wechat.cp.repo.mapper; import cn.xluobo.business.wechat.cp.repo.model.WechatCpAccount; import com.baomidou.mybatisplus.annotation.SqlParser; +import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; @@ -14,6 +15,7 @@ import java.util.List; * @author zhangby * @since 2024-01-23 06:59:58 */ +@Mapper public interface WechatCpAccountMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { @SqlParser(filter = true) diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactFollow.java b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactFollow.java index adcd812..8ec0858 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactFollow.java +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/wechat/cp/repo/model/WechatCpContactFollow.java @@ -35,7 +35,7 @@ public class WechatCpContactFollow implements Serializable { /** * 添加了此外部联系人的企业成员userid */ - @TableId(value = "cp_user_id", type = IdType.INPUT) + @TableField(value = "cp_user_id") private String cpUserId; /** diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/mybatis/MybatisConfiguration.java b/ruoyi-admin/src/main/java/cn/xluobo/config/mybatis/MybatisConfiguration.java index 692fa98..78b8d02 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/config/mybatis/MybatisConfiguration.java +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/mybatis/MybatisConfiguration.java @@ -20,7 +20,7 @@ import java.util.List; @EnableTransactionManagement @Configuration @AutoConfigureAfter(DataSourceAutoConfiguration.class) -@MapperScan(value = {"cn.xluobo.*.*.*.repo.mapper"}) +//@MapperScan(value = {"cn.xluobo.*.*.*.repo.mapper"}) public class MybatisConfiguration { /** diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/WechatCpConfiguration.java b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/WechatCpConfiguration.java index 246946f..7f4f8dd 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/WechatCpConfiguration.java +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/wechat/cp/WechatCpConfiguration.java @@ -23,7 +23,7 @@ import java.util.Optional; import java.util.stream.Collectors; -@Configuration +//@Configuration public class WechatCpConfiguration { @Autowired diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 10f88dd..b0d8aaa 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -127,7 +127,7 @@ mybatis-plus: # 搜索指定包别名 typeAliasesPackage: com.cyl.**.domain, com.ruoyi.common.core.domain.entity, com.ruoyi.**.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 - mapperLocations: classpath*:mapper/**/*Mapper.xml + mapperLocations: classpath*:mapper/**/*Mapper.xml,classpath*:cn/xluobo/business/**/**/repo/mapping/**.xml # 加载全局的配置文件 configLocation: classpath:mybatis/mybatis-config.xml global-config: diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java index 39d260f..1e815b6 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java @@ -17,7 +17,7 @@ import java.util.TimeZone; // 表示通过aop框架暴露该代理对象,AopContext能够访问 @EnableAspectJAutoProxy(exposeProxy = true) // 指定要扫描的Mapper类的包的路径 -@MapperScan({"com.ruoyi.**.mapper", "com.fjp.**.mapper", "com.cyl.**.mapper"}) +@MapperScan({"com.ruoyi.**.mapper", "com.fjp.**.mapper", "com.cyl.**.mapper","cn.xluobo.*.*.*.repo.mapper"}) public class ApplicationConfig { /** diff --git a/ruoyi-mall/src/main/java/com/cyl/h5/controller/H5CommonController.java b/ruoyi-mall/src/main/java/com/cyl/h5/controller/H5CommonController.java index 5263b54..e963575 100644 --- a/ruoyi-mall/src/main/java/com/cyl/h5/controller/H5CommonController.java +++ b/ruoyi-mall/src/main/java/com/cyl/h5/controller/H5CommonController.java @@ -11,7 +11,7 @@ import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.redis.RedisService; import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.OssUtils; +//import com.ruoyi.common.utils.OssUtils; import com.ruoyi.system.service.ISysConfigService; import io.swagger.annotations.ApiOperation; import org.apache.commons.lang3.StringUtils; @@ -27,8 +27,8 @@ import java.util.stream.Collectors; @RequestMapping public class H5CommonController { - @Autowired - private OssUtils ossUtils; +// @Autowired +// private OssUtils ossUtils; @Autowired private AddressMapper addressMapper; @Autowired @@ -97,8 +97,8 @@ public class H5CommonController { @PostMapping("/h5/file/upload") public AjaxResult uploadFile(MultipartFile file) { - String url = ossUtils.uploadOneFile(file); - return AjaxResult.successData(url); +// String url = ossUtils.uploadOneFile(file); + return AjaxResult.successData(null); } @GetMapping("/no-auth/config/get") From 03d7a29c0cf0580722657273827ad737056d9e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=A3=E5=93=B2=E5=A5=87?= <13840175730@139.com> Date: Thu, 23 Oct 2025 11:17:07 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/controller/ISysDeptController.java | 97 +++++++++++++++++++ .../admin/service/BusinessSysDeptService.java | 52 ++++++++++ .../config/mybatis/MybatisConfiguration.java | 14 +-- .../security/CustomAccessDecisionManager.java | 2 +- .../CustomAuthenticationSuccessHandler.java | 2 +- .../CustomSecurityMetadataSource.java | 2 +- 6 files changed, 159 insertions(+), 10 deletions(-) create mode 100644 ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/controller/ISysDeptController.java diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/controller/ISysDeptController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/controller/ISysDeptController.java new file mode 100644 index 0000000..6e6a0ad --- /dev/null +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/controller/ISysDeptController.java @@ -0,0 +1,97 @@ +package cn.xluobo.business.sys.admin.controller; + + +import cn.xluobo.business.sys.admin.domain.req.ReqSearchSysDept; +import cn.xluobo.business.sys.admin.domain.resp.RespTreeSelect; +import cn.xluobo.business.sys.admin.service.BusinessSysDeptService; +import cn.xluobo.core.api.APIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + *

+ * 部门表 前端控制器 + *

+ * + * @author zhangby + * @since 2020-01-18 + */ +@RestController +@RequestMapping("/api/system/dept") +public class ISysDeptController { + + @Autowired + private BusinessSysDeptService sysDeptService; + + /** + * 列表 + * + * @param reqSearchSysDept + * @return + */ + @GetMapping("/list/searchList") + public APIResponse searchList(ReqSearchSysDept reqSearchSysDept) { + return sysDeptService.searchList(reqSearchSysDept); + } + + /** + * 详情 + * + * @param deptId + * @return + */ + @GetMapping("/info/detailById/{deptId}") + public APIResponse detailById(@PathVariable("deptId") Long deptId) { + return sysDeptService.detailById(deptId); + } + + /** + * 校区列表 + * + * @return + */ + @GetMapping("/list/campusList") + public APIResponse campusList() { + List respTreeSelects = sysDeptService.campusList(); + return APIResponse.toAPIResponse(respTreeSelects); + } + + /** + * 校区列表 + * + * @return + */ + @GetMapping("/list/campusListLimitByUser") + public APIResponse campusListLimitByUser() { + List respTreeSelects = sysDeptService.campusListLimitByUser(); + return APIResponse.toAPIResponse(respTreeSelects); + } + + /** + * 可选校区类型 + * 如果拥有全部校区权限,返回全部校区 部分校区 + * 否二 返回 部分校区 + * + * @return + */ + @GetMapping("/list/campusSelect") + public APIResponse campusSelect() { + List respTreeSelects = sysDeptService.campusSelect(); + return APIResponse.toAPIResponse(respTreeSelects); + } + + /** + * 可选校区类型 + * 如果拥有全部校区权限,返回全部校区 部分校区 + * 否二 返回 部分校区 + * + * @return + */ + @GetMapping("/list/campusSelectLimitByUser") + public APIResponse campusSelectLimitByUser() { + List respTreeSelects = sysDeptService.campusSelectLimitByUser(); + return APIResponse.toAPIResponse(respTreeSelects); + } +} diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDeptService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDeptService.java index d21f4a1..2a2a747 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDeptService.java +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDeptService.java @@ -129,4 +129,56 @@ public class BusinessSysDeptService { return respTreeSelects; } + /** + * 前端select + * + * @return + */ + public List campusListLimitByUser() { + LoginUser loginUser = SecurityUtils.getLoginUser(); + List deptList = sysDeptService.selectUserCampusList(loginUser.getUserId()); + List respTreeSelects = deptList.stream().map(RespTreeSelect::new).collect(Collectors.toList()); + return respTreeSelects; + } + + /** + * 校区选择 + * 如果拥有全部校区权限,返回全部校区 部分校区 + * 否二 返回 部分校区 + * + * @return + */ + public List campusSelect() { + + List list = Lists.newArrayList(); + + list.add(new RespTreeSelect(9L,"全部校区",null)); + list.add(new RespTreeSelect(0L,"部分校区",null)); + + return list; + } + + /** + * 校区选择 + * 如果拥有全部校区权限,返回全部校区 部分校区 + * 否二 返回 部分校区 + * + * @return + */ + public List campusSelectLimitByUser() { + LoginUser loginUser = SecurityUtils.getLoginUser(); + + List list = Lists.newArrayList(); + + QueryWrapper qw = new QueryWrapper(); + qw.eq("user_id",loginUser.getUserId()); + qw.eq("dept_id","-1"); + SysUserDept one = userDeptService.getOne(qw); + if(null != one){ + list.add(new RespTreeSelect(9L,"全部校区",null)); + } + list.add(new RespTreeSelect(0L,"部分校区",null)); + + return list; + } } diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/mybatis/MybatisConfiguration.java b/ruoyi-admin/src/main/java/cn/xluobo/config/mybatis/MybatisConfiguration.java index 78b8d02..0ccddc2 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/config/mybatis/MybatisConfiguration.java +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/mybatis/MybatisConfiguration.java @@ -30,13 +30,13 @@ public class MybatisConfiguration { @ConditionalOnMissingBean(PaginationInterceptor.class) public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); - List sqlParserList = new ArrayList<>(); - - TenantSqlParser tenantSqlParser = new MyTenantParser(); - tenantSqlParser.setTenantHandler(new MyTenantHandler()); - sqlParserList.add(tenantSqlParser); - - paginationInterceptor.setSqlParserList(sqlParserList); +// List sqlParserList = new ArrayList<>(); +// +// TenantSqlParser tenantSqlParser = new MyTenantParser(); +// tenantSqlParser.setTenantHandler(new MyTenantHandler()); +// sqlParserList.add(tenantSqlParser); +// +// paginationInterceptor.setSqlParserList(sqlParserList); return paginationInterceptor; } diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAccessDecisionManager.java b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAccessDecisionManager.java index 23ef2e4..9b33a8f 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAccessDecisionManager.java +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAccessDecisionManager.java @@ -14,7 +14,7 @@ import java.util.Iterator; /** * Created by zhangbaoyu on 18/1/9. */ -@Service +//@Service public class CustomAccessDecisionManager implements AccessDecisionManager { // decide 方法是判定是否拥有权限的决策方法, diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAuthenticationSuccessHandler.java b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAuthenticationSuccessHandler.java index bbbcbf3..4b560ff 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAuthenticationSuccessHandler.java +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomAuthenticationSuccessHandler.java @@ -26,7 +26,7 @@ import java.io.PrintWriter; * @author :zhangbaoyu * @date :Created in 2020-02-27 17:41 */ -@Component +//@Component public class CustomAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { private RequestCache requestCache = new HttpSessionRequestCache(); diff --git a/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomSecurityMetadataSource.java b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomSecurityMetadataSource.java index 957019a..8217fdf 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomSecurityMetadataSource.java +++ b/ruoyi-admin/src/main/java/cn/xluobo/config/security/CustomSecurityMetadataSource.java @@ -16,7 +16,7 @@ import java.util.*; /** * Created by zhangbaoyu on 18/1/9. */ -@Component +//@Component public class CustomSecurityMetadataSource implements FilterInvocationSecurityMetadataSource { private HashMap> map =null; From 82a22322bfacf8edfe6c970ffd9785a578f24d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=A3=E5=93=B2=E5=A5=87?= <13840175730@139.com> Date: Mon, 27 Oct 2025 12:53:17 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../course/domain/resp/time/RespClaTime.java | 2 +- .../course/repo/mapping/ScClaTimeMapper.xml | 4 +- .../sc/course/repo/model/ScClaTime.java | 8 +-- .../BusinessScStudentCourseService.java | 8 +-- .../admin/controller/ISysDeptController.java | 10 +++ .../admin/service/BusinessSysDeptService.java | 62 ++++++++++++++++++- 6 files changed, 80 insertions(+), 14 deletions(-) diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTime.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTime.java index ab4bfed..0e46f43 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTime.java +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/domain/resp/time/RespClaTime.java @@ -45,7 +45,7 @@ public class RespClaTime { private String realEndTime; // 应到 - private Integer needAttendCnt; + private Integer bookAttendCnt; // 实到 private Integer realAttendCnt; diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeMapper.xml b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeMapper.xml index 33542ed..e0010ab 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeMapper.xml +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/mapping/ScClaTimeMapper.xml @@ -58,11 +58,11 @@ ct.status, ct.cla_date,ct.start_time,ct.end_time, ct.real_cla_date,ct.real_start_time,ct.real_end_time, - ct.need_attend_cnt,ct.real_attend_cnt,ct.leave_cnt,ct.out_cnt, + ct.book_attend_cnt,ct.real_attend_cnt,ct.out_cnt, ct.pay_hour,ct.pay_total_hour, ct.pay_total_fee, ct.room_name,ct.class_theme,ct.memo, - (select u.name from sys_user u where u.user_id=ct.last_update_user) as last_update_user_name, + (select u.user_name from sys_user u where u.user_id=ct.last_update_user) as last_update_user_name, ct.create_time,ct.last_update_time from sc_course_cla cc left join sc_course course on cc.course_id=course.course_id, diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTime.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTime.java index 170521c..5e4ccd4 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTime.java +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/course/repo/model/ScClaTime.java @@ -140,8 +140,8 @@ public class ScClaTime implements Serializable { /** * 应到人数 */ - @TableField("need_attend_cnt") - private Integer needAttendCnt; + @TableField("book_attend_cnt") + private Integer bookAttendCnt; /** * 实到人数 @@ -158,8 +158,8 @@ public class ScClaTime implements Serializable { /** * 请假人数 */ - @TableField("leave_cnt") - private Integer leaveCnt; +// @TableField("leave_cnt") +// private Integer leaveCnt; /** * 缺勤人数 diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentCourseService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentCourseService.java index e9ab08e..c213e05 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentCourseService.java +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sc/student/service/BusinessScStudentCourseService.java @@ -247,7 +247,7 @@ public class BusinessScStudentCourseService { updateClaTime.setRealStartTime(startTime); updateClaTime.setRealEndTime(endTime); updateClaTime.setStatus(ClaTimeStatusEnums.HAD_CLASS.getStatus()); - updateClaTime.setNeedAttendCnt(needAttendCnt); + updateClaTime.setBookAttendCnt(needAttendCnt); updateClaTime.setRealAttendCnt(realAttendCnt.intValue()); updateClaTime.setMemo(reqClaTimeAttend.getMemo()); updateClaTime.setLastUpdateUser(loginUser.getUserId()); @@ -269,7 +269,7 @@ public class BusinessScStudentCourseService { updateClaTime.setRealStartTime(startTime); updateClaTime.setRealEndTime(endTime); updateClaTime.setStatus(ClaTimeStatusEnums.HAD_CLASS.getStatus()); - updateClaTime.setNeedAttendCnt(needAttendCnt); + updateClaTime.setBookAttendCnt(needAttendCnt); updateClaTime.setRealAttendCnt(realAttendCnt.intValue()); updateClaTime.setMemo(reqClaTimeAttend.getMemo()); updateClaTime.setLastUpdateUser(loginUser.getUserId()); @@ -291,7 +291,7 @@ public class BusinessScStudentCourseService { addClaTime.setSource(ClaTimeSourceEnums.UN_PLAN_CLA_TIME.getSource()); addClaTime.setStatus(ClaTimeStatusEnums.HAD_CLASS.getStatus()); addClaTime.setPayHour(dbCla.getEveryStuLoseHour()); - addClaTime.setNeedAttendCnt(needAttendCnt); + addClaTime.setBookAttendCnt(needAttendCnt); addClaTime.setRealAttendCnt(realAttendCnt.intValue()); addClaTime.setMemo(reqClaTimeAttend.getMemo()); addClaTime.setCreateUser(loginUser.getUserId()); @@ -448,7 +448,7 @@ public class BusinessScStudentCourseService { updateClaTime.setPayTotalHour(totalPayHour); updateClaTime.setPayTotalFee(totalPayFee); updateClaTime.setAtClassCnt(realAttendCnt.intValue()); - updateClaTime.setLeaveCnt(leaveCnt.intValue()); +// updateClaTime.setLeaveCnt(leaveCnt.intValue()); updateClaTime.setOutCnt(outCnt.intValue()); claTimeService.updateById(updateClaTime); diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/controller/ISysDeptController.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/controller/ISysDeptController.java index 6e6a0ad..29ba1c9 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/controller/ISysDeptController.java +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/controller/ISysDeptController.java @@ -36,6 +36,16 @@ public class ISysDeptController { return sysDeptService.searchList(reqSearchSysDept); } + /** + * 前端select + * + * @return + */ + @GetMapping("/list/treeSelect") + public APIResponse treeSelect() { + return sysDeptService.treeSelect(); + } + /** * 详情 * diff --git a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDeptService.java b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDeptService.java index 2a2a747..9790644 100644 --- a/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDeptService.java +++ b/ruoyi-admin/src/main/java/cn/xluobo/business/sys/admin/service/BusinessSysDeptService.java @@ -17,9 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Arrays; -import java.util.Date; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; /** @@ -61,6 +59,64 @@ public class BusinessSysDeptService { return APIResponse.toAPIResponse(null); } + /** + * 前端select + * + * @return + */ + public APIResponse treeSelect() { + SysDept sysDept = new SysDept(); + QueryWrapper qw = new QueryWrapper(sysDept); + qw.orderByAsc("sort"); + List list = sysDeptService.list(qw); + SysDept tree = new SysDept(); + tree.setDeptId(-1L); + this.converterTree(list,tree); + List children = tree.getChildren(); + List respTreeSelects = children.stream().map(RespTreeSelect::new).collect(Collectors.toList()); + return APIResponse.toAPIResponse(respTreeSelects); + } + + private static Map> subTreeMap = new HashMap<>(); + private List children; + /** + * 树转换 + * @param sysDeptList + */ + public void converterTree(List sysDeptList,SysDept tree) { + subTreeMap.clear(); + for (SysDept menu : sysDeptList) { + List subTreeList = subTreeMap.get(menu.getParentId()); + if (null == subTreeList) { + subTreeList = new LinkedList<>(); + subTreeMap.put(menu.getParentId(),subTreeList); + } + subTreeList.add(menu); + } + + this.children = treeDepth(tree).getChildren(); + if(this.children.isEmpty()){ + this.children = sysDeptList; + } + } + private SysDept treeDepth(SysDept sysDept) { + Long deptId = sysDept.getDeptId(); + List childMenuList = subTreeMap.get(deptId); + if(null != childMenuList){ + List childList = Lists.newLinkedList(); + for (SysDept childMenu : childMenuList) { + SysDept child = treeDepth(childMenu); + childList.add(child); + } + sysDept.setChildren(childList); + return sysDept; + }else{ + sysDept.setChildren(Lists.newLinkedList()); + return sysDept; + } + } + + /** * 详情 *