From 4277ff1c528783325a0b78373ce08e8e6fbcd9e6 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 22 Oct 2023 09:03:14 +0800 Subject: [PATCH] =?UTF-8?q?member=EF=BC=9A=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E4=BC=9A=E5=91=98=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 4 +- yudao-module-member/pom.xml | 24 ++ .../yudao-module-member-api/pom.xml | 33 ++ .../module/member/api/address/AddressApi.java | 29 ++ .../api/address/dto/AddressRespDTO.java | 42 +++ .../member/api/config/MemberConfigApi.java | 18 ++ .../api/config/dto/MemberConfigRespDTO.java | 32 ++ .../member/api/level/MemberLevelApi.java | 41 +++ .../api/level/dto/MemberLevelRespDTO.java | 41 +++ .../yudao/module/member/api/package-info.java | 4 + .../member/api/point/MemberPointApi.java | 36 +++ .../module/member/api/user/MemberUserApi.java | 59 ++++ .../api/user/dto/MemberUserRespDTO.java | 55 ++++ .../member/enums/DictTypeConstants.java | 15 + .../member/enums/ErrorCodeConstants.java | 58 ++++ .../enums/MemberExperienceBizTypeEnum.java | 51 +++ .../enums/point/MemberPointBizTypeEnum.java | 58 ++++ .../yudao-module-member-biz/pom.xml | 95 ++++++ .../member/api/address/AddressApiImpl.java | 33 ++ .../api/config/MemberConfigApiImpl.java | 28 ++ .../member/api/level/MemberLevelApiImpl.java | 46 +++ .../yudao/module/member/api/package-info.java | 1 + .../member/api/point/MemberPointApiImpl.java | 46 +++ .../member/api/user/MemberUserApiImpl.java | 47 +++ .../admin/address/AddressController.java | 41 +++ .../admin/address/package-info.java | 1 + .../admin/address/vo/AddressBaseVO.java | 37 +++ .../admin/address/vo/AddressRespVO.java | 19 ++ .../admin/config/MemberConfigController.java | 45 +++ .../admin/config/vo/MemberConfigBaseVO.java | 31 ++ .../admin/config/vo/MemberConfigRespVO.java | 17 + .../config/vo/MemberConfigSaveReqVO.java | 13 + .../admin/group/MemberGroupController.java | 81 +++++ .../admin/group/vo/MemberGroupBaseVO.java | 29 ++ .../group/vo/MemberGroupCreateReqVO.java | 14 + .../admin/group/vo/MemberGroupPageReqVO.java | 30 ++ .../admin/group/vo/MemberGroupRespVO.java | 22 ++ .../group/vo/MemberGroupSimpleRespVO.java | 18 ++ .../group/vo/MemberGroupUpdateReqVO.java | 20 ++ .../MemberExperienceRecordController.java | 52 +++ .../admin/level/MemberLevelController.java | 80 +++++ .../level/MemberLevelRecordController.java | 52 +++ .../MemberExperienceRecordBaseVO.java | 43 +++ .../MemberExperienceRecordPageReqVO.java | 36 +++ .../MemberExperienceRecordRespVO.java | 22 ++ .../level/vo/level/MemberLevelBaseVO.java | 53 ++++ .../vo/level/MemberLevelCreateReqVO.java | 14 + .../level/vo/level/MemberLevelListReqVO.java | 18 ++ .../level/vo/level/MemberLevelRespVO.java | 22 ++ .../vo/level/MemberLevelSimpleRespVO.java | 21 ++ .../vo/level/MemberLevelUpdateReqVO.java | 20 ++ .../vo/record/MemberLevelRecordBaseVO.java | 47 +++ .../vo/record/MemberLevelRecordPageReqVO.java | 30 ++ .../vo/record/MemberLevelRecordRespVO.java | 22 ++ .../point/MemberPointRecordController.java | 56 ++++ .../vo/recrod/MemberPointRecordPageReqVO.java | 27 ++ .../vo/recrod/MemberPointRecordRespVO.java | 42 +++ .../signin/MemberSignInConfigController.java | 74 +++++ .../signin/MemberSignInRecordController.java | 55 ++++ .../vo/config/MemberSignInConfigBaseVO.java | 45 +++ .../config/MemberSignInConfigCreateReqVO.java | 12 + .../vo/config/MemberSignInConfigRespVO.java | 19 ++ .../config/MemberSignInConfigUpdateReqVO.java | 18 ++ .../record/MemberSignInRecordPageReqVO.java | 33 ++ .../vo/record/MemberSignInRecordRespVO.java | 30 ++ .../admin/tag/MemberTagController.java | 94 ++++++ .../admin/tag/vo/MemberTagBaseVO.java | 19 ++ .../admin/tag/vo/MemberTagCreateReqVO.java | 14 + .../admin/tag/vo/MemberTagPageReqVO.java | 27 ++ .../admin/tag/vo/MemberTagRespVO.java | 22 ++ .../admin/tag/vo/MemberTagUpdateReqVO.java | 20 ++ .../admin/user/MemberUserController.java | 121 +++++++ .../admin/user/vo/MemberUserBaseVO.java | 65 ++++ .../admin/user/vo/MemberUserPageReqVO.java | 48 +++ .../admin/user/vo/MemberUserRespVO.java | 52 +++ .../user/vo/MemberUserUpdateLevelReqVO.java | 29 ++ .../user/vo/MemberUserUpdatePointReqVO.java | 22 ++ .../admin/user/vo/MemberUserUpdateReqVO.java | 20 ++ .../app/address/AppAddressController.http | 54 ++++ .../app/address/AppAddressController.java | 82 +++++ .../app/address/vo/AppAddressBaseVO.java | 35 ++ .../app/address/vo/AppAddressCreateReqVO.java | 11 + .../app/address/vo/AppAddressRespVO.java | 20 ++ .../app/address/vo/AppAddressUpdateReqVO.java | 16 + .../app/auth/AppAuthController.http | 66 ++++ .../app/auth/AppAuthController.java | 128 ++++++++ .../app/auth/vo/AppAuthCheckCodeReqVO.java | 41 +++ .../app/auth/vo/AppAuthLoginReqVO.java | 56 ++++ .../app/auth/vo/AppAuthLoginRespVO.java | 38 +++ .../app/auth/vo/AppAuthSmsLoginReqVO.java | 58 ++++ .../app/auth/vo/AppAuthSmsSendReqVO.java | 26 ++ .../app/auth/vo/AppAuthSmsValidateReqVO.java | 35 ++ .../app/auth/vo/AppAuthSocialLoginReqVO.java | 34 ++ .../vo/AppAuthWeixinMiniAppLoginReqVO.java | 26 ++ .../vo/AuthWeixinJsapiSignatureRespVO.java | 31 ++ .../AppMemberExperienceRecordController.java | 43 +++ .../app/level/AppMemberLevelController.java | 36 +++ .../AppMemberExperienceRecordRespVO.java | 24 ++ .../level/vo/level/AppMemberLevelRespVO.java | 28 ++ .../point/AppMemberPointRecordController.java | 41 +++ .../point/vo/AppMemberPointRecordRespVO.java | 27 ++ .../AppMemberSignInConfigController.java | 37 +++ .../AppMemberSignInRecordController.java | 57 ++++ .../config/AppMemberSignInConfigRespVO.java | 16 + .../record/AppMemberSignInRecordRespVO.java | 24 ++ .../AppMemberSignInRecordSummaryRespVO.java | 19 ++ .../app/social/AppSocialUserController.java | 44 +++ .../app/social/vo/AppSocialUserBindReqVO.java | 34 ++ .../social/vo/AppSocialUserUnbindReqVO.java | 30 ++ .../app/user/AppMemberUserController.http | 4 + .../app/user/AppMemberUserController.java | 76 +++++ .../app/user/vo/AppMemberUserInfoRespVO.java | 53 ++++ .../vo/AppMemberUserResetPasswordReqVO.java | 38 +++ .../vo/AppMemberUserUpdateMobileReqVO.java | 40 +++ .../vo/AppMemberUserUpdatePasswordReqVO.java | 31 ++ .../app/user/vo/AppMemberUserUpdateReqVO.java | 18 ++ .../member/controller/package-info.java | 6 + .../convert/address/AddressConvert.java | 45 +++ .../member/convert/auth/AuthConvert.java | 35 ++ .../convert/config/MemberConfigConvert.java | 25 ++ .../convert/group/MemberGroupConvert.java | 35 ++ .../level/MemberExperienceRecordConvert.java | 34 ++ .../convert/level/MemberLevelConvert.java | 39 +++ .../level/MemberLevelRecordConvert.java | 37 +++ .../module/member/convert/package-info.java | 6 + .../point/MemberPointRecordConvert.java | 39 +++ .../signin/MemberSignInConfigConvert.java | 33 ++ .../signin/MemberSignInRecordConvert.java | 74 +++++ .../convert/social/SocialUserConvert.java | 19 ++ .../member/convert/tag/MemberTagConvert.java | 33 ++ .../convert/user/MemberUserConvert.java | 63 ++++ ...‹é“ Spring Boot å¯¹è±¡è½¬æ¢ MapStruct 入门》.md | 1 + .../dataobject/address/MemberAddressDO.java | 54 ++++ .../dal/dataobject/config/MemberConfigDO.java | 48 +++ .../dal/dataobject/group/MemberGroupDO.java | 45 +++ .../level/MemberExperienceRecordDO.java | 64 ++++ .../dal/dataobject/level/MemberLevelDO.java | 64 ++++ .../dataobject/level/MemberLevelRecordDO.java | 71 +++++ .../dataobject/point/MemberPointRecordDO.java | 69 ++++ .../signin/MemberSignInConfigDO.java | 50 +++ .../signin/MemberSignInRecordDO.java | 46 +++ .../dal/dataobject/tag/MemberTagDO.java | 34 ++ .../dal/dataobject/user/MemberUserDO.java | 145 +++++++++ .../mysql/address/MemberAddressMapper.java | 22 ++ .../dal/mysql/config/MemberConfigMapper.java | 14 + .../dal/mysql/group/MemberGroupMapper.java | 31 ++ .../level/MemberExperienceRecordMapper.java | 35 ++ .../dal/mysql/level/MemberLevelMapper.java | 33 ++ .../mysql/level/MemberLevelRecordMapper.java | 26 ++ .../mysql/point/MemberPointRecordMapper.java | 36 +++ .../signin/MemberSignInConfigMapper.java | 24 ++ .../signin/MemberSignInRecordMapper.java | 84 +++++ .../member/dal/mysql/tag/MemberTagMapper.java | 28 ++ .../dal/mysql/user/MemberUserMapper.java | 96 ++++++ .../yudao/module/member/dal/package-info.java | 9 + .../module/member/dal/redis/package-info.java | 4 + .../module/member/framework/package-info.java | 6 + .../web/config/MemberWebConfiguration.java | 24 ++ .../member/framework/web/package-info.java | 4 + .../mq/message/user/UserCreateMessage.java | 29 ++ .../mq/producer/user/UserCreateProducer.java | 31 ++ .../yudao/module/member/package-info.java | 8 + .../service/address/AddressService.java | 67 ++++ .../service/address/AddressServiceImpl.java | 97 ++++++ .../service/auth/MemberAuthService.java | 90 ++++++ .../service/auth/MemberAuthServiceImpl.java | 264 +++++++++++++++ .../service/config/MemberConfigService.java | 29 ++ .../config/MemberConfigServiceImpl.java | 44 +++ .../service/group/MemberGroupService.java | 86 +++++ .../service/group/MemberGroupServiceImpl.java | 103 ++++++ .../level/MemberExperienceRecordService.java | 53 ++++ .../MemberExperienceRecordServiceImpl.java | 55 ++++ .../level/MemberLevelRecordService.java | 37 +++ .../level/MemberLevelRecordServiceImpl.java | 39 +++ .../service/level/MemberLevelService.java | 102 ++++++ .../service/level/MemberLevelServiceImpl.java | 300 ++++++++++++++++++ .../point/MemberPointRecordService.java | 42 +++ .../point/MemberPointRecordServiceImpl.java | 94 ++++++ .../signin/MemberSignInConfigService.java | 62 ++++ .../signin/MemberSignInConfigServiceImpl.java | 106 +++++++ .../signin/MemberSignInRecordService.java | 50 +++ .../signin/MemberSignInRecordServiceImpl.java | 182 +++++++++++ .../member/service/tag/MemberTagService.java | 73 +++++ .../service/tag/MemberTagServiceImpl.java | 125 ++++++++ .../service/user/MemberUserService.java | 172 ++++++++++ .../service/user/MemberUserServiceImpl.java | 294 +++++++++++++++++ .../address/AddressServiceImplTest.java | 98 ++++++ .../service/auth/MemberAuthServiceTest.java | 118 +++++++ .../group/MemberGroupServiceImplTest.java | 160 ++++++++++ .../level/MemberLevelServiceImplTest.java | 268 ++++++++++++++++ .../service/tag/MemberTagServiceImplTest.java | 133 ++++++++ .../user/MemberUserServiceImplTest.java | 136 ++++++++ .../test/resources/application-unit-test.yaml | 49 +++ .../src/test/resources/logback.xml | 4 + .../src/test/resources/sql/clean.sql | 5 + .../src/test/resources/sql/create_tables.sql | 113 +++++++ 196 files changed, 9693 insertions(+), 2 deletions(-) create mode 100644 yudao-module-member/pom.xml create mode 100644 yudao-module-member/yudao-module-member-api/pom.xml create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/address/AddressApi.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/address/dto/AddressRespDTO.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/config/MemberConfigApi.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/config/dto/MemberConfigRespDTO.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/dto/MemberLevelRespDTO.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/point/MemberPointApi.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/MemberUserRespDTO.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/DictTypeConstants.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/MemberExperienceBizTypeEnum.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/point/MemberPointBizTypeEnum.java create mode 100644 yudao-module-member/yudao-module-member-biz/pom.xml create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/address/AddressApiImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/config/MemberConfigApiImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/point/MemberPointApiImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApiImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/AddressController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/package-info.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/vo/AddressBaseVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/vo/AddressRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/MemberConfigController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/vo/MemberConfigBaseVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/vo/MemberConfigRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/vo/MemberConfigSaveReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/MemberGroupController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupBaseVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupCreateReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupPageReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupSimpleRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupUpdateReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberExperienceRecordController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordBaseVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordPageReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelBaseVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelCreateReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelListReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelSimpleRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelUpdateReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordBaseVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordPageReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/MemberPointRecordController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/recrod/MemberPointRecordPageReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/recrod/MemberPointRecordRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/MemberSignInConfigController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/MemberSignInRecordController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigBaseVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigCreateReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigUpdateReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/record/MemberSignInRecordPageReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/record/MemberSignInRecordRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/MemberTagController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagBaseVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagCreateReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagPageReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagUpdateReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/MemberUserController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserBaseVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserPageReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdateLevelReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdatePointReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdateReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.http create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressBaseVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressCreateReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressUpdateReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthCheckCodeReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsLoginReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsSendReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsValidateReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLoginReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthWeixinMiniAppLoginReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AuthWeixinJsapiSignatureRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberExperienceRecordController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberLevelController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/experience/AppMemberExperienceRecordRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/level/AppMemberLevelRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/AppMemberPointRecordController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/vo/AppMemberPointRecordRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInConfigController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInRecordController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/vo/config/AppMemberSignInConfigRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/vo/record/AppMemberSignInRecordRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/vo/record/AppMemberSignInRecordSummaryRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserBindReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserUnbindReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.http create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserResetPasswordReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateMobileReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdatePasswordReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/package-info.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/address/AddressConvert.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/config/MemberConfigConvert.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/group/MemberGroupConvert.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberExperienceRecordConvert.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelConvert.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelRecordConvert.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/package-info.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/point/MemberPointRecordConvert.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/signin/MemberSignInConfigConvert.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/signin/MemberSignInRecordConvert.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/social/SocialUserConvert.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/tag/MemberTagConvert.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/ã€ŠèŠ‹é“ Spring Boot å¯¹è±¡è½¬æ¢ MapStruct 入门》.md create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/MemberAddressDO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/config/MemberConfigDO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/group/MemberGroupDO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberExperienceRecordDO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberLevelDO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberLevelRecordDO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/point/MemberPointRecordDO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/signin/MemberSignInConfigDO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/signin/MemberSignInRecordDO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/tag/MemberTagDO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/MemberAddressMapper.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/config/MemberConfigMapper.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/group/MemberGroupMapper.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberExperienceRecordMapper.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelMapper.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelRecordMapper.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/point/MemberPointRecordMapper.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/signin/MemberSignInConfigMapper.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/signin/MemberSignInRecordMapper.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/tag/MemberTagMapper.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/package-info.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/redis/package-info.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/package-info.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/web/config/MemberWebConfiguration.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/web/package-info.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/message/user/UserCreateMessage.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/user/UserCreateProducer.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/package-info.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/config/MemberConfigService.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/config/MemberConfigServiceImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/group/MemberGroupService.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/group/MemberGroupServiceImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordService.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelService.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordService.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordServiceImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInConfigService.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInConfigServiceImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordService.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordServiceImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/tag/MemberTagService.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/tag/MemberTagServiceImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceTest.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/group/MemberGroupServiceImplTest.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImplTest.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/tag/MemberTagServiceImplTest.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImplTest.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/test/resources/application-unit-test.yaml create mode 100644 yudao-module-member/yudao-module-member-biz/src/test/resources/logback.xml create mode 100644 yudao-module-member/yudao-module-member-biz/src/test/resources/sql/clean.sql create mode 100644 yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql diff --git a/pom.xml b/pom.xml index 17601bfea..65000e402 100644 --- a/pom.xml +++ b/pom.xml @@ -12,10 +12,10 @@ yudao-gateway yudao-framework - - yudao-module-bpm yudao-module-system yudao-module-infra + yudao-module-member + yudao-module-bpm yudao-module-pay yudao-module-report yudao-module-mp diff --git a/yudao-module-member/pom.xml b/yudao-module-member/pom.xml new file mode 100644 index 000000000..f481f6b26 --- /dev/null +++ b/yudao-module-member/pom.xml @@ -0,0 +1,24 @@ + + + + cn.iocoder.cloud + yudao + ${revision} + + 4.0.0 + + yudao-module-member-api + yudao-module-member-biz + + yudao-module-member + pom + + ${project.artifactId} + + member 模å—,我们放会员业务。 + 例如说:会员中心等等 + + + diff --git a/yudao-module-member/yudao-module-member-api/pom.xml b/yudao-module-member/yudao-module-member-api/pom.xml new file mode 100644 index 000000000..242df88f5 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/pom.xml @@ -0,0 +1,33 @@ + + + + cn.iocoder.cloud + yudao-module-member + ${revision} + + 4.0.0 + yudao-module-member-api + jar + + ${project.artifactId} + + member æ¨¡å— API,暴露给其它模å—调用 + + + + + cn.iocoder.cloud + yudao-common + + + + + org.springframework.boot + spring-boot-starter-validation + true + + + + diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/address/AddressApi.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/address/AddressApi.java new file mode 100644 index 000000000..658748819 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/address/AddressApi.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.member.api.address; + +import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; + +/** + * ç”¨æˆ·æ”¶ä»¶åœ°å€ API æŽ¥å£ + * + * @author 芋é“æºç  + */ +public interface AddressApi { + + /** + * èŽ·å¾—ç”¨æˆ·æ”¶ä»¶åœ°å€ + * + * @param id 收件地å€ç¼–å· + * @param userId ç”¨æˆ·ç¼–å· + * @return ç”¨æˆ·æ”¶ä»¶åœ°å€ + */ + AddressRespDTO getAddress(Long id, Long userId); + + /** + * èŽ·å¾—ç”¨æˆ·é»˜è®¤æ”¶ä»¶åœ°å€ + * + * @param userId ç”¨æˆ·ç¼–å· + * @return ç”¨æˆ·æ”¶ä»¶åœ°å€ + */ + AddressRespDTO getDefaultAddress(Long userId); + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/address/dto/AddressRespDTO.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/address/dto/AddressRespDTO.java new file mode 100644 index 000000000..5a5e44ff1 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/address/dto/AddressRespDTO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.member.api.address.dto; + +import lombok.Data; + +/** + * ç”¨æˆ·æ”¶ä»¶åœ°å€ Response DTO + * + * @author 芋é“æºç  + */ +@Data +public class AddressRespDTO { + + /** + * ç¼–å· + */ + private Long id; + /** + * ç”¨æˆ·ç¼–å· + */ + private Long userId; + /** + * 收件人å称 + */ + private String name; + /** + * æ‰‹æœºå· + */ + private String mobile; + /** + * åœ°åŒºç¼–å· + */ + private Integer areaId; + /** + * æ”¶ä»¶è¯¦ç»†åœ°å€ + */ + private String detailAddress; + /** + * 是å¦é»˜è®¤ + */ + private Boolean defaultStatus; + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/config/MemberConfigApi.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/config/MemberConfigApi.java new file mode 100644 index 000000000..dab7f6877 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/config/MemberConfigApi.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.member.api.config; + +import cn.iocoder.yudao.module.member.api.config.dto.MemberConfigRespDTO; + +/** + * 用户é…ç½® API æŽ¥å£ + * + * @author owen + */ +public interface MemberConfigApi { + + /** + * 获得积分é…ç½® + * + * @return 积分é…ç½® + */ + MemberConfigRespDTO getConfig(); +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/config/dto/MemberConfigRespDTO.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/config/dto/MemberConfigRespDTO.java new file mode 100644 index 000000000..59aab53f9 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/config/dto/MemberConfigRespDTO.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.member.api.config.dto; + +import lombok.Data; + +/** + * ç”¨æˆ·ä¿¡æ¯ Response DTO + * + * @author 芋é“æºç  + */ +@Data +public class MemberConfigRespDTO { + + /** + * 积分抵扣开关 + */ + private Boolean pointTradeDeductEnable; + /** + * 积分抵扣,å•ä½ï¼šåˆ† + *

+ * 1 积分抵扣多少分 + */ + private Integer pointTradeDeductUnitPrice; + /** + * 积分抵扣最大值 + */ + private Integer pointTradeDeductMaxPrice; + /** + * 1 元赠é€å¤šå°‘分 + */ + private Integer pointTradeGivePoint; + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java new file mode 100644 index 000000000..587683797 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.member.api.level; + +import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO; +import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; + +/** + * 会员等级 API æŽ¥å£ + * + * @author owen + */ +public interface MemberLevelApi { + + /** + * 获得会员等级 + * + * @param id ä¼šå‘˜ç­‰çº§ç¼–å· + * @return 会员等级 + */ + MemberLevelRespDTO getMemberLevel(Long id); + + /** + * 增加会员ç»éªŒ + * + * @param userId 会员ID + * @param experience ç»éªŒ + * @param bizType 业务类型 {@link MemberExperienceBizTypeEnum} + * @param bizId ä¸šåŠ¡ç¼–å· + */ + void addExperience(Long userId, Integer experience, Integer bizType, String bizId); + + /** + * 扣å‡ä¼šå‘˜ç»éªŒ + * + * @param userId 会员ID + * @param experience ç»éªŒ + * @param bizType 业务类型 {@link MemberExperienceBizTypeEnum} + * @param bizId ä¸šåŠ¡ç¼–å· + */ + void reduceExperience(Long userId, Integer experience, Integer bizType, String bizId); + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/dto/MemberLevelRespDTO.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/dto/MemberLevelRespDTO.java new file mode 100644 index 000000000..a72d65f23 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/dto/MemberLevelRespDTO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.member.api.level.dto; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import lombok.Data; + +/** + * 会员等级 Resp DTO + * + * @author 芋é“æºç  + */ +@Data +public class MemberLevelRespDTO { + + /** + * ç¼–å· + */ + private Long id; + /** + * 等级å称 + */ + private String name; + /** + * 等级 + */ + private Integer level; + /** + * å‡çº§ç»éªŒ + */ + private Integer experience; + /** + * 享å—折扣 + */ + private Integer discountPercent; + /** + * çŠ¶æ€ + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java new file mode 100644 index 000000000..56cd9857f --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java @@ -0,0 +1,4 @@ +/** + * member API 包,定义暴露给其它模å—çš„ API + */ +package cn.iocoder.yudao.module.member.api; diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/point/MemberPointApi.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/point/MemberPointApi.java new file mode 100644 index 000000000..3eb749fb6 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/point/MemberPointApi.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.member.api.point; + +import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; + +import javax.validation.constraints.Min; + +/** + * 用户积分的 API æŽ¥å£ + * + * @author owen + */ +public interface MemberPointApi { + + /** + * 增加用户积分 + * + * @param userId ç”¨æˆ·ç¼–å· + * @param point 积分 + * @param bizType 业务类型 {@link MemberPointBizTypeEnum} + * @param bizId ä¸šåŠ¡ç¼–å· + */ + void addPoint(Long userId, @Min(value = 1L, message = "积分必须是正数") Integer point, + Integer bizType, String bizId); + + /** + * å‡å°‘用户积分 + * + * @param userId ç”¨æˆ·ç¼–å· + * @param point 积分 + * @param bizType 业务类型 {@link MemberPointBizTypeEnum} + * @param bizId ä¸šåŠ¡ç¼–å· + */ + void reducePoint(Long userId, @Min(value = 1L, message = "积分必须是正数") Integer point, + Integer bizType, String bizId); + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java new file mode 100644 index 000000000..3d2130e18 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.member.api.user; + +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * 会员用户的 API æŽ¥å£ + * + * @author 芋é“æºç  + */ +public interface MemberUserApi { + + /** + * èŽ·å¾—ä¼šå‘˜ç”¨æˆ·ä¿¡æ¯ + * + * @param id ç”¨æˆ·ç¼–å· + * @return ç”¨æˆ·ä¿¡æ¯ + */ + MemberUserRespDTO getUser(Long id); + + /** + * 获得会员用户信æ¯ä»¬ + * + * @param ids 用户编å·çš„数组 + * @return 用户信æ¯ä»¬ + */ + List getUserList(Collection ids); + + /** + * 获得会员用户 Map + * + * @param ids 用户编å·çš„数组 + * @return 会员用户 Map + */ + default Map getUserMap(Collection ids) { + return convertMap(getUserList(ids), MemberUserRespDTO::getId); + } + + /** + * 基于用户昵称,模糊匹é…用户列表 + * + * @param nickname ç”¨æˆ·æ˜µç§°ï¼Œæ¨¡ç³ŠåŒ¹é… + * @return 用户信æ¯çš„列表 + */ + List getUserListByNickname(String nickname); + + /** + * 基于手机å·ï¼Œç²¾å‡†åŒ¹é…用户 + * + * @param mobile æ‰‹æœºå· + * @return ç”¨æˆ·ä¿¡æ¯ + */ + MemberUserRespDTO getUserByMobile(String mobile); +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/MemberUserRespDTO.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/MemberUserRespDTO.java new file mode 100644 index 000000000..50548f935 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/MemberUserRespDTO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.member.api.user.dto; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * ç”¨æˆ·ä¿¡æ¯ Response DTO + * + * @author 芋é“æºç  + */ +@Data +public class MemberUserRespDTO { + + /** + * 用户ID + */ + private Long id; + /** + * 用户昵称 + */ + private String nickname; + /** + * å¸å·çŠ¶æ€ + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + /** + * ç”¨æˆ·å¤´åƒ + */ + private String avatar; + /** + * 手机 + */ + private String mobile; + /** + * 创建时间(注册时间) + */ + private LocalDateTime createTime; + + // ========== å…¶å®ƒä¿¡æ¯ ========== + + /** + * ä¼šå‘˜çº§åˆ«ç¼–å· + */ + private Long levelId; + + /** + * 积分 + */ + private Integer point; + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/DictTypeConstants.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/DictTypeConstants.java new file mode 100644 index 000000000..c87cbb901 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/DictTypeConstants.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.member.enums; + +/** + * Member 字典类型的枚举类 + * + * @author owen + */ +public interface DictTypeConstants { + + /** + * 会员ç»éªŒè®°å½• - 业务类型 + */ + String MEMBER_EXPERIENCE_BIZ_TYPE = "member_experience_biz_type"; + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java new file mode 100644 index 000000000..c7dc8b749 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.member.enums; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; + +/** + * Member 错误ç æžšä¸¾ç±» + *

+ * member 系统,使用 1-004-000-000 段 + */ +public interface ErrorCodeConstants { + + // ========== 用户相关 1-004-001-000 ============ + ErrorCode USER_NOT_EXISTS = new ErrorCode(1_004_001_000, "用户ä¸å­˜åœ¨"); + ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1_004_001_001, "手机å·æœªæ³¨å†Œç”¨æˆ·"); + ErrorCode USER_MOBILE_USED = new ErrorCode(1_004_001_002, "修改手机失败,该手机å·({})å·²ç»è¢«ä½¿ç”¨"); + ErrorCode USER_POINT_NOT_ENOUGH = new ErrorCode(1_004_001_003, "用户积分余é¢ä¸è¶³"); + + // ========== AUTH æ¨¡å— 1-004-003-000 ========== + ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1_004_003_000, "登录失败,账å·å¯†ç ä¸æ­£ç¡®"); + ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1_004_003_001, "登录失败,账å·è¢«ç¦ç”¨"); + ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1_004_003_005, "未绑定账å·ï¼Œéœ€è¦è¿›è¡Œç»‘定"); + ErrorCode AUTH_MOBILE_USED = new ErrorCode(1_004_003_007, "手机å·å·²ç»è¢«ä½¿ç”¨"); + + // ========== ç”¨æˆ·æ”¶ä»¶åœ°å€ 1-004-004-000 ========== + ErrorCode ADDRESS_NOT_EXISTS = new ErrorCode(1_004_004_000, "用户收件地å€ä¸å­˜åœ¨"); + + //========== 用户标签 1-004-006-000 ========== + ErrorCode TAG_NOT_EXISTS = new ErrorCode(1_004_006_000, "用户标签ä¸å­˜åœ¨"); + ErrorCode TAG_NAME_EXISTS = new ErrorCode(1_004_006_001, "用户标签已ç»å­˜åœ¨"); + ErrorCode TAG_HAS_USER = new ErrorCode(1_004_006_002, "用户标签下存在用户,无法删除"); + + //========== 积分é…ç½® 1-004-007-000 ========== + + //========== 积分记录 1-004-008-000 ========== + ErrorCode POINT_RECORD_BIZ_NOT_SUPPORT = new ErrorCode(1_004_008_000, "用户积分记录业务类型ä¸æ”¯æŒ"); + + //========== 签到é…ç½® 1-004-009-000 ========== + ErrorCode SIGN_IN_CONFIG_NOT_EXISTS = new ErrorCode(1_004_009_000, "签到天数规则ä¸å­˜åœ¨"); + ErrorCode SIGN_IN_CONFIG_EXISTS = new ErrorCode(1_004_009_001, "签到天数规则已存在"); + + //========== 签到é…ç½® 1-004-010-000 ========== + ErrorCode SIGN_IN_RECORD_TODAY_EXISTS = new ErrorCode(1_004_010_000, "今日已签到,请勿é‡å¤ç­¾åˆ°"); + + //========== 用户等级 1-004-011-000 ========== + ErrorCode LEVEL_NOT_EXISTS = new ErrorCode(1_004_011_000, "用户等级ä¸å­˜åœ¨"); + ErrorCode LEVEL_NAME_EXISTS = new ErrorCode(1_004_011_001, "用户等级å称[{}]已被使用"); + ErrorCode LEVEL_VALUE_EXISTS = new ErrorCode(1_004_011_002, "用户等级值[{}]已被[{}]使用"); + ErrorCode LEVEL_EXPERIENCE_MIN = new ErrorCode(1_004_011_003, "å‡çº§ç»éªŒå¿…须大于上一个等级[{}]设置的å‡çº§ç»éªŒ[{}]"); + ErrorCode LEVEL_EXPERIENCE_MAX = new ErrorCode(1_004_011_004, "å‡çº§ç»éªŒå¿…é¡»å°äºŽä¸‹ä¸€ä¸ªç­‰çº§[{}]设置的å‡çº§ç»éªŒ[{}]"); + ErrorCode LEVEL_HAS_USER = new ErrorCode(1_004_011_005, "用户等级下存在用户,无法删除"); + + ErrorCode EXPERIENCE_BIZ_NOT_SUPPORT = new ErrorCode(1_004_011_201, "用户ç»éªŒä¸šåŠ¡ç±»åž‹ä¸æ”¯æŒ"); + + //========== 用户分组 1-004-012-000 ========== + ErrorCode GROUP_NOT_EXISTS = new ErrorCode(1_004_012_000, "用户分组ä¸å­˜åœ¨"); + ErrorCode GROUP_HAS_USER = new ErrorCode(1_004_012_001, "用户分组下存在用户,无法删除"); + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/MemberExperienceBizTypeEnum.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/MemberExperienceBizTypeEnum.java new file mode 100644 index 000000000..3038dba31 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/MemberExperienceBizTypeEnum.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.member.enums; + +import cn.hutool.core.util.EnumUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Objects; + +/** + * 会员ç»éªŒ - 业务类型 + * + * @author owen + */ +@Getter +@AllArgsConstructor +public enum MemberExperienceBizTypeEnum { + + /** + * 管ç†å‘˜è°ƒæ•´ã€é‚€è¯·æ–°ç”¨æˆ·ã€ä¸‹å•ã€é€€å•ã€ç­¾åˆ°ã€æŠ½å¥– + */ + ADMIN(0, "管ç†å‘˜è°ƒæ•´", "管ç†å‘˜è°ƒæ•´èŽ·å¾— {} ç»éªŒ", true), + INVITE_REGISTER(1, "邀新奖励", "邀请好å‹èŽ·å¾— {} ç»éªŒ", true), + SIGN_IN(4, "签到奖励", "签到获得 {} ç»éªŒ", true), + LOTTERY(5, "抽奖奖励", "抽奖获得 {} ç»éªŒ", true), + ORDER_GIVE(11, "下å•å¥–励", "下å•èŽ·å¾— {} ç»éªŒ", true), + ORDER_GIVE_CANCEL(12, "下å•å¥–励(整å•å–消)", "å–消订å•èŽ·å¾— {} ç»éªŒ", false), // ORDER_GIVE çš„å–消 + ORDER_GIVE_CANCEL_ITEM(13, "下å•å¥–励(å•ä¸ªé€€æ¬¾ï¼‰", "退款订å•èŽ·å¾— {} ç»éªŒ", false), // ORDER_GIVE çš„å–消 + ; + + /** + * 业务类型 + */ + private final int type; + /** + * 标题 + */ + private final String title; + /** + * æè¿° + */ + private final String description; + /** + * 是å¦ä¸ºæ‰£å‡ç§¯åˆ† + */ + private final boolean add; + + public static MemberExperienceBizTypeEnum getByType(Integer type) { + return EnumUtil.getBy(MemberExperienceBizTypeEnum.class, + e -> Objects.equals(type, e.getType())); + } +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/point/MemberPointBizTypeEnum.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/point/MemberPointBizTypeEnum.java new file mode 100644 index 000000000..ef491f42a --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/point/MemberPointBizTypeEnum.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.member.enums.point; + +import cn.hutool.core.util.EnumUtil; +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Objects; + +/** + * 会员积分的业务类型枚举 + * + * @author 芋é“æºç  + */ +@AllArgsConstructor +@Getter +public enum MemberPointBizTypeEnum implements IntArrayValuable { + + SIGN(1, "签到", "签到获得 {} 积分", true), + ADMIN(2, "管ç†å‘˜ä¿®æ”¹", "管ç†å‘˜ä¿®æ”¹ {} 积分", true), + + ORDER_USE(11, "订å•ç§¯åˆ†æŠµæ‰£", "下å•ä½¿ç”¨ {} 积分", false), // 下å•æ—¶ï¼Œæ‰£å‡ç§¯åˆ† + ORDER_USE_CANCEL(12, "订å•ç§¯åˆ†æŠµæ‰£ï¼ˆæ•´å•å–消)", "订å•å–消,退还 {} 积分", true), // ORDER_USE çš„å–消 + ORDER_USE_CANCEL_ITEM(13, "订å•ç§¯åˆ†æŠµæ‰£ï¼ˆå•ä¸ªé€€æ¬¾ï¼‰", "订å•é€€æ¬¾ï¼Œé€€è¿˜ {} 积分", true), // ORDER_USE çš„å–消 + + ORDER_GIVE(21, "订å•ç§¯åˆ†å¥–励", "下å•èŽ·å¾— {} 积分", true), // 支付订å•æ—¶ï¼Œèµ é€ç§¯åˆ† + ORDER_GIVE_CANCEL(22, "订å•ç§¯åˆ†å¥–励(整å•å–消)", "订å•å–消,退还 {} 积分", false), // ORDER_GIVE çš„å–消 + ORDER_GIVE_CANCEL_ITEM(23, "订å•ç§¯åˆ†å¥–励(å•ä¸ªé€€æ¬¾ï¼‰", "订å•é€€æ¬¾ï¼Œæ‰£é™¤èµ é€çš„ {} 积分", false) // ORDER_GIVE çš„å–消 + ; + + /** + * 类型 + */ + private final Integer type; + /** + * åå­— + */ + private final String name; + /** + * æè¿° + */ + private final String description; + /** + * 是å¦ä¸ºæ‰£å‡ç§¯åˆ† + */ + private final boolean add; + + @Override + public int[] array() { + return new int[0]; + } + + public static MemberPointBizTypeEnum getByType(Integer type) { + return EnumUtil.getBy(MemberPointBizTypeEnum.class, + e -> Objects.equals(type, e.getType())); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/pom.xml b/yudao-module-member/yudao-module-member-biz/pom.xml new file mode 100644 index 000000000..2d06e9c34 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/pom.xml @@ -0,0 +1,95 @@ + + + + cn.iocoder.cloud + yudao-module-member + ${revision} + + 4.0.0 + yudao-module-member-biz + jar + + ${project.artifactId} + + member 模å—,我们放会员业务。 + 例如说:会员中心等等 + + + + + cn.iocoder.cloud + yudao-module-member-api + ${revision} + + + cn.iocoder.cloud + yudao-module-system-api + ${revision} + + + cn.iocoder.cloud + yudao-module-infra-api + ${revision} + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-biz-operatelog + + + cn.iocoder.cloud + yudao-spring-boot-starter-biz-tenant + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-security + + + + org.springframework.boot + spring-boot-starter-validation + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-mybatis + + + + cn.iocoder.cloud + yudao-spring-boot-starter-redis + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-mq + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-test + test + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-excel + + + + cn.iocoder.cloud + yudao-spring-boot-starter-biz-ip + + + + + diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/address/AddressApiImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/address/AddressApiImpl.java new file mode 100644 index 000000000..b8088a455 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/address/AddressApiImpl.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.member.api.address; + +import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; +import cn.iocoder.yudao.module.member.convert.address.AddressConvert; +import cn.iocoder.yudao.module.member.service.address.AddressService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +/** + * ç”¨æˆ·æ”¶ä»¶åœ°å€ API 实现类 + * + * @author 芋é“æºç  + */ +@Service +@Validated +public class AddressApiImpl implements AddressApi { + + @Resource + private AddressService addressService; + + @Override + public AddressRespDTO getAddress(Long id, Long userId) { + return AddressConvert.INSTANCE.convert02(addressService.getAddress(userId, id)); + } + + @Override + public AddressRespDTO getDefaultAddress(Long userId) { + return AddressConvert.INSTANCE.convert02(addressService.getDefaultUserAddress(userId)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/config/MemberConfigApiImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/config/MemberConfigApiImpl.java new file mode 100644 index 000000000..510f4fff7 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/config/MemberConfigApiImpl.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.member.api.config; + +import cn.iocoder.yudao.module.member.api.config.dto.MemberConfigRespDTO; +import cn.iocoder.yudao.module.member.convert.config.MemberConfigConvert; +import cn.iocoder.yudao.module.member.service.config.MemberConfigService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +/** + * 用户é…ç½® API 实现类 + * + * @author owen + */ +@Service +@Validated +public class MemberConfigApiImpl implements MemberConfigApi { + + @Resource + private MemberConfigService memberConfigService; + + @Override + public MemberConfigRespDTO getConfig() { + return MemberConfigConvert.INSTANCE.convert01(memberConfigService.getConfig()); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java new file mode 100644 index 000000000..79fed98eb --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.member.api.level; + +import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO; +import cn.iocoder.yudao.module.member.convert.level.MemberLevelConvert; +import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; +import cn.iocoder.yudao.module.member.service.level.MemberLevelService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.EXPERIENCE_BIZ_NOT_SUPPORT; + +/** + * 会员等级 API 实现类 + * + * @author owen + */ +@Service +@Validated +public class MemberLevelApiImpl implements MemberLevelApi { + + @Resource + private MemberLevelService memberLevelService; + + @Override + public MemberLevelRespDTO getMemberLevel(Long id) { + return MemberLevelConvert.INSTANCE.convert02(memberLevelService.getLevel(id)); + } + + @Override + public void addExperience(Long userId, Integer experience, Integer bizType, String bizId) { + MemberExperienceBizTypeEnum bizTypeEnum = MemberExperienceBizTypeEnum.getByType(bizType); + if (bizTypeEnum == null) { + throw exception(EXPERIENCE_BIZ_NOT_SUPPORT); + } + memberLevelService.addExperience(userId, experience, bizTypeEnum, bizId); + } + + @Override + public void reduceExperience(Long userId, Integer experience, Integer bizType, String bizId) { + addExperience(userId, -experience, bizType, bizId); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java new file mode 100644 index 000000000..5f97979b8 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.member.api; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/point/MemberPointApiImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/point/MemberPointApiImpl.java new file mode 100644 index 000000000..6e21e8546 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/point/MemberPointApiImpl.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.member.api.point; + +import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; +import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.POINT_RECORD_BIZ_NOT_SUPPORT; + +/** + * 用户积分的 API 实现类 + * + * @author owen + */ +@Service +@Validated +public class MemberPointApiImpl implements MemberPointApi { + + @Resource + private MemberPointRecordService memberPointRecordService; + + @Override + public void addPoint(Long userId, Integer point, Integer bizType, String bizId) { + Assert.isTrue(point > 0); + MemberPointBizTypeEnum bizTypeEnum = MemberPointBizTypeEnum.getByType(bizType); + if (bizTypeEnum == null) { + throw exception(POINT_RECORD_BIZ_NOT_SUPPORT); + } + memberPointRecordService.createPointRecord(userId, point, bizTypeEnum, bizId); + } + + @Override + public void reducePoint(Long userId, Integer point, Integer bizType, String bizId) { + Assert.isTrue(point > 0); + MemberPointBizTypeEnum bizTypeEnum = MemberPointBizTypeEnum.getByType(bizType); + if (bizTypeEnum == null) { + throw exception(POINT_RECORD_BIZ_NOT_SUPPORT); + } + memberPointRecordService.createPointRecord(userId, -point, bizTypeEnum, bizId); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApiImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApiImpl.java new file mode 100644 index 000000000..8da857c6d --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApiImpl.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.member.api.user; + +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; + +/** + * 会员用户的 API 实现类 + * + * @author 芋é“æºç  + */ +@Service +@Validated +public class MemberUserApiImpl implements MemberUserApi { + + @Resource + private MemberUserService userService; + + @Override + public MemberUserRespDTO getUser(Long id) { + MemberUserDO user = userService.getUser(id); + return MemberUserConvert.INSTANCE.convert2(user); + } + + @Override + public List getUserList(Collection ids) { + return MemberUserConvert.INSTANCE.convertList2(userService.getUserList(ids)); + } + + @Override + public List getUserListByNickname(String nickname) { + return MemberUserConvert.INSTANCE.convertList2(userService.getUserListByNickname(nickname)); + } + + @Override + public MemberUserRespDTO getUserByMobile(String mobile) { + return MemberUserConvert.INSTANCE.convert2(userService.getUserByMobile(mobile)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/AddressController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/AddressController.java new file mode 100644 index 000000000..0363634c5 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/AddressController.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.member.controller.admin.address; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.member.controller.admin.address.vo.AddressRespVO; +import cn.iocoder.yudao.module.member.convert.address.AddressConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; +import cn.iocoder.yudao.module.member.service.address.AddressService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管ç†åŽå° - 用户收件地å€") +@RestController +@RequestMapping("/member/address") +@Validated +public class AddressController { + + @Resource + private AddressService addressService; + + @GetMapping("/list") + @Operation(summary = "获得用户收件地å€åˆ—表") + @Parameter(name = "userId", description = "用户编å·", required = true) + @PreAuthorize("@ss.hasPermission('member:user:query')") + public CommonResult> getAddressList(@RequestParam("userId") Long userId) { + List list = addressService.getAddressList(userId); + return success(AddressConvert.INSTANCE.convertList2(list)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/package-info.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/package-info.java new file mode 100644 index 000000000..652bbb6f1 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.member.controller.admin.address; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/vo/AddressBaseVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/vo/AddressBaseVO.java new file mode 100644 index 000000000..5fa2d1ed9 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/vo/AddressBaseVO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.member.controller.admin.address.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import java.util.*; +import javax.validation.constraints.*; + +/** + * ç”¨æˆ·æ”¶ä»¶åœ°å€ Base VO,æ供给添加ã€ä¿®æ”¹ã€è¯¦ç»†çš„å­ VO 使用 + * å¦‚æžœå­ VO 存在差异的字段,请ä¸è¦æ·»åŠ åˆ°è¿™é‡Œï¼Œå½±å“ Swagger æ–‡æ¡£ç”Ÿæˆ + */ +@Data +public class AddressBaseVO { + + @Schema(description = "收件人å称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @NotNull(message = "收件人å称ä¸èƒ½ä¸ºç©º") + private String name; + + @Schema(description = "手机å·", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "手机å·ä¸èƒ½ä¸ºç©º") + private String mobile; + + @Schema(description = "地区编ç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "15716") + @NotNull(message = "地区编ç ä¸èƒ½ä¸ºç©º") + private Long areaId; + + @Schema(description = "收件详细地å€", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "收件详细地å€ä¸èƒ½ä¸ºç©º") + private String detailAddress; + + @Schema(description = "是å¦é»˜è®¤", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "是å¦é»˜è®¤ä¸èƒ½ä¸ºç©º") + private Boolean defaultStatus; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/vo/AddressRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/vo/AddressRespVO.java new file mode 100644 index 000000000..26a4988af --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/vo/AddressRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.member.controller.admin.address.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.time.LocalDateTime; + +@Schema(description = "管ç†åŽå° - ç”¨æˆ·æ”¶ä»¶åœ°å€ Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AddressRespVO extends AddressBaseVO { + + @Schema(description = "收件地å€ç¼–å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "7380") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/MemberConfigController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/MemberConfigController.java new file mode 100644 index 000000000..730358f9b --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/MemberConfigController.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.member.controller.admin.config; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.member.controller.admin.config.vo.MemberConfigRespVO; +import cn.iocoder.yudao.module.member.controller.admin.config.vo.MemberConfigSaveReqVO; +import cn.iocoder.yudao.module.member.convert.config.MemberConfigConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.config.MemberConfigDO; +import cn.iocoder.yudao.module.member.service.config.MemberConfigService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管ç†åŽå° - 会员设置") +@RestController +@RequestMapping("/member/config") +@Validated +public class MemberConfigController { + + @Resource + private MemberConfigService memberConfigService; + + @PutMapping("/save") + @Operation(summary = "ä¿å­˜ä¼šå‘˜é…ç½®") + @PreAuthorize("@ss.hasPermission('member:config:save')") + public CommonResult saveConfig(@Valid @RequestBody MemberConfigSaveReqVO saveReqVO) { + memberConfigService.saveConfig(saveReqVO); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得会员é…ç½®") + @PreAuthorize("@ss.hasPermission('member:config:query')") + public CommonResult getConfig() { + MemberConfigDO config = memberConfigService.getConfig(); + return success(MemberConfigConvert.INSTANCE.convert(config)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/vo/MemberConfigBaseVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/vo/MemberConfigBaseVO.java new file mode 100644 index 000000000..a9a6b3195 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/vo/MemberConfigBaseVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.member.controller.admin.config.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 会员é…ç½® Base VO,æ供给添加ã€ä¿®æ”¹ã€è¯¦ç»†çš„å­ VO 使用 + * å¦‚æžœå­ VO 存在差异的字段,请ä¸è¦æ·»åŠ åˆ°è¿™é‡Œï¼Œå½±å“ Swagger æ–‡æ¡£ç”Ÿæˆ + */ +@Data +public class MemberConfigBaseVO { + + @Schema(description = "积分抵扣开关", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "积分抵扣开å‘ä¸èƒ½ä¸ºç©º") + private Boolean pointTradeDeductEnable; + + @Schema(description = "积分抵扣,å•ä½ï¼šåˆ†", requiredMode = Schema.RequiredMode.REQUIRED, example = "13506") + @NotNull(message = "积分抵扣ä¸èƒ½ä¸ºç©º") + private Integer pointTradeDeductUnitPrice; + + @Schema(description = "积分抵扣最大值", requiredMode = Schema.RequiredMode.REQUIRED, example = "32428") + @NotNull(message = "积分抵扣最大值ä¸èƒ½ä¸ºç©º") + private Integer pointTradeDeductMaxPrice; + + @Schema(description = "1 元赠é€å¤šå°‘分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "1 元赠é€ç§¯åˆ†ä¸èƒ½ä¸ºç©º") + private Integer pointTradeGivePoint; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/vo/MemberConfigRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/vo/MemberConfigRespVO.java new file mode 100644 index 000000000..04f14f3d1 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/vo/MemberConfigRespVO.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.member.controller.admin.config.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管ç†åŽå° - 会员é…ç½® Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberConfigRespVO extends MemberConfigBaseVO { + + @Schema(description = "自增主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/vo/MemberConfigSaveReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/vo/MemberConfigSaveReqVO.java new file mode 100644 index 000000000..8348f1f3c --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/vo/MemberConfigSaveReqVO.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.member.controller.admin.config.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管ç†åŽå° - 会员é…ç½®ä¿å­˜ Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberConfigSaveReqVO extends MemberConfigBaseVO { +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/MemberGroupController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/MemberGroupController.java new file mode 100644 index 000000000..566e516a1 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/MemberGroupController.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.member.controller.admin.group; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.group.vo.*; +import cn.iocoder.yudao.module.member.convert.group.MemberGroupConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.group.MemberGroupDO; +import cn.iocoder.yudao.module.member.service.group.MemberGroupService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + + +@Tag(name = "管ç†åŽå° - 用户分组") +@RestController +@RequestMapping("/member/group") +@Validated +public class MemberGroupController { + + @Resource + private MemberGroupService groupService; + + @PostMapping("/create") + @Operation(summary = "创建用户分组") + @PreAuthorize("@ss.hasPermission('member:group:create')") + public CommonResult createGroup(@Valid @RequestBody MemberGroupCreateReqVO createReqVO) { + return success(groupService.createGroup(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新用户分组") + @PreAuthorize("@ss.hasPermission('member:group:update')") + public CommonResult updateGroup(@Valid @RequestBody MemberGroupUpdateReqVO updateReqVO) { + groupService.updateGroup(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除用户分组") + @Parameter(name = "id", description = "ç¼–å·", required = true) + @PreAuthorize("@ss.hasPermission('member:group:delete')") + public CommonResult deleteGroup(@RequestParam("id") Long id) { + groupService.deleteGroup(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得用户分组") + @Parameter(name = "id", description = "ç¼–å·", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('member:group:query')") + public CommonResult getGroup(@RequestParam("id") Long id) { + MemberGroupDO group = groupService.getGroup(id); + return success(MemberGroupConvert.INSTANCE.convert(group)); + } + + @GetMapping("/list-all-simple") + @Operation(summary = "获å–会员分组精简信æ¯åˆ—表", description = "åªåŒ…å«è¢«å¼€å¯çš„会员分组,主è¦ç”¨äºŽå‰ç«¯çš„下拉选项") + public CommonResult> getSimpleGroupList() { + // 获用户列表,åªè¦å¼€å¯çŠ¶æ€çš„ + List list = groupService.getEnableGroupList(); + return success(MemberGroupConvert.INSTANCE.convertSimpleList(list)); + } + + @GetMapping("/page") + @Operation(summary = "获得用户分组分页") + @PreAuthorize("@ss.hasPermission('member:group:query')") + public CommonResult> getGroupPage(@Valid MemberGroupPageReqVO pageVO) { + PageResult pageResult = groupService.getGroupPage(pageVO); + return success(MemberGroupConvert.INSTANCE.convertPage(pageResult)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupBaseVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupBaseVO.java new file mode 100644 index 000000000..0519bd968 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupBaseVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.member.controller.admin.group.vo; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 用户分组 Base VO,æ供给添加ã€ä¿®æ”¹ã€è¯¦ç»†çš„å­ VO 使用 + * å¦‚æžœå­ VO 存在差异的字段,请ä¸è¦æ·»åŠ åˆ°è¿™é‡Œï¼Œå½±å“ Swagger æ–‡æ¡£ç”Ÿæˆ + */ +@Data +public class MemberGroupBaseVO { + + @Schema(description = "å称", requiredMode = Schema.RequiredMode.REQUIRED, example = "购物达人") + @NotNull(message = "å称ä¸èƒ½ä¸ºç©º") + private String name; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜") + private String remark; + + @Schema(description = "状æ€", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "状æ€ä¸èƒ½ä¸ºç©º") + @InEnum(CommonStatusEnum.class) + private Integer status; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupCreateReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupCreateReqVO.java new file mode 100644 index 000000000..ef3f83343 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupCreateReqVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.member.controller.admin.group.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管ç†åŽå° - 用户分组创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberGroupCreateReqVO extends MemberGroupBaseVO { + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupPageReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupPageReqVO.java new file mode 100644 index 000000000..ae67d5f6c --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupPageReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.member.controller.admin.group.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管ç†åŽå° - 用户分组分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberGroupPageReqVO extends PageParam { + + @Schema(description = "å称", example = "购物达人") + private String name; + + @Schema(description = "状æ€", example = "1") + private Integer status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupRespVO.java new file mode 100644 index 000000000..97365382a --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.member.controller.admin.group.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +@Schema(description = "管ç†åŽå° - 用户分组 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberGroupRespVO extends MemberGroupBaseVO { + + @Schema(description = "ç¼–å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "20357") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupSimpleRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupSimpleRespVO.java new file mode 100644 index 000000000..ee7d905d0 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupSimpleRespVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.member.controller.admin.group.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +@Schema(description = "管ç†åŽå° - 用户分组 Response VO") +@Data +@ToString(callSuper = true) +public class MemberGroupSimpleRespVO { + + @Schema(description = "ç¼–å·", example = "6103") + private Long id; + + @Schema(description = "等级å称", example = "芋艿") + private String name; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupUpdateReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupUpdateReqVO.java new file mode 100644 index 000000000..75910883b --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/group/vo/MemberGroupUpdateReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.member.controller.admin.group.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管ç†åŽå° - 用户分组更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberGroupUpdateReqVO extends MemberGroupBaseVO { + + @Schema(description = "ç¼–å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "20357") + @NotNull(message = "ç¼–å·ä¸èƒ½ä¸ºç©º") + private Long id; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberExperienceRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberExperienceRecordController.java new file mode 100644 index 000000000..cdbd76046 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberExperienceRecordController.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.member.controller.admin.level; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordRespVO; +import cn.iocoder.yudao.module.member.convert.level.MemberExperienceRecordConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO; +import cn.iocoder.yudao.module.member.service.level.MemberExperienceRecordService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管ç†åŽå° - 会员ç»éªŒè®°å½•") +@RestController +@RequestMapping("/member/experience-record") +@Validated +public class MemberExperienceRecordController { + + @Resource + private MemberExperienceRecordService experienceLogService; + + @GetMapping("/get") + @Operation(summary = "获得会员ç»éªŒè®°å½•") + @Parameter(name = "id", description = "ç¼–å·", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('member:experience-record:query')") + public CommonResult getExperienceRecord(@RequestParam("id") Long id) { + MemberExperienceRecordDO experienceLog = experienceLogService.getExperienceRecord(id); + return success(MemberExperienceRecordConvert.INSTANCE.convert(experienceLog)); + } + + @GetMapping("/page") + @Operation(summary = "获得会员ç»éªŒè®°å½•åˆ†é¡µ") + @PreAuthorize("@ss.hasPermission('member:experience-record:query')") + public CommonResult> getExperienceRecordPage( + @Valid MemberExperienceRecordPageReqVO pageVO) { + PageResult pageResult = experienceLogService.getExperienceRecordPage(pageVO); + return success(MemberExperienceRecordConvert.INSTANCE.convertPage(pageResult)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelController.java new file mode 100644 index 000000000..195800e98 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelController.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.member.controller.admin.level; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.*; +import cn.iocoder.yudao.module.member.convert.level.MemberLevelConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; +import cn.iocoder.yudao.module.member.service.level.MemberLevelService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管ç†åŽå° - 会员等级") +@RestController +@RequestMapping("/member/level") +@Validated +public class MemberLevelController { + + @Resource + private MemberLevelService levelService; + + @PostMapping("/create") + @Operation(summary = "创建会员等级") + @PreAuthorize("@ss.hasPermission('member:level:create')") + public CommonResult createLevel(@Valid @RequestBody MemberLevelCreateReqVO createReqVO) { + return success(levelService.createLevel(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新会员等级") + @PreAuthorize("@ss.hasPermission('member:level:update')") + public CommonResult updateLevel(@Valid @RequestBody MemberLevelUpdateReqVO updateReqVO) { + levelService.updateLevel(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除会员等级") + @Parameter(name = "id", description = "ç¼–å·", required = true) + @PreAuthorize("@ss.hasPermission('member:level:delete')") + public CommonResult deleteLevel(@RequestParam("id") Long id) { + levelService.deleteLevel(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得会员等级") + @Parameter(name = "id", description = "ç¼–å·", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('member:level:query')") + public CommonResult getLevel(@RequestParam("id") Long id) { + MemberLevelDO level = levelService.getLevel(id); + return success(MemberLevelConvert.INSTANCE.convert(level)); + } + + @GetMapping("/list-all-simple") + @Operation(summary = "获å–会员等级精简信æ¯åˆ—表", description = "åªåŒ…å«è¢«å¼€å¯çš„会员等级,主è¦ç”¨äºŽå‰ç«¯çš„下拉选项") + public CommonResult> getSimpleLevelList() { + // 获用户列表,åªè¦å¼€å¯çŠ¶æ€çš„ + List list = levelService.getEnableLevelList(); + // 排åºåŽï¼Œè¿”回给å‰ç«¯ + return success(MemberLevelConvert.INSTANCE.convertSimpleList(list)); + } + + @GetMapping("/list") + @Operation(summary = "获得会员等级列表") + @PreAuthorize("@ss.hasPermission('member:level:query')") + public CommonResult> getLevelList(@Valid MemberLevelListReqVO listReqVO) { + List result = levelService.getLevelList(listReqVO); + return success(MemberLevelConvert.INSTANCE.convertList(result)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java new file mode 100644 index 000000000..b54a54da0 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.member.controller.admin.level; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordRespVO; +import cn.iocoder.yudao.module.member.convert.level.MemberLevelRecordConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO; +import cn.iocoder.yudao.module.member.service.level.MemberLevelRecordService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管ç†åŽå° - 会员等级记录") +@RestController +@RequestMapping("/member/level-record") +@Validated +public class MemberLevelRecordController { + + @Resource + private MemberLevelRecordService levelLogService; + + @GetMapping("/get") + @Operation(summary = "获得会员等级记录") + @Parameter(name = "id", description = "ç¼–å·", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('member:level-record:query')") + public CommonResult getLevelRecord(@RequestParam("id") Long id) { + MemberLevelRecordDO levelLog = levelLogService.getLevelRecord(id); + return success(MemberLevelRecordConvert.INSTANCE.convert(levelLog)); + } + + @GetMapping("/page") + @Operation(summary = "获得会员等级记录分页") + @PreAuthorize("@ss.hasPermission('member:level-record:query')") + public CommonResult> getLevelRecordPage( + @Valid MemberLevelRecordPageReqVO pageVO) { + PageResult pageResult = levelLogService.getLevelRecordPage(pageVO); + return success(MemberLevelRecordConvert.INSTANCE.convertPage(pageResult)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordBaseVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordBaseVO.java new file mode 100644 index 000000000..7c71f8270 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordBaseVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.member.controller.admin.level.vo.experience; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 会员ç»éªŒè®°å½• Base VO,æ供给添加ã€ä¿®æ”¹ã€è¯¦ç»†çš„å­ VO 使用 + * å¦‚æžœå­ VO 存在差异的字段,请ä¸è¦æ·»åŠ åˆ°è¿™é‡Œï¼Œå½±å“ Swagger æ–‡æ¡£ç”Ÿæˆ + */ +@Data +public class MemberExperienceRecordBaseVO { + + @Schema(description = "用户编å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "3638") + @NotNull(message = "用户编å·ä¸èƒ½ä¸ºç©º") + private Long userId; + + @Schema(description = "业务编å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "12164") + @NotNull(message = "业务编å·ä¸èƒ½ä¸ºç©º") + private String bizId; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "业务类型ä¸èƒ½ä¸ºç©º") + private Integer bizType; + + @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "增加ç»éªŒ") + @NotNull(message = "标题ä¸èƒ½ä¸ºç©º") + private String title; + + @Schema(description = "ç»éªŒ", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "ç»éªŒä¸èƒ½ä¸ºç©º") + private Integer experience; + + @Schema(description = "å˜æ›´åŽçš„ç»éªŒ", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") + @NotNull(message = "å˜æ›´åŽçš„ç»éªŒä¸èƒ½ä¸ºç©º") + private Integer totalExperience; + + @Schema(description = "æè¿°", requiredMode = Schema.RequiredMode.REQUIRED, example = "下å•å¢žåŠ  100 ç»éªŒ") + @NotNull(message = "æè¿°ä¸èƒ½ä¸ºç©º") + private String description; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordPageReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordPageReqVO.java new file mode 100644 index 000000000..d18201d7c --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordPageReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.member.controller.admin.level.vo.experience; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管ç†åŽå° - 会员ç»éªŒè®°å½•åˆ†é¡µ Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberExperienceRecordPageReqVO extends PageParam { + + @Schema(description = "用户编å·", example = "3638") + private Long userId; + + @Schema(description = "业务编å·", example = "12164") + private String bizId; + + @Schema(description = "业务类型", example = "1") + private Integer bizType; + + @Schema(description = "标题", example = "增加ç»éªŒ") + private String title; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordRespVO.java new file mode 100644 index 000000000..5e652fcf0 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.member.controller.admin.level.vo.experience; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +@Schema(description = "管ç†åŽå° - 会员ç»éªŒè®°å½• Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberExperienceRecordRespVO extends MemberExperienceRecordBaseVO { + + @Schema(description = "ç¼–å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "19610") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelBaseVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelBaseVO.java new file mode 100644 index 000000000..9580647f8 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelBaseVO.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.member.controller.admin.level.vo.level; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.hibernate.validator.constraints.Range; +import org.hibernate.validator.constraints.URL; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; + +/** + * 会员等级 Base VO,æ供给添加ã€ä¿®æ”¹ã€è¯¦ç»†çš„å­ VO 使用 + * å¦‚æžœå­ VO 存在差异的字段,请ä¸è¦æ·»åŠ åˆ°è¿™é‡Œï¼Œå½±å“ Swagger æ–‡æ¡£ç”Ÿæˆ + */ +@Data +public class MemberLevelBaseVO { + + @Schema(description = "等级å称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @NotBlank(message = "等级å称ä¸èƒ½ä¸ºç©º") + private String name; + + @Schema(description = "å‡çº§ç»éªŒ", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "å‡çº§ç»éªŒä¸èƒ½ä¸ºç©º") + @Positive(message = "å‡çº§ç»éªŒå¿…须大于 0") + private Integer experience; + + @Schema(description = "等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "等级ä¸èƒ½ä¸ºç©º") + @Positive(message = "等级必须大于 0") + private Integer level; + + @Schema(description = "享å—折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "98") + @NotNull(message = "享å—折扣ä¸èƒ½ä¸ºç©º") + @Range(min = 0, max = 100, message = "享å—折扣的范围为 0-100") + private Integer discountPercent; + + @Schema(description = "等级图标", example = "https://www.iocoder.cn/yudao.jpg") + @URL(message = "等级图标必须是 URL æ ¼å¼") + private String icon; + + @Schema(description = "等级背景图", example = "https://www.iocoder.cn/yudao.jpg") + @URL(message = "等级背景图必须是 URL æ ¼å¼") + private String backgroundUrl; + + @Schema(description = "状æ€", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "状æ€ä¸èƒ½ä¸ºç©º") + @InEnum(CommonStatusEnum.class) + private Integer status; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelCreateReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelCreateReqVO.java new file mode 100644 index 000000000..f51a7d967 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelCreateReqVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.member.controller.admin.level.vo.level; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管ç†åŽå° - 会员等级创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberLevelCreateReqVO extends MemberLevelBaseVO { + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelListReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelListReqVO.java new file mode 100644 index 000000000..348e78e8e --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelListReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.member.controller.admin.level.vo.level; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +@Schema(description = "管ç†åŽå° - 会员等级列表筛选 Request VO") +@Data +@ToString(callSuper = true) +public class MemberLevelListReqVO { + + @Schema(description = "等级å称", example = "芋艿") + private String name; + + @Schema(description = "状æ€", example = "1") + private Integer status; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelRespVO.java new file mode 100644 index 000000000..df91a814f --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.member.controller.admin.level.vo.level; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +@Schema(description = "管ç†åŽå° - 会员等级 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberLevelRespVO extends MemberLevelBaseVO { + + @Schema(description = "ç¼–å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "6103") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelSimpleRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelSimpleRespVO.java new file mode 100644 index 000000000..96c515c8b --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelSimpleRespVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.member.controller.admin.level.vo.level; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +@Schema(description = "管ç†åŽå° - 会员等级 Response VO") +@Data +@ToString(callSuper = true) +public class MemberLevelSimpleRespVO { + + @Schema(description = "ç¼–å·", example = "6103") + private Long id; + + @Schema(description = "等级å称", example = "芋艿") + private String name; + + @Schema(description = "等级图标", example = "https://www.iocoder.cn/yudao.jpg") + private String icon; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelUpdateReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelUpdateReqVO.java new file mode 100644 index 000000000..83ad768de --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelUpdateReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.member.controller.admin.level.vo.level; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管ç†åŽå° - 会员等级更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberLevelUpdateReqVO extends MemberLevelBaseVO { + + @Schema(description = "ç¼–å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "6103") + @NotNull(message = "ç¼–å·ä¸èƒ½ä¸ºç©º") + private Long id; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordBaseVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordBaseVO.java new file mode 100644 index 000000000..99df53648 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordBaseVO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.member.controller.admin.level.vo.record; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 会员等级记录 Base VO,æ供给添加ã€ä¿®æ”¹ã€è¯¦ç»†çš„å­ VO 使用 + * å¦‚æžœå­ VO 存在差异的字段,请ä¸è¦æ·»åŠ åˆ°è¿™é‡Œï¼Œå½±å“ Swagger æ–‡æ¡£ç”Ÿæˆ + */ +@Data +public class MemberLevelRecordBaseVO { + + @Schema(description = "用户编å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "25923") + @NotNull(message = "用户编å·ä¸èƒ½ä¸ºç©º") + private Long userId; + + @Schema(description = "等级编å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "25985") + @NotNull(message = "等级编å·ä¸èƒ½ä¸ºç©º") + private Long levelId; + + @Schema(description = "会员等级", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "会员等级ä¸èƒ½ä¸ºç©º") + private Integer level; + + @Schema(description = "享å—折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "13319") + @NotNull(message = "享å—折扣ä¸èƒ½ä¸ºç©º") + private Integer discountPercent; + + @Schema(description = "å‡çº§ç»éªŒ", requiredMode = Schema.RequiredMode.REQUIRED, example = "13319") + @NotNull(message = "å‡çº§ç»éªŒä¸èƒ½ä¸ºç©º") + private Integer experience; + + @Schema(description = "会员此时的ç»éªŒ", requiredMode = Schema.RequiredMode.REQUIRED, example = "13319") + @NotNull(message = "会员此时的ç»éªŒä¸èƒ½ä¸ºç©º") + private Integer userExperience; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "推广需è¦") + @NotNull(message = "备注ä¸èƒ½ä¸ºç©º") + private String remark; + + @Schema(description = "æè¿°", requiredMode = Schema.RequiredMode.REQUIRED, example = "å‡çº§ä¸ºé‡‘牌会员") + @NotNull(message = "æè¿°ä¸èƒ½ä¸ºç©º") + private String description; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordPageReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordPageReqVO.java new file mode 100644 index 000000000..2590cfba6 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordPageReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.member.controller.admin.level.vo.record; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管ç†åŽå° - 会员等级记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberLevelRecordPageReqVO extends PageParam { + + @Schema(description = "用户编å·", example = "25923") + private Long userId; + + @Schema(description = "等级编å·", example = "25985") + private Long levelId; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordRespVO.java new file mode 100644 index 000000000..caf98ea4e --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.member.controller.admin.level.vo.record; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +@Schema(description = "管ç†åŽå° - 会员等级记录 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberLevelRecordRespVO extends MemberLevelRecordBaseVO { + + @Schema(description = "ç¼–å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "8741") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/MemberPointRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/MemberPointRecordController.java new file mode 100644 index 000000000..4d6ec352b --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/MemberPointRecordController.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.member.controller.admin.point; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordRespVO; +import cn.iocoder.yudao.module.member.convert.point.MemberPointRecordConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO; +import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管ç†åŽå° - 签到记录") +@RestController +@RequestMapping("/member/point/record") +@Validated +public class MemberPointRecordController { + + @Resource + private MemberPointRecordService pointRecordService; + + @Resource + private MemberUserApi memberUserApi; + + @GetMapping("/page") + @Operation(summary = "获得用户积分记录分页") + @PreAuthorize("@ss.hasPermission('point:record:query')") + public CommonResult> getPointRecordPage(@Valid MemberPointRecordPageReqVO pageVO) { + // 执行分页查询 + PageResult pageResult = pointRecordService.getPointRecordPage(pageVO); + if (CollectionUtils.isEmpty(pageResult.getList())) { + return success(PageResult.empty(pageResult.getTotal())); + } + + // 拼接结果返回 + List users = memberUserApi.getUserList( + convertSet(pageResult.getList(), MemberPointRecordDO::getUserId)); + return success(MemberPointRecordConvert.INSTANCE.convertPage(pageResult, users)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/recrod/MemberPointRecordPageReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/recrod/MemberPointRecordPageReqVO.java new file mode 100644 index 000000000..63cc80006 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/recrod/MemberPointRecordPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管ç†åŽå° - 用户积分记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberPointRecordPageReqVO extends PageParam { + + @Schema(description = "用户昵称", example = "张三") + private String nickname; + + @Schema(description = "用户编å·", example = "123") + private Long userId; + + @Schema(description = "业务类型", example = "1") + private Integer bizType; + + @Schema(description = "积分标题", example = "呵呵") + private String title; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/recrod/MemberPointRecordRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/recrod/MemberPointRecordRespVO.java new file mode 100644 index 000000000..6714aa87f --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/recrod/MemberPointRecordRespVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管ç†åŽå° - 用户积分记录 Response VO") +@Data +public class MemberPointRecordRespVO { + + @Schema(description = "自增主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "31457") + private Long id; + + @Schema(description = "用户编å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long userId; + + @Schema(description = "昵称", example = "张三") + private String nickname; + + @Schema(description = "业务编ç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "22706") + private String bizId; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer bizType; + + @Schema(description = "积分标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜") + private String title; + + @Schema(description = "积分æè¿°", example = "你猜") + private String description; + + @Schema(description = "积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Integer point; + + @Schema(description = "å˜åŠ¨åŽçš„积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") + private Integer totalPoint; + + @Schema(description = "å‘生时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/MemberSignInConfigController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/MemberSignInConfigController.java new file mode 100644 index 000000000..65bfe44c2 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/MemberSignInConfigController.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.member.controller.admin.signin; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.config.MemberSignInConfigCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.config.MemberSignInConfigRespVO; +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.config.MemberSignInConfigUpdateReqVO; +import cn.iocoder.yudao.module.member.convert.signin.MemberSignInConfigConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO; +import cn.iocoder.yudao.module.member.service.signin.MemberSignInConfigService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +// TODO 芋艿:url +@Tag(name = "管ç†åŽå° - 签到规则") +@RestController +@RequestMapping("/member/sign-in/config") +@Validated +public class MemberSignInConfigController { + + @Resource + private MemberSignInConfigService signInConfigService; + + @PostMapping("/create") + @Operation(summary = "创建签到规则") + @PreAuthorize("@ss.hasPermission('point:sign-in-config:create')") + public CommonResult createSignInConfig(@Valid @RequestBody MemberSignInConfigCreateReqVO createReqVO) { + return success(signInConfigService.createSignInConfig(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新签到规则") + @PreAuthorize("@ss.hasPermission('point:sign-in-config:update')") + public CommonResult updateSignInConfig(@Valid @RequestBody MemberSignInConfigUpdateReqVO updateReqVO) { + signInConfigService.updateSignInConfig(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除签到规则") + @Parameter(name = "id", description = "ç¼–å·", required = true) + @PreAuthorize("@ss.hasPermission('point:sign-in-config:delete')") + public CommonResult deleteSignInConfig(@RequestParam("id") Long id) { + signInConfigService.deleteSignInConfig(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得签到规则") + @Parameter(name = "id", description = "ç¼–å·", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('point:sign-in-config:query')") + public CommonResult getSignInConfig(@RequestParam("id") Long id) { + MemberSignInConfigDO signInConfig = signInConfigService.getSignInConfig(id); + return success(MemberSignInConfigConvert.INSTANCE.convert(signInConfig)); + } + + @GetMapping("/list") + @Operation(summary = "获得签到规则列表") + @PreAuthorize("@ss.hasPermission('point:sign-in-config:query')") + public CommonResult> getSignInConfigList() { + List list = signInConfigService.getSignInConfigList(); + return success(MemberSignInConfigConvert.INSTANCE.convertList(list)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/MemberSignInRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/MemberSignInRecordController.java new file mode 100644 index 000000000..83b8f9b3f --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/MemberSignInRecordController.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.member.controller.admin.signin; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordRespVO; +import cn.iocoder.yudao.module.member.convert.signin.MemberSignInRecordConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO; +import cn.iocoder.yudao.module.member.service.signin.MemberSignInRecordService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管ç†åŽå° - 签到记录") +@RestController +@RequestMapping("/member/sign-in/record") +@Validated +public class MemberSignInRecordController { + + @Resource + private MemberSignInRecordService signInRecordService; + + @Resource + private MemberUserApi memberUserApi; + + @GetMapping("/page") + @Operation(summary = "获得签到记录分页") + @PreAuthorize("@ss.hasPermission('point:sign-in-record:query')") + public CommonResult> getSignInRecordPage(@Valid MemberSignInRecordPageReqVO pageVO) { + // 执行分页查询 + PageResult pageResult = signInRecordService.getSignInRecordPage(pageVO); + if (CollectionUtils.isEmpty(pageResult.getList())) { + return success(PageResult.empty(pageResult.getTotal())); + } + + // 拼接结果返回 + List users = memberUserApi.getUserList( + convertSet(pageResult.getList(), MemberSignInRecordDO::getUserId)); + return success(MemberSignInRecordConvert.INSTANCE.convertPage(pageResult, users)); + } +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigBaseVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigBaseVO.java new file mode 100644 index 000000000..2ddeeb9be --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigBaseVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.member.controller.admin.signin.vo.config; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.AssertTrue; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.PositiveOrZero; + +/** + * 签到规则 Base VO,æ供给添加ã€ä¿®æ”¹ã€è¯¦ç»†çš„å­ VO 使用 + * å¦‚æžœå­ VO 存在差异的字段,请ä¸è¦æ·»åŠ åˆ°è¿™é‡Œï¼Œå½±å“ Swagger æ–‡æ¡£ç”Ÿæˆ + */ +@Data +public class MemberSignInConfigBaseVO { + + @Schema(description = "签到第 x 天", requiredMode = Schema.RequiredMode.REQUIRED, example = "7") + @NotNull(message = "签到天数ä¸èƒ½ä¸ºç©º") + private Integer day; + + @Schema(description = "奖励积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "奖励积分ä¸èƒ½ä¸ºç©º") + @PositiveOrZero(message = "奖励积分ä¸èƒ½å°äºŽ 0") + private Integer point; + + @Schema(description = "奖励ç»éªŒ", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "奖励ç»éªŒä¸èƒ½ä¸ºç©º") + @PositiveOrZero(message = "奖励ç»éªŒä¸èƒ½å°äºŽ 0") + private Integer experience; + + @Schema(description = "状æ€", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "状æ€ä¸èƒ½ä¸ºç©º") + @InEnum(CommonStatusEnum.class) + private Integer status; + + @AssertTrue(message = "签到奖励积分和ç»éªŒä¸èƒ½åŒæ—¶ä¸ºç©º") + @JsonIgnore + public boolean isConfigAward() { + return ObjUtil.notEqual(point, 0) || ObjUtil.notEqual(experience, 0); + } +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigCreateReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigCreateReqVO.java new file mode 100644 index 000000000..7ca03fa93 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigCreateReqVO.java @@ -0,0 +1,12 @@ +package cn.iocoder.yudao.module.member.controller.admin.signin.vo.config; + +import lombok.*; +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(description = "管ç†åŽå° - 签到规则创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberSignInConfigCreateReqVO extends MemberSignInConfigBaseVO { + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigRespVO.java new file mode 100644 index 000000000..8d423b25c --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.member.controller.admin.signin.vo.config; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.time.LocalDateTime; + +@Schema(description = "管ç†åŽå° - 签到规则 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberSignInConfigRespVO extends MemberSignInConfigBaseVO { + + @Schema(description = "自增主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "20937") + private Integer id; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigUpdateReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigUpdateReqVO.java new file mode 100644 index 000000000..89b6de15c --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigUpdateReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.member.controller.admin.signin.vo.config; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import javax.validation.constraints.*; + +@Schema(description = "管ç†åŽå° - 签到规则更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberSignInConfigUpdateReqVO extends MemberSignInConfigBaseVO { + + @Schema(description = "规则自增主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "13653") + @NotNull(message = "规则自增主键ä¸èƒ½ä¸ºç©º") + private Long id; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/record/MemberSignInRecordPageReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/record/MemberSignInRecordPageReqVO.java new file mode 100644 index 000000000..b46712b6e --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/record/MemberSignInRecordPageReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.member.controller.admin.signin.vo.record; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管ç†åŽå° - 签到记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberSignInRecordPageReqVO extends PageParam { + + @Schema(description = "签到用户", example = "土豆") + private String nickname; + + @Schema(description = "第几天签到", example = "10") + private Integer day; + + @Schema(description = "用户编å·", example = "123") + private Long userId; + + @Schema(description = "签到时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/record/MemberSignInRecordRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/record/MemberSignInRecordRespVO.java new file mode 100644 index 000000000..b5755ba53 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/record/MemberSignInRecordRespVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.member.controller.admin.signin.vo.record; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管ç†åŽå° - 签到记录 Response VO") +@Data +public class MemberSignInRecordRespVO { + + @Schema(description = "签到自增 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "11903") + private Long id; + + @Schema(description = "签到用户", requiredMode = Schema.RequiredMode.REQUIRED, example = "6507") + private Long userId; + + @Schema(description = "昵称", example = "张三") + private String nickname; + + @Schema(description = "第几天签到", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer day; + + @Schema(description = "签到的积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer point; + + @Schema(description = "签到时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/MemberTagController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/MemberTagController.java new file mode 100644 index 000000000..34f3c20cc --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/MemberTagController.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.member.controller.admin.tag; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagRespVO; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagUpdateReqVO; +import cn.iocoder.yudao.module.member.convert.tag.MemberTagConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO; +import cn.iocoder.yudao.module.member.service.tag.MemberTagService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管ç†åŽå° - 会员标签") +@RestController +@RequestMapping("/member/tag") +@Validated +public class MemberTagController { + + @Resource + private MemberTagService tagService; + + @PostMapping("/create") + @Operation(summary = "创建会员标签") + @PreAuthorize("@ss.hasPermission('member:tag:create')") + public CommonResult createTag(@Valid @RequestBody MemberTagCreateReqVO createReqVO) { + return success(tagService.createTag(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新会员标签") + @PreAuthorize("@ss.hasPermission('member:tag:update')") + public CommonResult updateTag(@Valid @RequestBody MemberTagUpdateReqVO updateReqVO) { + tagService.updateTag(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除会员标签") + @Parameter(name = "id", description = "ç¼–å·", required = true) + @PreAuthorize("@ss.hasPermission('member:tag:delete')") + public CommonResult deleteTag(@RequestParam("id") Long id) { + tagService.deleteTag(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得会员标签") + @Parameter(name = "id", description = "ç¼–å·", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('member:tag:query')") + public CommonResult getMemberTag(@RequestParam("id") Long id) { + MemberTagDO tag = tagService.getTag(id); + return success(MemberTagConvert.INSTANCE.convert(tag)); + } + + @GetMapping("/list-all-simple") + @Operation(summary = "获å–会员标签精简信æ¯åˆ—表", description = "åªåŒ…å«è¢«å¼€å¯çš„会员标签,主è¦ç”¨äºŽå‰ç«¯çš„下拉选项") + public CommonResult> getSimpleTagList() { + // 获用户列表,åªè¦å¼€å¯çŠ¶æ€çš„ + List list = tagService.getTagList(); + // 排åºåŽï¼Œè¿”回给å‰ç«¯ + return success(MemberTagConvert.INSTANCE.convertList(list)); + } + + @GetMapping("/list") + @Operation(summary = "获得会员标签列表") + @Parameter(name = "ids", description = "ç¼–å·åˆ—表", required = true, example = "1024,2048") + @PreAuthorize("@ss.hasPermission('member:tag:query')") + public CommonResult> getMemberTagList(@RequestParam("ids") Collection ids) { + List list = tagService.getTagList(ids); + return success(MemberTagConvert.INSTANCE.convertList(list)); + } + + @GetMapping("/page") + @Operation(summary = "获得会员标签分页") + @PreAuthorize("@ss.hasPermission('member:tag:query')") + public CommonResult> getTagPage(@Valid MemberTagPageReqVO pageVO) { + PageResult pageResult = tagService.getTagPage(pageVO); + return success(MemberTagConvert.INSTANCE.convertPage(pageResult)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagBaseVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagBaseVO.java new file mode 100644 index 000000000..bc0efea68 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagBaseVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.member.controller.admin.tag.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 会员标签 Base VO,æ供给添加ã€ä¿®æ”¹ã€è¯¦ç»†çš„å­ VO 使用 + * å¦‚æžœå­ VO 存在差异的字段,请ä¸è¦æ·»åŠ åˆ°è¿™é‡Œï¼Œå½±å“ Swagger æ–‡æ¡£ç”Ÿæˆ + */ +@Data +public class MemberTagBaseVO { + + @Schema(description = "标签å称", requiredMode = Schema.RequiredMode.REQUIRED, example = "æŽå››") + @NotNull(message = "标签å称ä¸èƒ½ä¸ºç©º") + private String name; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagCreateReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagCreateReqVO.java new file mode 100644 index 000000000..b61f26bb2 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagCreateReqVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.member.controller.admin.tag.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管ç†åŽå° - 会员标签创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberTagCreateReqVO extends MemberTagBaseVO { + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagPageReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagPageReqVO.java new file mode 100644 index 000000000..99f59b068 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.member.controller.admin.tag.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管ç†åŽå° - 会员标签分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberTagPageReqVO extends PageParam { + + @Schema(description = "标签å称", example = "æŽå››") + private String name; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagRespVO.java new file mode 100644 index 000000000..2c21f53e3 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.member.controller.admin.tag.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +@Schema(description = "管ç†åŽå° - 会员标签 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberTagRespVO extends MemberTagBaseVO { + + @Schema(description = "ç¼–å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "907") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagUpdateReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagUpdateReqVO.java new file mode 100644 index 000000000..2fe0e614d --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/tag/vo/MemberTagUpdateReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.member.controller.admin.tag.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管ç†åŽå° - 会员标签更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberTagUpdateReqVO extends MemberTagBaseVO { + + @Schema(description = "ç¼–å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "907") + @NotNull(message = "ç¼–å·ä¸èƒ½ä¸ºç©º") + private Long id; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/MemberUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/MemberUserController.java new file mode 100644 index 000000000..b382c1caf --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/MemberUserController.java @@ -0,0 +1,121 @@ +package cn.iocoder.yudao.module.member.controller.admin.user; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.user.vo.*; +import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.group.MemberGroupDO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; +import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; +import cn.iocoder.yudao.module.member.service.group.MemberGroupService; +import cn.iocoder.yudao.module.member.service.level.MemberLevelService; +import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService; +import cn.iocoder.yudao.module.member.service.tag.MemberTagService; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; + +@Tag(name = "管ç†åŽå° - 会员用户") +@RestController +@RequestMapping("/member/user") +@Validated +public class MemberUserController { + + @Resource + private MemberUserService memberUserService; + @Resource + private MemberTagService memberTagService; + @Resource + private MemberLevelService memberLevelService; + @Resource + private MemberGroupService memberGroupService; + @Resource + private MemberPointRecordService memberPointRecordService; + + @PutMapping("/update") + @Operation(summary = "更新会员用户") + @PreAuthorize("@ss.hasPermission('member:user:update')") + public CommonResult updateUser(@Valid @RequestBody MemberUserUpdateReqVO updateReqVO) { + memberUserService.updateUser(updateReqVO); + return success(true); + } + + @PutMapping("/update-level") + @Operation(summary = "更新会员用户等级") + @PreAuthorize("@ss.hasPermission('member:user:update-level')") + public CommonResult updateUserLevel(@Valid @RequestBody MemberUserUpdateLevelReqVO updateReqVO) { + memberLevelService.updateUserLevel(updateReqVO); + return success(true); + } + + @PutMapping("/update-point") + @Operation(summary = "更新会员用户积分") + @PreAuthorize("@ss.hasPermission('member:user:update-point')") + public CommonResult updateUserPoint(@Valid @RequestBody MemberUserUpdatePointReqVO updateReqVO) { + memberPointRecordService.createPointRecord(updateReqVO.getId(), updateReqVO.getPoint(), + MemberPointBizTypeEnum.ADMIN, String.valueOf(getLoginUserId())); + return success(true); + } + + @PutMapping("/update-balance") + @Operation(summary = "更新会员用户余é¢") + @PreAuthorize("@ss.hasPermission('member:user:update-balance')") + public CommonResult updateUserBalance(@Valid @RequestBody Long id) { + // todo @jason:增加一个ã€ä¿®æ”¹ä½™é¢ã€‘ + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得会员用户") + @Parameter(name = "id", description = "ç¼–å·", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('member:user:query')") + public CommonResult getUser(@RequestParam("id") Long id) { + MemberUserDO user = memberUserService.getUser(id); + return success(MemberUserConvert.INSTANCE.convert03(user)); + } + + @GetMapping("/page") + @Operation(summary = "获得会员用户分页") + @PreAuthorize("@ss.hasPermission('member:user:query')") + public CommonResult> getUserPage(@Valid MemberUserPageReqVO pageVO) { + PageResult pageResult = memberUserService.getUserPage(pageVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty()); + } + + // 处ç†ç”¨æˆ·æ ‡ç­¾è¿”显 + Set tagIds = pageResult.getList().stream() + .map(MemberUserDO::getTagIds) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .collect(Collectors.toSet()); + List tags = memberTagService.getTagList(tagIds); + // 处ç†ç”¨æˆ·çº§åˆ«è¿”显 + List levels = memberLevelService.getLevelList( + convertSet(pageResult.getList(), MemberUserDO::getLevelId)); + // 处ç†ç”¨æˆ·åˆ†ç»„返显 + List groups = memberGroupService.getGroupList( + convertSet(pageResult.getList(), MemberUserDO::getGroupId)); + return success(MemberUserConvert.INSTANCE.convertPage(pageResult, tags, levels, groups)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserBaseVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserBaseVO.java new file mode 100644 index 000000000..e20963e5e --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserBaseVO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.member.controller.admin.user.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.hibernate.validator.constraints.URL; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; + +/** + * 会员用户 Base VO,æ供给添加ã€ä¿®æ”¹ã€è¯¦ç»†çš„å­ VO 使用 + * å¦‚æžœå­ VO 存在差异的字段,请ä¸è¦æ·»åŠ åˆ°è¿™é‡Œï¼Œå½±å“ Swagger æ–‡æ¡£ç”Ÿæˆ + */ +@Data +public class MemberUserBaseVO { + + @Schema(description = "手机å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300") + @NotNull(message = "手机å·ä¸èƒ½ä¸ºç©º") + private String mobile; + + @Schema(description = "状æ€", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "状æ€ä¸èƒ½ä¸ºç©º") + private Byte status; + + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "æŽå››") + @NotNull(message = "用户昵称ä¸èƒ½ä¸ºç©º") + private String nickname; + + @Schema(description = "头åƒ", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/x.png") + @URL(message = "头åƒå¿…须是 URL æ ¼å¼") + private String avatar; + + @Schema(description = "用户昵称", example = "æŽå››") + private String name; + + @Schema(description = "用户性别", example = "1") + private Byte sex; + + @Schema(description = "所在地编å·", example = "4371") + private Long areaId; + + @Schema(description = "所在地全程", example = "上海上海市普陀区") + private String areaName; + + @Schema(description = "出生日期", example = "2023-03-12") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + private LocalDateTime birthday; + + @Schema(description = "会员备注", example = "我是å°å¤‡æ³¨") + private String mark; + + @Schema(description = "会员标签", example = "[1, 2]") + private List tagIds; + + @Schema(description = "会员等级编å·", example = "1") + private Long levelId; + + @Schema(description = "用户分组编å·", example = "1") + private Long groupId; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserPageReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserPageReqVO.java new file mode 100644 index 000000000..abb94285e --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserPageReqVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.member.controller.admin.user.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管ç†åŽå° - 会员用户分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberUserPageReqVO extends PageParam { + + @Schema(description = "手机å·", example = "15601691300") + private String mobile; + + @Schema(description = "用户昵称", example = "æŽå››") + private String nickname; + + @Schema(description = "最åŽç™»å½•æ—¶é—´") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] loginDate; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + + @Schema(description = "会员标签编å·åˆ—表", example = "[1, 2]") + private List tagIds; + + @Schema(description = "会员等级编å·", example = "1") + private Long levelId; + + @Schema(description = "用户分组编å·", example = "1") + private Long groupId; + + // TODO 芋艿:注册用户类型; + + // TODO 芋艿:登录用户类型; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserRespVO.java new file mode 100644 index 000000000..1cd228335 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserRespVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.member.controller.admin.user.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管ç†åŽå° - 会员用户 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberUserRespVO extends MemberUserBaseVO { + + @Schema(description = "ç¼–å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "23788") + private Long id; + + @Schema(description = "注册 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") + private String registerIp; + + @Schema(description = "最åŽç™»å½•IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") + private String loginIp; + + @Schema(description = "最åŽç™»å½•æ—¶é—´", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime loginDate; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + + // ========== å…¶å®ƒä¿¡æ¯ ========== + + @Schema(description = "积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Integer point; + + @Schema(description = "总积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000") + private Integer totalPoint; + + @Schema(description = "会员标签", example = "[红色, å¿«ä¹]") + private List tagNames; + + @Schema(description = "会员等级", example = "黄金会员") + private String levelName; + + @Schema(description = "用户分组", example = "购物达人") + private String groupName; + + @Schema(description = "用户ç»éªŒå€¼", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") + private Integer experience; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdateLevelReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdateLevelReqVO.java new file mode 100644 index 000000000..dba48f670 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdateLevelReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.member.controller.admin.user.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +@Schema(description = "管ç†åŽå° - 用户修改等级 Request VO") +@Data +@ToString(callSuper = true) +public class MemberUserUpdateLevelReqVO { + + @Schema(description = "用户编å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "23788") + @NotNull(message = "用户编å·ä¸èƒ½ä¸ºç©º") + private Long id; + + /** + * å–消用户等级时,值为空 + */ + @Schema(description = "用户等级编å·", example = "1") + private Long levelId; + + @Schema(description = "修改原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "推广需è¦") + @NotBlank(message = "修改原因ä¸èƒ½ä¸ºç©º") + private String reason; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdatePointReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdatePointReqVO.java new file mode 100644 index 000000000..a072c0726 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdatePointReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.member.controller.admin.user.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管ç†åŽå° - 用户修改积分 Request VO") +@Data +@ToString(callSuper = true) +public class MemberUserUpdatePointReqVO { + + @Schema(description = "用户编å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "23788") + @NotNull(message = "用户编å·ä¸èƒ½ä¸ºç©º") + private Long id; + + @Schema(description = "å˜åŠ¨ç§¯åˆ†ï¼Œæ­£æ•°ä¸ºå¢žåŠ ï¼Œè´Ÿæ•°ä¸ºå‡å°‘", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "å˜åŠ¨ç§¯åˆ†ä¸èƒ½ä¸ºç©º") + private Integer point; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdateReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdateReqVO.java new file mode 100644 index 000000000..c6a92758d --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdateReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.member.controller.admin.user.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管ç†åŽå° - 会员用户更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberUserUpdateReqVO extends MemberUserBaseVO { + + @Schema(description = "ç¼–å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "23788") + @NotNull(message = "ç¼–å·ä¸èƒ½ä¸ºç©º") + private Long id; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.http b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.http new file mode 100644 index 000000000..6bae7c7eb --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.http @@ -0,0 +1,54 @@ +### 请求 /create æŽ¥å£ => æˆåŠŸ +POST {{appApi}}//member/address/create +Content-Type: application/json +tenant-id: {{appTenentId}} +Authorization: Bearer {{appToken}} + +{ + "name": "yunai", + "mobile": "15601691300", + "areaId": "610632", + "postCode": "200000", + "detailAddress": "芋é“æºç  233 å· 666 室", + "defaulted": true +} + +### 请求 /update æŽ¥å£ => æˆåŠŸ +PUT {{appApi}}//member/address/update +Content-Type: application/json +tenant-id: {{appTenentId}} +Authorization: Bearer {{appToken}} + +{ + "id": "1", + "name": "yunai888", + "mobile": "15601691300", + "areaId": "610632", + "postCode": "200000", + "detailAddress": "芋é“æºç  233 å· 666 室", + "defaulted": false +} + +### 请求 /delete æŽ¥å£ => æˆåŠŸ +DELETE {{appApi}}//member/address/delete?id=2 +Content-Type: application/json +tenant-id: {{appTenentId}} +Authorization: Bearer {{appToken}} + +### 请求 /get æŽ¥å£ => æˆåŠŸ +GET {{appApi}}//member/address/get?id=1 +Content-Type: application/json +tenant-id: {{appTenentId}} +Authorization: Bearer {{appToken}} + +### 请求 /get-default æŽ¥å£ => æˆåŠŸ +GET {{appApi}}//member/address/get-default +Content-Type: application/json +tenant-id: {{appTenentId}} +Authorization: Bearer {{appToken}} + +### 请求 /list æŽ¥å£ => æˆåŠŸ +GET {{appApi}}//member/address/list +Content-Type: application/json +tenant-id: {{appTenentId}} +Authorization: Bearer {{appToken}} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java new file mode 100644 index 000000000..7ba55c3bd --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.member.controller.app.address; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressRespVO; +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; +import cn.iocoder.yudao.module.member.convert.address.AddressConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; +import cn.iocoder.yudao.module.member.service.address.AddressService; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "用户 APP - 用户收件地å€") +@RestController +@RequestMapping("/member/address") +@Validated +public class AppAddressController { + + @Resource + private AddressService addressService; + + @PostMapping("/create") + @Operation(summary = "创建用户收件地å€") + @PreAuthenticated + public CommonResult createAddress(@Valid @RequestBody AppAddressCreateReqVO createReqVO) { + return success(addressService.createAddress(getLoginUserId(), createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新用户收件地å€") + @PreAuthenticated + public CommonResult updateAddress(@Valid @RequestBody AppAddressUpdateReqVO updateReqVO) { + addressService.updateAddress(getLoginUserId(), updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除用户收件地å€") + @Parameter(name = "id", description = "ç¼–å·", required = true) + @PreAuthenticated + public CommonResult deleteAddress(@RequestParam("id") Long id) { + addressService.deleteAddress(getLoginUserId(), id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得用户收件地å€") + @Parameter(name = "id", description = "ç¼–å·", required = true, example = "1024") + @PreAuthenticated + public CommonResult getAddress(@RequestParam("id") Long id) { + MemberAddressDO address = addressService.getAddress(getLoginUserId(), id); + return success(AddressConvert.INSTANCE.convert(address)); + } + + @GetMapping("/get-default") + @Operation(summary = "获得默认的用户收件地å€") + @PreAuthenticated + public CommonResult getDefaultUserAddress() { + MemberAddressDO address = addressService.getDefaultUserAddress(getLoginUserId()); + return success(AddressConvert.INSTANCE.convert(address)); + } + + @GetMapping("/list") + @Operation(summary = "获得用户收件地å€åˆ—表") + @PreAuthenticated + public CommonResult> getAddressList() { + List list = addressService.getAddressList(getLoginUserId()); + return success(AddressConvert.INSTANCE.convertList(list)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressBaseVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressBaseVO.java new file mode 100644 index 000000000..076ce36ff --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressBaseVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.member.controller.app.address.vo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +// TODO 芋艿:example 缺失 +/** +* ç”¨æˆ·æ”¶ä»¶åœ°å€ Base VO,æ供给添加ã€ä¿®æ”¹ã€è¯¦ç»†çš„å­ VO 使用 +* å¦‚æžœå­ VO 存在差异的字段,请ä¸è¦æ·»åŠ åˆ°è¿™é‡Œï¼Œå½±å“ Swagger æ–‡æ¡£ç”Ÿæˆ +*/ +@Data +public class AppAddressBaseVO { + + @Schema(description = "收件人å称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "收件人å称ä¸èƒ½ä¸ºç©º") + private String name; + + @Schema(description = "手机å·", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "手机å·ä¸èƒ½ä¸ºç©º") + private String mobile; + + @Schema(description = "地区编å·", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "地区编å·ä¸èƒ½ä¸ºç©º") + private Long areaId; + + @Schema(description = "收件详细地å€", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "收件详细地å€ä¸èƒ½ä¸ºç©º") + private String detailAddress; + + @Schema(description = "是å¦é»˜è®¤åœ°å€", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "是å¦é»˜è®¤åœ°å€ä¸èƒ½ä¸ºç©º") + private Boolean defaultStatus; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressCreateReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressCreateReqVO.java new file mode 100644 index 000000000..c92687f27 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressCreateReqVO.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.module.member.controller.app.address.vo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@Schema(description = "用户 APP - 用户收件地å€åˆ›å»º Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AppAddressCreateReqVO extends AppAddressBaseVO { + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressRespVO.java new file mode 100644 index 000000000..d3e2f9ffd --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressRespVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.member.controller.app.address.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "用户 APP - ç”¨æˆ·æ”¶ä»¶åœ°å€ Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AppAddressRespVO extends AppAddressBaseVO { + + @Schema(description = "ç¼–å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "地区åå­—", requiredMode = Schema.RequiredMode.REQUIRED, example = "上海上海市普陀区") + private String areaName; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressUpdateReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressUpdateReqVO.java new file mode 100644 index 000000000..19b58d807 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressUpdateReqVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.member.controller.app.address.vo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import javax.validation.constraints.*; + +@Schema(description = "用户 APP - 用户收件地å€æ›´æ–° Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AppAddressUpdateReqVO extends AppAddressBaseVO { + + @Schema(description = "ç¼–å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "ç¼–å·ä¸èƒ½ä¸ºç©º") + private Long id; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http new file mode 100644 index 000000000..998c70c21 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http @@ -0,0 +1,66 @@ +### 请求 /login æŽ¥å£ => æˆåŠŸ +POST {{appApi}}/member/auth/login +Content-Type: application/json +tenant-id: {{appTenentId}} + +{ + "mobile": "15601691300", + "password": "admin123" +} + +### 请求 /send-sms-code æŽ¥å£ => æˆåŠŸ +POST {{appApi}}/member/auth/send-sms-code +Content-Type: application/json +tenant-id: {{appTenentId}} + +{ + "mobile": "15601691399", + "scene": 1 +} + +### 请求 /sms-login æŽ¥å£ => æˆåŠŸ +POST {{appApi}}/member/auth/sms-login +Content-Type: application/json +tenant-id: {{appTenentId}} + +{ + "mobile": "15601691301", + "code": 9999 +} + +### 请求 /social-login æŽ¥å£ => æˆåŠŸ +POST {{appApi}}/member/auth/social-login +Content-Type: application/json +tenant-id: {{appTenentId}} + +{ + "type": 34, + "code": "0e1oc9000CTjFQ1oim200bhtb61oc90g", + "state": "default" +} + +### 请求 /weixin-mini-app-login æŽ¥å£ => æˆåŠŸ +POST {{appApi}}/member/auth/weixin-mini-app-login +Content-Type: application/json +tenant-id: {{appTenentId}} + +{ + "phoneCode": "618e6412e0c728f5b8fc7164497463d0158a923c9e7fd86af8bba393b9decbc5", + "loginCode": "001frTkl21JUf94VGxol2hSlff1frTkR" +} + +### 请求 /logout æŽ¥å£ => æˆåŠŸ +POST {{appApi}}/member/auth/logout +Content-Type: application/json +Authorization: Bearer c1b76bdaf2c146c581caa4d7fd81ee66 +tenant-id: {{appTenentId}} + +### 请求 /auth/refresh-token æŽ¥å£ => æˆåŠŸ +POST {{appApi}}/member/auth/refresh-token?refreshToken=bc43d929094849a28b3a69f6e6940d70 +Content-Type: application/json +tenant-id: {{appTenentId}} + +### 请求 /auth/create-weixin-jsapi-signature æŽ¥å£ => æˆåŠŸ +POST {{appApi}}/member/auth/create-weixin-jsapi-signature?url=http://www.iocoder.cn +Authorization: Bearer {{appToken}} +tenant-id: {{appTenentId}} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java new file mode 100644 index 000000000..ed3963e90 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java @@ -0,0 +1,128 @@ +package cn.iocoder.yudao.module.member.controller.app.auth; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.security.config.SecurityProperties; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.member.controller.app.auth.vo.*; +import cn.iocoder.yudao.module.member.convert.auth.AuthConvert; +import cn.iocoder.yudao.module.member.service.auth.MemberAuthService; +import cn.iocoder.yudao.module.system.api.social.SocialClientApi; +import cn.iocoder.yudao.module.system.api.social.dto.SocialWxJsapiSignatureRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.annotation.security.PermitAll; +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "用户 APP - 认è¯") +@RestController +@RequestMapping("/member/auth") +@Validated +@Slf4j +public class AppAuthController { + + @Resource + private MemberAuthService authService; + + @Resource + private SocialClientApi socialClientApi; + + @Resource + private SecurityProperties securityProperties; + + @PostMapping("/login") + @Operation(summary = "使用手机 + 密ç ç™»å½•") + public CommonResult login(@RequestBody @Valid AppAuthLoginReqVO reqVO) { + return success(authService.login(reqVO)); + } + + @PostMapping("/logout") + @PermitAll + @Operation(summary = "登出系统") + public CommonResult logout(HttpServletRequest request) { + String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader()); + if (StrUtil.isNotBlank(token)) { + authService.logout(token); + } + return success(true); + } + + @PostMapping("/refresh-token") + @Operation(summary = "刷新令牌") + @Parameter(name = "refreshToken", description = "刷新令牌", required = true) + @OperateLog(enable = false) // é¿å… Post 请求被记录æ“作日志 + public CommonResult refreshToken(@RequestParam("refreshToken") String refreshToken) { + return success(authService.refreshToken(refreshToken)); + } + + // ========== 短信登录相关 ========== + + @PostMapping("/sms-login") + @Operation(summary = "使用手机 + 验è¯ç ç™»å½•") + public CommonResult smsLogin(@RequestBody @Valid AppAuthSmsLoginReqVO reqVO, + @RequestHeader Integer terminal) { + return success(authService.smsLogin(reqVO, terminal)); + } + + @PostMapping("/send-sms-code") + @Operation(summary = "å‘é€æ‰‹æœºéªŒè¯ç ") + public CommonResult sendSmsCode(@RequestBody @Valid AppAuthSmsSendReqVO reqVO) { + authService.sendSmsCode(getLoginUserId(), reqVO); + return success(true); + } + + @PostMapping("/validate-sms-code") + @Operation(summary = "校验手机验è¯ç ") + public CommonResult validateSmsCode(@RequestBody @Valid AppAuthSmsValidateReqVO reqVO) { + authService.validateSmsCode(getLoginUserId(), reqVO); + return success(true); + } + + // ========== 社交登录相关 ========== + + @GetMapping("/social-auth-redirect") + @Operation(summary = "社交授æƒçš„跳转") + @Parameters({ + @Parameter(name = "type", description = "社交类型", required = true), + @Parameter(name = "redirectUri", description = "回调路径") + }) + public CommonResult socialAuthRedirect(@RequestParam("type") Integer type, + @RequestParam("redirectUri") String redirectUri) { + return CommonResult.success(authService.getSocialAuthorizeUrl(type, redirectUri)); + } + + @PostMapping("/social-login") + @Operation(summary = "社交快æ·ç™»å½•ï¼Œä½¿ç”¨ code 授æƒç ", description = "适åˆæœªç™»å½•çš„用户,但是社交账å·å·²ç»‘定用户") + public CommonResult socialLogin(@RequestBody @Valid AppAuthSocialLoginReqVO reqVO) { + return success(authService.socialLogin(reqVO)); + } + + @PostMapping("/weixin-mini-app-login") + @Operation(summary = "微信å°ç¨‹åºçš„一键登录") + public CommonResult weixinMiniAppLogin(@RequestBody @Valid AppAuthWeixinMiniAppLoginReqVO reqVO) { + return success(authService.weixinMiniAppLogin(reqVO)); + } + + @PostMapping("/create-weixin-jsapi-signature") + @Operation(summary = "创建微信 JS SDK åˆå§‹åŒ–所需的签å", + description = "å‚考 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html 文档") + public CommonResult createWeixinMpJsapiSignature(@RequestParam("url") String url) { + SocialWxJsapiSignatureRespDTO signature = socialClientApi.createWxMpJsapiSignature( + UserTypeEnum.MEMBER.getValue(), url); + return success(AuthConvert.INSTANCE.convert(signature)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthCheckCodeReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthCheckCodeReqVO.java new file mode 100644 index 000000000..eee7062cb --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthCheckCodeReqVO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.member.controller.app.auth.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; + +// TODO 芋艿:code review 相关逻辑 +@Schema(description = "用户 APP - 校验验è¯ç  Request VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AppAuthCheckCodeReqVO { + + @Schema(description = "手机å·", example = "15601691234") + @NotBlank(message = "手机å·ä¸èƒ½ä¸ºç©º") + @Mobile + private String mobile; + + @Schema(description = "手机验è¯ç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotBlank(message = "手机验è¯ç ä¸èƒ½ä¸ºç©º") + @Length(min = 4, max = 6, message = "手机验è¯ç é•¿åº¦ä¸º 4-6 ä½") + @Pattern(regexp = "^[0-9]+$", message = "手机验è¯ç å¿…须都是数字") + private String code; + + @Schema(description = "å‘é€åœºæ™¯,对应 SmsSceneEnum 枚举", example = "1") + @NotNull(message = "å‘é€åœºæ™¯ä¸èƒ½ä¸ºç©º") + @InEnum(SmsSceneEnum.class) + private Integer scene; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java new file mode 100644 index 000000000..e64209de8 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.member.controller.app.auth.vo; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.AssertTrue; +import javax.validation.constraints.NotEmpty; + +@Schema(description = "用户 APP - 手机 + 密ç ç™»å½• Request VO,如果登录并绑定社交用户,需è¦ä¼ é€’ social 开头的å‚æ•°") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AppAuthLoginReqVO { + + @Schema(description = "手机å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300") + @NotEmpty(message = "手机å·ä¸èƒ½ä¸ºç©º") + @Mobile + private String mobile; + + @Schema(description = "密ç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao") + @NotEmpty(message = "密ç ä¸èƒ½ä¸ºç©º") + @Length(min = 4, max = 16, message = "密ç é•¿åº¦ä¸º 4-16 ä½") + private String password; + + // ========== 绑定社交登录时,需è¦ä¼ é€’如下å‚æ•° ========== + + @Schema(description = "社交平å°çš„类型,å‚è§ SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @InEnum(SocialTypeEnum.class) + private Integer socialType; + + @Schema(description = "授æƒç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private String socialCode; + + @Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62") + private String socialState; + + @AssertTrue(message = "授æƒç ä¸èƒ½ä¸ºç©º") + public boolean isSocialCodeValid() { + return socialType == null || StrUtil.isNotEmpty(socialCode); + } + + @AssertTrue(message = "æŽˆæƒ state ä¸èƒ½ä¸ºç©º") + public boolean isSocialState() { + return socialType == null || StrUtil.isNotEmpty(socialState); + } + +} \ No newline at end of file diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java new file mode 100644 index 000000000..072ec9e4b --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.member.controller.app.auth.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Schema(description = "用户 APP - 登录 Response VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AppAuthLoginRespVO { + + @Schema(description = "用户编å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long userId; + + @Schema(description = "访问令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "happy") + private String accessToken; + + @Schema(description = "刷新令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "nice") + private String refreshToken; + + @Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime expiresTime; + + /** + * 仅社交登录ã€ç¤¾äº¤ç»‘定时会返回 + * + * 为什么需è¦è¿”回?微信公众å·ã€å¾®ä¿¡å°ç¨‹åºæ”¯ä»˜éœ€è¦ä¼ é€’ openid ç»™æ”¯ä»˜æŽ¥å£ + */ + @Schema(description = "社交用户 openid", example = "qq768") + private String openid; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsLoginReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsLoginReqVO.java new file mode 100644 index 000000000..8225269a3 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsLoginReqVO.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.member.controller.app.auth.vo; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.AssertTrue; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; + +@Schema(description = "用户 APP - 手机 + 验è¯ç ç™»å½• Request VO,如果登录并绑定社交用户,需è¦ä¼ é€’ social 开头的å‚æ•°") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AppAuthSmsLoginReqVO { + + @Schema(description = "手机å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300") + @NotEmpty(message = "手机å·ä¸èƒ½ä¸ºç©º") + @Mobile + private String mobile; + + @Schema(description = "手机验è¯ç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotEmpty(message = "手机验è¯ç ä¸èƒ½ä¸ºç©º") + @Length(min = 4, max = 6, message = "手机验è¯ç é•¿åº¦ä¸º 4-6 ä½") + @Pattern(regexp = "^[0-9]+$", message = "手机验è¯ç å¿…须都是数字") + private String code; + + // ========== 绑定社交登录时,需è¦ä¼ é€’如下å‚æ•° ========== + + @Schema(description = "社交平å°çš„类型,å‚è§ SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @InEnum(SocialTypeEnum.class) + private Integer socialType; + + @Schema(description = "授æƒç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private String socialCode; + + @Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62") + private String socialState; + + @AssertTrue(message = "授æƒç ä¸èƒ½ä¸ºç©º") + public boolean isSocialCodeValid() { + return socialType == null || StrUtil.isNotEmpty(socialCode); + } + + @AssertTrue(message = "æŽˆæƒ state ä¸èƒ½ä¸ºç©º") + public boolean isSocialState() { + return socialType == null || StrUtil.isNotEmpty(socialState); + } + +} \ No newline at end of file diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsSendReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsSendReqVO.java new file mode 100644 index 000000000..5f4b030f3 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsSendReqVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.member.controller.app.auth.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; + +@Schema(description = "用户 APP - å‘é€æ‰‹æœºéªŒè¯ç  Request VO") +@Data +@Accessors(chain = true) +public class AppAuthSmsSendReqVO { + + @Schema(description = "手机å·", example = "15601691234") + @Mobile + private String mobile; + + @Schema(description = "å‘é€åœºæ™¯,对应 SmsSceneEnum 枚举", example = "1") + @NotNull(message = "å‘é€åœºæ™¯ä¸èƒ½ä¸ºç©º") + @InEnum(SmsSceneEnum.class) + private Integer scene; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsValidateReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsValidateReqVO.java new file mode 100644 index 000000000..1a57be74b --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsValidateReqVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.member.controller.app.auth.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; + +@Schema(description = "用户 APP - 校验手机验è¯ç  Request VO") +@Data +@Accessors(chain = true) +public class AppAuthSmsValidateReqVO { + + @Schema(description = "手机å·", example = "15601691234") + @Mobile + private String mobile; + + @Schema(description = "å‘é€åœºæ™¯,对应 SmsSceneEnum 枚举", example = "1") + @NotNull(message = "å‘é€åœºæ™¯ä¸èƒ½ä¸ºç©º") + @InEnum(SmsSceneEnum.class) + private Integer scene; + + @Schema(description = "手机验è¯ç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotEmpty(message = "手机验è¯ç ä¸èƒ½ä¸ºç©º") + @Length(min = 4, max = 6, message = "手机验è¯ç é•¿åº¦ä¸º 4-6 ä½") + @Pattern(regexp = "^[0-9]+$", message = "手机验è¯ç å¿…须都是数字") + private String code; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLoginReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLoginReqVO.java new file mode 100644 index 000000000..d3bac4799 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLoginReqVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.member.controller.app.auth.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@Schema(description = "用户 APP - 社交快æ·ç™»å½• Request VO,使用 code 授æƒç ") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AppAuthSocialLoginReqVO { + + @Schema(description = "社交平å°çš„类型,å‚è§ SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @InEnum(SocialTypeEnum.class) + @NotNull(message = "社交平å°çš„类型ä¸èƒ½ä¸ºç©º") + private Integer type; + + @Schema(description = "授æƒç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotEmpty(message = "授æƒç ä¸èƒ½ä¸ºç©º") + private String code; + + @Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62") + @NotEmpty(message = "state ä¸èƒ½ä¸ºç©º") + private String state; + +} \ No newline at end of file diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthWeixinMiniAppLoginReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthWeixinMiniAppLoginReqVO.java new file mode 100644 index 000000000..11dcdf957 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthWeixinMiniAppLoginReqVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.member.controller.app.auth.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; + +@Schema(description = "用户 APP - 微信å°ç¨‹åºæ‰‹æœºç™»å½• Request VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AppAuthWeixinMiniAppLoginReqVO { + + @Schema(description = "手机 code,å°ç¨‹åºé€šè¿‡ wx.getPhoneNumber 方法获得", requiredMode = Schema.RequiredMode.REQUIRED, example = "hello") + @NotEmpty(message = "手机 code ä¸èƒ½ä¸ºç©º") + private String phoneCode; + + @Schema(description = "登录 code,å°ç¨‹åºé€šè¿‡ wx.login 方法获得", requiredMode = Schema.RequiredMode.REQUIRED, example = "word") + @NotEmpty(message = "登录 code ä¸èƒ½ä¸ºç©º") + private String loginCode; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AuthWeixinJsapiSignatureRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AuthWeixinJsapiSignatureRespVO.java new file mode 100644 index 000000000..37e63652b --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AuthWeixinJsapiSignatureRespVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.member.controller.app.auth.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Schema(description = "用户 APP - å¾®ä¿¡å…¬ä¼—å· JSAPI ç­¾å Response VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AuthWeixinJsapiSignatureRespVO { + + @Schema(description = "微信公众å·çš„ appId", requiredMode = Schema.RequiredMode.REQUIRED, example = "hello") + private String appId; + + @Schema(description = "匿å串", requiredMode = Schema.RequiredMode.REQUIRED, example = "world") + private String nonceStr; + + @Schema(description = "时间戳", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long timestamp; + + @Schema(description = "URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn") + private String url; + + @Schema(description = "ç­¾å", requiredMode = Schema.RequiredMode.REQUIRED, example = "阿巴阿巴") + private String signature; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberExperienceRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberExperienceRecordController.java new file mode 100644 index 000000000..5c33e5c1b --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberExperienceRecordController.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.member.controller.app.level; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.member.controller.app.level.vo.experience.AppMemberExperienceRecordRespVO; +import cn.iocoder.yudao.module.member.convert.level.MemberExperienceRecordConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO; +import cn.iocoder.yudao.module.member.service.level.MemberExperienceRecordService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "用户 App - 会员ç»éªŒè®°å½•") +@RestController +@RequestMapping("/member/experience-record") +@Validated +public class AppMemberExperienceRecordController { + + @Resource + private MemberExperienceRecordService experienceLogService; + + @GetMapping("/page") + @Operation(summary = "获得会员ç»éªŒè®°å½•åˆ†é¡µ") + @PreAuthenticated + public CommonResult> getExperienceRecordPage( + @Valid PageParam pageParam) { + PageResult pageResult = experienceLogService.getExperienceRecordPage( + getLoginUserId(), pageParam); + return success(MemberExperienceRecordConvert.INSTANCE.convertPage02(pageResult)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberLevelController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberLevelController.java new file mode 100644 index 000000000..d4a4483af --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberLevelController.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.member.controller.app.level; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.member.controller.app.level.vo.level.AppMemberLevelRespVO; +import cn.iocoder.yudao.module.member.convert.level.MemberLevelConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; +import cn.iocoder.yudao.module.member.service.level.MemberLevelService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "用户 App - 会员等级") +@RestController +@RequestMapping("/member/level") +@Validated +public class AppMemberLevelController { + + @Resource + private MemberLevelService levelService; + + @GetMapping("/list") + @Operation(summary = "获得会员等级列表") + public CommonResult> getLevelList() { + List result = levelService.getEnableLevelList(); + return success(MemberLevelConvert.INSTANCE.convertList02(result)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/experience/AppMemberExperienceRecordRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/experience/AppMemberExperienceRecordRespVO.java new file mode 100644 index 000000000..e2d7bb0c3 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/experience/AppMemberExperienceRecordRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.member.controller.app.level.vo.experience; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "用户 App - 会员ç»éªŒè®°å½• Response VO") +@Data +public class AppMemberExperienceRecordRespVO { + + @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "增加ç»éªŒ") + private String title; + + @Schema(description = "ç»éªŒ", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Integer experience; + + @Schema(description = "æè¿°", requiredMode = Schema.RequiredMode.REQUIRED, example = "下å•å¢žåŠ  100 ç»éªŒ") + private String description; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/level/AppMemberLevelRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/level/AppMemberLevelRespVO.java new file mode 100644 index 000000000..fdade172f --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/level/AppMemberLevelRespVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.member.controller.app.level.vo.level; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 App - 会员等级 Response VO") +@Data +public class AppMemberLevelRespVO { + + @Schema(description = "等级å称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + private String name; + + @Schema(description = "等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer level; + + @Schema(description = "å‡çº§ç»éªŒ", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Integer experience; + + @Schema(description = "享å—折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "98") + private Integer discountPercent; + + @Schema(description = "等级图标", example = "https://www.iocoder.cn/yudao.jpg") + private String icon; + + @Schema(description = "等级背景图", example = "https://www.iocoder.cn/yudao.jpg") + private String backgroundUrl; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/AppMemberPointRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/AppMemberPointRecordController.java new file mode 100644 index 000000000..1e63cc7d4 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/AppMemberPointRecordController.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.member.controller.app.point; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordRespVO; +import cn.iocoder.yudao.module.member.convert.point.MemberPointRecordConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO; +import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "用户 App - 签到记录") +@RestController +@RequestMapping("/member/point/record") +@Validated +public class AppMemberPointRecordController { + + @Resource + private MemberPointRecordService pointRecordService; + + @GetMapping("/page") + @Operation(summary = "获得用户积分记录分页") + @PreAuthenticated + public CommonResult> getPointRecordPage(@Valid PageParam pageVO) { + PageResult pageResult = pointRecordService.getPointRecordPage(getLoginUserId(), pageVO); + return success(MemberPointRecordConvert.INSTANCE.convertPage02(pageResult)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/vo/AppMemberPointRecordRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/vo/AppMemberPointRecordRespVO.java new file mode 100644 index 000000000..ec95b2e02 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/vo/AppMemberPointRecordRespVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.member.controller.app.point.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "用户 App - 用户积分记录 Response VO") +@Data +public class AppMemberPointRecordRespVO { + + @Schema(description = "自增主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "31457") + private Long id;; + + @Schema(description = "积分标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜") + private String title; + + @Schema(description = "积分æè¿°", example = "你猜") + private String description; + + @Schema(description = "积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Integer point; + + @Schema(description = "å‘生时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInConfigController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInConfigController.java new file mode 100644 index 000000000..62a52e3d8 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInConfigController.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.member.controller.app.signin; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.member.controller.app.signin.vo.config.AppMemberSignInConfigRespVO; +import cn.iocoder.yudao.module.member.convert.signin.MemberSignInConfigConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO; +import cn.iocoder.yudao.module.member.service.signin.MemberSignInConfigService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "用户 App - 签到规则") +@RestController +@RequestMapping("/member/sign-in/config") +@Validated +public class AppMemberSignInConfigController { + + @Resource + private MemberSignInConfigService signInConfigService; + + @GetMapping("/list") + @Operation(summary = "获得签到规则列表") + public CommonResult> getSignInConfigList() { + List pageResult = signInConfigService.getSignInConfigList(CommonStatusEnum.ENABLE.getStatus()); + return success(MemberSignInConfigConvert.INSTANCE.convertList02(pageResult)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInRecordController.java new file mode 100644 index 000000000..2f7afa042 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInRecordController.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.member.controller.app.signin; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO; +import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordSummaryRespVO; +import cn.iocoder.yudao.module.member.convert.signin.MemberSignInRecordConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO; +import cn.iocoder.yudao.module.member.service.signin.MemberSignInRecordService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管ç†åŽå° - 签到记录") +@RestController +@RequestMapping("/member/sign-in/record") +@Validated +public class AppMemberSignInRecordController { + + @Resource + private MemberSignInRecordService signInRecordService; + + @GetMapping("/get-summary") + @Operation(summary = "获得个人签到统计") + @PreAuthenticated + public CommonResult getSignInRecordSummary() { + return success(signInRecordService.getSignInRecordSummary(getLoginUserId())); + } + + @PostMapping("/create") + @Operation(summary = "签到") + @PreAuthenticated + public CommonResult createSignInRecord() { + MemberSignInRecordDO recordDO = signInRecordService.createSignRecord(getLoginUserId()); + return success(MemberSignInRecordConvert.INSTANCE.coverRecordToAppRecordVo(recordDO)); + } + + @GetMapping("/page") + @Operation(summary = "获得签到记录分页") + @PreAuthenticated + public CommonResult> getSignRecordPage(PageParam pageParam) { + PageResult pageResult = signInRecordService.getSignRecordPage(getLoginUserId(), pageParam); + return success(MemberSignInRecordConvert.INSTANCE.convertPage02(pageResult)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/vo/config/AppMemberSignInConfigRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/vo/config/AppMemberSignInConfigRespVO.java new file mode 100644 index 000000000..a18d3a28e --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/vo/config/AppMemberSignInConfigRespVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.member.controller.app.signin.vo.config; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 App - 签到规则 Response VO") +@Data +public class AppMemberSignInConfigRespVO { + + @Schema(description = "签到第 x 天", requiredMode = Schema.RequiredMode.REQUIRED, example = "7") + private Integer day; + + @Schema(description = "奖励积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer point; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/vo/record/AppMemberSignInRecordRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/vo/record/AppMemberSignInRecordRespVO.java new file mode 100644 index 000000000..2d910d0c6 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/vo/record/AppMemberSignInRecordRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.member.controller.app.signin.vo.record; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "用户 App - 签到记录 Response VO") +@Data +public class AppMemberSignInRecordRespVO { + + @Schema(description = "第几天签到", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer day; + + @Schema(description = "签到的分数", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer point; + + @Schema(description = "签到的ç»éªŒ", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer experience; + + @Schema(description = "签到时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/vo/record/AppMemberSignInRecordSummaryRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/vo/record/AppMemberSignInRecordSummaryRespVO.java new file mode 100644 index 000000000..30fb66a15 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/vo/record/AppMemberSignInRecordSummaryRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.member.controller.app.signin.vo.record; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 App - 个人签到统计 Response VO") +@Data +public class AppMemberSignInRecordSummaryRespVO { + + @Schema(description = "总签到天数", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer totalDay; + + @Schema(description = "连续签到第 x 天", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") + private Integer continuousDay; + + @Schema(description = "今天是å¦å·²ç­¾åˆ°", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean todaySignIn; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java new file mode 100644 index 000000000..fd5e3fa83 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.member.controller.app.social; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserBindReqVO; +import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserUnbindReqVO; +import cn.iocoder.yudao.module.member.convert.social.SocialUserConvert; +import cn.iocoder.yudao.module.system.api.social.SocialUserApi; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; + +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "用户 App - 社交用户") +@RestController +@RequestMapping("/system/social-user") +@Validated +public class AppSocialUserController { + + @Resource + private SocialUserApi socialUserApi; + + @PostMapping("/bind") + @Operation(summary = "社交绑定,使用 code 授æƒç ") + public CommonResult socialBind(@RequestBody @Valid AppSocialUserBindReqVO reqVO) { + socialUserApi.bindSocialUser(SocialUserConvert.INSTANCE.convert(getLoginUserId(), UserTypeEnum.MEMBER.getValue(), reqVO)); + return CommonResult.success(true); + } + + @DeleteMapping("/unbind") + @Operation(summary = "å–消社交绑定") + @PreAuthenticated + public CommonResult socialUnbind(@RequestBody AppSocialUserUnbindReqVO reqVO) { + socialUserApi.unbindSocialUser(SocialUserConvert.INSTANCE.convert(getLoginUserId(), UserTypeEnum.MEMBER.getValue(), reqVO)); + return CommonResult.success(true); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserBindReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserBindReqVO.java new file mode 100644 index 000000000..49141f935 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserBindReqVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.member.controller.app.social.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@Schema(description = "用户 APP - 社交绑定 Request VO,使用 code 授æƒç ") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AppSocialUserBindReqVO { + + @Schema(description = "社交平å°çš„类型,å‚è§ SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @InEnum(SocialTypeEnum.class) + @NotNull(message = "社交平å°çš„类型ä¸èƒ½ä¸ºç©º") + private Integer type; + + @Schema(description = "授æƒç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotEmpty(message = "授æƒç ä¸èƒ½ä¸ºç©º") + private String code; + + @Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62") + @NotEmpty(message = "state ä¸èƒ½ä¸ºç©º") + private String state; + +} \ No newline at end of file diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserUnbindReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserUnbindReqVO.java new file mode 100644 index 000000000..159cdcd33 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserUnbindReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.member.controller.app.social.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@Schema(description = "用户 APP - å–消社交绑定 Request VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AppSocialUserUnbindReqVO { + + @Schema(description = "社交平å°çš„类型,å‚è§ SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @InEnum(SocialTypeEnum.class) + @NotNull(message = "社交平å°çš„类型ä¸èƒ½ä¸ºç©º") + private Integer type; + + @Schema(description = "社交用户的 openid", requiredMode = Schema.RequiredMode.REQUIRED, example = "IPRmJ0wvBptiPIlGEZiPewGwiEiE") + @NotEmpty(message = "社交用户的 openid ä¸èƒ½ä¸ºç©º") + private String openid; + +} \ No newline at end of file diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.http b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.http new file mode 100644 index 000000000..745556f75 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.http @@ -0,0 +1,4 @@ +### 请求 /member/user/profile/get æŽ¥å£ => 没有æƒé™ +GET {{appApi}}/member/user/get +Authorization: Bearer test245 +tenant-id: {{appTenentId}} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java new file mode 100644 index 000000000..9322f9146 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.member.controller.app.user; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.member.controller.app.user.vo.*; +import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.service.level.MemberLevelService; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "用户 APP - 用户个人中心") +@RestController +@RequestMapping("/member/user") +@Validated +@Slf4j +public class AppMemberUserController { + + @Resource + private MemberUserService userService; + @Resource + private MemberLevelService levelService; + + @GetMapping("/get") + @Operation(summary = "获得基本信æ¯") + @PreAuthenticated + public CommonResult getUserInfo() { + MemberUserDO user = userService.getUser(getLoginUserId()); + MemberLevelDO level = levelService.getLevel(user.getLevelId()); + return success(MemberUserConvert.INSTANCE.convert(user, level)); + } + + @PutMapping("/update") + @Operation(summary = "修改基本信æ¯") + @PreAuthenticated + public CommonResult updateUser(@RequestBody @Valid AppMemberUserUpdateReqVO reqVO) { + userService.updateUser(getLoginUserId(), reqVO); + return success(true); + } + + @PutMapping("/update-mobile") + @Operation(summary = "修改用户手机") + @PreAuthenticated + public CommonResult updateUserMobile(@RequestBody @Valid AppMemberUserUpdateMobileReqVO reqVO) { + userService.updateUserMobile(getLoginUserId(), reqVO); + return success(true); + } + + @PutMapping("/update-password") + @Operation(summary = "修改用户密ç ", description = "用户修改密ç æ—¶ä½¿ç”¨") + @PreAuthenticated + public CommonResult updatePassword(@RequestBody @Valid AppMemberUserUpdatePasswordReqVO reqVO) { + userService.updateUserPassword(getLoginUserId(), reqVO); + return success(true); + } + + @PutMapping("/reset-password") + @Operation(summary = "é‡ç½®å¯†ç ", description = "用户忘记密ç æ—¶ä½¿ç”¨") + public CommonResult resetPassword(@RequestBody @Valid AppMemberUserResetPasswordReqVO reqVO) { + userService.resetUserPassword(reqVO); + return success(true); + } + +} + diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java new file mode 100644 index 000000000..25cceedc2 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.member.controller.app.user.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Schema(description = "用户 APP - ç”¨æˆ·ä¸ªäººä¿¡æ¯ Response VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AppMemberUserInfoRespVO { + + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + private String nickname; + + @Schema(description = "用户头åƒ", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.png") + private String avatar; + + @Schema(description = "用户手机å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300") + private String mobile; + + @Schema(description = "积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer point; + + @Schema(description = "ç»éªŒå€¼", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer experience; + + @Schema(description = "用户等级") + private Level level; + + @Schema(description = "是å¦æˆä¸ºæŽ¨å¹¿å‘˜", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean brokerageEnabled; + + @Schema(description = "用户 App - 会员等级") + @Data + public static class Level { + + @Schema(description = "等级编å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "等级å称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + private String name; + + @Schema(description = "等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer level; + + @Schema(description = "等级图标", example = "https://www.iocoder.cn/yudao.jpg") + private String icon; + + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserResetPasswordReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserResetPasswordReqVO.java new file mode 100644 index 000000000..22cbf55ee --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserResetPasswordReqVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.member.controller.app.user.vo; + +import cn.iocoder.yudao.framework.common.validation.Mobile; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; + +@Schema(description = "用户 APP - é‡ç½®å¯†ç  Request VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AppMemberUserResetPasswordReqVO { + + @Schema(description = "新密ç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao") + @NotEmpty(message = "新密ç ä¸èƒ½ä¸ºç©º") + @Length(min = 4, max = 16, message = "密ç é•¿åº¦ä¸º 4-16 ä½") + private String password; + + @Schema(description = "手机验è¯ç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotEmpty(message = "手机验è¯ç ä¸èƒ½ä¸ºç©º") + @Length(min = 4, max = 6, message = "手机验è¯ç é•¿åº¦ä¸º 4-6 ä½") + @Pattern(regexp = "^[0-9]+$", message = "手机验è¯ç å¿…须都是数字") + private String code; + + @Schema(description = "手机å·",requiredMode = Schema.RequiredMode.REQUIRED,example = "15878962356") + @NotBlank(message = "手机å·ä¸èƒ½ä¸ºç©º") + @Mobile + private String mobile; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateMobileReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateMobileReqVO.java new file mode 100644 index 000000000..6653506fc --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateMobileReqVO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.member.controller.app.user.vo; + +import cn.iocoder.yudao.framework.common.validation.Mobile; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; + +@Schema(description = "用户 APP - 修改手机 Request VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AppMemberUserUpdateMobileReqVO { + + @Schema(description = "手机验è¯ç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotEmpty(message = "手机验è¯ç ä¸èƒ½ä¸ºç©º") + @Length(min = 4, max = 6, message = "手机验è¯ç é•¿åº¦ä¸º 4-6 ä½") + @Pattern(regexp = "^[0-9]+$", message = "手机验è¯ç å¿…须都是数字") + private String code; + + @Schema(description = "手机å·",requiredMode = Schema.RequiredMode.REQUIRED,example = "15823654487") + @NotBlank(message = "手机å·ä¸èƒ½ä¸ºç©º") + @Length(min = 8, max = 11, message = "手机å·ç é•¿åº¦ä¸º 8-11 ä½") + @Mobile + private String mobile; + + @Schema(description = "原手机验è¯ç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotEmpty(message = "原手机验è¯ç ä¸èƒ½ä¸ºç©º") + @Length(min = 4, max = 6, message = "手机验è¯ç é•¿åº¦ä¸º 4-6 ä½") + @Pattern(regexp = "^[0-9]+$", message = "手机验è¯ç å¿…须都是数字") + private String oldCode; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdatePasswordReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdatePasswordReqVO.java new file mode 100644 index 000000000..cc78ca832 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdatePasswordReqVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.member.controller.app.user.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; + +@Schema(description = "用户 APP - ä¿®æ”¹å¯†ç  Request VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AppMemberUserUpdatePasswordReqVO { + + @Schema(description = "新密ç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao") + @NotEmpty(message = "新密ç ä¸èƒ½ä¸ºç©º") + @Length(min = 4, max = 16, message = "密ç é•¿åº¦ä¸º 4-16 ä½") + private String password; + + @Schema(description = "手机验è¯ç ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotEmpty(message = "手机验è¯ç ä¸èƒ½ä¸ºç©º") + @Length(min = 4, max = 6, message = "手机验è¯ç é•¿åº¦ä¸º 4-6 ä½") + @Pattern(regexp = "^[0-9]+$", message = "手机验è¯ç å¿…须都是数字") + private String code; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateReqVO.java new file mode 100644 index 000000000..a676f6256 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.member.controller.app.user.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.hibernate.validator.constraints.URL; + +@Schema(description = "用户 App - 会员用户更新 Request VO") +@Data +public class AppMemberUserUpdateReqVO { + + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "æŽå››") + private String nickname; + + @Schema(description = "头åƒ", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/x.png") + @URL(message = "头åƒå¿…须是 URL æ ¼å¼") + private String avatar; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/package-info.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/package-info.java new file mode 100644 index 000000000..9e2888c69 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * æä¾› RESTful API ç»™å‰ç«¯ï¼š + * 1. admin 包:æ供给管ç†åŽå° yudao-ui-admin å‰ç«¯é¡¹ç›® + * 2. app 包:æ供给用户 APP yudao-ui-app å‰ç«¯é¡¹ç›®ï¼Œå®ƒçš„ Controller å’Œ VO 都è¦æ·»åŠ  App å‰ç¼€ï¼Œç”¨äºŽå’Œç®¡ç†åŽå°è¿›è¡ŒåŒºåˆ† + */ +package cn.iocoder.yudao.module.member.controller; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/address/AddressConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/address/AddressConvert.java new file mode 100644 index 000000000..fd5198e14 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/address/AddressConvert.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.member.convert.address; + +import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; +import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; +import cn.iocoder.yudao.module.member.controller.admin.address.vo.AddressRespVO; +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressRespVO; +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Named; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * ç”¨æˆ·æ”¶ä»¶åœ°å€ Convert + * + * @author 芋é“æºç  + */ +@Mapper +public interface AddressConvert { + + AddressConvert INSTANCE = Mappers.getMapper(AddressConvert.class); + + MemberAddressDO convert(AppAddressCreateReqVO bean); + + MemberAddressDO convert(AppAddressUpdateReqVO bean); + + @Mapping(source = "areaId", target = "areaName", qualifiedByName = "convertAreaIdToAreaName") + AppAddressRespVO convert(MemberAddressDO bean); + + List convertList(List list); + + AddressRespDTO convert02(MemberAddressDO bean); + + @Named("convertAreaIdToAreaName") + default String convertAreaIdToAreaName(Integer areaId) { + return AreaUtils.format(areaId); + } + + List convertList2(List list); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java new file mode 100644 index 000000000..29e8f4fdc --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.member.convert.auth; + +import cn.iocoder.yudao.module.member.controller.app.auth.vo.*; +import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserUnbindReqVO; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserResetPasswordReqVO; +import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeValidateReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialWxJsapiSignatureRespDTO; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface AuthConvert { + + AuthConvert INSTANCE = Mappers.getMapper(AuthConvert.class); + + SocialUserBindReqDTO convert(Long userId, Integer userType, AppAuthSocialLoginReqVO reqVO); + SocialUserUnbindReqDTO convert(Long userId, Integer userType, AppSocialUserUnbindReqVO reqVO); + + SmsCodeSendReqDTO convert(AppAuthSmsSendReqVO reqVO); + SmsCodeUseReqDTO convert(AppMemberUserResetPasswordReqVO reqVO, SmsSceneEnum scene, String usedIp); + SmsCodeUseReqDTO convert(AppAuthSmsLoginReqVO reqVO, Integer scene, String usedIp); + + AppAuthLoginRespVO convert(OAuth2AccessTokenRespDTO bean, String openid); + + SmsCodeValidateReqDTO convert(AppAuthSmsValidateReqVO bean); + + SocialWxJsapiSignatureRespDTO convert(SocialWxJsapiSignatureRespDTO bean); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/config/MemberConfigConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/config/MemberConfigConvert.java new file mode 100644 index 000000000..9847645f9 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/config/MemberConfigConvert.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.member.convert.config; + +import cn.iocoder.yudao.module.member.api.config.dto.MemberConfigRespDTO; +import cn.iocoder.yudao.module.member.controller.admin.config.vo.MemberConfigRespVO; +import cn.iocoder.yudao.module.member.controller.admin.config.vo.MemberConfigSaveReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.config.MemberConfigDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 会员é…ç½® Convert + * + * @author QingX + */ +@Mapper +public interface MemberConfigConvert { + + MemberConfigConvert INSTANCE = Mappers.getMapper(MemberConfigConvert.class); + + MemberConfigRespVO convert(MemberConfigDO bean); + + MemberConfigDO convert(MemberConfigSaveReqVO bean); + + MemberConfigRespDTO convert01(MemberConfigDO config); +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/group/MemberGroupConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/group/MemberGroupConvert.java new file mode 100644 index 000000000..06f49d60c --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/group/MemberGroupConvert.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.member.convert.group; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupRespVO; +import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupSimpleRespVO; +import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupUpdateReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.group.MemberGroupDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 用户分组 Convert + * + * @author owen + */ +@Mapper +public interface MemberGroupConvert { + + MemberGroupConvert INSTANCE = Mappers.getMapper(MemberGroupConvert.class); + + MemberGroupDO convert(MemberGroupCreateReqVO bean); + + MemberGroupDO convert(MemberGroupUpdateReqVO bean); + + MemberGroupRespVO convert(MemberGroupDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertSimpleList(List list); +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberExperienceRecordConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberExperienceRecordConvert.java new file mode 100644 index 000000000..93f864f08 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberExperienceRecordConvert.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.member.convert.level; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordRespVO; +import cn.iocoder.yudao.module.member.controller.app.level.vo.experience.AppMemberExperienceRecordRespVO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 会员ç»éªŒè®°å½• Convert + * + * @author owen + */ +@Mapper +public interface MemberExperienceRecordConvert { + + MemberExperienceRecordConvert INSTANCE = Mappers.getMapper(MemberExperienceRecordConvert.class); + + MemberExperienceRecordRespVO convert(MemberExperienceRecordDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + MemberExperienceRecordDO convert(Long userId, Integer experience, Integer totalExperience, + String bizId, Integer bizType, + String title, String description); + + PageResult convertPage02(PageResult page); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelConvert.java new file mode 100644 index 000000000..f2282815e --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelConvert.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.member.convert.level; + +import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelRespVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelSimpleRespVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelUpdateReqVO; +import cn.iocoder.yudao.module.member.controller.app.level.vo.level.AppMemberLevelRespVO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 会员等级 Convert + * + * @author owen + */ +@Mapper +public interface MemberLevelConvert { + + MemberLevelConvert INSTANCE = Mappers.getMapper(MemberLevelConvert.class); + + MemberLevelDO convert(MemberLevelCreateReqVO bean); + + MemberLevelDO convert(MemberLevelUpdateReqVO bean); + + MemberLevelRespVO convert(MemberLevelDO bean); + + List convertList(List list); + + List convertSimpleList(List list); + + List convertList02(List list); + + MemberLevelRespDTO convert02(MemberLevelDO bean); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelRecordConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelRecordConvert.java new file mode 100644 index 000000000..d01f1b63c --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelRecordConvert.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.member.convert.level; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordRespVO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 会员等级记录 Convert + * + * @author owen + */ +@Mapper +public interface MemberLevelRecordConvert { + + MemberLevelRecordConvert INSTANCE = Mappers.getMapper(MemberLevelRecordConvert.class); + + MemberLevelRecordRespVO convert(MemberLevelRecordDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + default MemberLevelRecordDO copyTo(MemberLevelDO from, MemberLevelRecordDO to) { + if (from != null) { + to.setLevelId(from.getId()); + to.setLevel(from.getLevel()); + to.setDiscountPercent(from.getDiscountPercent()); + to.setExperience(from.getExperience()); + } + return to; + } +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/package-info.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/package-info.java new file mode 100644 index 000000000..6523a6656 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/package-info.java @@ -0,0 +1,6 @@ +/** + * æä¾› POJO ç±»çš„å®žä½“è½¬æ¢ + * + * ç›®å‰ä½¿ç”¨ MapStruct 框架 + */ +package cn.iocoder.yudao.module.member.convert; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/point/MemberPointRecordConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/point/MemberPointRecordConvert.java new file mode 100644 index 000000000..1d2c146d2 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/point/MemberPointRecordConvert.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.member.convert.point; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordRespVO; +import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordRespVO; +import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * 用户积分记录 Convert + * + * @author QingX + */ +@Mapper +public interface MemberPointRecordConvert { + + MemberPointRecordConvert INSTANCE = Mappers.getMapper(MemberPointRecordConvert.class); + + default PageResult convertPage(PageResult pageResult, List users) { + PageResult voPageResult = convertPage(pageResult); + // user 拼接 + Map userMap = convertMap(users, MemberUserRespDTO::getId); + voPageResult.getList().forEach(record -> MapUtils.findAndThen(userMap, record.getUserId(), + memberUserRespDTO -> record.setNickname(memberUserRespDTO.getNickname()))); + return voPageResult; + } + PageResult convertPage(PageResult pageResult); + + PageResult convertPage02(PageResult pageResult); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/signin/MemberSignInConfigConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/signin/MemberSignInConfigConvert.java new file mode 100644 index 000000000..5acd87151 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/signin/MemberSignInConfigConvert.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.member.convert.signin; + +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.config.MemberSignInConfigCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.config.MemberSignInConfigRespVO; +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.config.MemberSignInConfigUpdateReqVO; +import cn.iocoder.yudao.module.member.controller.app.signin.vo.config.AppMemberSignInConfigRespVO; +import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 签到规则 Convert + * + * @author QingX + */ +@Mapper +public interface MemberSignInConfigConvert { + + MemberSignInConfigConvert INSTANCE = Mappers.getMapper(MemberSignInConfigConvert.class); + + MemberSignInConfigDO convert(MemberSignInConfigCreateReqVO bean); + + MemberSignInConfigDO convert(MemberSignInConfigUpdateReqVO bean); + + MemberSignInConfigRespVO convert(MemberSignInConfigDO bean); + + List convertList(List list); + + List convertList02(List list); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/signin/MemberSignInRecordConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/signin/MemberSignInRecordConvert.java new file mode 100644 index 000000000..0526ed64a --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/signin/MemberSignInRecordConvert.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.member.convert.signin; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordRespVO; +import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO; +import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO; +import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * 签到记录 Convert + * + * @author 芋é“æºç  + */ +@Mapper +public interface MemberSignInRecordConvert { + + MemberSignInRecordConvert INSTANCE = Mappers.getMapper(MemberSignInRecordConvert.class); + + default PageResult convertPage(PageResult pageResult, List users) { + PageResult voPageResult = convertPage(pageResult); + // user 拼接 + Map userMap = convertMap(users, MemberUserRespDTO::getId); + voPageResult.getList().forEach(record -> MapUtils.findAndThen(userMap, record.getUserId(), + memberUserRespDTO -> record.setNickname(memberUserRespDTO.getNickname()))); + return voPageResult; + } + + PageResult convertPage(PageResult pageResult); + + PageResult convertPage02(PageResult pageResult); + + AppMemberSignInRecordRespVO coverRecordToAppRecordVo(MemberSignInRecordDO memberSignInRecordDO); + + default MemberSignInRecordDO convert(Long userId, MemberSignInRecordDO firstRecord, List signInConfigs) { + // 1. 计算今天是第几天签到 + long day = ChronoUnit.DAYS.between(firstRecord.getCreateTime(), LocalDateTime.now()); + // 2. åˆå§‹åŒ–ç­¾åˆ°ä¿¡æ¯ + // TODO @puhui999:signInRecord=》record + MemberSignInRecordDO signInRecord = new MemberSignInRecordDO().setUserId(userId) + .setDay(Integer.parseInt(Long.toString(day))) // 设置签到天数 TODO @puhui999:day 应该跟ç€ç¬¬å‡ å¤©ç­¾åˆ°èµ°ï¼›ä¸æ˜¯ç´¯åŠ å“ˆï¼›å¦å¤– long 转 int,应该 (int) day å°±å¯ä»¥äº†ã€‚。。 + .setPoint(0) // 设置签到积分默认为 + .setExperience(0); // 设置签到ç»éªŒé»˜è®¤ä¸º 0 + // 3. 获å–签到对应的积分数 + MemberSignInConfigDO lastConfig = signInConfigs.get(signInConfigs.size() - 1); // 最大签到天数 + if (day > lastConfig.getDay()) { // 超出范围按第一天的ç»éªŒè®¡ç®— + // TODO @puhui999:ä¸èƒ½ç›´æŽ¥å– 0,万一它 day ä¸åŒ¹é…哈。就是第一天没奖励。。。 + signInRecord.setPoint(signInConfigs.get(0).getPoint()); + signInRecord.setExperience(signInConfigs.get(0).getExperience()); + return signInRecord; + } + // TODO @puhui999:signInConfig å¯ä»¥æ”¹æˆ configï¼› + MemberSignInConfigDO signInConfig = CollUtil.findOne(signInConfigs, config -> ObjUtil.equal(config.getDay(), day)); + if (signInConfig == null) { + return signInRecord; + } + signInRecord.setPoint(signInConfig.getPoint()); + signInRecord.setExperience(signInConfig.getExperience()); + return signInRecord; + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/social/SocialUserConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/social/SocialUserConvert.java new file mode 100644 index 000000000..3c9288ba8 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/social/SocialUserConvert.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.member.convert.social; + +import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserBindReqVO; +import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserUnbindReqVO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface SocialUserConvert { + + SocialUserConvert INSTANCE = Mappers.getMapper(SocialUserConvert.class); + + SocialUserBindReqDTO convert(Long userId, Integer userType, AppSocialUserBindReqVO reqVO); + + SocialUserUnbindReqDTO convert(Long userId, Integer userType, AppSocialUserUnbindReqVO reqVO); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/tag/MemberTagConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/tag/MemberTagConvert.java new file mode 100644 index 000000000..9d3a41f1a --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/tag/MemberTagConvert.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.member.convert.tag; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagRespVO; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagUpdateReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 会员标签 Convert + * + * @author 芋é“æºç  + */ +@Mapper +public interface MemberTagConvert { + + MemberTagConvert INSTANCE = Mappers.getMapper(MemberTagConvert.class); + + MemberTagDO convert(MemberTagCreateReqVO bean); + + MemberTagDO convert(MemberTagUpdateReqVO bean); + + MemberTagRespVO convert(MemberTagDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java new file mode 100644 index 000000000..aae9a7601 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.member.convert.user; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserRespVO; +import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateReqVO; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserInfoRespVO; +import cn.iocoder.yudao.module.member.convert.address.AddressConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.group.MemberGroupDO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; +import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +@Mapper(uses = {AddressConvert.class}) +public interface MemberUserConvert { + + MemberUserConvert INSTANCE = Mappers.getMapper(MemberUserConvert.class); + + AppMemberUserInfoRespVO convert(MemberUserDO bean); + + @Mapping(source = "level", target = "level") + @Mapping(source = "bean.experience", target = "experience") + AppMemberUserInfoRespVO convert(MemberUserDO bean, MemberLevelDO level); + + MemberUserRespDTO convert2(MemberUserDO bean); + + List convertList2(List list); + + MemberUserDO convert(MemberUserUpdateReqVO bean); + + PageResult convertPage(PageResult page); + + @Mapping(source = "areaId", target = "areaName", qualifiedByName = "convertAreaIdToAreaName") + MemberUserRespVO convert03(MemberUserDO bean); + + default PageResult convertPage(PageResult pageResult, + List tags, + List levels, + List groups) { + PageResult result = convertPage(pageResult); + // 处ç†å…³è”æ•°æ® + Map tagMap = convertMap(tags, MemberTagDO::getId, MemberTagDO::getName); + Map levelMap = convertMap(levels, MemberLevelDO::getId, MemberLevelDO::getName); + Map groupMap = convertMap(groups, MemberGroupDO::getId, MemberGroupDO::getName); + // å¡«å……å…³è”æ•°æ® + result.getList().forEach(user -> { + user.setTagNames(convertList(user.getTagIds(), tagMap::get)); + user.setLevelName(levelMap.get(user.getLevelId())); + user.setGroupName(groupMap.get(user.getGroupId())); + }); + return result; + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/ã€ŠèŠ‹é“ Spring Boot å¯¹è±¡è½¬æ¢ MapStruct 入门》.md b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/ã€ŠèŠ‹é“ Spring Boot å¯¹è±¡è½¬æ¢ MapStruct 入门》.md new file mode 100644 index 000000000..8153487b7 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/ã€ŠèŠ‹é“ Spring Boot å¯¹è±¡è½¬æ¢ MapStruct 入门》.md @@ -0,0 +1 @@ + diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/MemberAddressDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/MemberAddressDO.java new file mode 100644 index 000000000..f2e43b563 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/MemberAddressDO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.member.dal.dataobject.address; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * ç”¨æˆ·æ”¶ä»¶åœ°å€ DO + * + * @author 芋é“æºç  + */ +@TableName("member_address") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberAddressDO extends BaseDO { + + /** + * ç¼–å· + */ + @TableId + private Long id; + /** + * ç”¨æˆ·ç¼–å· + */ + private Long userId; + /** + * 收件人å称 + */ + private String name; + /** + * æ‰‹æœºå· + */ + private String mobile; + /** + * åœ°åŒºç¼–å· + */ + private Long areaId; + /** + * æ”¶ä»¶è¯¦ç»†åœ°å€ + */ + private String detailAddress; + /** + * 是å¦é»˜è®¤ + * + * true - é»˜è®¤æ”¶ä»¶åœ°å€ + */ + private Boolean defaultStatus; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/config/MemberConfigDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/config/MemberConfigDO.java new file mode 100644 index 000000000..6efb4a1c0 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/config/MemberConfigDO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.member.dal.dataobject.config; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 会员é…ç½® DO + * + * @author QingX + */ +@TableName(value = "member_config", autoResultMap = true) +@KeySequence("member_config_seq") // 用于 Oracleã€PostgreSQLã€Kingbaseã€DB2ã€H2 æ•°æ®åº“的主键自增。如果是 MySQL 等数æ®åº“,å¯ä¸å†™ã€‚ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberConfigDO extends BaseDO { + + /** + * 自增主键 + */ + @TableId + private Long id; + /** + * 积分抵扣开关 + */ + private Boolean pointTradeDeductEnable; + /** + * 积分抵扣,å•ä½ï¼šåˆ† + * + * 1 积分抵扣多少分 + */ + private Integer pointTradeDeductUnitPrice; + /** + * 积分抵扣最大值 + */ + private Integer pointTradeDeductMaxPrice; + /** + * 1 元赠é€å¤šå°‘分 + */ + private Integer pointTradeGivePoint; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/group/MemberGroupDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/group/MemberGroupDO.java new file mode 100644 index 000000000..c9a82ab5d --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/group/MemberGroupDO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.member.dal.dataobject.group; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 用户分组 DO + * + * @author owen + */ +@TableName("member_group") +@KeySequence("member_group_seq") // 用于 Oracleã€PostgreSQLã€Kingbaseã€DB2ã€H2 æ•°æ®åº“的主键自增。如果是 MySQL 等数æ®åº“,å¯ä¸å†™ã€‚ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberGroupDO extends BaseDO { + + /** + * ç¼–å· + */ + @TableId + private Long id; + /** + * å称 + */ + private String name; + /** + * 备注 + */ + private String remark; + /** + * çŠ¶æ€ + *

+ * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberExperienceRecordDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberExperienceRecordDO.java new file mode 100644 index 000000000..d7c06d4ba --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberExperienceRecordDO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.member.dal.dataobject.level; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 会员ç»éªŒè®°å½• DO + * + * @author owen + */ +@TableName("member_experience_record") +@KeySequence("member_experience_record_seq") // 用于 Oracleã€PostgreSQLã€Kingbaseã€DB2ã€H2 æ•°æ®åº“的主键自增。如果是 MySQL 等数æ®åº“,å¯ä¸å†™ã€‚ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberExperienceRecordDO extends BaseDO { + + /** + * ç¼–å· + */ + @TableId + private Long id; + /** + * ç”¨æˆ·ç¼–å· + * + * å…³è” {@link MemberUserDO#getId()} 字段 + */ + private Long userId; + /** + * 业务类型 + *

+ * 枚举 {@link MemberExperienceBizTypeEnum} + */ + private Integer bizType; + /** + * ä¸šåŠ¡ç¼–å· + */ + private String bizId; + /** + * 标题 + */ + private String title; + /** + * æè¿° + */ + private String description; + /** + * ç»éªŒ + */ + private Integer experience; + /** + * å˜æ›´åŽçš„ç»éªŒ + */ + private Integer totalExperience; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberLevelDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberLevelDO.java new file mode 100644 index 000000000..05035ffe5 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberLevelDO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.member.dal.dataobject.level; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 会员等级 DO + * + * é…ç½®æ¯ä¸ªç­‰çº§éœ€è¦çš„积分 + * + * @author owen + */ +@TableName("member_level") +@KeySequence("member_level_seq") // 用于 Oracleã€PostgreSQLã€Kingbaseã€DB2ã€H2 æ•°æ®åº“的主键自增。如果是 MySQL 等数æ®åº“,å¯ä¸å†™ã€‚ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberLevelDO extends BaseDO { + + /** + * ç¼–å· + */ + @TableId + private Long id; + /** + * 等级å称 + */ + private String name; + /** + * 等级 + */ + private Integer level; + /** + * å‡çº§ç»éªŒ + */ + private Integer experience; + /** + * 享å—折扣 + */ + private Integer discountPercent; + + /** + * 等级图标 + */ + private String icon; + /** + * 等级背景图 + */ + private String backgroundUrl; + /** + * çŠ¶æ€ + *

+ * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberLevelRecordDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberLevelRecordDO.java new file mode 100644 index 000000000..8b5451d45 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberLevelRecordDO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.member.dal.dataobject.level; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 会员等级记录 DO + * + * 用户æ¯æ¬¡ç­‰çº§å‘生å˜æ›´æ—¶ï¼Œè®°å½•ä¸€æ¡æ—¥å¿— + * + * @author owen + */ +@TableName("member_level_record") +@KeySequence("member_level_record_seq") // 用于 Oracleã€PostgreSQLã€Kingbaseã€DB2ã€H2 æ•°æ®åº“的主键自增。如果是 MySQL 等数æ®åº“,å¯ä¸å†™ã€‚ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberLevelRecordDO extends BaseDO { + + /** + * ç¼–å· + */ + @TableId + private Long id; + /** + * ç”¨æˆ·ç¼–å· + * + * å…³è” {@link MemberUserDO#getId()} 字段 + */ + private Long userId; + /** + * ç­‰çº§ç¼–å· + * + * å…³è” {@link MemberLevelDO#getId()} 字段 + */ + private Long levelId; + /** + * 会员等级 + * + * 冗余 {@link MemberLevelDO#getLevel()} 字段 + */ + private Integer level; + /** + * 享å—折扣 + */ + private Integer discountPercent; + /** + * å‡çº§ç»éªŒ + */ + private Integer experience; + /** + * 会员此时的ç»éªŒ + */ + private Integer userExperience; + /** + * 备注 + */ + private String remark; + /** + * æè¿° + */ + private String description; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/point/MemberPointRecordDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/point/MemberPointRecordDO.java new file mode 100644 index 000000000..f884f08d8 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/point/MemberPointRecordDO.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.member.dal.dataobject.point; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 用户积分记录 DO + * + * @author QingX + */ +@TableName("member_point_record") +@KeySequence("member_point_record_seq") // 用于 Oracleã€PostgreSQLã€Kingbaseã€DB2ã€H2 æ•°æ®åº“的主键自增。如果是 MySQL 等数æ®åº“,å¯ä¸å†™ã€‚ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberPointRecordDO extends BaseDO { + + /** + * 自增主键 + */ + @TableId + private Long id; + /** + * ç”¨æˆ·ç¼–å· + * + * 对应 MemberUserDO çš„ id 属性 + */ + private Long userId; + + /** + * ä¸šåŠ¡ç¼–ç  + */ + private String bizId; + /** + * 业务类型 + * + * 枚举 {@link MemberPointBizTypeEnum} + */ + private Integer bizType; + + /** + * 积分标题 + */ + private String title; + /** + * 积分æè¿° + */ + private String description; + + /** + * å˜åŠ¨ç§¯åˆ† + * + * 1ã€æ­£æ•°è¡¨ç¤ºèŽ·å¾—积分 + * 2ã€è´Ÿæ•°è¡¨ç¤ºæ¶ˆè€—积分 + */ + private Integer point; + /** + * å˜åŠ¨åŽçš„积分 + */ + private Integer totalPoint; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/signin/MemberSignInConfigDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/signin/MemberSignInConfigDO.java new file mode 100644 index 000000000..76d55c9bf --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/signin/MemberSignInConfigDO.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.member.dal.dataobject.signin; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 签到规则 DO + * + * @author QingX + */ +@TableName("member_sign_in_config") +@KeySequence("member_sign_in_config_seq") // 用于 Oracleã€PostgreSQLã€Kingbaseã€DB2ã€H2 æ•°æ®åº“的主键自增。如果是 MySQL 等数æ®åº“,å¯ä¸å†™ã€‚ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberSignInConfigDO extends BaseDO { + + /** + * 规则自增主键 + */ + @TableId + private Long id; + /** + * 签到第 x 天 + */ + private Integer day; + /** + * 奖励积分 + */ + private Integer point; + /** + * 奖励ç»éªŒ + */ + private Integer experience; + + /** + * çŠ¶æ€ + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/signin/MemberSignInRecordDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/signin/MemberSignInRecordDO.java new file mode 100644 index 000000000..b07b5efbc --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/signin/MemberSignInRecordDO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.member.dal.dataobject.signin; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 签到记录 DO + * + * @author 芋é“æºç  + */ +@TableName("member_sign_in_record") +@KeySequence("member_sign_in_record_seq") // 用于 Oracleã€PostgreSQLã€Kingbaseã€DB2ã€H2 æ•°æ®åº“的主键自增。如果是 MySQL 等数æ®åº“,å¯ä¸å†™ã€‚ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberSignInRecordDO extends BaseDO { + + /** + * ç¼–å· + */ + @TableId + private Long id; + /** + * 签到用户 + */ + private Long userId; + /** + * 第几天签到 + */ + private Integer day; + /** + * 签到的积分 + */ + private Integer point; + /** + * 签到的ç»éªŒ + */ + private Integer experience; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/tag/MemberTagDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/tag/MemberTagDO.java new file mode 100644 index 000000000..b984064e0 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/tag/MemberTagDO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.member.dal.dataobject.tag; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 会员标签 DO + * + * @author 芋é“æºç  + */ +@TableName("member_tag") +@KeySequence("member_tag_seq") // 用于 Oracleã€PostgreSQLã€Kingbaseã€DB2ã€H2 æ•°æ®åº“的主键自增。如果是 MySQL 等数æ®åº“,å¯ä¸å†™ã€‚ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberTagDO extends BaseDO { + + /** + * ç¼–å· + */ + @TableId + private Long id; + /** + * 标签å称 + */ + private String name; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java new file mode 100644 index 000000000..97ddc191d --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java @@ -0,0 +1,145 @@ +package cn.iocoder.yudao.module.member.dal.dataobject.user; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.enums.TerminalEnum; +import cn.iocoder.yudao.framework.ip.core.Area; +import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; +import cn.iocoder.yudao.module.member.dal.dataobject.group.MemberGroupDO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; +import cn.iocoder.yudao.module.system.enums.common.SexEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 会员用户 DO + * + * uk_mobile 索引:基于 {@link #mobile} 字段 + * + * @author 芋é“æºç  + */ +@TableName(value = "member_user", autoResultMap = true) +@KeySequence("member_user_seq") // 用于 Oracleã€PostgreSQLã€Kingbaseã€DB2ã€H2 æ•°æ®åº“的主键自增。如果是 MySQL 等数æ®åº“,å¯ä¸å†™ã€‚ +@Data +@EqualsAndHashCode(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberUserDO extends TenantBaseDO { + + // ========== è´¦å·ä¿¡æ¯ ========== + + /** + * 用户ID + */ + @TableId + private Long id; + /** + * 手机 + */ + private String mobile; + /** + * 加密åŽçš„å¯†ç  + * + * 因为目å‰ä½¿ç”¨ {@link BCryptPasswordEncoder} åŠ å¯†å™¨ï¼Œæ‰€ä»¥æ— éœ€è‡ªå·±å¤„ç† salt ç› + */ + private String password; + /** + * å¸å·çŠ¶æ€ + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + /** + * 注册 IP + */ + private String registerIp; + /** + * 注册终端 + * 枚举 {@link TerminalEnum} + */ + private Integer registerTerminal; + /** + * 最åŽç™»å½•IP + */ + private String loginIp; + /** + * 最åŽç™»å½•æ—¶é—´ + */ + private LocalDateTime loginDate; + + // ========== åŸºç¡€ä¿¡æ¯ ========== + + /** + * 用户昵称 + */ + private String nickname; + /** + * ç”¨æˆ·å¤´åƒ + */ + private String avatar; + + /** + * 真实åå­— + */ + private String name; + /** + * 性别 + * + * 枚举 {@link SexEnum} + */ + private Integer sex; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 所在地 + * + * å…³è” {@link Area#getId()} 字段 + */ + private Integer areaId; + /** + * 用户备注 + */ + private String mark; + + // ========== å…¶å®ƒä¿¡æ¯ ========== + + /** + * 积分 + */ + private Integer point; + // TODO 疯狂:增加一个 totalPoint;个人信æ¯æŽ¥å£è¦è¿”回 + + /** + * 会员标签列表,以逗å·åˆ†éš” + */ + @TableField(typeHandler = LongListTypeHandler.class) + private List tagIds; + + /** + * ä¼šå‘˜çº§åˆ«ç¼–å· + * + * å…³è” {@link MemberLevelDO#getId()} 字段 + */ + private Long levelId; + /** + * 会员ç»éªŒ + */ + private Integer experience; + /** + * ç”¨æˆ·åˆ†ç»„ç¼–å· + * + * å…³è” {@link MemberGroupDO#getId()} 字段 + */ + private Long groupId; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/MemberAddressMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/MemberAddressMapper.java new file mode 100644 index 000000000..3df68c51a --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/MemberAddressMapper.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.member.dal.mysql.address; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface MemberAddressMapper extends BaseMapperX { + + default MemberAddressDO selectByIdAndUserId(Long id, Long userId) { + return selectOne(MemberAddressDO::getId, id, MemberAddressDO::getUserId, userId); + } + + default List selectListByUserIdAndDefaulted(Long userId, Boolean defaulted) { + return selectList(new LambdaQueryWrapperX().eq(MemberAddressDO::getUserId, userId) + .eqIfPresent(MemberAddressDO::getDefaultStatus, defaulted)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/config/MemberConfigMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/config/MemberConfigMapper.java new file mode 100644 index 000000000..e03938378 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/config/MemberConfigMapper.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.member.dal.mysql.config; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.member.dal.dataobject.config.MemberConfigDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 积分设置 Mapper + * + * @author QingX + */ +@Mapper +public interface MemberConfigMapper extends BaseMapperX { +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/group/MemberGroupMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/group/MemberGroupMapper.java new file mode 100644 index 000000000..da4f7b7a8 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/group/MemberGroupMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.member.dal.mysql.group; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupPageReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.group.MemberGroupDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 用户分组 Mapper + * + * @author owen + */ +@Mapper +public interface MemberGroupMapper extends BaseMapperX { + + default PageResult selectPage(MemberGroupPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MemberGroupDO::getName, reqVO.getName()) + .eqIfPresent(MemberGroupDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MemberGroupDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MemberGroupDO::getId)); + } + + default List selectListByStatus(Integer status) { + return selectList(MemberGroupDO::getStatus, status); + } +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberExperienceRecordMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberExperienceRecordMapper.java new file mode 100644 index 000000000..4e5f6f567 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberExperienceRecordMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.member.dal.mysql.level; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordPageReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 会员ç»éªŒè®°å½• Mapper + * + * @author owen + */ +@Mapper +public interface MemberExperienceRecordMapper extends BaseMapperX { + + default PageResult selectPage(MemberExperienceRecordPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MemberExperienceRecordDO::getUserId, reqVO.getUserId()) + .eqIfPresent(MemberExperienceRecordDO::getBizId, reqVO.getBizId()) + .eqIfPresent(MemberExperienceRecordDO::getBizType, reqVO.getBizType()) + .eqIfPresent(MemberExperienceRecordDO::getTitle, reqVO.getTitle()) + .betweenIfPresent(MemberExperienceRecordDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MemberExperienceRecordDO::getId)); + } + + default PageResult selectPage(Long userId, PageParam pageParam) { + return selectPage(pageParam, new LambdaQueryWrapper() + .eq(MemberExperienceRecordDO::getUserId, userId) + .orderByDesc(MemberExperienceRecordDO::getId)); + } +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelMapper.java new file mode 100644 index 000000000..d2dcb6cb4 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelMapper.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.member.dal.mysql.level; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelListReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 会员等级 Mapper + * + * @author owen + */ +@Mapper +public interface MemberLevelMapper extends BaseMapperX { + + default List selectList(MemberLevelListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(MemberLevelDO::getName, reqVO.getName()) + .eqIfPresent(MemberLevelDO::getStatus, reqVO.getStatus()) + .orderByAsc(MemberLevelDO::getLevel)); + } + + + default List selectListByStatus(Integer status) { + return selectList(new LambdaQueryWrapperX() + .eq(MemberLevelDO::getStatus, status) + .orderByAsc(MemberLevelDO::getLevel)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelRecordMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelRecordMapper.java new file mode 100644 index 000000000..6808b957a --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelRecordMapper.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.member.dal.mysql.level; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordPageReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 会员等级记录 Mapper + * + * @author owen + */ +@Mapper +public interface MemberLevelRecordMapper extends BaseMapperX { + + default PageResult selectPage(MemberLevelRecordPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MemberLevelRecordDO::getUserId, reqVO.getUserId()) + .eqIfPresent(MemberLevelRecordDO::getLevelId, reqVO.getLevelId()) + .betweenIfPresent(MemberLevelRecordDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MemberLevelRecordDO::getId)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/point/MemberPointRecordMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/point/MemberPointRecordMapper.java new file mode 100644 index 000000000..5c3370929 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/point/MemberPointRecordMapper.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.member.dal.mysql.point; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordPageReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Set; + +/** + * 用户积分记录 Mapper + * + * @author QingX + */ +@Mapper +public interface MemberPointRecordMapper extends BaseMapperX { + + default PageResult selectPage(MemberPointRecordPageReqVO reqVO, Set userIds) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .inIfPresent(MemberPointRecordDO::getUserId, userIds) + .eqIfPresent(MemberPointRecordDO::getUserId, reqVO.getUserId()) + .eqIfPresent(MemberPointRecordDO::getBizType, reqVO.getBizType()) + .likeIfPresent(MemberPointRecordDO::getTitle, reqVO.getTitle()) + .orderByDesc(MemberPointRecordDO::getId)); + } + + default PageResult selectPage(Long userId, PageParam pageVO) { + return selectPage(pageVO, new LambdaQueryWrapperX() + .eq(MemberPointRecordDO::getUserId, userId) + .orderByDesc(MemberPointRecordDO::getId)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/signin/MemberSignInConfigMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/signin/MemberSignInConfigMapper.java new file mode 100644 index 000000000..211ead33d --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/signin/MemberSignInConfigMapper.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.member.dal.mysql.signin; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 签到规则 Mapper + * + * @author QingX + */ +@Mapper +public interface MemberSignInConfigMapper extends BaseMapperX { + + default MemberSignInConfigDO selectByDay(Integer day) { + return selectOne(MemberSignInConfigDO::getDay, day); + } + + default List selectListByStatus(Integer status) { + return selectList(MemberSignInConfigDO::getStatus, status); + } +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/signin/MemberSignInRecordMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/signin/MemberSignInRecordMapper.java new file mode 100644 index 000000000..01fe75c14 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/signin/MemberSignInRecordMapper.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.member.dal.mysql.signin; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordPageReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Set; + +/** + * 签到记录 Mapper + * + * @author 芋é“æºç  + */ +@Mapper +public interface MemberSignInRecordMapper extends BaseMapperX { + + default PageResult selectPage(MemberSignInRecordPageReqVO reqVO, Set userIds) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .inIfPresent(MemberSignInRecordDO::getUserId, userIds) + .eqIfPresent(MemberSignInRecordDO::getUserId, reqVO.getUserId()) + .eqIfPresent(MemberSignInRecordDO::getDay, reqVO.getDay()) + .betweenIfPresent(MemberSignInRecordDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MemberSignInRecordDO::getId)); + } + + default PageResult selectPage(Long userId, PageParam pageParam) { + return selectPage(pageParam, new LambdaQueryWrapperX() + .eq(MemberSignInRecordDO::getUserId, userId) + .orderByDesc(MemberSignInRecordDO::getId)); + } + + // TODO @puhui999:这 2 个方法,是ä¸æ˜¯ä¸€ä¸ª first;一个 last å°±å¯ä»¥äº†ã€‚。 + /** + * 获å–用户最近的签到记录信æ¯ï¼Œæ ¹æ®ç­¾åˆ°æ—¶é—´å€’åº + * + * @param userId ç”¨æˆ·ç¼–å· + * @return 签到记录列表 + */ + default MemberSignInRecordDO selectLastRecordByUserIdDesc(Long userId) { + return selectOne(new QueryWrapper() + .eq("user_id", userId) + .orderByDesc("create_time") + .last("limit 1")); + } + + /** + * 获å–用户最早的签到记录信æ¯,æ ¹æ®ç­¾åˆ°æ—¶é—´å€’åº + * + * @param userId ç”¨æˆ·ç¼–å· + * @return 签到记录列表 + */ + default MemberSignInRecordDO selectLastRecordByUserIdAsc(Long userId) { + return selectOne(new QueryWrapper() + .eq("user_id", userId) + .orderByAsc("create_time") + .last("limit 1")); + } + + default Long selectCountByUserId(Long userId) { + // TODO @puhui999:å¯ä»¥ä½¿ç”¨ selectCount 里é¢å…许传递字段的方法 + return selectCount(new LambdaQueryWrapperX() + .eq(MemberSignInRecordDO::getUserId, userId)); + } + + /** + * 获å–用户的签到记录列表信æ¯,æ ¹æ®ç­¾åˆ°æ—¶é—´å€’åº + * + * @param userId ç”¨æˆ·ç¼–å· + * @return ç­¾åˆ°è®°å½•ä¿¡æ¯ + */ + // TODO @puhui999:这个排åºï¼Œå¯ä»¥äº¤ç»™ service 哈; + default List selectListByUserId(Long userId) { + return selectList(new LambdaQueryWrapperX() + .eq(MemberSignInRecordDO::getUserId, userId) + .orderByDesc(MemberSignInRecordDO::getCreateTime)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/tag/MemberTagMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/tag/MemberTagMapper.java new file mode 100644 index 000000000..f4723e282 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/tag/MemberTagMapper.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.member.dal.mysql.tag; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagPageReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 会员标签 Mapper + * + * @author 芋é“æºç  + */ +@Mapper +public interface MemberTagMapper extends BaseMapperX { + + default PageResult selectPage(MemberTagPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MemberTagDO::getName, reqVO.getName()) + .betweenIfPresent(MemberTagDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MemberTagDO::getId)); + } + + default MemberTagDO selelctByName(String name) { + return selectOne(MemberTagDO::getName, name); + } +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java new file mode 100644 index 000000000..3f871020c --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java @@ -0,0 +1,96 @@ +package cn.iocoder.yudao.module.member.dal.mysql.user; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 会员 User Mapper + * + * @author 芋é“æºç  + */ +@Mapper +public interface MemberUserMapper extends BaseMapperX { + + default MemberUserDO selectByMobile(String mobile) { + return selectOne(MemberUserDO::getMobile, mobile); + } + + default List selectListByNicknameLike(String nickname) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(MemberUserDO::getNickname, nickname)); + } + + default PageResult selectPage(MemberUserPageReqVO reqVO) { + // å¤„ç† tagIds 过滤æ¡ä»¶ + String tagIdSql = ""; + if (CollUtil.isNotEmpty(reqVO.getTagIds())) { + tagIdSql = reqVO.getTagIds().stream() + .map(tagId -> "FIND_IN_SET(" + tagId + ", tag_ids)") + .collect(Collectors.joining(" OR ")); + } + // 分页查询 + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MemberUserDO::getMobile, reqVO.getMobile()) + .betweenIfPresent(MemberUserDO::getLoginDate, reqVO.getLoginDate()) + .likeIfPresent(MemberUserDO::getNickname, reqVO.getNickname()) + .betweenIfPresent(MemberUserDO::getCreateTime, reqVO.getCreateTime()) + .eqIfPresent(MemberUserDO::getLevelId, reqVO.getLevelId()) + .eqIfPresent(MemberUserDO::getGroupId, reqVO.getGroupId()) + .apply(StrUtil.isNotEmpty(tagIdSql), tagIdSql) + .orderByDesc(MemberUserDO::getId)); + } + + default Long selectCountByGroupId(Long groupId) { + return selectCount(MemberUserDO::getGroupId, groupId); + } + + default Long selectCountByLevelId(Long levelId) { + return selectCount(MemberUserDO::getLevelId, levelId); + } + + default Long selectCountByTagId(Long tagId) { + return selectCount(new LambdaQueryWrapperX() + .apply("FIND_IN_SET({0}, tag_ids)", tagId)); + } + + /** + * 更新用户积分(增加) + * + * @param id ç”¨æˆ·ç¼–å· + * @param incrCount 增加积分(正数) + */ + default void updatePointIncr(Long id, Integer incrCount) { + Assert.isTrue(incrCount > 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" point = point + " + incrCount) + .eq(MemberUserDO::getId, id); + update(null, lambdaUpdateWrapper); + } + + /** + * 更新用户积分(å‡å°‘) + * + * @param id ç”¨æˆ·ç¼–å· + * @param incrCount 增加积分(负数) + * @return 更新行数 + */ + default int updatePointDecr(Long id, Integer incrCount) { + Assert.isTrue(incrCount < 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" point = point + " + incrCount) // 负数,所以使用 + å· + .eq(MemberUserDO::getId, id); + return update(null, lambdaUpdateWrapper); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/package-info.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/package-info.java new file mode 100644 index 000000000..a45c2a161 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/package-info.java @@ -0,0 +1,9 @@ +/** + * DAL = Data Access Layer æ•°æ®è®¿é—®å±‚ + * 1. data object:数æ®å¯¹è±¡ + * 2. redis:Redis çš„ CRUD æ“作 + * 3. mysql:MySQL çš„ CRUD æ“作 + * + * 其中,MySQL 的表以 member_ 作为å‰ç¼€ + */ +package cn.iocoder.yudao.module.member.dal; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/redis/package-info.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/redis/package-info.java new file mode 100644 index 000000000..8dfa9fb20 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/redis/package-info.java @@ -0,0 +1,4 @@ +/** + * å ä½ï¼ŒåŽç»­æœ‰ç±»åŽï¼Œå¯ä»¥åˆ é™¤ï¼Œé¿å… package 无法æ交到 Git 上 + */ +package cn.iocoder.yudao.module.member.dal.redis; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/package-info.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/package-info.java new file mode 100644 index 000000000..7e9ca95de --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于 member 模å—çš„ framework å°è£… + * + * @author 芋é“æºç  + */ +package cn.iocoder.yudao.module.member.framework; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/web/config/MemberWebConfiguration.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/web/config/MemberWebConfiguration.java new file mode 100644 index 000000000..82c70034e --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/web/config/MemberWebConfiguration.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.member.framework.web.config; + +import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration; +import org.springdoc.core.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * member 模å—çš„ web 组件的 Configuration + * + * @author 芋é“æºç  + */ +@Configuration(proxyBeanMethods = false) +public class MemberWebConfiguration { + + /** + * member 模å—çš„ API 分组 + */ + @Bean + public GroupedOpenApi memberGroupedOpenApi() { + return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("member"); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/web/package-info.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/web/package-info.java new file mode 100644 index 000000000..3a964cfc2 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/web/package-info.java @@ -0,0 +1,4 @@ +/** + * member 模å—çš„ web é…ç½® + */ +package cn.iocoder.yudao.module.member.framework.web; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/message/user/UserCreateMessage.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/message/user/UserCreateMessage.java new file mode 100644 index 000000000..509527b09 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/message/user/UserCreateMessage.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.member.mq.message.user; + +import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.NotNull; + +/** + * ä¼šå‘˜ç”¨æˆ·åˆ›å»ºæ¶ˆæ¯ + * + * @author owen + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class UserCreateMessage extends AbstractStreamMessage { + + /** + * ç”¨æˆ·ç¼–å· + */ + @NotNull(message = "用户编å·ä¸èƒ½ä¸ºç©º") + private Long userId; + + @Override + public String getStreamKey() { + return "member.create.send"; + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/user/UserCreateProducer.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/user/UserCreateProducer.java new file mode 100644 index 000000000..6337b9f00 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/user/UserCreateProducer.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.member.mq.producer.user; + +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; +import cn.iocoder.yudao.module.member.mq.message.user.UserCreateMessage; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 会员用户创建 Producer + * + * @author owen + */ +@Slf4j +@Component +public class UserCreateProducer { + + @Resource + private RedisMQTemplate redisMQTemplate; + + /** + * å‘é€ {@link UserCreateMessage} æ¶ˆæ¯ + * + * @param userId ç”¨æˆ·ç¼–å· + */ + public void sendUserCreateMessage(Long userId) { + redisMQTemplate.send(new UserCreateMessage().setUserId(userId)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/package-info.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/package-info.java new file mode 100644 index 000000000..405aa4cbf --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/package-info.java @@ -0,0 +1,8 @@ +/** + * member 模å—,我们放会员业务。 + * 例如说:会员中心等等 + * + * 1. Controller URL:以 /member/ 开头,é¿å…和其它 Module å†²çª + * 2. DataObject 表å:以 member_ 开头,方便在数æ®åº“中区分 + */ +package cn.iocoder.yudao.module.member; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java new file mode 100644 index 000000000..099c49c42 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.member.service.address; + +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; + +import javax.validation.Valid; +import java.util.List; + +/** + * ç”¨æˆ·æ”¶ä»¶åœ°å€ Service æŽ¥å£ + * + * @author 芋é“æºç  + */ +public interface AddressService { + + /** + * åˆ›å»ºç”¨æˆ·æ”¶ä»¶åœ°å€ + * + * + * @param userId ç”¨æˆ·ç¼–å· + * @param createReqVO åˆ›å»ºä¿¡æ¯ + * @return ç¼–å· + */ + Long createAddress(Long userId, @Valid AppAddressCreateReqVO createReqVO); + + /** + * æ›´æ–°ç”¨æˆ·æ”¶ä»¶åœ°å€ + * + * @param userId ç”¨æˆ·ç¼–å· + * @param updateReqVO æ›´æ–°ä¿¡æ¯ + */ + void updateAddress(Long userId, @Valid AppAddressUpdateReqVO updateReqVO); + + /** + * åˆ é™¤ç”¨æˆ·æ”¶ä»¶åœ°å€ + * + * @param userId ç”¨æˆ·ç¼–å· + * @param id ç¼–å· + */ + void deleteAddress(Long userId, Long id); + + /** + * èŽ·å¾—ç”¨æˆ·æ”¶ä»¶åœ°å€ + * + * @param id ç¼–å· + * @return ç”¨æˆ·æ”¶ä»¶åœ°å€ + */ + MemberAddressDO getAddress(Long userId, Long id); + + /** + * 获得用户收件地å€åˆ—表 + * + * @param userId ç”¨æˆ·ç¼–å· + * @return 用户收件地å€åˆ—表 + */ + List getAddressList(Long userId); + + /** + * èŽ·å¾—ç”¨æˆ·é»˜è®¤çš„æ”¶ä»¶åœ°å€ + * + * @param userId ç”¨æˆ·ç¼–å· + * @return ç”¨æˆ·æ”¶ä»¶åœ°å€ + */ + MemberAddressDO getDefaultUserAddress(Long userId); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java new file mode 100644 index 000000000..901f1b340 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.member.service.address; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; +import cn.iocoder.yudao.module.member.convert.address.AddressConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; +import cn.iocoder.yudao.module.member.dal.mysql.address.MemberAddressMapper; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.ADDRESS_NOT_EXISTS; + +/** + * ç”¨æˆ·æ”¶ä»¶åœ°å€ Service 实现类 + * + * @author 芋é“æºç  + */ +@Service +@Validated +public class AddressServiceImpl implements AddressService { + + @Resource + private MemberAddressMapper memberAddressMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createAddress(Long userId, AppAddressCreateReqVO createReqVO) { + // 如果添加的是默认收件地å€ï¼Œåˆ™å°†åŽŸé»˜è®¤åœ°å€ä¿®æ”¹ä¸ºéžé»˜è®¤ + if (Boolean.TRUE.equals(createReqVO.getDefaultStatus())) { + List addresses = memberAddressMapper.selectListByUserIdAndDefaulted(userId, true); + addresses.forEach(address -> memberAddressMapper.updateById(new MemberAddressDO().setId(address.getId()).setDefaultStatus(false))); + } + + // æ’å…¥ + MemberAddressDO address = AddressConvert.INSTANCE.convert(createReqVO); + address.setUserId(userId); + memberAddressMapper.insert(address); + // 返回 + return address.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateAddress(Long userId, AppAddressUpdateReqVO updateReqVO) { + // 校验存在,校验是å¦èƒ½å¤Ÿæ“作 + validAddressExists(userId, updateReqVO.getId()); + + // 如果修改的是默认收件地å€ï¼Œåˆ™å°†åŽŸé»˜è®¤åœ°å€ä¿®æ”¹ä¸ºéžé»˜è®¤ + if (Boolean.TRUE.equals(updateReqVO.getDefaultStatus())) { + List addresses = memberAddressMapper.selectListByUserIdAndDefaulted(userId, true); + addresses.stream().filter(u -> !u.getId().equals(updateReqVO.getId())) // 排除自己 + .forEach(address -> memberAddressMapper.updateById(new MemberAddressDO().setId(address.getId()).setDefaultStatus(false))); + } + + // æ›´æ–° + MemberAddressDO updateObj = AddressConvert.INSTANCE.convert(updateReqVO); + memberAddressMapper.updateById(updateObj); + } + + @Override + public void deleteAddress(Long userId, Long id) { + // 校验存在,校验是å¦èƒ½å¤Ÿæ“作 + validAddressExists(userId, id); + // 删除 + memberAddressMapper.deleteById(id); + } + + private void validAddressExists(Long userId, Long id) { + MemberAddressDO addressDO = getAddress(userId, id); + if (addressDO == null) { + throw exception(ADDRESS_NOT_EXISTS); + } + } + + @Override + public MemberAddressDO getAddress(Long userId, Long id) { + return memberAddressMapper.selectByIdAndUserId(id, userId); + } + + @Override + public List getAddressList(Long userId) { + return memberAddressMapper.selectListByUserIdAndDefaulted(userId, null); + } + + @Override + public MemberAddressDO getDefaultUserAddress(Long userId) { + List addresses = memberAddressMapper.selectListByUserIdAndDefaulted(userId, true); + return CollUtil.getFirst(addresses); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java new file mode 100644 index 000000000..9ab878817 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.member.service.auth; + +import cn.iocoder.yudao.framework.common.enums.TerminalEnum; +import cn.iocoder.yudao.module.member.controller.app.auth.vo.*; + +import javax.validation.Valid; + +/** + * ä¼šå‘˜çš„è®¤è¯ Service æŽ¥å£ + * + * æ供用户的账å·å¯†ç ç™»å½•ã€token 的校验等认è¯ç›¸å…³çš„功能 + * + * @author 芋é“æºç  + */ +public interface MemberAuthService { + + /** + * 手机 + 密ç ç™»å½• + * + * @param reqVO ç™»å½•ä¿¡æ¯ + * @return 登录结果 + */ + AppAuthLoginRespVO login(@Valid AppAuthLoginReqVO reqVO); + + /** + * 基于 token 退出登录 + * + * @param token token + */ + void logout(String token); + + /** + * 手机 + 验è¯ç ç™»é™† + * + * @param reqVO ç™»é™†ä¿¡æ¯ + * @param terminal 终端 {@link TerminalEnum} + * @return 登录结果 + */ + AppAuthLoginRespVO smsLogin(@Valid AppAuthSmsLoginReqVO reqVO, Integer terminal); + + /** + * 社交登录,使用 code 授æƒç  + * + * @param reqVO ç™»å½•ä¿¡æ¯ + * @return 登录结果 + */ + AppAuthLoginRespVO socialLogin(@Valid AppAuthSocialLoginReqVO reqVO); + + /** + * 微信å°ç¨‹åºçš„一键登录 + * + * @param reqVO ç™»å½•ä¿¡æ¯ + * @return 登录结果 + */ + AppAuthLoginRespVO weixinMiniAppLogin(AppAuthWeixinMiniAppLoginReqVO reqVO); + + /** + * èŽ·å¾—ç¤¾äº¤è®¤è¯ URL + * + * @param type 社交平å°ç±»åž‹ + * @param redirectUri è·³è½¬åœ°å€ + * @return è®¤è¯ URL + */ + String getSocialAuthorizeUrl(Integer type, String redirectUri); + + /** + * 给用户å‘é€çŸ­ä¿¡éªŒè¯ç  + * + * @param userId ç”¨æˆ·ç¼–å· + * @param reqVO å‘é€ä¿¡æ¯ + */ + void sendSmsCode(Long userId, AppAuthSmsSendReqVO reqVO); + + /** + * 校验短信验è¯ç æ˜¯å¦æ­£ç¡® + * + * @param userId ç”¨æˆ·ç¼–å· + * @param reqVO æ ¡éªŒä¿¡æ¯ + */ + void validateSmsCode(Long userId, AppAuthSmsValidateReqVO reqVO); + + /** + * 刷新访问令牌 + * + * @param refreshToken 刷新令牌 + * @return 登录结果 + */ + AppAuthLoginRespVO refreshToken(String refreshToken); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java new file mode 100644 index 000000000..b6e88fd41 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java @@ -0,0 +1,264 @@ +package cn.iocoder.yudao.module.member.service.auth; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.enums.TerminalEnum; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; +import cn.iocoder.yudao.module.member.controller.app.auth.vo.*; +import cn.iocoder.yudao.module.member.convert.auth.AuthConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import cn.iocoder.yudao.module.system.api.logger.LoginLogApi; +import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; +import cn.iocoder.yudao.module.system.api.oauth2.OAuth2TokenApi; +import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCreateReqDTO; +import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO; +import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; +import cn.iocoder.yudao.module.system.api.social.SocialClientApi; +import cn.iocoder.yudao.module.system.api.social.SocialUserApi; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO; +import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; +import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; +import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2ClientConstants; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*; + +/** + * ä¼šå‘˜çš„è®¤è¯ Service æŽ¥å£ + * + * @author 芋é“æºç  + */ +@Service +@Slf4j +public class MemberAuthServiceImpl implements MemberAuthService { + + @Resource + private MemberUserService userService; + @Resource + private SmsCodeApi smsCodeApi; + @Resource + private LoginLogApi loginLogApi; + @Resource + private SocialUserApi socialUserApi; + @Resource + private SocialClientApi socialClientApi; + @Resource + private OAuth2TokenApi oauth2TokenApi; + + @Override + public AppAuthLoginRespVO login(AppAuthLoginReqVO reqVO) { + // 使用手机 + 密ç ï¼Œè¿›è¡Œç™»å½•ã€‚ + MemberUserDO user = login0(reqVO.getMobile(), reqVO.getPassword()); + + // 如果 socialType éžç©ºï¼Œè¯´æ˜Žéœ€è¦ç»‘定社交用户 + String openid = null; + if (reqVO.getSocialType() != null) { + openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), + reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())); + } + + // 创建 Token 令牌,记录登录日志 + return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE, openid); + } + + @Override + @Transactional + public AppAuthLoginRespVO smsLogin(AppAuthSmsLoginReqVO reqVO, Integer terminal) { + // 校验验è¯ç  + String userIp = getClientIP(); + smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_LOGIN.getScene(), userIp)); + + // 获得获得注册用户 + MemberUserDO user = userService.createUserIfAbsent(reqVO.getMobile(), userIp, terminal); + Assert.notNull(user, "获å–用户失败,结果为空"); + + // 如果 socialType éžç©ºï¼Œè¯´æ˜Žéœ€è¦ç»‘定社交用户 + String openid = null; + if (reqVO.getSocialType() != null) { + openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), + reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())); + } + + // 创建 Token 令牌,记录登录日志 + return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_SMS, openid); + } + + @Override + public AppAuthLoginRespVO socialLogin(AppAuthSocialLoginReqVO reqVO) { + // 使用 code 授æƒç ï¼Œè¿›è¡Œç™»å½•ã€‚然åŽï¼ŒèŽ·å¾—åˆ°ç»‘å®šçš„ç”¨æˆ·ç¼–å· + SocialUserRespDTO socialUser = socialUserApi.getSocialUser(UserTypeEnum.MEMBER.getValue(), reqVO.getType(), + reqVO.getCode(), reqVO.getState()); + if (socialUser == null) { + throw exception(AUTH_THIRD_LOGIN_NOT_BIND); + } + + // 自动登录 + MemberUserDO user = userService.getUser(socialUser.getUserId()); + if (user == null) { + throw exception(USER_NOT_EXISTS); + } + + // 创建 Token 令牌,记录登录日志 + return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, socialUser.getOpenid()); + } + + @Override + public AppAuthLoginRespVO weixinMiniAppLogin(AppAuthWeixinMiniAppLoginReqVO reqVO) { + // 获得对应的手机å·ä¿¡æ¯ + SocialWxPhoneNumberInfoRespDTO phoneNumberInfo = socialClientApi.getWxMaPhoneNumberInfo( + UserTypeEnum.MEMBER.getValue(), reqVO.getPhoneCode()); + Assert.notNull(phoneNumberInfo, "获得手机信æ¯å¤±è´¥ï¼Œç»“果为空"); + + // 获得获得注册用户 + MemberUserDO user = userService.createUserIfAbsent(phoneNumberInfo.getPurePhoneNumber(), + getClientIP(), TerminalEnum.WECHAT_MINI_PROGRAM.getTerminal()); + Assert.notNull(user, "获å–用户失败,结果为空"); + + // 绑定社交用户 + String openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), + SocialTypeEnum.WECHAT_MINI_APP.getType(), reqVO.getLoginCode(), "")); + + // 创建 Token 令牌,记录登录日志 + return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, openid); + } + + private AppAuthLoginRespVO createTokenAfterLoginSuccess(MemberUserDO user, String mobile, + LoginLogTypeEnum logType, String openid) { + // æ’入登陆日志 + createLoginLog(user.getId(), mobile, logType, LoginResultEnum.SUCCESS); + // 创建 Token 令牌 + OAuth2AccessTokenRespDTO accessTokenRespDTO = oauth2TokenApi.createAccessToken(new OAuth2AccessTokenCreateReqDTO() + .setUserId(user.getId()).setUserType(getUserType().getValue()) + .setClientId(OAuth2ClientConstants.CLIENT_ID_DEFAULT)); + // 构建返回结果 + return AuthConvert.INSTANCE.convert(accessTokenRespDTO, openid); + } + + @Override + public String getSocialAuthorizeUrl(Integer type, String redirectUri) { + return socialClientApi.getAuthorizeUrl(type, UserTypeEnum.MEMBER.getValue(), redirectUri); + } + + private MemberUserDO login0(String mobile, String password) { + final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_MOBILE; + // 校验账å·æ˜¯å¦å­˜åœ¨ + MemberUserDO user = userService.getUserByMobile(mobile); + if (user == null) { + createLoginLog(null, mobile, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); + throw exception(AUTH_LOGIN_BAD_CREDENTIALS); + } + if (!userService.isPasswordMatch(password, user.getPassword())) { + createLoginLog(user.getId(), mobile, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); + throw exception(AUTH_LOGIN_BAD_CREDENTIALS); + } + // 校验是å¦ç¦ç”¨ + if (ObjectUtil.notEqual(user.getStatus(), CommonStatusEnum.ENABLE.getStatus())) { + createLoginLog(user.getId(), mobile, logTypeEnum, LoginResultEnum.USER_DISABLED); + throw exception(AUTH_LOGIN_USER_DISABLED); + } + return user; + } + + private void createLoginLog(Long userId, String mobile, LoginLogTypeEnum logType, LoginResultEnum loginResult) { + // æ’入登录日志 + LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO(); + reqDTO.setLogType(logType.getType()); + reqDTO.setTraceId(TracerUtils.getTraceId()); + reqDTO.setUserId(userId); + reqDTO.setUserType(getUserType().getValue()); + reqDTO.setUsername(mobile); + reqDTO.setUserAgent(ServletUtils.getUserAgent()); + reqDTO.setUserIp(getClientIP()); + reqDTO.setResult(loginResult.getResult()); + loginLogApi.createLoginLog(reqDTO); + // 更新最åŽç™»å½•æ—¶é—´ + if (userId != null && Objects.equals(LoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) { + userService.updateUserLogin(userId, getClientIP()); + } + } + + @Override + public void logout(String token) { + // 删除访问令牌 + OAuth2AccessTokenRespDTO accessTokenRespDTO = oauth2TokenApi.removeAccessToken(token); + if (accessTokenRespDTO == null) { + return; + } + // 删除æˆåŠŸï¼Œåˆ™è®°å½•ç™»å‡ºæ—¥å¿— + createLogoutLog(accessTokenRespDTO.getUserId()); + } + + @Override + public void sendSmsCode(Long userId, AppAuthSmsSendReqVO reqVO) { + // 情况 1:如果是修改手机场景,需è¦æ ¡éªŒæ–°æ‰‹æœºå·æ˜¯å¦å·²ç»æ³¨å†Œï¼Œè¯´æ˜Žä¸èƒ½ä½¿ç”¨è¯¥æ‰‹æœºäº† + if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene())) { + MemberUserDO user = userService.getUserByMobile(reqVO.getMobile()); + if (user != null && !Objects.equals(user.getId(), userId)) { + throw exception(AUTH_MOBILE_USED); + } + } + // 情况 2:如果是é‡ç½®å¯†ç åœºæ™¯ï¼Œéœ€è¦æ ¡éªŒæ‰‹æœºå·æ˜¯å­˜åœ¨çš„ + if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_RESET_PASSWORD.getScene())) { + MemberUserDO user= userService.getUserByMobile(reqVO.getMobile()); + if (user == null) { + throw exception(USER_MOBILE_NOT_EXISTS); + } + } + + // 执行å‘é€ + smsCodeApi.sendSmsCode(AuthConvert.INSTANCE.convert(reqVO).setCreateIp(getClientIP())); + } + + @Override + public void validateSmsCode(Long userId, AppAuthSmsValidateReqVO reqVO) { + smsCodeApi.validateSmsCode(AuthConvert.INSTANCE.convert(reqVO)); + } + + @Override + public AppAuthLoginRespVO refreshToken(String refreshToken) { + OAuth2AccessTokenRespDTO accessTokenDO = oauth2TokenApi.refreshAccessToken(refreshToken, + OAuth2ClientConstants.CLIENT_ID_DEFAULT); + return AuthConvert.INSTANCE.convert(accessTokenDO, null); + } + + private void createLogoutLog(Long userId) { + LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO(); + reqDTO.setLogType(LoginLogTypeEnum.LOGOUT_SELF.getType()); + reqDTO.setTraceId(TracerUtils.getTraceId()); + reqDTO.setUserId(userId); + reqDTO.setUserType(getUserType().getValue()); + reqDTO.setUsername(getMobile(userId)); + reqDTO.setUserAgent(ServletUtils.getUserAgent()); + reqDTO.setUserIp(getClientIP()); + reqDTO.setResult(LoginResultEnum.SUCCESS.getResult()); + loginLogApi.createLoginLog(reqDTO); + } + + private String getMobile(Long userId) { + if (userId == null) { + return null; + } + MemberUserDO user = userService.getUser(userId); + return user != null ? user.getMobile() : null; + } + + private UserTypeEnum getUserType() { + return UserTypeEnum.MEMBER; + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/config/MemberConfigService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/config/MemberConfigService.java new file mode 100644 index 000000000..fc4545425 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/config/MemberConfigService.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.member.service.config; + +import cn.iocoder.yudao.module.member.controller.admin.config.vo.MemberConfigSaveReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.config.MemberConfigDO; + +import javax.validation.Valid; + +/** + * 会员é…ç½® Service æŽ¥å£ + * + * @author QingX + */ +public interface MemberConfigService { + + /** + * ä¿å­˜ä¼šå‘˜é…ç½® + * + * @param saveReqVO æ›´æ–°ä¿¡æ¯ + */ + void saveConfig(@Valid MemberConfigSaveReqVO saveReqVO); + + /** + * 获得会员é…ç½® + * + * @return 积分é…ç½® + */ + MemberConfigDO getConfig(); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/config/MemberConfigServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/config/MemberConfigServiceImpl.java new file mode 100644 index 000000000..be56f8a8a --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/config/MemberConfigServiceImpl.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.member.service.config; + +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.member.controller.admin.config.vo.MemberConfigSaveReqVO; +import cn.iocoder.yudao.module.member.convert.config.MemberConfigConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.config.MemberConfigDO; +import cn.iocoder.yudao.module.member.dal.mysql.config.MemberConfigMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 会员é…ç½® Service 实现类 + * + * @author QingX + */ +@Service +@Validated +public class MemberConfigServiceImpl implements MemberConfigService { + + @Resource + private MemberConfigMapper memberConfigMapper; + + @Override + public void saveConfig(MemberConfigSaveReqVO saveReqVO) { + // 存在,则进行更新 + MemberConfigDO dbConfig = getConfig(); + if (dbConfig != null) { + memberConfigMapper.updateById(MemberConfigConvert.INSTANCE.convert(saveReqVO).setId(dbConfig.getId())); + return; + } + // ä¸å­˜åœ¨ï¼Œåˆ™è¿›è¡Œæ’å…¥ + memberConfigMapper.insert(MemberConfigConvert.INSTANCE.convert(saveReqVO)); + } + + @Override + public MemberConfigDO getConfig() { + List list = memberConfigMapper.selectList(); + return CollectionUtils.getFirst(list); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/group/MemberGroupService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/group/MemberGroupService.java new file mode 100644 index 000000000..54c7882e0 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/group/MemberGroupService.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.member.service.group; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupUpdateReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.group.MemberGroupDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * 用户分组 Service æŽ¥å£ + * + * @author owen + */ +public interface MemberGroupService { + + /** + * 创建用户分组 + * + * @param createReqVO åˆ›å»ºä¿¡æ¯ + * @return ç¼–å· + */ + Long createGroup(@Valid MemberGroupCreateReqVO createReqVO); + + /** + * 更新用户分组 + * + * @param updateReqVO æ›´æ–°ä¿¡æ¯ + */ + void updateGroup(@Valid MemberGroupUpdateReqVO updateReqVO); + + /** + * 删除用户分组 + * + * @param id ç¼–å· + */ + void deleteGroup(Long id); + + /** + * 获得用户分组 + * + * @param id ç¼–å· + * @return 用户分组 + */ + MemberGroupDO getGroup(Long id); + + /** + * 获得用户分组列表 + * + * @param ids ç¼–å· + * @return 用户分组列表 + */ + List getGroupList(Collection ids); + + /** + * 获得用户分组分页 + * + * @param pageReqVO 分页查询 + * @return 用户分组分页 + */ + PageResult getGroupPage(MemberGroupPageReqVO pageReqVO); + + + /** + * 获得指定状æ€çš„用户分组列表 + * + * @param status çŠ¶æ€ + * @return 用户分组列表 + */ + List getGroupListByStatus(Integer status); + + + /** + * 获得开å¯çŠ¶æ€çš„用户分组列表 + * + * @return 用户分组列表 + */ + default List getEnableGroupList() { + return getGroupListByStatus(CommonStatusEnum.ENABLE.getStatus()); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/group/MemberGroupServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/group/MemberGroupServiceImpl.java new file mode 100644 index 000000000..cdf1e4fee --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/group/MemberGroupServiceImpl.java @@ -0,0 +1,103 @@ +package cn.iocoder.yudao.module.member.service.group; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupUpdateReqVO; +import cn.iocoder.yudao.module.member.convert.group.MemberGroupConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.group.MemberGroupDO; +import cn.iocoder.yudao.module.member.dal.mysql.group.MemberGroupMapper; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.GROUP_HAS_USER; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.GROUP_NOT_EXISTS; + +/** + * 用户分组 Service 实现类 + * + * @author owen + */ +@Service +@Validated +public class MemberGroupServiceImpl implements MemberGroupService { + + @Resource + private MemberGroupMapper memberGroupMapper; + + @Resource + private MemberUserService memberUserService; + + @Override + public Long createGroup(MemberGroupCreateReqVO createReqVO) { + // æ’å…¥ + MemberGroupDO group = MemberGroupConvert.INSTANCE.convert(createReqVO); + memberGroupMapper.insert(group); + // 返回 + return group.getId(); + } + + @Override + public void updateGroup(MemberGroupUpdateReqVO updateReqVO) { + // 校验存在 + validateGroupExists(updateReqVO.getId()); + // æ›´æ–° + MemberGroupDO updateObj = MemberGroupConvert.INSTANCE.convert(updateReqVO); + memberGroupMapper.updateById(updateObj); + } + + @Override + public void deleteGroup(Long id) { + // 校验存在 + validateGroupExists(id); + // 校验分组下是å¦æœ‰ç”¨æˆ· + validateGroupHasUser(id); + // 删除 + memberGroupMapper.deleteById(id); + } + + void validateGroupExists(Long id) { + if (memberGroupMapper.selectById(id) == null) { + throw exception(GROUP_NOT_EXISTS); + } + } + + void validateGroupHasUser(Long id) { + Long count = memberUserService.getUserCountByGroupId(id); + if (count > 0) { + throw exception(GROUP_HAS_USER); + } + } + + @Override + public MemberGroupDO getGroup(Long id) { + return memberGroupMapper.selectById(id); + } + + @Override + public List getGroupList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return memberGroupMapper.selectBatchIds(ids); + } + + @Override + public PageResult getGroupPage(MemberGroupPageReqVO pageReqVO) { + return memberGroupMapper.selectPage(pageReqVO); + } + + @Override + public List getGroupListByStatus(Integer status) { + return memberGroupMapper.selectListByStatus(status); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordService.java new file mode 100644 index 000000000..76470f72a --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordService.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.member.service.level; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordPageReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO; +import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; + +/** + * 会员ç»éªŒè®°å½• Service æŽ¥å£ + * + * @author owen + */ +public interface MemberExperienceRecordService { + + /** + * 获得会员ç»éªŒè®°å½• + * + * @param id ç¼–å· + * @return 会员ç»éªŒè®°å½• + */ + MemberExperienceRecordDO getExperienceRecord(Long id); + + /** + * ã€ç®¡ç†å‘˜ã€‘获得会员ç»éªŒè®°å½•åˆ†é¡µ + * + * @param pageReqVO 分页查询 + * @return 会员ç»éªŒè®°å½•åˆ†é¡µ + */ + PageResult getExperienceRecordPage(MemberExperienceRecordPageReqVO pageReqVO); + + /** + * ã€ä¼šå‘˜ã€‘获得会员ç»éªŒè®°å½•åˆ†é¡µ + * + * @param userId ç”¨æˆ·ç¼–å· + * @param pageParam 分页查询 + * @return 会员ç»éªŒè®°å½•åˆ†é¡µ + */ + PageResult getExperienceRecordPage(Long userId, PageParam pageParam); + + /** + * æ ¹æ®ä¸šåŠ¡ç±»åž‹, 创建 ç»éªŒå˜åŠ¨è®°å½• + * + * @param userId ä¼šå‘˜ç¼–å· + * @param experience å˜åŠ¨ç»éªŒå€¼ + * @param totalExperience 会员当å‰çš„ç»éªŒ + * @param bizType 业务类型 + * @param bizId 业务ID + */ + void createExperienceRecord(Long userId, Integer experience, Integer totalExperience, + MemberExperienceBizTypeEnum bizType, String bizId); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java new file mode 100644 index 000000000..80ecc84d6 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.member.service.level; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordPageReqVO; +import cn.iocoder.yudao.module.member.convert.level.MemberExperienceRecordConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO; +import cn.iocoder.yudao.module.member.dal.mysql.level.MemberExperienceRecordMapper; +import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; + +/** + * 会员ç»éªŒè®°å½• Service 实现类 + * + * @author owen + */ +@Service +@Validated +public class MemberExperienceRecordServiceImpl implements MemberExperienceRecordService { + + @Resource + private MemberExperienceRecordMapper experienceLogMapper; + + @Override + public MemberExperienceRecordDO getExperienceRecord(Long id) { + return experienceLogMapper.selectById(id); + } + + @Override + public PageResult getExperienceRecordPage(MemberExperienceRecordPageReqVO pageReqVO) { + return experienceLogMapper.selectPage(pageReqVO); + } + + @Override + public PageResult getExperienceRecordPage(Long userId, PageParam pageParam) { + return experienceLogMapper.selectPage(userId, pageParam); + } + + @Override + public void createExperienceRecord(Long userId, Integer experience, Integer totalExperience, + MemberExperienceBizTypeEnum bizType, String bizId) { + String description = StrUtil.format(bizType.getDescription(), experience); + MemberExperienceRecordDO record = MemberExperienceRecordConvert.INSTANCE.convert( + userId, experience, totalExperience, + bizId, bizType.getType(), bizType.getTitle(), description); + experienceLogMapper.insert(record); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java new file mode 100644 index 000000000..b5e4f669e --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.member.service.level; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordPageReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO; + +/** + * 会员等级记录 Service æŽ¥å£ + * + * @author owen + */ +public interface MemberLevelRecordService { + + /** + * 获得会员等级记录 + * + * @param id ç¼–å· + * @return 会员等级记录 + */ + MemberLevelRecordDO getLevelRecord(Long id); + + /** + * 获得会员等级记录分页 + * + * @param pageReqVO 分页查询 + * @return 会员等级记录分页 + */ + PageResult getLevelRecordPage(MemberLevelRecordPageReqVO pageReqVO); + + /** + * 创建会员等级记录 + * + * @param levelRecord 会员等级记录 + */ + void createLevelRecord(MemberLevelRecordDO levelRecord); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java new file mode 100644 index 000000000..810961241 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.member.service.level; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordPageReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO; +import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelRecordMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +/** + * 会员等级记录 Service 实现类 + * + * @author owen + */ +@Service +@Validated +public class MemberLevelRecordServiceImpl implements MemberLevelRecordService { + + @Resource + private MemberLevelRecordMapper levelLogMapper; + + @Override + public MemberLevelRecordDO getLevelRecord(Long id) { + return levelLogMapper.selectById(id); + } + + @Override + public PageResult getLevelRecordPage(MemberLevelRecordPageReqVO pageReqVO) { + return levelLogMapper.selectPage(pageReqVO); + } + + @Override + public void createLevelRecord(MemberLevelRecordDO levelRecord) { + levelLogMapper.insert(levelRecord); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelService.java new file mode 100644 index 000000000..76d46e5c3 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelService.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.member.service.level; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelListReqVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelUpdateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateLevelReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; +import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * 会员等级 Service æŽ¥å£ + * + * @author owen + */ +public interface MemberLevelService { + + /** + * 创建会员等级 + * + * @param createReqVO åˆ›å»ºä¿¡æ¯ + * @return ç¼–å· + */ + Long createLevel(@Valid MemberLevelCreateReqVO createReqVO); + + /** + * 更新会员等级 + * + * @param updateReqVO æ›´æ–°ä¿¡æ¯ + */ + void updateLevel(@Valid MemberLevelUpdateReqVO updateReqVO); + + /** + * 删除会员等级 + * + * @param id ç¼–å· + */ + void deleteLevel(Long id); + + /** + * 获得会员等级 + * + * @param id ç¼–å· + * @return 会员等级 + */ + MemberLevelDO getLevel(Long id); + + /** + * 获得会员等级列表 + * + * @param ids ç¼–å· + * @return 会员等级列表 + */ + List getLevelList(Collection ids); + + /** + * 获得会员等级列表 + * + * @param listReqVO 查询å‚æ•° + * @return 会员等级列表 + */ + List getLevelList(MemberLevelListReqVO listReqVO); + + /** + * 获得指定状æ€çš„会员等级列表 + * + * @param status çŠ¶æ€ + * @return 会员等级列表 + */ + List getLevelListByStatus(Integer status); + + /** + * 获得开å¯çŠ¶æ€çš„会员等级列表 + * + * @return 会员等级列表 + */ + default List getEnableLevelList() { + return getLevelListByStatus(CommonStatusEnum.ENABLE.getStatus()); + } + + /** + * 修改会员的等级 + * + * @param updateReqVO 修改å‚æ•° + */ + void updateUserLevel(MemberUserUpdateLevelReqVO updateReqVO); + + /** + * 增加会员ç»éªŒ + * + * @param userId 会员ID + * @param experience ç»éªŒ + * @param bizType 业务类型 + * @param bizId ä¸šåŠ¡ç¼–å· + */ + void addExperience(Long userId, Integer experience, MemberExperienceBizTypeEnum bizType, String bizId); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java new file mode 100644 index 000000000..c98dd4b97 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java @@ -0,0 +1,300 @@ +package cn.iocoder.yudao.module.member.service.level; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelListReqVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelUpdateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateLevelReqVO; +import cn.iocoder.yudao.module.member.convert.level.MemberLevelConvert; +import cn.iocoder.yudao.module.member.convert.level.MemberLevelRecordConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelMapper; +import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import com.google.common.annotations.VisibleForTesting; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*; + +/** + * 会员等级 Service 实现类 + * + * @author owen + */ +@Slf4j +@Service +@Validated +public class MemberLevelServiceImpl implements MemberLevelService { + + @Resource + private MemberLevelMapper memberLevelMapper; + + @Resource + private MemberLevelRecordService memberLevelRecordService; + @Resource + private MemberExperienceRecordService memberExperienceRecordService; + @Resource + private MemberUserService memberUserService; + + @Override + public Long createLevel(MemberLevelCreateReqVO createReqVO) { + // 校验é…置是å¦æœ‰æ•ˆ + validateConfigValid(null, createReqVO.getName(), createReqVO.getLevel(), createReqVO.getExperience()); + + // æ’å…¥ + MemberLevelDO level = MemberLevelConvert.INSTANCE.convert(createReqVO); + memberLevelMapper.insert(level); + // 返回 + return level.getId(); + } + + @Override + public void updateLevel(MemberLevelUpdateReqVO updateReqVO) { + // 校验存在 + validateLevelExists(updateReqVO.getId()); + // 校验é…置是å¦æœ‰æ•ˆ + validateConfigValid(updateReqVO.getId(), updateReqVO.getName(), updateReqVO.getLevel(), updateReqVO.getExperience()); + + // æ›´æ–° + MemberLevelDO updateObj = MemberLevelConvert.INSTANCE.convert(updateReqVO); + memberLevelMapper.updateById(updateObj); + } + + @Override + public void deleteLevel(Long id) { + // 校验存在 + validateLevelExists(id); + // 校验分组下是å¦æœ‰ç”¨æˆ· + validateLevelHasUser(id); + // 删除 + memberLevelMapper.deleteById(id); + } + + @VisibleForTesting + MemberLevelDO validateLevelExists(Long id) { + MemberLevelDO levelDO = memberLevelMapper.selectById(id); + if (levelDO == null) { + throw exception(LEVEL_NOT_EXISTS); + } + return levelDO; + } + + @VisibleForTesting + void validateNameUnique(List list, Long id, String name) { + for (MemberLevelDO levelDO : list) { + if (ObjUtil.notEqual(levelDO.getName(), name)) { + continue; + } + if (id == null || !id.equals(levelDO.getId())) { + throw exception(LEVEL_NAME_EXISTS, levelDO.getName()); + } + } + } + + @VisibleForTesting + void validateLevelUnique(List list, Long id, Integer level) { + for (MemberLevelDO levelDO : list) { + if (ObjUtil.notEqual(levelDO.getLevel(), level)) { + continue; + } + + if (id == null || !id.equals(levelDO.getId())) { + throw exception(LEVEL_VALUE_EXISTS, levelDO.getLevel(), levelDO.getName()); + } + } + } + + @VisibleForTesting + void validateExperienceOutRange(List list, Long id, Integer level, Integer experience) { + for (MemberLevelDO levelDO : list) { + if (levelDO.getId().equals(id)) { + continue; + } + + if (levelDO.getLevel() < level) { + // ç»éªŒå¤§äºŽå‰ä¸€ä¸ªç­‰çº§ + if (experience <= levelDO.getExperience()) { + throw exception(LEVEL_EXPERIENCE_MIN, levelDO.getName(), levelDO.getExperience()); + } + } else if (levelDO.getLevel() > level) { + //å°äºŽä¸‹ä¸€ä¸ªçº§åˆ« + if (experience >= levelDO.getExperience()) { + throw exception(LEVEL_EXPERIENCE_MAX, levelDO.getName(), levelDO.getExperience()); + } + } + } + } + + @VisibleForTesting + void validateConfigValid(Long id, String name, Integer level, Integer experience) { + List list = memberLevelMapper.selectList(); + // 校验å称唯一 + validateNameUnique(list, id, name); + // 校验等级唯一 + validateLevelUnique(list, id, level); + // 校验å‡çº§æ‰€éœ€ç»éªŒæ˜¯å¦æœ‰æ•ˆ: 大于å‰ä¸€ä¸ªç­‰çº§ï¼Œå°äºŽä¸‹ä¸€ä¸ªçº§åˆ« + validateExperienceOutRange(list, id, level, experience); + } + + @VisibleForTesting + void validateLevelHasUser(Long id) { + Long count = memberUserService.getUserCountByLevelId(id); + if (count > 0) { + throw exception(LEVEL_HAS_USER); + } + } + + @Override + public MemberLevelDO getLevel(Long id) { + return id != null && id > 0 ? memberLevelMapper.selectById(id) : null; + } + + @Override + public List getLevelList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return memberLevelMapper.selectBatchIds(ids); + } + + @Override + public List getLevelList(MemberLevelListReqVO listReqVO) { + return memberLevelMapper.selectList(listReqVO); + } + + @Override + public List getLevelListByStatus(Integer status) { + return memberLevelMapper.selectListByStatus(status); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateUserLevel(MemberUserUpdateLevelReqVO updateReqVO) { + MemberUserDO user = memberUserService.getUser(updateReqVO.getId()); + if (user == null) { + throw exception(USER_NOT_EXISTS); + } + // 等级未å‘生å˜åŒ– + if (ObjUtil.equal(user.getLevelId(), updateReqVO.getLevelId())) { + return; + } + + // 1. 记录等级å˜åŠ¨ + MemberLevelRecordDO levelRecord = new MemberLevelRecordDO() + .setUserId(user.getId()).setRemark(updateReqVO.getReason()); + MemberLevelDO memberLevel = null; + if (updateReqVO.getLevelId() == null) { + // å–消用户等级时,需è¦æ‰£å‡ç»éªŒ + levelRecord.setExperience(-user.getExperience()); + levelRecord.setUserExperience(0); + levelRecord.setDescription("管ç†å‘˜å–消了等级"); + } else { + // å¤åˆ¶ç­‰çº§é…ç½® + memberLevel = validateLevelExists(updateReqVO.getLevelId()); + MemberLevelRecordConvert.INSTANCE.copyTo(memberLevel, levelRecord); + // å˜åŠ¨ç»éªŒå€¼ = 等级的å‡çº§ç»éªŒ - 会员当å‰çš„ç»éªŒï¼›æ­£æ•°ä¸ºå¢žåŠ ç»éªŒï¼Œè´Ÿæ•°ä¸ºæ‰£å‡ç»éªŒ + levelRecord.setExperience(memberLevel.getExperience() - user.getExperience()); + levelRecord.setUserExperience(memberLevel.getExperience()); // 会员当å‰çš„ç»éªŒ = 等级的å‡çº§ç»éªŒ + levelRecord.setDescription("管ç†å‘˜è°ƒæ•´ä¸ºï¼š" + memberLevel.getName()); + } + memberLevelRecordService.createLevelRecord(levelRecord); + + // 2. 记录会员ç»éªŒå˜åŠ¨ + memberExperienceRecordService.createExperienceRecord(user.getId(), + levelRecord.getExperience(), levelRecord.getUserExperience(), + MemberExperienceBizTypeEnum.ADMIN, String.valueOf(MemberExperienceBizTypeEnum.ADMIN.getType())); + + // 3. 更新会员表上的等级编å·ã€ç»éªŒå€¼ + memberUserService.updateUserLevel(user.getId(), updateReqVO.getLevelId(), + levelRecord.getUserExperience()); + + // 4. 给会员å‘é€ç­‰çº§å˜åŠ¨æ¶ˆæ¯ + notifyMemberLevelChange(user.getId(), memberLevel); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void addExperience(Long userId, Integer experience, MemberExperienceBizTypeEnum bizType, String bizId) { + if (experience == 0) { + return; + } + if (!bizType.isAdd() && experience > 0) { + experience = -experience; + } + + // 1. 创建ç»éªŒè®°å½• + MemberUserDO user = memberUserService.getUser(userId); + Integer userExperience = ObjUtil.defaultIfNull(user.getExperience(), 0); + userExperience = NumberUtil.max(userExperience + experience, 0); // 防止扣出负数 + MemberLevelRecordDO levelRecord = new MemberLevelRecordDO() + .setUserId(user.getId()) + .setExperience(experience) + .setUserExperience(userExperience); + memberExperienceRecordService.createExperienceRecord(userId, experience, userExperience, + bizType, bizId); + + // 2.1 ä¿å­˜ç­‰çº§å˜æ›´è®°å½• + MemberLevelDO newLevel = calculateNewLevel(user, userExperience); + if (newLevel != null) { + MemberLevelRecordConvert.INSTANCE.copyTo(newLevel, levelRecord); + memberLevelRecordService.createLevelRecord(levelRecord); + + // 2.2 给会员å‘é€ç­‰çº§å˜åŠ¨æ¶ˆæ¯ + notifyMemberLevelChange(userId, newLevel); + } + + // 3. 更新会员表上的等级编å·ã€ç»éªŒå€¼ + memberUserService.updateUserLevel(user.getId(), levelRecord.getLevelId(), userExperience); + } + + /** + * 计算会员等级 + * + * @param user 会员 + * @param userExperience 会员当å‰çš„ç»éªŒå€¼ + * @return 会员新的等级,null表示无å˜åŒ– + */ + private MemberLevelDO calculateNewLevel(MemberUserDO user, int userExperience) { + List list = getEnableLevelList(); + if (CollUtil.isEmpty(list)) { + log.warn("计算会员等级失败:会员等级é…ç½®ä¸å­˜åœ¨"); + return null; + } + + MemberLevelDO matchLevel = list.stream() + .filter(level -> userExperience >= level.getExperience()) + .max(Comparator.nullsFirst(Comparator.comparing(MemberLevelDO::getLevel))) + .orElse(null); + if (matchLevel == null) { + log.warn("计算会员等级失败:未找到会员{}ç»éªŒ{}对应的等级é…ç½®", user.getId(), userExperience); + return null; + } + + // 等级没有å˜åŒ– + if (ObjectUtil.equal(matchLevel.getId(), user.getLevelId())) { + return null; + } + + return matchLevel; + } + + private void notifyMemberLevelChange(Long userId, MemberLevelDO level) { + //todo: 给会员å‘æ¶ˆæ¯ + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordService.java new file mode 100644 index 000000000..74e91880f --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordService.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.member.service.point; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordPageReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO; +import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; + +/** + * 用户积分记录 Service æŽ¥å£ + * + * @author QingX + */ +public interface MemberPointRecordService { + + /** + * ã€ç®¡ç†å‘˜ã€‘获得积分记录分页 + * + * @param pageReqVO 分页查询 + * @return 签到记录分页 + */ + PageResult getPointRecordPage(MemberPointRecordPageReqVO pageReqVO); + + /** + * ã€ä¼šå‘˜ã€‘获得积分记录分页 + * + * @param userId ç”¨æˆ·ç¼–å· + * @param pageVO 分页查询 + * @return 签到记录分页 + */ + PageResult getPointRecordPage(Long userId, PageParam pageVO); + + /** + * 创建用户积分记录 + * + * @param userId 用户ID + * @param point å˜åŠ¨ç§¯åˆ† + * @param bizType 业务类型 + * @param bizId ä¸šåŠ¡ç¼–å· + */ + void createPointRecord(Long userId, Integer point, MemberPointBizTypeEnum bizType, String bizId); +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordServiceImpl.java new file mode 100644 index 000000000..e665bdf13 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordServiceImpl.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.member.service.point; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordPageReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.dal.mysql.point.MemberPointRecordMapper; +import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.USER_POINT_NOT_ENOUGH; + + +/** + * 积分记录 Service 实现类 + * + * @author QingX + */ +@Slf4j +@Service +@Validated +public class MemberPointRecordServiceImpl implements MemberPointRecordService { + + @Resource + private MemberPointRecordMapper memberPointRecordMapper; + + @Resource + private MemberUserService memberUserService; + + @Override + public PageResult getPointRecordPage(MemberPointRecordPageReqVO pageReqVO) { + // æ ¹æ®ç”¨æˆ·æ˜µç§°æŸ¥è¯¢å‡ºç”¨æˆ· ids + Set userIds = null; + if (StringUtils.isNotBlank(pageReqVO.getNickname())) { + List users = memberUserService.getUserListByNickname(pageReqVO.getNickname()); + // 如果查询用户结果为空直接返回无需继续查询 + if (CollectionUtils.isEmpty(users)) { + return PageResult.empty(); + } + userIds = convertSet(users, MemberUserDO::getId); + } + // 执行查询 + return memberPointRecordMapper.selectPage(pageReqVO, userIds); + } + + @Override + public PageResult getPointRecordPage(Long userId, PageParam pageVO) { + return memberPointRecordMapper.selectPage(userId, pageVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void createPointRecord(Long userId, Integer point, MemberPointBizTypeEnum bizType, String bizId) { + if (point == 0) { + return; + } + // 1. æ ¡éªŒç”¨æˆ·ç§¯åˆ†ä½™é¢ + MemberUserDO user = memberUserService.getUser(userId); + Integer userPoint = ObjectUtil.defaultIfNull(user.getPoint(), 0); + int totalPoint = userPoint + point; // 用户å˜åŠ¨åŽçš„积分 + if (totalPoint < 0) { + throw exception(USER_POINT_NOT_ENOUGH); + } + + // 2. 更新用户积分 + boolean success = memberUserService.updateUserPoint(userId, point); + if (!success) { + throw exception(USER_POINT_NOT_ENOUGH); + } + + // 3. 增加积分记录 + MemberPointRecordDO record = new MemberPointRecordDO() + .setUserId(userId).setBizId(bizId).setBizType(bizType.getType()) + .setTitle(bizType.getName()).setDescription(StrUtil.format(bizType.getDescription(), point)) + .setPoint(point).setTotalPoint(totalPoint); + memberPointRecordMapper.insert(record); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInConfigService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInConfigService.java new file mode 100644 index 000000000..b4a9c041c --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInConfigService.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.member.service.signin; + +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.config.MemberSignInConfigCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.config.MemberSignInConfigUpdateReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO; + +import javax.validation.Valid; +import java.util.List; + +/** + * 签到规则 Service æŽ¥å£ + * + * @author QingX + */ +public interface MemberSignInConfigService { + + /** + * 创建签到规则 + * + * @param createReqVO åˆ›å»ºä¿¡æ¯ + * @return ç¼–å· + */ + Long createSignInConfig(@Valid MemberSignInConfigCreateReqVO createReqVO); + + /** + * 更新签到规则 + * + * @param updateReqVO æ›´æ–°ä¿¡æ¯ + */ + void updateSignInConfig(@Valid MemberSignInConfigUpdateReqVO updateReqVO); + + /** + * 删除签到规则 + * + * @param id ç¼–å· + */ + void deleteSignInConfig(Long id); + + /** + * 获得签到规则 + * + * @param id ç¼–å· + * @return 签到规则 + */ + MemberSignInConfigDO getSignInConfig(Long id); + + /** + * 获得签到规则列表 + * + * @return 签到规则分页 + */ + List getSignInConfigList(); + + /** + * 获得签到规则列表 + * + * @param status çŠ¶æ€ + * @return 签到规则分页 + */ + List getSignInConfigList(Integer status); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInConfigServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInConfigServiceImpl.java new file mode 100644 index 000000000..4e2b04c63 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInConfigServiceImpl.java @@ -0,0 +1,106 @@ +package cn.iocoder.yudao.module.member.service.signin; + +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.config.MemberSignInConfigCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.config.MemberSignInConfigUpdateReqVO; +import cn.iocoder.yudao.module.member.convert.signin.MemberSignInConfigConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO; +import cn.iocoder.yudao.module.member.dal.mysql.signin.MemberSignInConfigMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Comparator; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.SIGN_IN_CONFIG_EXISTS; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.SIGN_IN_CONFIG_NOT_EXISTS; + +/** + * 签到规则 Service 实现类 + * + * @author QingX + */ +@Service +@Validated +public class MemberSignInConfigServiceImpl implements MemberSignInConfigService { + + @Resource + private MemberSignInConfigMapper memberSignInConfigMapper; + + @Override + public Long createSignInConfig(MemberSignInConfigCreateReqVO createReqVO) { + // 判断是å¦é‡å¤æ’入签到天数 + validateSignInConfigDayDuplicate(createReqVO.getDay(), null); + + // æ’å…¥ + MemberSignInConfigDO signInConfig = MemberSignInConfigConvert.INSTANCE.convert(createReqVO); + memberSignInConfigMapper.insert(signInConfig); + // 返回 + return signInConfig.getId(); + } + + @Override + public void updateSignInConfig(MemberSignInConfigUpdateReqVO updateReqVO) { + // 校验存在 + validateSignInConfigExists(updateReqVO.getId()); + // 判断是å¦é‡å¤æ’入签到天数 + validateSignInConfigDayDuplicate(updateReqVO.getDay(), updateReqVO.getId()); + + // 判断更新 + MemberSignInConfigDO updateObj = MemberSignInConfigConvert.INSTANCE.convert(updateReqVO); + memberSignInConfigMapper.updateById(updateObj); + } + + @Override + public void deleteSignInConfig(Long id) { + // 校验存在 + validateSignInConfigExists(id); + // 删除 + memberSignInConfigMapper.deleteById(id); + } + + private void validateSignInConfigExists(Long id) { + if (memberSignInConfigMapper.selectById(id) == null) { + throw exception(SIGN_IN_CONFIG_NOT_EXISTS); + } + } + + /** + * 校验 day 是å¦é‡å¤ + * + * @param day 天 + * @param id ç¼–å·ï¼Œåªæœ‰æ›´æ–°çš„时候会传递 + */ + private void validateSignInConfigDayDuplicate(Integer day, Long id) { + MemberSignInConfigDO config = memberSignInConfigMapper.selectByDay(day); + // 1. 新增时,config éžç©ºï¼Œåˆ™è¯´æ˜Žé‡å¤ + if (id == null && config != null) { + throw exception(SIGN_IN_CONFIG_EXISTS); + } + // 2. 更新时,如果 config éžç©ºï¼Œä¸” id ä¸ç›¸ç­‰ï¼Œåˆ™è¯´æ˜Žé‡å¤ + if (id != null && config != null && !config.getId().equals(id)) { + throw exception(SIGN_IN_CONFIG_EXISTS); + } + } + + @Override + public MemberSignInConfigDO getSignInConfig(Long id) { + return memberSignInConfigMapper.selectById(id); + } + + @Override + public List getSignInConfigList() { + List list = memberSignInConfigMapper.selectList(); + list.sort(Comparator.comparing(MemberSignInConfigDO::getDay)); + return list; + } + + @Override + public List getSignInConfigList(Integer status) { + List list = memberSignInConfigMapper.selectListByStatus(status); + list.sort(Comparator.comparing(MemberSignInConfigDO::getDay)); + return list; + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordService.java new file mode 100644 index 000000000..b22ceed1a --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordService.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.member.service.signin; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordPageReqVO; +import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordSummaryRespVO; +import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO; + +/** + * 签到记录 Service æŽ¥å£ + * + * @author 芋é“æºç  + */ +public interface MemberSignInRecordService { + + /** + * ã€ç®¡ç†å‘˜ã€‘获得签到记录分页 + * + * @param pageReqVO 分页查询 + * @return 签到记录分页 + */ + PageResult getSignInRecordPage(MemberSignInRecordPageReqVO pageReqVO); + + /** + * ã€ä¼šå‘˜ã€‘获得签到记录分页 + * + * @param userId ç”¨æˆ·ç¼–å· + * @param pageParam 分页查询 + * @return 签到记录分页 + */ + PageResult getSignRecordPage(Long userId, PageParam pageParam); + + /** + * 创建签到记录 + * + * @param userId ç”¨æˆ·ç¼–å· + * @return 签到记录 + */ + MemberSignInRecordDO createSignRecord(Long userId); + + /** + * æ ¹æ®ç”¨æˆ·ç¼–å·ï¼ŒèŽ·å¾—ä¸ªäººç­¾åˆ°ç»Ÿè®¡ä¿¡æ¯ + * + * @param userId ç”¨æˆ·ç¼–å· + * @return ä¸ªäººç­¾åˆ°ç»Ÿè®¡ä¿¡æ¯ + */ + AppMemberSignInRecordSummaryRespVO getSignInRecordSummary(Long userId); + + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordServiceImpl.java new file mode 100644 index 000000000..be9b420e9 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordServiceImpl.java @@ -0,0 +1,182 @@ +package cn.iocoder.yudao.module.member.service.signin; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordPageReqVO; +import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordSummaryRespVO; +import cn.iocoder.yudao.module.member.convert.signin.MemberSignInRecordConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO; +import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO; +import cn.iocoder.yudao.module.member.dal.mysql.signin.MemberSignInRecordMapper; +import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; +import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; +import cn.iocoder.yudao.module.member.service.level.MemberLevelService; +import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.time.LocalDate; +import java.util.Comparator; +import java.util.List; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.SIGN_IN_RECORD_TODAY_EXISTS; + +/** + * 签到记录 Service 实现类 + * + * @author 芋é“æºç  + */ +@Service +@Validated +public class MemberSignInRecordServiceImpl implements MemberSignInRecordService { + + @Resource + private MemberSignInRecordMapper signInRecordMapper; + @Resource + private MemberSignInConfigService signInConfigService; + @Resource + private MemberPointRecordService pointRecordService; + @Resource + private MemberLevelService memberLevelService; + + @Resource + private MemberUserApi memberUserApi; + + @Override + public AppMemberSignInRecordSummaryRespVO getSignInRecordSummary(Long userId) { + // 1. åˆå§‹åŒ–é»˜è®¤è¿”å›žä¿¡æ¯ + // TODO @puhui999:这里 vo æ”¹æˆ summary 会更好ç†è§£ï¼› + AppMemberSignInRecordSummaryRespVO vo = new AppMemberSignInRecordSummaryRespVO(); + vo.setTotalDay(0); + vo.setContinuousDay(0); + vo.setTodaySignIn(false); + + // 2. 获å–用户签到的记录数 + Long signCount = signInRecordMapper.selectCountByUserId(userId); + if (ObjUtil.equal(signCount, 0L)) { + return vo; + } + vo.setTotalDay(signCount.intValue()); // 设置总签到天数 + + // 3. 校验当天是å¦æœ‰ç­¾åˆ° + // TODO @puhui999:是ä¸æ˜¯ signInRecord å¯ä»¥ç²¾ç®€æˆ record 哈;å¦å¤–,Desc 貌似å¯ä»¥åŽ»æŽ‰å“ˆï¼›æœ€åŽä¸€æ¡äº†ï¼› + MemberSignInRecordDO signInRecord = signInRecordMapper.selectLastRecordByUserIdDesc(userId); + if (signInRecord == null) { + return vo; + } + vo.setTodaySignIn(DateUtils.isToday(signInRecord.getCreateTime())); + + // 4. 校验今天是å¦ç­¾åˆ°ï¼Œæ²¡æœ‰ç­¾åˆ°åˆ™ç›´æŽ¥è¿”回 + if (!vo.getTodaySignIn()) { + return vo; + } + // 4.1. 判断连续签到天数 + // TODO @puhui999:连续签到,å¯ä»¥åŸºäºŽ signInRecord çš„ day 和当å‰æ—¶é—´åˆ¤æ–­å‘€ï¼Ÿ + List signInRecords = signInRecordMapper.selectListByUserId(userId); + vo.setContinuousDay(calculateConsecutiveDays(signInRecords)); + return vo; + } + + /** + * 计算连续签到天数 + * + * @param signInRecords 签到记录列表 + * @return int 连续签到天数 + */ + public int calculateConsecutiveDays(List signInRecords) { + int consecutiveDays = 1; // åˆå§‹è¿žç»­å¤©æ•°ä¸º1 + LocalDate previousDate = null; + + for (MemberSignInRecordDO record : signInRecords) { + LocalDate currentDate = record.getCreateTime().toLocalDate(); + + if (previousDate != null) { + // 检查相邻两个日期是å¦è¿žç»­ + if (currentDate.minusDays(1).isEqual(previousDate)) { + consecutiveDays++; + } else { + // 如果日期ä¸è¿žç»­ï¼Œåœæ­¢é历 + break; + } + } + + previousDate = currentDate; + } + + return consecutiveDays; + } + + @Override + public PageResult getSignInRecordPage(MemberSignInRecordPageReqVO pageReqVO) { + // æ ¹æ®ç”¨æˆ·æ˜µç§°æŸ¥è¯¢å‡ºç”¨æˆ·ids + Set userIds = null; + if (StringUtils.isNotBlank(pageReqVO.getNickname())) { + List users = memberUserApi.getUserListByNickname(pageReqVO.getNickname()); + // 如果查询用户结果为空直接返回无需继续查询 + if (CollUtil.isEmpty(users)) { + return PageResult.empty(); + } + userIds = convertSet(users, MemberUserRespDTO::getId); + } + // 分页查询 + return signInRecordMapper.selectPage(pageReqVO, userIds); + } + + @Override + public PageResult getSignRecordPage(Long userId, PageParam pageParam) { + return signInRecordMapper.selectPage(userId, pageParam); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public MemberSignInRecordDO createSignRecord(Long userId) { + // 1. 获å–当å‰ç”¨æˆ·æœ€è¿‘的签到 + MemberSignInRecordDO lastRecord = signInRecordMapper.selectLastRecordByUserIdDesc(userId); + // 1.1. 判断是å¦é‡å¤ç­¾åˆ° + validateSigned(lastRecord); + + // 2. 获å–当å‰ç”¨æˆ·æœ€æ—©çš„一次å‰ç«¯è®°å½•ï¼Œç”¨äºŽè®¡ç®—今天是第几天签到 + MemberSignInRecordDO firstRecord = signInRecordMapper.selectLastRecordByUserIdAsc(userId); + // 2.1. 获å–所有的签到规则 + List signInConfigs = signInConfigService.getSignInConfigList(CommonStatusEnum.ENABLE.getStatus()); + signInConfigs.sort(Comparator.comparing(MemberSignInConfigDO::getDay)); + // 2.2. 组åˆæ•°æ® + MemberSignInRecordDO record = MemberSignInRecordConvert.INSTANCE.convert(userId, firstRecord, signInConfigs); + + // 3. æ’入签到记录 + signInRecordMapper.insert(record); + + // 4. 增加积分 + if (!ObjectUtils.equalsAny(record.getPoint(), null, 0)) { + pointRecordService.createPointRecord(userId, record.getPoint(), MemberPointBizTypeEnum.SIGN, String.valueOf(record.getId())); + } + // 5. 增加ç»éªŒ + if (!ObjectUtils.equalsAny(record.getExperience(), null, 0)) { + memberLevelService.addExperience(userId, record.getExperience(), MemberExperienceBizTypeEnum.SIGN_IN, String.valueOf(record.getId())); + } + return record; + } + + private void validateSigned(MemberSignInRecordDO signInRecordDO) { + if (signInRecordDO == null) { + return; + } + if (DateUtils.isToday(signInRecordDO.getCreateTime())) { + throw exception(SIGN_IN_RECORD_TODAY_EXISTS); + } + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/tag/MemberTagService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/tag/MemberTagService.java new file mode 100644 index 000000000..5e3393394 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/tag/MemberTagService.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.member.service.tag; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagUpdateReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * 会员标签 Service æŽ¥å£ + * + * @author 芋é“æºç  + */ +public interface MemberTagService { + + /** + * 创建会员标签 + * + * @param createReqVO åˆ›å»ºä¿¡æ¯ + * @return ç¼–å· + */ + Long createTag(@Valid MemberTagCreateReqVO createReqVO); + + /** + * 更新会员标签 + * + * @param updateReqVO æ›´æ–°ä¿¡æ¯ + */ + void updateTag(@Valid MemberTagUpdateReqVO updateReqVO); + + /** + * 删除会员标签 + * + * @param id ç¼–å· + */ + void deleteTag(Long id); + + /** + * 获得会员标签 + * + * @param id ç¼–å· + * @return 会员标签 + */ + MemberTagDO getTag(Long id); + + /** + * 获得会员标签列表 + * + * @param ids ç¼–å· + * @return 会员标签列表 + */ + List getTagList(Collection ids); + + /** + * 获得会员标签分页 + * + * @param pageReqVO 分页查询 + * @return 会员标签分页 + */ + PageResult getTagPage(MemberTagPageReqVO pageReqVO); + + /** + * 获å–标签列表 + * + * @return 标签列表 + */ + List getTagList(); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/tag/MemberTagServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/tag/MemberTagServiceImpl.java new file mode 100644 index 000000000..b267227d9 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/tag/MemberTagServiceImpl.java @@ -0,0 +1,125 @@ +package cn.iocoder.yudao.module.member.service.tag; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagUpdateReqVO; +import cn.iocoder.yudao.module.member.convert.tag.MemberTagConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO; +import cn.iocoder.yudao.module.member.dal.mysql.tag.MemberTagMapper; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*; + +/** + * 会员标签 Service 实现类 + * + * @author 芋é“æºç  + */ +@Service +@Validated +public class MemberTagServiceImpl implements MemberTagService { + + @Resource + private MemberTagMapper memberTagMapper; + + @Resource + private MemberUserService memberUserService; + + @Override + public Long createTag(MemberTagCreateReqVO createReqVO) { + // 校验å称唯一 + validateTagNameUnique(null, createReqVO.getName()); + // æ’å…¥ + MemberTagDO tag = MemberTagConvert.INSTANCE.convert(createReqVO); + memberTagMapper.insert(tag); + // 返回 + return tag.getId(); + } + + @Override + public void updateTag(MemberTagUpdateReqVO updateReqVO) { + // 校验存在 + validateTagExists(updateReqVO.getId()); + // 校验å称唯一 + validateTagNameUnique(updateReqVO.getId(), updateReqVO.getName()); + // æ›´æ–° + MemberTagDO updateObj = MemberTagConvert.INSTANCE.convert(updateReqVO); + memberTagMapper.updateById(updateObj); + } + + @Override + public void deleteTag(Long id) { + // 校验存在 + validateTagExists(id); + // 校验标签下是å¦æœ‰ç”¨æˆ· + validateTagHasUser(id); + // 删除 + memberTagMapper.deleteById(id); + } + + private void validateTagExists(Long id) { + if (memberTagMapper.selectById(id) == null) { + throw exception(TAG_NOT_EXISTS); + } + } + + private void validateTagNameUnique(Long id, String name) { + if (StrUtil.isBlank(name)) { + return; + } + MemberTagDO tag = memberTagMapper.selelctByName(name); + if (tag == null) { + return; + } + + // 如果 id 为空,说明ä¸ç”¨æ¯”较是å¦ä¸ºç›¸åŒ id 的标签 + if (id == null) { + throw exception(TAG_NAME_EXISTS); + } + if (!tag.getId().equals(id)) { + throw exception(TAG_NAME_EXISTS); + } + } + + void validateTagHasUser(Long id) { + Long count = memberUserService.getUserCountByTagId(id); + if (count > 0) { + throw exception(TAG_HAS_USER); + } + } + + @Override + public MemberTagDO getTag(Long id) { + return memberTagMapper.selectById(id); + } + + @Override + public List getTagList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return memberTagMapper.selectBatchIds(ids); + } + + @Override + public PageResult getTagPage(MemberTagPageReqVO pageReqVO) { + return memberTagMapper.selectPage(pageReqVO); + } + + @Override + public List getTagList() { + return memberTagMapper.selectList(); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java new file mode 100644 index 000000000..8b640c850 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java @@ -0,0 +1,172 @@ +package cn.iocoder.yudao.module.member.service.user; + +import cn.iocoder.yudao.framework.common.enums.TerminalEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateReqVO; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserResetPasswordReqVO; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdateMobileReqVO; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdatePasswordReqVO; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdateReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * 会员用户 Service æŽ¥å£ + * + * @author 芋é“æºç  + */ +public interface MemberUserService { + + /** + * 通过手机查询用户 + * + * @param mobile 手机 + * @return 用户对象 + */ + MemberUserDO getUserByMobile(String mobile); + + /** + * 基于用户昵称,模糊匹é…用户列表 + * + * @param nickname ç”¨æˆ·æ˜µç§°ï¼Œæ¨¡ç³ŠåŒ¹é… + * @return 用户信æ¯çš„列表 + */ + List getUserListByNickname(String nickname); + + /** + * 基于手机å·åˆ›å»ºç”¨æˆ·ã€‚ + * 如果用户已ç»å­˜åœ¨ï¼Œåˆ™ç›´æŽ¥è¿›è¡Œè¿”回 + * + * @param mobile æ‰‹æœºå· + * @param registerIp 注册 IP + * @param terminal 终端 {@link TerminalEnum} + * @return 用户对象 + */ + MemberUserDO createUserIfAbsent(@Mobile String mobile, String registerIp, Integer terminal); + + /** + * 更新用户的最åŽç™»é™†ä¿¡æ¯ + * + * @param id ç”¨æˆ·ç¼–å· + * @param loginIp 登陆 IP + */ + void updateUserLogin(Long id, String loginIp); + + /** + * 通过用户 ID 查询用户 + * + * @param id 用户ID + * @return ç”¨æˆ·å¯¹è±¡ä¿¡æ¯ + */ + MemberUserDO getUser(Long id); + + /** + * 通过用户 ID 查询用户们 + * + * @param ids 用户 ID + * @return 用户对象信æ¯æ•°ç»„ + */ + List getUserList(Collection ids); + + /** + * ã€ä¼šå‘˜ã€‘ä¿®æ”¹åŸºæœ¬ä¿¡æ¯ + * + * @param userId ç”¨æˆ·ç¼–å· + * @param reqVO åŸºæœ¬ä¿¡æ¯ + */ + void updateUser(Long userId, AppMemberUserUpdateReqVO reqVO); + + /** + * ã€ä¼šå‘˜ã€‘修改手机 + * + * @param userId ç”¨æˆ·ç¼–å· + * @param reqVO è¯·æ±‚ä¿¡æ¯ + */ + void updateUserMobile(Long userId, AppMemberUserUpdateMobileReqVO reqVO); + + /** + * ã€ä¼šå‘˜ã€‘ä¿®æ”¹å¯†ç  + * + * @param userId ç”¨æˆ·ç¼–å· + * @param reqVO è¯·æ±‚ä¿¡æ¯ + */ + void updateUserPassword(Long userId, AppMemberUserUpdatePasswordReqVO reqVO); + + /** + * ã€ä¼šå‘˜ã€‘å¿˜è®°å¯†ç  + * + * @param reqVO è¯·æ±‚ä¿¡æ¯ + */ + void resetUserPassword(AppMemberUserResetPasswordReqVO reqVO); + + /** + * 判断密ç æ˜¯å¦åŒ¹é… + * + * @param rawPassword æœªåŠ å¯†çš„å¯†ç  + * @param encodedPassword 加密åŽçš„å¯†ç  + * @return 是å¦åŒ¹é… + */ + boolean isPasswordMatch(String rawPassword, String encodedPassword); + + /** + * ã€ç®¡ç†å‘˜ã€‘更新会员用户 + * + * @param updateReqVO æ›´æ–°ä¿¡æ¯ + */ + void updateUser(@Valid MemberUserUpdateReqVO updateReqVO); + + /** + * ã€ç®¡ç†å‘˜ã€‘获得会员用户分页 + * + * @param pageReqVO 分页查询 + * @return 会员用户分页 + */ + PageResult getUserPage(MemberUserPageReqVO pageReqVO); + + /** + * 更新用户的等级和ç»éªŒ + * + * @param id ç”¨æˆ·ç¼–å· + * @param levelId 用户等级 + * @param experience 用户ç»éªŒ + */ + void updateUserLevel(Long id, Long levelId, Integer experience); + + /** + * èŽ·å¾—æŒ‡å®šç”¨æˆ·åˆ†ç»„ä¸‹çš„ç”¨æˆ·æ•°é‡ + * + * @param groupId ç”¨æˆ·åˆ†ç»„ç¼–å· + * @return ç”¨æˆ·æ•°é‡ + */ + Long getUserCountByGroupId(Long groupId); + + /** + * èŽ·å¾—æŒ‡å®šç”¨æˆ·ç­‰çº§ä¸‹çš„ç”¨æˆ·æ•°é‡ + * + * @param levelId ç”¨æˆ·ç­‰çº§ç¼–å· + * @return ç”¨æˆ·æ•°é‡ + */ + Long getUserCountByLevelId(Long levelId); + + /** + * èŽ·å¾—æŒ‡å®šä¼šå‘˜æ ‡ç­¾ä¸‹çš„ç”¨æˆ·æ•°é‡ + * + * @param tagId ç”¨æˆ·æ ‡ç­¾ç¼–å· + * @return ç”¨æˆ·æ•°é‡ + */ + Long getUserCountByTagId(Long tagId); + + /** + * 更新用户的积分 + * + * @param userId ç”¨æˆ·ç¼–å· + * @param point ç§¯åˆ†æ•°é‡ + * @return 更新结果 + */ + boolean updateUserPoint(Long userId, Integer point); +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java new file mode 100644 index 000000000..0d53c388d --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java @@ -0,0 +1,294 @@ +package cn.iocoder.yudao.module.member.service.user; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.api.file.FileApi; +import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateReqVO; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserResetPasswordReqVO; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdateMobileReqVO; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdatePasswordReqVO; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdateReqVO; +import cn.iocoder.yudao.module.member.convert.auth.AuthConvert; +import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; +import cn.iocoder.yudao.module.member.mq.producer.user.UserCreateProducer; +import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; +import com.google.common.annotations.VisibleForTesting; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; +import org.springframework.transaction.support.TransactionTemplate; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*; + +/** + * 会员 User Service 实现类 + * + * @author 芋é“æºç  + */ +@Service +@Valid +@Slf4j +public class MemberUserServiceImpl implements MemberUserService { + + @Resource + private MemberUserMapper memberUserMapper; + + @Resource + private FileApi fileApi; + @Resource + private SmsCodeApi smsCodeApi; + + @Resource + private PasswordEncoder passwordEncoder; + + @Resource + private UserCreateProducer registerCouponProducer; + + @Resource + private TransactionTemplate transactionTemplate; + + @Override + public MemberUserDO getUserByMobile(String mobile) { + return memberUserMapper.selectByMobile(mobile); + } + + @Override + public List getUserListByNickname(String nickname) { + return memberUserMapper.selectListByNicknameLike(nickname); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public MemberUserDO createUserIfAbsent(String mobile, String registerIp, Integer terminal) { + // 用户已ç»å­˜åœ¨ + MemberUserDO user = memberUserMapper.selectByMobile(mobile); + if (user != null) { + return user; + } + // 用户ä¸å­˜åœ¨ï¼Œåˆ™è¿›è¡Œåˆ›å»º + return createUser(mobile, registerIp, terminal); + } + + private MemberUserDO createUser(String mobile, String registerIp, Integer terminal) { + // 生æˆå¯†ç  + String password = IdUtil.fastSimpleUUID(); + // æ’入用户 + MemberUserDO user = new MemberUserDO(); + user.setMobile(mobile); + user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // é»˜è®¤å¼€å¯ + user.setPassword(encodePassword(password)); // åŠ å¯†å¯†ç  + user.setRegisterIp(registerIp); + user.setRegisterTerminal(terminal); + memberUserMapper.insert(user); + + // å‘é€ MQ 消æ¯ï¼šç”¨æˆ·åˆ›å»º + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + + @Override + public void afterCommit() { + registerCouponProducer.sendUserCreateMessage(user.getId()); + } + + }); + return user; + } + + @Override + public void updateUserLogin(Long id, String loginIp) { + memberUserMapper.updateById(new MemberUserDO().setId(id) + .setLoginIp(loginIp).setLoginDate(LocalDateTime.now())); + } + + @Override + public MemberUserDO getUser(Long id) { + return memberUserMapper.selectById(id); + } + + @Override + public List getUserList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return memberUserMapper.selectBatchIds(ids); + } + + @Override + public void updateUser(Long userId, AppMemberUserUpdateReqVO reqVO) { + memberUserMapper.updateById(new MemberUserDO().setId(userId) + .setNickname(reqVO.getNickname()).setAvatar(reqVO.getAvatar())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateUserMobile(Long userId, AppMemberUserUpdateMobileReqVO reqVO) { + // 检测用户是å¦å­˜åœ¨ + MemberUserDO user = validateUserExists(userId); + // 校验新手机是å¦å·²ç»è¢«ç»‘定 + validateMobileUnique(null, reqVO.getMobile()); + + // 校验旧手机和旧验è¯ç  + smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getOldCode()) + .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())); + // 使用新验è¯ç  + smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getMobile()).setCode(reqVO.getCode()) + .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())); + + // 更新用户手机 + memberUserMapper.updateById(MemberUserDO.builder().id(userId).mobile(reqVO.getMobile()).build()); + } + + @Override + public void updateUserPassword(Long userId, AppMemberUserUpdatePasswordReqVO reqVO) { + // 检测用户是å¦å­˜åœ¨ + MemberUserDO user = validateUserExists(userId); + // 校验验è¯ç  + smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getCode()) + .setScene(SmsSceneEnum.MEMBER_UPDATE_PASSWORD.getScene()).setUsedIp(getClientIP())); + + // æ›´æ–°ç”¨æˆ·å¯†ç  + memberUserMapper.updateById(MemberUserDO.builder().id(userId) + .password(passwordEncoder.encode(reqVO.getPassword())).build()); + } + + @Override + public void resetUserPassword(AppMemberUserResetPasswordReqVO reqVO) { + // 检验用户是å¦å­˜åœ¨ + MemberUserDO user = validateUserExists(reqVO.getMobile()); + + // 使用验è¯ç  + smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_RESET_PASSWORD, + getClientIP())); + + // æ›´æ–°å¯†ç  + memberUserMapper.updateById(MemberUserDO.builder().id(user.getId()) + .password(passwordEncoder.encode(reqVO.getPassword())).build()); + } + + private MemberUserDO validateUserExists(String mobile) { + MemberUserDO user = memberUserMapper.selectByMobile(mobile); + if (user == null) { + throw exception(USER_MOBILE_NOT_EXISTS); + } + return user; + } + + @Override + public boolean isPasswordMatch(String rawPassword, String encodedPassword) { + return passwordEncoder.matches(rawPassword, encodedPassword); + } + + /** + * 对密ç è¿›è¡ŒåŠ å¯† + * + * @param password å¯†ç  + * @return 加密åŽçš„å¯†ç  + */ + private String encodePassword(String password) { + return passwordEncoder.encode(password); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateUser(MemberUserUpdateReqVO updateReqVO) { + // 校验存在 + validateUserExists(updateReqVO.getId()); + // 校验手机唯一 + validateMobileUnique(updateReqVO.getId(), updateReqVO.getMobile()); + + // æ›´æ–° + MemberUserDO updateObj = MemberUserConvert.INSTANCE.convert(updateReqVO); + memberUserMapper.updateById(updateObj); + } + + @VisibleForTesting + MemberUserDO validateUserExists(Long id) { + if (id == null) { + return null; + } + MemberUserDO user = memberUserMapper.selectById(id); + if (user == null) { + throw exception(USER_NOT_EXISTS); + } + return user; + } + + @VisibleForTesting + void validateMobileUnique(Long id, String mobile) { + if (StrUtil.isBlank(mobile)) { + return; + } + MemberUserDO user = memberUserMapper.selectByMobile(mobile); + if (user == null) { + return; + } + // 如果 id 为空,说明ä¸ç”¨æ¯”较是å¦ä¸ºç›¸åŒ id 的用户 + if (id == null) { + throw exception(USER_MOBILE_USED, mobile); + } + if (!user.getId().equals(id)) { + throw exception(USER_MOBILE_USED, mobile); + } + } + + @Override + public PageResult getUserPage(MemberUserPageReqVO pageReqVO) { + return memberUserMapper.selectPage(pageReqVO); + } + + @Override + public void updateUserLevel(Long id, Long levelId, Integer experience) { + // 0 代表无等级:防止UpdateById时,会被过滤掉的问题 + levelId = ObjectUtil.defaultIfNull(levelId, 0L); + memberUserMapper.updateById(new MemberUserDO() + .setId(id) + .setLevelId(levelId).setExperience(experience) + ); + } + + @Override + public Long getUserCountByGroupId(Long groupId) { + return memberUserMapper.selectCountByGroupId(groupId); + } + + @Override + public Long getUserCountByLevelId(Long levelId) { + return memberUserMapper.selectCountByLevelId(levelId); + } + + @Override + public Long getUserCountByTagId(Long tagId) { + return memberUserMapper.selectCountByTagId(tagId); + } + + @Override + public boolean updateUserPoint(Long id, Integer point) { + if (point > 0) { + memberUserMapper.updatePointIncr(id, point); + } else if (point < 0) { + return memberUserMapper.updatePointDecr(id, point) > 0; + } + return true; + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java new file mode 100644 index 000000000..e4337f2c9 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java @@ -0,0 +1,98 @@ +package cn.iocoder.yudao.module.member.service.address; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; +import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; +import cn.iocoder.yudao.module.member.dal.mysql.address.MemberAddressMapper; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.ADDRESS_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +/** + * {@link AddressServiceImpl} çš„å•å…ƒæµ‹è¯•ç±» + * + * @author 芋é“æºç  + */ +@Import(AddressServiceImpl.class) +public class AddressServiceImplTest extends BaseDbUnitTest { + + @Resource + private AddressServiceImpl addressService; + + @Resource + private MemberAddressMapper addressMapper; + + @Test + public void testCreateAddress_success() { + // 准备å‚æ•° + AppAddressCreateReqVO reqVO = randomPojo(AppAddressCreateReqVO.class); + + // 调用 + Long addressId = addressService.createAddress(randomLongId(), reqVO); + // 断言 + assertNotNull(addressId); + // 校验记录的属性是å¦æ­£ç¡® + MemberAddressDO address = addressMapper.selectById(addressId); + assertPojoEquals(reqVO, address); + } + + @Test + public void testUpdateAddress_success() { + // mock æ•°æ® + MemberAddressDO dbAddress = randomPojo(MemberAddressDO.class); + addressMapper.insert(dbAddress);// @Sql: å…ˆæ’入出一æ¡å­˜åœ¨çš„æ•°æ® + // 准备å‚æ•° + AppAddressUpdateReqVO reqVO = randomPojo(AppAddressUpdateReqVO.class, o -> { + o.setId(dbAddress.getId()); // 设置更新的 ID + }); + + // 调用 + addressService.updateAddress(dbAddress.getUserId(), reqVO); + // 校验是å¦æ›´æ–°æ­£ç¡® + MemberAddressDO address = addressMapper.selectById(reqVO.getId()); // 获å–最新的 + assertPojoEquals(reqVO, address); + } + + @Test + public void testUpdateAddress_notExists() { + // 准备å‚æ•° + AppAddressUpdateReqVO reqVO = randomPojo(AppAddressUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> addressService.updateAddress(randomLongId(), reqVO), ADDRESS_NOT_EXISTS); + } + + @Test + public void testDeleteAddress_success() { + // mock æ•°æ® + MemberAddressDO dbAddress = randomPojo(MemberAddressDO.class); + addressMapper.insert(dbAddress);// @Sql: å…ˆæ’入出一æ¡å­˜åœ¨çš„æ•°æ® + // 准备å‚æ•° + Long id = dbAddress.getId(); + + // 调用 + addressService.deleteAddress(dbAddress.getUserId(), id); + // 校验数æ®ä¸å­˜åœ¨äº† + assertNull(addressMapper.selectById(id)); + } + + @Test + public void testDeleteAddress_notExists() { + // 准备å‚æ•° + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> addressService.deleteAddress(randomLongId(), id), ADDRESS_NOT_EXISTS); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceTest.java b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceTest.java new file mode 100644 index 000000000..78ddc5677 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceTest.java @@ -0,0 +1,118 @@ +package cn.iocoder.yudao.module.member.service.auth; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; +import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import cn.iocoder.yudao.module.system.api.logger.LoginLogApi; +import cn.iocoder.yudao.module.system.api.oauth2.OAuth2TokenApi; +import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; +import cn.iocoder.yudao.module.system.api.social.SocialUserApi; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.security.crypto.password.PasswordEncoder; + +import javax.annotation.Resource; +import java.util.function.Consumer; + +import static cn.hutool.core.util.RandomUtil.randomEle; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; + +// TODO @芋艿:å•æµ‹çš„ review,等逻辑都达æˆä¸€è‡´åŽ +/** + * {@link MemberAuthService} çš„å•å…ƒæµ‹è¯•ç±» + * + * @author 宋天 + */ +@Import({MemberAuthServiceImpl.class, YudaoRedisAutoConfiguration.class}) +public class MemberAuthServiceTest extends BaseDbAndRedisUnitTest { + + // TODO @芋艿:登录相关的å•æµ‹ï¼Œå¾…补全 + + @Resource + private MemberAuthServiceImpl authService; + + @MockBean + private MemberUserService userService; + @MockBean + private SmsCodeApi smsCodeApi; + @MockBean + private LoginLogApi loginLogApi; + @MockBean + private OAuth2TokenApi oauth2TokenApi; + @MockBean + private SocialUserApi socialUserApi; + @MockBean + private PasswordEncoder passwordEncoder; + + @Resource + private MemberUserMapper memberUserMapper; + + // TODO 芋艿:åŽç»­é‡æž„这个å•æµ‹ +// @Test +// public void testUpdatePassword_success(){ +// // 准备å‚æ•° +// MemberUserDO userDO = randomUserDO(); +// memberUserMapper.insert(userDO); +// +// // æ–°å¯†ç  +// String newPassword = randomString(); +// +// // 请求实体 +// AppMemberUserUpdatePasswordReqVO reqVO = AppMemberUserUpdatePasswordReqVO.builder() +// .oldPassword(userDO.getPassword()) +// .password(newPassword) +// .build(); +// +// // 测试桩 +// // 这两个相等是为了返回ture这个结果 +// when(passwordEncoder.matches(reqVO.getOldPassword(),reqVO.getOldPassword())).thenReturn(true); +// when(passwordEncoder.encode(newPassword)).thenReturn(newPassword); +// +// // æ›´æ–°ç”¨æˆ·å¯†ç  +// authService.updatePassword(userDO.getId(), reqVO); +// assertEquals(memberUserMapper.selectById(userDO.getId()).getPassword(),newPassword); +// } + + // TODO 芋艿:åŽç»­é‡æž„这个å•æµ‹ +// @Test +// public void testResetPassword_success(){ +// // 准备å‚æ•° +// MemberUserDO userDO = randomUserDO(); +// memberUserMapper.insert(userDO); +// +// // éšæœºå¯†ç  +// String password = randomNumbers(11); +// // éšæœºéªŒè¯ç  +// String code = randomNumbers(4); +// +// // mock +// when(passwordEncoder.encode(password)).thenReturn(password); +// +// // æ›´æ–°ç”¨æˆ·å¯†ç  +// AppMemberUserResetPasswordReqVO reqVO = new AppMemberUserResetPasswordReqVO(); +// reqVO.setMobile(userDO.getMobile()); +// reqVO.setPassword(password); +// reqVO.setCode(code); +// +// authService.resetPassword(reqVO); +// assertEquals(memberUserMapper.selectById(userDO.getId()).getPassword(),password); +// } + + // ========== éšæœºå¯¹è±¡ ========== + + @SafeVarargs + private static MemberUserDO randomUserDO(Consumer... consumers) { + Consumer consumer = (o) -> { + o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // ä¿è¯ status 的范围 + o.setPassword(randomString()); + }; + return randomPojo(MemberUserDO.class, ArrayUtils.append(consumer, consumers)); + } + + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/group/MemberGroupServiceImplTest.java b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/group/MemberGroupServiceImplTest.java new file mode 100644 index 000000000..6d8e6f9ce --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/group/MemberGroupServiceImplTest.java @@ -0,0 +1,160 @@ +package cn.iocoder.yudao.module.member.service.group; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupUpdateReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.group.MemberGroupDO; +import cn.iocoder.yudao.module.member.dal.mysql.group.MemberGroupMapper; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.GROUP_HAS_USER; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.GROUP_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +// TODO 芋艿:完全 review 完,在去 review å•æµ‹ +/** + * {@link MemberGroupServiceImpl} çš„å•å…ƒæµ‹è¯•ç±» + * + * @author owen + */ +@Import(MemberGroupServiceImpl.class) +public class MemberGroupServiceImplTest extends BaseDbUnitTest { + + @Resource + private MemberGroupServiceImpl groupService; + + @Resource + private MemberGroupMapper groupMapper; + + @MockBean + private MemberUserService memberUserService; + + @Test + public void testCreateGroup_success() { + // 准备å‚æ•° + MemberGroupCreateReqVO reqVO = randomPojo(MemberGroupCreateReqVO.class, + o -> o.setStatus(randomCommonStatus())); + + // 调用 + Long groupId = groupService.createGroup(reqVO); + // 断言 + assertNotNull(groupId); + // 校验记录的属性是å¦æ­£ç¡® + MemberGroupDO group = groupMapper.selectById(groupId); + assertPojoEquals(reqVO, group); + } + + @Test + public void testUpdateGroup_success() { + // mock æ•°æ® + MemberGroupDO dbGroup = randomPojo(MemberGroupDO.class); + groupMapper.insert(dbGroup);// @Sql: å…ˆæ’入出一æ¡å­˜åœ¨çš„æ•°æ® + // 准备å‚æ•° + MemberGroupUpdateReqVO reqVO = randomPojo(MemberGroupUpdateReqVO.class, o -> { + o.setId(dbGroup.getId()); // 设置更新的 ID + o.setStatus(randomCommonStatus()); + }); + + // 调用 + groupService.updateGroup(reqVO); + // 校验是å¦æ›´æ–°æ­£ç¡® + MemberGroupDO group = groupMapper.selectById(reqVO.getId()); // 获å–最新的 + assertPojoEquals(reqVO, group); + } + + @Test + public void testUpdateGroup_notExists() { + // 准备å‚æ•° + MemberGroupUpdateReqVO reqVO = randomPojo(MemberGroupUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> groupService.updateGroup(reqVO), GROUP_NOT_EXISTS); + } + + @Test + public void testDeleteGroup_success() { + // mock æ•°æ® + MemberGroupDO dbGroup = randomPojo(MemberGroupDO.class); + groupMapper.insert(dbGroup);// @Sql: å…ˆæ’入出一æ¡å­˜åœ¨çš„æ•°æ® + // 准备å‚æ•° + Long id = dbGroup.getId(); + + // 调用 + groupService.deleteGroup(id); + // 校验数æ®ä¸å­˜åœ¨äº† + assertNull(groupMapper.selectById(id)); + } + + @Test + public void testDeleteGroup_notExists() { + // 准备å‚æ•° + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> groupService.deleteGroup(id), GROUP_NOT_EXISTS); + } + + @Test + public void testDeleteGroup_hasUser() { + // mock æ•°æ® + MemberGroupDO dbGroup = randomPojo(MemberGroupDO.class); + groupMapper.insert(dbGroup);// @Sql: å…ˆæ’入出一æ¡å­˜åœ¨çš„æ•°æ® + // 准备å‚æ•° + Long id = dbGroup.getId(); + + // mock ä¼šå‘˜æ•°æ® + when(memberUserService.getUserCountByGroupId(eq(id))).thenReturn(1L); + + // 调用, 并断言异常 + assertServiceException(() -> groupService.deleteGroup(id), GROUP_HAS_USER); + } + + @Test + public void testGetGroupPage() { + String name = randomString(); + int status = CommonStatusEnum.ENABLE.getStatus(); + + // mock æ•°æ® + MemberGroupDO dbGroup = randomPojo(MemberGroupDO.class, o -> { // 等会查询到 + o.setName(name); + o.setStatus(status); + o.setCreateTime(buildTime(2023, 2, 18)); + }); + groupMapper.insert(dbGroup); + // 测试 name ä¸åŒ¹é… + groupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setName(""))); + // 测试 status ä¸åŒ¹é… + groupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); + // 测试 createTime ä¸åŒ¹é… + groupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setCreateTime(null))); + // 准备å‚æ•° + MemberGroupPageReqVO reqVO = new MemberGroupPageReqVO(); + reqVO.setName(name); + reqVO.setStatus(status); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = groupService.getGroupPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbGroup, pageResult.getList().get(0)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImplTest.java b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImplTest.java new file mode 100644 index 000000000..439322913 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImplTest.java @@ -0,0 +1,268 @@ +package cn.iocoder.yudao.module.member.service.level; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelListReqVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelUpdateReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; +import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelMapper; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.List; +import java.util.function.Consumer; + +import static cn.hutool.core.util.RandomUtil.randomInt; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*; +import static org.junit.jupiter.api.Assertions.*; + +// TODO 芋艿:完全 review 完,在去 review å•æµ‹ +/** + * {@link MemberLevelServiceImpl} çš„å•å…ƒæµ‹è¯•ç±» + * + * @author owen + */ +@Import(MemberLevelServiceImpl.class) +public class MemberLevelServiceImplTest extends BaseDbUnitTest { + + @Resource + private MemberLevelServiceImpl levelService; + + @Resource + private MemberLevelMapper memberlevelMapper; + + @MockBean + private MemberLevelRecordService memberLevelRecordService; + @MockBean + private MemberExperienceRecordService memberExperienceRecordService; + @MockBean + private MemberUserService memberUserService; + + @Test + public void testCreateLevel_success() { + // 准备å‚æ•° + MemberLevelCreateReqVO reqVO = randomPojo(MemberLevelCreateReqVO.class, o -> { + o.setDiscountPercent(randomInt()); + o.setIcon(randomURL()); + o.setBackgroundUrl(randomURL()); + o.setStatus(randomCommonStatus()); + }); + + // 调用 + Long levelId = levelService.createLevel(reqVO); + // 断言 + assertNotNull(levelId); + // 校验记录的属性是å¦æ­£ç¡® + MemberLevelDO level = memberlevelMapper.selectById(levelId); + assertPojoEquals(reqVO, level); + } + + @Test + public void testUpdateLevel_success() { + // mock æ•°æ® + MemberLevelDO dbLevel = randomPojo(MemberLevelDO.class); + memberlevelMapper.insert(dbLevel);// @Sql: å…ˆæ’入出一æ¡å­˜åœ¨çš„æ•°æ® + // 准备å‚æ•° + MemberLevelUpdateReqVO reqVO = randomPojo(MemberLevelUpdateReqVO.class, o -> { + o.setId(dbLevel.getId()); // 设置更新的 ID + //以下è¦ä¿æŒä¸€è‡´ + o.setName(dbLevel.getName()); + o.setLevel(dbLevel.getLevel()); + o.setExperience(dbLevel.getExperience()); + //以下是è¦ä¿®æ”¹çš„字段 + o.setDiscountPercent(randomInt()); + o.setIcon(randomURL()); + o.setBackgroundUrl(randomURL()); + o.setStatus(randomCommonStatus()); + }); + + // 调用 + levelService.updateLevel(reqVO); + // 校验是å¦æ›´æ–°æ­£ç¡® + MemberLevelDO level = memberlevelMapper.selectById(reqVO.getId()); // 获å–最新的 + assertPojoEquals(reqVO, level); + } + + @Test + public void testUpdateLevel_notExists() { + // 准备å‚æ•° + MemberLevelUpdateReqVO reqVO = randomPojo(MemberLevelUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> levelService.updateLevel(reqVO), LEVEL_NOT_EXISTS); + } + + @Test + public void testDeleteLevel_success() { + // mock æ•°æ® + MemberLevelDO dbLevel = randomPojo(MemberLevelDO.class); + memberlevelMapper.insert(dbLevel);// @Sql: å…ˆæ’入出一æ¡å­˜åœ¨çš„æ•°æ® + // 准备å‚æ•° + Long id = dbLevel.getId(); + + // 调用 + levelService.deleteLevel(id); + // 校验数æ®ä¸å­˜åœ¨äº† + assertNull(memberlevelMapper.selectById(id)); + } + + @Test + public void testDeleteLevel_notExists() { + // 准备å‚æ•° + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> levelService.deleteLevel(id), LEVEL_NOT_EXISTS); + } + + @Test + public void testGetLevelList() { + // mock æ•°æ® + MemberLevelDO dbLevel = randomPojo(MemberLevelDO.class, o -> { // 等会查询到 + o.setName("黄金会员"); + o.setStatus(1); + }); + memberlevelMapper.insert(dbLevel); + // 测试 name ä¸åŒ¹é… + memberlevelMapper.insert(cloneIgnoreId(dbLevel, o -> o.setName(""))); + // 测试 status ä¸åŒ¹é… + memberlevelMapper.insert(cloneIgnoreId(dbLevel, o -> o.setStatus(0))); + // 准备å‚æ•° + MemberLevelListReqVO reqVO = new MemberLevelListReqVO(); + reqVO.setName("黄金会员"); + reqVO.setStatus(1); + + // 调用 + List list = levelService.getLevelList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbLevel, list.get(0)); + } + + @Test + public void testCreateLevel_nameUnique() { + // 准备å‚æ•° + String name = randomString(); + + // mock æ•°æ® + memberlevelMapper.insert(randomLevelDO(o -> o.setName(name))); + + // 调用,校验异常 + List list = memberlevelMapper.selectList(); + assertServiceException(() -> levelService.validateNameUnique(list, null, name), LEVEL_NAME_EXISTS, name); + } + + @Test + public void testUpdateLevel_nameUnique() { + // 准备å‚æ•° + Long id = randomLongId(); + String name = randomString(); + + // mock æ•°æ® + memberlevelMapper.insert(randomLevelDO(o -> o.setName(name))); + + // 调用,校验异常 + List list = memberlevelMapper.selectList(); + assertServiceException(() -> levelService.validateNameUnique(list, id, name), LEVEL_NAME_EXISTS, name); + } + + @Test + public void testCreateLevel_levelUnique() { + // 准备å‚æ•° + Integer level = randomInteger(); + String name = randomString(); + + // mock æ•°æ® + memberlevelMapper.insert(randomLevelDO(o -> { + o.setLevel(level); + o.setName(name); + })); + + // 调用,校验异常 + List list = memberlevelMapper.selectList(); + assertServiceException(() -> levelService.validateLevelUnique(list, null, level), LEVEL_VALUE_EXISTS, level, name); + } + + @Test + public void testUpdateLevel_levelUnique() { + // 准备å‚æ•° + Long id = randomLongId(); + Integer level = randomInteger(); + String name = randomString(); + + // mock æ•°æ® + memberlevelMapper.insert(randomLevelDO(o -> { + o.setLevel(level); + o.setName(name); + })); + + // 调用,校验异常 + List list = memberlevelMapper.selectList(); + assertServiceException(() -> levelService.validateLevelUnique(list, id, level), LEVEL_VALUE_EXISTS, level, name); + } + + @Test + public void testCreateLevel_experienceOutRange() { + // 准备å‚æ•° + int level = 10; + int experience = 10; + String name = randomString(); + + // mock æ•°æ® + memberlevelMapper.insert(randomLevelDO(o -> { + o.setLevel(level); + o.setExperience(experience); + o.setName(name); + })); + List list = memberlevelMapper.selectList(); + + // 调用,校验异常 + assertServiceException(() -> levelService.validateExperienceOutRange(list, null, level + 1, experience - 1), LEVEL_EXPERIENCE_MIN, name, level); + // 调用,校验异常 + assertServiceException(() -> levelService.validateExperienceOutRange(list, null, level - 1, experience + 1), LEVEL_EXPERIENCE_MAX, name, level); + } + + @Test + public void testUpdateLevel_experienceOutRange() { + // 准备å‚æ•° + int level = 10; + int experience = 10; + Long id = randomLongId(); + String name = randomString(); + + // mock æ•°æ® + memberlevelMapper.insert(randomLevelDO(o -> { + o.setLevel(level); + o.setExperience(experience); + o.setName(name); + })); + List list = memberlevelMapper.selectList(); + + // 调用,校验异常 + assertServiceException(() -> levelService.validateExperienceOutRange(list, id, level + 1, experience - 1), LEVEL_EXPERIENCE_MIN, name, level); + // 调用,校验异常 + assertServiceException(() -> levelService.validateExperienceOutRange(list, id, level - 1, experience + 1), LEVEL_EXPERIENCE_MAX, name, level); + } + + // ========== éšæœºå¯¹è±¡ ========== + + @SafeVarargs + private static MemberLevelDO randomLevelDO(Consumer... consumers) { + Consumer consumer = (o) -> { + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + o.setDiscountPercent(randomInt(0, 100)); + o.setIcon(randomURL()); + o.setBackgroundUrl(randomURL()); + }; + return randomPojo(MemberLevelDO.class, ArrayUtils.append(consumer, consumers)); + } +} diff --git a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/tag/MemberTagServiceImplTest.java b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/tag/MemberTagServiceImplTest.java new file mode 100644 index 000000000..5fd4f7a9c --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/tag/MemberTagServiceImplTest.java @@ -0,0 +1,133 @@ +package cn.iocoder.yudao.module.member.service.tag; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagCreateReqVO; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagUpdateReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO; +import cn.iocoder.yudao.module.member.dal.mysql.tag.MemberTagMapper; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.TAG_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +// TODO 芋艿:完全 review 完,在去 review å•æµ‹ +/** + * {@link MemberTagServiceImpl} çš„å•å…ƒæµ‹è¯•ç±» + * + * @author 芋é“æºç  + */ +@Import(MemberTagServiceImpl.class) +public class MemberTagServiceImplTest extends BaseDbUnitTest { + + @Resource + private MemberTagServiceImpl tagService; + + @Resource + private MemberTagMapper tagMapper; + + @MockBean + private MemberUserService memberUserService; + + @Test + public void testCreateTag_success() { + // 准备å‚æ•° + MemberTagCreateReqVO reqVO = randomPojo(MemberTagCreateReqVO.class); + + // 调用 + Long tagId = tagService.createTag(reqVO); + // 断言 + assertNotNull(tagId); + // 校验记录的属性是å¦æ­£ç¡® + MemberTagDO tag = tagMapper.selectById(tagId); + assertPojoEquals(reqVO, tag); + } + + @Test + public void testUpdateTag_success() { + // mock æ•°æ® + MemberTagDO dbTag = randomPojo(MemberTagDO.class); + tagMapper.insert(dbTag);// @Sql: å…ˆæ’入出一æ¡å­˜åœ¨çš„æ•°æ® + // 准备å‚æ•° + MemberTagUpdateReqVO reqVO = randomPojo(MemberTagUpdateReqVO.class, o -> { + o.setId(dbTag.getId()); // 设置更新的 ID + }); + + // 调用 + tagService.updateTag(reqVO); + // 校验是å¦æ›´æ–°æ­£ç¡® + MemberTagDO tag = tagMapper.selectById(reqVO.getId()); // 获å–最新的 + assertPojoEquals(reqVO, tag); + } + + @Test + public void testUpdateTag_notExists() { + // 准备å‚æ•° + MemberTagUpdateReqVO reqVO = randomPojo(MemberTagUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> tagService.updateTag(reqVO), TAG_NOT_EXISTS); + } + + @Test + public void testDeleteTag_success() { + // mock æ•°æ® + MemberTagDO dbTag = randomPojo(MemberTagDO.class); + tagMapper.insert(dbTag);// @Sql: å…ˆæ’入出一æ¡å­˜åœ¨çš„æ•°æ® + // 准备å‚æ•° + Long id = dbTag.getId(); + + // 调用 + tagService.deleteTag(id); + // 校验数æ®ä¸å­˜åœ¨äº† + assertNull(tagMapper.selectById(id)); + } + + @Test + public void testDeleteTag_notExists() { + // 准备å‚æ•° + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> tagService.deleteTag(id), TAG_NOT_EXISTS); + } + + @Test + public void testGetTagPage() { + // mock æ•°æ® + MemberTagDO dbTag = randomPojo(MemberTagDO.class, o -> { // 等会查询到 + o.setName("test"); + o.setCreateTime(buildTime(2023, 2, 18)); + }); + tagMapper.insert(dbTag); + // 测试 name ä¸åŒ¹é… + tagMapper.insert(cloneIgnoreId(dbTag, o -> o.setName("ne"))); + // 测试 createTime ä¸åŒ¹é… + tagMapper.insert(cloneIgnoreId(dbTag, o -> o.setCreateTime(null))); + // 准备å‚æ•° + MemberTagPageReqVO reqVO = new MemberTagPageReqVO(); + reqVO.setName("test"); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = tagService.getTagPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbTag, pageResult.getList().get(0)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImplTest.java b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImplTest.java new file mode 100644 index 000000000..bff2ae0c1 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImplTest.java @@ -0,0 +1,136 @@ +package cn.iocoder.yudao.module.member.service.user; + +import cn.hutool.core.util.RandomUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; +import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest; +import cn.iocoder.yudao.module.infra.api.file.FileApi; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdateMobileReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; +import cn.iocoder.yudao.module.member.service.auth.MemberAuthServiceImpl; +import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.security.crypto.password.PasswordEncoder; + +import javax.annotation.Resource; +import java.util.function.Consumer; + +import static cn.hutool.core.util.RandomUtil.randomEle; +import static cn.hutool.core.util.RandomUtil.randomNumbers; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.assertEquals; + +// TODO @芋艿:å•æµ‹çš„ review,等逻辑都达æˆä¸€è‡´åŽ +/** + * {@link MemberUserServiceImpl} çš„å•å…ƒæµ‹è¯•ç±» + * + * @author 宋天 + */ +@Import({MemberUserServiceImpl.class, YudaoRedisAutoConfiguration.class}) +public class MemberUserServiceImplTest extends BaseDbAndRedisUnitTest { + + @Resource + private MemberUserServiceImpl memberUserService; + + @Resource + private StringRedisTemplate stringRedisTemplate; + + @Resource + private MemberUserMapper userMapper; + + @MockBean + private MemberAuthServiceImpl authService; + + @MockBean + private PasswordEncoder passwordEncoder; + + @MockBean + private SmsCodeApi smsCodeApi; + @MockBean + private FileApi fileApi; + + // TODO 芋艿:åŽç»­é‡æž„这个å•æµ‹ +// @Test +// public void testUpdateNickName_success(){ +// // mock æ•°æ® +// MemberUserDO userDO = randomUserDO(); +// userMapper.insert(userDO); +// +// // éšæœºæ˜µç§° +// String newNickName = randomString(); +// +// // 调用接å£ä¿®æ”¹æ˜µç§° +// memberUserService.updateUser(userDO.getId(),newNickName); +// // 查询新修改åŽçš„昵称 +// String nickname = memberUserService.getUser(userDO.getId()).getNickname(); +// // 断言 +// assertEquals(newNickName,nickname); +// } +// +// @Test +// public void testUpdateAvatar_success() throws Exception { +// // mock æ•°æ® +// MemberUserDO dbUser = randomUserDO(); +// userMapper.insert(dbUser); +// +// // 准备å‚æ•° +// Long userId = dbUser.getId(); +// byte[] avatarFileBytes = randomBytes(10); +// ByteArrayInputStream avatarFile = new ByteArrayInputStream(avatarFileBytes); +// // mock 方法 +// String avatar = randomString(); +// when(fileApi.createFile(eq(avatarFileBytes))).thenReturn(avatar); +// // 调用 +// String str = memberUserService.updateUserAvatar(userId, avatarFile); +// // 断言 +// assertEquals(avatar, str); +// } + + @Test + @Disabled // TODO 芋艿:åŽç»­å†ä¿®å¤ + public void updateMobile_success(){ + // mockæ•°æ® + String oldMobile = randomNumbers(11); + MemberUserDO userDO = randomUserDO(); + userDO.setMobile(oldMobile); + userMapper.insert(userDO); + + // TODO 芋艿:需è¦ä¿®å¤è¯¥å•å…ƒæµ‹è¯•ï¼Œé‡æž„多模å—带æ¥çš„ + // 旧手机和旧验è¯ç  +// SmsCodeDO codeDO = new SmsCodeDO(); + String oldCode = RandomUtil.randomString(4); +// codeDO.setMobile(userDO.getMobile()); +// codeDO.setCode(oldCode); +// codeDO.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()); +// codeDO.setUsed(Boolean.FALSE); +// when(smsCodeService.checkCodeIsExpired(codeDO.getMobile(),codeDO.getCode(),codeDO.getScene())).thenReturn(codeDO); + + // æ›´æ–°æ‰‹æœºå· + String newMobile = randomNumbers(11); + String newCode = randomNumbers(4); + AppMemberUserUpdateMobileReqVO reqVO = new AppMemberUserUpdateMobileReqVO(); + reqVO.setMobile(newMobile); + reqVO.setCode(newCode); + reqVO.setOldCode(oldCode); + memberUserService.updateUserMobile(userDO.getId(),reqVO); + + assertEquals(memberUserService.getUser(userDO.getId()).getMobile(),newMobile); + } + + // ========== éšæœºå¯¹è±¡ ========== + + @SafeVarargs + private static MemberUserDO randomUserDO(Consumer... consumers) { + Consumer consumer = (o) -> { + o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // ä¿è¯ status 的范围 + }; + return randomPojo(MemberUserDO.class, ArrayUtils.append(consumer, consumers)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/test/resources/application-unit-test.yaml b/yudao-module-member/yudao-module-member-biz/src/test/resources/application-unit-test.yaml new file mode 100644 index 000000000..a384353aa --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/test/resources/application-unit-test.yaml @@ -0,0 +1,49 @@ +spring: + main: + lazy-initialization: true # å¼€å¯æ‡’加载,加快速度 + banner-mode: off # å•å…ƒæµ‹è¯•ï¼Œç¦ç”¨ Banner + +--- #################### æ•°æ®åº“相关é…ç½® #################### + +spring: + # æ•°æ®æºé…置项 + datasource: + name: ruoyi-vue-pro + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模å¼ï¼›DATABASE_TO_UPPER é…置表和字段使用å°å†™ + driver-class-name: org.h2.Driver + username: sa + password: + druid: + async-init: true # å•å…ƒæµ‹è¯•ï¼Œå¼‚æ­¥åˆå§‹åŒ– Druid 连接池,æå‡å¯åŠ¨é€Ÿåº¦ + initial-size: 1 # å•å…ƒæµ‹è¯•ï¼Œé…置为 1,æå‡å¯åŠ¨é€Ÿåº¦ + sql: + init: + schema-locations: classpath:/sql/create_tables.sql + + # Redis é…置。Redisson 默认的é…置足够使用,一般ä¸éœ€è¦è¿›è¡Œè°ƒä¼˜ + redis: + host: 127.0.0.1 # åœ°å€ + port: 16379 # 端å£ï¼ˆå•å…ƒæµ‹è¯•ï¼Œä½¿ç”¨ 16379 端å£ï¼‰ + database: 0 # æ•°æ®åº“索引 + +mybatis: + lazy-initialization: true # å•å…ƒæµ‹è¯•ï¼Œè®¾ç½® MyBatis Mapper 延迟加载,加速æ¯ä¸ªå•å…ƒæµ‹è¯• + +--- #################### 定时任务相关é…ç½® #################### + +--- #################### é…置中心相关é…ç½® #################### + +--- #################### æœåŠ¡ä¿éšœç›¸å…³é…ç½® #################### + +# Lock4j é…置项(å•å…ƒæµ‹è¯•ï¼Œç¦ç”¨ Lock4j) + +# Resilience4j é…置项 + +--- #################### 监控相关é…ç½® #################### + +--- #################### 芋é“相关é…ç½® #################### + +# 芋é“é…置项,设置当å‰é¡¹ç›®æ‰€æœ‰è‡ªå®šä¹‰çš„é…ç½® +yudao: + info: + base-package: cn.iocoder.yudao.module diff --git a/yudao-module-member/yudao-module-member-biz/src/test/resources/logback.xml b/yudao-module-member/yudao-module-member-biz/src/test/resources/logback.xml new file mode 100644 index 000000000..daf756bff --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/test/resources/logback.xml @@ -0,0 +1,4 @@ + + + + diff --git a/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/clean.sql b/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/clean.sql new file mode 100644 index 000000000..f972e048d --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/clean.sql @@ -0,0 +1,5 @@ +DELETE FROM "member_user"; +DELETE FROM "member_address"; +DELETE FROM "member_tag"; +DELETE FROM "member_level"; +DELETE FROM "member_group"; \ No newline at end of file diff --git a/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql b/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql new file mode 100644 index 000000000..782a81810 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql @@ -0,0 +1,113 @@ +CREATE TABLE IF NOT EXISTS "member_user" +( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT 'ç¼–å·', + "nickname" varchar(30) NOT NULL DEFAULT '' COMMENT '用户昵称', + "name" varchar(30) NULL COMMENT '真实åå­—', + sex tinyint null comment '性别', + birthday datetime null comment '出生日期', + area_id int null comment '所在地', + mark varchar(255) null comment '用户备注', + point int default 0 null comment '积分', + "avatar" varchar(255) NOT NULL DEFAULT '' COMMENT '头åƒ', + "status" tinyint NOT NULL COMMENT '状æ€', + "mobile" varchar(11) NOT NULL COMMENT '手机å·', + "password" varchar(100) NOT NULL DEFAULT '' COMMENT '密ç ', + "register_ip" varchar(32) NOT NULL COMMENT '注册 IP', + "login_ip" varchar(50) NULL DEFAULT '' COMMENT '最åŽç™»å½•IP', + "login_date" datetime NULL DEFAULT NULL COMMENT '最åŽç™»å½•æ—¶é—´', + "tag_ids" varchar(255) NULL DEFAULT NULL COMMENT '用户标签编å·åˆ—表,以逗å·åˆ†éš”', + "level_id" bigint NULL DEFAULT NULL COMMENT '等级编å·', + "experience" bigint NULL DEFAULT NULL COMMENT 'ç»éªŒ', + "group_id" bigint NULL DEFAULT NULL COMMENT '用户分组编å·', + "creator" varchar(64) NULL DEFAULT '' COMMENT '创建者', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + "updater" varchar(64) NULL DEFAULT '' COMMENT '更新者', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + "deleted" bit(1) NOT NULL DEFAULT '0' COMMENT '是å¦åˆ é™¤', + "tenant_id" bigint not null default '0', + PRIMARY KEY ("id") +) COMMENT '会员表'; + +CREATE TABLE IF NOT EXISTS "member_address" ( + "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "user_id" bigint(20) NOT NULL, + "name" varchar(10) NOT NULL, + "mobile" varchar(20) NOT NULL, + "area_id" bigint(20) NOT NULL, + "detail_address" varchar(250) NOT NULL, + "default_status" bit NOT NULL, + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "creator" varchar(64) DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "updater" varchar(64) DEFAULT '', + PRIMARY KEY ("id") +) COMMENT '用户收件地å€'; + +CREATE TABLE IF NOT EXISTS "member_tag" +( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL default '0', + PRIMARY KEY ("id") +) COMMENT '会员标签'; + +CREATE TABLE IF NOT EXISTS "member_level" +( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "experience" int NOT NULL, + "level" int NOT NULL, + "discount_percent" int NOT NULL, + "icon" varchar NOT NULL, + "background_url" varchar NOT NULL, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint not null default '0', + "status" tinyint NOT NULL DEFAULT '0', + PRIMARY KEY ("id") +) COMMENT '会员等级'; + +CREATE TABLE IF NOT EXISTS "member_group" +( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "remark" varchar NOT NULL, + "status" tinyint NOT NULL DEFAULT '0', + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint not null default '0', + PRIMARY KEY ("id") +) COMMENT '用户分组'; +CREATE TABLE IF NOT EXISTS "member_brokerage_record" +( + "id" int NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "user_id" bigint NOT NULL, + "biz_id" varchar NOT NULL, + "biz_type" varchar NOT NULL, + "title" varchar NOT NULL, + "price" int NOT NULL, + "total_price" int NOT NULL, + "description" varchar NOT NULL, + "status" varchar NOT NULL, + "frozen_days" int NOT NULL, + "unfreeze_time" varchar, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint not null default '0', + PRIMARY KEY ("id") +) COMMENT '佣金记录';