Parcourir la source

add 过期账号分配客服

zoujiajian il y a 3 ans
Parent
commit
9ce7b8ad32
18 fichiers modifiés avec 302 ajouts et 36 suppressions
  1. 4 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/Account.java
  3. 14 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CmsUser.java
  4. 9 3
      netflix-dao/src/main/java/com/cyksj/model/manage/views/AccountView.java
  5. 5 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/GroupsRelationView.java
  6. 1 1
      netflix-dao/src/main/java/com/cyksj/model/request/CmsUserReq.java
  7. 24 0
      netflix-dao/src/main/java/com/cyksj/model/views/CustomerServiceUpdatePwdDetail.java
  8. 1 1
      netflix-dao/src/main/java/com/cyksj/model/views/DistributeBusinessView.java
  9. 2 0
      netflix-dao/src/main/java/com/cyksj/model/views/GroupsView.java
  10. 2 2
      netflix-dao/src/main/resources/mapper/CmsUserMapper.xml
  11. 5 0
      netflix-service/src/main/java/com/cyksj/service/mange/CmsAccountService.java
  12. 64 1
      netflix-service/src/main/java/com/cyksj/service/mange/account/CmsAccountServiceImpl.java
  13. 5 5
      netflix-service/src/main/java/com/cyksj/service/mange/cms/CmsUserManager.java
  14. 34 1
      netflix-service/src/main/java/com/cyksj/task/Scheduler.java
  15. 44 19
      netflix-web/src/main/java/com/cyksj/web/controller/group/GroupController.java
  16. 55 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java
  17. 27 2
      netflix-web/src/main/java/com/cyksj/web/controller/manage/cms/CmsAdminUserController.java
  18. 1 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/distribute/DistributeController.java

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

@@ -79,4 +79,8 @@ public interface Constant {
 	List<String> registerAccount = List.of("apple", "spotify", "google");
 
 	String SUCCESS = "success";
+
+	List<Long> CHAT_GPT_SKU_IDS = List.of(161l, 168l);
+
+	List<Long> MIDJOURNEY_SKU_IDS = List.of(175l, 185l, 186l);
 }

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

@@ -44,5 +44,10 @@ public class Account extends BaseEntity {
      */
     private String usAccount;
 
+    /**
+     * 客服id
+     */
+    private Long customerServiceId;
+
     private String remark;
 }

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

@@ -1,5 +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;
 
@@ -46,4 +48,16 @@ public class CmsUser extends BaseEntity{
 	 * 管理员是否允许登录
 	 */
 	private Boolean status;
+
+	/**
+	 * 角色列表
+	 */
+	@DbIgnore
+	@TableField(exist = false)
+	private String roleNames;
+
+
+	@DbIgnore
+	@TableField(exist = false)
+	private String roleIds;
 }

+ 9 - 3
netflix-dao/src/main/java/com/cyksj/model/manage/views/AccountView.java

@@ -19,7 +19,7 @@ import java.util.Date;
         "left join groups_trips gt on gt.account_id = a.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,a.bank_card,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.id,gdk.spec_val")
+        groupBy = "a.id,g.id,a.bank_card,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.id,gdk.spec_val,a.customer_service_id")
 public class AccountView {
 
     @DbField("a.id")
@@ -61,6 +61,12 @@ public class AccountView {
     @DbField("a.us_account")
     private String usAccount;
 
+    @DbField("a.customer_service_id")
+    private Long customerServiceId;
+
+    @DbIgnore
+    private String customerServiceName;
+
     @DbIgnore
     private Integer invited;
 
@@ -88,12 +94,12 @@ 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 and source = 'self'")
+    @DbField("select count(ur.id) from user_ticket_cleared_record ur where ur.account_id = a.id and deleted is true and source = 'self' :yesTime:")
     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 and source = 'self'" +
+            " from user_ticket_cleared_record ur where ur.deleted is true and source = 'self' :yesTime:" +
             " 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;

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

@@ -32,6 +32,7 @@ public class GroupsRelationView {
     private Long skuId;
 
     @DbField("a.account")
+    @JsonIgnore
     private String tripsAccount;
 
     @DbField("g.id")
@@ -65,6 +66,7 @@ public class GroupsRelationView {
     private Date expiryTime;
 
     @DbField("gr.num")
+    @JsonIgnore
     private Integer num;
 
     @DbField("u.nickname")
@@ -86,18 +88,21 @@ public class GroupsRelationView {
      * 创建时间
      */
     @DbField("gr.created_time")
+    @JsonIgnore
     private Date createdTime;
 
     /**
      * 创建时间
      */
     @DbField("gr.update_time")
+    @JsonIgnore
     private Date update_time;
 
     /**
      * 账号
      */
     @DbField("gr.account")
+    @JsonIgnore
     private String account;
 
     @DbIgnore

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

@@ -14,7 +14,7 @@ import javax.validation.constraints.NotBlank;
 @Getter
 @Setter
 public class CmsUserReq {
-	private Integer id;
+	private Long id;
 	/**
 	 * 登录账号
 	 */

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CustomerServiceUpdatePwdDetail.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.views;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: CustomerServiceUpdatePwdDetail
+ *创建者: JavaZou
+ *创建时间:2023/4/7 15:52
+ */
+@Getter
+@Setter
+public class CustomerServiceUpdatePwdDetail {
+	/**
+	 * 全部过期的账号数
+	 */
+	private Integer numOfExpiredAllAccount;
+
+	/**
+	 * 需要修改密码的账号数
+	 */
+	private Integer numOfExpiredAccount;
+}

+ 1 - 1
netflix-dao/src/main/java/com/cyksj/model/views/DistributeBusinessView.java

@@ -16,7 +16,7 @@ import java.math.BigDecimal;
  */
 @Getter
 @Setter
-@SearchBean(tables = "(select distinct business_id from user_distribute_business_rate) ur left join user_distribute_business_order_don_record ubr on ubr.business_id = ur.business_id" +
+@SearchBean(tables = "(select distinct business_id from user_distribute_business_rate) ur left join user_distribute_business_order_don_record ubr on ubr.business_id = ur.business_id and :time:" +
 		" left join cms_user cu on cu.id = ur.business_id",
 		groupBy = "ur.business_id,cu.nickname,date_format(ubr.order_created_time,'%Y-%m')")
 public class DistributeBusinessView {

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GroupsView.java

@@ -29,12 +29,14 @@ public class GroupsView {
      * 车位数量
      */
     @DbField("g.num")
+    @JsonIgnore
     private Integer num;
 
     /**
      * 可用车位数
      */
     @DbField("g.available_num")
+    @JsonIgnore
     private Integer availableNum;
 
     /**

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

@@ -4,8 +4,8 @@
 <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)
+        select any_value(u.nickname) as nickname,
+               group_concat(r.role_name) as roleNames
         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

+ 5 - 0
netflix-service/src/main/java/com/cyksj/service/mange/CmsAccountService.java

@@ -6,6 +6,7 @@ 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.CmsUserVO;
 import com.cyksj.model.views.ExpiredAccountDataView;
 
 import java.util.Date;
@@ -35,4 +36,8 @@ public interface CmsAccountService extends IService<Account> {
 	void saveRecord(Long operateUserId,Long accountId, String oldPassword, String newPassword, String type);
 
 	void recordAutoUpdatePwd(Long accountId, String account, String oldPwd, String newPwd, String operateIp);
+
+	void assignDeleteCustomerAccount(Long customerServiceId);
+
+	void assignCustomerAccount(List<CmsUserVO> customers, List<AccountView> accountViews);
 }

+ 64 - 1
netflix-service/src/main/java/com/cyksj/service/mange/account/CmsAccountServiceImpl.java

@@ -1,24 +1,31 @@
 package com.cyksj.service.mange.account;
 
+import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cyksj.mapper.AccountMapper;
 import com.cyksj.mapper.AccountUpdatePasswordRecordMapper;
-import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.mapper.manage.AutoUpdateAccountPwdLogMapper;
+import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.model.entity.Account;
 import com.cyksj.model.entity.AccountUpdatePasswordRecord;
 import com.cyksj.model.entity.AutoUpdateAccountPwdLog;
 import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.excel.ExcelAccountData;
 import com.cyksj.model.manage.views.AccountView;
+import com.cyksj.model.views.CmsUserVO;
 import com.cyksj.model.views.ExpiredAccountDataView;
 import com.cyksj.service.mange.CmsAccountService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapUtils;
+import com.google.common.collect.Lists;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -43,6 +50,8 @@ public class CmsAccountServiceImpl extends ServiceImpl<AccountMapper, Account> i
 
 	private final AutoUpdateAccountPwdLogMapper autoUpdateAccountPwdLogMapper;
 
+	private final BeanSearcher beanSearcher;
+
 	@Override
 	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));
@@ -94,6 +103,60 @@ public class CmsAccountServiceImpl extends ServiceImpl<AccountMapper, Account> i
 		autoUpdateAccountPwdLogMapper.insert(log);
 	}
 
+	@Override
+	public void assignDeleteCustomerAccount(Long customerServiceId) {
+		List<AccountView> accountViews = beanSearcher.searchAll(AccountView.class, MapUtils.builder()
+				.field(AccountView::getCustomerServiceId, customerServiceId)
+				.build());
+		if (accountViews.size() > 0) {
+			List<CmsUserVO> customers = beanSearcher.searchAll(CmsUserVO.class, MapUtils.builder()
+					.field(CmsUserVO::getId, customerServiceId).op(Operator.NotEqual)
+					.field(CmsUserVO::getRoleNames, "客服").op(Operator.Contain)
+					.build());
+			if (customers.size() > 0) {
+				log.info("删除客服id:{},分配其未修改的过期账号,账号数量:{}", customerServiceId, accountViews.size());
+				assignCustomerAccount(customers, accountViews);
+			}
+		}
+	}
+
+	@Override
+	public void assignCustomerAccount(List<CmsUserVO> customers, List<AccountView> accountViews) {
+		int customerSize = customers.size();
+
+		int accountSize = accountViews.size();
+
+		int num = accountSize / customerSize;
+
+		int remain = accountSize % customerSize;
+
+		List<List<AccountView>> partition = Lists.partition(accountViews, num);
+		for (int i = 0; i < customerSize; i++) {
+			List<AccountView> expiredAccounts = partition.get(i);
+			CmsUserVO customer = customers.get(i);
+			expiredAccounts.forEach(ea -> {
+				Long accountId = ea.getId();
+				accountMapper.update(null, Wrappers.lambdaUpdate(Account.class)
+						.set(Account::getCustomerServiceId, customer.getId())
+						.eq(Account::getId, accountId));
+			});
+		}
+		if (remain > 0) {
+			log.info("分配多余的过期账号给客服");
+			List<AccountView> remainExpiredAccount = partition.get(customerSize);
+			remainExpiredAccount.forEach(remainAccount -> {
+				int randomIndex = RandomUtil.randomInt(customerSize);
+				log.info("获取的随机下标:{}", randomIndex);
+				CmsUserVO customer = customers.get(randomIndex);
+				log.info("随机分配的客服是:{}", customer.getNickname());
+				Long accountId = remainAccount.getId();
+				accountMapper.update(null, Wrappers.lambdaUpdate(Account.class)
+						.set(Account::getCustomerServiceId, customer.getId())
+						.eq(Account::getId, accountId));
+			});
+		}
+	}
+
 	public String getRealAddressByIP(String ip) {
 		if (StrUtil.isBlank(ip)) {
 			return "unknown";

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

@@ -117,14 +117,14 @@ public class CmsUserManager {
 		});
 	}
 
-	public void delUserRoleRelation(CmsUser cmsUser) throws Exception {
-		cmsUserRoleMapper.delete(Wrappers.lambdaQuery(CmsUserRole.class).eq(CmsUserRole::getUserId, cmsUser.getId()));
+	public void delUserRoleRelation(Long userId) throws Exception {
+		cmsUserRoleMapper.delete(Wrappers.lambdaQuery(CmsUserRole.class).eq(CmsUserRole::getUserId, userId));
 		//删除用户缓存
-		cacheService.deleteUserCache(cmsUser.getId());
+		cacheService.deleteUserCache(userId);
 		//删除角色缓存
-		cacheService.delUserRoleCache(cmsUser.getId());
+		cacheService.delUserRoleCache(userId);
 		//删除权限缓存
-		cacheService.delUserPermissionsCache(cmsUser.getId());
+		cacheService.delUserPermissionsCache(userId);
 	}
 
 	public void saveUserRoleRelationAndCache(CmsUser cmsUser, String roles) throws Exception {

+ 34 - 1
netflix-service/src/main/java/com/cyksj/task/Scheduler.java

@@ -12,14 +12,20 @@ import com.cyksj.mapper.manage.distribute.DistributeWaitingSendPointsMapper;
 import com.cyksj.model.dto.WxMpTemplateData;
 import com.cyksj.model.dto.WxMpTemplateMessage;
 import com.cyksj.model.entity.*;
+import com.cyksj.model.manage.views.AccountView;
+import com.cyksj.model.views.CmsUserVO;
 import com.cyksj.model.views.WxAppTemplateView;
 import com.cyksj.redis.RedisService;
+import com.cyksj.service.mange.CmsAccountService;
 import com.cyksj.service.order.OrderDonService;
 import com.cyksj.service.register.RegisterOrderDonService;
 import com.cyksj.service.register.SpotifyService;
 import com.cyksj.service.relation.GroupRelationClearService;
 import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.service.wechat.WeChatService;
+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.dao.DuplicateKeyException;
@@ -51,7 +57,7 @@ public class Scheduler {
 
         private final AccountMapper accountMapper;
 
-        private final CustomerServiceMapper customerServiceMapper;
+        private final BeanSearcher beanSearcher;
 
         private final SpotifyService spotifyService;
 
@@ -73,6 +79,8 @@ public class Scheduler {
 
         private final GroupRelationClearService groupRelationClearService;
 
+        private final CmsAccountService cmsAccountService;
+
 
     /**
      * 每5分钟清理过期账号
@@ -282,4 +290,29 @@ public class Scheduler {
             log.info("更新用户记录:{}已购买实物意愿商品状态成功", update);
         }
     }
+
+    /**
+     * 统计昨日过期账号 分配给客服
+     */
+    @Scheduled(cron = "0 30 8 * * ?")
+    public void assignNeedUpdateExpiredAccount() {
+        DateTime beginOfDay = DateUtil.beginOfDay(DateTime.now());
+        List<AccountView> accountViews = beanSearcher.searchAll(AccountView.class, MapUtils.builder()
+                .field(AccountView::getExpiryCount, 0).op(Operator.GreaterThan)
+                .field(AccountView::getCustomerServiceId, 0)
+                .put("yesTime", String.format("and ur.created_time < '%s'", beginOfDay))
+                .build());
+        if (accountViews.size() > 0) {
+            int accountSize = accountViews.size();
+            log.info("开始给客服分配过期账号,过期账号数量:{}", accountSize);
+            List<CmsUserVO> customers = beanSearcher.searchAll(CmsUserVO.class, MapUtils.builder().field(CmsUserVO::getRoleNames, "客服").op(Operator.Contain).build());
+            if (customers.isEmpty()) {
+                log.info("暂无客服");
+                return;
+            }
+            //分配过期账号
+            cmsAccountService.assignCustomerAccount(customers, accountViews);
+        }
+
+    }
 }

+ 44 - 19
netflix-web/src/main/java/com/cyksj/web/controller/group/GroupController.java

@@ -1,10 +1,9 @@
 package com.cyksj.web.controller.group;
 
-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.GoodsDonSkuMapper;
-import com.cyksj.model.entity.GoodsDonSku;
 import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.views.GroupsView;
 import com.ejlchina.searcher.BeanSearcher;
@@ -19,8 +18,6 @@ import org.springframework.web.bind.annotation.RestController;
 import javax.servlet.http.HttpServletRequest;
 import java.util.Comparator;
 import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
 
 /**
  * @author chan
@@ -39,28 +36,56 @@ public class GroupController {
     private final GoodsDonSkuMapper goodsDonSkuMapper;
 
     @GetMapping("/get")
-    public Result<SearchResult<GroupsView>> get(Long skuId) {
+    public Result<SearchResult<GroupsView>> get() {
         SearchResult<GroupsView> search = beanSearcher.search(GroupsView.class, MapUtils.flatBuilder(request.getParameterMap())
                 .orderBy(GroupsView::getOrderBy).asc()
                 .orderBy(GroupsView::getId).desc().build()
         );
-        List<GoodsDonSku> goodsDonSkus = goodsDonSkuMapper.selectList(Wrappers.lambdaQuery(GoodsDonSku.class).eq(GoodsDonSku::getGoodsId, 18).select(GoodsDonSku::getId));
-        Set<Long> skuIds = goodsDonSkus.stream().map(GoodsDonSku::getId).collect(Collectors.toSet());
-        if (skuIds.contains(skuId)) {
-            search.getDataList().forEach((groupsView)->{
-                groupsView.setRelations(beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
+        search.getDataList().forEach((groupsView) -> {
+            if (Constant.CHAT_GPT_SKU_IDS.contains(groupsView.getSkuId())) {
+                List<GroupsRelationView> relationViewList = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
                         .field(GroupsRelationView::getGroupsId, groupsView.getId())
                         .orderBy(GroupsRelationView::getUpdate_time).desc()
-                        .build()));
-            });
-            search.getDataList().sort(Comparator.comparing(GroupsView::getOrderBy));
-        }else {
-            search.getDataList().forEach((groupsView) -> {
+                        .build());
+                List<GroupsRelationView> all = null;
+                //GPT 月付 暗改成20个 展示10个
+                if (groupsView.getSkuId().equals(Constant.CHAT_GPT_SKU_IDS.get(0))) {
+                    all = relationViewList.subList(0, 5);
+                    List<GroupsRelationView> after = relationViewList.subList(relationViewList.size() - 5, 20);
+                    all.addAll(after);
+                }
+                //GPT 4人月付暗改成6个 展示4个
+                if (groupsView.getSkuId().equals(Constant.CHAT_GPT_SKU_IDS.get(1))) {
+                    all = relationViewList.subList(0, 2);
+                    List<GroupsRelationView> after = relationViewList.subList(relationViewList.size() - 2, 6);
+                    all.addAll(after);
+                }
+                groupsView.setRelations(all);
+            } else if (Constant.MIDJOURNEY_SKU_IDS.contains(groupsView.getSkuId()) && groupsView.getNum() == 15) {
+                List<GroupsRelationView> relationViewList = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
+                        .field(GroupsRelationView::getGroupsId, groupsView.getId())
+                        .orderBy(GroupsRelationView::getUpdate_time).desc()
+                        .build());
+                List<GroupsRelationView> all = null;
+                //MIDJOURNEY 月付5个 暗改15个 展示5个
+                if (groupsView.getSkuId() == Constant.MIDJOURNEY_SKU_IDS.get(0)) {
+                    all = relationViewList.subList(0, 5);
+                    List<GroupsRelationView> after = relationViewList.subList(relationViewList.size() - 1, 15);
+                    all.addAll(after);
+                }
+                //MIDJOURNEY 标准会员月付10个 暗改15个 展示10个
+                if (groupsView.getSkuId() == Constant.MIDJOURNEY_SKU_IDS.get(1) || groupsView.getSkuId() == Constant.MIDJOURNEY_SKU_IDS.get(2)) {
+                    all = relationViewList.subList(0, 5);
+                    List<GroupsRelationView> after = relationViewList.subList(relationViewList.size() - 5, 15);
+                    all.addAll(after);
+                }
+                groupsView.setRelations(all);
+            } else {
                 groupsView.setRelations(beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder().field(GroupsRelationView::getGroupsId, groupsView.getId()).build()));
-            });
-        }
+            }
+
+        });
+        search.getDataList().sort(Comparator.comparing(GroupsView::getOrderBy));
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }
-
-
 }

+ 55 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java

@@ -21,6 +21,7 @@ import com.cyksj.mapper.GroupsMapper;
 import com.cyksj.mapper.HomeGroupMapper;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.UserTicketClearedRecordMapper;
+import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.excel.ExcelImportAccountData;
 import com.cyksj.model.excel.ExcelManageAccountData;
@@ -29,10 +30,12 @@ import com.cyksj.model.manage.views.AccountView;
 import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.response.ExpiredAccountRep;
 import com.cyksj.model.response.OrderDonAccountRep;
+import com.cyksj.model.views.CustomerServiceUpdatePwdDetail;
 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.mange.cms.CmsUserManager;
 import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.web.util.EasyExcelUtils;
 import com.ejlchina.searcher.BeanSearcher;
@@ -51,7 +54,9 @@ import org.springframework.web.multipart.MultipartFile;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
 /**
@@ -82,6 +87,10 @@ public class CmsAccountController {
 
 	private final UserMapper userMapper;
 
+	private final CmsUserMapper cmsUserMapper;
+
+	private final CmsUserManager cmsUserManager;
+
     @GetMapping("/get")
     @SaCheckPermission("account:view")
     public Result<SearchResult<AccountView>> get(Long userId ,String nickName ,String submitAccount ,String expiryStartTime, String expiryEndTime) {
@@ -115,6 +124,10 @@ public class CmsAccountController {
 					        .orderBy(AccountUpdatePasswordRecord::getId)
 					        .build());
 	        accountView.setUpdatePwdNum(recordList.size());
+	        if (accountView.getCustomerServiceId() != 0) {
+		        CmsUser cmsUser = cmsUserMapper.selectById(accountView.getCustomerServiceId());
+		        Optional.ofNullable(cmsUser).ifPresent(customer -> accountView.setCustomerServiceName(cmsUser.getNickname()));
+	        }
 	        if (recordList.size() > 0) {
 		        accountView.setLastUpdatePwdDate(recordList.get(0).getCreatedTime());
 	        }
@@ -190,6 +203,7 @@ public class CmsAccountController {
 						String new_pass = data.getPassword();
 						if (StrUtil.isNotBlank(new_pass) && !new_pass.trim().equals(account.getPassword())) {
 							account.setPassword(new_pass.trim());
+							account.setCustomerServiceId(0l);
 							flag = true;
 							isUpdatePwd = true;
 							//发放模板消息
@@ -315,7 +329,13 @@ public class CmsAccountController {
 	    }
 	    long userId = StpUtil.getLoginIdAsLong();
 	    if (!db.getPassword().equals(account.getPassword())) {
+		    account.setCustomerServiceId(0l);
 		    accountService.saveRecord(userId, account.getId(), db.getPassword(), account.getPassword(), "操作编辑");
+		    
+		    //清空过期账号 逻辑删除
+		    userTicketClearedRecordMapper.update(null, Wrappers.lambdaUpdate(UserTicketClearedRecord.class)
+				    .set(UserTicketClearedRecord::getDeleted, false)
+				    .eq(UserTicketClearedRecord::getAccountId, account.getId()));
 	    }
 	    if (StrUtil.isNotBlank(account.getAccount())){
 			account.setAccount(account.getAccount().trim());
@@ -351,6 +371,7 @@ public class CmsAccountController {
 				String updatePWd = account.getPassword().trim();
 				if (!oldPwd.equals(updatePWd)) {
 					db.setPassword(updatePWd);
+					db.setCustomerServiceId(0l);
 					accountService.updateById(db);
 					//记录
 					accountService.saveRecord(userId, account.getId(), oldPwd, updatePWd, "多选修改密码");
@@ -504,11 +525,14 @@ public class CmsAccountController {
 			String new_pass = accountReq.getPassword();
 			if (StrUtil.isNotBlank(new_pass) && !new_pass.trim().equals(account.getPassword())) {
 				account.setPassword(new_pass.trim());
+				account.setCustomerServiceId(0l);
 				flag = true;
 				//发放模板消息
 				templateCommonService.sendAccountTemplateMsg(account);
 				//记录操作日志
 				accountService.recordAutoUpdatePwd(account.getId(), account.getAccount(), oldPwd, new_pass, ServletUtil.getClientIP(request));
+				//记录
+				accountService.saveRecord(0l, account.getId(), oldPwd, new_pass, "自动修改密码");
 			}
 			if (flag) {
 				accountService.updateById(account);
@@ -516,4 +540,35 @@ public class CmsAccountController {
 		}
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
+
+	/**
+	 * 客服需要修改密码详情
+	 */
+	@GetMapping("/get/updatePwd/num")
+	public Result<CustomerServiceUpdatePwdDetail> updatePwdDetails() {
+		long userId = StpUtil.getLoginIdAsLong();
+		CmsUser user = cmsUserManager.getUser(userId);
+		MapBuilder builder = MapUtils.builder();
+		if (user != null && user.getRoleNames() != null && user.getRoleNames().contains("客服")) {
+			builder.field(AccountView::getCustomerServiceId, userId);
+		}
+		AtomicInteger numOfExpiredAccount = new AtomicInteger(0);
+
+		AtomicInteger numOfExpiredAllAccount = new AtomicInteger(0);
+
+		List<AccountView> accountViews = beanSearcher.searchAll(AccountView.class, builder.onlySelect(AccountView::getId, AccountView::getExpiryCount, AccountView::getExpiredAll).build());
+		accountViews.forEach(account -> {
+			if (account.getExpiryCount() > 0) {
+				numOfExpiredAccount.getAndAdd(1);
+			}
+			if (account.getExpiredAll()) {
+				numOfExpiredAllAccount.getAndAdd(1);
+			}
+		});
+		CustomerServiceUpdatePwdDetail updatePwdDetail = new CustomerServiceUpdatePwdDetail();
+		updatePwdDetail.setNumOfExpiredAccount(numOfExpiredAccount.get());
+		updatePwdDetail.setNumOfExpiredAllAccount(numOfExpiredAllAccount.get());
+
+		return GatewayResponse.SUCCESS.newBuilder().toResult(updatePwdDetail);
+	}
 }

+ 27 - 2
netflix-web/src/main/java/com/cyksj/web/controller/manage/cms/CmsAdminUserController.java

@@ -24,6 +24,7 @@ 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.CmsAccountService;
 import com.cyksj.service.mange.cms.CmsUserManager;
 import com.cyksj.service.mange.cms.manager.service.CacheService;
 import com.ejlchina.searcher.BeanSearcher;
@@ -62,6 +63,8 @@ public class CmsAdminUserController {
 
 	private final BeanSearcher beanSearcher;
 
+	private final CmsAccountService cmsAccountService;
+
 	private final HttpServletRequest request;
 
 	@PostMapping(value = "/login")
@@ -132,11 +135,25 @@ public class CmsAdminUserController {
 		if (exist == null) {
 			throw BusinessRuntimeException.getInstance("账号不存在,请重新登录");
 		}
+		//是不是客服
+		CmsUserVO isCustomer = beanSearcher.searchFirst(CmsUserVO.class, MapUtils.builder()
+				.field(CmsUserVO::getId, id)
+				.build());
+		if (isCustomer == null) {
+			throw BusinessRuntimeException.getInstance("被删除的用户不存在");
+		}
+
 		if (id.equals(adminId)) {
 			throw BusinessRuntimeException.getInstance("无法删除自己");
 		}
+
+		if (isCustomer.getRoleNames().contains("客服")) {
+			//是否未修改密码的账号
+			cmsAccountService.assignDeleteCustomerAccount(id);
+		}
+
 		//删除用户角色关联关系、缓存
-		cmsUserManager.delUserRoleRelation(exist);
+		cmsUserManager.delUserRoleRelation(id);
 		cmsUserMapper.deleteById(id);
 		//删除用户,将上线的用户踢下
 		StpUtil.logoutByLoginId(id);
@@ -178,7 +195,7 @@ public class CmsAdminUserController {
 		}
 		user.setNickname(cmsUserReq.getNickname());
 		if (StrUtil.isNotBlank(cmsUserReq.getRoleIds())) {
-			cmsUserManager.delUserRoleRelation(user);
+			cmsUserManager.delUserRoleRelation(user.getId());
 			cmsUserManager.saveUserRoleRelationAndCache(user, cmsUserReq.getRoleIds());
 		}
 		user.setPhone(cmsUserReq.getPhone());
@@ -187,6 +204,14 @@ public class CmsAdminUserController {
 		if (flag) {
 			StpUtil.logoutByLoginId(cmsUserReq.getId());
 		}
+		//是不是客服
+		CmsUserVO isCustomer = beanSearcher.searchFirst(CmsUserVO.class, MapUtils.builder()
+				.field(CmsUserVO::getId, cmsUserReq.getId())
+				.build());
+		if (isCustomer != null && !isCustomer.getRoleNames().contains("客服")) {
+			//是否未修改密码的账号
+			cmsAccountService.assignDeleteCustomerAccount(cmsUserReq.getId());
+		}
 
 		return GatewayResponse.SUCCESS.newBuilder().toResult("编辑成功");
 	}

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

@@ -370,7 +370,7 @@ public class DistributeController {
 		if (userBusinessRateService.isBusiness(adminId)) {
 			builder.field(DistributeBusinessView::getBusinessId, adminId);
 		}
-		builder.field(DistributeBusinessView::getMonthDate, thisMonth);
+		builder.put("time", String.format("date_format(ubr.order_created_time,'%%Y-%%m') = '%s'", thisMonth));
 		SearchResult<DistributeBusinessView> search = beanSearcher.search(DistributeBusinessView.class, builder.build());
 		search.getDataList().forEach(data->{
 			Number numOfRelation = beanSearcher.searchCount(UserDistribute.class, MapUtils.builder().field(UserDistribute::getBusinessId, data.getBusinessId()).field(UserDistribute::getDeleted, true).build());