Pārlūkot izejas kodu

add
实物分销;硬件权益;车位优选;后台权限;数据统计

add 新增账号直接发布车队;已过期车票列表

add 领取实物权益;实物分销

fix 账号数据统计;实物分销

fix 个人分销详情折线图;后台平台订单统计折线图

fix 寻找车队的车位类似过期时间优先上车

fix 发货时,发放实物权益;可选权益车票

fix

fix 按最小过期时间倒序

fix 折线图

fix 返回折线图最大最小值

fix

fix

add 后台权限

fix

fix

fix order字段

fix

fix 映射路径

fix

fix 放开新版登录接口权限

fix 表名

fix

fix

fix 接口权限

fix 订单发货物流

fix 去掉条件

fix

fix 固定推广者套餐分销比例

fix 手机号返回

fix 日志

fix 统计appleOne退款;注解验权

fix 代理

fix

fix 排序

fix 修改平台分销去除实物限制

fix 实物分销

fix

fix 字段统一

fix 微信退款扣除购买实物权益

fix 实物分销权益json格式

fix 账号今日全部到期;需要修改密码平台展示

add 数据统计导出接口

fix 权益领取

fix

fix 分销

fix 退款扣除权益加减去3天

fix

add 批量导入账号

fix 实物退款统计数据

fix 按时间查询

fix 获取全部已过期车票的账号列表

fix

fix

zoujiajian 3 gadi atpakaļ
vecāks
revīzija
0296c9695c
100 mainītis faili ar 3808 papildinājumiem un 278 dzēšanām
  1. 38 0
      netflix-common/src/main/java/com/cyksj/common/annotation/Log.java
  2. 10 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  3. 19 0
      netflix-common/src/main/java/com/cyksj/enums/BusinessStatus.java
  4. 39 0
      netflix-common/src/main/java/com/cyksj/enums/BusinessType.java
  5. 5 2
      netflix-dao/src/main/java/com/cyksj/mapper/AccountMapper.java
  6. 6 0
      netflix-dao/src/main/java/com/cyksj/mapper/GroupsRelationMapper.java
  7. 5 0
      netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java
  8. 30 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/cms/CmsMenuMapper.java
  9. 24 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/cms/CmsRoleMapper.java
  10. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/cms/CmsRoleMenuMapper.java
  11. 15 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/cms/CmsUserMapper.java
  12. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/cms/CmsUserRoleMapper.java
  13. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/cms/SysLogMapper.java
  14. 21 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/statistics/StatisticsUserDataMapper.java
  15. 4 0
      netflix-dao/src/main/java/com/cyksj/model/entity/Account.java
  16. 33 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CmsMenu.java
  17. 18 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CmsRole.java
  18. 22 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CmsRoleMenu.java
  19. 49 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CmsUser.java
  20. 22 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CmsUserRole.java
  21. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDon.java
  22. 2 0
      netflix-dao/src/main/java/com/cyksj/model/entity/StatisticsFashionGoodsData.java
  23. 84 0
      netflix-dao/src/main/java/com/cyksj/model/entity/SysLog.java
  24. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserPayEquipmentAvailableBenefits.java
  25. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserPlatDistributeRate.java
  26. 25 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserTicketClearedRecord.java
  27. 27 0
      netflix-dao/src/main/java/com/cyksj/model/excel/ExcelImportAccountData.java
  28. 166 0
      netflix-dao/src/main/java/com/cyksj/model/excel/ExcelRealGoodsOrderData.java
  29. 77 0
      netflix-dao/src/main/java/com/cyksj/model/excel/statistics/ExcelAppleOneData.java
  30. 32 0
      netflix-dao/src/main/java/com/cyksj/model/excel/statistics/ExcelFashionData.java
  31. 35 0
      netflix-dao/src/main/java/com/cyksj/model/excel/statistics/ExcelRealGoodsData.java
  32. 29 0
      netflix-dao/src/main/java/com/cyksj/model/excel/statistics/ExcelRegisterAccountData.java
  33. 77 0
      netflix-dao/src/main/java/com/cyksj/model/excel/statistics/ExcelStreamingAccountData.java
  34. 15 0
      netflix-dao/src/main/java/com/cyksj/model/manage/dto/AdminInfo.java
  35. 10 0
      netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSkuInsert.java
  36. 5 0
      netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSpuInsert.java
  37. 15 1
      netflix-dao/src/main/java/com/cyksj/model/manage/views/AccountView.java
  38. 6 3
      netflix-dao/src/main/java/com/cyksj/model/manage/views/GoodsDonViewer.java
  39. 9 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonView.java
  40. 34 0
      netflix-dao/src/main/java/com/cyksj/model/request/CmsRoleReq.java
  41. 42 0
      netflix-dao/src/main/java/com/cyksj/model/request/CmsUserReq.java
  42. 5 0
      netflix-dao/src/main/java/com/cyksj/model/request/ReceiveBenefitsReq.java
  43. 5 0
      netflix-dao/src/main/java/com/cyksj/model/views/BackgroundDataView.java
  44. 36 0
      netflix-dao/src/main/java/com/cyksj/model/views/BrokenLineObjView.java
  45. 23 0
      netflix-dao/src/main/java/com/cyksj/model/views/CmsMenuVO.java
  46. 80 0
      netflix-dao/src/main/java/com/cyksj/model/views/CmsUserVO.java
  47. 7 2
      netflix-dao/src/main/java/com/cyksj/model/views/ExpiredAccountDataView.java
  48. 40 0
      netflix-dao/src/main/java/com/cyksj/model/views/PersonDistributeBrokenLineView.java
  49. 42 0
      netflix-dao/src/main/java/com/cyksj/model/views/PlatOrderDonBrokenLineView.java
  50. 54 0
      netflix-dao/src/main/java/com/cyksj/model/views/UserAvailableGoodsTicketView.java
  51. 5 0
      netflix-dao/src/main/java/com/cyksj/model/views/UserDistributeView.java
  52. 74 0
      netflix-dao/src/main/java/com/cyksj/model/views/UserTicketClearedRecordView.java
  53. 36 1
      netflix-dao/src/main/resources/mapper/AccountMapper.xml
  54. 87 0
      netflix-dao/src/main/resources/mapper/CmsMenuMapper.xml
  55. 40 0
      netflix-dao/src/main/resources/mapper/CmsRoleMapper.xml
  56. 15 0
      netflix-dao/src/main/resources/mapper/CmsUserMapper.xml
  57. 29 0
      netflix-dao/src/main/resources/mapper/GroupRelationMapper.xml
  58. 36 0
      netflix-dao/src/main/resources/mapper/OrderDonMapper.xml
  59. 48 0
      netflix-dao/src/main/resources/mapper/StatisticsUserDataMapper.xml
  60. 3 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  61. 0 9
      netflix-service/src/main/java/com/cyksj/service/distribute/equipment/impl/EquipmentDistributeServiceImpl.java
  62. 2 2
      netflix-service/src/main/java/com/cyksj/service/distribute/impl/DistributeServiceImpl.java
  63. 23 15
      netflix-service/src/main/java/com/cyksj/service/exchange/impl/ExchangeCodeServiceImpl.java
  64. 8 2
      netflix-service/src/main/java/com/cyksj/service/mange/CmsAccountService.java
  65. 9 4
      netflix-service/src/main/java/com/cyksj/service/mange/account/CmsAccountServiceImpl.java
  66. 123 0
      netflix-service/src/main/java/com/cyksj/service/mange/cms/CmsUserManager.java
  67. 34 0
      netflix-service/src/main/java/com/cyksj/service/mange/cms/service/CacheService.java
  68. 121 0
      netflix-service/src/main/java/com/cyksj/service/mange/cms/service/impl/CacheServiceImpl.java
  69. 26 5
      netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java
  70. 15 5
      netflix-service/src/main/java/com/cyksj/service/mange/statistics/StatisticsDataService.java
  71. 260 58
      netflix-service/src/main/java/com/cyksj/service/mange/statistics/impl/StatisticsDataServiceImpl.java
  72. 15 1
      netflix-service/src/main/java/com/cyksj/service/order/UserRealOrderBenefitsService.java
  73. 55 45
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  74. 124 38
      netflix-service/src/main/java/com/cyksj/service/order/impl/UserRealOrderBenefitsImpl.java
  75. 3 0
      netflix-service/src/main/java/com/cyksj/service/relation/GroupRelationFrontService.java
  76. 2 0
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationClearServiceImpl.java
  77. 21 0
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java
  78. 1 1
      netflix-service/src/main/java/com/cyksj/service/template/TemplateCommonService.java
  79. 5 4
      netflix-service/src/main/java/com/cyksj/service/template/impl/TemplateCommonServiceImpl.java
  80. 26 22
      netflix-service/src/main/java/com/cyksj/task/StatisticsDataScheduler.java
  81. 207 0
      netflix-web/src/main/java/com/cyksj/aspect/LogAspect.java
  82. 40 35
      netflix-web/src/main/java/com/cyksj/config/SaTokenConfigure.java
  83. 10 0
      netflix-web/src/main/java/com/cyksj/web/GlobalExceptionHandler.java
  84. 28 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java
  85. 2 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsUserController.java
  86. 159 5
      netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java
  87. 2 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/channel/CmsChannelController.java
  88. 2 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/channel/CmsChannelPopularizeController.java
  89. 274 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/cms/CmsAdminUserController.java
  90. 123 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/cms/CmsMenuController.java
  91. 142 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/cms/CmsRoleController.java
  92. 35 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/cms/CmsSysController.java
  93. 34 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/cms/interceptor/StpInterfaceImpl.java
  94. 7 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/coupon/CouponController.java
  95. 33 5
      netflix-web/src/main/java/com/cyksj/web/controller/manage/distribute/DistributeController.java
  96. 11 2
      netflix-web/src/main/java/com/cyksj/web/controller/manage/exchange/ExchangeCodeController.java
  97. 34 3
      netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonController.java
  98. 6 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonSkuController.java
  99. 9 3
      netflix-web/src/main/java/com/cyksj/web/controller/manage/group/CmsGroupController.java
  100. 8 4
      netflix-web/src/main/java/com/cyksj/web/controller/manage/group/CmsHomeGroupController.java

+ 38 - 0
netflix-common/src/main/java/com/cyksj/common/annotation/Log.java

@@ -0,0 +1,38 @@
+package com.cyksj.common.annotation;
+
+
+import com.cyksj.enums.BusinessType;
+
+import java.lang.annotation.*;
+
+/*
+ *项目名: yicang-admin
+ *文件名: Log
+ *创建者: JavaZou
+ *创建时间:2022/9/30 10:47
+ */
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Log {
+	/**
+	 * 模块
+	 */
+	String module() default "";
+
+	/**
+	 * 功能
+	 */
+	BusinessType businessType() default BusinessType.OTHER;
+
+	/**
+	 * 是否保存请求的参数
+	 */
+	boolean isSaveRequestData() default false;
+
+	/**
+	 * 是否保存响应的参数
+	 */
+	boolean isSaveResponseData() default false;
+
+}

+ 10 - 0
netflix-common/src/main/java/com/cyksj/common/constant/Constant.java

@@ -57,4 +57,14 @@ public interface Constant {
 	 * 实物分销配置
 	 */
 	String EQUIPMENT_DISTRIBUTE_KEY = "equipment_distribute_key";
+
+	String INITIAL_PASSWORD ="qwer1234";
+
+	List<String> serviceKeys = List.of("service_img_set", "service_name_set");
+
+	List<Long> dsGoodsIds = List.of(1l, 2l);
+
+	List<String> payType = List.of("月", "季", "年");
+
+	List<String> registerAccount = List.of("apple", "spotify", "google");
 }

+ 19 - 0
netflix-common/src/main/java/com/cyksj/enums/BusinessStatus.java

@@ -0,0 +1,19 @@
+package com.cyksj.enums;
+
+/*
+ *项目名: yicang-admin
+ *文件名: BusinessStatus
+ *创建者: JavaZou
+ *创建时间:2022/9/30 11:03
+ */
+public enum BusinessStatus {
+	/**
+	 * 成功
+	 */
+	SUCCESS,
+
+	/**
+	 * 失败
+	 */
+	FAIL,
+}

+ 39 - 0
netflix-common/src/main/java/com/cyksj/enums/BusinessType.java

@@ -0,0 +1,39 @@
+package com.cyksj.enums;
+
+/*
+ *项目名: yicang-admin
+ *文件名: BusinessType
+ *创建者: JavaZou
+ *创建时间:2022/9/30 10:51
+ */
+public enum BusinessType {
+	/**
+	 * 其它
+	 */
+	OTHER,
+
+	/**
+	 * 新增
+	 */
+	POST,
+
+	/**
+	 * 修改
+	 */
+	PUT,
+
+	/**
+	 * 删除
+	 */
+	DELETE,
+
+	/**
+	 * 导出
+	 */
+	EXPORT,
+
+	/**
+	 * 导入
+	 */
+	IMPORT,
+}

+ 5 - 2
netflix-dao/src/main/java/com/cyksj/mapper/AccountMapper.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.cyksj.model.entity.Account;
 import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.excel.ExcelAccountData;
+import com.cyksj.model.manage.views.AccountView;
 import com.cyksj.model.views.ExpiredAccountDataView;
 import org.apache.ibatis.annotations.Param;
 
@@ -18,11 +19,13 @@ import java.util.List;
  */
 public interface AccountMapper extends BaseMapper<Account> {
 
-	IPage<ExpiredAccountDataView> getExpiredAccountView(@Param("isCorpWx") Boolean isCorpWx, @Param("customerService") String customerService, @Param("goodsId") Integer goodsId, @Param("account") String account, @Param("renewStatus") Boolean renewStatus, @Param("handleStatus") Boolean handleStatus, @Param("cnAccount") String cnAccount, @Param("usAccount") String usAccount, @Param("userId") Integer userId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("now") String now, @Param("page") Page page);
+	IPage<ExpiredAccountDataView> getExpiredAccountView(@Param("isCorpWx") Boolean isCorpWx, @Param("customerService") String customerService, @Param("goodsId") Long goodsId, @Param("skuId") Long skuId, @Param("account") String account, @Param("renewStatus") Boolean renewStatus, @Param("handleStatus") Boolean handleStatus, @Param("cnAccount") String cnAccount, @Param("usAccount") String usAccount, @Param("userId") Integer userId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("now") String now, @Param("page") Page page);
 
 	List<Account> getNoAppleOneAccount(String appleOne);
 
 	List<OrderDon> getNoAppleOneOrderDon(@Param("skuIds") List<Long> skuIds, @Param("yesZeroDate") Date yesZeroDate, @Param("thisZeroDate") Date thisZeroDate, @Param("noOrderStatus") List<String> noOrderStatus);
 
-	List<ExcelAccountData> getExpiredAccountViewNoPage(@Param("isCorpWx") Boolean isCorpWx, @Param("customerService") String customerService, @Param("goodsId") Integer goodsId, @Param("account") String account, @Param("renewStatus") Boolean renewStatus, @Param("handleStatus") Boolean handleStatus, @Param("cnAccount") String cnAccount, @Param("usAccount") String usAccount, @Param("userId") Integer userId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("now") String now);
+	List<ExcelAccountData> getExpiredAccountViewNoPage(@Param("isCorpWx") Boolean isCorpWx, @Param("customerService") String customerService, @Param("goodsId") Long goodsId, @Param("skuId") Long skuId, @Param("account") String account, @Param("renewStatus") Boolean renewStatus, @Param("handleStatus") Boolean handleStatus, @Param("cnAccount") String cnAccount, @Param("usAccount") String usAccount, @Param("userId") Integer userId, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("now") String now);
+
+	List<AccountView> getExpiredAllAccount();
 }

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GroupsRelationMapper.java

@@ -1,7 +1,9 @@
 package com.cyksj.mapper;
 
+import cn.hutool.core.date.DateTime;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.cyksj.model.entity.GroupsRelation;
+import com.cyksj.model.manage.views.GroupsRelationView;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Update;
 
@@ -22,4 +24,8 @@ public interface GroupsRelationMapper extends BaseMapper<GroupsRelation> {
 
 	@Update("update groups_relation set customer_service = null where id = #{id}")
 	void updateCustomerService(Long id);
+
+	Long selectSimilarExpiredRelation(@Param("skuId") Long skuId, @Param("minExpiryTime") DateTime minExpiryTime);
+
+	List<GroupsRelationView> selectRelationByGoodsId(@Param("goodsId") Long goodsId, @Param("userId") Long userId);
 }

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java

@@ -5,6 +5,7 @@ import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.entity.RealGoodsInterestUser;
 import com.cyksj.model.excel.ExcelOrderDonInfo;
 import com.cyksj.model.manage.views.OrderDonView;
+import com.cyksj.model.views.BrokenLineObjView;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.Date;
@@ -28,4 +29,8 @@ public interface OrderDonMapper extends BaseMapper<OrderDon> {
 	void updateHasPaymentInterestRealGoodsPayTime();
 
 	OrderDonView getOrderDetail(Long orderId);
+
+	BrokenLineObjView selectPlatBrokenLineMoney(@Param("first") String first, @Param("end") String end);
+
+	BrokenLineObjView selectPersonDistributeBrokenLine(@Param("userId") Long userId, @Param("first") String first, @Param("end") String end);
 }

+ 30 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/cms/CmsMenuMapper.java

@@ -0,0 +1,30 @@
+package com.cyksj.mapper.manage.cms;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CmsMenu;
+import com.cyksj.model.entity.CmsUser;
+import com.cyksj.model.views.CmsMenuVO;
+
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: CmsMenuMapper
+ *创建者: JavaZou
+ *创建时间:2023/1/11 15:11
+ */
+public interface CmsMenuMapper extends BaseMapper<CmsMenu> {
+	List<CmsMenu> getCmsMenusByUserId(Long userId);
+
+	List<CmsUser> getAllCmsUserByMenuId(Long menuId);
+
+	void deleteMenuAndChild(Long id);
+
+	List<CmsMenuVO> getALlMenu();
+
+	List<CmsMenuVO> getCmsMenusList();
+
+	List<CmsMenuVO> getSelfCmsMenusList(Long adminId);
+
+	List<CmsMenu> getCmsMenusByAccount(Long account);
+}

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/cms/CmsRoleMapper.java

@@ -0,0 +1,24 @@
+package com.cyksj.mapper.manage.cms;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CmsRole;
+import com.cyksj.model.entity.CmsUser;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: CmsRoleMapper
+ *创建者: JavaZou
+ *创建时间:2023/1/11 15:11
+ */
+public interface CmsRoleMapper extends BaseMapper<CmsRole> {
+	List<CmsRole> getCmsRolesByUserId(Long userId);
+
+	List<CmsUser> getAllCmsUserByRoleId(Long roleId);
+
+	List<String> getAllMenusByRoleIds(@Param("list") String[] roleIds);
+
+	List<CmsRole> getCmsRolesByAccount(Long account);
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/cms/CmsRoleMenuMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.manage.cms;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CmsRoleMenu;
+
+/*
+ *项目名: netflix
+ *文件名: CmsRoleMenuMapper
+ *创建者: JavaZou
+ *创建时间:2023/3/9 11:49
+ */
+public interface CmsRoleMenuMapper extends BaseMapper<CmsRoleMenu> {
+}

+ 15 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/cms/CmsUserMapper.java

@@ -0,0 +1,15 @@
+package com.cyksj.mapper.manage.cms;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CmsUser;
+import com.cyksj.model.views.CmsUserVO;
+
+/*
+ *项目名: netflix
+ *文件名: CmsUserMapper
+ *创建者: JavaZou
+ *创建时间:2023/1/11 15:10
+ */
+public interface CmsUserMapper extends BaseMapper<CmsUser> {
+	CmsUserVO getCmsUserDetailByUserId(Long userId);
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/cms/CmsUserRoleMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.manage.cms;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CmsUserRole;
+
+/*
+ *项目名: netflix
+ *文件名: CmsUserRoleMapper
+ *创建者: JavaZou
+ *创建时间:2023/3/9 13:45
+ */
+public interface CmsUserRoleMapper extends BaseMapper<CmsUserRole> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/cms/SysLogMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.manage.cms;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.SysLog;
+
+/*
+ *项目名: netflix
+ *文件名: SysLogMapper
+ *创建者: JavaZou
+ *创建时间:2023/3/9 13:37
+ */
+public interface SysLogMapper extends BaseMapper<SysLog> {
+}

+ 21 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/statistics/StatisticsUserDataMapper.java

@@ -1,11 +1,15 @@
 package com.cyksj.mapper.manage.statistics;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.RegisterOrderDon;
 import com.cyksj.model.entity.StatisticsUserData;
+import com.cyksj.model.excel.statistics.ExcelRealGoodsData;
+import com.cyksj.model.excel.statistics.ExcelStreamingAccountData;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
 import java.util.Date;
+import java.util.List;
 
 /*
  *项目名: netflix
@@ -31,4 +35,21 @@ public interface StatisticsUserDataMapper extends BaseMapper<StatisticsUserData>
 
 	@Select("select count(*) from user_distribute_shared where created_time between #{yesZeroDate} and #{thisZeroDate}")
 	Integer getNumOfDistributeUserToday(@Param("yesZeroDate") Date yesZeroDate, @Param("thisZeroDate") Date thisZeroDate);
+
+	@Select("select goods_id from `streaming_account_data` sd where statistics_date between #{start} and #{end} group by goods_id")
+	List<Long> getAllStreaming(@Param("start") String start, @Param("end") String end);
+
+	ExcelStreamingAccountData getExportStreamingAccountData(@Param("goodsId") Long goodsId, @Param("isDis") Boolean isDis, @Param("isCode") Boolean isCode, @Param("start") String start, @Param("end") String end);
+
+	Integer getTypeData(@Param("goodsId") Long goodsId, @Param("type") String type, @Param("start") String start, @Param("end") String end);
+
+	@Select("select goods_id from `real_goods_data` sd where statistics_date between #{start} and #{end} group by goods_id")
+	List<Long> getAllRealGoods(@Param("start") String start, @Param("end") String end);
+
+	ExcelRealGoodsData getExportGoodsDonDataBySkuId(@Param("skuId") Long skuId, @Param("start") String start, @Param("end") String end);
+
+	List<RegisterOrderDon> getPlatformHasPaymentOrders(@Param("platform") String platform, @Param("start") String start, @Param("end") String end);
+
+	@Select("select goods_id from `statistics_fashion_goods_data` sd where statistics_date between #{start} and #{end} group by goods_id")
+	List<Long> getAllFashionGoods(@Param("start") String start, @Param("end") String end);
 }

+ 4 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/Account.java

@@ -1,5 +1,6 @@
 package com.cyksj.model.entity;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -22,6 +23,9 @@ public class Account extends BaseEntity {
 
     private Long goodsId;
 
+    @TableField(exist = false)
+    private Long skuId;
+
     private Date startTime;
 
     private Date expiryTime;

+ 33 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CmsMenu.java

@@ -0,0 +1,33 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotEmpty;
+
+/*
+ *项目名: netflix
+ *文件名: CmsMenu
+ *创建者: JavaZou
+ *创建时间:2023/1/11 15:06
+ */
+@Getter
+@Setter
+public class CmsMenu extends BaseEntity{
+	@NotEmpty
+	private String title;
+
+	@NotEmpty
+	private String menuName;
+
+	private String perms;
+
+	@NotEmpty
+	private String type;
+
+	private String path;
+
+	private Integer orderBy;
+
+	private Long parentId;
+}

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CmsRole.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: CmsRole
+ *创建者: JavaZou
+ *创建时间:2023/1/11 15:05
+ */
+@Getter
+@Setter
+public class CmsRole extends BaseEntity{
+	private String roleName;
+
+	private String remark;
+}

+ 22 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CmsRoleMenu.java

@@ -0,0 +1,22 @@
+package com.cyksj.model.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: CmsRoleMenu
+ *创建者: JavaZou
+ *创建时间:2023/1/11 15:08
+ */
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class CmsRoleMenu extends BaseEntity{
+	private Long roleId;
+
+	private Long menuId;
+}

+ 49 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CmsUser.java

@@ -0,0 +1,49 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+
+/*
+ *项目名: netflix
+ *文件名: CmsUser
+ *创建者: JavaZou
+ *创建时间:2023/1/11 14:27
+ */
+@Getter
+@Setter
+public class CmsUser extends BaseEntity{
+	/**
+	 * 管理员昵称
+	 */
+	@NotBlank(message = "请填写负责人姓名")
+	private String nickname;
+
+	/**
+	 * 管理帐户密码
+	 */
+	private String password;
+
+	/**
+	 * 手机号码
+	 */
+	@NotBlank(message = "手机号不能为空")
+	private String phone;
+
+	/**
+	 * 添加人
+	 */
+	private String addName;
+
+	/**
+	 * 修改人
+	 */
+	private String modifiedBy;
+
+
+	/**
+	 * 管理员是否允许登录
+	 */
+	private Boolean status;
+}

+ 22 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CmsUserRole.java

@@ -0,0 +1,22 @@
+package com.cyksj.model.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: CmsUserRole
+ *创建者: JavaZou
+ *创建时间:2023/1/11 15:08
+ */
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class CmsUserRole extends BaseEntity{
+	private Long userId;
+
+	private Long roleId;
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDon.java

@@ -79,6 +79,11 @@ public class GoodsDon extends BaseEntity {
      */
     private Integer rate;
 
+    /**
+     * 第二分销比例 不包含套餐
+     */
+    private Integer secondRate;
+
     /**
      * 排序
      */

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/StatisticsFashionGoodsData.java

@@ -1,6 +1,7 @@
 package com.cyksj.model.entity;
 
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.DbIgnore;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -52,6 +53,7 @@ public class StatisticsFashionGoodsData extends BaseEntity{
 	private BigDecimal money;
 
 	@TableField(exist = false)
+	@DbIgnore
 	private BigDecimal refundMoney;
 
 	private Date statisticsDate;

+ 84 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/SysLog.java

@@ -0,0 +1,84 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: yicang-admin
+ *文件名: SysLog
+ *创建者: JavaZou
+ *创建时间:2022/9/30 11:24
+ */
+@Getter
+@Setter
+public class SysLog extends BaseEntity {
+	/**
+	 * 操作人
+	 */
+	private String operator;
+
+	/**
+	 * 用户账号
+	 */
+	private String account;
+
+	/**
+	 * 操作模块
+	 */
+	private String module;
+
+	/**
+	 * 功能业务
+	 */
+	private Integer businessType;
+
+	/**
+	 * 方法名
+	 */
+	private String method;
+
+	/**
+	 * 请求方式
+	 */
+	private String requestMethod;
+
+	/**
+	 * 操作url
+	 */
+	private String operateUrl;
+
+	/**
+	 * 操作ip
+	 */
+	private String operateIp;
+
+	/**
+	 * 操作地点
+	 */
+	private String operateLocation;
+
+	/**
+	 * 请求参数
+	 */
+	private String operateParams;
+
+	/**
+	 * 返回参数
+	 */
+	private String jsonResult;
+
+	/**
+	 * 状态
+	 */
+	private Integer status;
+
+	/**
+	 * 错误信息
+	 */
+	private String errMsg;
+
+	/**
+	 * 操作时间
+	 */
+	private String operateTime;
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserPayEquipmentAvailableBenefits.java

@@ -24,4 +24,9 @@ public class UserPayEquipmentAvailableBenefits extends BaseEntity {
 	private Long realOrderId;
 
 	private Boolean deleted;
+
+	/**
+	 * 1成功领取,0否
+	 */
+	private Integer statusCode;
 }

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserPlatDistributeRate.java

@@ -23,5 +23,10 @@ public class UserPlatDistributeRate extends BaseEntity{
 	 * 分销比例
 	 */
 	private Integer rate;
+
+	/**
+	 * 第二分销比例 不包含套餐
+	 */
+	private Integer secondRate;
 }
 

+ 25 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserTicketClearedRecord.java

@@ -16,6 +16,15 @@ import java.util.Date;
 public class UserTicketClearedRecord extends BaseEntity{
 	private Long userId;
 
+	private Long accountId;
+
+	/**
+	 * 主账号
+	 */
+	private String account;
+
+	private Source source;
+
 	private Long goodsId;
 
 	private Long skuId;
@@ -25,4 +34,20 @@ public class UserTicketClearedRecord extends BaseEntity{
 	private Date startTime;
 
 	private Date expiryTime;
+
+	private Boolean deleted;
+
+	@Getter
+	public enum Source{
+		self("自购"),
+		distribute("分销权益"),
+		pay_equipment("购买实物权益"),
+		specific("抽奖"),
+		;
+		String desc;
+
+		Source(String desc) {
+			this.desc = desc;
+		}
+	}
 }

+ 27 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExcelImportAccountData.java

@@ -0,0 +1,27 @@
+package com.cyksj.model.excel;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: ExcelImportAccountData
+ *创建者: JavaZou
+ *创建时间:2023/3/15 14:19
+ */
+@Getter
+@Setter
+public class ExcelImportAccountData {
+	@ExcelProperty("账号")
+	private String account;
+
+	@ExcelProperty("密码")
+	private String password;
+
+	@ExcelProperty("首开时间")
+	private String startTime;
+
+	@ExcelProperty("到期时间")
+	private String expiryTime;
+}

+ 166 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExcelRealGoodsOrderData.java

@@ -0,0 +1,166 @@
+package com.cyksj.model.excel;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.cyksj.model.entity.OrderDon;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: ExcelRealGoodsOrderData
+ *创建者: JavaZou
+ *创建时间:2023/3/8 12:01
+ */
+@Getter
+@Setter
+@SearchBean(tables = "order_don o left join goods_don_sku sku on o.sku_id = sku.id " +
+		"left join goods_don g on g.id = sku.goods_id " +
+		"left join user u on o.user_id = u.id " +
+		"left join groups_relation gr on gr.id = o.relation_id " +
+		"left join channel_popularize cp on o.popularize_id = cp.id " +
+		"left join channel c on c.id = cp.channel_id " +
+		"left join order_don_transport odt on odt.order_id = o.id")
+public class ExcelRealGoodsOrderData {
+
+	@DbField("c.id")
+	@ExcelIgnore
+	private Long channelId;
+
+	@DbField("o.relation_id")
+	@ExcelIgnore
+	private Long relationId;
+
+	@DbField("gr.groups_id")
+	@ExcelIgnore
+	private Long groupsId;
+
+	@DbField("gr.account")
+	@ExcelIgnore
+	private String account;
+
+	@DbField("g.type")
+	@ExcelIgnore
+	private Integer goodsDonType;
+
+	@DbField("g.second_type")
+	@ExcelIgnore
+	private Integer secondType;
+
+	@DbField("o.order_no")
+	@ExcelIgnore
+	private String orderNo;
+
+	@DbField("o.transaction_id")
+	@ExcelIgnore
+	private String transactionId;
+
+	@DbField("g.title")
+	@ExcelIgnore
+	private String title;
+
+	@DbField("u.id")
+	@ExcelIgnore
+	private Long userId;
+
+	@DbField("case when u.login_phone != '' then 'phone' when u.email != '' then 'email' when u.open_id != '' then 'wechat' else 'wechat' end")
+	@ExcelIgnore
+	private String register;
+
+	@DbField("o.status")
+	@ExcelIgnore
+	private OrderDon.Status status;
+
+	@DbField("o.type")
+	@ExcelIgnore
+	private OrderDon.Type type;
+
+	@DbField("o.order_type")
+	@ExcelIgnore
+	private Integer orderType;
+
+	@DbField("o.num")
+	@ExcelIgnore
+	private Integer num;
+
+	@DbField("o.created_time")
+	@ExcelIgnore
+	private Date createdTime;
+
+	@DbField("o.ex_code")
+	@ExcelIgnore
+	private String exCode;
+
+	/**
+	 * 收货人
+	 */
+	@ExcelProperty("姓名")
+	@DbField("odt.receiver")
+	private String receiver;
+
+	/**
+	 * 手机号
+	 */
+	@ExcelProperty("手机号码")
+	@DbField("odt.phone")
+	private String phone;
+
+	@ExcelProperty("座机号")
+	private String landLine;
+
+	@ExcelProperty("公司名称")
+	private String company;
+
+	/**
+	 * 省份
+	 */
+	@ExcelProperty("省")
+	@DbField("odt.province")
+	private String province;
+
+	/**
+	 * 城市
+	 */
+	@ExcelProperty("市")
+	@DbField("odt.city")
+	private String city;
+
+	/**
+	 * 区/县
+	 */
+	@ExcelProperty("区")
+	@DbField("odt.district")
+	private String district;
+
+	/**
+	 * 详细地址
+	 */
+	@ExcelProperty("详细地址")
+	@DbField("odt.address")
+	private String address;
+
+	@ExcelProperty("付款方式")
+	private String payType;
+
+	@ExcelProperty("月结卡号")
+	private String monthCardNo;
+
+	@ExcelProperty("托寄物名称")
+	private String realGoodName;
+
+	@ExcelProperty("代收卡号(可选增加服务)")
+	private String toMoneyCardNumber;
+
+	@ExcelProperty("代收金额(可选增值服务)")
+	private String toMoney;
+
+	@ExcelProperty("收件统编")
+	private String deliveryNumber;
+
+	@ExcelProperty("备注")
+	private String remark;
+}

+ 77 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/statistics/ExcelAppleOneData.java

@@ -0,0 +1,77 @@
+package com.cyksj.model.excel.statistics;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: ExcelAppleOneData
+ *创建者: JavaZou
+ *创建时间:2023/3/14 9:48
+ */
+@Getter
+@Setter
+public class ExcelAppleOneData {
+	/**
+	 * 平台
+	 */
+	@ExcelProperty("区域")
+	private String area;
+
+	/**
+	 * 用户数
+	 */
+	@ExcelProperty("用户数")
+	private Integer numOfUser;
+
+	/**
+	 * 订单
+	 */
+	@ExcelProperty("订单数")
+	private Integer numOfOrder;
+
+	/**
+	 * 兑换订单
+	 */
+	@ExcelProperty("兑换订单数")
+	private Integer numOfExCodeOrder;
+
+	/**
+	 * 金额
+	 */
+	@ExcelProperty("金额")
+	private BigDecimal money;
+
+	/**
+	 * 月付单数
+	 */
+	@ExcelProperty("月付单数")
+	private Integer month;
+
+	/**
+	 * 季付单数
+	 */
+	@ExcelProperty("季付单数")
+	private Integer season;
+
+	/**
+	 * 年付单数
+	 */
+	@ExcelProperty("年付单数")
+	private Integer year;
+
+	/**
+	 * 分销单数
+	 */
+	@ExcelProperty("分销单数")
+	private Integer disOrder;
+
+	/**
+	 * 分销金额
+	 */
+	@ExcelProperty("分销金额")
+	private BigDecimal disMoney;
+}

+ 32 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/statistics/ExcelFashionData.java

@@ -0,0 +1,32 @@
+package com.cyksj.model.excel.statistics;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: ExcelFashionData
+ *创建者: JavaZou
+ *创建时间:2023/3/14 16:42
+ */
+@Getter
+@Setter
+public class ExcelFashionData {
+	@ExcelProperty("名称")
+	private String name;
+
+	@ExcelProperty("规格")
+	private String specVal;
+
+	@ExcelProperty("用户数")
+	private Integer numOfUser;
+
+	@ExcelProperty("订单数")
+	private Integer numOfOrder;
+
+	@ExcelProperty("金额")
+	private BigDecimal money;
+}

+ 35 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/statistics/ExcelRealGoodsData.java

@@ -0,0 +1,35 @@
+package com.cyksj.model.excel.statistics;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: ExcelRealGoodsData
+ *创建者: JavaZou
+ *创建时间:2023/3/14 9:49
+ */
+@Getter
+@Setter
+public class ExcelRealGoodsData {
+	/**
+	 * 设备名
+	 */
+	@ExcelProperty("设备名")
+	private String name;
+
+	@ExcelProperty("规格")
+	private String specVal;
+
+	@ExcelProperty("用户数")
+	private Integer numOfUser;
+
+	@ExcelProperty("订单数")
+	private Integer numOfOrder;
+
+	@ExcelProperty("金额")
+	private BigDecimal money;
+}

+ 29 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/statistics/ExcelRegisterAccountData.java

@@ -0,0 +1,29 @@
+package com.cyksj.model.excel.statistics;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: ExcelRegisterAccountData
+ *创建者: JavaZou
+ *创建时间:2023/3/14 9:50
+ */
+@Getter
+@Setter
+public class ExcelRegisterAccountData {
+	@ExcelProperty("平台")
+	private String platform;
+
+	@ExcelProperty("用户数")
+	private Integer numOfUser;
+
+	@ExcelProperty("订单数")
+	private Integer numOfOrder;
+
+	@ExcelProperty("金额")
+	private BigDecimal money;
+}

+ 77 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/statistics/ExcelStreamingAccountData.java

@@ -0,0 +1,77 @@
+package com.cyksj.model.excel.statistics;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: ExcelStreamingAccountData
+ *创建者: JavaZou
+ *创建时间:2023/3/14 9:49
+ */
+@Getter
+@Setter
+public class ExcelStreamingAccountData {
+	/**
+	 * 平台
+	 */
+	@ExcelProperty("name")
+	private String name;
+
+	/**
+	 * 用户数
+	 */
+	@ExcelProperty("用户数")
+	private Integer numOfUser;
+
+	/**
+	 * 订单
+	 */
+	@ExcelProperty("订单数")
+	private Integer numOfOrder;
+
+	/**
+	 * 兑换订单
+	 */
+	@ExcelProperty("兑换订单数")
+	private Integer numOfExCodeOrder;
+
+	/**
+	 * 金额
+	 */
+	@ExcelProperty("金额")
+	private BigDecimal money;
+
+	/**
+	 * 月付单数
+	 */
+	@ExcelProperty("月付单数")
+	private Integer month;
+
+	/**
+	 * 季付单数
+	 */
+	@ExcelProperty("季付单数")
+	private Integer season;
+
+	/**
+	 * 年付单数
+	 */
+	@ExcelProperty("年付单数")
+	private Integer year;
+
+	/**
+	 * 分销单数
+	 */
+	@ExcelProperty("分销单数")
+	private Integer disOrder;
+
+	/**
+	 * 分销金额
+	 */
+	@ExcelProperty("分销金额")
+	private BigDecimal disMoney;
+}

+ 15 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/dto/AdminInfo.java

@@ -1,5 +1,6 @@
 package com.cyksj.model.manage.dto;
 
+import com.cyksj.model.entity.CmsUser;
 import com.cyksj.model.manage.entity.Admin;
 import lombok.AllArgsConstructor;
 import lombok.Data;
@@ -7,6 +8,7 @@ import lombok.NoArgsConstructor;
 import lombok.experimental.Accessors;
 
 import java.io.Serializable;
+import java.util.Set;
 
 /**
  * @author chan
@@ -21,4 +23,17 @@ public class AdminInfo implements Serializable {
     private String token;
 
     private Admin info;
+
+    private CmsUser info2;
+
+
+    /**
+     * 权限列表
+     */
+    private Set<String> permissions;
+
+    /**
+     * 角色列表
+     */
+    private Set<String> roles;
 }

+ 10 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSkuInsert.java

@@ -68,6 +68,16 @@ public class ReqGoodsSkuInsert {
          */
         private Boolean status;
 
+        /**
+         * 是否开启实物车票时长权益
+         */
+        private Boolean isBenefits;
+
+        /**
+         * 权益列表
+         */
+        private String benefitsList;
+
     }
 
 }

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSpuInsert.java

@@ -80,6 +80,11 @@ public class ReqGoodsSpuInsert {
      */
     private Integer rate;
 
+    /**
+     * 第二分销比例 不包含套餐
+     */
+    private Integer secondRate;
+
     /**
      * 排序
      */

+ 15 - 1
netflix-dao/src/main/java/com/cyksj/model/manage/views/AccountView.java

@@ -17,7 +17,9 @@ import java.util.Date;
 @Setter
 @SearchBean(tables = "account a left join goods_don g on a.goods_id = g.id " +
         "left join groups_trips gt on gt.account_id = a.id " +
-        "left join goods_don_sku gdk on gdk.id = gt.sku_id")
+        "left join groups_relation gr on gr.groups_id = gt.id " +
+        "left join goods_don_sku gdk on gdk.id = gt.sku_id",
+        groupBy = "a.id,g.id,g.title,a.account,a.password,a.start_time,a.expiry_time,a.amount,a.cn_account,a.us_account,gt.id,a.remark,gdk.spec_val")
 public class AccountView {
 
     @DbField("a.id")
@@ -80,4 +82,16 @@ public class AccountView {
     @DbField("gdk.spec_val")
     private String specVal;
 
+    @DbField("select count(ur.id) from user_ticket_cleared_record ur where ur.account_id = a.id and deleted is true")
+    private Integer expiryCount;
+
+    @DbField("if((select s.account_id from (select s.account_id, count(*) num" +
+            " from (select ur.account_id, ur.relation_id" +
+            " from user_ticket_cleared_record ur where ur.deleted is true" +
+            " group by ur.account_id, ur.relation_id) s" +
+            "  group by s.account_id) s left join groups_trips gt on gt.account_id = s.account_id where s.account_id = a.id and s.num >= gt.num)is null,false,true)")
+    private Boolean expiredAll;
+
+    @DbField("max(gr.expiry_time)")
+    private Date lastTicketTime;
 }

+ 6 - 3
netflix-dao/src/main/java/com/cyksj/model/manage/views/GoodsDonViewer.java

@@ -118,12 +118,15 @@ public class GoodsDonViewer {
     @DbField("g.second_type")
     private Integer secondType;
 
-    /**
-     * banner
-     */
     @DbField("g.rate")
     private Integer rate;
 
+    /**
+     * 第二分销比例 不包含套餐
+     */
+    @DbField("g.second_rate")
+    private Integer secondRate;
+
     @DbField("g.sort_by")
     private Integer sortBy;
 

+ 9 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonView.java

@@ -100,6 +100,9 @@ public class OrderDonView {
     @DbField("o.money")
     private BigDecimal money;
 
+    @DbField("o.refund_money")
+    private BigDecimal refundMoney;
+
     @DbField("o.status")
     private OrderDon.Status status;
 
@@ -186,4 +189,10 @@ public class OrderDonView {
 
     @DbIgnore
     private String afterServiceName;
+
+    /**
+     * 是否可领取实物购买权益
+     */
+    @DbIgnore
+    private Boolean isHasBenefits;
 }

+ 34 - 0
netflix-dao/src/main/java/com/cyksj/model/request/CmsRoleReq.java

@@ -0,0 +1,34 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotEmpty;
+
+/*
+ *项目名: yicang-admin
+ *文件名: CmsRoleReq
+ *创建者: JavaZou
+ *创建时间:2022/9/30 16:15
+ */
+@Getter
+@Setter
+public class CmsRoleReq {
+	private Long id;
+	/**
+	 * 角色名
+	 */
+	@NotEmpty
+	private String roleName;
+
+	/**
+	 * 角色描述
+	 */
+	private String remark;
+
+	/**
+	 * 菜单列表
+	 */
+	@NotEmpty
+	private String menuIds;
+}

+ 42 - 0
netflix-dao/src/main/java/com/cyksj/model/request/CmsUserReq.java

@@ -0,0 +1,42 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+
+/*
+ *项目名: yicang-admin
+ *文件名: CmsUserReq
+ *创建者: JavaZou
+ *创建时间:2022/9/30 15:18
+ */
+@Getter
+@Setter
+public class CmsUserReq {
+	private Integer id;
+	/**
+	 * 登录账号
+	 */
+	private String account;
+
+	@NotBlank(message = "手机号不能为空")
+	private String phone;
+
+	/**
+	 * 用户成员名称
+	 */
+	@NotBlank(message = "请填写负责人姓名")
+	private String nickname;
+
+	/**
+	 * 登录密码
+	 */
+	private String password;
+
+	/**
+	 * 角色ids
+	 */
+	private String roleIds;
+
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/request/ReceiveBenefitsReq.java

@@ -14,6 +14,11 @@ import javax.validation.constraints.NotNull;
 @Getter
 @Setter
 public class ReceiveBenefitsReq {
+	/**
+	 * 可获取权益id
+	 */
+	private Long benefitsId;
+
 	@NotNull
 	private Long goodsId;
 

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/views/BackgroundDataView.java

@@ -178,4 +178,9 @@ public class BackgroundDataView {
 	 */
 	private Integer numOfMonthEmptyTripsNetflix;
 
+	/**
+	 * 待发货实物订单
+	 */
+	private Integer waitingSendRealOrder;
+
 }

+ 36 - 0
netflix-dao/src/main/java/com/cyksj/model/views/BrokenLineObjView.java

@@ -0,0 +1,36 @@
+package com.cyksj.model.views;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
+/*
+ *项目名: netflix
+ *文件名: BrokenLineObjView
+ *创建者: JavaZou
+ *创建时间:2023/3/9 11:02
+ */
+@Getter
+@Setter
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class BrokenLineObjView {
+	private Integer minOrdersCount;
+
+	private Integer maxOrdersCount;
+
+	private BigDecimal minMoney;
+
+	private BigDecimal maxMoney;
+
+	private String firstDate;
+
+	private String lastDate;
+
+	private Map<Long, List<PlatOrderDonBrokenLineView>> goodsData;
+
+	private Map<Long, List<PersonDistributeBrokenLineView>> distributeData;
+}

+ 23 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CmsMenuVO.java

@@ -0,0 +1,23 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.CmsMenu;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+
+/*
+ *项目名: yicang-admin
+ *文件名: CmsMenuVO
+ *创建者: JavaZou
+ *创建时间:2022/10/8 11:34
+ */
+@Getter
+@Setter
+public class CmsMenuVO extends CmsMenu {
+
+	private Boolean hasChildren;
+
+	private List<CmsMenuVO> child;
+}

+ 80 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CmsUserVO.java

@@ -0,0 +1,80 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+import java.util.Set;
+
+/*
+ *项目名: yicang-admin
+ *文件名: CmsUserVO
+ *创建者: JavaZou
+ *创建时间:2022/9/30 13:34
+ */
+@Getter
+@Setter
+@SearchBean(tables = " cms_user cu left join `cms_user_role` cur on cur.user_id = cu.id" +
+		" left join `cms_role` cr on cr.id = cur.role_id"
+		, groupBy = "cu.id, cu.nickname,cu.phone, cu.add_name, cu.modified_by, cu.status, cu.created_time,cu.update_time")
+public class CmsUserVO {
+	@DbField("cu.id")
+	private Long id;
+
+	/**
+	 * 用户名称
+	 */
+	@DbField("cu.nickname")
+	private String nickname;
+
+	@DbField("cu.phone")
+	private String phone;
+
+	/**
+	 * 角色名称
+	 */
+	@DbField("group_concat(cr.role_name)")
+	private String roleNames;
+
+	@DbField("group_concat(cr.id)")
+	private String roleIds;
+
+	@DbIgnore
+	private String token;
+
+	@DbField("cu.status")
+	private Boolean status;
+
+	/**
+	 * 添加人
+	 */
+	@DbField("cu.add_name")
+	private String addName;
+
+	/**
+	 * 修改人
+	 */
+	@DbField("cu.modified_by")
+	private String modifiedBy;
+
+	/**
+	 * 权限列表
+	 */
+	@DbIgnore
+	private Set<String> permissions;
+
+	/**
+	 * 角色列表
+	 */
+	@DbIgnore
+	private Set<String> roles;
+
+	@DbField("cu.created_time")
+	private Date createdTime;
+
+	@DbField("cu.update_time")
+	private Date updateTime;
+}

+ 7 - 2
netflix-dao/src/main/java/com/cyksj/model/views/ExpiredAccountDataView.java

@@ -37,7 +37,7 @@ public class ExpiredAccountDataView {
 	/**
 	 * 类型
 	 */
-	private String type;
+	private String specVal;
 
 	/**
 	 * 用户id
@@ -57,13 +57,18 @@ public class ExpiredAccountDataView {
 	/**
 	 * 用户昵称
 	 */
-	private String nickName;
+	private String nickname;
 
 	/**
 	 * 购买时间
 	 */
 	private Date payTime;
 
+	/**
+	 * 车票开始时间
+	 */
+	private Date startTime;
+
 	/**
 	 * 过期时间
 	 */

+ 40 - 0
netflix-dao/src/main/java/com/cyksj/model/views/PersonDistributeBrokenLineView.java

@@ -0,0 +1,40 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: PersonDistributeBrokenLineView
+ *创建者: JavaZou
+ *创建时间:2023/3/8 14:40
+ */
+@Getter
+@Setter
+@SearchBean(tables = "distribute_waiting_send_points dw left join order_don od on od.id = dw.order_id"
+		, where = ":userId: and od.is_distribute is true and dw.send_status not in ('not_exist','close')"
+		, groupBy = "od.goods_id,date_format(od.created_time,'%Y-%m-%d')")
+public class PersonDistributeBrokenLineView {
+	@DbField("od.goods_id")
+	private Long goodsId;
+
+	/**
+	 * 平台名称
+	 */
+	@DbField("select title from goods_don where id = od.goods_id")
+	private String goodsTitle;
+
+	/**
+	 * 当前日期订单数
+	 */
+	@DbField("count(od.id)")
+	private Integer orderNum;
+
+	/**
+	 * 日期
+	 */
+	@DbField("date_format(od.created_time,'%Y-%m-%d')")
+	private String date;
+}

+ 42 - 0
netflix-dao/src/main/java/com/cyksj/model/views/PlatOrderDonBrokenLineView.java

@@ -0,0 +1,42 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: PlatOrderDonBrokenLineView
+ *创建者: JavaZou
+ *创建时间:2023/3/8 15:22
+ */
+@Getter
+@Setter
+@SearchBean(tables = "order_don od",
+		where = "od.status not in ('noPayment','close','refund')"
+		, groupBy = "od.goods_id,date_format(od.created_time,'%Y-%m-%d')")
+public class PlatOrderDonBrokenLineView {
+	@DbField("od.goods_id")
+	private Long goodsId;
+
+	/**
+	 * 平台名称
+	 */
+	@DbField("select title from goods_don where id = od.goods_id")
+	private String goodsTitle;
+
+	/**
+	 * 当前日期订单数
+	 */
+	@DbField("cast(sum(od.money)/100 as decimal(10,2))")
+	private BigDecimal money;
+
+	/**
+	 * 日期
+	 */
+	@DbField("date_format(od.created_time,'%Y-%m-%d')")
+	private String date;
+}

+ 54 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserAvailableGoodsTicketView.java

@@ -0,0 +1,54 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.manage.views.GroupsRelationView;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: UserAvailableGoodsTicketView
+ *创建者: JavaZou
+ *创建时间:2023/3/8 17:02
+ */
+@Getter
+@Setter
+@SearchBean(tables = "user_pay_equipment_available_benefits ub left join goods_don_sku gdk on gdk.id = ub.sku_id" +
+		" left join goods_don g on g.id = gdk.goods_id")
+public class UserAvailableGoodsTicketView {
+	@DbField("ub.id")
+	private Long benefitsId;
+
+	@DbField("g.id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String goodsTile;
+
+	@DbField("ub.sku_id")
+	private Long skuId;
+
+	@DbField("ub.real_order_id")
+	private Long realOrderId;
+
+	@DbField("ub.user_id")
+	private Long userId;
+
+	@DbField("gdk.months")
+	private Integer months;
+
+	@DbField("gdk.spec_val")
+	private String specVal;
+
+	@DbField("ub.deleted")
+	@JsonIgnore
+	private Boolean deleted;
+
+	@DbIgnore
+	private List<GroupsRelationView> ticketList;
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserDistributeView.java

@@ -32,4 +32,9 @@ public class UserDistributeView {
 	@DbField("up.rate")
 	private Integer rate;
 
+	@DbField("gd.type")
+	private Integer type;
+
+	@DbField("gd.second_rate")
+	private Integer secondRate;
 }

+ 74 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserTicketClearedRecordView.java

@@ -0,0 +1,74 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.UserTicketClearedRecord;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: UserTicketClearedRecordView
+ *创建者: JavaZou
+ *创建时间:2023/3/7 17:09
+ */
+@Getter
+@Setter
+@SearchBean(tables = "user_ticket_cleared_record ur left join account a on a.id = ur.account_id" +
+		" left join goods_don g on g.id = ur.goods_id left join goods_don_sku gdk on gdk.id = ur.sku_id" +
+		" left join user u on u.id = ur.user_id left join corp_user cu on cu.unionid = u.unionid")
+public class UserTicketClearedRecordView {
+	@DbField("ur.id")
+	private Long recordId;
+
+	@DbField("ur.user_id")
+	private Long userId;
+
+	@DbField("ur.goods_id")
+	private Long goodsId;
+
+	@DbField("ur.sku_id")
+	private Long skuId;
+
+	@DbField("ur.relation_id")
+	private Long relationId;
+
+	@DbField("ur.account_id")
+	private Long accountId;
+
+	@DbField("ur.account")
+	private String account;
+
+	@DbField("a.password")
+	private String password;
+
+	@DbField("ur.source")
+	private UserTicketClearedRecord.Source source;
+
+	@DbField("ur.start_time")
+	private Date startTime;
+
+	@DbField("ur.expiry_time")
+	private Date expiryTime;
+
+	@DbField("ur.deleted")
+	private Boolean deleted;
+
+	@DbField("g.title")
+	private String platform;
+
+	@DbField("gdk.spec_val")
+	private String specVal;
+
+	@DbField("u.nickname")
+	private String nickname;
+
+	@DbField("u.headimgurl")
+	private String img;
+
+	@DbField("if(cu.id is null,false,true)")
+	private Boolean isCorpWx;
+}
+

+ 36 - 1
netflix-dao/src/main/resources/mapper/AccountMapper.xml

@@ -9,12 +9,13 @@
                a.password,
                a.us_account,
                a.cn_account,
-               concat(gdk.spec_val,'¥',cast(gdk.price/100 as decimal(10,2))) as 'type',
+               concat(gdk.spec_val,'¥',cast(gdk.price/100 as decimal(10,2))) as 'specVal',
                gr.user_id,
                gr.account as userAccount,
                u.headimgurl as img,
                u.nickname,
                gr.start_time as payTime,
+               gr.start_time,
                gr.expiry_time,
                gr.renew_status,
                gr.is_handle,
@@ -42,6 +43,9 @@
             <if test="goodsId != null">
                 and a.goods_id = #{goodsId}
             </if>
+            <if test="skuId != null">
+                and gdk.id = #{skuId}
+            </if>
             <if test="account != null and account != ''">
                 and a.account like '%${account}%'
             </if>
@@ -132,6 +136,9 @@
             <if test="goodsId != null">
                 and a.goods_id = #{goodsId}
             </if>
+            <if test="skuId != null">
+                and gdk.id = #{skuId}
+            </if>
             <if test="account != null and account != ''">
                 and a.account like '%${account}%'
             </if>
@@ -160,4 +167,32 @@
             order by expiry_time
         </where>
     </select>
+
+    <select id="getExpiredAllAccount" resultType="com.cyksj.model.manage.views.AccountView">
+        select a.id,
+               a.account,
+               a.password,
+               a.goods_id,
+               a.bank_card,
+               a.start_time,
+               a.expiry_time,
+               a.amount,
+               a.remark,
+               a.cn_account,
+               a.us_account,
+               us_account,
+               a.created_time,
+               a.update_time,
+               g.title
+        from (select s.account_id, count(*) num
+              from (select ur.account_id, ur.relation_id
+                    from user_ticket_cleared_record ur
+                    where ur.deleted is true
+                    group by ur.account_id, ur.relation_id) s
+              group by s.account_id) s
+                 left join account a on a.id = s.account_id
+                 left join groups_trips gt on gt.account_id = s.account_id
+                 left join goods_don g on g.id = a.goods_id
+        where s.num >= gt.num
+    </select>
 </mapper>

+ 87 - 0
netflix-dao/src/main/resources/mapper/CmsMenuMapper.xml

@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.cyksj.mapper.manage.cms.CmsMenuMapper">
+
+    <delete id="deleteMenuAndChild">
+        delete from `cms_menu` where id = #{id} or parent_id = #{id}
+    </delete>
+
+    <select id="getCmsMenusByUserId" resultType="com.cyksj.model.entity.CmsMenu">
+        select distinct m.id,
+                        m.title,
+                        m.menu_name,
+                        m.perms,
+                        m.type,
+                        m.order_by,
+                        m.parent_id
+        from `cms_menu` m
+                 inner join `cms_role_menu` um on m.id = um.menu_id
+                 inner join `cms_user_role` cur on cur.role_id = um.role_id
+                 inner join `cms_user` u on u.id = cur.user_id
+        where u.id = #{userId}
+    </select>
+
+    <select id="getAllCmsUserByMenuId" resultType="com.cyksj.model.entity.CmsUser">
+        select u.*
+        from `cms_user` u
+                 inner join `cms_user_role` cr on cr.user_id = u.id
+                 inner join `cms_role_menu` cmr on cmr.role_id = cr.role_id
+        where cmr.menu_id = #{menuId}
+    </select>
+
+    <select id="getALlMenu" resultType="com.cyksj.model.views.CmsMenuVO">
+        select *
+        from `cms_menu`
+        order by `order_by`
+    </select>
+
+    <select id="getCmsMenusList" resultType="com.cyksj.model.views.CmsMenuVO">
+        select id,
+               title,
+               menu_name,
+               perms,
+               `type`,
+               `order_by`,
+               `path`,
+               created_time,
+               update_time,
+               parent_id
+        from `cms_menu`
+        where `type` != 'button' and parent_id = 0 order by `order_by`
+    </select>
+
+    <select id="getSelfCmsMenusList" resultType="com.cyksj.model.views.CmsMenuVO">
+        select cm.id,
+               cm.title,
+               cm.menu_name,
+               cm.perms,
+               cm.type,
+               cm.order_by,
+               cm.path,
+               cm.created_time,
+               cm.update_time,
+               parent_id
+        from `cms_menu` cm
+                 inner join `cms_role_menu` crm
+                            on crm.menu_id = cm.id
+                 inner join `cms_user_role` cur on cur.role_id = crm.role_id
+                 inner join `cms_user` cu on cu.id = cur.user_id
+        where cu.id = #{adminId} and cm.type != 'button' order by `order_by`
+    </select>
+
+    <select id="getCmsMenusByAccount" resultType="com.cyksj.model.entity.CmsMenu">
+        select distinct m.id,
+                        m.title,
+                        m.menu_name,
+                        m.perms,
+                        m.type,
+                        m.order_by,
+                        m.parent_id
+        from `cms_menu` m
+                 inner join `cms_role_menu` um on m.id = um.menu_id
+                 inner join `cms_user_role` cur on cur.role_id = um.role_id
+                 inner join `cms_user` u on u.id = cur.user_id
+        where u.id = #{account}
+    </select>
+</mapper>

+ 40 - 0
netflix-dao/src/main/resources/mapper/CmsRoleMapper.xml

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.cyksj.mapper.manage.cms.CmsRoleMapper">
+
+    <select id="getCmsRolesByUserId" resultType="com.cyksj.model.entity.CmsRole">
+        select distinct r.id,
+                        r.role_name,
+                        r.remark
+        from `cms_role` r
+                 inner join `cms_user_role` ur on r.id = ur.role_id
+                 inner join `cms_user` u on u.id = ur.user_id
+        where u.id = #{userId}
+    </select>
+
+    <select id="getAllCmsUserByRoleId" resultType="com.cyksj.model.entity.CmsUser">
+        select u.*
+        from `cms_user` u
+                 inner join `cms_user_role` ur on ur.user_id = u.id
+        where ur.role_id = #{roleId}
+    </select>
+
+    <select id="getAllMenusByRoleIds" resultType="java.lang.String">
+        select distinct cm.id from `cms_menu` cm inner join `cms_role_menu` cmr on cm.id = cmr.menu_id
+        where cmr.role_id in
+        <foreach collection="list" item="item" separator="," open="(" close=")">
+            #{item}
+        </foreach>
+    </select>
+
+    <select id="getCmsRolesByAccount" resultType="com.cyksj.model.entity.CmsRole">
+        select distinct r.id,
+                        r.role_name,
+                        r.remark
+        from `cms_role` r
+                 inner join `cms_user_role` ur on r.id = ur.role_id
+                 inner join `cms_user` u on u.id = ur.user_id
+        where u.id = #{account}
+    </select>
+</mapper>

+ 15 - 0
netflix-dao/src/main/resources/mapper/CmsUserMapper.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.cyksj.mapper.manage.cms.CmsUserMapper">
+
+    <select id="getCmsUserDetailByUserId" resultType="com.cyksj.model.views.CmsUserVO">
+        select any_value(u.nickname),
+               group_concat(r.role_name)
+        from `cms_user` u
+                 inner join `cms_user_role` ur on u.id = ur.user_id
+                 inner join `cms_role` r on r.id = ur.role_id
+        where u.id = #{userId}
+        group by u.id
+    </select>
+</mapper>

+ 29 - 0
netflix-dao/src/main/resources/mapper/GroupRelationMapper.xml

@@ -35,4 +35,33 @@
     <select id="getGroupTripsSkuIdByRelationId" resultType="java.lang.Long">
         select gt.sku_id from `groups_trips` gt left join `groups_relation` gr on gr.groups_id = gt.id where gr.id = #{relationId} limit 1
     </select>
+
+    <select id="selectSimilarExpiredRelation" resultType="java.lang.Long">
+        select s.id
+        from (select gt.id, min(gr.expiry_time) minExpiryTime
+              from `groups_trips` gt
+                       left join `groups_relation` gr on gr.groups_id = gt.id
+              where gt.sku_id = #{skuId}
+                and gt.available_num > 0
+                and gt.status = 'validity'
+                and gr.status = 'validity'
+                and gr.user_id != 0
+              and gr.expiry_time is not null
+              group by gr.groups_id) s
+        where s.minExpiryTime >= #{minExpiryTime}
+        order by minExpiryTime desc limit 1
+    </select>
+
+    <select id="selectRelationByGoodsId" resultType="com.cyksj.model.manage.views.GroupsRelationView">
+        select gr.*
+        from groups_relation gr
+                 left join groups_trips gt on gr.groups_id = gt.id
+                 left join account a on a.id = gt.account_id
+                 left join user u on gr.user_id = u.id
+                 left join goods_don g on a.goods_id = g.id
+        where g.id = #{goodsId}
+          and gr.user_id = #{userId}
+          and gt.status = 'validity'
+          and gr.status = 'validity'
+    </select>
 </mapper>

+ 36 - 0
netflix-dao/src/main/resources/mapper/OrderDonMapper.xml

@@ -91,4 +91,40 @@
                  left join `goods_don` gd on gd.id = od.goods_id
         where od.id = #{orderId}
     </select>
+
+    <select id="selectPlatBrokenLineMoney" resultType="com.cyksj.model.views.BrokenLineObjView">
+        select min(curdate) as firstDate,
+               max(curdate) as lastDate
+        from (select cast(sum(od.money)/100 as decimal(10,2)) as curdateMoney,
+                     date_format(od.created_time,'%Y-%m-%d') curdate from order_don od
+        where od.status not in ('noPayment','close','refund')
+        group by od.goods_id,date_format(od.created_time,'%Y-%m-%d'))s
+        where 1 = 1
+        <if test="first != null">
+            and curdate >= #{first}
+        </if>
+        <if test="end != null">
+            and curdate &lt;= #{end}
+        </if>
+    </select>
+
+    <select id="selectPersonDistributeBrokenLine" resultType="com.cyksj.model.views.BrokenLineObjView">
+        select min(curdate) as firstDate,
+               max(curdate) as lastDate
+        from (select date_format(od.created_time,'%Y-%m-%d') curdate,
+                     count(od.id) curdateOrderCount
+        from distribute_waiting_send_points dw
+        left join order_don od on od.id = dw.order_id
+        where dw.shared_id = #{userId}
+          and od.is_distribute is true
+          and dw.send_status not in ('not_exist', 'close')
+        group by od.goods_id, date_format(od.created_time, '%Y-%m-%d'))s
+        where 1 = 1
+        <if test="first != null">
+            and curdate >= #{first}
+        </if>
+        <if test="end != null">
+            and curdate &lt;= #{end}
+        </if>
+    </select>
 </mapper>

+ 48 - 0
netflix-dao/src/main/resources/mapper/StatisticsUserDataMapper.xml

@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.cyksj.mapper.manage.statistics.StatisticsUserDataMapper">
+
+    <select id="getExportStreamingAccountData"
+            resultType="com.cyksj.model.excel.statistics.ExcelStreamingAccountData">
+        select count(distinct user_id) as numOfUser, count(*) as numOfOrder,ifnull(sum(money)/100,0) as money from
+        `order_don`
+        where sku_id in (select id from `goods_don_sku` where goods_id = #{goodsId})
+        and status not in ('close','noPayment','refund')
+        <if test="isDis!=null and isDis">
+            and is_distribute = 1
+        </if>
+        <if test="isCode!=null and isCode">
+            and `type` = 'EX_CODE'
+        </if>
+        and created_time between #{start} and #{end}
+    </select>
+
+    <select id="getTypeData" resultType="java.lang.Integer">
+        select count(*) as numOfOrder from `order_don` od where
+        sku_id in (select id from `goods_don_sku` where goods_id = #{goodsId} and spec_val like '%${type}%%'
+        <if test="type =='月'.toString()">
+            and spec_val not like '%年%'
+        </if>)
+        and status not in ('close','noPayment','refund')
+        and created_time between #{start} and #{end}
+    </select>
+
+    <select id="getExportRealData" resultType="com.cyksj.model.excel.statistics.ExcelRealGoodsData">
+        select count(distinct user_id) as numOfUser, count(*) as numOfOrder, ifnull(sum(money) / 100, 0) as money
+        from `order_don`
+        where sku_id = #{skuId}
+          and status not in ('close', 'noPayment', 'refund')
+          and created_time between #{start} and #{end}
+    </select>
+
+    <select id="getPlatformHasPaymentOrders" resultType="com.cyksj.model.entity.RegisterOrderDon">
+        select id,
+               platform,
+               money,
+               user_id
+        from `register_order_don`
+        where platform = #{platform}
+          and created_time between #{start} and #{end}
+          and status not in ('close', 'noPayment', 'refund')
+    </select>
+</mapper>

+ 3 - 0
netflix-service/src/main/java/com/cyksj/redis/RedisService.java

@@ -596,6 +596,9 @@ public class RedisService {
         WX_GZH_QRCODE_LOGIN("wx_gzh_qrcode_login:%s", "微信公众号扫码登录key", 60),
         WX_GZH_QRCODE_SHARED_LOGIN("wx_gzh_qrcode_shared_login:%s", "微信公众号扫码分享邀请key", 60),
         EQUIPMENT_DISTRIBUTE_COUPON_KEY("equipment_distribute_coupon_key:%s", "实物设备分销新用户优惠券展示key", 60),
+        CMS_USER_KEY("cms:user:%s:", "user缓存前缀", 60 * 60 * 24L * 7),
+        CMS_USER_ROLE_KEY("cms:user:role:%s:", "user角色缓存前缀", 60 * 60 * 24L * 7),
+        CMS_USER_PERMISSION_KEY("cms:user:permission:%s:", "user权限缓存前缀", 60 * 60 * 24L * 7),
         ;
 
         private String name;

+ 0 - 9
netflix-service/src/main/java/com/cyksj/service/distribute/equipment/impl/EquipmentDistributeServiceImpl.java

@@ -200,15 +200,6 @@ public class EquipmentDistributeServiceImpl implements EquipmentDistributeServic
 				groupsRelationMapper.updateById(relation);
 			}
 		}
-		DateTime now = DateTime.now();
-		Date finalDate = DateUtil.offset(expiryTime, DateField.MONTH, -months);
-		if (now.isAfter(finalDate)) {
-			//过期 直接清除车票
-			groupRelationClearService.clearTicket(relation);
-		} else {
-			relation.setExpiryTime(finalDate);
-			groupsRelationMapper.updateById(relation);
-		}
 		Optional.ofNullable(receiveBenefitsRecord.getOrderId()).ifPresent(selfOrderId->{
 			orderDonMapper.update(null, Wrappers.lambdaUpdate(OrderDon.class).eq(OrderDon::getId, selfOrderId)
 					.set(OrderDon::getRefundMoney, BigDecimal.ZERO)

+ 2 - 2
netflix-service/src/main/java/com/cyksj/service/distribute/impl/DistributeServiceImpl.java

@@ -57,7 +57,7 @@ public class DistributeServiceImpl implements DistributeService {
 				throw new BusinessRuntimeException("比例错误");
 			}
 			GoodsDon goodsDon = goodsDonMapper.selectById(rate.getGoodsId());
-			if (goodsDon == null || !goodsDon.getDeleted() || goodsDon.getType() == 2) {
+			if (goodsDon == null || !goodsDon.getDeleted() || goodsDon.getType() == 3) {
 				throw new BusinessRuntimeException("平台错误");
 			}
 			rate.setDistributeId(userDistribute.getId());
@@ -79,7 +79,7 @@ public class DistributeServiceImpl implements DistributeService {
 				throw new BusinessRuntimeException("比例错误");
 			}
 			GoodsDon goodsDon = goodsDonMapper.selectById(rate.getGoodsId());
-			if (goodsDon == null || !goodsDon.getDeleted() || goodsDon.getType() == 2) {
+			if (goodsDon == null || !goodsDon.getDeleted() || goodsDon.getType() == 3) {
 				throw new BusinessRuntimeException("平台错误");
 			}
 			rate.setDistributeId(userDistribute.getId());

+ 23 - 15
netflix-service/src/main/java/com/cyksj/service/exchange/impl/ExchangeCodeServiceImpl.java

@@ -25,6 +25,7 @@ import com.cyksj.model.request.ExchangeCodeReq;
 import com.cyksj.model.request.ExchangeCodeTicket;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.exchange.ExchangeCodeService;
+import com.cyksj.service.relation.GroupRelationFrontService;
 import com.cyksj.service.template.TemplateCommonService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.util.MapUtils;
@@ -78,6 +79,8 @@ public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, Exc
 
 	private final BeanSearcher beanSearcher;
 
+	private final GroupRelationFrontService groupRelationFrontService;
+
 	@Override
 	@Transactional(rollbackFor = Throwable.class)
 	public List<ExcelExchangeCodeData> createExchangeCode(ExchangeCodeReq exchangeCodeReq) {
@@ -224,23 +227,27 @@ public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, Exc
 		if (user == null) {
 			throw BusinessRuntimeException.getInstance("用户不存在");
 		}
-		GroupsTrips groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class).eq(GroupsTrips::getSkuId, sku.getId()).gt(GroupsTrips::getAvailableNum, 0).last("limit 1").orderByAsc(GroupsTrips::getAvailableNum));
 		GroupsRelation relation = null;
-		if (groups == null) {
-			//新增车位 并关联
-			relation = createNewGroupTripsAndRelation(sku, groups, relation);
-		} else {
-			//寻找快满编车队进行占座
-			relation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
-					.eq(GroupsRelation::getGroupsId, groups.getId())
-					.eq(GroupsRelation::getStatus, "none")
-					.eq(GroupsRelation::getUserId, 0)
-					.orderByAsc(GroupsRelation::getNum)
-					.last("limit 1")
-			);
-			//如果占位失败 新增车位并关联
-			if (relation == null) {
+		//寻找差不多过期时间规格的车位
+		relation = groupRelationFrontService.getSimilarExpiredGroupRelation(sku.getId(), sku.getMonths());
+		if (relation == null) {
+			GroupsTrips groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class).eq(GroupsTrips::getSkuId, sku.getId()).gt(GroupsTrips::getAvailableNum, 0).last("limit 1").orderByAsc(GroupsTrips::getAvailableNum));
+			if (groups == null) {
+				//新增车位 并关联
 				relation = createNewGroupTripsAndRelation(sku, groups, relation);
+			} else {
+				//寻找快满编车队进行占座
+				relation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
+						.eq(GroupsRelation::getGroupsId, groups.getId())
+						.eq(GroupsRelation::getStatus, "none")
+						.eq(GroupsRelation::getUserId, 0)
+						.orderByAsc(GroupsRelation::getNum)
+						.last("limit 1")
+				);
+				//如果占位失败 新增车位并关联
+				if (relation == null) {
+					relation = createNewGroupTripsAndRelation(sku, groups, relation);
+				}
 			}
 		}
 
@@ -250,6 +257,7 @@ public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, Exc
 		} catch (Exception e) {
 			//失败重新给他分配车位
 			getGroupTripsTicket(sku, userId, exCodeOrderDon, orderDonTye);
+			redisService.del(RedisKey.GROUPS_RELATION_NUM_KEY + relation.getId());
 		}
 		relation.setUserId(userId);
 		relation.setStatus(GroupsRelation.Status.validity);

+ 8 - 2
netflix-service/src/main/java/com/cyksj/service/mange/CmsAccountService.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.cyksj.model.entity.Account;
 import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.excel.ExcelAccountData;
+import com.cyksj.model.manage.views.AccountView;
 import com.cyksj.model.views.ExpiredAccountDataView;
 
 import java.util.Date;
@@ -15,11 +16,16 @@ import java.util.List;
  * @date 2022/9/27 6:23 PM
  */
 public interface CmsAccountService extends IService<Account> {
-	IPage<ExpiredAccountDataView> getExpiredAccountView(Boolean isCorpWx, String customerService, Integer goodsId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, String startTime, String endTime, String now, Long offset, Long limit);
+	IPage<ExpiredAccountDataView> getExpiredAccountView(Boolean isCorpWx, String customerService, Long goodsId, Long skuId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, String startTime, String endTime, String now, Long offset, Long limit);
 
 	List<Account> getNoAppleOneAccount(String appleOne);
 
 	List<OrderDon> getNoAppleOneOrderDon(List<Long> skuIds, Date yesZeroDate, Date thisZeroDate, List<String> noOrderStatus);
 
-	List<ExcelAccountData> getExpiredAccountViewNoPage(Boolean isCorpWx, String customerService, Integer goodsId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, String startDate, String endDate, String toString);
+	List<ExcelAccountData> getExpiredAccountViewNoPage(Boolean isCorpWx, String customerService, Long goodsId, Long skuId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, String startDate, String endDate, String toString);
+
+	/**
+	 * 获取所有车票已过期的账号
+	 */
+	List<AccountView> getExpiredAllAccount();
 }

+ 9 - 4
netflix-service/src/main/java/com/cyksj/service/mange/account/CmsAccountServiceImpl.java

@@ -7,6 +7,7 @@ import com.cyksj.mapper.AccountMapper;
 import com.cyksj.model.entity.Account;
 import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.excel.ExcelAccountData;
+import com.cyksj.model.manage.views.AccountView;
 import com.cyksj.model.views.ExpiredAccountDataView;
 import com.cyksj.service.mange.CmsAccountService;
 import lombok.RequiredArgsConstructor;
@@ -27,13 +28,13 @@ public class CmsAccountServiceImpl extends ServiceImpl<AccountMapper, Account> i
 	private final AccountMapper accountMapper;
 
 	@Override
-	public IPage<ExpiredAccountDataView> getExpiredAccountView(Boolean isCorpWx, String customerService, Integer goodsId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, String startTime, String endTime, String now, Long offset, Long limit) {
-		return accountMapper.getExpiredAccountView(isCorpWx, customerService, goodsId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startTime, endTime, now, new Page<>(offset, limit));
+	public IPage<ExpiredAccountDataView> getExpiredAccountView(Boolean isCorpWx, String customerService, Long goodsId, Long skuId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, String startTime, String endTime, String now, Long offset, Long limit) {
+		return accountMapper.getExpiredAccountView(isCorpWx, customerService, goodsId, skuId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startTime, endTime, now, new Page<>(offset, limit));
 	}
 
 	@Override
-	public List<ExcelAccountData> getExpiredAccountViewNoPage(Boolean isCorpWx, String customerService, Integer goodsId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, String startTime, String endTime, String now) {
-		return accountMapper.getExpiredAccountViewNoPage(isCorpWx, customerService, goodsId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startTime, endTime, now);
+	public List<ExcelAccountData> getExpiredAccountViewNoPage(Boolean isCorpWx, String customerService, Long goodsId, Long skuId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, String startTime, String endTime, String now) {
+		return accountMapper.getExpiredAccountViewNoPage(isCorpWx, customerService, goodsId, skuId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startTime, endTime, now);
 	}
 
 	@Override
@@ -46,4 +47,8 @@ public class CmsAccountServiceImpl extends ServiceImpl<AccountMapper, Account> i
 		return accountMapper.getNoAppleOneOrderDon(skuIds, yesZeroDate, thisZeroDate, noOrderStatus);
 	}
 
+	@Override
+	public List<AccountView> getExpiredAllAccount() {
+		return accountMapper.getExpiredAllAccount();
+	}
 }

+ 123 - 0
netflix-service/src/main/java/com/cyksj/service/mange/cms/CmsUserManager.java

@@ -0,0 +1,123 @@
+package com.cyksj.service.mange.cms;
+
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.mapper.manage.cms.CmsMenuMapper;
+import com.cyksj.mapper.manage.cms.CmsRoleMapper;
+import com.cyksj.mapper.manage.cms.CmsUserMapper;
+import com.cyksj.mapper.manage.cms.CmsUserRoleMapper;
+import com.cyksj.model.entity.CmsMenu;
+import com.cyksj.model.entity.CmsRole;
+import com.cyksj.model.entity.CmsUser;
+import com.cyksj.model.entity.CmsUserRole;
+import com.cyksj.service.mange.cms.manager.service.CacheService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+/*
+ *项目名: yicang-admin
+ *文件名: CmsUserManager
+ *创建者: JavaZou
+ *创建时间:2022/9/30 13:59
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class CmsUserManager {
+	private final CacheService cacheService;
+
+	private final CmsUserMapper cmsUserMapper;
+
+	private final CmsRoleMapper cmsRoleMapper;
+
+	private final CmsMenuMapper cmsMenuMapper;
+
+	private final CmsUserRoleMapper cmsUserRoleMapper;
+
+	public CmsUser getUser(Long account) {
+		return selectCacheByTemplate(() -> cacheService.getUserCache(account), () -> cmsUserMapper.selectById(account));
+	}
+
+
+	public void loadUserRedisCache(CmsUser user) throws Exception {
+		cacheService.saveUser(user.getId());
+		// 缓存用户角色
+		cacheService.saveRoles(user.getId());
+		// 缓存用户权限
+		cacheService.savePermissions(user.getId());
+	}
+
+	public Set<String> getUserPermissions(Long account) {
+		List<CmsMenu> cmsMenus = selectCacheByTemplate(() -> cacheService.getUserPermsCache(account), () -> cmsMenuMapper.getCmsMenusByAccount(account));
+		if (cmsMenus == null) {
+			return null;
+		}
+		return cmsMenus.stream().map(CmsMenu::getPerms).collect(Collectors.toSet());
+	}
+
+	public Set<String> getUserRoles(Long adminId) {
+		List<CmsRole> cmsRoles = selectCacheByTemplate(
+				() -> cacheService.getUserRoleCache(adminId),
+				() -> cmsRoleMapper.getCmsRolesByAccount(adminId)
+		);
+		if (cmsRoles == null) {
+			return null;
+		}
+		return cmsRoles.stream().map(CmsRole::getRoleName).collect(Collectors.toSet());
+	}
+
+	/**
+	 * 缓存查询模板
+	 *
+	 * @param cacheSelector    查询缓存的方法
+	 * @param databaseSelector 数据库查询方法
+	 * @return T
+	 */
+	public static <T> T selectCacheByTemplate(Supplier<T> cacheSelector, Supplier<T> databaseSelector) {
+		try {
+			log.debug("查询redis ······");
+			// 先查 Redis缓存
+			T t = cacheSelector.get();
+			if (t == null) {
+				// 没有记录再查询数据库
+				return databaseSelector.get();
+			}
+			return t;
+		} catch (Exception e) {
+			// 缓存查询出错,则去数据库查询
+			log.error("redis查询 error:", e);
+			log.debug("查询数据库 ······");
+			return databaseSelector.get();
+		}
+	}
+
+	public void saveUserRoleRelation(Long userId, String roleIds) {
+		Arrays.stream(roleIds.split(",")).collect(Collectors.toSet()).forEach(roleId->{
+			cmsUserRoleMapper.insert(new CmsUserRole(userId, Long.valueOf(roleId)));
+		});
+	}
+
+	public void delUserRoleRelation(CmsUser cmsUser) throws Exception {
+		cmsUserRoleMapper.delete(Wrappers.lambdaQuery(CmsUserRole.class).eq(CmsUserRole::getUserId, cmsUser.getId()));
+		//删除用户缓存
+		cacheService.deleteUserCache(cmsUser.getId());
+		//删除角色缓存
+		cacheService.delUserRoleCache(cmsUser.getId());
+		//删除权限缓存
+		cacheService.delUserPermissionsCache(cmsUser.getId());
+	}
+
+	public void saveUserRoleRelationAndCache(CmsUser cmsUser, String roles) throws Exception {
+		//用户角色关联入库
+		this.saveUserRoleRelation(cmsUser.getId(), roles);
+		//缓存用户最数据
+		loadUserRedisCache(cmsUser);
+	}
+}

+ 34 - 0
netflix-service/src/main/java/com/cyksj/service/mange/cms/service/CacheService.java

@@ -0,0 +1,34 @@
+package com.cyksj.service.mange.cms.manager.service;
+
+
+import com.cyksj.model.entity.CmsMenu;
+import com.cyksj.model.entity.CmsRole;
+import com.cyksj.model.entity.CmsUser;
+
+import java.util.List;
+
+/*
+ *项目名: yicang-admin
+ *文件名: CacheService
+ *创建者: JavaZou
+ *创建时间:2022/9/30 14:08
+ */
+public interface CacheService {
+	void saveUser(Long userId) throws Exception;
+
+	void saveRoles(Long userId) throws Exception;
+
+	void savePermissions(Long userId) throws Exception;
+
+	void deleteUserCache(Long userId) throws Exception;
+
+	List<CmsRole> getUserRoleCache(Long userId);
+
+	List<CmsMenu> getUserPermsCache(Long userId);
+
+	CmsUser getUserCache(Long userId);
+
+	void delUserRoleCache(Long userId);
+
+	void delUserPermissionsCache(Long userId);
+}

+ 121 - 0
netflix-service/src/main/java/com/cyksj/service/mange/cms/service/impl/CacheServiceImpl.java

@@ -0,0 +1,121 @@
+package com.cyksj.service.mange.cms.manager.service.impl;
+
+
+import com.cyksj.mapper.manage.cms.CmsMenuMapper;
+import com.cyksj.mapper.manage.cms.CmsRoleMapper;
+import com.cyksj.mapper.manage.cms.CmsUserMapper;
+import com.cyksj.model.entity.CmsMenu;
+import com.cyksj.model.entity.CmsRole;
+import com.cyksj.model.entity.CmsUser;
+import com.cyksj.model.views.CmsUserVO;
+import com.cyksj.redis.RedisService;
+import com.cyksj.service.mange.cms.manager.service.CacheService;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/*
+ *项目名: yicang-admin
+ *文件名: CacheServiceImpl
+ *创建者: JavaZou
+ *创建时间:2022/9/30 14:11
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class CacheServiceImpl implements CacheService {
+	private final CmsUserMapper cmsUserMapper;
+
+	private final CmsRoleMapper cmsRoleMapper;
+
+	private final CmsMenuMapper cmsMenuMapper;
+
+	private final RedisService redisService;
+
+	private final ObjectMapper mapper;
+
+	@Override
+	public void saveUser(Long userId) throws Exception {
+		CmsUserVO cmsUserVO = cmsUserMapper.getCmsUserDetailByUserId(userId);
+		this.deleteUserCache(userId);
+		redisService.set(RedisService.key.CMS_USER_KEY.getNameFormat(userId), mapper.writeValueAsString(cmsUserVO));
+	}
+
+	@Override
+	public void saveRoles(Long userId) throws Exception {
+		List<CmsRole> roles = cmsRoleMapper.getCmsRolesByUserId(userId);
+		if (roles.size() > 0) {
+			this.deleteUserRolesCache(userId);
+			redisService.set(RedisService.key.CMS_USER_ROLE_KEY.getNameFormat(userId), mapper.writeValueAsString(roles));
+		}
+	}
+
+	@Override
+	public void savePermissions(Long userId) throws Exception {
+		List<CmsMenu> cmsMenus = cmsMenuMapper.getCmsMenusByUserId(userId);
+		if (cmsMenus.size() > 0) {
+			this.deleteUserPermissionsCache(userId);
+			redisService.set(RedisService.key.CMS_USER_PERMISSION_KEY.getNameFormat(userId), mapper.writeValueAsString(cmsMenus));
+		}
+	}
+
+	private void deleteUserRolesCache(Long userId) {
+		redisService.del(RedisService.key.CMS_USER_ROLE_KEY.getNameFormat(userId));
+	}
+
+	private void deleteUserPermissionsCache(Long userId) {
+		redisService.del(RedisService.key.CMS_USER_PERMISSION_KEY.getNameFormat(userId));
+	}
+
+	@Override
+	public void deleteUserCache(Long userId) {
+		redisService.del(RedisService.key.CMS_USER_KEY.getNameFormat(userId));
+	}
+
+	@SneakyThrows
+	@Override
+	public List<CmsRole> getUserRoleCache(Long userId){
+		Object cmsRoleStr = redisService.get(RedisService.key.CMS_USER_ROLE_KEY.getNameFormat(userId));
+		if (cmsRoleStr == null) {
+			return null;
+		}
+		JavaType type = mapper.getTypeFactory().constructParametricType(List.class, CmsRole.class);
+		return mapper.readValue(cmsRoleStr.toString(), type);
+	}
+
+	@SneakyThrows
+	@Override
+	public List<CmsMenu> getUserPermsCache(Long userId){
+		Object cmsMenusStr = redisService.get(RedisService.key.CMS_USER_PERMISSION_KEY.getNameFormat(userId));
+		if (cmsMenusStr == null) {
+			return null;
+		}
+		JavaType type = mapper.getTypeFactory().constructParametricType(List.class, CmsMenu.class);
+		return mapper.readValue(cmsMenusStr.toString(), type);
+	}
+
+	@SneakyThrows
+	@Override
+	public CmsUser getUserCache(Long userId) {
+		Object o = redisService.get(RedisService.key.CMS_USER_KEY.getNameFormat(userId));
+		if (o == null) {
+			return null;
+		}
+		return mapper.readValue(o.toString(), CmsUser.class);
+	}
+
+	@Override
+	public void delUserRoleCache(Long userId) {
+		redisService.del(RedisService.key.CMS_USER_ROLE_KEY.getNameFormat(userId));
+	}
+
+	@Override
+	public void delUserPermissionsCache(Long userId) {
+		redisService.del(RedisService.key.CMS_USER_PERMISSION_KEY.getNameFormat(userId));
+	}
+}

+ 26 - 5
netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java

@@ -1,20 +1,21 @@
 package com.cyksj.service.mange.impl;
 
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.mapper.GoodsDonSkuMapper;
 import com.cyksj.mapper.OrderDonMapper;
 import com.cyksj.mapper.OrderDonTransportMapper;
 import com.cyksj.mapper.OrderDonWaybillMapper;
 import com.cyksj.mapper.stock.GoodsSkuStockRelateMapper;
-import com.cyksj.model.entity.GoodsSkuStockRelate;
-import com.cyksj.model.entity.OrderDon;
-import com.cyksj.model.entity.OrderDonTransport;
-import com.cyksj.model.entity.OrderDonWaybill;
+import com.cyksj.model.entity.*;
 import com.cyksj.model.excel.ExcelOrderDonInfo;
 import com.cyksj.model.manage.request.ReqSetLogisticsPost;
 import com.cyksj.service.mange.CmsOrderDonService;
 import com.cyksj.service.mange.stock.GoodsDonStockService;
+import com.cyksj.service.order.UserRealOrderBenefitsService;
 import com.cyksj.service.template.TemplateCommonService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -43,6 +44,10 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
 
     private final TemplateCommonService templateCommonService;
 
+    private final GoodsDonSkuMapper goodsDonSkuMapper;
+
+    private final UserRealOrderBenefitsService userRealOrderBenefitsService;
+
     private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
 
     @Override
@@ -68,7 +73,23 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
             orderDonWaybillMapper.insert(orderDonWaybill);
             orderDon.setStatus(OrderDon.Status.transport);
             updateById(orderDon);
+            //发放实物购买权益
+            Boolean isReceivedAll = true;
+            GoodsDonSku sku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
+            if (sku != null) {
+                if (sku.getIsBenefits()) {
+                    if (StrUtil.isNotEmpty(sku.getBenefitsList())) {
+                        try {
+                            List<GoodsDonSku> goodsDonSkus = Jsons.parseList(sku.getBenefitsList(), GoodsDonSku.class);
+                            //自购实物 获取权益
+                            isReceivedAll = userRealOrderBenefitsService.getPayRealGoodsBenefits(orderDon.getUserId(), orderDon.getId(), goodsDonSkus);
+                        } catch (Exception e) {
 
+                        }
+                    }
+                }
+            }
+            final Boolean flag = isReceivedAll;
             //库存扣减逻辑
             List<GoodsSkuStockRelate> relateList = skuStockRelateMapper.selectList(Wrappers.lambdaQuery(GoodsSkuStockRelate.class).eq(GoodsSkuStockRelate::getSkuId,orderDon.getSkuId()));
             if(!relateList.isEmpty()){
@@ -81,7 +102,7 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
             TASK_POOL.execute(()->{
                 try {
                     log.info("发送发货通知至{}用户", orderDon.getUserId());
-                    templateCommonService.sendTransportMsgNotify(orderDon, reqSetLogisticsPost);
+                    templateCommonService.sendTransportMsgNotify(orderDon, reqSetLogisticsPost, flag);
                 } catch (Exception e) {
                     log.error("发送发货通知至{}用户失败:{}", orderDon.getUserId(), e);
                 }

+ 15 - 5
netflix-service/src/main/java/com/cyksj/service/mange/statistics/StatisticsDataService.java

@@ -3,9 +3,11 @@ package com.cyksj.service.mange.statistics;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.cyksj.dto.Result;
 import com.cyksj.model.excel.ExcelAccountData;
+import com.cyksj.model.excel.ExcelSheetAndData;
 import com.cyksj.model.views.BackgroundDataView;
 import com.cyksj.model.views.ExpiredAccountDataView;
 
+import java.util.Date;
 import java.util.List;
 
 /*
@@ -15,15 +17,23 @@ import java.util.List;
  *创建时间:2022/10/17 14:43
  */
 public interface StatisticsDataService {
-	Result<BackgroundDataView> getStatisticsByCondition(Integer type, Long startTime, Long endTime);
+	Result<BackgroundDataView> getStatisticsByCondition(Long startTime, Long endTime);
 
-	IPage<ExpiredAccountDataView> getExpiredAccountView(Boolean isCorpWx, String customerService, Integer goodsId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer uid, Long startTime, Long endTime, Long start, Long limit);
+	IPage<ExpiredAccountDataView> getExpiredAccountView(Boolean isCorpWx, String customerService, Long goodsId, Long skuId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer uid, Long startTime, Long endTime, Long start, Long limit);
 
-	Result<String> updateRenewStatus(Integer relationId);
+	Result<String> updateRenewStatus(Long relationId);
 
-	Result<String> updateHandleStatus(Integer relationId);
+	Result<String> updateHandleStatus(Long relationId);
 
-	List<ExcelAccountData> getExpiredAccountViewNoPage(Boolean isCorpWx, String customerService, Integer goodsId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, Long startTime, Long endTime);
+	List<ExcelAccountData> getExpiredAccountViewNoPage(Boolean isCorpWx, String customerService, Long goodsId, Long skuId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, Long startTime, Long endTime);
 
 	BackgroundDataView getTitleData();
+
+	//分销金额数据统计
+	void distribute(BackgroundDataView backgroundDataView, Date startDate, Date endDate);
+
+	/**
+	 * 数据导出
+	 */
+	List<ExcelSheetAndData> exportStatisticsDataByType(Integer type, Long startTime, Long endTime);
 }

+ 260 - 58
netflix-service/src/main/java/com/cyksj/service/mange/statistics/impl/StatisticsDataServiceImpl.java

@@ -8,16 +8,17 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
-import com.cyksj.mapper.GoodsDonMapper;
-import com.cyksj.mapper.GoodsDonSkuMapper;
-import com.cyksj.mapper.GroupsMapper;
-import com.cyksj.mapper.GroupsRelationMapper;
+import com.cyksj.mapper.*;
 import com.cyksj.mapper.manage.statistics.AppleOneDataMapper;
 import com.cyksj.mapper.manage.statistics.RealGoodsDataMapper;
+import com.cyksj.mapper.manage.statistics.StatisticsUserDataMapper;
 import com.cyksj.mapper.manage.statistics.StreamingAccountDataMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.excel.ExcelAccountData;
+import com.cyksj.model.excel.ExcelSheetAndData;
+import com.cyksj.model.excel.statistics.*;
 import com.cyksj.model.manage.views.GroupsRelationView;
+import com.cyksj.model.manage.views.OrderDonView;
 import com.cyksj.model.views.*;
 import com.cyksj.service.mange.CmsAccountService;
 import com.cyksj.service.mange.statistics.StatisticsDataService;
@@ -67,8 +68,12 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 
 	private final GroupsMapper groupsMapper;
 
+	private final OrderDonMapper orderDonMapper;
+
+	private final StatisticsUserDataMapper statisticsUserDataMapper;
+
 	@Override
-	public Result<BackgroundDataView> getStatisticsByCondition(Integer type, Long startTime, Long endTime) {
+	public Result<BackgroundDataView> getStatisticsByCondition(Long startTime, Long endTime) {
 		BackgroundDataView backgroundDataView = new BackgroundDataView();
 		Date startDate = null;
 		Date endDate = null;
@@ -80,24 +85,16 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 		}
 		//头部数据
 		headerData(backgroundDataView, startDate, endDate);
-		switch (type) {
-			case 1:
-				//流媒体账号
-				getStreamingAccountDataView(backgroundDataView, startDate, endDate);
-				break;
-			case 2:
-				//实物数据
-				getRealGoodsData(backgroundDataView, startDate, endDate);
-				break;
-			case 3:
-				//注册账号数据
-				getRegisterAccountData(backgroundDataView, startDate, endDate);
-				break;
-			case 4:
-				//潮玩好物数据
-				getFashionGoodsData(backgroundDataView, startDate, endDate);
-				break;
-		}
+		//流媒体账号
+		getStreamingAccountDataView(backgroundDataView, startDate, endDate);
+		//appleOne
+		getAppleOneDataView(backgroundDataView, startDate, endDate);
+		//实物数据
+		getRealGoodsData(backgroundDataView, startDate, endDate);
+		//注册账号数据
+		getRegisterAccountData(backgroundDataView, startDate, endDate);
+		//潮玩好物数据
+		getFashionGoodsData(backgroundDataView, startDate, endDate);
 		return GatewayResponse.SUCCESS.newBuilder().toResult(backgroundDataView);
 	}
 
@@ -106,7 +103,7 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 			List<StatisticsFashionGoodsData> fashionGoodsData = statistics.statisticsFashionGoodsData(startDate, endDate, true);
 			List<StatisticsFashionGoodsData> collect = fashionGoodsData.stream().filter(data -> {
 				if (data.getNumOfUser() != null && data.getNumOfUser() > 0) {
-					data.setRefundMoney(getRefundMoney(data.getGoodsId(), startDate, endDate));
+					data.setRefundMoney(getRefundMoney(data.getGoodsId(), null, startDate, endDate));
 					data.setMoney(data.getMoney().divide(BigDecimal.valueOf(100)));
 					return true;
 				}
@@ -125,7 +122,7 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 				if (goodsDonSku != null) {
 					data.setSpecVal(goodsDonSku.getSpecVal());
 				}
-				data.setRefundMoney(getRefundMoney(data.getGoodsId(), startDate, endDate));
+				data.setRefundMoney(getRefundMoney(data.getGoodsId(), null, startDate, endDate));
 			}));
 			backgroundDataView.setFashionGoodsDataViews(fashionGoodsData);
 		}
@@ -135,7 +132,7 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 	 * 注册账号数据
 	 */
 	private void getRegisterAccountData(BackgroundDataView backgroundDataView, Date startDate, Date endDate) {
-		if (DateUtil.beginOfDay(DateTime.now()).equals(startDate) && DateUtil.beginOfDay(DateUtil.offsetDay(DateTime.now(),1)).equals(endDate)) {
+		if (DateUtil.beginOfDay(DateTime.now()).equals(startDate) && DateUtil.beginOfDay(DateUtil.offsetDay(DateTime.now(), 1)).equals(endDate)) {
 			List<RegisterAccountData> registerAccountData = statistics.statisticsRegisterAccountData(startDate, endDate, true);
 			List<RegisterAccountData> collect = registerAccountData.stream().filter(data -> {
 				if (data.getNumOfUser() != null && data.getNumOfUser() > 0) {
@@ -146,14 +143,14 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 				return false;
 			}).collect(Collectors.toList());
 			backgroundDataView.setRegisterAccountDataViews(collect);
-		}else {
+		} else {
 			List<RegisterAccountData> registerAccountData = realGoodsDataMapper.statisticsRegisterAccountData(startDate, endDate);
 			backgroundDataView.setRegisterAccountDataViews(registerAccountData);
 		}
 	}
 
 	@Override
-	public IPage<ExpiredAccountDataView> getExpiredAccountView(Boolean isCorpWx, String customerService, Integer goodsId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, Long startTime, Long endTime, Long start, Long limit) {
+	public IPage<ExpiredAccountDataView> getExpiredAccountView(Boolean isCorpWx, String customerService, Long goodsId, Long skuId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, Long startTime, Long endTime, Long start, Long limit) {
 		String startDate = null;
 		String endDate = null;
 		if (startTime != null) {
@@ -162,12 +159,12 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 		if (endTime != null) {
 			endDate = DateTime.of(endTime).toString();
 		}
-		IPage<ExpiredAccountDataView> expiredAccountDataViews = accountService.getExpiredAccountView(isCorpWx, customerService, goodsId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startDate, endDate, DateTime.now().toString(), start, limit);
+		IPage<ExpiredAccountDataView> expiredAccountDataViews = accountService.getExpiredAccountView(isCorpWx, customerService, goodsId, skuId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startDate, endDate, DateTime.now().toString(), start, limit);
 		return expiredAccountDataViews;
 	}
 
 	@Override
-	public List<ExcelAccountData> getExpiredAccountViewNoPage(Boolean isCorpWx, String customerService, Integer goodsId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, Long startTime, Long endTime) {
+	public List<ExcelAccountData> getExpiredAccountViewNoPage(Boolean isCorpWx, String customerService, Long goodsId, Long skuId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, Long startTime, Long endTime) {
 		String startDate = null;
 		String endDate = null;
 		if (startTime != null) {
@@ -176,7 +173,7 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 		if (endTime != null) {
 			endDate = DateTime.of(endTime).toString();
 		}
-		List<ExcelAccountData> expiredAccountDataViews = accountService.getExpiredAccountViewNoPage(isCorpWx, customerService, goodsId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startDate, endDate, DateTime.now().toString());
+		List<ExcelAccountData> expiredAccountDataViews = accountService.getExpiredAccountViewNoPage(isCorpWx, customerService, goodsId, skuId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startDate, endDate, DateTime.now().toString());
 		return expiredAccountDataViews;
 	}
 
@@ -185,11 +182,11 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 		BackgroundDataView backgroundDataView = new BackgroundDataView();
 		Number waitingRegisterNum = beanSearcher.searchCount(RegisterOrderDon.class, MapUtils.builder()
 				.field(RegisterOrderDon::getStatus, RegisterOrderDon.Status.hasPayment.name()).op(Operator.Equal)
-				.onlySelect(RegisterOrderDon ::getId).build());
+				.onlySelect(RegisterOrderDon::getId).build());
 		backgroundDataView.setWaitingRegisterNum(waitingRegisterNum.intValue());
 		Number errorRegisterNum = beanSearcher.searchCount(RegisterOrderDon.class, MapUtils.builder()
 				.field(RegisterOrderDon::getStatus, RegisterOrderDon.Status.error.name()).op(Operator.Equal)
-				.onlySelect(RegisterOrderDon ::getId)
+				.onlySelect(RegisterOrderDon::getId)
 				.build());
 		backgroundDataView.setFailRegisterNum(errorRegisterNum.intValue());
 
@@ -212,11 +209,15 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 
 		Integer numOfMonthEmptyTripsNetflix = groupsMapper.selectEmptyNetfilxTrips(skuId);
 		backgroundDataView.setNumOfMonthEmptyTripsNetflix(numOfMonthEmptyTripsNetflix);
+		Number number = beanSearcher.searchCount(OrderDonView.class, MapUtils.builder().field(OrderDonView::getType, Constant.realGoodsType).op(Operator.InList)
+				.field(OrderDonView::getStatus, OrderDon.Status.hasPayment.name())
+				.build());
+		backgroundDataView.setWaitingSendRealOrder(number.intValue());
 		return backgroundDataView;
 	}
 
 	@Override
-	public Result<String> updateRenewStatus(Integer relationId) {
+	public Result<String> updateRenewStatus(Long relationId) {
 		GroupsRelation groupsRelation = groupsRelationMapper.selectById(relationId);
 		groupsRelation.setRenewStatus(!groupsRelation.getRenewStatus());
 		groupsRelationMapper.updateById(groupsRelation);
@@ -224,69 +225,258 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 	}
 
 	@Override
-	public Result<String> updateHandleStatus(Integer relationId) {
+	public Result<String> updateHandleStatus(Long relationId) {
 		GroupsRelation groupsRelation = groupsRelationMapper.selectById(relationId);
 		groupsRelation.setIsHandle(!groupsRelation.getIsHandle());
 		groupsRelationMapper.updateById(groupsRelation);
 		return GatewayResponse.SUCCESS.newBuilder().toResult("处理状态变更成功");
 	}
 
+	@Override
+	public List<ExcelSheetAndData> exportStatisticsDataByType(Integer type, Long startTime, Long endTime) {
+		String startDate = null;
+		String endDate = null;
+		if (type == null) type = 0;
+		if (startTime != null) {
+			startDate = DateTime.of(startTime).toString();
+		}
+		if (endTime != null) {
+			endDate = DateTime.of(endTime).toString();
+		}
+		List<ExcelSheetAndData> excelSheetDataList = new ArrayList<>();
+		switch (type) {
+			case 1:
+				exportAppleOneData(excelSheetDataList, startDate, endDate);
+				break;
+			case 2:
+				exportStreamingAccountData(excelSheetDataList, startDate, endDate);
+				break;
+			case 3:
+				exportRealGoodsData(excelSheetDataList, startDate, endDate);
+				break;
+			case 4:
+				exportFashionData(excelSheetDataList, startDate, endDate);
+				break;
+			case 5:
+				exportRegisterData(excelSheetDataList, startDate, endDate);
+				break;
+			default:
+				exportAppleOneData(excelSheetDataList, startDate, endDate);
+				exportStreamingAccountData(excelSheetDataList, startDate, endDate);
+				exportRealGoodsData(excelSheetDataList, startDate, endDate);
+				exportFashionData(excelSheetDataList, startDate, endDate);
+				exportRegisterData(excelSheetDataList, startDate, endDate);
+		}
+		return excelSheetDataList;
+	}
+
+	private void exportRegisterData(List<ExcelSheetAndData> excelSheetDataList, String startDate, String endDate) {
+		List<ExcelRegisterAccountData> registerAccountData = new ArrayList<>();
+		Constant.registerAccount.forEach(platform -> {
+			List<RegisterOrderDon> registerOrderDons = statisticsUserDataMapper.getPlatformHasPaymentOrders(platform, startDate, endDate);
+			if (registerOrderDons.isEmpty()) {
+				return;
+			}
+			ExcelRegisterAccountData registerDataExcel = new ExcelRegisterAccountData();
+			registerDataExcel.setPlatform(platform);
+			registerDataExcel.setNumOfOrder(registerOrderDons.size());
+			Set<Long> userSet = registerOrderDons.stream().map(RegisterOrderDon::getUserId).collect(Collectors.toSet());
+			registerDataExcel.setNumOfUser(userSet.size());
+			Optional<BigDecimal> reduce = registerOrderDons.stream().map(RegisterOrderDon::getMoney).reduce(BigDecimal::add);
+			registerDataExcel.setMoney(reduce.isPresent() ? reduce.get().divide(BigDecimal.valueOf(100)) : BigDecimal.ZERO);
+			registerAccountData.add(registerDataExcel);
+		});
+		if (registerAccountData.isEmpty()) {
+			return;
+		}
+		excelSheetDataList.add(new ExcelSheetAndData("注册账号数据", registerAccountData, ExcelRegisterAccountData.class));
+	}
+
+	private void exportFashionData(List<ExcelSheetAndData> excelSheetDataList, String startDate, String endDate) {
+		List<Long> goodsIds = statisticsUserDataMapper.getAllFashionGoods(startDate, endDate);
+		List<ExcelRealGoodsData> fashionData = new ArrayList<>();
+		goodsIds.forEach(goodsId -> {
+			//查找所有规格
+			List<Long> skuIds = goodsDonSkuMapper.selectList(Wrappers.lambdaQuery(GoodsDonSku.class).eq(GoodsDonSku::getGoodsId, goodsId)).stream().map(GoodsDonSku::getId).collect(Collectors.toList());
+			skuIds.forEach(skuId -> {
+				//订单数据
+				ExcelRealGoodsData exportData = statisticsUserDataMapper.getExportGoodsDonDataBySkuId(skuId, startDate, endDate);
+				if (exportData == null) {
+					return;
+				}
+				exportData.setName(goodsDonMapper.selectById(goodsId).getTitle());
+				exportData.setSpecVal(goodsDonSkuMapper.selectById(skuId).getSpecVal());
+				if (exportData.getNumOfOrder() != 0) {
+					fashionData.add(exportData);
+				}
+			});
+		});
+		if (fashionData.isEmpty()) {
+			return;
+		}
+		excelSheetDataList.add(new ExcelSheetAndData("潮玩好物", fashionData, ExcelRealGoodsData.class));
+	}
+
+	private void exportRealGoodsData(List<ExcelSheetAndData> excelSheetDataList, String startDate, String endDate) {
+		List<Long> goodsIds = statisticsUserDataMapper.getAllRealGoods(startDate, endDate);
+		List<ExcelRealGoodsData> realGoodsData = new ArrayList<>();
+		goodsIds.forEach(goodsId -> {
+			//查找所有规格
+			List<Long> skuIds = goodsDonSkuMapper.selectList(Wrappers.lambdaQuery(GoodsDonSku.class).eq(GoodsDonSku::getGoodsId, goodsId)).stream().map(GoodsDonSku::getId).collect(Collectors.toList());
+			skuIds.forEach(skuId -> {
+				//订单数据
+				ExcelRealGoodsData exportData = statisticsUserDataMapper.getExportGoodsDonDataBySkuId(skuId, startDate, endDate);
+				if (exportData == null) {
+					return;
+				}
+				exportData.setName(goodsDonMapper.selectById(goodsId).getTitle());
+				exportData.setSpecVal(goodsDonSkuMapper.selectById(skuId).getSpecVal());
+				if (exportData.getNumOfOrder() != 0) {
+					realGoodsData.add(exportData);
+				}
+			});
+		});
+		if (realGoodsData.isEmpty()) {
+			return;
+		}
+		excelSheetDataList.add(new ExcelSheetAndData("硬件设备数据", realGoodsData, ExcelRealGoodsData.class));
+	}
+
+	private void exportStreamingAccountData(List<ExcelSheetAndData> excelSheetDataList, String startDate, String endDate) {
+		List<Long> goodsIds = statisticsUserDataMapper.getAllStreaming(startDate, endDate);
+		List<ExcelStreamingAccountData> streamingAccountData = new ArrayList<>();
+		goodsIds.forEach(goodsId -> {
+			//订单数据
+			ExcelStreamingAccountData exportData = statisticsUserDataMapper.getExportStreamingAccountData(goodsId, null, null, startDate, endDate);
+			exportData.setName(goodsDonMapper.selectById(goodsId).getTitle());
+			//兑换单数
+			exportData.setNumOfExCodeOrder(statisticsUserDataMapper.getExportStreamingAccountData(goodsId, null, true, startDate, endDate).getNumOfOrder());
+			//分销记录
+			ExcelStreamingAccountData distributeData = statisticsUserDataMapper.getExportStreamingAccountData(goodsId, true, null, startDate, endDate);
+			exportData.setDisOrder(distributeData.getNumOfOrder());
+			exportData.setDisMoney(distributeData.getMoney() != null ? distributeData.getMoney() : BigDecimal.ZERO);
+			//月、季、年
+			exportData.setMonth(statisticsUserDataMapper.getTypeData(goodsId, Constant.payType.get(0), startDate, endDate));
+			exportData.setSeason(statisticsUserDataMapper.getTypeData(goodsId, Constant.payType.get(1), startDate, endDate));
+			exportData.setYear(statisticsUserDataMapper.getTypeData(goodsId, Constant.payType.get(2), startDate, endDate));
+			streamingAccountData.add(exportData);
+		});
+		if (streamingAccountData.isEmpty()) {
+			return;
+		}
+		excelSheetDataList.add(new ExcelSheetAndData("流媒体账号数据", streamingAccountData, ExcelStreamingAccountData.class));
+	}
+
+	private void exportAppleOneData(List<ExcelSheetAndData> excelSheetDataList, String startDate, String endDate) {
+		Map<String, List<GoodsDonSku>> appleOneMap = statistics.getAppleOneMap();
+		List<ExcelAppleOneData> appleData = new ArrayList<>();
+		appleOneMap.forEach((k, v) -> {
+			ExcelAppleOneData appleDataExcel = new ExcelAppleOneData();
+			appleDataExcel.setArea(k);
+			Set<Long> skuIds = v.stream().map(GoodsDonSku::getId).collect(Collectors.toSet());
+			List<OrderDon> orderDons = orderDonMapper.selectList(Wrappers.lambdaQuery(OrderDon.class).in(OrderDon::getSkuId, skuIds).notIn(OrderDon::getStatus, Constant.noOrderStatus).between(OrderDon::getCreatedTime, startDate, endDate));
+			appleDataExcel.setNumOfOrder(orderDons.size());
+			Set<Long> userSet = Optional.ofNullable(orderDons.stream().map(OrderDon::getUserId).collect(Collectors.toSet())).orElse(new HashSet<>());
+			appleDataExcel.setNumOfUser(userSet.size());
+			List<OrderDon> exCodeOrders = orderDonMapper.selectList(Wrappers.lambdaQuery(OrderDon.class)
+					.eq(OrderDon::getType, OrderDon.Type.EX_CODE)
+					.in(OrderDon::getSkuId, skuIds)
+					.notIn(OrderDon::getStatus, Constant.noOrderStatus).between(OrderDon::getCreatedTime, startDate, endDate));
+			if (orderDons.isEmpty()) {
+				return;
+			}
+			appleDataExcel.setNumOfExCodeOrder(exCodeOrders.size());
+			Optional<BigDecimal> money = orderDons.stream().map(OrderDon::getMoney).reduce(BigDecimal::add);
+			appleDataExcel.setMoney(money.isPresent() ? money.get().divide(BigDecimal.valueOf(100)) : BigDecimal.ZERO);
+			List<OrderDon> distributeOrders = orderDonMapper.selectList(Wrappers.lambdaQuery(OrderDon.class)
+					.eq(OrderDon::getIsDistribute, true)
+					.in(OrderDon::getSkuId, skuIds)
+					.notIn(OrderDon::getStatus, Constant.noOrderStatus).between(OrderDon::getCreatedTime, startDate, endDate));
+			appleDataExcel.setDisOrder(distributeOrders.size());
+			Optional<BigDecimal> distributeMoney = distributeOrders.stream().map(OrderDon::getMoney).reduce(BigDecimal::add);
+			appleDataExcel.setDisMoney(distributeMoney.isPresent() ? distributeMoney.get().divide(BigDecimal.valueOf(100)) : BigDecimal.ZERO);
+			Map<Long, List<OrderDon>> skuMaps = orderDons.stream().collect(Collectors.groupingBy(OrderDon::getSkuId));
+			v.forEach(sku -> {
+				Long skuId = sku.getId();
+				List<OrderDon> dons = Optional.ofNullable(skuMaps.get(skuId)).orElse(new ArrayList<>());
+				if (sku.getSpecVal().contains(Constant.payType.get(0)) && !sku.getSpecVal().contains(Constant.payType.get(2))) {
+					appleDataExcel.setMonth(dons.size());
+				} else if (sku.getSpecVal().contains(Constant.payType.get(1))) {
+					appleDataExcel.setSeason(dons.size());
+				} else if (!sku.getSpecVal().contains(Constant.payType.get(0)) && sku.getSpecVal().contains(Constant.payType.get(2))) {
+					appleDataExcel.setYear(dons.size());
+				}
+			});
+			appleData.add(appleDataExcel);
+		});
+		if (appleData.isEmpty()) {
+			return;
+		}
+		excelSheetDataList.add(new ExcelSheetAndData("Apple One数据", appleData, ExcelAppleOneData.class));
+	}
+
+
+
 	private void getAppleOneDataView(BackgroundDataView backgroundDataView, Date startDate, Date endDate) {
 		List<AppleOneData> appleOneData = appleOneDataMapper.statisticsAppleOneData(startDate, endDate);
-		if (DateUtil.beginOfDay(DateTime.now()).equals(startDate) && DateUtil.beginOfDay(DateUtil.offsetDay(DateTime.now(),1)).equals(endDate)) {
+		if (DateUtil.beginOfDay(DateTime.now()).equals(startDate) && DateUtil.beginOfDay(DateUtil.offsetDay(DateTime.now(), 1)).equals(endDate)) {
 			List<AppleOneData> appleOneData1 = statistics.statisticsAppleOneData(startDate, endDate, true);
 			List<AppleOneData> collect = appleOneData1.stream().filter(data -> {
 				if (data.getNumOfUser() != null && data.getNumOfUser() > 0) {
 					data.setMoney(data.getMoney().divide(BigDecimal.valueOf(100)));
+					data.setRefundMoney(getAppleOneRefundMoneyByArea(data.getAreaName(), startDate, endDate));
 					data.setDistributeOrderMoney(data.getDistributeOrderMoney().divide(BigDecimal.valueOf(100)));
 					return true;
 				}
 				return false;
 			}).collect(Collectors.toList());
 			backgroundDataView.setAppleOneDataViews(collect);
-		}else {
+		} else {
+			appleOneData.forEach(data -> {
+				data.setRefundMoney(getAppleOneRefundMoneyByArea(data.getAreaName(), startDate, endDate));
+			});
 			backgroundDataView.setAppleOneDataViews(appleOneData);
 		}
 	}
 
 	private void getStreamingAccountDataView(BackgroundDataView backgroundDataView, Date startDate, Date endDate) {
-		if (DateUtil.beginOfDay(DateTime.now()).equals(startDate) && DateUtil.beginOfDay(DateUtil.offsetDay(DateTime.now(),1)).equals(endDate)) {
+		if (DateUtil.beginOfDay(DateTime.now()).equals(startDate) && DateUtil.beginOfDay(DateUtil.offsetDay(DateTime.now(), 1)).equals(endDate)) {
 			List<StreamingAccountData> streamingAccountData = statistics.statisticsStreamingAccountData(startDate, endDate, true);
 			List<StreamingAccountData> collect = streamingAccountData.stream().filter(data -> {
 				if (data.getNumOfUser() != null && data.getNumOfUser() > 0) {
-					data.setRefundMoney(getRefundMoney(data.getGoodsId(), startDate, endDate));
+					data.setRefundMoney(getRefundMoney(data.getGoodsId(), null, startDate, endDate));
 					data.setMoney(data.getMoney().divide(BigDecimal.valueOf(100)));
 					return true;
 				}
 				return false;
 			}).collect(Collectors.toList());
 			backgroundDataView.setStreamAccountDataViews(collect);
-		}else {
+		} else {
 			List<StreamingAccountData> streamingAccountData = streamingAccountDataMapper.statisticsStreamingData(startDate, endDate);
-			Optional.ofNullable(streamingAccountData).ifPresent(list->list.forEach(data->{
+			Optional.ofNullable(streamingAccountData).ifPresent(list -> list.forEach(data -> {
 				GoodsDon goodsDon = goodsDonMapper.selectOne(Wrappers.lambdaQuery(GoodsDon.class).eq(GoodsDon::getId, data.getGoodsId()).last("limit 1"));
 				if (goodsDon != null) {
 					data.setAccountName(goodsDon.getTitle());
 				}
-				data.setRefundMoney(getRefundMoney(data.getGoodsId(), startDate, endDate));
+				data.setRefundMoney(getRefundMoney(data.getGoodsId(), null, startDate, endDate));
 			}));
 			backgroundDataView.setStreamAccountDataViews(streamingAccountData);
 		}
 	}
 
 	private void getRealGoodsData(BackgroundDataView backgroundDataView, Date startDate, Date endDate) {
-		if (DateUtil.beginOfDay(DateTime.now()).equals(startDate) && DateUtil.beginOfDay(DateUtil.offsetDay(DateTime.now(),1)).equals(endDate)) {
+		if (DateUtil.beginOfDay(DateTime.now()).equals(startDate) && DateUtil.beginOfDay(DateUtil.offsetDay(DateTime.now(), 1)).equals(endDate)) {
 			List<RealGoodsData> realGoodsData = statistics.statisticsRealGoodsData(startDate, endDate, true);
-			List<RealGoodsData> collect = realGoodsData.stream().filter(data ->{
+			List<RealGoodsData> collect = realGoodsData.stream().filter(data -> {
 				if (data.getNumOfUser() != null && data.getNumOfUser() > 0) {
-					data.setRefundMoney(getRefundMoney(data.getGoodsId(), startDate, endDate));
+					data.setRefundMoney(getRefundMoney(null, data.getSkuId(), startDate, endDate));
 					data.setMoney(data.getMoney().divide(BigDecimal.valueOf(100)));
 					return true;
 				}
 				return false;
 			}).collect(Collectors.toList());
 			backgroundDataView.setRealGoodsDataViews(collect);
-		}else {
+		} else {
 			List<RealGoodsData> realGoodsData = realGoodsDataMapper.statisticsRealGoodsData(startDate, endDate);
 			Optional.ofNullable(realGoodsData).ifPresent(list -> list.forEach(data -> {
 				GoodsDon goodsDon = goodsDonMapper.selectOne(Wrappers.lambdaQuery(GoodsDon.class).eq(GoodsDon::getId, data.getGoodsId()).last("limit 1"));
@@ -297,7 +487,7 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 				if (goodsDonSku != null) {
 					data.setSpecVal(goodsDonSku.getSpecVal());
 				}
-				data.setRefundMoney(getRefundMoney(data.getGoodsId(), startDate, endDate));
+				data.setRefundMoney(getRefundMoney(null, data.getSkuId(), startDate, endDate));
 			}));
 			backgroundDataView.setRealGoodsDataViews(realGoodsData);
 		}
@@ -329,20 +519,19 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 		List<Account> expiredAccounts = Optional.ofNullable(accountService.list(Wrappers.lambdaQuery(Account.class).le(Account::getExpiryTime, now))).orElse(new ArrayList<>());
 		backgroundDataView.setTotalExpiredAccountNum(expiredAccounts.size());
 		//虚物
-		setGoodsMoneyAndOrder(1, backgroundDataView);
+		setGoodsMoneyAndOrder(1, startDate, endDate, backgroundDataView);
 		//实物
-		setGoodsMoneyAndOrder(2, backgroundDataView);
+		setGoodsMoneyAndOrder(2, startDate, endDate, backgroundDataView);
 		//潮玩
-		setGoodsMoneyAndOrder(3, backgroundDataView);
-
-		//分销金额数据统计
-		distribute(backgroundDataView, startDate, endDate);
+		setGoodsMoneyAndOrder(3, startDate, endDate, backgroundDataView);
 	}
 
 	/**
 	 * 分销金额信息补充
+	 *
 	 * @param backgroundDataView
 	 */
+	@Override
 	public void distribute(BackgroundDataView backgroundDataView, Date startDate, Date endDate) {
 		List<DistributeOrdersView> distributeOrders = Optional.ofNullable(beanSearcher.searchAll(DistributeOrdersView.class, MapUtils.builder()
 				.field(DistributeOrdersView::getCreatedTime, startDate, endDate).op(Operator.Between)
@@ -350,13 +539,13 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 		backgroundDataView.setDistributeOrders(distributeOrders.size());
 		//固定推广者订单
 		List<DistributeOrdersView> distributePopularizeOrders = Optional.ofNullable(beanSearcher.searchAll(DistributeOrdersView.class, MapUtils.builder()
-				.field(DistributeOrdersView::getIsFixedDistribute,true).op(Operator.Equal)
+				.field(DistributeOrdersView::getIsFixedDistribute, true).op(Operator.Equal)
 				.field(DistributeOrdersView::getCreatedTime, startDate, endDate).op(Operator.Between)
 				.build())).orElse(new ArrayList<>());
 		backgroundDataView.setDistributePopularizeOrders(distributePopularizeOrders.size());
 		//普通分销单数
 		List<DistributeOrdersView> distributeOriginalOrders = Optional.ofNullable(beanSearcher.searchAll(DistributeOrdersView.class, MapUtils.builder()
-				.field(DistributeOrdersView::getIsFixedDistribute,false).op(Operator.Equal)
+				.field(DistributeOrdersView::getIsFixedDistribute, false).op(Operator.Equal)
 				.field(DistributeOrdersView::getCreatedTime, startDate, endDate).op(Operator.Between)
 				.build())).orElse(new ArrayList<>());
 		backgroundDataView.setDistributeOriginalOrders(distributeOriginalOrders.size());
@@ -391,9 +580,10 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 		}
 	}
 
-	public BigDecimal getRefundMoney(Long goodsId, Date startDate, Date endDate) {
+	public BigDecimal getRefundMoney(Long goodsId, Long skuId, Date startDate, Date endDate) {
 		Number refundMoneyNumber = beanSearcher.searchSum(OrderDon.class, MapUtils.builder()
 				.field(OrderDon::getGoodsId, goodsId)
+				.field(OrderDon::getSkuId, skuId)
 				.field(OrderDon::getStatus, OrderDon.Status.refund.name())
 				.field(OrderDon::getCreatedTime, startDate, endDate).op(Operator.Between)
 				.build(), "refundMoney");
@@ -401,10 +591,12 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 		return refundMoney;
 	}
 
-	public void setGoodsMoneyAndOrder(Integer type, BackgroundDataView backgroundDataView) {
+	public void setGoodsMoneyAndOrder(Integer type, Date startDate, Date endDate, BackgroundDataView backgroundDataView) {
 		List<OrderDonStatisticsView> orderDonStatisticsView = Optional.ofNullable(beanSearcher.searchAll(OrderDonStatisticsView.class,
 				MapUtils.builder().field(OrderDonStatisticsView::getGoodsType, type)
-						.field(OrderDonStatisticsView::getStatus, Constant.noOrderStatus).op(Operator.InList).build())).orElse(new ArrayList<>());
+						.field(OrderDonStatisticsView::getStatus, Constant.noOrderStatus).op(Operator.NotIn)
+						.field(OrderDonStatisticsView::getCreateTime, startDate, endDate).op(Operator.Between)
+						.build())).orElse(new ArrayList<>());
 		Optional<BigDecimal> orderMoneyReduce = orderDonStatisticsView.stream().map(OrderDonStatisticsView::getMoney).reduce(BigDecimal::add);
 		int totalOrder = orderDonStatisticsView.size();
 
@@ -422,4 +614,14 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 			backgroundDataView.setFashionAccountOfOrder(orderMoney);
 		}
 	}
+
+	private BigDecimal getAppleOneRefundMoneyByArea(String areaName, Date startDate, Date endDate) {
+		Number refundMoneyNumber = beanSearcher.searchSum(OrderDonView.class, MapUtils.builder()
+				.field(OrderDonView::getSpecVal, areaName).op(Operator.Contain)
+				.field(OrderDon::getStatus, OrderDon.Status.refund.name())
+				.field(OrderDon::getCreatedTime, startDate, endDate).op(Operator.Between)
+				.build(), "refundMoney");
+		BigDecimal refundMoney = BigDecimal.valueOf(refundMoneyNumber.intValue()).divide(BigDecimal.valueOf(100));
+		return refundMoney;
+	}
 }

+ 15 - 1
netflix-service/src/main/java/com/cyksj/service/order/UserRealOrderBenefitsService.java

@@ -1,5 +1,9 @@
 package com.cyksj.service.order;
 
+import com.cyksj.model.entity.GoodsDonSku;
+import com.cyksj.model.manage.views.GroupsRelationView;
+import com.cyksj.model.views.UserAvailableGoodsTicketView;
+
 import java.util.List;
 
 /*
@@ -13,10 +17,20 @@ public interface UserRealOrderBenefitsService {
 	/**
 	 * 获取购买实物权益
 	 */
-	void receivePayRealGoodsBenefits(Long userId, Long id, Long id1, List<Long> skuIds);
+	Boolean getPayRealGoodsBenefits(Long userId, Long orderId, List<GoodsDonSku> skuIds);
 
 	/**
 	 * 扣除实物权益
 	 */
 	void deductUserRealGoodsBenefits(Long orderId);
+
+	/**
+	 * 领取实物权益
+	 */
+	GroupsRelationView receiveRealGoodsBenefits(Long userId, Long benefitsId, Long goodsId, Long skuId, Long relationId);
+
+	/**
+	 * 实物权益可选车票
+	 */
+	List<UserAvailableGoodsTicketView> getAvailableBenefitsTickets(Long userId, Long orderId);
 }

+ 55 - 45
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -64,6 +64,7 @@ import com.cyksj.service.market.MarketFrontService;
 import com.cyksj.service.market.task.TaskService;
 import com.cyksj.service.order.OrderDonService;
 import com.cyksj.service.order.UserRealOrderBenefitsService;
+import com.cyksj.service.relation.GroupRelationFrontService;
 import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.service.wechat.WeChatService;
 import com.cyksj.task.JobManager;
@@ -181,6 +182,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	private final CouponDistributePopularizeMapper couponDistributePopularizeMapper;
 
+	private final GroupRelationFrontService groupRelationFrontService;
+
 	private final List<String> noChekGoodsTemp = List.of("Apple One", "Youtube", "Spotify");
 
 	@Transactional(rollbackFor = Throwable.class)
@@ -223,22 +226,26 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 					}
 
 				} else {
-					//TODO 如果没指定座位,等待逻辑确认
-					GroupsTrips groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class).eq(GroupsTrips::getSkuId, payRequest.getSkuId()).gt(GroupsTrips::getAvailableNum, 0).last("limit 1").orderByAsc(GroupsTrips::getAvailableNum));
-					if (groups == null) {
-						relation = createNewGroupsTrips(sku, true);
-						isNew = true;
-					} else {
-						//寻找快满编车队进行占座
-						relation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
-								.eq(GroupsRelation::getGroupsId, groups.getId())
-								.eq(GroupsRelation::getStatus, "none")
-								.eq(GroupsRelation::getUserId, 0)
-								.orderByAsc(GroupsRelation::getNum)
-								.last("limit 1")
-						);
-						if (relation == null) {
-							throw new BusinessRuntimeException(GROUP_INDEX_NOT_FIND.getCode(), GROUP_INDEX_NOT_FIND.getMsg());
+					//寻找差不多过期时间规格的车位
+					relation = groupRelationFrontService.getSimilarExpiredGroupRelation(sku.getId(), sku.getMonths());
+					if (relation == null) {
+						//TODO 如果没指定座位,等待逻辑确认
+						GroupsTrips groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class).eq(GroupsTrips::getSkuId, payRequest.getSkuId()).gt(GroupsTrips::getAvailableNum, 0).last("limit 1").orderByAsc(GroupsTrips::getAvailableNum));
+						if (groups == null) {
+							relation = createNewGroupsTrips(sku, true);
+							isNew = true;
+						} else {
+							//寻找快满编车队进行占座
+							relation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
+									.eq(GroupsRelation::getGroupsId, groups.getId())
+									.eq(GroupsRelation::getStatus, "none")
+									.eq(GroupsRelation::getUserId, 0)
+									.orderByAsc(GroupsRelation::getNum)
+									.last("limit 1")
+							);
+							if (relation == null) {
+								throw new BusinessRuntimeException(GROUP_INDEX_NOT_FIND.getCode(), GROUP_INDEX_NOT_FIND.getMsg());
+							}
 						}
 					}
 				}
@@ -307,7 +314,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		orderDon.setCouponExCode(payRequest.getCouponExCode());
 		if (isNoLogin == null || !isNoLogin) {
 			//虚拟商品订单,是否是分销订单
-			if (goodsDon.getType() == 1) {
+			if (goodsDon.getType() == 1 || goodsDon.getType() == 2) {
 				UserDistributeShared userDistributeShared = userDistributeSharedMapper.selectOne(Wrappers.lambdaQuery(UserDistributeShared.class).eq(UserDistributeShared::getUserId, user.getId()).last("limit 1"));
 				if (userDistributeShared != null) {
 					orderDon.setIsDistribute(true);
@@ -506,17 +513,6 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				marketFrontService.addSpecificChanceNum(order.getUserId(), order.getId(), order.getGoodsId(), order.getSkuId());
 				if (goodsDon.getType() == 2) {
 					equipmentDistributeService.addDistributeBenefitsChance(order.getUserId(), order.getId());
-					if (sku.getIsBenefits()) {
-						if (StrUtil.isNotEmpty(sku.getBenefitsList())) {
-							try {
-								List<Long> skuIds = Jsons.parseList(sku.getBenefitsList(), Long.class);
-								//自购实物 获取权益
-								userRealOrderBenefitsService.receivePayRealGoodsBenefits(order.getUserId(), order.getId(), goodsDon.getId(), skuIds);
-							} catch (Exception e) {
-
-							}
-						}
-					}
 				}
 				//若该订单使用了规定推广者的兑换码 增加上下级关系
 				if (StrUtil.isNotBlank(order.getCouponExCode())) {
@@ -795,17 +791,6 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				marketFrontService.addSpecificChanceNum(orderDon.getUserId(), orderDon.getId(), orderDon.getGoodsId(), orderDon.getSkuId());
 				if (goodsDon.getType() == 2) {
 					equipmentDistributeService.addDistributeBenefitsChance(orderDon.getUserId(), orderDon.getId());
-					if (sku.getIsBenefits()) {
-						if (StrUtil.isNotEmpty(sku.getBenefitsList())) {
-							try {
-								List<Long> skuIds = Jsons.parseList(sku.getBenefitsList(), Long.class);
-								//自购实物 获取权益
-								userRealOrderBenefitsService.receivePayRealGoodsBenefits(orderDon.getUserId(), orderDon.getId(), goodsDon.getId(), skuIds);
-							} catch (Exception e) {
-
-							}
-						}
-					}
 				}
 				//若该订单使用了规定推广者的兑换码 增加上下级关系
 				if (StrUtil.isNotBlank(orderDon.getCouponExCode())) {
@@ -1149,6 +1134,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId());
 				if (goodsDon.getType() == 2) {
 					equipmentDistributeService.subDistributeBenefitsChance(orderDon.getUserId(), orderDon.getId());
+					//扣除用户自身实物权益
+					userRealOrderBenefitsService.deductUserRealGoodsBenefits(orderDon.getId());
 				}
 			} catch (Exception e) {
 				log.error("wx减少抽奖机会错误,orderId:{},error:{}", orderDon.getId(), e);
@@ -1358,11 +1345,24 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				log.info("分销兑换积分比例未配置");
 			} else {
 				UserDistribute userDistribute = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class).eq(UserDistribute::getUserId, userDistributeShared.getSharedId()).eq(UserDistribute::getDeleted, true).last("limit 1"));
+				//普通分销
+				GoodsDon goodsDon = goodsDonMapper.selectById(order.getGoodsId());
+				//分销比例
+				Integer rate = 0;
 				if (userDistribute == null) {
-					//普通分销
-					GoodsDon goodsDon = goodsDonMapper.selectById(order.getGoodsId());
 					if (goodsDon != null) {
-						returnMoney = orderMoney.multiply(BigDecimal.valueOf(goodsDon.getRate())).divide(BigDecimal.valueOf(100));
+						rate = goodsDon.getRate();
+						//实物分销比例
+						if (goodsDon.getType() == 2) {
+							GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(order.getSkuId());
+							if (goodsDonSku != null) {
+								//不包含套餐权益
+								if (!goodsDonSku.getIsBenefits()) {
+									rate = goodsDon.getSecondRate();
+								}
+							}
+						}
+						returnMoney = orderMoney.multiply(BigDecimal.valueOf(rate)).divide(BigDecimal.valueOf(100));
 					}
 				}else {
 					//固定推广分销
@@ -1371,7 +1371,17 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 							.eq(UserPlatDistributeRate::getDistributeId, userDistribute.getId())
 							.last("limit 1"));
 					if (userPlatDistributeRate != null) {
-						returnMoney = orderMoney.multiply(BigDecimal.valueOf(userPlatDistributeRate.getRate())).divide(BigDecimal.valueOf(100));
+						rate = userPlatDistributeRate.getRate();
+						if (goodsDon != null && goodsDon.getType() == 2) {
+							GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(order.getSkuId());
+							if (goodsDonSku != null) {
+								//不包含套餐权益
+								if (!goodsDonSku.getIsBenefits()) {
+									rate = userPlatDistributeRate.getSecondRate();
+								}
+							}
+						}
+						returnMoney = orderMoney.multiply(BigDecimal.valueOf(rate)).divide(BigDecimal.valueOf(100));
 					}
 				}
 				if (returnMoney != null) {
@@ -1380,9 +1390,9 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				}
 				distributeWaitingSendPoints.setPoints(points);
 				if (points != null && points.compareTo(BigDecimal.ZERO) > 0) {
-					log.info("用户{}邀请{},产生分销订单分发积分记录入库", userDistributeShared.getUserId(), order.getUserId());
+					log.info("用户{}邀请{},产生分销订单分发积分记录入库", userDistributeShared.getSharedId(), order.getUserId());
 					distributeWaitingSendPoints.setSendStatus(DistributeWaitingSendPoints.Status.waiting);
-					distributeWaitingSendPoints.setSendTime(DateUtil.offsetDay(order.getPayTime(), 7));
+					distributeWaitingSendPoints.setSendTime(DateUtil.offsetDay(order.getPayTime(), 3));
 					distributeWaitingSendPointsMapper.insert(distributeWaitingSendPoints);
 				}
 			}

+ 124 - 38
netflix-service/src/main/java/com/cyksj/service/order/impl/UserRealOrderBenefitsImpl.java

@@ -13,20 +13,20 @@ import com.cyksj.mapper.channel.UserPayEquipmentAvailableBenefitsMapper;
 import com.cyksj.mapper.channel.UserPayEquipmentReceiveBenefitsRecordMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.GroupsRelationView;
+import com.cyksj.model.views.UserAvailableGoodsTicketView;
 import com.cyksj.service.exchange.ExchangeCodeService;
 import com.cyksj.service.order.UserRealOrderBenefitsService;
 import com.cyksj.service.relation.GroupRelationClearService;
 import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.param.Operator;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
 
 /*
  *项目名: netflix
@@ -55,41 +55,52 @@ public class UserRealOrderBenefitsImpl implements UserRealOrderBenefitsService {
 	private final OrderDonMapper orderDonMapper;
 
 	@Override
-	public void receivePayRealGoodsBenefits(Long userId, Long orderId, Long goodsId, List<Long> skuIds) {
-		skuIds.forEach(skuId->{
-			GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(skuId);
-			if (goodsDonSku != null) {
-				List<GroupsRelationView> relationViewList = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
-						.field(GroupsRelationView::getGoodsId, goodsId)
-						.field(GroupsRelationView::getSkuId, skuId)
-						.field(GroupsRelationView::getUserId, userId)
-						.field(GroupsRelationView::getStatus, GroupsRelation.Status.validity.name())
-						.build());
-				//是否有该规格车票,若无直接发放车票
-				if (CollUtil.isEmpty(relationViewList)) {
-					//领取权益时,没有车票的用户自动上车,获得对应车票
-					GroupsRelation relation = exchangeCodeService.getGroupTripsTicket(goodsDonSku, userId, null, OrderDon.Type.PAY_EQUIPMENT);
-					saveReceiveBenefitsRecord(userId, skuId, orderId, relation.getOrderId(), relation.getId(), goodsDonSku.getMonths(), 1);
-				} else if (relationViewList.size() == 1) {
-					//若有且只有一张增加时长
-					GroupsRelationView groupsRelationView = relationViewList.get(0);
-					Date expiryTime = groupsRelationView.getExpiryTime();
-					if (expiryTime == null) {
-						throw BusinessRuntimeException.getInstance("该车位暂未发车,请发车后再领取权益");
-					}
-					DateTime updateExpiryTime = DateUtil.offset(expiryTime, DateField.MONTH, goodsDonSku.getMonths());
-					groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
-							.eq(GroupsRelation::getId, groupsRelationView.getId())
-							.eq(GroupsRelation::getUserId, userId)
-							.set(GroupsRelation::getExpiryTime, updateExpiryTime));
-					groupsRelationView.setUpdateExpiryTime(updateExpiryTime);
-					saveReceiveBenefitsRecord(userId, skuId, orderId, null, groupsRelationView.getId(), goodsDonSku.getMonths(), 1);
-				}else {
-					//若有该规格多张车票,保存可获取的车票权益 以供用户自行选择
-					saveAvailableBenefits(userId, skuId, orderId);
+	public Boolean getPayRealGoodsBenefits(Long userId, Long orderId, List<GoodsDonSku> skuIds) {
+		Boolean isReceivedAll = true;
+		for (GoodsDonSku sku : skuIds) {
+			Long skuId = sku.getId();
+			Long goodsId = sku.getGoodsId();
+			sku = goodsDonSkuMapper.selectById(skuId);
+//			List<GroupsRelationView> relationViewList = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
+//					.field(GroupsRelationView::getGoodsId, goodsId)
+//					.field(GroupsRelationView::getUserId, userId)
+//					.field(GroupsRelationView::getStatus, GroupsRelation.Status.validity.name())
+//					.build());
+			List<GroupsRelationView> relationViewList = groupsRelationMapper.selectRelationByGoodsId(goodsId, userId);
+			//是否有该规格车票,若无直接发放车票
+			if (CollUtil.isEmpty(relationViewList)) {
+				//领取权益时,没有车票的用户自动上车,获得对应车票
+				GroupsRelation relation = exchangeCodeService.getGroupTripsTicket(sku, userId, null, OrderDon.Type.PAY_EQUIPMENT);
+				//多给三天
+				DateTime expiryTime = DateUtil.offsetDay(relation.getExpiryTime(), 3);
+				groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
+						.set(GroupsRelation::getExpiryTime, expiryTime)
+						.eq(GroupsRelation::getId, relation.getId()));
+				saveReceiveBenefitsRecord(userId, skuId, orderId, relation.getOrderId(), relation.getId(), sku.getMonths(), 1);
+			} else if (relationViewList.size() == 1) {
+				//若有且只有一张增加时长
+				GroupsRelationView groupsRelationView = relationViewList.get(0);
+				Date expiryTime = groupsRelationView.getExpiryTime();
+				if (expiryTime == null) {
+					throw BusinessRuntimeException.getInstance("该车位暂未发车,请发车后再领取权益");
+				}
+				DateTime updateExpiryTime = DateUtil.offset(expiryTime, DateField.MONTH, sku.getMonths());
+				updateExpiryTime = DateUtil.offsetDay(updateExpiryTime, 3);
+				groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
+						.eq(GroupsRelation::getId, groupsRelationView.getId())
+						.eq(GroupsRelation::getUserId, userId)
+						.set(GroupsRelation::getExpiryTime, updateExpiryTime));
+				groupsRelationView.setUpdateExpiryTime(updateExpiryTime);
+				saveReceiveBenefitsRecord(userId, skuId, orderId, null, groupsRelationView.getId(), sku.getMonths(), 1);
+			} else {
+				//若有该规格多张车票,保存可获取的车票权益 以供用户自行选择
+				saveAvailableBenefits(userId, skuId, orderId);
+				if (isReceivedAll) {
+					isReceivedAll = false;
 				}
 			}
-		});
+		}
+		return isReceivedAll;
 	}
 
 	@Override
@@ -99,7 +110,6 @@ public class UserRealOrderBenefitsImpl implements UserRealOrderBenefitsService {
 				.eq(UserPayEquipmentReceiveBenefitsRecord::getRealOrderId, orderId))).orElse(new ArrayList<>());
 		benefitsRecords.forEach(benefitsRecord -> {
 			//扣除领取的权益
-			Long benefitsRecordId = benefitsRecord.getId();
 			deductReceivedBenefits(benefitsRecord.getUserId(), benefitsRecord.getTicketOrderId(), benefitsRecord.getRelationId(), benefitsRecord.getMonths());
 			benefitsRecord.setStatusCode(0);
 			receiveBenefitsRecordMapper.updateById(benefitsRecord);
@@ -111,6 +121,81 @@ public class UserRealOrderBenefitsImpl implements UserRealOrderBenefitsService {
 				.eq(UserPayEquipmentAvailableBenefits::getRealOrderId, orderId));
 	}
 
+	@Override
+	@Transactional(rollbackFor = Throwable.class)
+	public GroupsRelationView receiveRealGoodsBenefits(Long userId, Long benefitsId, Long goodsId, Long skuId, Long relationId) {
+		//可获取的权益是否存在
+		UserPayEquipmentAvailableBenefits availableBenefits = availableBenefitsMapper.selectById(benefitsId);
+		if (availableBenefits == null) {
+			throw BusinessRuntimeException.getInstance("可获取的权益不存在");
+		}
+		if (availableBenefits.getStatusCode() == 1) {
+			throw BusinessRuntimeException.getInstance("已领取该权益");
+		}
+		if (!availableBenefits.getDeleted()) {
+			throw BusinessRuntimeException.getInstance("购买的实物设备已退款,无法领取该权益");
+		}
+		if (!availableBenefits.getSkuId().equals(skuId)) {
+			throw BusinessRuntimeException.getInstance("可领取的车票权益规格错误");
+		}
+		GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder()
+				.field(GroupsRelationView::getGoodsId, goodsId)
+				.field(GroupsRelationView::getId, relationId)
+				.field(GroupsRelationView::getStatus, GroupsRelation.Status.validity.name())
+				.field(GroupsRelationView::getUserId, userId)
+				.build());
+		Optional.ofNullable(groupRelationClearService).ifPresentOrElse(ticket -> {
+			Date expiryTime = groupsRelationView.getExpiryTime();
+			if (expiryTime == null) {
+				throw BusinessRuntimeException.getInstance("该车位暂未发车,请发车后再领取权益");
+			}
+			GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(skuId);
+			if (goodsDonSku == null || !goodsDonSku.getGoodsId().equals(goodsId)) {
+				throw BusinessRuntimeException.getInstance("");
+			}
+			//删除可领取的权益
+			int update = availableBenefitsMapper.update(null, Wrappers.lambdaUpdate(UserPayEquipmentAvailableBenefits.class)
+					.set(UserPayEquipmentAvailableBenefits::getStatusCode, 1)
+					.set(UserPayEquipmentAvailableBenefits::getDeleted, false)
+					.eq(UserPayEquipmentAvailableBenefits::getDeleted, true)
+					.eq(UserPayEquipmentAvailableBenefits::getId, benefitsId));
+			if (update != 1) {
+				throw BusinessRuntimeException.getInstance("系统错误,请刷新页面重试");
+			}
+			DateTime updateExpiryTime = DateUtil.offset(expiryTime, DateField.MONTH, goodsDonSku.getMonths());
+			updateExpiryTime = DateUtil.offsetDay(updateExpiryTime, 3);
+			groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
+					.eq(GroupsRelation::getId, groupsRelationView.getId())
+					.eq(GroupsRelation::getUserId, userId)
+					.set(GroupsRelation::getExpiryTime, updateExpiryTime));
+			groupsRelationView.setUpdateExpiryTime(updateExpiryTime);
+			//保存领取权益
+			saveReceiveBenefitsRecord(userId, skuId, availableBenefits.getRealOrderId(), null, relationId, goodsDonSku.getMonths(), 1);
+		}, () -> {
+			throw BusinessRuntimeException.getInstance("对应规格车票不存在");
+		});
+		return groupsRelationView;
+	}
+
+	@Override
+	public List<UserAvailableGoodsTicketView> getAvailableBenefitsTickets(Long userId, Long orderId) {
+		List<UserAvailableGoodsTicketView> ticketViews = beanSearcher.searchAll(UserAvailableGoodsTicketView.class, MapUtils.builder()
+				.field(UserAvailableGoodsTicketView::getUserId, userId)
+				.field(UserAvailableGoodsTicketView::getDeleted, true)
+				.field(UserAvailableGoodsTicketView::getRealOrderId, orderId)
+				.build());
+		ticketViews.forEach(ticket -> {
+			List<GroupsRelationView> relationViewList = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
+					.field(GroupsRelationView::getUserId, userId)
+					.field(GroupsRelationView::getGoodsId, ticket.getGoodsId())
+					.field(GroupsRelationView::getStatus, GroupsRelation.Status.validity.name())
+					.field(GroupsRelationView::getExpiryTime).op(Operator.NotNull)
+					.build());
+			ticket.setTicketList(relationViewList);
+		});
+		return ticketViews;
+	}
+
 	/**
 	 * 保存获取权益记录
 	 */
@@ -157,6 +242,7 @@ public class UserRealOrderBenefitsImpl implements UserRealOrderBenefitsService {
 		} else {
 			DateTime now = DateTime.now();
 			Date finalDate = DateUtil.offset(expiryTime, DateField.MONTH, -months);
+			finalDate = DateUtil.offsetDay(finalDate, -3);
 			if (now.isAfter(finalDate)) {
 				//过期 直接清除车票
 				groupRelationClearService.clearTicket(relation);

+ 3 - 0
netflix-service/src/main/java/com/cyksj/service/relation/GroupRelationFrontService.java

@@ -1,5 +1,6 @@
 package com.cyksj.service.relation;
 
+import com.cyksj.model.entity.GroupsRelation;
 import com.cyksj.model.views.RenewalView;
 
 import java.util.List;
@@ -14,4 +15,6 @@ public interface GroupRelationFrontService {
 	List<RenewalView> getMyTicket(long userId, Boolean isLoginPopularize);
 
 	Boolean isJoinCorpWx(Long userId, Boolean isJoin, Boolean noCoupon);
+
+	GroupsRelation getSimilarExpiredGroupRelation(Long skuId, Integer months);
 }

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationClearServiceImpl.java

@@ -60,6 +60,8 @@ public class GroupRelationClearServiceImpl implements GroupRelationClearService
 						MapUtils.builder().field(GroupsRelationView::getId, relationId).build());
 				if (groupsTrips != null) {
 					UserTicketClearedRecord userTicketClearedRecord = new UserTicketClearedRecord();
+					userTicketClearedRecord.setAccountId(groupsTrips.getAccountId());
+					userTicketClearedRecord.setAccount(groupsTrips.getTripsAccount());
 					userTicketClearedRecord.setRelationId(relationId);
 					userTicketClearedRecord.setUserId(userId);
 					userTicketClearedRecord.setGoodsId(groupsTrips.getGoodsId());

+ 21 - 0
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java

@@ -1,11 +1,13 @@
 package com.cyksj.service.relation.impl;
 
 import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.enums.GatewayApiCode;
+import com.cyksj.mapper.GroupsRelationMapper;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.corp.CorpUserMapper;
 import com.cyksj.mapper.market.task.UserBindPhoneMapper;
@@ -44,6 +46,8 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 
 	private final CouponCommonService couponCommonService;
 
+	private final GroupsRelationMapper groupsRelationMapper;
+
 	@Override
 	public List<RenewalView> getMyTicket(long userId, Boolean isLoginPopularize) {
 		User u = userMapper.selectById(userId);
@@ -127,4 +131,21 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 		}
 		return true;
 	}
+
+	@Override
+	public GroupsRelation getSimilarExpiredGroupRelation(Long skuId, Integer months) {
+		DateTime expiryTime = DateUtil.offsetMonth(DateTime.now(), months);
+		DateTime minExpiryTime = DateUtil.offsetDay(expiryTime, -5);
+		Long groupsId = groupsRelationMapper.selectSimilarExpiredRelation(skuId, minExpiryTime);
+		if (groupsId == null) {
+			return null;
+		}
+		GroupsRelation relation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
+				.eq(GroupsRelation::getGroupsId, groupsId)
+				.eq(GroupsRelation::getStatus, GroupsRelation.Status.none)
+				.eq(GroupsRelation::getUserId, 0)
+				.orderByAsc(GroupsRelation::getNum)
+				.last("limit 1"));
+		return relation;
+	}
 }

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/template/TemplateCommonService.java

@@ -29,7 +29,7 @@ public interface TemplateCommonService {
 	/**
 	 * 发货通知模板消息
 	 */
-	void sendTransportMsgNotify(OrderDon orderDon, ReqSetLogisticsPost reqSetLogisticsPost) throws Exception;
+	void sendTransportMsgNotify(OrderDon orderDon, ReqSetLogisticsPost reqSetLogisticsPost, Boolean isReceiveAll) throws Exception;
 
 	/**
 	 * 空车位通知模板

+ 5 - 4
netflix-service/src/main/java/com/cyksj/service/template/impl/TemplateCommonServiceImpl.java

@@ -124,7 +124,7 @@ public class TemplateCommonServiceImpl implements TemplateCommonService {
 	}
 
 	@Override
-	public void sendTransportMsgNotify(OrderDon orderDon, ReqSetLogisticsPost reqSetLogisticsPost) throws Exception {
+	public void sendTransportMsgNotify(OrderDon orderDon, ReqSetLogisticsPost reqSetLogisticsPost, Boolean isReceiveAll) throws Exception {
 		if (!EnvCommonService.active.equals(envCommonService.getEnv())) {
 			Long userId = orderDon.getUserId();
 			WxAppTemplateView wxAppTemplateView = this.getWxAppByUserId(userId, TemplateEnum.ORDER_TRANSPORT_TEMPLATE.getDesc());
@@ -137,11 +137,12 @@ public class TemplateCommonServiceImpl implements TemplateCommonService {
 					}
 					openId = u.getOpenId();
 				}
+				String url = String.format("%s%s", envCommonService.getDomain(), "order");
 				WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
 						.setToUser(openId)
 						.setTemplateId(wxAppTemplateView.getTemplateId())
-						//TODO
-						.setUrl(" ");
+						.setUrl(url);
+				String msg = isReceiveAll ? "家庭套餐特权已生效,可在我的车票中查看" : "存在待领取权益,点击查看详情";
 				GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId());
 				OrderDonTransport transport = transportMapper.selectOne(Wrappers.lambdaQuery(OrderDonTransport.class).eq(OrderDonTransport::getOrderId, reqSetLogisticsPost.getOrderId()).last("limit 1"));
 				WxMpTemplateMessage.TemplateData data = templateMessage.getData();
@@ -151,7 +152,7 @@ public class TemplateCommonServiceImpl implements TemplateCommonService {
 				data.setKeyword3(new WxMpTemplateData(reqSetLogisticsPost.getCodeCn()));
 				data.setKeyword4(new WxMpTemplateData(reqSetLogisticsPost.getTrackingNumber()));
 				data.setKeyword5(new WxMpTemplateData(String.format("%s%s%s%s", transport.getProvince(), transport.getCity(), transport.getDistrict(), transport.getAddress())));
-				data.setRemark(new WxMpTemplateData("可复制运单编号查询物流信息"));
+				data.setRemark(new WxMpTemplateData(String.format("可复制运单编号查询物流信息\n%s", msg)));
 				weChatService.sendTemplateMessage(weChatService.getAccessToken(wxAppTemplateView.getAppId()), Jsons.toJson(templateMessage));
 			}
 		}

+ 26 - 22
netflix-service/src/main/java/com/cyksj/task/StatisticsDataScheduler.java

@@ -55,10 +55,6 @@ public class StatisticsDataScheduler {
 
 	private final static String APPLE_ONE = "Apple One";
 
-	public static List<String> payType = List.of("月", "季", "年");
-
-	private final static List<String> registerAccount = List.of("apple", "spotify", "google");
-
 	private final GoodsDonMapper goodsDonMapper;
 
 	private final RealGoodsDataMapper realGoodsDataMapper;
@@ -163,7 +159,7 @@ public class StatisticsDataScheduler {
 	 */
 	public List<RegisterAccountData> statisticsRegisterAccountData(Date yesZeroDate, Date thisZeroDate, Boolean today) {
 		List<RegisterAccountData> list = new ArrayList<>();
-		registerAccount.forEach(platform -> {
+		Constant.registerAccount.forEach(platform -> {
 			RegisterAccountData entity = Optional.ofNullable(registerOrderDonMapper.registerAccountDataEveryDay(yesZeroDate, thisZeroDate, platform)).orElse(new RegisterAccountData());
 			entity.setPlatform(platform);
 			RegisterAccountData dto = Optional.ofNullable(registerOrderDonMapper.selectRefundOrderDetail(yesZeroDate, thisZeroDate, platform)).orElse(new RegisterAccountData());
@@ -188,20 +184,7 @@ public class StatisticsDataScheduler {
 	 * @return
 	 */
 	public List<AppleOneData> statisticsAppleOneData(Date yesZeroDate, Date thisZeroDate, Boolean today) {
-		GoodsDon goodsDon = goodsDonMapper.selectOne(Wrappers.lambdaQuery(GoodsDon.class).eq(GoodsDon::getTitle, APPLE_ONE).last("limit 1"));
-		List<GoodsDonSku> list = goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class).eq(GoodsDonSku::getGoodsId, goodsDon.getId()).select(GoodsDonSku::getId, GoodsDonSku::getSpecVal));
-		Set<String> area = new HashSet<>();
-		list.forEach(sku -> {
-			String areaName = sku.getSpecVal().substring(0, sku.getSpecVal().indexOf("区") + 1);
-			if (!area.contains(areaName)) {
-				area.add(areaName);
-			}
-		});
-		Map<String, List<GoodsDonSku>> areaDataMap = new HashMap<>();
-		for (String name : area) {
-			List<GoodsDonSku> sku = Optional.ofNullable(goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class).like(GoodsDonSku::getSpecVal, name).select(GoodsDonSku::getId, GoodsDonSku::getGoodsId))).orElse(new ArrayList<>());
-			areaDataMap.put(name, sku);
-		}
+		Map<String, List<GoodsDonSku>> areaDataMap = getAppleOneMap();
 
 		List<AbstractBackData> appleOneSave = new ArrayList<>();
 		List<AppleOneData> appleOneData = new ArrayList<>();
@@ -369,11 +352,11 @@ public class StatisticsDataScheduler {
 			List<GoodsDonSku> goodsDonSkus = Optional.ofNullable(goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class).in(GoodsDonSku::getId, skuIdMaps.keySet()))).orElse(new ArrayList<>());
 			for (GoodsDonSku donSkus : goodsDonSkus) {
 				int size = skuIdMaps.get(donSkus.getId()).size();
-				if (donSkus.getSpecVal().contains(payType.get(0)) && !donSkus.getSpecVal().contains(payType.get(2))) {
+				if (donSkus.getSpecVal().contains(Constant.payType.get(0)) && !donSkus.getSpecVal().contains(Constant.payType.get(2))) {
 					numOfMonthOrder += size;
-				} else if (donSkus.getSpecVal().contains(payType.get(1))) {
+				} else if (donSkus.getSpecVal().contains(Constant.payType.get(1))) {
 					numOfSeasonOrder += size;
-				} else if (donSkus.getSpecVal().contains(payType.get(2))) {
+				} else if (donSkus.getSpecVal().contains(Constant.payType.get(2))) {
 					numOfYearOrder += size;
 				}
 			}
@@ -385,4 +368,25 @@ public class StatisticsDataScheduler {
 		//年付
 		backData.setNumOfYearOrder(numOfYearOrder);
 	}
+
+	/**
+	 * 获取Apple区域map
+	 */
+	public Map<String, List<GoodsDonSku>> getAppleOneMap() {
+		GoodsDon goodsDon = goodsDonMapper.selectOne(Wrappers.lambdaQuery(GoodsDon.class).eq(GoodsDon::getTitle, APPLE_ONE).last("limit 1"));
+		List<GoodsDonSku> list = goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class).eq(GoodsDonSku::getGoodsId, goodsDon.getId()).select(GoodsDonSku::getId, GoodsDonSku::getSpecVal));
+		Set<String> area = new HashSet<>();
+		list.forEach(sku -> {
+			String areaName = sku.getSpecVal().substring(0, sku.getSpecVal().indexOf("区") + 1);
+			if (!area.contains(areaName)) {
+				area.add(areaName);
+			}
+		});
+		Map<String, List<GoodsDonSku>> areaDataMap = new HashMap<>();
+		for (String name : area) {
+			List<GoodsDonSku> sku = Optional.ofNullable(goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class).like(GoodsDonSku::getSpecVal, name).select(GoodsDonSku::getId, GoodsDonSku::getGoodsId))).orElse(new ArrayList<>());
+			areaDataMap.put(name, sku);
+		}
+		return areaDataMap;
+	}
 }

+ 207 - 0
netflix-web/src/main/java/com/cyksj/aspect/LogAspect.java

@@ -0,0 +1,207 @@
+package com.cyksj.aspect;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.servlet.ServletUtil;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.cyksj.common.annotation.Log;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.enums.BusinessStatus;
+import com.cyksj.mapper.manage.cms.SysLogMapper;
+import com.cyksj.model.entity.CmsUser;
+import com.cyksj.model.entity.SysLog;
+import com.cyksj.service.mange.cms.CmsUserManager;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.http.HttpMethod;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.servlet.HandlerMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Map;
+
+/*
+ *项目名: yicang-admin
+ *文件名: LogAspect
+ *创建者: JavaZou
+ *创建时间:2022/9/30 10:55
+ */
+@Aspect
+@Component
+@Slf4j
+@RequiredArgsConstructor
+public class LogAspect {
+	private final HttpServletRequest request;
+
+	private final CmsUserManager cmsUserManager;
+
+	private final SysLogMapper sysLogManager;
+
+	/**
+	 * 处理后完成
+	 * 切入点
+	 */
+	@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
+	public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {
+		handleLog(joinPoint, controllerLog, null, jsonResult);
+	}
+
+	/**
+	 * 异常处理
+	 * 切入
+	 */
+	@AfterThrowing(pointcut = "@annotation(controllerLog)", throwing = "e")
+	public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {
+		handleLog(joinPoint, controllerLog, e, null);
+	}
+
+	private void handleLog(JoinPoint joinPoint, Log controllerLog, Exception e, Object jsonResult) {
+		try {
+			// 获取当前的用户
+			CmsUser cmsUser = cmsUserManager.getUser(StpUtil.getLoginIdAsLong());
+			SysLog sysLog = new SysLog();
+			sysLog.setOperateIp(ServletUtil.getClientIP(request));
+			sysLog.setOperateUrl(request.getRequestURI());
+			sysLog.setStatus(BusinessStatus.SUCCESS.ordinal());
+			sysLog.setOperateTime(DateTime.now().toString());
+			//操作人
+			if (cmsUser != null) {
+				sysLog.setOperator(cmsUser.getNickname());
+				sysLog.setAccount(cmsUser.getPhone());
+			}
+			if (e != null) {
+				sysLog.setStatus(BusinessStatus.FAIL.ordinal());
+				sysLog.setErrMsg(StrUtil.subSufByLength(e.getMessage(), 2000));
+			}
+			// 设置方法名称
+			String className = joinPoint.getTarget().getClass().getName();
+			String methodName = joinPoint.getSignature().getName();
+			sysLog.setMethod(String.format("%s.%s", className, methodName));
+			// 处理设置注解上的参数
+			getControllerMethodDescription(joinPoint, controllerLog, sysLog, jsonResult);
+			//请求方式
+			sysLog.setRequestMethod(request.getMethod());
+			sysLog.setOperateLocation(getRealAddressByIP(sysLog.getOperateIp()));
+			sysLogManager.insert(sysLog);
+		} catch (Exception exp) {
+			// 记录本地异常日志
+			log.error("==前置通知异常==");
+			log.error("异常信息:{}", exp.getMessage());
+		}
+	}
+
+	private void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysLog sysLog, Object jsonResult) throws Exception {
+		sysLog.setModule(log.module());
+		sysLog.setBusinessType(log.businessType().ordinal());
+		// 是否需要保存request,参数和值
+		if (log.isSaveRequestData()) {
+			// 获取参数的信息,传入到数据库中。
+			setRequestValue(joinPoint, sysLog, log);
+		}
+		// 是否需要保存response,参数和值
+		if (log.isSaveResponseData() && jsonResult != null) {
+			sysLog.setJsonResult(StrUtil.subSufByLength(Jsons.toJson(jsonResult), 2000));
+		}
+	}
+
+	/**
+	 * 请求入参
+	 */
+	private void setRequestValue(JoinPoint joinPoint, SysLog sysLog, Log log) throws Exception {
+		String requestMethod = log.businessType().name();
+		if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
+			String params = argsArrayToString(joinPoint.getArgs());
+			sysLog.setOperateParams(StrUtil.subSufByLength(params, 2000));
+		} else {
+			Map<Object, Object> paramsMap = (Map<Object, Object>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
+			if (paramsMap.size() == 0) {
+				Enumeration<String> parameterNames = request.getParameterNames();
+				while (parameterNames.hasMoreElements()) {
+					String key = parameterNames.nextElement();
+					String value = request.getParameter(key);
+					paramsMap.put(key, value);
+				}
+			}
+			sysLog.setOperateParams(StrUtil.subSufByLength(paramsMap.toString(), 2000));
+		}
+	}
+
+	/**
+	 * 参数拼装
+	 */
+	private String argsArrayToString(Object[] paramsArray) {
+		String params = "";
+		if (paramsArray != null && paramsArray.length > 0) {
+			for (Object o : paramsArray) {
+				if (o != null && !isFilterObject(o)) {
+					try {
+						Object jsonObj = Jsons.toJson(o);
+						params += jsonObj.toString() + " ";
+					} catch (Exception e) {
+					}
+				}
+			}
+		}
+		return params.trim();
+	}
+
+	/**
+	 * 判断是否需要过滤的对象。
+	 *
+	 * @param o 对象信息。
+	 * @return 如果是需要过滤的对象,则返回true;否则返回false。
+	 */
+	@SuppressWarnings("rawtypes")
+	public boolean isFilterObject(final Object o) {
+		Class<?> clazz = o.getClass();
+		if (clazz.isArray()) {
+			return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
+		} else if (Collection.class.isAssignableFrom(clazz)) {
+			Collection collection = (Collection) o;
+			for (Object value : collection) {
+				return value instanceof MultipartFile;
+			}
+		} else if (Map.class.isAssignableFrom(clazz)) {
+			Map map = (Map) o;
+			for (Object value : map.entrySet()) {
+				Map.Entry entry = (Map.Entry) value;
+				return entry.getValue() instanceof MultipartFile;
+			}
+		}
+		return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
+				|| o instanceof BindingResult;
+	}
+
+	public String getRealAddressByIP(String ip) {
+		if (StrUtil.isBlank(ip)) {
+			return "unknown";
+		}
+		try {
+			String rspStr = HttpUtil.get("http://whois.pconline.com.cn/ipJson.jsp?ip=" + ip + "&json=true");
+			if (StrUtil.isEmpty(rspStr)) {
+				log.error("获取地理位置异常 {}", ip);
+				return "unknown";
+			}
+			JSONObject obj = JSONUtil.parseObj(rspStr);
+			String region = obj.getStr("pro");
+			String city = obj.getStr("city");
+			return String.format("%s %s", region, city);
+		} catch (Exception e) {
+			log.error("获取地理位置异常 {}", ip);
+		}
+
+		return "unknown";
+	}
+}

+ 40 - 35
netflix-web/src/main/java/com/cyksj/config/SaTokenConfigure.java

@@ -1,35 +1,40 @@
-//package com.cyksj.config;
-//
-//import cn.dev33.satoken.interceptor.SaRouteInterceptor;
-//import org.springframework.context.annotation.Configuration;
-//import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-//
-//import java.util.List;
-//
-///*
-// *项目名: yicang-admin
-// *文件名: SaTokenConfigure
-// *创建者: JavaZou
-// *创建时间:2022/12/19 10:01
-// */
-//@Configuration
-//public class SaTokenConfigure implements WebMvcConfigurer {
-//	// 注册拦截器
-//	@Override
-//	public void addInterceptors(InterceptorRegistry registry) {
-//		registry.addInterceptor(new SaRouteInterceptor())
-//				.addPathPatterns(List.of("/manage/**", "/manager/**", "/sys/update", "/sys/delete/**"))
-//				.excludePathPatterns(List.of("/manage/admin/login",
-//						"/manage/admin/get/loginInfo",
-//						"/manage/corp/**",
-//						"/manage/coupon/corp/send",
-//						"/manage/coupon",
-//						"/manage/register/wx/refund/notify",
-//						"/manage/register/unLimit",
-//						"/manage/gzh/msg/notify",
-//						"/manage/admin/send/template",
-//						"/manage/order/put/status/*"));
-//	}
-//}
-//
+package com.cyksj.config;
+
+import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
+import cn.dev33.satoken.interceptor.SaRouteInterceptor;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.util.List;
+
+/*
+ *项目名: yicang-admin
+ *文件名: SaTokenConfigure
+ *创建者: JavaZou
+ *创建时间:2022/12/19 10:01
+ */
+@Configuration
+public class SaTokenConfigure implements WebMvcConfigurer {
+	// 注册拦截器
+	@Override
+	public void addInterceptors(InterceptorRegistry registry) {
+		registry.addInterceptor(new SaRouteInterceptor())
+				.addPathPatterns(List.of("/manage/**", "/manager/**", "/sys/update", "/sys/delete/**"))
+				.excludePathPatterns(List.of("/manage/admin/login",
+						"/manage/admin/get/loginInfo",
+						"/manage/corp/**",
+						"/manage/coupon/corp/send",
+						"/manage/coupon",
+						"/manage/register/wx/refund/notify",
+						"/manage/register/unLimit",
+						"/manage/gzh/msg/notify",
+						"/manage/admin/send/template",
+						"/manage/order/put/status/*",
+						"/manage/user/get/loginInfo",
+						"/manage/user/login"));
+		//注解权限校验
+		registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**");
+	}
+}
+

+ 10 - 0
netflix-web/src/main/java/com/cyksj/web/GlobalExceptionHandler.java

@@ -1,6 +1,8 @@
 package com.cyksj.web;
 
 import cn.dev33.satoken.exception.NotLoginException;
+import cn.dev33.satoken.exception.NotPermissionException;
+import cn.dev33.satoken.exception.NotRoleException;
 import cn.hutool.core.lang.Validator;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.StringUtil;
@@ -73,6 +75,14 @@ public class GlobalExceptionHandler {
             } else {
                 apiCode = GatewayApiCode.CMS_USER_NO_LOGIN;
             }
+        } else if (e instanceof NotRoleException) {
+            // 如果是角色异常
+            NotRoleException ee = (NotRoleException) e;
+            apiCode = GatewayApiCode.CMS_USER_NO_ROLE;
+        } else if (e instanceof NotPermissionException) {
+            // 如果是权限异常
+            NotPermissionException ee = (NotPermissionException) e;
+            apiCode = GatewayApiCode.CMS_USER_NO_PERMISSION;
         }
         log.error("全局错误处理: \n Cause: {} \n Value: {}", message, value);
         if (apiCode != null) {

+ 28 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java

@@ -1,13 +1,16 @@
 package com.cyksj.web.controller.manage;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.excel.support.ExcelTypeEnum;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.annotation.Log;
 import com.cyksj.common.annotation.NoSubmit;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.StringUtil;
 import com.cyksj.dto.Result;
+import com.cyksj.enums.BusinessType;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.OrderCommentMapper;
 import com.cyksj.mapper.RealGoodsInterestUserMapper;
@@ -15,6 +18,7 @@ import com.cyksj.mapper.manage.RealGoodsOrderHandleMapper;
 import com.cyksj.mapper.manage.coupon.CouponMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.excel.ExcelOrderDonData;
+import com.cyksj.model.excel.ExcelRealGoodsOrderData;
 import com.cyksj.model.excel.ExcelRealGoodsUserInterestData;
 import com.cyksj.model.excel.ExcelRealGoodsUserInterestHasPaymentData;
 import com.cyksj.model.manage.request.ReqSetLogisticsPost;
@@ -75,6 +79,7 @@ public class CmsOrderController {
 
 
     @GetMapping("/get")
+    @SaCheckPermission("order:view")
     public Result<SearchResult<OrderDonView>> get() {
         SearchResult<OrderDonView> search = beanSearcher.search(OrderDonView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
         search.getDataList().forEach(data -> {
@@ -101,6 +106,8 @@ public class CmsOrderController {
 	 * 订单导出
 	 */
 	@GetMapping("/export")
+	@SaCheckPermission("order:export")
+	@Log(module = "订单管理/导出订单", businessType = BusinessType.EXPORT, isSaveRequestData = true)
 	public void exportOrders(HttpServletResponse response) {
 		List<ExcelOrderDonData> list = beanSearcher.searchAll(ExcelOrderDonData.class, MapUtils.flatBuilder(request.getParameterMap()).build());
 		list.forEach(data -> {
@@ -135,6 +142,25 @@ public class CmsOrderController {
 		EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelOrderDonData.class, list, "订单列表", "订单列表", ExcelTypeEnum.XLSX, null);
 	}
 
+	/**
+	 * 导出实物模板 订单excel
+	 */
+	@GetMapping("/export/realGoods")
+	public void exportRealGoods(HttpServletResponse response) {
+		List<ExcelRealGoodsOrderData> list = beanSearcher.searchAll(ExcelRealGoodsOrderData.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(ExcelOrderDonData::getGoodsDonType, Constant.realGoodsType).op(Operator.InList)
+				.build());
+		list.forEach(data -> {
+			data.setPayType("寄付现结");
+			if (data.getGoodsDonType() == Constant.realGoodsType.get(0)) {
+				data.setRealGoodName("路由器");
+			} else if (data.getGoodsDonType() == Constant.realGoodsType.get(1)) {
+				data.setRealGoodName("银河潮玩");
+			}
+		});
+		EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelRealGoodsOrderData.class, list, "实物订单列表", "实物订单列表", ExcelTypeEnum.XLSX, null);
+	}
+
 	@PutMapping("/update/status")
     public Result<String> upStatus(@RequestBody OrderDon orderDon){
         cmsOrderDonService.update(Wrappers.lambdaUpdate(OrderDon.class).eq(OrderDon::getId,orderDon.getId()).set(OrderDon::getStatus,orderDon.getStatus()));
@@ -172,6 +198,7 @@ public class CmsOrderController {
 	 * 用户购买实物商品意愿列表
 	 */
 	@GetMapping("/get/realGooods/interest/users")
+	@SaCheckPermission("interest:view")
 	public Result<SearchResult> getInterestUserList(RealGoodsInterestUser.Status interestStatus, HttpServletRequest request) {
 		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
 		SearchResult<RealGoodsInterestUserView> search;
@@ -272,6 +299,7 @@ public class CmsOrderController {
      */
     @PostMapping("/put/realGoods/service")
     @NoSubmit
+    @Log(module = "订单管理/售前、售后客服", businessType = BusinessType.PUT, isSaveRequestData = true)
     public Result<String> putRealGoodsService(@RequestBody @Validated RealGoodsServiceReq request) {
         OrderDon orderDon = cmsOrderDonService.getById(request.getOrderId());
         if (orderDon == null || orderDon.getRelationId() != 0) {

+ 2 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsUserController.java

@@ -1,5 +1,6 @@
 package com.cyksj.web.controller.manage;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
@@ -42,6 +43,7 @@ public class CmsUserController{
 
 
     @GetMapping("/get")
+    @SaCheckPermission("user:view")
     public Result<SearchResult<UserView>> get(){
         SearchResult<UserView> search = beanSearcher.search(UserView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
         search.getDataList().forEach((userView)->{

+ 159 - 5
netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java

@@ -1,5 +1,6 @@
 package com.cyksj.web.controller.manage.account;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
@@ -8,20 +9,26 @@ import com.alibaba.excel.context.AnalysisContext;
 import com.alibaba.excel.event.AnalysisEventListener;
 import com.alibaba.excel.support.ExcelTypeEnum;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.annotation.Log;
 import com.cyksj.common.annotation.NoSubmit;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.dto.Result;
+import com.cyksj.enums.BusinessType;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.GroupsMapper;
 import com.cyksj.mapper.HomeGroupMapper;
-import com.cyksj.model.entity.Account;
-import com.cyksj.model.entity.GroupsTrips;
-import com.cyksj.model.entity.HomeGroup;
+import com.cyksj.mapper.UserTicketClearedRecordMapper;
+import com.cyksj.model.entity.*;
 import com.cyksj.model.excel.ExcelAccountTemplateData;
+import com.cyksj.model.excel.ExcelImportAccountData;
 import com.cyksj.model.excel.ExcelManageAccountData;
 import com.cyksj.model.manage.request.ReqAccountIncrExpiryTime;
 import com.cyksj.model.manage.views.AccountView;
+import com.cyksj.model.manage.views.GroupsRelationView;
+import com.cyksj.model.views.GoodsDonSkuView;
+import com.cyksj.model.views.UserTicketClearedRecordView;
 import com.cyksj.service.mange.CmsAccountService;
+import com.cyksj.service.mange.CmsGroupService;
 import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.web.util.EasyExcelUtils;
 import com.ejlchina.searcher.BeanSearcher;
@@ -33,12 +40,15 @@ import lombok.RequiredArgsConstructor;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * @author chan
@@ -62,7 +72,12 @@ public class CmsAccountController {
 
 	private final TemplateCommonService templateCommonService;
 
+	private final CmsGroupService cmsGroupService;
+
+	private final UserTicketClearedRecordMapper userTicketClearedRecordMapper;
+
     @GetMapping("/get")
+    @SaCheckPermission("account:view")
     public Result<SearchResult<AccountView>> get(Long userId ,String nickName ,String submitAccount ,String expiryStartTime, String expiryEndTime) {
         MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
         if (StrUtil.isNotEmpty(expiryStartTime) || StrUtil.isNotEmpty(expiryEndTime)) {
@@ -96,6 +111,8 @@ public class CmsAccountController {
      * 导出账号
      */
     @GetMapping("/export/account")
+    @SaCheckPermission("account:export")
+    @Log(module = "平台管理/导出账号", businessType = BusinessType.EXPORT, isSaveRequestData = true)
     public void exportAccount(Long userId, String nickName, String submitAccount, String expiryStartTime, String expiryEndTime, HttpServletResponse response) {
         MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
         if (StrUtil.isNotEmpty(expiryStartTime) || StrUtil.isNotEmpty(expiryEndTime)) {
@@ -120,6 +137,7 @@ public class CmsAccountController {
      * 下载导入模板
      */
     @GetMapping("/get/account/template")
+    @SaCheckPermission("account:batchUpdatePwd")
     public void getAccountTemplate(HttpServletResponse response) {
         EasyExcelUtils.createTemplateExcel(response, ExcelAccountTemplateData.class, "账号导入模板", "账号导入模板", ExcelTypeEnum.XLSX, null);
     }
@@ -151,6 +169,10 @@ public class CmsAccountController {
 						}
 						if (flag) {
 							accountService.updateById(account);
+							//清空过期账号 逻辑删除
+							userTicketClearedRecordMapper.update(null, Wrappers.lambdaUpdate(UserTicketClearedRecord.class)
+									.set(UserTicketClearedRecord::getDeleted, false)
+									.eq(UserTicketClearedRecord::getAccountId, account.getId()));
 						}
 					}
 				}
@@ -166,6 +188,9 @@ public class CmsAccountController {
 
     @PostMapping("/post")
     @NoSubmit
+    @Transactional(rollbackFor = Throwable.class)
+    @SaCheckPermission("account:add")
+    @Log(module = "平台管理/新增账号", businessType = BusinessType.POST, isSaveRequestData = true)
     public Result<String> add(@RequestBody Account account){
 		account.setAccount(account.getAccount().trim());
 		account.setPassword(account.getPassword().trim());
@@ -179,10 +204,78 @@ public class CmsAccountController {
 		    }
 	    }
         accountService.save(account);
+	    //自动配置车队
+	    GroupsTrips groupsTrips = new GroupsTrips();
+	    groupsTrips.setSkuId(account.getSkuId());
+	    groupsTrips.setAccountId(account.getId());
+	    cmsGroupService.issuance(groupsTrips);
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
 
+	/**
+	 * 获取导入账号模板
+	 */
+	@GetMapping("/get/account/import/template")
+	public void getImportAccountTemplate(HttpServletResponse response) {
+		EasyExcelUtils.createTemplateExcel(response, ExcelImportAccountData.class, "导入账号模板", "导入账号模板", ExcelTypeEnum.XLSX, null);
+	}
+
+	/**
+	 * 导入账号
+	 */
+	@PostMapping("/import/account/issuance")
+	public Result<String> importAccountAndIssuance(Long goodsId, Long skuId, MultipartFile file) throws Exception {
+		GoodsDonSkuView goodsDonSkuView = beanSearcher.searchFirst(GoodsDonSkuView.class, MapUtils.builder().field(GoodsDonSkuView::getGoodsId, goodsId).field(GoodsDonSkuView::getSkuId, skuId).build());
+		if (goodsDonSkuView == null) {
+			throw BusinessRuntimeException.getInstance("所选平台与规格不匹配");
+		}
+		EasyExcel.read(file.getInputStream(), ExcelImportAccountData.class, new AnalysisEventListener<ExcelImportAccountData>() {
+			@SneakyThrows
+			@Override
+			public void invoke(ExcelImportAccountData data, AnalysisContext analysisContext) {
+				String account = data.getAccount(), password = data.getPassword(), startTime = data.getStartTime(), expiryTime = data.getExpiryTime();
+				if (StrUtil.isNotBlank(data.getAccount())) {
+					//账号是否已经添加过
+					if (!account.contains("客服")) {
+						int count = accountService.count(Wrappers.lambdaQuery(Account.class)
+								.eq(Account::getAccount, account)
+								.eq(Account::getGoodsId, goodsId));
+						if (count > 0) {
+							log.info("该平台下:{}已生成该账号:{}", goodsId, account);
+							return;
+						}
+					}
+					Account at = new Account();
+					at.setAccount(account.trim());
+					at.setPassword(password.trim());
+					at.setGoodsId(goodsId);
+					at.setSkuId(skuId);
+					if (StrUtil.isNotBlank(startTime)) {
+						at.setStartTime(DateUtil.parse(startTime, "yyyy-MM-dd HH:mm:ss"));
+					}
+					if (StrUtil.isNotBlank(expiryTime)) {
+						at.setExpiryTime(DateUtil.parse(expiryTime, "yyyy-MM-dd HH:mm:ss"));
+					}
+					accountService.save(at);
+					//自动配置车队
+					GroupsTrips groupsTrips = new GroupsTrips();
+					groupsTrips.setSkuId(at.getSkuId());
+					groupsTrips.setAccountId(at.getId());
+					cmsGroupService.issuance(groupsTrips);
+				}
+			}
+
+			@Override
+			public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+
+			}
+		}).sheet().doRead();
+		return GatewayResponse.SUCCESS.newBuilder().toResult("导入账号成功");
+	}
+
     @PutMapping("/update")
+    @SaCheckPermission("account:update")
+    @Log(module = "平台管理/编辑账号", businessType = BusinessType.PUT, isSaveRequestData = true)
     public Result<String> update(@RequestBody Account account){
 		if (StrUtil.isNotBlank(account.getAccount())){
 			account.setAccount(account.getAccount().trim());
@@ -194,8 +287,57 @@ public class CmsAccountController {
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
 
-    @DeleteMapping("/delete/{id}")
-    public Result<String> update(@PathVariable Long id){
+	/**
+	 * 修改密码并发送模板消息
+	 */
+	@PutMapping("/update/pwd")
+	@Log(module = "平台管理/批量修改密码", businessType = BusinessType.PUT, isSaveRequestData = true)
+	public Result<String> updatePwdAndSendMsg(@RequestBody List<Account> accounts) throws Exception {
+		accounts.forEach(account -> {
+			Account db = accountService.getById(account.getId());
+			String updatePWd = account.getPassword().trim();
+			if (!db.getPassword().equals(updatePWd)) {
+				db.setPassword(updatePWd);
+				accountService.updateById(db);
+				//清空过期账号 逻辑删除
+				userTicketClearedRecordMapper.update(null, Wrappers.lambdaUpdate(UserTicketClearedRecord.class)
+						.set(UserTicketClearedRecord::getDeleted, false)
+						.eq(UserTicketClearedRecord::getAccountId, account.getId()));
+				//发放模板消息
+				try {
+					templateCommonService.sendAccountTemplateMsg(account);
+				} catch (Exception e) {
+					log.error("发送账号{}修改密码消息模板错误", account.getId());
+				}
+			}
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 账号已过期车票列表
+	 */
+	@GetMapping("/get/expired/ticket")
+	public Result<SearchResult<UserTicketClearedRecordView>> getUserHadExpiredTicket() {
+		SearchResult<UserTicketClearedRecordView> search = beanSearcher.search(UserTicketClearedRecordView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 账号未过期车票列表
+	 */
+	@GetMapping("/get/valid/ticket")
+	public Result<SearchResult<GroupsRelationView>> getValidTicket() {
+		SearchResult<GroupsRelationView> search = beanSearcher.search(GroupsRelationView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(GroupsRelationView::getStatus, GroupsRelation.Status.validity.name()).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+
+	@DeleteMapping("/delete/{id}")
+	@SaCheckPermission("account:delete")
+	@Log(module = "平台管理/删除账号", businessType = BusinessType.DELETE, isSaveRequestData = true)
+	public Result<String> update(@PathVariable Long id){
 	    //是否关联了车队
 	    Integer count = groupsMapper.selectCount(Wrappers.lambdaQuery(GroupsTrips.class).eq(GroupsTrips::getAccountId, id));
 	    if (count > 0) {
@@ -206,6 +348,7 @@ public class CmsAccountController {
     }
 
     @PutMapping("/update/expiryTime")
+    @SaCheckPermission("account:addExpiryTime")
     public Result<String> updateExpiryTime(@RequestBody ReqAccountIncrExpiryTime incrExpiryTime){
         incrExpiryTime.getAccounts().forEach((accountId)->{
             Account account = accountService.getById(accountId);
@@ -214,4 +357,15 @@ public class CmsAccountController {
         });
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
+
+	/**
+	 * 需要修改主账号密码的平台
+	 */
+	@GetMapping("/get/expired/platform")
+	public Result<String> getExpiredPlatform() {
+		List<AccountView> expiredAllAccount = accountService.getExpiredAllAccount();
+		Set<String> platFormSet = expiredAllAccount.stream().map(AccountView::getTitle).collect(Collectors.toSet());
+		String platForms = platFormSet.stream().collect(Collectors.joining("、"));
+		return GatewayResponse.SUCCESS.newBuilder().toResult(platForms);
+	}
 }

+ 2 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/channel/CmsChannelController.java

@@ -1,5 +1,6 @@
 package com.cyksj.web.controller.manage.channel;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
@@ -37,6 +38,7 @@ public class CmsChannelController {
     private final HttpServletRequest request;
 
     @GetMapping
+    @SaCheckPermission("channel:view")
     public Result<SearchResult<ChannelView>> get(String startTime, String endTime){
         String timeSql = StringUtils.EMPTY;
         if(StringUtils.isNotBlank(startTime)){

+ 2 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/channel/CmsChannelPopularizeController.java

@@ -1,5 +1,6 @@
 package com.cyksj.web.controller.manage.channel;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.dto.Result;
@@ -44,6 +45,7 @@ public class CmsChannelPopularizeController {
     private final OrderDonMapper orderDonMapper;
 
     @GetMapping
+    @SaCheckPermission("promotion:view")
     public Result<SearchResult<ChannelPopularizeView>> get(String startTime, String endTime){
         String timeSql = StringUtils.EMPTY;
         if(StringUtils.isNotBlank(startTime)){

+ 274 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/cms/CmsAdminUserController.java

@@ -0,0 +1,274 @@
+package com.cyksj.web.controller.manage.cms;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.lang.Validator;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.annotation.Log;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.Codec;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.BusinessType;
+import com.cyksj.enums.GatewayApiCode;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.PhoneCodeMapper;
+import com.cyksj.mapper.manage.cms.CmsUserMapper;
+import com.cyksj.model.entity.CmsUser;
+import com.cyksj.model.entity.PhoneCode;
+import com.cyksj.model.manage.dto.AdminInfo;
+import com.cyksj.model.request.CmsUserReq;
+import com.cyksj.model.views.CmsUserVO;
+import com.cyksj.service.mange.cms.CmsUserManager;
+import com.cyksj.service.mange.cms.manager.service.CacheService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: CmsAdminUserController
+ *创建者: JavaZou
+ *创建时间:2023/1/11 14:26
+ */
+@RestController
+@RequestMapping("/manage/user")
+@RequiredArgsConstructor
+@Slf4j
+public class CmsAdminUserController {
+	private final CmsUserMapper cmsUserMapper;
+
+	private final PhoneCodeMapper phoneCodeMapper;
+
+	private final CmsUserManager cmsUserManager;
+
+	private final CacheService cacheService;
+
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	@PostMapping(value = "/login")
+	public Result<String> login(@RequestBody CmsUser adminRequest) throws Exception {
+		CmsUser admin = cmsUserMapper.selectOne(
+				new QueryWrapper<CmsUser>().lambda().eq(CmsUser::getPhone,adminRequest.getPhone()).last("limit 1"));
+
+		if (null == admin) {
+			throw BusinessRuntimeException.getInstance("该用户不存在.");
+		}
+		if (null == admin.getStatus() || !admin.getStatus()) {
+			throw BusinessRuntimeException.getInstance("无登录权限.");
+		}
+
+		// 对比密码
+		String encodePasscode = Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.SHA256).setStringData(adminRequest.getPassword()).toBase64String();
+
+		if (!StringUtils.equals(admin.getPassword(), encodePasscode)) {
+			throw BusinessRuntimeException.getInstance("密码有误.");
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	@PostMapping("/post")
+	@Log(module = "用户管理/新增用户", businessType = BusinessType.POST, isSaveRequestData = true)
+	public Result<String> saveAdmin(@RequestBody @Validated CmsUserReq cmsUserReq) throws Exception {
+		Long adminId = StpUtil.getLoginIdAsLong();
+		CmsUser exist = cmsUserMapper.selectById(adminId);
+		if (exist == null) {
+			throw BusinessRuntimeException.getInstance("账号不存在,请重新登录");
+		}
+		CmsUser cmsUser = new CmsUser();
+		BeanUtil.copyProperties(cmsUserReq, cmsUser);
+		if (StringUtils.isNotBlank(cmsUserReq.getPassword())) {
+			cmsUser.setPassword(Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.SHA256).setStringData(cmsUserReq.getPassword()).toBase64String());
+		}
+		if (cmsUser.getId() == null) {
+			CmsUser ad = cmsUserMapper.selectOne(new LambdaQueryWrapper<CmsUser>().eq(CmsUser::getPhone, cmsUser.getPhone()).last("limit 1"));
+			if (ad != null) {
+				throw BusinessRuntimeException.getInstance("该账号已存在.");
+			}
+		}
+		boolean mobile = Validator.isMobile(cmsUser.getPhone());
+		if (!mobile) {
+			throw BusinessRuntimeException.getInstance("请输入正确的手机号");
+		}
+
+		try {
+			cmsUserMapper.insert(cmsUser);
+			//保存用户角色关系
+			cmsUserManager.saveUserRoleRelation(cmsUser.getId(), cmsUserReq.getRoleIds());
+		} catch (DuplicateKeyException e) {
+			throw BusinessRuntimeException.getInstance("手机号重复");
+		}
+
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 删除管理员
+	 */
+	@DeleteMapping("/delete/{id}")
+	@Log(module = "用户管理/删除用户", businessType = BusinessType.DELETE)
+	public Result<String> deleteAdminById(@PathVariable Long id) throws Exception {
+		Long adminId = StpUtil.getLoginIdAsLong();
+		CmsUser exist = cmsUserMapper.selectById(adminId);
+		if (exist == null) {
+			throw BusinessRuntimeException.getInstance("账号不存在,请重新登录");
+		}
+		if (id.equals(adminId)) {
+			throw BusinessRuntimeException.getInstance("无法删除自己");
+		}
+		//删除用户角色关联关系、缓存
+		cmsUserManager.delUserRoleRelation(exist);
+		cmsUserMapper.deleteById(id);
+		//删除用户,将上线的用户踢下
+		StpUtil.logoutByLoginId(id);
+		return GatewayResponse.SUCCESS.newBuilder().toResult("删除成功");
+	}
+
+	/**
+	 * 编辑管理员
+	 */
+	@PutMapping("/put")
+	@Log(module = "用户管理/编辑用户", businessType = BusinessType.PUT, isSaveRequestData = true)
+	public Result<String> editAdmin(@RequestBody CmsUserReq cmsUserReq) throws Exception {
+		Long adminId = StpUtil.getLoginIdAsLong();
+		CmsUser exist = cmsUserMapper.selectById(adminId);
+		if (exist == null) {
+			throw BusinessRuntimeException.getInstance("账号不存在,请重新登录");
+		}
+		CmsUser user = cmsUserMapper.selectById(cmsUserReq.getId());
+		if (cmsUserReq.getId() == null || user == null) {
+			throw BusinessRuntimeException.getInstance("账号不存在");
+		}
+		Boolean flag = false;
+		if (StrUtil.isNotEmpty(cmsUserReq.getPhone())) {
+			boolean mobile = Validator.isMobile(cmsUserReq.getPhone());
+			if (!mobile) {
+				throw BusinessRuntimeException.getInstance("请输入正确的手机号");
+			}
+			if (!cmsUserReq.getPhone().equals(user.getPhone())) {
+				flag = true;
+			}
+		}
+		if (StrUtil.isNotEmpty(cmsUserReq.getPassword())) {
+			String encodePwd = Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.SHA256).setStringData(cmsUserReq.getPassword()).toBase64String();
+			cmsUserReq.setPassword(encodePwd);
+			if (!encodePwd.equals(user.getPassword())) {
+				flag = true;
+				user.setPassword(encodePwd);
+			}
+		}
+		user.setNickname(cmsUserReq.getNickname());
+		if (StrUtil.isNotBlank(cmsUserReq.getRoleIds())) {
+			cmsUserManager.delUserRoleRelation(user);
+			cmsUserManager.saveUserRoleRelationAndCache(user, cmsUserReq.getRoleIds());
+		}
+		user.setModifiedBy(exist.getNickname());
+		cmsUserMapper.updateById(user);
+		if (flag) {
+			StpUtil.logoutByLoginId(cmsUserReq.getId());
+		}
+
+		return GatewayResponse.SUCCESS.newBuilder().toResult("编辑成功");
+	}
+
+	@PutMapping("/put/status/{id}")
+	public Result<String> updateUserStatus(@PathVariable("id") Integer id) {
+		if (id == null || id < 1) {
+			throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_USER_NO_FIND);
+		}
+		CmsUser cmsUser = cmsUserMapper.selectById(id);
+		if (cmsUser == null) {
+			throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_USER_NO_FIND);
+		}
+		cmsUser.setStatus(!cmsUser.getStatus());
+		cmsUserMapper.updateById(cmsUser);
+		if (!cmsUser.getStatus()) {
+			//状态为禁用时,将上线的用户下线
+			StpUtil.logoutByLoginId(cmsUser.getId());
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult("用户状态变更成功");
+	}
+
+	@SneakyThrows
+	@PutMapping("/put/reset/pwd/{id}")
+	public Result<String> resetPwd(@PathVariable("id") Integer id) {
+		CmsUser cmsUser = cmsUserMapper.selectById(id);
+		cmsUser.setPassword(Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.SHA256).setStringData(Constant.INITIAL_PASSWORD).toBase64String());
+		cmsUserMapper.updateById(cmsUser);
+		cacheService.saveUser(cmsUser.getId());
+		return GatewayResponse.SUCCESS.newBuilder().toResult("重置密码成功");
+	}
+
+	/**
+	 * 手机号获取登录信息
+	 */
+	@GetMapping("/get/loginInfo")
+	public Result<AdminInfo> getLoginInfo(String phone, String code) throws Exception {
+		CmsUser admin = cmsUserMapper.selectOne(
+				new QueryWrapper<CmsUser>().lambda().eq(CmsUser::getPhone, phone).last("limit 1"));
+		if (null == admin) {
+			throw BusinessRuntimeException.getInstance("该用户不存在.");
+		}
+		if (StrUtil.hasEmpty(phone, code)) {
+			throw BusinessRuntimeException.getInstance("请输入对应信息");
+		}
+		DateTime now = DateTime.now();
+		PhoneCode phoneCode = phoneCodeMapper.selectOne(Wrappers.lambdaQuery(PhoneCode.class).eq(PhoneCode::getPhone, phone).last("limit 1"));
+		if (phoneCode == null || StrUtil.isEmpty(phoneCode.getCode())) {
+			throw BusinessRuntimeException.getInstance("请重新获取手机验证码");
+		}
+		//3分钟失效
+		Date updateTime = phoneCode.getUpdateTime();
+		DateTime afterFiveMinutes = DateUtil.offsetMinute(updateTime, 3);
+		if (now.isAfter(afterFiveMinutes)) {
+			throw BusinessRuntimeException.getInstance("手机验证码已失效,请重新获取");
+		}
+		if (!StrUtil.equals(code, phoneCode.getCode())) {
+			throw BusinessRuntimeException.getInstance("手机验证码错误,请重新输入");
+		}
+		// 生成token
+
+		StpUtil.login(admin.getId());
+
+		String token = StpUtil.getTokenValue();
+
+		admin.setPassword("");
+
+		AdminInfo info = new AdminInfo();
+		info.setInfo2(admin);
+		info.setToken(token);
+
+		//缓存用户信息
+		cmsUserManager.loadUserRedisCache(admin);
+
+		//用户权限
+		info.setPermissions(cmsUserManager.getUserPermissions(admin.getId()));
+
+		//用户角色
+		info.setRoles(cmsUserManager.getUserRoles(admin.getId()));
+		return GatewayResponse.SUCCESS.newBuilder().toResult(info);
+	}
+
+	@GetMapping("/get/list")
+	public Result<SearchResult<CmsUserVO>> list() {
+		SearchResult<CmsUserVO> search = beanSearcher.search(CmsUserVO.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+}

+ 123 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/cms/CmsMenuController.java

@@ -0,0 +1,123 @@
+package com.cyksj.web.controller.manage.cms;
+
+import cn.dev33.satoken.stp.StpUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.manage.cms.CmsMenuMapper;
+import com.cyksj.mapper.manage.cms.CmsRoleMenuMapper;
+import com.cyksj.model.entity.CmsMenu;
+import com.cyksj.model.entity.CmsRoleMenu;
+import com.cyksj.model.entity.CmsUser;
+import com.cyksj.model.views.CmsMenuVO;
+import com.cyksj.service.mange.cms.CmsUserManager;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/*
+ *项目名: netflix
+ *文件名: CmsMenuController
+ *创建者: JavaZou
+ *创建时间:2023/1/11 14:26
+ */
+@RestController
+@RequestMapping("/manage/menu")
+@RequiredArgsConstructor
+@Slf4j
+public class CmsMenuController {
+	private final CmsMenuMapper cmsMenuMapper;
+
+	private final CmsUserManager cmsUserManager;
+
+	private final CmsRoleMenuMapper cmsRoleMenuMapper;
+
+	@PostMapping("/post")
+	public Result<String> addMenu(@RequestBody @Validated CmsMenu cmsMenu) {
+		cmsMenuMapper.insert(cmsMenu);
+		return GatewayResponse.SUCCESS.newBuilder().toResult("新增菜单成功");
+	}
+
+	@PutMapping("/put")
+	public Result<String> putMenu(@RequestBody CmsMenu cmsMenu) throws Exception {
+		if (cmsMenu.getId() == null || cmsMenu.getId() < 1) {
+			throw BusinessRuntimeException.getInstance("菜单不存在");
+		}
+		CmsMenu menu = cmsMenuMapper.selectById( cmsMenu.getId());
+		BeanUtils.copyProperties(cmsMenu, menu);
+		cmsMenuMapper.updateById(menu);
+		//更新该菜单关联的权限
+		List<CmsUser> cmsUserList = cmsMenuMapper.getAllCmsUserByMenuId(cmsMenu.getId());
+		if (null != cmsUserList) {
+			for (CmsUser cmsUser : cmsUserList) {
+				cmsUserManager.loadUserRedisCache(cmsUser);
+			}
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult("编辑菜单成功");
+	}
+
+	@DeleteMapping("/delete/{id}")
+	public Result<String> deleteMenuById(@PathVariable("id") Long id) throws Exception {
+		if (id == null || id < 1) {
+			throw BusinessRuntimeException.getInstance("菜单不存在");
+		}
+		List<CmsUser> cmsUserList = cmsMenuMapper.getAllCmsUserByMenuId(id);
+		if (null != cmsUserList) {
+			for (CmsUser cmsUser : cmsUserList) {
+				cmsUserManager.loadUserRedisCache(cmsUser);
+			}
+		}
+		cmsRoleMenuMapper.delete(Wrappers.lambdaQuery(CmsRoleMenu.class).eq(CmsRoleMenu::getMenuId, id));
+		cmsMenuMapper.deleteMenuAndChild(id);
+		cmsMenuMapper.delete(Wrappers.lambdaQuery(CmsMenu.class).eq(CmsMenu::getId, id).or().eq(CmsMenu::getParentId, id));
+		return GatewayResponse.SUCCESS.newBuilder().toResult("删除菜单成功");
+	}
+
+	@GetMapping("/get")
+	public Result<List<CmsMenuVO>> getMenuList() {
+		Map<Long, List<CmsMenuVO>> idMenusMap = cmsMenuMapper.getALlMenu().stream().collect(Collectors.groupingBy(CmsMenu::getParentId));
+		List<CmsMenuVO> list = cmsMenuMapper.getCmsMenusList();
+		for (CmsMenuVO cmsMenuVO : list) {
+			findChildMenu(cmsMenuVO, idMenusMap);
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(list);
+	}
+
+	@GetMapping("/get/noPerms")
+	public Result<List<CmsMenuVO>> getNoPermsALLMenu() {
+		Map<Long, List<CmsMenuVO>> idMenusMap = cmsMenuMapper.getALlMenu().stream().collect(Collectors.groupingBy(CmsMenu::getParentId));
+		List<CmsMenuVO> list = cmsMenuMapper.getCmsMenusList();
+		for (CmsMenuVO cmsMenuVO : list) {
+			findChildMenu(cmsMenuVO, idMenusMap);
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(list);
+	}
+
+	@GetMapping("/get/self/menu")
+	public Result<List<CmsMenuVO>> getSelfMenuList() {
+		List<CmsMenuVO> allSelf = cmsMenuMapper.getSelfCmsMenusList(StpUtil.getLoginIdAsLong());
+		Map<Long, List<CmsMenuVO>> idMenusMap = allSelf.stream().collect(Collectors.groupingBy(CmsMenu::getParentId));
+		List<CmsMenuVO> list = allSelf.stream().filter(vo -> vo.getParentId() == 0).collect(Collectors.toList());
+		for (CmsMenuVO cmsMenuVO : list) {
+			findChildMenu(cmsMenuVO, idMenusMap);
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(list);
+	}
+
+	private void findChildMenu(CmsMenuVO cmsMenuVO, Map<Long, List<CmsMenuVO>> idMenusMap) {
+		List<CmsMenuVO> list = idMenusMap.get(cmsMenuVO.getId());
+		cmsMenuVO.setHasChildren(false);
+		if (list != null && list.size() > 0) {
+			cmsMenuVO.setChild(list);
+			cmsMenuVO.setHasChildren(true);
+			list.forEach(child -> findChildMenu(child, idMenusMap));
+		}
+	}
+}

+ 142 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/cms/CmsRoleController.java

@@ -0,0 +1,142 @@
+package com.cyksj.web.controller.manage.cms;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.manage.cms.CmsRoleMapper;
+import com.cyksj.mapper.manage.cms.CmsRoleMenuMapper;
+import com.cyksj.model.entity.CmsRole;
+import com.cyksj.model.entity.CmsRoleMenu;
+import com.cyksj.model.entity.CmsUser;
+import com.cyksj.model.request.CmsRoleReq;
+import com.cyksj.service.mange.cms.CmsUserManager;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Arrays;
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: CmsRoleController
+ *创建者: JavaZou
+ *创建时间:2023/1/11 14:26
+ */
+@RestController
+@RequestMapping("/manage/role")
+@RequiredArgsConstructor
+@Slf4j
+public class CmsRoleController {
+	private final CmsRoleMapper cmsRoleMapper;
+
+	private final CmsRoleMenuMapper cmsRoleMenuMapper;
+
+	private final CmsUserManager cmsUserManager;
+
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	@PostMapping("/post")
+	public Result<String> addRole(@RequestBody @Validated CmsRoleReq cmsRoleReq) {
+		try {
+			CmsRole cmsRole = new CmsRole();
+			BeanUtils.copyProperties(cmsRoleReq, cmsRole);
+			cmsRoleMapper.insert(cmsRole);
+			cmsRoleReq.setId(cmsRole.getId());
+			if (StrUtil.isNotEmpty(cmsRoleReq.getMenuIds())) {
+				saveRoleMenuRelation(cmsRoleReq);
+			}
+		} catch (DuplicateKeyException keyEx) {
+			throw BusinessRuntimeException.getInstance("角色名重复");
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult("新增角色成功");
+	}
+
+	@PostMapping("/put")
+	public Result<String> putRole(@RequestBody CmsRoleReq cmsRoleReq) throws Exception {
+		if (cmsRoleReq.getId() == null || cmsRoleReq.getId() < 0) {
+			throw BusinessRuntimeException.getInstance("角色不存在");
+		}
+		if (StrUtil.isEmpty(cmsRoleReq.getMenuIds())) {
+			throw BusinessRuntimeException.getInstance("请选择对应的菜单");
+		}
+		CmsRole cmsRole = cmsRoleMapper.selectById(cmsRoleReq.getId());
+		Boolean isFlag = false;
+		if (StrUtil.isNotBlank(cmsRoleReq.getRoleName())) {
+			cmsRole.setRoleName(cmsRoleReq.getRoleName());
+			isFlag = true;
+		}
+		if (StrUtil.isNotBlank(cmsRoleReq.getRemark())) {
+			cmsRole.setRemark(cmsRoleReq.getRemark());
+			isFlag = true;
+		}
+		if (isFlag) {
+			cmsRoleMapper.updateById(cmsRole);
+		}
+		cmsRoleMenuMapper.delete(Wrappers.lambdaQuery(CmsRoleMenu.class).eq(CmsRoleMenu::getRoleId, cmsRoleReq.getId()));
+		if (StrUtil.isNotBlank(cmsRoleReq.getMenuIds())) {
+			this.saveRoleMenuRelation(cmsRoleReq);
+		}
+		//查出所关联该角色的所有用户
+		List<CmsUser> cmsUserList = cmsRoleMapper.getAllCmsUserByRoleId(cmsRoleReq.getId());
+		if (cmsUserList != null) {
+			for (CmsUser cmsUser : cmsUserList) {
+				//更新缓存
+				cmsUserManager.loadUserRedisCache(cmsUser);
+			}
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult("更新角色成功");
+	}
+
+	@DeleteMapping("/delete/{id}")
+	public Result<String> delRoleById(@PathVariable("id") Long id) {
+		if (id == null || id < 0) {
+			throw BusinessRuntimeException.getInstance("角色不存在");
+		}
+		List<CmsUser> cmsUserList = cmsRoleMapper.getAllCmsUserByRoleId(id);
+		if (null != cmsUserList && !cmsUserList.isEmpty()) {
+			throw BusinessRuntimeException.getInstance("请先删除该角色关联下的用户");
+		}
+		cmsRoleMenuMapper.delete(Wrappers.lambdaQuery(CmsRoleMenu.class).eq(CmsRoleMenu::getRoleId, id));
+		cmsRoleMapper.deleteById(id);
+		return GatewayResponse.SUCCESS.newBuilder().toResult("删除角色成功");
+	}
+
+
+	@GetMapping("/get")
+	public Result<SearchResult<CmsRole>> getRoleList() {
+		SearchResult<CmsRole> search = beanSearcher.search(CmsRole.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+	@GetMapping("/get/menu")
+	public Result<List<String>> getMenuByRoleId(String roleId) {
+		if (StrUtil.isEmpty(roleId)) {
+			throw BusinessRuntimeException.getInstance("角色不存在");
+		}
+		//目前是单个角色
+		List<String> menus = cmsRoleMapper.getAllMenusByRoleIds(roleId.split(","));
+		return GatewayResponse.SUCCESS.newBuilder().toResult(menus);
+	}
+
+	@GetMapping("/get/detail/{roleId}")
+	public Result<CmsRole> getDetailByRoleId(@PathVariable("roleId") Integer roleId) {
+		return GatewayResponse.SUCCESS.newBuilder().toResult(cmsRoleMapper.selectById(roleId));
+	}
+
+	private void saveRoleMenuRelation(CmsRoleReq cmsRoleReq) {
+		Arrays.stream(cmsRoleReq.getMenuIds().split(",")).forEach(menuId -> {
+			cmsRoleMenuMapper.insert(new CmsRoleMenu(cmsRoleReq.getId(), Long.valueOf(menuId)));
+		});
+	}
+}

+ 35 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/cms/CmsSysController.java

@@ -0,0 +1,35 @@
+package com.cyksj.web.controller.manage.cms;
+
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.SysLog;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+
+/*
+ *项目名: netflix
+ *文件名: CmsSysController
+ *创建者: JavaZou
+ *创建时间:2023/3/9 10:44
+ */
+@RestController
+@RequestMapping("/manage/sysLog")
+@RequiredArgsConstructor
+public class CmsSysController {
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	@GetMapping
+	public Result<SearchResult<SysLog>> sysLogListByCondition(){
+		SearchResult<SysLog> search = beanSearcher.search(SysLog.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+}

+ 34 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/cms/interceptor/StpInterfaceImpl.java

@@ -0,0 +1,34 @@
+package com.cyksj.web.controller.manage.cms.interceptor;
+
+import cn.dev33.satoken.stp.StpInterface;
+import com.cyksj.service.mange.cms.CmsUserManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+ *项目名: yicang-admin
+ *文件名: Inter
+ *创建者: JavaZou
+ *创建时间:2022/9/30 10:34
+ */
+@Component
+public class StpInterfaceImpl implements StpInterface {
+	@Autowired
+	private CmsUserManager cmsUserManager;
+
+	/**
+	 * 用户权限列表
+	 */
+	@Override
+	public List<String> getPermissionList(Object loginId, String loginType) {
+		return new ArrayList<>(cmsUserManager.getUserPermissions(Long.valueOf(loginId.toString())));
+	}
+
+	@Override
+	public List<String> getRoleList(Object loginId, String loginType) {
+		return new ArrayList<>(cmsUserManager.getUserRoles(Long.valueOf(loginId.toString())));
+	}
+}

+ 7 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/coupon/CouponController.java

@@ -3,9 +3,11 @@ package com.cyksj.web.controller.manage.coupon;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.annotation.Log;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.config.corp.WeChatCorpFactory;
 import com.cyksj.dto.Result;
+import com.cyksj.enums.BusinessType;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.corp.CorpUserAuthMapper;
 import com.cyksj.mapper.corp.CorpUserMapper;
@@ -73,6 +75,7 @@ public class CouponController {
 	 * 新增优惠券
 	 */
 	@PostMapping
+	@Log(module = "优惠券/新增优惠券", businessType = BusinessType.POST, isSaveRequestData = true)
 	public Result<String> couponSave(@RequestBody @Validated Coupon coupon) throws Exception {
 		couponCommonService.saveCoupon(coupon);
 		return GatewayResponse.SUCCESS.newBuilder().toResult("新增优惠券成功");
@@ -83,6 +86,7 @@ public class CouponController {
 	 */
 	@DeleteMapping("/{id}")
 	@Transactional(rollbackFor = Throwable.class)
+	@Log(module = "优惠券/删除优惠券", businessType = BusinessType.DELETE)
 	public Result<String> couponSave(@PathVariable Long id) throws Exception {
 		couponMapper.deleteById(id);
 		couponSkuMapper.deleteByCid(id);
@@ -96,6 +100,7 @@ public class CouponController {
 	 * 修改优惠券
 	 */
 	@PutMapping
+	@Log(module = "优惠券/编辑优惠券", businessType = BusinessType.PUT, isSaveRequestData = true)
 	public Result<String> putCoupon(@RequestBody @Validated Coupon coupon) throws Exception {
 		couponCommonService.updateCoupon(coupon);
 		return GatewayResponse.SUCCESS.newBuilder().toResult("修改优惠券成功");
@@ -105,6 +110,7 @@ public class CouponController {
 	 * 发放优惠券
 	 */
 	@PostMapping("/send")
+	@Log(module = "优惠券/发放优惠券", businessType = BusinessType.POST, isSaveRequestData = true)
 	public Result<String> senCoupon(@RequestBody @Validated CouponActiveReq couponActiveReq) throws Exception {
 		couponCommonService.sendCoupon(couponActiveReq);
 		return GatewayResponse.SUCCESS.newBuilder().toResult("发放优惠券成功");
@@ -114,6 +120,7 @@ public class CouponController {
 	 * 优惠券 设置为推荐优惠券
 	 */
 	@PutMapping("/set/hot/{couponId}")
+	@Log(module = "优惠券/推荐优惠券", businessType = BusinessType.POST)
 	public Result<String> setHotCoupon(@PathVariable @Min(value = 1) Long couponId) {
 		couponCommonService.setHotCoupon(couponId);
 		return GatewayResponse.SUCCESS.newBuilder().toResult("推荐优惠券成功");

+ 33 - 5
netflix-web/src/main/java/com/cyksj/web/controller/manage/distribute/DistributeController.java

@@ -1,14 +1,16 @@
 package com.cyksj.web.controller.manage.distribute;
 
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.annotation.Log;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.dto.Result;
+import com.cyksj.enums.BusinessType;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.GoodsDonMapper;
 import com.cyksj.mapper.GoodsDonSkuMapper;
-import com.cyksj.mapper.OrderDonMapper;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.manage.distribute.DistributeMoneyApplyMapper;
 import com.cyksj.mapper.manage.distribute.DistributePointsExchangeMoneyMapper;
@@ -18,6 +20,7 @@ import com.cyksj.model.request.DistributeApplyMoneyReq;
 import com.cyksj.model.request.UserDistributeReq;
 import com.cyksj.model.views.*;
 import com.cyksj.service.distribute.DistributeService;
+import com.cyksj.service.mange.statistics.StatisticsDataService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.param.Operator;
@@ -31,6 +34,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.validation.constraints.NotNull;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.util.Date;
 import java.util.List;
 import java.util.Optional;
 
@@ -52,8 +56,6 @@ public class DistributeController {
 
 	private final BeanSearcher beanSearcher;
 
-	private final OrderDonMapper orderDonMapper;
-
 	private final DistributeMoneyApplyMapper distributeMoneyApplyMapper;
 
 	private final DistributePointsExchangeMoneyMapper distributePointsExchangeMoneyMapper;
@@ -64,10 +66,13 @@ public class DistributeController {
 
 	private final GoodsDonSkuMapper goodsDonSkuMapper;
 
+	private final StatisticsDataService statisticsDataService;
+
 	/**
 	 * 添加固定推广者
 	 */
 	@PostMapping
+	@Log(module = "分销管理/增加推广者", businessType = BusinessType.POST, isSaveRequestData = true)
 	public Result<String> saveDistributes(@RequestBody @NotNull UserDistributeReq userDistributeReq) {
 		distributeService.insertDistribute(userDistributeReq);
 		return GatewayResponse.SUCCESS.newBuilder().toResult("添加成功");
@@ -77,6 +82,7 @@ public class DistributeController {
 	 * 删除固定推广者
 	 */
 	@DeleteMapping("/del/{id}")
+	@Log(module = "分销管理/删除推广者", businessType = BusinessType.DELETE, isSaveRequestData = true)
 	public Result<String> deleteDistributesById(@PathVariable Long id) {
 		if (id == null || id < 1) {
 			throw BusinessRuntimeException.getInstance("id不存在");
@@ -89,6 +95,7 @@ public class DistributeController {
 	 * 推广者编辑
 	 */
 	@PutMapping
+	@Log(module = "分销管理/编辑推广者", businessType = BusinessType.PUT, isSaveRequestData = true)
 	public Result<String> editDistribute(@RequestBody UserDistributeReq userDistributeReq) {
 		distributeService.editDistribute(userDistributeReq);
 		return GatewayResponse.SUCCESS.newBuilder().toResult("编辑成功");
@@ -134,7 +141,7 @@ public class DistributeController {
 	 */
 	@GetMapping("/get/plat")
 	public Result<List<GoodsDon>> getGoodsDistributeRate() {
-		return GatewayResponse.SUCCESS.newBuilder().toResult(goodsDonMapper.selectList(Wrappers.lambdaQuery(GoodsDon.class).eq(GoodsDon::getType, 1).eq(GoodsDon::getDeleted, true).orderByAsc(GoodsDon::getId).select(GoodsDon::getId, GoodsDon::getTitle, GoodsDon::getRate)));
+		return GatewayResponse.SUCCESS.newBuilder().toResult(goodsDonMapper.selectList(Wrappers.lambdaQuery(GoodsDon.class).in(GoodsDon::getType, Constant.dsGoodsIds).eq(GoodsDon::getDeleted, true).orderByAsc(GoodsDon::getType).orderByAsc(GoodsDon::getId).select(GoodsDon::getId, GoodsDon::getType, GoodsDon::getTitle, GoodsDon::getRate, GoodsDon::getSecondRate)));
 	}
 
 	/**
@@ -185,16 +192,18 @@ public class DistributeController {
 	 * 平台分销比例修改
 	 */
 	@PutMapping("/put/goods/rate")
+	@Log(module = "分销管理/修改平台分销比例", businessType = BusinessType.PUT, isSaveRequestData = true)
 	public Result<String> editGoodsDistributeRate(@RequestBody UserDistributeReq userDistributeReq) {
 		for (UserPlatDistributeRate rate : userDistributeReq.getRates()) {
 			if (rate.getRate() < 0 || rate.getRate() > 100) {
 				throw new BusinessRuntimeException("比例错误");
 			}
 			GoodsDon goodsDon = goodsDonMapper.selectById(rate.getGoodsId());
-			if (goodsDon == null || goodsDon.getType() == 2) {
+			if (goodsDon == null || goodsDon.getType() == 3) {
 				throw new BusinessRuntimeException("平台错误");
 			}
 			goodsDon.setRate(rate.getRate());
+			goodsDon.setSecondRate(rate.getSecondRate());
 			goodsDonMapper.updateById(goodsDon);
 		}
 		return GatewayResponse.SUCCESS.newBuilder().toResult("编辑成功");
@@ -285,4 +294,23 @@ public class DistributeController {
 		distributeMoneyApplyMapper.updateById(apply);
 		return GatewayResponse.SUCCESS.newBuilder().toResult("编辑成功");
 	}
+
+	/**
+	 * 获取分销head
+	 */
+	@GetMapping("/get/headData")
+	public Result<BackgroundDataView> getDistributeHeadData(Long startTime, Long endTime) {
+		BackgroundDataView backgroundDataView = new BackgroundDataView();
+		Date startDate = null;
+		Date endDate = null;
+		if (startTime != null) {
+			startDate = DateUtil.date(startTime);
+		}
+		if (endTime != null) {
+			endDate = DateUtil.date(endTime);
+		}
+		//分销金额数据统计
+		statisticsDataService.distribute(backgroundDataView, startDate, endDate);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(backgroundDataView);
+	}
 }

+ 11 - 2
netflix-web/src/main/java/com/cyksj/web/controller/manage/exchange/ExchangeCodeController.java

@@ -1,9 +1,12 @@
 package com.cyksj.web.controller.manage.exchange;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.excel.support.ExcelTypeEnum;
+import com.cyksj.common.annotation.Log;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.dto.Result;
+import com.cyksj.enums.BusinessType;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.model.excel.ExcelExchangeCodeData;
 import com.cyksj.model.request.ExchangeCodeReq;
@@ -14,7 +17,9 @@ import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -41,7 +46,9 @@ public class ExchangeCodeController {
 	 * 生成兑换码 并导出
 	 */
 	@GetMapping("/createAndExport")
-	private void createAndExportCode(ExchangeCodeReq exchangeCodeReq, HttpServletResponse response) {
+	@SaCheckPermission("exchangeCode:add")
+	@Log(module = "兑换码/生成兑换码", businessType = BusinessType.POST, isSaveRequestData = true)
+	public void createAndExportCode(ExchangeCodeReq exchangeCodeReq, HttpServletResponse response) {
 		if (ObjectUtil.hasEmpty(exchangeCodeReq.getGoodsId(), exchangeCodeReq.getSkuId(), exchangeCodeReq.getNumber())) {
 			throw BusinessRuntimeException.getInstance("必填项为空");
 		}
@@ -53,6 +60,7 @@ public class ExchangeCodeController {
 	 * 兑换码列表
 	 */
 	@GetMapping("/get")
+	@SaCheckPermission("exchangeCode:view")
 	public Result<SearchResult<ExchangeCodeView>> getExchangeCodeView() {
 		return GatewayResponse.SUCCESS.newBuilder().toResult(beanSearcher.search(ExchangeCodeView.class, MapUtils.flat(request.getParameterMap())));
 	}
@@ -61,6 +69,7 @@ public class ExchangeCodeController {
 	 * 导出兑换码
 	 */
 	@GetMapping("/export")
+	@SaCheckPermission("exchangeCode:export")
 	public void exportExchangeCode(HttpServletResponse response) {
 		List<ExcelExchangeCodeData> data = beanSearcher.searchAll(ExcelExchangeCodeData.class, MapUtils.flat(request.getParameterMap()));
 		EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelExchangeCodeData.class, data, "银河兑换码","银河兑换码", ExcelTypeEnum.XLSX, null);

+ 34 - 3
netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonController.java

@@ -1,7 +1,11 @@
 package com.cyksj.web.controller.manage.goods;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.core.bean.BeanUtil;
+import com.cyksj.common.annotation.Log;
+import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.dto.Result;
+import com.cyksj.enums.BusinessType;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.model.entity.GoodsDon;
 import com.cyksj.model.entity.GoodsDonSku;
@@ -68,10 +72,12 @@ public class CmsGoodsDonController {
      * 新增 商品spu
      */
     @PostMapping(value = "/post")
-    public Result<Long> spuInsert(@Validated @RequestBody ReqGoodsSpuInsert spu) throws Exception{
+    @SaCheckPermission("platform:add")
+    @Log(module = "平台管理/新增平台", businessType = BusinessType.POST, isSaveRequestData = true)
+    public Result<Long> spuInsert(@Validated @RequestBody ReqGoodsSpuInsert spu) throws Exception {
         // 新增商品
         GoodsDon goods = new GoodsDon();
-        BeanUtil.copyProperties(spu,goods);
+        BeanUtil.copyProperties(spu, goods);
 
         goodsDonService.save(goods);
         return GatewayResponse.SUCCESS.newBuilder().toResult(goods.getId());
@@ -81,6 +87,8 @@ public class CmsGoodsDonController {
      * 修改 商品spu
      */
     @PutMapping(value = "/update")
+    @SaCheckPermission("platform:update")
+    @Log(module = "平台管理/编辑平台", businessType = BusinessType.PUT, isSaveRequestData = true)
     public Result<String> spuUpdate(@Validated @RequestBody ReqGoodsSpuInsert spu) throws Exception{
         GoodsDon goods = new GoodsDon();
         BeanUtil.copyProperties(spu,goods);
@@ -89,7 +97,30 @@ public class CmsGoodsDonController {
     }
 
 
+    @PutMapping("/put/status/{id}")
+    @SaCheckPermission("platform:updateStatus")
+    @Log(module = "平台管理/平台上下架", businessType = BusinessType.PUT, isSaveRequestData = true, isSaveResponseData = true)
+    public Result<Boolean> updateStatus(@PathVariable Long id) {
+        GoodsDon goods = goodsDonService.getById(id);
+        if (goods == null) {
+            throw BusinessRuntimeException.getInstance("平台不存在");
+        }
+        goods.setStatus(!goods.getStatus());
+        goodsDonService.updateById(goods);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(goods.getStatus());
+    }
 
-
+    @DeleteMapping("/delete/{id}")
+    @SaCheckPermission("platform:delete")
+    @Log(module = "平台管理/删除平台", businessType = BusinessType.DELETE, isSaveRequestData = true, isSaveResponseData = true)
+    public Result<Long> deleteById(@PathVariable Long id) {
+        GoodsDon goods = goodsDonService.getById(id);
+        if (goods == null) {
+            throw BusinessRuntimeException.getInstance("平台不存在");
+        }
+        goods.setDeleted(false);
+        goodsDonService.updateById(goods);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(id);
+    }
 
 }

+ 6 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonSkuController.java

@@ -2,9 +2,10 @@ package com.cyksj.web.controller.manage.goods;
 
 import cn.hutool.core.bean.BeanUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.cyksj.common.util.IoKit;
+import com.cyksj.common.annotation.Log;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.dto.Result;
+import com.cyksj.enums.BusinessType;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.model.entity.GoodsDon;
 import com.cyksj.model.entity.GoodsDonSku;
@@ -47,6 +48,7 @@ public class CmsGoodsDonSkuController {
      * 新增 商品spec & sku
      */
     @PostMapping(value = "/post/spec-sku")
+    @Log(module = "平台管理/新增商品sku&spec", businessType = BusinessType.POST, isSaveRequestData = true)
     public Result<String> skuInsert(@Validated @RequestBody ReqGoodsSkuInsert insert) throws Exception{
 
         GoodsDon goods = goodsDonService.getById(insert.getGoodsId());
@@ -125,6 +127,7 @@ public class CmsGoodsDonSkuController {
      */
     @Transactional(rollbackFor = Throwable.class)
     @PostMapping(value = "/post")
+    @Log(module = "平台管理/新增规格", businessType = BusinessType.POST, isSaveRequestData = true)
     public Result<String> skuAppend(@Validated @RequestBody ReqGoodsSkuInsert insert) throws Exception{
 
         GoodsDon goods = goodsDonService.getById(insert.getGoodsId());
@@ -215,6 +218,7 @@ public class CmsGoodsDonSkuController {
      */
     @Transactional(rollbackFor = Throwable.class)
     @PutMapping(value = "/update")
+    @Log(module = "平台管理/编辑规格", businessType = BusinessType.PUT, isSaveRequestData = true)
     public Result<String> skuUpdate(@RequestBody GoodsDonSku sku){
         goodsDonSkuService.saveOrUpdate(sku);
         return GatewayResponse.SUCCESS.newBuilder().toResult();
@@ -226,6 +230,7 @@ public class CmsGoodsDonSkuController {
      */
     @Transactional(rollbackFor = Throwable.class)
     @DeleteMapping("/delete/{skuId}")
+    @Log(module = "平台管理/删除规格", businessType = BusinessType.DELETE)
     public Result<String> skuDelete(@PathVariable Long skuId) {
         goodsDonSkuService.removeById(skuId);
         return GatewayResponse.SUCCESS.newBuilder().toResult();

+ 9 - 3
netflix-web/src/main/java/com/cyksj/web/controller/manage/group/CmsGroupController.java

@@ -1,15 +1,17 @@
 package com.cyksj.web.controller.manage.group;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.cyksj.common.annotation.Log;
 import com.cyksj.common.annotation.NoSubmit;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.dto.Result;
+import com.cyksj.enums.BusinessType;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.GroupsRelationMapper;
 import com.cyksj.model.entity.Account;
 import com.cyksj.model.entity.GroupsTrips;
 import com.cyksj.model.views.GroupsTripsWaitingView;
 import com.cyksj.service.mange.CmsAccountService;
-import com.cyksj.service.mange.CmsGoodsDonSkuService;
 import com.cyksj.service.mange.CmsGroupService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
@@ -40,14 +42,13 @@ public class CmsGroupController {
 
     private final CmsGroupService groupService;
 
-    private final CmsGoodsDonSkuService skuService;
-
     private final CmsAccountService accountService;
 
     private final GroupsRelationMapper relationMapper;
 
 
     @GetMapping("/get")
+    @SaCheckPermission("group:view")
     public Result<SearchResult<GroupsTrips>> get(String account, Long userId, String nickName, String submitAccount, Boolean isEmpty) {
         MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
         if (userId != null || StringUtils.isNotBlank(nickName) || StringUtils.isNotBlank(submitAccount)) {
@@ -79,6 +80,8 @@ public class CmsGroupController {
 
     @PostMapping("/post")
     @NoSubmit
+    @SaCheckPermission("group:add")
+    @Log(module = "发布车票/新增车队", businessType = BusinessType.POST, isSaveRequestData = true)
     public Result<GroupsTrips> add(@RequestBody GroupsTrips groups){
 
         GroupsTrips groupsTrips = groupService.issuance(groups);
@@ -87,12 +90,14 @@ public class CmsGroupController {
     }
 
     @PutMapping("/update")
+    @Log(module = "发布车票/编辑车队", businessType = BusinessType.PUT, isSaveRequestData = true)
     public Result<String> update(@RequestBody GroupsTrips groups){
         groupService.updateById(groups);
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
 
     @DeleteMapping("/delete/{id}")
+    @Log(module = "发布车票/删除车队", businessType = BusinessType.DELETE, isSaveRequestData = true)
     public Result<String> delete(@PathVariable Long id){
         groupService.close(id);
 
@@ -100,6 +105,7 @@ public class CmsGroupController {
     }
 
     @PutMapping("/update/set/account")
+    @Log(module = "发布车票/配置账号", businessType = BusinessType.PUT, isSaveRequestData = true)
     public Result<String> setAccount(@RequestBody GroupsTrips groupsTrips){
         Account account = accountService.getById(groupsTrips.getAccountId());
         if(account == null){

+ 8 - 4
netflix-web/src/main/java/com/cyksj/web/controller/manage/group/CmsHomeGroupController.java

@@ -1,14 +1,16 @@
 package com.cyksj.web.controller.manage.group;
 
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.annotation.Log;
 import com.cyksj.dto.Result;
+import com.cyksj.enums.BusinessType;
 import com.cyksj.enums.GatewayResponse;
-import com.cyksj.mapper.GroupsRelationMapper;
-import com.cyksj.model.entity.*;
+import com.cyksj.model.entity.HomeGroup;
+import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.manage.views.HomeGroupView;
 import com.cyksj.model.manage.views.HomeUserView;
-import com.cyksj.service.mange.*;
+import com.cyksj.service.mange.CmsHomeGroupService;
+import com.cyksj.service.mange.CmsOrderDonService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.util.MapUtils;
@@ -55,6 +57,7 @@ public class CmsHomeGroupController {
 
     @Transactional(rollbackFor = Throwable.class)
     @PostMapping("/post")
+    @Log(module = "平台管理/家庭组管理新增用户", businessType = BusinessType.POST, isSaveRequestData = true)
     public Result<String> post(@RequestBody HomeGroup homeGroup) {
         OrderDon orderDon = orderDonService.getOne(Wrappers.lambdaQuery(OrderDon.class)
                 .eq(OrderDon::getUserId, homeGroup.getUserId())
@@ -74,6 +77,7 @@ public class CmsHomeGroupController {
     }
 
     @DeleteMapping("/delete/{id}")
+    @Log(module = "平台管理/家庭组管理删除用户", businessType = BusinessType.DELETE, isSaveRequestData = true)
     public Result<String> delete(@PathVariable Long id) {
         homeGroupService.removeById(id);
         return GatewayResponse.SUCCESS.newBuilder().toResult();

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels