Bladeren bron

Merge branch 'abroad_coupon_0808' into abroad_pre

# Conflicts:
#	netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
#	netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java
#	netflix-dao/src/main/java/com/cyksj/model/entity/BackInfoTranslations.java
#	netflix-dao/src/main/java/com/cyksj/model/entity/OrderDon.java
#	netflix-dao/src/main/resources/mapper/OrderDonMapper.xml
#	netflix-service/src/main/java/com/cyksj/service/mange/CmsAccountService.java
#	netflix-service/src/main/java/com/cyksj/service/mange/account/CmsAccountServiceImpl.java
#	netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
#	netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupsRelationNetflixServiceImpl.java
#	netflix-service/src/main/java/com/cyksj/service/translations/BackInfoTranslationsFrontService.java
#	netflix-service/src/main/java/com/cyksj/service/translations/impl/BackInfoTranslationsFrontServiceImpl.java
#	netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java
#	netflix-web/src/main/java/com/cyksj/web/controller/manage/coupon/CouponController.java
zoujiajian 2 jaren geleden
bovenliggende
commit
68cc159f1a
38 gewijzigde bestanden met toevoegingen van 1499 en 543 verwijderingen
  1. 5 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 17 0
      netflix-dao/src/main/java/com/cyksj/mapper/AccountBlockedReplaceRecordMapper.java
  3. 3 1
      netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java
  4. 3 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/coupon/CouponMapper.java
  5. 6 1
      netflix-dao/src/main/java/com/cyksj/mapper/manage/coupon/CouponUserMapper.java
  6. 23 1
      netflix-dao/src/main/java/com/cyksj/model/entity/Account.java
  7. 50 0
      netflix-dao/src/main/java/com/cyksj/model/entity/AccountBlockedReplaceRecord.java
  8. 4 1
      netflix-dao/src/main/java/com/cyksj/model/entity/BackInfoTranslations.java
  9. 6 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CouponUser.java
  10. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/OrderDon.java
  11. 25 0
      netflix-dao/src/main/java/com/cyksj/model/excel/ExcelBannedAccountData.java
  12. 3 0
      netflix-dao/src/main/java/com/cyksj/model/excel/ExcelImportAccountData.java
  13. 27 0
      netflix-dao/src/main/java/com/cyksj/model/excel/ExcelPrepareAccountData.java
  14. 28 1
      netflix-dao/src/main/java/com/cyksj/model/manage/views/AccountView.java
  15. 0 2
      netflix-dao/src/main/java/com/cyksj/model/request/RenewTimeUpReq.java
  16. 116 0
      netflix-dao/src/main/java/com/cyksj/model/views/AccountDisableView.java
  17. 45 0
      netflix-dao/src/main/java/com/cyksj/model/views/CouponReceiptDetailView.java
  18. 59 0
      netflix-dao/src/main/java/com/cyksj/model/views/CouponUsedDetailView.java
  19. 4 1
      netflix-dao/src/main/java/com/cyksj/model/views/CouponView.java
  20. 13 0
      netflix-dao/src/main/resources/mapper/AccountBlockedReplaceRecordMapper.xml
  21. 7 0
      netflix-dao/src/main/resources/mapper/CouponMapper.xml
  22. 63 31
      netflix-dao/src/main/resources/mapper/CouponUserMapper.xml
  23. 7 1
      netflix-dao/src/main/resources/mapper/OrderDonMapper.xml
  24. 7 11
      netflix-service/src/main/java/com/cyksj/service/coupon/CouponFontService.java
  25. 35 49
      netflix-service/src/main/java/com/cyksj/service/coupon/impl/CouponFontServiceImpl.java
  26. 11 0
      netflix-service/src/main/java/com/cyksj/service/mange/AccountCommonService.java
  27. 2 0
      netflix-service/src/main/java/com/cyksj/service/mange/CmsAccountService.java
  28. 2 0
      netflix-service/src/main/java/com/cyksj/service/mange/CmsGroupService.java
  29. 37 0
      netflix-service/src/main/java/com/cyksj/service/mange/account/AccountCommonServiceImpl.java
  30. 33 0
      netflix-service/src/main/java/com/cyksj/service/mange/account/CmsAccountServiceImpl.java
  31. 33 0
      netflix-service/src/main/java/com/cyksj/service/mange/group/CmsGroupServiceImpl.java
  32. 121 2
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  33. 11 8
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupsRelationNetflixServiceImpl.java
  34. 10 0
      netflix-service/src/main/java/com/cyksj/service/translations/BackInfoTranslationsFrontService.java
  35. 68 5
      netflix-service/src/main/java/com/cyksj/service/translations/impl/BackInfoTranslationsFrontServiceImpl.java
  36. 25 146
      netflix-web/src/main/java/com/cyksj/web/controller/coupon/CouponFrontController.java
  37. 521 210
      netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java
  38. 64 72
      netflix-web/src/main/java/com/cyksj/web/controller/manage/coupon/CouponController.java

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

@@ -139,4 +139,9 @@ public interface Constant {
 	 * 电影域名
 	 */
 	String ZHAOJU_MOVIES = "https://zhaoju666.com";
+
+	/**
+	 * GPT 平台账号重复
+	 */
+	List<Long> GPT_GOODS_IDS = List.of(18l, 29l, 30l);
 }

+ 17 - 0
netflix-dao/src/main/java/com/cyksj/mapper/AccountBlockedReplaceRecordMapper.java

@@ -0,0 +1,17 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.AccountBlockedReplaceRecord;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 项目名: netflix-job
+ * 文件名: AccountBlockedReplaceRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/1/16 16:39
+ */
+public interface AccountBlockedReplaceRecordMapper extends BaseMapper<AccountBlockedReplaceRecord> {
+	void batchInsert(@Param("list") List<AccountBlockedReplaceRecord> list);
+}

+ 3 - 1
netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java

@@ -36,7 +36,7 @@ public interface OrderDonMapper extends BaseMapper<OrderDon> {
 
 	ChannelStatisticsView selectChannelStatistics(@Param("first") String first, @Param("end") String end);
 
-	Integer selectCouponCodeUserNum(@Param("dsPopularizeId") Long dsPopularizeId, @Param("noOrderAllStatus") List<String> noOrderAllStatus);
+	Integer selectCouponCodeUserNum(@Param("dsPopularizeId") Long dsPopularizeId, @Param("exCode") String exCode, @Param("noOrderAllStatus") List<String> noOrderAllStatus);
 
 	ChannelPopularizeView countPopularizeOrderDetail(@Param("popularizeId") Long popularizeId, @Param("startTime") String startTime, @Param("endTime") String endTime);
 
@@ -49,4 +49,6 @@ public interface OrderDonMapper extends BaseMapper<OrderDon> {
 	OrderDonCustomerServiceRelate selectOrderRelate(Long orderId);
 
 	String selectMaxRefundGoodsName(@Param("operator") String operator, @Param("startTime") String startTime, @Param("endTime") String endTime);
+
+	BigDecimal getCouponUsedMoney(Long couponId);
 }

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/coupon/CouponMapper.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.cyksj.model.dto.CouponPopularizeDto;
 import com.cyksj.model.entity.Coupon;
 import com.cyksj.model.entity.CouponUser;
+import com.cyksj.model.entity.GoodsDonSku;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
@@ -29,4 +30,6 @@ public interface CouponMapper extends BaseMapper<Coupon> {
 
 	@Select("select name from coupon where id = #{couponId}")
 	String getCouponNameById(Long couponId);
+
+	List<GoodsDonSku> getCouponSku(Long couponId);
 }

+ 6 - 1
netflix-dao/src/main/java/com/cyksj/mapper/manage/coupon/CouponUserMapper.java

@@ -10,6 +10,7 @@ import com.cyksj.model.views.CouponUserView;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
+import java.util.Map;
 
 /*
  *项目名: netflix
@@ -24,7 +25,11 @@ public interface CouponUserMapper extends BaseMapper<CouponUser> {
 
 	Page<CouponActiveView> couponCenterList(@Param("userId") Long userId, IPage<CouponUserView> page);
 
-	Page<CouponUserView> couponPersonalList(@Param("userId") Long userId, @Param("page") Page<CouponUserView> page);
+	Page<CouponUserView> couponPersonalList(@Param("userId") Long userId, @Param("page") Page<CouponUserView> page, @Param("couponId") Long couponId);
 
 	CouponUserView getNewUserWelfareCouponsByUserId(@Param("userId") long userId, @Param("channel") CouponUser.Channel channel, @Param("now") DateTime now);
+
+	Map<String, Long> selectCouponUserNumData(Long couponId);
+
+	CouponUserView getCouponDetailById(@Param("userId") long userId, @Param("couponId") Long couponId);
 }

+ 23 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/Account.java

@@ -21,6 +21,8 @@ public class Account extends BaseEntity {
 
     private String password;
 
+    private Boolean isMonth;
+
     private Long goodsId;
 
     private String bankCard;
@@ -54,6 +56,11 @@ public class Account extends BaseEntity {
      */
     private String apiKey;
 
+    /**
+     * chatGpt 邮箱密码
+     */
+    private String gptEmailPwd;
+
     /**
      * 辅助邮箱
      */
@@ -85,4 +92,19 @@ public class Account extends BaseEntity {
      * gpt accesToken
      */
     private String gptRefreshToken;
-}
+
+    /**
+     * 备用账号类型sku_ids
+     */
+    private String preSkuIds;
+
+    /**
+     * 类型 1通用 2备用
+     */
+    private Integer type;
+
+    /**
+     * 账号是否禁用
+     */
+    private Boolean isDisable;
+}

+ 50 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/AccountBlockedReplaceRecord.java

@@ -0,0 +1,50 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: netflix-job
+ * 文件名: AccountBlockedReplaceRecord
+ * 创建者: JavaZou
+ * 创建时间:2024/1/16 16:37
+ */
+@Getter
+@Setter
+@SearchBean(tables = "account_blocked_replace_record ar left join goods_don g on g.id = ar.goods_id")
+public class AccountBlockedReplaceRecord {
+
+
+	@DbField("ar.id")
+	private Long id;
+
+	@DbField("ar.account")
+	private String account;
+
+	@DbField("ar.goods_id")
+	private Long goodsId;
+
+	@DbField("a.title")
+	@TableField(exist = false)
+	private String title;
+
+	/**
+	 * 创建时间
+	 */
+	@TableField(fill = FieldFill.INSERT)
+	@DbField("ar.created_time")
+	private Date createdTime;
+
+	/**
+	 * 修改时间
+	 */
+	@TableField(fill = FieldFill.INSERT_UPDATE)
+	@DbField("ar.update_time")
+	private Date updateTime;
+}

+ 4 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/BackInfoTranslations.java

@@ -39,7 +39,10 @@ public class BackInfoTranslations extends BaseEntity{
 	public enum Type {
 		goods("商品"),
 		sku("规格"),
-		spec("一级规格");
+		spec("一级规格"),
+		coupon("优惠券"),
+		coupon_classification("优惠券分类"),
+		;
 		String remark;
 
 		Type(String remark) {

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CouponUser.java

@@ -3,6 +3,7 @@ package com.cyksj.model.entity;
 import lombok.Getter;
 import lombok.Setter;
 
+import java.math.BigDecimal;
 import java.util.Date;
 
 /*
@@ -41,6 +42,11 @@ public class CouponUser extends BaseEntity {
 	 */
 	private Channel channel;
 
+	/**
+	 * 折扣卷折扣 用于分销
+	 */
+	private BigDecimal discount;
+
 	/**
 	 * 优惠券使用状态
 	 */

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

@@ -59,6 +59,11 @@ public class OrderDon extends BaseEntity implements Serializable {
     @DbIgnore
     private BigDecimal dpMoney;
 
+    /**
+     * 主平台订单金额 用于加购订单分销
+     */
+    private BigDecimal oriMoney;
+
     /**
      * 货币单位
      */

+ 25 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExcelBannedAccountData.java

@@ -0,0 +1,25 @@
+package com.cyksj.model.excel;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: ExcelBannedAccountData
+ * 创建者: JavaZou
+ * 创建时间:2023/10/7 15:35
+ */
+@Getter
+@Setter
+public class ExcelBannedAccountData {
+
+	@ExcelProperty("原账号")
+	private String oldAccount;
+
+	@ExcelProperty("新账号")
+	private String account;
+
+	@ExcelProperty("新账号密码")
+	private String password;
+}

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

@@ -27,4 +27,7 @@ public class ExcelImportAccountData {
 
 	@ExcelProperty("到期时间")
 	private String expiryTime;
+
+	@ExcelProperty("是否月抛")
+	private String isMonth;
 }

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

@@ -0,0 +1,27 @@
+package com.cyksj.model.excel;
+
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class ExcelPrepareAccountData {
+
+    @ExcelProperty("账号")
+    private String account;
+
+    /**
+     * 省份
+     */
+    @ExcelProperty("密码")
+    private String password;
+
+
+    /**
+     * 银行卡号
+     */
+    @ExcelProperty("银行卡号")
+    private String bankCard;
+}

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

@@ -40,12 +40,21 @@ public class AccountView {
     @DbField("a.account")
     private String account;
 
+    @DbIgnore
+    private String emailPassword;
+
     @DbField("a.password")
     private String password;
 
+    @DbField("a.is_month")
+    private Boolean isMonth;
+
     @DbField("a.api_key")
     private String apiKey;
 
+    @DbField("a.gpt_email_pwd")
+    private String gptEmailPwd;
+
     @DbField("a.verify_codes")
     private String verifyCodes;
 
@@ -109,6 +118,9 @@ public class AccountView {
     @DbField("gdk.id")
     private Long skuId;
 
+    @DbField("gdk.is_mirror")
+    private Boolean isMirror;
+
     @DbField("a.gpt_refresh_token")
     private String gptRefreshToken;
 
@@ -118,6 +130,9 @@ public class AccountView {
     @DbField("gdk.spec_val")
     private String specVal;
 
+    @DbField("a.created_time")
+    private Date createdTime;
+
     //@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:")
     @DbIgnore
     private Integer expiryCount;
@@ -137,4 +152,16 @@ public class AccountView {
 
     @DbIgnore
     private Date lastUpdatePwdDate;
-}
+
+    @DbField("a.pre_sku_ids")
+    private String preSkuIds;
+
+    @DbField("a.type")
+    private Integer accountType;
+
+    @DbIgnore
+    private Boolean isMjMirror;
+
+    @DbField("a.is_disable")
+    private Boolean isDisable;
+}

+ 0 - 2
netflix-dao/src/main/java/com/cyksj/model/request/RenewTimeUpReq.java

@@ -3,7 +3,6 @@ package com.cyksj.model.request;
 import lombok.Getter;
 import lombok.Setter;
 
-import javax.validation.constraints.Min;
 import javax.validation.constraints.NotNull;
 
 /*
@@ -25,7 +24,6 @@ public class RenewTimeUpReq {
 	 * 增加天数
 	 */
 	@NotNull(message = "天数不为空")
-	@Min(value = 1)
 	private Integer days;
 
 	/**

+ 116 - 0
netflix-dao/src/main/java/com/cyksj/model/views/AccountDisableView.java

@@ -0,0 +1,116 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.GroupsTrips;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: AccountDisableView
+ * 创建者: JavaZou
+ * 创建时间:2024/7/1 16:29
+ */
+@Getter
+@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")
+public class AccountDisableView {
+	@DbField("a.id")
+	private Long id;
+
+	@DbField("g.id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("g.second_type")
+	private Integer goodsSecondType;
+
+	@DbField("a.bank_card")
+	private String bankCard;
+
+	@DbField("a.account")
+	private String account;
+
+	@DbField("a.password")
+	private String password;
+
+	@DbField("a.is_month")
+	private Boolean isMonth;
+
+	@DbField("a.api_key")
+	private String apiKey;
+
+	@DbField("a.gpt_email_pwd")
+	private String gptEmailPwd;
+
+	@DbField("a.verify_codes")
+	private String verifyCodes;
+
+	@DbField("a.api_secret")
+	private String apiSecret;
+
+	@DbField("a.start_time")
+	private Date startTime;
+
+	@DbField("a.expiry_time")
+	private Date expiryTime;
+
+	@DbField("a.amount")
+	private BigDecimal amount;
+
+	/**
+	 * 国区id
+	 */
+	@DbField("a.cn_account")
+	private String cnAccount;
+
+	/**
+	 * 美区id
+	 */
+	@DbField("a.us_account")
+	private String usAccount;
+
+	@DbField("a.customer_service_id")
+	private Long customerServiceId;
+
+	@DbField("a.secret")
+	private String secret;
+
+	@DbField("gt.id")
+	private Long groupsId;
+
+	@DbField("gt.status")
+	private GroupsTrips.Status gtStatus;
+
+	/**
+	 * 账号备注
+	 */
+	@DbField("a.remark")
+	private String remark;
+
+	@DbField("a.email")
+	private String email;
+
+	@DbField("gdk.id")
+	private Long skuId;
+
+	/**
+	 * 规格
+	 */
+	@DbField("gdk.spec_val")
+	private String specVal;
+
+	@DbField("a.created_time")
+	private Date createdTime;
+
+	@DbField("a.is_disable")
+	private Boolean isDisable;
+}

+ 45 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CouponReceiptDetailView.java

@@ -0,0 +1,45 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.CouponUser;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: CouponReceiptDetailView
+ * 创建者: JavaZou
+ * 创建时间:2024/4/16 16:58
+ */
+@Getter
+@Setter
+@SearchBean(tables = "(select id,name from coupon where deleted is true :cid:) c inner join coupon_user cu on cu.coupon_id = c.id inner join user u on u.id = cu.user_id")
+public class CouponReceiptDetailView {
+
+	@DbField("cu.id")
+	private Long id;
+
+	@DbField("c.id")
+	private Long couponId;
+
+	@DbField("c.name")
+	private String name;
+
+	@DbField("u.id")
+	private Long userId;
+
+	@DbField("u.nickname")
+	private String nickname;
+
+	@DbField("cu.status")
+	private CouponUser.Status status;
+
+	@DbField("cu.created_time")
+	private Date receiptTime;
+
+	@DbField("cu.valid_end_time")
+	private Date expiryTime;
+}

+ 59 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CouponUsedDetailView.java

@@ -0,0 +1,59 @@
+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.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: CouponUsedDetailView
+ * 创建者: JavaZou
+ * 创建时间:2024/4/16 17:05
+ */
+@Getter
+@Setter
+@SearchBean(tables = "(select id,name from coupon where deleted is true :cid:) c inner join coupon_user cu on cu.coupon_id = c.id inner join user u on u.id = cu.user_id" +
+		" inner join order_don o on o.coupon_user_id = cu.id and o.status not in ('close','noPayment','refund')" +
+		" left join goods_don g on g.id = o.goods_id" +
+		" left join goods_don_sku sku on sku.id = o.sku_id")
+public class CouponUsedDetailView {
+
+	@DbField("cu.id")
+	private Long id;
+
+	@DbField("c.id")
+	private Long couponId;
+
+	@DbField("c.name")
+	private String name;
+
+	@DbField("u.id")
+	private Long userId;
+
+	@DbField("u.nickname")
+	private String nickname;
+
+	@DbField("o.order_no")
+	private String orderNo;
+
+	@DbField("cu.created_time")
+	private Date receiptTime;
+
+	@DbField("sku.id")
+	private Long skuId;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	@DbField("g.id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String goodsName;
+
+	@DbField("o.created_time")
+	private Date usedTime;
+}

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

@@ -124,6 +124,9 @@ public class CouponView {
 	@DbIgnore
 	private Integer usedNum;
 
+	@DbIgnore
+	private Integer receiptNum;
+
 	/**
 	 * 发放状态
 	 */
@@ -147,4 +150,4 @@ public class CouponView {
 
 	@DbField("c.created_time")
 	private Date createdTime;
-}
+}

+ 13 - 0
netflix-dao/src/main/resources/mapper/AccountBlockedReplaceRecordMapper.xml

@@ -0,0 +1,13 @@
+<?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.AccountBlockedReplaceRecordMapper">
+
+    <insert id="batchInsert">
+        insert ignore into
+        account_blocked_replace_record(`account`,`goods_id`,`created_time`,`update_time`)
+        values
+        <foreach collection="list" item="item" separator=",">
+            (#{item.account},#{item.goodsId},now(),now())
+        </foreach>
+    </insert>
+</mapper>

+ 7 - 0
netflix-dao/src/main/resources/mapper/CouponMapper.xml

@@ -41,4 +41,11 @@
         where cp.deleted is true
           and (cp.ex_code = #{couponExCode} or cdp.ex_code = #{couponExCode}) limit 1
     </select>
+
+    <select id="getCouponSku" resultType="com.cyksj.model.entity.GoodsDonSku">
+        select sku.id, sku.goods_id, sku.spec_val
+        from `coupon_sku` ck
+                 left join `goods_don_sku` gdk on gdk.id = ck.sku_id
+        where ck.coupon_id = #{couponId}
+    </select>
 </mapper>

+ 63 - 31
netflix-dao/src/main/resources/mapper/CouponUserMapper.xml

@@ -139,10 +139,49 @@
 
     <select id="couponPersonalList" resultType="com.cyksj.model.views.CouponUserView">
         select s.* from (select cu.id,
-               cu.channel,
-               cu.user_id,
-               c.id                     as couponId,
-               ca.id                    as couponActiveId,
+        cu.channel,
+        cu.user_id,
+        c.id                     as couponId,
+        ca.id                    as couponActiveId,
+        c.name,
+        c.goods_type,
+        c.type,
+        c.reduce_condition,
+        c.reduce_money,
+        c.discount,
+        c.use_scope,
+        c.goods_sku_ids,
+        c.is_valid_time,
+        cu.valid_start_time,
+        c.valid_days,
+        c.valid_hours,
+        cu.valid_end_time,
+        (case
+        when cu.status = 'used' then 'used'
+        when cu.valid_end_time &lt; now() then 'expired'
+        when ca.id is not null and ca.expiry_status = 0 then 'invalid'
+        when cu.valid_start_time > now() then 'notEffective'
+        else cu.status end) as couponUserStatus,
+        (case
+        when cu.status = 'used' then 4
+        when cu.valid_end_time &lt; now() then 2
+        when ca.id is not null and ca.expiry_status = 0 then 3
+        when cu.valid_start_time > now() then 1
+        when cu.status = 'unused' then 0
+        end)                 as orderby
+        from `coupon_user` cu
+        left join `coupon` c on c.id = cu.coupon_id
+        left join `coupon_active` ca on ca.id = cu.coupon_active_id
+        where cu.user_id = #{userId}
+        <if test="couponId !=null">
+            and cu.coupon_id = #{couponId}
+        </if>
+        and cu.channel != 'exCode'
+        order by `orderby`)s where s.couponUserStatus != 'expired' and s.couponUserStatus != 'invalid'
+    </select>
+
+    <select id="getNewUserWelfareCouponsByUserId" resultType="com.cyksj.model.views.CouponUserView">
+        select cu.*,
                c.name,
                c.goods_type,
                c.type,
@@ -151,33 +190,28 @@
                c.discount,
                c.use_scope,
                c.goods_sku_ids,
-               c.is_valid_time,
                cu.valid_start_time,
-               c.valid_days,
-               c.valid_hours,
                cu.valid_end_time,
-               (case
-                    when cu.status = 'used' then 'used'
-                    when cu.valid_end_time &lt; now() then 'expired'
-                    when ca.id is not null and ca.expiry_status = 0 then 'invalid'
-                    when cu.valid_start_time > now() then 'notEffective'
-                    else cu.status end) as couponUserStatus,
-               (case
-                    when cu.status = 'used' then 4
-                    when cu.valid_end_time &lt; now() then 2
-                    when ca.id is not null and ca.expiry_status = 0 then 3
-                    when cu.valid_start_time > now() then 1
-                    when cu.status = 'unused' then 0
-                   end)                 as orderby
-        from `coupon_user` cu
-                 left join `coupon` c on c.id = cu.coupon_id
-                 left join `coupon_active` ca on ca.id = cu.coupon_active_id
-        where cu.user_id = #{userId}
-          and cu.channel != 'exCode'
-        order by `orderby`)s where s.couponUserStatus != 'expired' and s.couponUserStatus != 'invalid'
+               unix_timestamp(cu.valid_end_time) * 1000 as validEndTimestamp
+        from (select coupon_id,
+                     valid_start_time,
+                     valid_end_time,
+                     status as couponUserStatus
+              from `coupon_user`
+              where channel = #{channel}
+                and user_id = #{userId}
+                and valid_end_time > #{now}
+                 and status = 'unused' limit 1) cu
+                 inner join coupon c on c.id = cu.coupon_id
     </select>
 
-    <select id="getNewUserWelfareCouponsByUserId" resultType="com.cyksj.model.views.CouponUserView">
+    <select id="selectCouponUserNumData" resultType="java.util.Map">
+        select count(if(status = 'used', 1, NULL)) usedNum, count(*) receiptNum
+        from coupon_user
+        where coupon_id = #{couponId}
+    </select>
+
+    <select id="getCouponDetailById" resultType="com.cyksj.model.views.CouponUserView">
         select cu.*,
                c.name,
                c.goods_type,
@@ -195,10 +229,8 @@
                      valid_end_time,
                      status as couponUserStatus
               from `coupon_user`
-              where channel = #{channel}
-                and user_id = #{userId}
-                and valid_end_time > #{now}
-                 and status = 'unused' limit 1) cu
+              where user_id = #{userId}
+                and coupon_id = #{couponId} limit 1) cu
                  inner join coupon c on c.id = cu.coupon_id
     </select>
 </mapper>

+ 7 - 1
netflix-dao/src/main/resources/mapper/OrderDonMapper.xml

@@ -103,7 +103,7 @@
     </select>
 
     <select id="selectCouponCodeUserNum" resultType="java.lang.Integer">
-        select count(distinct user_id) from order_don where ds_popularize_id = #{dsPopularizeId}
+        select count(distinct user_id) from order_don where (ds_popularize_id = #{dsPopularizeId} or coupon_ex_code = #{exCode})
         and status not in
         <foreach collection="noOrderAllStatus" item="item" open="(" separator="," close=")">
             #{item}
@@ -190,4 +190,10 @@
         group by o.goods_id
         order by count(*) desc limit 1
     </select>
+
+    <select id="getCouponUsedMoney" resultType="java.math.BigDecimal">
+        select sum(money) - sum(ifnull(refund_money, 0))
+        from (select id from coupon_user where coupon_id = #{couponId}) cu
+                 inner join order_don o on o.coupon_user_id = cu.id and o.status not in ('close', 'noPayment')
+    </select>
 </mapper>

+ 7 - 11
netflix-service/src/main/java/com/cyksj/service/coupon/CouponFontService.java

@@ -20,20 +20,10 @@ public interface CouponFontService {
 	 */
 	void collectCoupon(CouponCollectReq couponCollectReq, Long userId);
 
-	/**
-	 * 领取推荐优惠券
-	 */
-	void collectRecommendCoupon(CouponCollectReq couponCollectReq, Long userId);
-
-	/**
-	 * 一键领取推荐优惠券
-	 */
-	void collectWholeRecommendCoupon(Long userId);
-
 	/**
 	 * 可用/不可用优惠券
 	 */
-	Page<CouponUserView> getAvailableCouponList(Long skuId, Long couponId, Long userId, Boolean isRenew, Long start, Long limit);
+	Page<CouponUserView> getAvailableCouponList(Long skuId, Long couponId, Long userId, Boolean isRenew, Long start, Long limit, String lang);
 
 	/**
 	 * 优惠券状态
@@ -66,4 +56,10 @@ public interface CouponFontService {
 	 * 新用户福利优惠券
 	 */
 	CouponUserView getNewUserWelfareCoupons(long userId, DateTime now);
+
+	CouponUserView getCouponDetailById(long userId, Long couponId, String lang);
+
+	CouponUserView receiveCoupon(long userId, Long couponId, String lang);
+
+	String setCouponSkuLanguage(Long couponId, String lang);
 }

+ 35 - 49
netflix-service/src/main/java/com/cyksj/service/coupon/impl/CouponFontServiceImpl.java

@@ -19,6 +19,7 @@ import com.cyksj.model.request.ChannelPopularizeCouponReq;
 import com.cyksj.model.request.CouponCollectReq;
 import com.cyksj.model.views.*;
 import com.cyksj.service.coupon.CouponFontService;
+import com.cyksj.service.translations.BackInfoTranslationsFrontService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.param.Operator;
 import com.ejlchina.searcher.util.MapUtils;
@@ -62,6 +63,8 @@ public class CouponFontServiceImpl implements CouponFontService {
 
 	private final UserMapper userMapper;
 
+	private final BackInfoTranslationsFrontService backInfoTranslationsFrontService;
+
 	@Override
 	@Transactional(rollbackFor = Throwable.class)
 	public void collectCoupon(CouponCollectReq couponCollectReq, Long userId) {
@@ -86,45 +89,7 @@ public class CouponFontServiceImpl implements CouponFontService {
 	}
 
 	@Override
-	@Transactional(rollbackFor = Throwable.class)
-	public void collectRecommendCoupon(CouponCollectReq couponCollectReq, Long userId) {
-		collectCommonCheck(couponCollectReq.getCouponId(), userId);
-
-		receiveCouponUser(couponCollectReq.getCouponId(), userId, CouponUser.Channel.recommend);
-	}
-
-	@Override
-	@Transactional(rollbackFor = Throwable.class)
-	public void collectWholeRecommendCoupon(Long userId) {
-		CouponNewUserView couponNewUserView = beanSearcher.searchFirst(CouponNewUserView.class, MapUtils.builder().field(CouponNewUserView::getUserId, userId).op(Operator.Equal).build());
-		Boolean isNewUser = true;
-		if (couponNewUserView != null) {
-			isNewUser = false;
-		}
-		//查询所有可领取的推荐优惠券
-		List<CouponAvailableRecommendView> couponAvailableRecommendViews = recommendMapper.getRecommendCouponList(userId, isNewUser);
-		couponAvailableRecommendViews.stream().forEach(data -> {
-			//领取优惠券
-			CouponUser couponUser = new CouponUser();
-			couponUser.setUserId(userId);
-			couponUser.setCouponId(data.getCouponId());
-			//推荐渠道
-			couponUser.setChannel(CouponUser.Channel.recommend);
-			couponUser.setStatus(CouponUser.Status.unused);
-			couponUser.setRecommendId(data.getRecommendId());
-			//优惠券有效时间
-			this.updateCouponUserValidTime(data.getCouponId(), couponUser);
-			try {
-				couponUserMapper.insert(couponUser);
-			} catch (DuplicateKeyException e) {
-				//插入失败继续插入 不影响
-				log.info("用户:{}一键领取推荐优惠券{}插入数据错误", userId, data.getCouponId());
-			}
-		});
-	}
-
-	@Override
-	public Page<CouponUserView> getAvailableCouponList(Long skuId, Long couponId, Long userId, Boolean isRenew, Long start, Long limit) {
+	public Page<CouponUserView> getAvailableCouponList(Long skuId, Long couponId, Long userId, Boolean isRenew, Long start, Long limit, String lang) {
 		DateTime now = DateTime.now();
 		Long goodsId = null;
 		//实物还是虚物
@@ -137,10 +102,9 @@ public class CouponFontServiceImpl implements CouponFontService {
 			goodsId = goodsDonSkuView.getGoodsId();
 		}
 		Page<CouponUserView> availableCouponList = couponUserMapper.getAvailableCouponList(skuId, couponId, goodsId, userId, isRenew, new Page<>(start, limit));
-		Optional.ofNullable(availableCouponList).ifPresent(page->{
-			page.getRecords().stream().forEach(data->{
-				String str = couponSkuMapper.selectGoodsSkuStr(data.getCouponId());
-				data.setGoodsSkuStr(str.replaceAll(",", "/").replaceAll(";", ""));
+		Optional.ofNullable(availableCouponList).ifPresent(page -> {
+			page.getRecords().stream().forEach(data -> {
+				data.setGoodsSkuStr(backInfoTranslationsFrontService.setCouponGoodsSkuStrLanguage(data.getCouponId(), lang));
 				List<CouponSkuView> couponSkus = couponSkuMapper.getGoodsSkuByCouponId(data.getCouponId());
 				try {
 					data.setGoodsSkuIds(Jsons.toJson(couponSkus));
@@ -149,12 +113,6 @@ public class CouponFontServiceImpl implements CouponFontService {
 				}
 
 				if (!data.getIsAvailable()) {
-//					data.setReason(String.format("仅限%s", data.getGoodsSkuStr()));
-//					if (data.getUseScope() == Coupon.UseScope.renew) {
-//						data.setReason(String.format("%s续费时可使用", data.getReason()));
-//					} else if (data.getUseScope() == Coupon.UseScope.orders) {
-//						data.setReason(String.format("%s下单时可使用", data.getReason()));
-//					}
 					if (data.getUseScope() == Coupon.UseScope.renew) {
 						data.setReason(I18nMessageUtil.getI18nMsg("coupon_sku_not_available_renew_error"));
 					} else if (data.getUseScope() == Coupon.UseScope.orders) {
@@ -372,4 +330,32 @@ public class CouponFontServiceImpl implements CouponFontService {
 	public CouponUserView getNewUserWelfareCoupons(long userId, DateTime now) {
 		return couponUserMapper.getNewUserWelfareCouponsByUserId(userId, CouponUser.Channel.new_welfare, now);
 	}
+
+	@Override
+	public String setCouponSkuLanguage(Long couponId, String lang) {
+		return backInfoTranslationsFrontService.setCouponGoodsSkuStrLanguage(couponId, lang);
+	}
+
+	@Override
+	public CouponUserView getCouponDetailById(long userId, Long couponId, String lang) {
+		CouponUserView couponUserView = couponUserMapper.getCouponDetailById(userId, couponId);
+		if (couponUserView != null) {
+			//多语言
+			backInfoTranslationsFrontService.setFieldLanguage(CouponUserView.class, couponUserView, BackInfoTranslations.Type.coupon.ordinal(), couponUserView.getCouponId(), lang);
+
+			String goodsSkuStr = backInfoTranslationsFrontService.setCouponGoodsSkuStrLanguage(couponId, lang);
+			couponUserView.setGoodsSkuStr(goodsSkuStr);
+		}
+		return couponUserView;
+	}
+
+	@Override
+	public CouponUserView receiveCoupon(long userId, Long couponId, String lang) {
+		try {
+			receiveCouponUser(couponId, userId, CouponUser.Channel.manual);
+		} catch (Exception e) {
+			return null;
+		}
+		return getCouponDetailById(userId, couponId, lang);
+	}
 }

+ 11 - 0
netflix-service/src/main/java/com/cyksj/service/mange/AccountCommonService.java

@@ -0,0 +1,11 @@
+package com.cyksj.service.mange;
+
+/*
+ *项目名: netflix
+ *文件名: AccountCommonService
+ *创建者: JavaZou
+ *创建时间:2023/8/16 17:12
+ */
+public interface AccountCommonService {
+	Boolean checkIsDupAccount(Long goodsId, String account);
+}

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

@@ -51,4 +51,6 @@ public interface CmsAccountService extends IService<Account> {
 	void analysisAmericaAppidAccount(Long goodsId, Long skuId, List<Object> accountList);
 
 	void readFileAndImportEmail(MultipartFile file) throws Exception;
+
+	void batchImportBlockedAccount(Long goodsId, List<Object> accountBlockedList);
 }

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/mange/CmsGroupService.java

@@ -17,4 +17,6 @@ public interface CmsGroupService extends IService<GroupsTrips> {
     void setAccount(GroupsTrips groupsTrips) throws Exception;
 
     void replaceTripsAccount(ReplaceTripsAccountReq req);
+
+	void sendChangeAccountMsg(Long groupsId, Long goodsId, String account);
 }

+ 37 - 0
netflix-service/src/main/java/com/cyksj/service/mange/account/AccountCommonServiceImpl.java

@@ -0,0 +1,37 @@
+package com.cyksj.service.mange.account;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.mapper.AccountMapper;
+import com.cyksj.model.entity.Account;
+import com.cyksj.service.mange.AccountCommonService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+/*
+ *项目名: netflix
+ *文件名: AccountCommonServiceImpl
+ *创建者: JavaZou
+ *创建时间:2023/8/16 17:12
+ */
+@Service
+@RequiredArgsConstructor
+public class AccountCommonServiceImpl implements AccountCommonService {
+
+	private final AccountMapper accountMapper;
+
+	@Override
+	public Boolean checkIsDupAccount(Long goodsId, String account) {
+		LambdaQueryWrapper<Account> wrapper = Wrappers.lambdaQuery(Account.class)
+				.eq(Account::getAccount, account);
+		if (Constant.GPT_GOODS_IDS.contains(goodsId)) {
+			wrapper.in(Account::getGoodsId, Constant.GPT_GOODS_IDS);
+		} else {
+			wrapper.eq(Account::getGoodsId, goodsId);
+		}
+		int count = accountMapper.selectCount(wrapper);
+		if (count > 0) return true;
+		return false;
+	}
+}

+ 33 - 0
netflix-service/src/main/java/com/cyksj/service/mange/account/CmsAccountServiceImpl.java

@@ -1,9 +1,11 @@
 package com.cyksj.service.mange.account;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.Validator;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -11,8 +13,10 @@ import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.common.util.StringUtil;
+import com.cyksj.mapper.AccountBlockedReplaceRecordMapper;
 import com.cyksj.mapper.AccountMapper;
 import com.cyksj.mapper.AccountUpdatePasswordRecordMapper;
+import com.cyksj.mapper.GoodsDonMapper;
 import com.cyksj.mapper.manage.AutoUpdateAccountPwdLogMapper;
 import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.mapper.sys.SysEmailMapper;
@@ -66,6 +70,10 @@ public class CmsAccountServiceImpl extends ServiceImpl<AccountMapper, Account> i
 
 	private final SysConfigService sysConfigService;
 
+	private final GoodsDonMapper goodsDonMapper;
+
+	private final AccountBlockedReplaceRecordMapper accountBlockedReplaceRecordMapper;
+
 	@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));
@@ -231,6 +239,31 @@ public class CmsAccountServiceImpl extends ServiceImpl<AccountMapper, Account> i
 		System.out.println(Jsons.toJson(error));
 	}
 
+	@Override
+	public void batchImportBlockedAccount(Long goodsId, List<Object> accountBlockedList) {
+		GoodsDon goodsDon = goodsDonMapper.selectById(goodsId);
+		Assert.notNull(goodsDon, "平台不存在");
+		List<AccountBlockedReplaceRecord> list = new ArrayList<>();
+		accountBlockedList.forEach(accountBlocked->{
+			Map<String, Object> map = Jsons.toMap(accountBlocked);
+			String blockedAccount = map.get("0").toString();
+			if (!Validator.isEmail(blockedAccount)) {
+				return;
+			}
+			AccountBlockedReplaceRecord accountBlockedReplaceRecord = new AccountBlockedReplaceRecord();
+			accountBlockedReplaceRecord.setGoodsId(goodsId);
+			accountBlockedReplaceRecord.setAccount(blockedAccount);
+			list.add(accountBlockedReplaceRecord);
+			if (list.size() == 400) {
+				accountBlockedReplaceRecordMapper.batchInsert(list);
+				list.clear();
+			}
+		});
+		if (list.size() > 0) {
+			accountBlockedReplaceRecordMapper.batchInsert(list);
+		}
+	}
+
 	/**
 	 *
 	 * @param goodsId

+ 33 - 0
netflix-service/src/main/java/com/cyksj/service/mange/group/CmsGroupServiceImpl.java

@@ -1,5 +1,6 @@
 package com.cyksj.service.mange.group;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateField;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
@@ -16,6 +17,7 @@ import com.cyksj.mapper.manage.DelGroupsTripsRecordMapper;
 import com.cyksj.mapper.manage.GroupsTripsAccountReplaceRecordMapper;
 import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.model.entity.*;
+import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.request.ReplaceTripsAccountReq;
 import com.cyksj.model.views.GroupsAccountView;
 import com.cyksj.redis.RedisService;
@@ -341,4 +343,35 @@ public class CmsGroupServiceImpl extends ServiceImpl<GroupsMapper,GroupsTrips> i
             }
         });
     }
+
+    @Override
+    public void sendChangeAccountMsg(Long groupsId, Long goodsId, String account) {
+        GoodsDon goodsDon = goodsDonMapper.selectById(goodsId);
+        String title = goodsDon != null ? goodsDon.getTitle() : "车票";
+        DateTime now = DateTime.now();
+        Boolean isPrd = envCommonService.isPrdEnv();
+        List<GroupsRelationView> groupsRelations = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder().field(GroupsRelationView::getGroupsId, groupsId).build());
+        if (CollUtil.isEmpty(groupsRelations)) {
+            return;
+        }
+        groupsRelations.forEach(relation -> {
+            if (relation.getExpiryTime() == null) {
+                return;
+            }
+            //账号有效期小于5天的人,不发账号替换/改密码短信提醒
+            if (now.after(DateUtil.offsetDay(relation.getExpiryTime(), -5))) {
+                return;
+            }
+            //去掉GPT过滤平台
+            if (Constant.CHANGE_ACCOUNT_PWD_FILTER_GIDS.get(1) == goodsId) {
+                return;
+            }
+            if (relation.getUserId() != 0 && isPrd) {
+                try {
+                    smsService.sendSmsToRelationUser(relation.getUserId(), String.format(Constant.CHANGE_GROUPS_TRIPS_ACCOUNT, title, envCommonService.getDomain()));
+                } catch (Exception e) {
+                }
+            }
+        });
+    }
 }

+ 121 - 2
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -297,7 +297,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			orderDon.setPopularizeId(payRequest.getPopularizeId());
 		}
 		//扣除使用优惠券、余额的订单金额
-//		deductOrderMoney(orderDon, couponUser, payRequest.getBalance(), user, sku.getPrice(), goodsDon.getType());
+		deductOrderMoney(orderDon, couponUser, payRequest.getBalance(), user, sku.getPrice(), goodsDon.getType());
 
 		orderDon.setSkuId(payRequest.getSkuId());
 		orderDon.setRelationId(relationId);
@@ -406,6 +406,10 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 					clearUserLockingRelation(groupsRelation, orderDon);
 				}
 			}
+			//返还优惠券
+			if (orderDon.getCouponUserId() != 0) {
+				couponFontService.updateOrderDonCouponStatus(orderDon);
+			}
 		}
 	}
 
@@ -576,7 +580,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 		orderDon.setRealMoney(orderDon.getMoney());
 		//扣除使用优惠券、余额的订单金额
-//		deductOrderMoney(orderDon, couponUser, payRequest.getBalance(), user, price, goodsDon.getType());
+		deductOrderMoney(orderDon, couponUser, payRequest.getBalance(), user, sku.getPrice(), goodsDon.getType());
 		if ("TWD".equals(payRequest.getCurrency())){
 			orderDon.setMoney(orderDon.getMoney().setScale(-2, RoundingMode.HALF_UP));
 		}
@@ -988,6 +992,69 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 	}
 
+	/**
+	 * 使用推广者的优惠码增加上下级
+	 */
+	private void addDistributeCouponCode(Long userId, String couponExCode) {
+		UserDistributeShared userDistributeShared = userDistributeSharedMapper.selectOne(Wrappers.lambdaQuery(UserDistributeShared.class)
+				.eq(UserDistributeShared::getUserId, userId).last("limit 1"));
+		if (userDistributeShared == null) {
+			CouponDistributePopularize couponDistributePopularize = couponDistributePopularizeMapper.selectOne(Wrappers.lambdaQuery(CouponDistributePopularize.class).eq(CouponDistributePopularize::getExCode, couponExCode).last("limit 1"));
+			Optional.ofNullable(couponDistributePopularize).ifPresent(popularize -> {
+				try {
+					Long sharedId;
+					//是否是普通推广专属关联
+					if (popularize.getIsGeneral()) {
+						sharedId = popularize.getUserId();
+					} else {
+						UserDistribute userDistribute = userDistributeMapper.selectById(popularize.getDistributeId());
+						if (userDistribute == null || !userDistribute.getDeleted()) {
+							return;
+						}
+						sharedId = userDistribute.getUserId();
+					}
+					if (sharedId.equals(userId)) {
+						return;
+					}
+					UserDistributeShared ud = new UserDistributeShared();
+					ud.setUserId(userId);
+					ud.setSharedId(sharedId);
+					ud.setRemark("优惠码");
+					userDistributeSharedMapper.insert(ud);
+					log.info("userId:{}使用优惠码:{}与推广用户sharedId:{}建立关系", userId, couponExCode, sharedId);
+				} catch (DuplicateKeyException e) {
+
+				}
+			});
+		}
+	}
+
+	/**
+	 * 保存转账记录
+	 */
+	public void saveTransferRecord(Long userId, String donNo, String account, String name, BigDecimal money, BigDecimal points, String type, Integer scope, String body, String error) throws Exception {
+		TransferAccountsRecord record = new TransferAccountsRecord();
+		JSONObject re = Jsons.parseObject(body, JSONObject.class);
+		JSONObject response = Jsons.parseObject(re.get("alipay_fund_trans_uni_transfer_response"), JSONObject.class);
+		String transactionId = response.getStr("order_id");
+		String transDate = response.getStr("trans_date");
+		record.setUserId(userId);
+		record.setAccount(account);
+		record.setName(name);
+		record.setMoney(money);
+		record.setType(type);
+		record.setScope(scope);
+		Optional.ofNullable(error).ifPresent(msg -> {
+			record.setErrorMsg(msg);
+			record.setStatus(0);
+		});
+		record.setPoints(points);
+		record.setTransferOutNo(donNo);
+		record.setTransactionId(transactionId);
+		Optional.ofNullable(transDate).ifPresent(transferTime -> record.setTransferTime(DateTime.of(transferTime, "yyyy-MM-dd HH:mm:ss")));
+		transferAccountsRecordMapper.insert(record);
+	}
+
 	/**
 	 * @param orderDon 续费订单
 	 * @param afterSku 续费之后的规格
@@ -1292,4 +1359,56 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 		return user;
 	}
+
+
+	/**
+	 * 使用优惠营销 订单金额抵扣
+	 */
+	public void deductOrderMoney(OrderDon orderDon, CouponUser couponUser, BigDecimal balance, User user, BigDecimal skuMoney, Integer goodsType) {
+		BigDecimal first_money = orderDon.getMoney();
+		//存在优惠券
+		if (couponUser != null) {
+			Long couponId = couponUser.getCouponId();
+			Coupon coupon = couponMapper.getCouponById(couponId);
+			BigDecimal couponMoney = null;
+			BigDecimal payMoney = orderDon.getMoney();
+			BigDecimal needDeductMoney = payMoney;
+			if (orderDon.getOriMoney() == null) {
+				orderDon.setOriMoney(payMoney);
+			}
+			if (orderDon.getIsDp() != null && orderDon.getIsDp()) {
+				needDeductMoney = needDeductMoney.subtract(orderDon.getDpMoney());
+			}
+			if (coupon.getType() == Coupon.Type.discount) {
+				couponMoney = needDeductMoney.multiply(BigDecimal.valueOf(1).subtract(coupon.getDiscount()));
+				//需支付金额
+				orderDon.setMoney(payMoney.subtract(couponMoney));
+
+				orderDon.setOriMoney(orderDon.getOriMoney().multiply(coupon.getDiscount()));
+				//记录折扣 用于分销
+				couponUser.setDiscount(coupon.getDiscount());
+				couponUserMapper.updateById(couponUser);
+			} else if (coupon.getType() == Coupon.Type.reduce) {
+				//设备
+				if (goodsType == 2) {
+					if (skuMoney.compareTo(coupon.getReduceCondition()) < 0) {
+						throw BusinessRuntimeException.getInstance(I18nMessageUtil.getI18nMsg("sys_error"));
+					}
+				}
+				BigDecimal subtractMoney = payMoney.subtract(coupon.getReduceMoney());
+				orderDon.setMoney(subtractMoney);
+				couponMoney = coupon.getReduceMoney();
+
+				orderDon.setOriMoney(orderDon.getOriMoney().subtract(coupon.getReduceMoney()));
+			}
+			if (couponMoney != null && couponMoney.compareTo(first_money) >= 0) {
+				throw BusinessRuntimeException.getInstance(I18nMessageUtil.getI18nMsg("coupon_money_error"));
+			}
+			orderDon.setCouponMoney(couponMoney);
+			orderDon.setCouponUserId(couponUser.getId());
+		}
+
+		//存在余额
+//		deductBalancePayOrderMoney(orderDon, balance, user);
+	}
 }

+ 11 - 8
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupsRelationNetflixServiceImpl.java

@@ -155,14 +155,17 @@ public class GroupsRelationNetflixServiceImpl implements GroupsRelationNetflixSe
 	 */
 	@Override
 	public void timingSetNetflix(Integer num, String nickname, String account, String password, Date expiryTime) {
-		String key = RedisService.key.NETFLIX_SET_LIMIT_TIME.getName();
-		if (!redisService.setNx(key, 1L, 30L)) {
-			jobManager.addJob(30001, () -> {
-				timingSetNetflix(num, nickname, account, password, expiryTime);
-			});
-		} else {
-			setNetflixSeatNum(num, nickname, account, password, expiryTime, null);
-			log.info("当前时间:{}开始调用设置奈飞座位信息接口", DateTime.now());
+		try {
+			String key = RedisService.key.NETFLIX_SET_LIMIT_TIME.getName();
+			if (!redisService.setNx(key, 1L, 30L)) {
+				jobManager.addJob(30001, () -> {
+					timingSetNetflix(num, nickname, account, password, expiryTime);
+				});
+			} else {
+				setNetflixSeatNum(num, nickname, account, password, expiryTime, null);
+				log.info("当前时间:{}开始调用设置奈飞座位信息接口", DateTime.now());
+			}
+		} catch (Exception e) {
 		}
 	}
 }

+ 10 - 0
netflix-service/src/main/java/com/cyksj/service/translations/BackInfoTranslationsFrontService.java

@@ -2,6 +2,7 @@ package com.cyksj.service.translations;
 
 import com.cyksj.model.entity.GoodsDonSku;
 import com.cyksj.model.manage.views.GoodsDonViewer;
+import com.cyksj.model.views.CouponView;
 import com.cyksj.model.views.GoodsFrontListCategoryView;
 import com.cyksj.model.views.GoodsFrontListView;
 
@@ -27,4 +28,13 @@ public interface BackInfoTranslationsFrontService {
 	String setSpecVal(Long skuId, String lang);
 
 	String setGoodsTitle(Long goodsId, String lang);
+
+	void setCouponLanguage(CouponView couponView, String lang);
+
+	void setFieldLanguage(Class<?> tclass, Object obj, Integer type, Long funcId, String lang);
+
+	/**
+	 * 设置优惠券规格展示多语言
+	 */
+	String setCouponGoodsSkuStrLanguage(Long couponId, String lang);
 }

+ 68 - 5
netflix-service/src/main/java/com/cyksj/service/translations/impl/BackInfoTranslationsFrontServiceImpl.java

@@ -4,19 +4,21 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.mapper.BackInfoTranslationsMapper;
+import com.cyksj.mapper.manage.coupon.CouponMapper;
+import com.cyksj.mapper.manage.coupon.CouponSkuMapper;
 import com.cyksj.model.entity.BackInfoTranslations;
 import com.cyksj.model.entity.GoodsDonSku;
+import com.cyksj.model.entity.UserPageLanguage;
 import com.cyksj.model.manage.views.GoodsDonViewer;
-import com.cyksj.model.views.GoodsDonSkuFrontView;
-import com.cyksj.model.views.GoodsDonSpecFrontView;
-import com.cyksj.model.views.GoodsFrontListCategoryView;
-import com.cyksj.model.views.GoodsFrontListView;
+import com.cyksj.model.views.*;
 import com.cyksj.service.translations.BackInfoTranslationsFrontService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 import java.lang.reflect.Field;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 项目名: yhlxj2
@@ -29,6 +31,10 @@ import java.util.List;
 public class BackInfoTranslationsFrontServiceImpl implements BackInfoTranslationsFrontService {
 	private final BackInfoTranslationsMapper backInfoTranslationsMapper;
 
+	private final CouponMapper couponMapper;
+
+	private final CouponSkuMapper couponSkuMapper;
+
 	@Override
 	public void setGoodsDetailLanguage(GoodsFrontListView views, String lang) {
 		if (views == null) {
@@ -112,8 +118,24 @@ public class BackInfoTranslationsFrontServiceImpl implements BackInfoTranslation
 		return null;
 	}
 
+	@Override
+	public void setCouponLanguage(CouponView couponView, String lang) {
+		setFieldLanguage(couponView.getClass(), couponView, BackInfoTranslations.Type.coupon.ordinal(), couponView.getId(), lang);
+		if (couponView.getClassificationId() != null) {
+			BackInfoTranslations classificationTranslation = backInfoTranslationsMapper.selectOne(Wrappers.lambdaQuery(BackInfoTranslations.class)
+					.eq(BackInfoTranslations::getType, BackInfoTranslations.Type.coupon_classification.ordinal())
+					.eq(BackInfoTranslations::getLang, lang)
+					.eq(BackInfoTranslations::getFuncId, couponView.getClassificationId())
+					.eq(BackInfoTranslations::getFieldName, "name"));
+			if (classificationTranslation != null) {
+				couponView.setCouponClassificationName(classificationTranslation.getDesp());
+			}
+		}
+	}
+
+	@Override
 	public void setFieldLanguage(Class<?> tclass, Object obj, Integer type, Long funcId, String lang) {
-		if (StrUtil.isEmpty(lang)) {
+		if (StrUtil.isEmpty(lang) || StrUtil.equals(UserPageLanguage.Language.zh_HK.name(), lang)) {
 			return;
 		}
 		List<BackInfoTranslations> backInfoTranslations = backInfoTranslationsMapper.selectList(Wrappers.lambdaQuery(BackInfoTranslations.class)
@@ -134,4 +156,45 @@ public class BackInfoTranslationsFrontServiceImpl implements BackInfoTranslation
 			});
 		}
 	}
+
+
+	@Override
+	public String setCouponGoodsSkuStrLanguage(Long couponId, String lang) {
+		if (StrUtil.isEmpty(lang) || StrUtil.equals(UserPageLanguage.Language.zh_HK.name(), lang)) {
+			String str = couponSkuMapper.selectGoodsSkuStr(couponId);
+			str = str.replaceAll(",", "/").replaceAll(";", "");
+			return str;
+		}
+
+		List<GoodsDonSku> goodsDonSkus = couponMapper.getCouponSku(couponId);
+		StringBuilder skuGoodsStrSb = new StringBuilder(128);
+		Map<Long, String> map = new HashMap<>();
+		goodsDonSkus.forEach(sku -> {
+			String title = map.get(sku.getGoodsId());
+			if (StrUtil.isEmpty(title)) {
+				BackInfoTranslations backGoodsInfoTranslations = backInfoTranslationsMapper.selectOne(Wrappers.lambdaQuery(BackInfoTranslations.class)
+						.eq(BackInfoTranslations::getType, BackInfoTranslations.Type.goods.ordinal())
+						.eq(BackInfoTranslations::getLang, lang)
+						.eq(BackInfoTranslations::getFieldName, "title")
+						.eq(BackInfoTranslations::getFuncId, sku.getGoodsId()));
+				if (backGoodsInfoTranslations != null) {
+					title = backGoodsInfoTranslations.getDesp();
+					map.put(sku.getGoodsId(), title);
+				}
+			}
+			BackInfoTranslations backSkuInfoTranslations = backInfoTranslationsMapper.selectOne(Wrappers.lambdaQuery(BackInfoTranslations.class)
+					.eq(BackInfoTranslations::getType, BackInfoTranslations.Type.sku.ordinal())
+					.eq(BackInfoTranslations::getLang, lang)
+					.eq(BackInfoTranslations::getFieldName, "specVal")
+					.eq(BackInfoTranslations::getFuncId, sku.getId()));
+			if (skuGoodsStrSb.length() > 0) {
+				skuGoodsStrSb.append("/");
+			}
+			if (backSkuInfoTranslations != null) {
+				skuGoodsStrSb.append(title).append(" ").append(backSkuInfoTranslations.getDesp());
+			}
+		});
+
+		return skuGoodsStrSb.toString();
+	}
 }

+ 25 - 146
netflix-web/src/main/java/com/cyksj/web/controller/coupon/CouponFrontController.java

@@ -4,7 +4,6 @@ import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.cyksj.common.annotation.NoSubmit;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.i18n.I18nMessageUtil;
 import com.cyksj.common.util.Jsons;
@@ -12,14 +11,12 @@ import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.manage.coupon.CouponMapper;
-import com.cyksj.mapper.manage.coupon.CouponRecommendMapper;
 import com.cyksj.mapper.manage.coupon.CouponSkuMapper;
 import com.cyksj.mapper.manage.coupon.CouponUserMapper;
 import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
 import com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper;
 import com.cyksj.model.dto.CouponPopularizeDto;
 import com.cyksj.model.entity.*;
-import com.cyksj.model.request.ChannelPopularizeCouponReq;
 import com.cyksj.model.request.CouponCollectReq;
 import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
@@ -29,9 +26,9 @@ import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.param.Operator;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
-import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import javax.servlet.http.HttpServletRequest;
 import java.math.BigDecimal;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -60,47 +57,25 @@ public class CouponFrontController {
 
 	private final UserDistributeMapper userDistributeMapper;
 
-	private final CouponRecommendMapper couponRecommendMapper;
+	private final HttpServletRequest request;
 
 	private final UserDistributeSharedMapper userDistributeSharedMapper;
 
 	private final UserMapper userMapper;
-
-	/**
-	 * 优惠券领取中心列表
-	 */
-	@GetMapping("/center/list")
-	public Result<Page<CouponActiveView>> couponCenterList(@RequestParam(defaultValue = "1") Long start, @RequestParam(defaultValue = "5") Long limit) {
-		Long userId = StpUserUtil.getLoginIdAsLong();
-		Page<CouponActiveView> page = couponUserMapper.couponCenterList(userId, new Page<>(start, limit));
-		page.getRecords().forEach(data -> {
-			String str = couponSkuMapper.selectGoodsSkuStr(data.getCouponId());
-			data.setGoodsSkuStr(str.replaceAll(",", "/").replaceAll(";", ""));
-			List<CouponSkuView> couponSkus = couponSkuMapper.getGoodsSkuByCouponId(data.getCouponId());
-			try {
-				data.setGoodsSkuIds(Jsons.toJson(couponSkus));
-			} catch (Exception e) {
-
-			}
-		});
-		return GatewayResponse.SUCCESS.newBuilder().toResult(page);
-	}
-
 	/**
 	 * 个人优惠券列表
 	 */
 	@GetMapping("/personal/list")
-	public Result<Page<CouponUserView>> couponPersonalList(@RequestParam(defaultValue = "1") Long start, @RequestParam(defaultValue = "5") Long limit) {
+	public Result<Page<CouponUserView>> couponPersonalList(@RequestParam(defaultValue = "1") Long start, @RequestParam(defaultValue = "5") Long limit, Long couponId) {
+		String lang = request.getHeader("lang");
 		Long userId = StpUserUtil.getLoginIdAsLong();
-		Page<CouponUserView> page = couponUserMapper.couponPersonalList(userId, new Page<>(start, limit));
+		Page<CouponUserView> page = couponUserMapper.couponPersonalList(userId, new Page<>(start, limit), couponId);
 		page.getRecords().forEach(data -> {
-			String str = couponSkuMapper.selectGoodsSkuStr(data.getCouponId());
-			data.setGoodsSkuStr(str.replaceAll(",", "/").replaceAll(";", ""));
+			data.setGoodsSkuStr(couponFontService.setCouponSkuLanguage(data.getCouponId(), lang));
 			List<CouponSkuView> couponSkus = couponSkuMapper.getGoodsSkuByCouponId(data.getCouponId());
 			try {
 				data.setGoodsSkuIds(Jsons.toJson(couponSkus));
 			} catch (Exception e) {
-
 			}
 		});
 		return GatewayResponse.SUCCESS.newBuilder().toResult(page);
@@ -138,65 +113,12 @@ public class CouponFrontController {
 
 	@GetMapping("/available/list")
 	public Result<Page<CouponUserView>> availableCouponList(Long skuId, Long couponId, Boolean isRenew, @RequestParam(defaultValue = "1") Long start, @RequestParam(defaultValue = "5") Long limit) {
+		String lang = request.getHeader("lang");
 		Long userId = StpUserUtil.getLoginIdAsLong();
-		Page<CouponUserView> couponActiveViewList = couponFontService.getAvailableCouponList(skuId, couponId, userId, isRenew, start, limit);
+		Page<CouponUserView> couponActiveViewList = couponFontService.getAvailableCouponList(skuId, couponId, userId, isRenew, start, limit, lang);
 		return GatewayResponse.SUCCESS.newBuilder().toResult(couponActiveViewList);
 	}
 
-	/**
-	 * 推荐优惠券列表
-	 */
-	@GetMapping("/recommend/list")
-	public Result<Page<CouponRecommendView>> getRecommendList(@RequestParam(defaultValue = "1") Long start, @RequestParam(defaultValue = "5") Long limit) {
-		Long userId = StpUserUtil.getLoginIdAsLong();
-		CouponNewUserView couponNewUserView = beanSearcher.searchFirst(CouponNewUserView.class, MapUtils.builder().field(CouponNewUserView::getUserId, userId).op(Operator.Equal).build());
-		Boolean isNewUser = true;
-		if (couponNewUserView != null) {
-			isNewUser = false;
-		}
-		Page<CouponRecommendView> page = couponRecommendMapper.getRecommendCouponViewList(userId, isNewUser, new Page<>(start, limit));
-		page.getRecords().forEach(data -> {
-			if (data.getCouponStatus() == CouponActiveView.CouponStatus.received) {
-				data.setValidStartTime(data.getUserValidStartTime());
-				data.setValidEndTime(data.getUserValidEndTime());
-			}
-			String str = couponSkuMapper.selectGoodsSkuStr(data.getCouponId());
-			data.setGoodsSkuStr(str.replaceAll(",", "/").replaceAll(";", ""));
-			List<CouponSkuView> couponSkus = couponSkuMapper.getGoodsSkuByCouponId(data.getCouponId());
-			try {
-				data.setGoodsSkuIds(Jsons.toJson(couponSkus));
-			} catch (Exception e) {
-
-			}
-		});
-		return GatewayResponse.SUCCESS.newBuilder().toResult(page);
-	}
-
-	/**
-	 * 一键领取推荐优惠券
-	 */
-	@PostMapping("/collect/recommend/whole")
-	@NoSubmit
-	public Result<String> collectWholeRecommendCoupon() {
-		Long userId = StpUserUtil.getLoginIdAsLong();
-		couponFontService.collectWholeRecommendCoupon(userId);
-		return GatewayResponse.SUCCESS.newBuilder().toResult();
-	}
-
-	/**
-	 * 今日推荐优惠券弹窗已弹
-	 */
-	@GetMapping("/get/recommend/appear")
-	public Result<Boolean> recommendIsAppear() {
-		Long userId = StpUserUtil.getLoginIdAsLong();
-		String zero = DateUtil.beginOfDay(DateTime.now()).toString();
-		Object exists = redisService.get(RedisService.key.RECOMMEND_COUPON_DAY.getNameFormat(String.format("%s-%s", zero, userId)));
-		if (exists == null) {
-			redisService.set(RedisService.key.RECOMMEND_COUPON_DAY.getNameFormat(String.format("%s-%s", zero, userId)), userId, RedisService.key.RECOMMEND_COUPON_DAY.getTimeout());
-		}
-		return GatewayResponse.SUCCESS.newBuilder().toResult(exists == null ? false : true);
-	}
-
 	/**
 	 * 领取优惠券
 	 */
@@ -207,31 +129,6 @@ public class CouponFrontController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
 
-	/**
-	 * 领取推荐优惠券
-	 */
-	@PostMapping("/recommend/collect")
-	public Result<String> collectRecommendCoupon(@RequestBody CouponCollectReq couponCollectReq) {
-		Long userId = StpUserUtil.getLoginIdAsLong();
-		couponFontService.collectRecommendCoupon(couponCollectReq, userId);
-		return GatewayResponse.SUCCESS.newBuilder().toResult();
-	}
-
-	/**
-	 * 查询有可以领取的推荐优惠券
-	 */
-	@GetMapping("/recommend/collect/num")
-	public Result<Integer> collectRecommendCouponNum() {
-		Long userId = StpUserUtil.getLoginIdAsLong();
-		CouponNewUserView couponNewUserView = beanSearcher.searchFirst(CouponNewUserView.class, MapUtils.builder().field(CouponNewUserView::getUserId, userId).op(Operator.Equal).build());
-		Boolean isNewUser = true;
-		if (couponNewUserView != null) {
-			isNewUser = false;
-		}
-		Integer num = couponFontService.collectRecommendCouponNum(userId, isNewUser);
-		return GatewayResponse.SUCCESS.newBuilder().toResult(num);
-	}
-
 
 	/**
 	 * 优惠码详情
@@ -245,7 +142,7 @@ public class CouponFrontController {
 		}
 		BigDecimal skuMoney = goodsDonSkuView.getMoney();
 		if (goodsDonSkuView.getType() == 2) {
-			throw BusinessRuntimeException.getInstance(I18nMessageUtil.getI18nMsg("coupon_sku_not_available_error"));
+			throw BusinessRuntimeException.getInstance("");
 		}
 		CouponPopularizeDto dto = couponMapper.checkExCode(exCode);
 		if (dto == null) {
@@ -272,10 +169,10 @@ public class CouponFrontController {
 						throw BusinessRuntimeException.getInstance(I18nMessageUtil.getI18nMsg("coupon_code_new_user_error"));
 					}
 					CouponNewUserView couponNewUserView = beanSearcher.searchFirst(CouponNewUserView.class, MapUtils.builder().field(CouponNewUserView::getUserId, userId).op(Operator.Equal).build());
-					if (couponNewUserView != null) throw BusinessRuntimeException.getInstance(I18nMessageUtil.getI18nMsg("coupon_code_new_user_error"));
+					if (couponNewUserView != null) throw BusinessRuntimeException.getInstance(I18nMessageUtil.getI18nMsg("coupon_code_new_user_error"));;
 				}
 				if (userDistributeShared != null && !userDistributeShared.getSharedId().equals(dto.getUserId())) {
-					throw BusinessRuntimeException.getInstance(I18nMessageUtil.getI18nMsg("coupon_code_popularize_repeat_use_error"));
+					throw BusinessRuntimeException.getInstance("");
 				}
 			}
 		}
@@ -288,13 +185,13 @@ public class CouponFrontController {
 		if (isRenew != null && isRenew) {
 			Coupon.UseScope useScope = dto.getUseScope();
 			if (useScope == Coupon.UseScope.orders) {
-				throw BusinessRuntimeException.getInstance(I18nMessageUtil.getI18nMsg("coupon_code_only_order_error"));
+				throw BusinessRuntimeException.getInstance(I18nMessageUtil.getI18nMsg("coupon_only_order_error"));
 			}
 		}
 		if (isRenew == null || !isRenew) {
 			Coupon.UseScope useScope = dto.getUseScope();
 			if (useScope == Coupon.UseScope.renew) {
-				throw BusinessRuntimeException.getInstance(I18nMessageUtil.getI18nMsg("coupon_code_only_renew_order_error"));
+				throw BusinessRuntimeException.getInstance(I18nMessageUtil.getI18nMsg("coupon_only_renew_error"));
 			}
 		}
 		if (dto.getIsValidTime() && dto.getValidStartTime().after(DateTime.now())) {
@@ -308,12 +205,7 @@ public class CouponFrontController {
 				.eq(CouponSku::getCouponId, dto.getCouponId())
 				.select(CouponSku::getId).last("limit 1"));
 		if (couponSku == null) {
-			throw BusinessRuntimeException.getInstance(I18nMessageUtil.getI18nMsg("coupon_sku_not_available_error"));
-		}
-		if (goodsDonSkuView.getType() == 2) {
-			if (dto.getType() == Coupon.Type.reduce && skuMoney.compareTo(dto.getReduceCondition()) < 0) {
-				throw BusinessRuntimeException.getInstance(I18nMessageUtil.getI18nMsg("coupon_reduce_money_not_available_error"));
-			}
+			throw BusinessRuntimeException.getInstance("");
 		}
 		return GatewayResponse.SUCCESS.newBuilder().toResult(dto);
 	}
@@ -328,40 +220,27 @@ public class CouponFrontController {
 		}
 		List<CouponView> couponViews = beanSearcher.searchAll(CouponView.class, MapUtils.builder()
 				.field(CouponView::getId, couponIds).op(Operator.InList)
-				.orderBy(CouponView ::getId).desc()
+				.orderBy(CouponView::getId).desc()
 				.build());
 		return GatewayResponse.SUCCESS.newBuilder().toResult(couponViews);
 	}
 
-	/**
-	 * 渠道推广用户领取优惠券
-	 */
-	@PostMapping("/channel/popularize/receive")
-	public Result<String> receiveChannelPopularizeCoupon(@RequestBody @Validated ChannelPopularizeCouponReq req) {
+	@GetMapping("/get/coupon/detail/{couponId}")
+	public Result<CouponUserView> getCouponDetailById(@PathVariable Long couponId) {
+		String lang = request.getHeader("lang");
 		long userId = StpUserUtil.getLoginIdAsLong();
-		req.setUserId(userId);
-		couponFontService.receiveChannelPopularizeCoupon(req);
-		return GatewayResponse.SUCCESS.newBuilder().toResult();
-	}
-
-	/**
-	 * 渠道推广一键领取优惠券
-	 */
-	@PostMapping("/channel/popularize/collectAll/{popularizeId}")
-	public Result<String> collectAllChannelCoupons(@PathVariable Long popularizeId) {
-		long userId = StpUserUtil.getLoginIdAsLong();
-		couponFontService.collectAllChannelCoupons(userId, popularizeId);
-		return GatewayResponse.SUCCESS.newBuilder().toResult();
+		CouponUserView couponUserView = couponFontService.getCouponDetailById(userId, couponId, lang);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(couponUserView);
 	}
 
 	/**
-	 * 新用户福利 优惠券详情展示
+	 * 领取优惠券
 	 */
-	@GetMapping("/get/newUser/welfare")
-	public Result<CouponUserView> getNewUserWelfare() {
+	@PostMapping("/receive/coupon/{couponId}")
+	public Result<CouponUserView> receiveCoupon(@PathVariable Long couponId) {
+		String lang = request.getHeader("lang");
 		long userId = StpUserUtil.getLoginIdAsLong();
-		DateTime now = DateTime.now();
-		CouponUserView couponUserView = couponFontService.getNewUserWelfareCoupons(userId, now);
+		CouponUserView couponUserView = couponFontService.receiveCoupon(userId, couponId, lang);
 		return GatewayResponse.SUCCESS.newBuilder().toResult(couponUserView);
 	}
 }

+ 521 - 210
netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java

@@ -9,11 +9,15 @@ import com.alibaba.excel.EasyExcel;
 import com.alibaba.excel.context.AnalysisContext;
 import com.alibaba.excel.event.AnalysisEventListener;
 import com.alibaba.excel.support.ExcelTypeEnum;
+import com.baomidou.mybatisplus.core.toolkit.Assert;
 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.task.GlobalThreadPoolTaskExecutor;
+import com.cyksj.common.util.J11HttpC;
+import com.cyksj.common.util.Jsons;
 import com.cyksj.dto.RedisKey;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.BusinessType;
@@ -22,10 +26,7 @@ import com.cyksj.mapper.*;
 import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.mapper.sys.SysEmailMapper;
 import com.cyksj.model.entity.*;
-import com.cyksj.model.excel.ExcelDoubleVerifyAccountData;
-import com.cyksj.model.excel.ExcelImportAccountData;
-import com.cyksj.model.excel.ExcelImportDoubleVerifyAccountData;
-import com.cyksj.model.excel.ExcelManageAccountData;
+import com.cyksj.model.excel.*;
 import com.cyksj.model.manage.request.ReqAccountIncrExpiryTime;
 import com.cyksj.model.manage.views.AccountView;
 import com.cyksj.model.manage.views.GroupsRelationView;
@@ -33,6 +34,7 @@ import com.cyksj.model.response.ExpiredAccountRep;
 import com.cyksj.model.response.OrderDonAccountRep;
 import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
+import com.cyksj.service.mange.AccountCommonService;
 import com.cyksj.service.mange.CmsAccountService;
 import com.cyksj.service.mange.CmsGroupService;
 import com.cyksj.service.mange.cms.CmsUserManager;
@@ -57,6 +59,7 @@ import org.springframework.web.multipart.MultipartFile;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.net.http.HttpResponse;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -98,14 +101,20 @@ public class CmsAccountController {
 
 	private final AccountUpdatePasswordRecordMapper accountUpdatePasswordRecordMapper;
 
+	private final AccountCommonService accountCommonService;
+
 	private final RedisService redisService;
 
+	private final GoodsDonSkuMapper goodsDonSkuMapper;
+
 	private final SysEmailMapper sysEmailMapper;
 
-	private final GoodsDonSkuMapper goodsDonSkuMapper;
+	private final AccountBlockedReplaceRecordMapper accountBlockedReplaceRecordMapper;
+
+	private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
 
 	@GetMapping("/get")
-	public Result<SearchResult<AccountView>> get(Long userId, String showId, String nickName, String submitAccount, String expiryStartTime, String expiryEndTime, Boolean expiredAll, Boolean existsExpired, Boolean existsExpiredToday, Integer noChangeMonths) {
+	public Result<SearchResult<AccountView>> get(Long userId, String showId, String nickName, String submitAccount, String expiryStartTime, String expiryEndTime, Boolean expiredAll, Boolean existsExpired, Boolean existsExpiredToday, Integer noChangeMonths, Boolean isMjMirror) {
 		MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
 		if (StrUtil.isNotEmpty(expiryStartTime) || StrUtil.isNotEmpty(expiryEndTime)) {
 			mapBuilder.field(AccountView::getExpiryTime, expiryStartTime, expiryEndTime)
@@ -151,6 +160,12 @@ public class CmsAccountController {
 				extra_sql += String.format(" (select min(expiry_time) from (select gt.id from groups_trips where account_id = a.id) gt inner join groups_relation gr on gr.groups_id = gt.id) > '%s'", endOfDay);
 			}
 		}
+		if (isMjMirror != null) {
+			if (StrUtil.isNotEmpty(extra_sql)) {
+				extra_sql += " and";
+			}
+			extra_sql += String.format(" %s (select 1 from midjourney_account ma where ma.account_id = a.id limit 1)", isMjMirror ? "EXISTS" : "NOT EXISTS");
+		}
 		if (StrUtil.isNotEmpty(extra_sql)) {
 			mapBuilder.put("extra_sql", extra_sql);
 		}
@@ -179,76 +194,83 @@ public class CmsAccountController {
 			}
 			Integer expiryCount = groupsMapper.countExpiredNum(accountView.getId());
 			accountView.setExpiryCount(expiryCount);
+
+			if (StrUtil.isNotEmpty(accountView.getAccount())) {
+				Optional.ofNullable(sysEmailMapper.selectOne(Wrappers.lambdaQuery(SysEmail.class)
+								.eq(SysEmail::getEmail, accountView.getAccount()).select(SysEmail::getPassword)
+								.last("limit 1")))
+						.ifPresent(email -> accountView.setEmailPassword(email.getPassword()));
+			}
 		});
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
 
-    /**
-     * 导出账号
-     */
-    @GetMapping("/export/account")
-    @Log(module = "平台管理/导出账号", businessType = BusinessType.EXPORT, isSaveRequestData = true)
-    public void exportAccount(Long userId, String showId, String nickName, String submitAccount, String expiryStartTime, String expiryEndTime, Boolean expiredAll, Boolean existsExpired, Boolean existsExpiredToday, Integer noChangeMonths, HttpServletResponse response) {
-        MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
-        if (StrUtil.isNotEmpty(expiryStartTime) || StrUtil.isNotEmpty(expiryEndTime)) {
-            mapBuilder.field(ExcelManageAccountData::getExpiryTime, expiryStartTime, expiryEndTime)
-                    .op(Operator.Between);
-        }
-	    if (StrUtil.isNotEmpty(showId)) {
-		    userId = userMapper.getUserIdByShowId(showId);
-	    }
-
-        if (userId != null || StringUtils.isNotBlank(nickName) || StringUtils.isNotBlank(submitAccount)) {
-            List<Long> accountIds = homeGroupMapper.getAccountIdsByUserIdOrNickNameOrSubmitAccount(userId, nickName, submitAccount);
-            if (accountIds.isEmpty()) {
-                throw BusinessRuntimeException.getInstance("暂无数据!");
-            }
-
-            mapBuilder.field(ExcelManageAccountData::getId, accountIds).op(Operator.InList);
-        }
-	    String extra_sql = StrUtil.EMPTY;
-	    if (expiredAll != null && expiredAll) {
-		    extra_sql += "(if((select count(ur.id) from user_ticket_cleared_record ur where ur.account_id = a.id and deleted is true and source = 'self')>=3,true,false)) = 1";
-	    }
-
-	    if (noChangeMonths != null) {
-		    DateTime pastMonth = DateUtil.offsetMonth(DateTime.now(), -noChangeMonths);
-		    List<Long> accountIds = accountUpdatePasswordRecordMapper.selectPasswordNotChangedThePastMonthAccountId(pastMonth);
-		    mapBuilder.field(AccountView::getId, accountIds).op(Operator.InList);
-	    }
-
-	    if (existsExpired != null && existsExpired) {
-		    if (StrUtil.isNotEmpty(extra_sql)) {
-			    extra_sql += " and";
-		    }
-		    extra_sql += "(select count(ur.id) from user_ticket_cleared_record ur where ur.account_id = a.id and deleted is true and source = 'self') > 0";
-	    }
-	    if (existsExpiredToday != null) {
-		    DateTime endOfDay = DateUtil.endOfDay(DateTime.now());
-		    if (StrUtil.isNotEmpty(extra_sql)) {
-			    extra_sql += " and";
-		    }
-		    if (existsExpiredToday) {
-			    extra_sql += String.format(" (select min(expiry_time) from (select gt.id from groups_trips where account_id = a.id) gt inner join groups_relation gr on gr.groups_id = gt.id) <= '%s'", endOfDay);
-		    } else {
-			    extra_sql += String.format(" (select min(expiry_time) from (select gt.id from groups_trips where account_id = a.id) gt inner join groups_relation gr on gr.groups_id = gt.id) > '%s'", endOfDay);
-		    }
-	    }
-	    if (StrUtil.isNotEmpty(extra_sql)) {
-		    mapBuilder.put("extra_sql", extra_sql);
-	    }
-	    List<ExcelManageAccountData> list = beanSearcher.searchAll(ExcelManageAccountData.class, mapBuilder.build());
-
-	    EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelManageAccountData.class, list, "账号列表", "账号列表", ExcelTypeEnum.XLSX, null);
-    }
-
-    /**
-     * 下载批量修改密码模板
-     */
-    @GetMapping("/get/account/template")
-    public void getAccountTemplate(HttpServletResponse response) {
-        EasyExcelUtils.createTemplateExcel(response, ExcelImportAccountData.class, "账号批量修改密码模板", "账号批量修改密码模板", ExcelTypeEnum.XLSX, null);
-    }
+	/**
+	 * 导出账号
+	 */
+	@GetMapping("/export/account")
+	@Log(module = "平台管理/导出账号", businessType = BusinessType.EXPORT, isSaveRequestData = true)
+	public void exportAccount(Long userId, String showId, String nickName, String submitAccount, String expiryStartTime, String expiryEndTime, Boolean expiredAll, Boolean existsExpired, Boolean existsExpiredToday, Integer noChangeMonths, HttpServletResponse response) {
+		MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
+		if (StrUtil.isNotEmpty(expiryStartTime) || StrUtil.isNotEmpty(expiryEndTime)) {
+			mapBuilder.field(ExcelManageAccountData::getExpiryTime, expiryStartTime, expiryEndTime)
+					.op(Operator.Between);
+		}
+		if (StrUtil.isNotEmpty(showId)) {
+			userId = userMapper.getUserIdByShowId(showId);
+		}
+
+		if (userId != null || StringUtils.isNotBlank(nickName) || StringUtils.isNotBlank(submitAccount)) {
+			List<Long> accountIds = homeGroupMapper.getAccountIdsByUserIdOrNickNameOrSubmitAccount(userId, nickName, submitAccount);
+			if (accountIds.isEmpty()) {
+				throw BusinessRuntimeException.getInstance("暂无数据!");
+			}
+
+			mapBuilder.field(ExcelManageAccountData::getId, accountIds).op(Operator.InList);
+		}
+		String extra_sql = StrUtil.EMPTY;
+		if (expiredAll != null && expiredAll) {
+			extra_sql += "(if((select count(ur.id) from user_ticket_cleared_record ur where ur.account_id = a.id and deleted is true and source = 'self')>=3,true,false)) = 1";
+		}
+
+		if (noChangeMonths != null) {
+			DateTime pastMonth = DateUtil.offsetMonth(DateTime.now(), -noChangeMonths);
+			List<Long> accountIds = accountUpdatePasswordRecordMapper.selectPasswordNotChangedThePastMonthAccountId(pastMonth);
+			mapBuilder.field(AccountView::getId, accountIds).op(Operator.InList);
+		}
+
+		if (existsExpired != null && existsExpired) {
+			if (StrUtil.isNotEmpty(extra_sql)) {
+				extra_sql += " and";
+			}
+			extra_sql += "(select count(ur.id) from user_ticket_cleared_record ur where ur.account_id = a.id and deleted is true and source = 'self') > 0";
+		}
+		if (existsExpiredToday != null) {
+			DateTime endOfDay = DateUtil.endOfDay(DateTime.now());
+			if (StrUtil.isNotEmpty(extra_sql)) {
+				extra_sql += " and";
+			}
+			if (existsExpiredToday) {
+				extra_sql += String.format(" (select min(expiry_time) from (select gt.id from groups_trips where account_id = a.id) gt inner join groups_relation gr on gr.groups_id = gt.id) <= '%s'", endOfDay);
+			} else {
+				extra_sql += String.format(" (select min(expiry_time) from (select gt.id from groups_trips where account_id = a.id) gt inner join groups_relation gr on gr.groups_id = gt.id) > '%s'", endOfDay);
+			}
+		}
+		if (StrUtil.isNotEmpty(extra_sql)) {
+			mapBuilder.put("extra_sql", extra_sql);
+		}
+		List<ExcelManageAccountData> list = beanSearcher.searchAll(ExcelManageAccountData.class, mapBuilder.build());
+
+		EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelManageAccountData.class, list, "账号列表", "账号列表", ExcelTypeEnum.XLSX, null);
+	}
+
+	/**
+	 * 下载批量修改密码模板
+	 */
+	@GetMapping("/get/account/template")
+	public void getAccountTemplate(HttpServletResponse response) {
+		EasyExcelUtils.createTemplateExcel(response, ExcelImportAccountData.class, "账号批量修改密码模板", "账号批量修改密码模板", ExcelTypeEnum.XLSX, null);
+	}
 
 	/**
 	 * 导入文件,修改密码
@@ -273,7 +295,7 @@ public class CmsAccountController {
 						}
 						String oldPwd = account.getPassword();
 						if (StrUtil.isNotBlank(data.getExpiryTime())) {
-							account.setExpiryTime(DateUtil.parse(data.getExpiryTime(), "yyyy-MM-dd HH:mm:ss"));
+							account.setExpiryTime(DateUtil.parse(data.getExpiryTime()));
 							flag = true;
 						}
 						String new_pass = data.getPassword();
@@ -338,30 +360,79 @@ public class CmsAccountController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
 
-    @PostMapping("/post")
-    @NoSubmit
-    @Transactional(rollbackFor = Throwable.class)
-    @Log(module = "平台管理/新增账号", businessType = BusinessType.POST, isSaveRequestData = true)
-    public Result<String> add(@RequestBody Account account){
+	@GetMapping("/test")
+	public Result<String> stest(MultipartFile file) throws IOException {
+		List<Object> objects = EasyExcel.read(file.getInputStream()).sheet().headRowNumber(0).doReadSync();
+
+		String url = "https://plus1.caifree.com/api?email=%s";
+		objects.forEach(e->{
+			Map<String, Object> map = Jsons.toMap(e);
+			String account = String.valueOf(map.get("0"));
+			if (StrUtil.isNotEmpty(account)) {
+				String formatUrl = String.format(url, account);
+				try {
+					HttpResponse<String> send = J11HttpC.custom()
+							.ofGet()
+							.url(formatUrl)
+							.send(HttpResponse.BodyHandlers.ofString());
+					System.out.println(send.body());
+				} catch (Exception exception) {
+
+				}
+			}
+
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	public static void main(String[] args) {
+		String url = "https://plus1.caifree.com/api?email=sentzb99@gmail.com";
+		try {
+			HttpResponse<String> send = J11HttpC.custom()
+					.ofGet()
+					.url(url)
+					.send(HttpResponse.BodyHandlers.ofString());
+			System.out.println(send.body());
+		} catch (Exception exception) {
+
+		}
+	}
+
+	@PostMapping("/post")
+	@NoSubmit
+	@Transactional(rollbackFor = Throwable.class)
+	@Log(module = "平台管理/新增账号", businessType = BusinessType.POST, isSaveRequestData = true)
+	public Result<String> add(@RequestBody Account account){
 		account.setAccount(account.getAccount().trim());
 		account.setPassword(account.getPassword().trim());
-	    //账号是否已经添加过
-	    if (!account.getAccount().contains("客服")) {
-		    int count = accountService.count(Wrappers.lambdaQuery(Account.class)
-				    .eq(Account::getAccount, account.getAccount())
-				    .eq(Account::getGoodsId, account.getGoodsId()));
-		    if (count > 0) {
-			    throw BusinessRuntimeException.getInstance("该平台下已生成该账号");
-		    }
-	    }
-        accountService.save(account);
-	    //自动配置车队
-	    GroupsTrips groupsTrips = new GroupsTrips();
-	    groupsTrips.setSkuId(account.getSkuId());
-	    groupsTrips.setAccountId(account.getId());
-	    cmsGroupService.issuance(groupsTrips, account.getVerifyCodes());
-        return GatewayResponse.SUCCESS.newBuilder().toResult();
-    }
+		//账号是否已经添加过
+		if (!account.getAccount().contains("客服")) {
+			if (accountCommonService.checkIsDupAccount(account.getGoodsId(), account.getAccount())) {
+				throw BusinessRuntimeException.getInstance("该平台下已生成该账号");
+			}
+		}
+		accountService.save(account);
+		if (account.getSkuId() != null) {
+			//自动配置车队
+			GroupsTrips groupsTrips = new GroupsTrips();
+
+			//限制每天新车队前3天 停车数量
+			Integer availableParkingNum = 0;
+			if (account.getSkuId() == 161l) {
+				availableParkingNum = 10;
+			}
+			if (account.getSkuId() == 178l) {
+				availableParkingNum = 4;
+			}
+			groupsTrips.setAvailableParkingNum(availableParkingNum);
+
+			groupsTrips.setSkuId(account.getSkuId());
+			groupsTrips.setAccountId(account.getId());
+			cmsGroupService.issuance(groupsTrips, account.getVerifyCodes());
+		}
+
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
 
 	/**
 	 * 获取导入账号模板
@@ -388,10 +459,7 @@ public class CmsAccountController {
 				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) {
+						if (accountCommonService.checkIsDupAccount(goodsId, account)) {
 							log.info("该平台下:{}已生成该账号:{}", goodsId, account);
 							return;
 						}
@@ -402,18 +470,37 @@ public class CmsAccountController {
 					at.setGoodsId(goodsId);
 					at.setSkuId(skuId);
 					at.setBankCard(bankCard);
+					String isMonth = data.getIsMonth();
+					if (StrUtil.isNotBlank(isMonth)) {
+						at.setIsMonth(true);
+					}
 					if (StrUtil.isNotBlank(startTime)) {
-						at.setStartTime(DateUtil.parse(startTime, "yyyy-MM-dd HH:mm:ss"));
+						at.setStartTime(DateUtil.parse(startTime));
+					} else {
+						at.setStartTime(DateTime.now());
 					}
 					if (StrUtil.isNotBlank(expiryTime)) {
-						at.setExpiryTime(DateUtil.parse(expiryTime, "yyyy-MM-dd HH:mm:ss"));
+						at.setExpiryTime(DateUtil.parse(expiryTime));
+					} else {
+						at.setExpiryTime(DateUtil.offsetMonth(at.getStartTime(), 1));
 					}
 					accountService.save(at);
-					//自动配置车队
-					GroupsTrips groupsTrips = new GroupsTrips();
-					groupsTrips.setSkuId(at.getSkuId());
-					groupsTrips.setAccountId(at.getId());
-					cmsGroupService.issuance(groupsTrips, null);
+					if (at.getSkuId() != null) {
+						//自动配置车队
+						GroupsTrips groupsTrips = new GroupsTrips();
+						//限制每天新车队前3天 停车数量
+						Integer availableParkingNum = 0;
+						if (at.getSkuId() == 161l) {
+							availableParkingNum = 10;
+						}
+						if (at.getSkuId() == 178l) {
+							availableParkingNum = 4;
+						}
+						groupsTrips.setAvailableParkingNum(availableParkingNum);
+						groupsTrips.setSkuId(at.getSkuId());
+						groupsTrips.setAccountId(at.getId());
+						cmsGroupService.issuance(groupsTrips, null);
+					}
 				}
 			}
 
@@ -425,89 +512,86 @@ public class CmsAccountController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult("导入账号成功");
 	}
 
-    @PutMapping("/update")
-    @Log(module = "平台管理/编辑账号", businessType = BusinessType.PUT, isSaveRequestData = true)
-    public Result<String> update(@RequestBody Account account){
-	    Account db = accountService.getById(account.getId());
-	    if (db == null) {
-		    throw BusinessRuntimeException.getInstance("该账号不存在");
-	    }
-	    Boolean isClear = false;
-	    String dbAccount = db.getAccount();
-	    long userId = StpAbroadUtil.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()));
-		    isClear = true;
-	    }
-	    if (StrUtil.isNotBlank(account.getAccount())){
+	@PutMapping("/update")
+	@Log(module = "平台管理/编辑账号", businessType = BusinessType.PUT, isSaveRequestData = true)
+	public Result<String> update(@RequestBody Account account) throws Exception {
+		Account db = accountService.getById(account.getId());
+		if (db == null) {
+			throw BusinessRuntimeException.getInstance("该账号不存在");
+		}
+		Boolean isClear = false;
+		String dbAccount = db.getAccount();
+		long userId = StpAbroadUtil.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()));
+			isClear = true;
+		}
+		if (!db.getAccount().equals(account.getAccount())){
 			account.setAccount(account.getAccount().trim());
 			//账号是否已经添加过
 			if (!account.getAccount().contains("客服")) {
-				int count = accountService.count(Wrappers.lambdaQuery(Account.class)
-						.ne(Account::getId, account.getId())
-						.eq(Account::getAccount, account.getAccount())
-						.eq(Account::getGoodsId, account.getGoodsId()));
-				if (count > 0) {
+				if (accountCommonService.checkIsDupAccount(account.getGoodsId(), account.getAccount())) {
 					throw BusinessRuntimeException.getInstance("该平台下已生成该账号");
 				}
 			}
-		    if (!dbAccount.equals(account.getAccount())) {
-			    isClear = true;
-		    }
-		}
-	    if (StrUtil.isNotBlank(account.getPassword())){
-		    account.setPassword(account.getPassword().trim());
-	    }
-	    String verifyCodes = account.getVerifyCodes();
-	    if (StrUtil.isNotBlank(verifyCodes) && !StrUtil.equals(verifyCodes, db.getVerifyCodes())) {
-		    verifyCodes = verifyCodes.replaceAll("\n", "");
-		    String[] verifyCodesArray = verifyCodes.split("\\*");
-		    List<String> verifyCodeList = Arrays.stream(verifyCodesArray).filter(str -> StrUtil.isNotBlank(str)).map(str -> str.trim()).collect(Collectors.toList());
-		    List<GroupsRelationView> relationViews = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
-				    .field(GroupsRelationView::getAccountId, account.getId())
-				    .onlySelect(GroupsRelationView::getId)
-				    .build());
-		    if (CollUtil.isNotEmpty(relationViews)) {
-			    for (int i = 0; i < verifyCodeList.size(); i++) {
-				    if (i < relationViews.size()) {
-					    GroupsRelationView groupsRelationView = relationViews.get(i);
-					    groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
-							    .set(GroupsRelation::getVerifyCode, verifyCodeList.get(i))
-							    .eq(GroupsRelation::getId, groupsRelationView.getId()));
-				    }
-			    }
-		    }
-	    }
-	    String apiSecret = account.getApiSecret();
-	    if (StrUtil.isNotBlank(apiSecret)) {
-		    doubleVerifyRecordMapper.update(null, Wrappers.lambdaUpdate(AccountDoubleVerifyRecord.class)
-				    .set(AccountDoubleVerifyRecord::getDeleted, false)
-				    .set(AccountDoubleVerifyRecord::getApiSecret, apiSecret)
-				    .eq(AccountDoubleVerifyRecord::getAccountId, account.getId()));
-	    }
-	    account.setStartTime(null);
-	    if (isClear){
-		    account.setGptRefreshToken(StrUtil.EMPTY);
-		    //清除gpt token
-		    redisService.del(RedisKey.CHATGPT_ACCESS_TOKEN + dbAccount);
-		    redisService.del(RedisService.key.CHAT_GPT_TOKEN_EXCEPTION_KEY.getName() + dbAccount);
-	    }
-	    //时间有效
-	    if (account.getExpiryTime() != null && account.getExpiryTime().after(DateTime.now())) {
-		    groupsMapper.update(null, Wrappers.lambdaUpdate(GroupsTrips.class)
-				    .set(GroupsTrips::getStatus, GroupsTrips.Status.validity)
-				    .eq(GroupsTrips::getAccountId, account.getId())
-				    .eq(GroupsTrips::getStatus, GroupsTrips.Status.down));
-	    }
-	    accountService.updateById(account);
-        return GatewayResponse.SUCCESS.newBuilder().toResult();
-    }
+			if (!dbAccount.equals(account.getAccount())) {
+				isClear = true;
+			}
+		}
+		if (StrUtil.isNotBlank(account.getPassword())){
+			account.setPassword(account.getPassword().trim());
+		}
+		String verifyCodes = account.getVerifyCodes();
+		if (StrUtil.isNotBlank(verifyCodes) && !StrUtil.equals(verifyCodes, db.getVerifyCodes())) {
+			verifyCodes = verifyCodes.replaceAll("\n", "");
+			String[] verifyCodesArray = verifyCodes.split("\\*");
+			List<String> verifyCodeList = Arrays.stream(verifyCodesArray).filter(str -> StrUtil.isNotBlank(str)).map(str -> str.trim()).collect(Collectors.toList());
+			List<GroupsRelationView> relationViews = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
+					.field(GroupsRelationView::getAccountId, account.getId())
+					.onlySelect(GroupsRelationView::getId)
+					.build());
+			if (CollUtil.isNotEmpty(relationViews)) {
+				for (int i = 0; i < verifyCodeList.size(); i++) {
+					if (i < relationViews.size()) {
+						GroupsRelationView groupsRelationView = relationViews.get(i);
+						groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
+								.set(GroupsRelation::getVerifyCode, verifyCodeList.get(i))
+								.eq(GroupsRelation::getId, groupsRelationView.getId()));
+					}
+				}
+			}
+		}
+		String apiSecret = account.getApiSecret();
+		if (StrUtil.isNotBlank(apiSecret)) {
+			doubleVerifyRecordMapper.update(null, Wrappers.lambdaUpdate(AccountDoubleVerifyRecord.class)
+					.set(AccountDoubleVerifyRecord::getDeleted, false)
+					.set(AccountDoubleVerifyRecord::getApiSecret, apiSecret)
+					.eq(AccountDoubleVerifyRecord::getAccountId, account.getId()));
+		}
+		account.setStartTime(null);
+		if (isClear){
+			account.setGptRefreshToken(StrUtil.EMPTY);
+			//清除gpt token
+			redisService.del(RedisKey.CHATGPT_ACCESS_TOKEN + dbAccount);
+			redisService.del(RedisService.key.CHAT_GPT_TOKEN_EXCEPTION_KEY.getName() + dbAccount);
+			templateCommonService.sendAccountTemplateMsg(account);
+		}
+		//时间有效
+		if (account.getExpiryTime() != null && account.getExpiryTime().after(DateTime.now())) {
+			groupsMapper.update(null, Wrappers.lambdaUpdate(GroupsTrips.class)
+					.set(GroupsTrips::getStatus, GroupsTrips.Status.validity)
+					.eq(GroupsTrips::getAccountId, account.getId())
+					.eq(GroupsTrips::getStatus, GroupsTrips.Status.down));
+		}
+		accountService.updateById(account);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
 
 	/**
 	 * 修改密码并发送模板消息
@@ -540,6 +624,7 @@ public class CmsAccountController {
 							.eq(UserTicketClearedRecord::getAccountId, account.getId()));
 					//发放模板消息
 					try {
+						account.setAccount(db.getAccount());
 						templateCommonService.sendAccountTemplateMsg(account);
 					} catch (Exception e) {
 						log.error("发送账号{}修改密码消息模板错误", account.getId());
@@ -587,24 +672,24 @@ public class CmsAccountController {
 	@DeleteMapping("/delete/{id}")
 	@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) {
-		    throw BusinessRuntimeException.getInstance("已经发布账号,必须先删除车队才可删除账号");
-	    }
-        accountService.removeById(id);
-        return GatewayResponse.SUCCESS.newBuilder().toResult();
-    }
-
-    @PutMapping("/update/expiryTime")
-    public Result<String> updateExpiryTime(@RequestBody ReqAccountIncrExpiryTime incrExpiryTime){
-        incrExpiryTime.getAccounts().forEach((accountId)->{
-            Account account = accountService.getById(accountId);
-            DateTime time = DateUtil.offsetDay(account.getExpiryTime(), incrExpiryTime.getDays());
-            accountService.update(Wrappers.lambdaUpdate(Account.class).eq(Account::getId,accountId).set(Account::getExpiryTime,time));
-        });
-        return GatewayResponse.SUCCESS.newBuilder().toResult();
-    }
+		//是否关联了车队
+		Integer count = groupsMapper.selectCount(Wrappers.lambdaQuery(GroupsTrips.class).eq(GroupsTrips::getAccountId, id));
+		if (count > 0) {
+			throw BusinessRuntimeException.getInstance("已经发布账号,必须先删除车队才可删除账号");
+		}
+		accountService.removeById(id);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	@PutMapping("/update/expiryTime")
+	public Result<String> updateExpiryTime(@RequestBody ReqAccountIncrExpiryTime incrExpiryTime){
+		incrExpiryTime.getAccounts().forEach((accountId)->{
+			Account account = accountService.getById(accountId);
+			DateTime time = DateUtil.offsetDay(account.getExpiryTime(), incrExpiryTime.getDays());
+			accountService.update(Wrappers.lambdaUpdate(Account.class).eq(Account::getId,accountId).set(Account::getExpiryTime,time));
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
 
 	/**
 	 * 需要修改主账号密码的平台
@@ -677,15 +762,6 @@ public class CmsAccountController {
 		if (account.getGoodsId() != 1l) {
 			return GatewayResponse.SUCCESS.newBuilder().toResult();
 		}
-		//账号是否已经添加过
-		if (!account.getAccount().contains("客服")) {
-			int count = accountService.count(Wrappers.lambdaQuery(Account.class)
-					.eq(Account::getAccount, account.getAccount())
-					.eq(Account::getGoodsId, account.getGoodsId()));
-			if (count > 0) {
-				throw BusinessRuntimeException.getInstance("该平台下已生成该账号");
-			}
-		}
 		Boolean flag = false;
 		String oldPwd = account.getPassword();
 		if (account != null) {
@@ -792,6 +868,7 @@ public class CmsAccountController {
 		if (isFlag) {
 			boolean b = accountService.updateById(db);
 			if (StrUtil.isNotBlank(newPwd) && !dnPwd.equals(newPwd) && b) {
+				account.setAccount(db.getAccount());
 				templateCommonService.sendAccountTemplateMsg(account);
 			}
 		}
@@ -904,6 +981,185 @@ public class CmsAccountController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
 
+	/**
+	 * 编辑 未续费的账号
+	 */
+	@PutMapping("/update/renew/account")
+	public Result<String> updateRenewAccount(@RequestBody Account account) {
+		Long id = account.getId();
+		Date startTime = account.getStartTime();
+		Date expiryTime = account.getExpiryTime();
+		String remark = account.getRemark();
+		Account byId = accountService.getById(id);
+		Assert.notNull(byId, "账号不存在");
+		byId.setStartTime(startTime);
+		byId.setExpiryTime(expiryTime);
+		byId.setRemark(remark);
+		accountService.updateById(byId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 下载 替换错误账号模板
+	 */
+	@GetMapping("/get/replace/banned/template")
+	public void getReplaceBannedTemplate(HttpServletResponse response) {
+		EasyExcelUtils.createTemplateExcel(response, ExcelBannedAccountData.class, "封禁账号替换模板", "封禁账号替换模板", ExcelTypeEnum.XLSX, null);
+	}
+
+	/**
+	 * 替换封禁账号
+	 */
+	@PostMapping("/replace/banned")
+	public Result<List<String>> replaceBannedAccount(Long goodsId, MultipartFile file) throws IOException {
+		List<String> repeat = new ArrayList<>();
+		List<Long> sendMsgList = new ArrayList<>();
+		EasyExcel.read(file.getInputStream(), ExcelBannedAccountData.class, new AnalysisEventListener<ExcelBannedAccountData>() {
+			@Override
+			public void invoke(ExcelBannedAccountData data, AnalysisContext analysisContext) {
+				String oldAccount = data.getOldAccount();
+				String account = data.getAccount();
+				String password = data.getPassword();
+				if (StrUtil.isEmpty(oldAccount) || StrUtil.isEmpty(account) || StrUtil.isEmpty(password)) {
+					return;
+				}
+				Account dbAccount = accountService.getOne(Wrappers.lambdaQuery(Account.class)
+						.eq(Account::getGoodsId, goodsId)
+						.eq(Account::getAccount, oldAccount.trim())
+						.last("limit 1"));
+				if (dbAccount == null) {
+					return;
+				}
+				account = account.trim();
+				password = password.trim();
+				if (accountCommonService.checkIsDupAccount(goodsId, account)) {
+					repeat.add(oldAccount);
+					return;
+				}
+				dbAccount.setAccount(account);
+				dbAccount.setPassword(password);
+				dbAccount.setStartTime(DateTime.now());
+				dbAccount.setExpiryTime(DateUtil.offsetMonth(DateTime.now(), 1));
+				accountService.updateById(dbAccount);
+
+				GroupsTrips groupsTrips = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class)
+						.eq(GroupsTrips::getAccountId, dbAccount.getId())
+						.eq(GroupsTrips::getStatus, GroupsTrips.Status.down)
+						.last("limit 1"));
+				if (groupsTrips != null) {
+					groupsTrips.setStatus(GroupsTrips.Status.validity);
+					groupsMapper.updateById(groupsTrips);
+				}
+				sendMsgList.add(dbAccount.getId());
+			}
+
+			@Override
+			public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+
+			}
+		}).sheet().doRead();
+
+		if (CollUtil.isNotEmpty(sendMsgList)) {
+			TASK_EXECUTOR.execute(() -> {
+				sendMsgList.forEach(accountId -> {
+					GroupsTrips groupsTrips = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class)
+							.eq(GroupsTrips::getAccountId, accountId).last("limit 1"));
+					if (groupsTrips != null) {
+						Account byId = accountService.getById(accountId);
+						cmsGroupService.sendChangeAccountMsg(groupsTrips.getId(), goodsId, byId.getAccount());
+					}
+				});
+			});
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(repeat);
+	}
+
+	/**
+	 * 导入备用账号模板
+	 */
+	@GetMapping("/export/prepare/template")
+	public void getPrepareTemplate(HttpServletResponse response) {
+		EasyExcelUtils.createTemplateExcel(response, ExcelPrepareAccountData.class, "导入备用账号模板", "导入备用账号模板", ExcelTypeEnum.XLSX, null);
+	}
+
+	/**
+	 * 批量导入备用账号
+	 */
+	@PostMapping("/batch/import/prepare")
+	public Result<String> batchImportPrepare(Long goodsId, String preSkuIds, MultipartFile file) throws IOException {
+		if (goodsId == null) {
+			throw BusinessRuntimeException.getInstance("请选择对应平台");
+		}
+		if (goodsId == 26) {
+			if (StrUtil.isEmpty(preSkuIds)) {
+				throw BusinessRuntimeException.getInstance("请选择对应规格id");
+			}
+			String[] split = preSkuIds.split(",");
+			preSkuIds = Arrays.stream(split).distinct().collect(Collectors.joining(","));
+		}
+		final String f_skuIds = preSkuIds;
+		EasyExcel.read(file.getInputStream(), ExcelPrepareAccountData.class, new AnalysisEventListener<ExcelPrepareAccountData>() {
+			@Override
+			public void invoke(ExcelPrepareAccountData data, AnalysisContext analysisContext) {
+				String account = data.getAccount();
+				String password = data.getPassword();
+				if (StrUtil.isEmpty(account) || StrUtil.isEmpty(password)) {
+					return;
+				}
+				Account insert = new Account();
+				insert.setAccount(account.trim());
+				insert.setPassword(password.trim());
+				insert.setGoodsId(goodsId);
+				insert.setPreSkuIds(f_skuIds);
+				insert.setType(2);
+				insert.setStartTime(DateTime.now());
+				insert.setExpiryTime(DateUtil.offsetMonth(DateTime.now(), 1));
+				insert.setBankCard(data.getBankCard());
+				//账号是否已经添加过
+				if (!insert.getAccount().contains("客服")) {
+					if (accountCommonService.checkIsDupAccount(insert.getGoodsId(), insert.getAccount())) {
+						return;
+					}
+				}
+				insert.setType(2);
+				accountService.save(insert);
+			}
+
+			@Override
+			public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+
+			}
+		}).sheet().doRead();
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 新增预备账号
+	 */
+	@PostMapping("/post/prepare")
+	public Result<String> postPrepare(@RequestBody Account account) {
+		account.setAccount(account.getAccount().trim());
+		account.setPassword(account.getPassword().trim());
+		//账号是否已经添加过
+		if (!account.getAccount().contains("客服")) {
+			if (accountCommonService.checkIsDupAccount(account.getGoodsId(), account.getAccount())) {
+				throw BusinessRuntimeException.getInstance("该平台下已生成该账号");
+			}
+		}
+		account.setType(2);
+		if (account.getGoodsId() == 26) {
+			String preSkuIds = account.getPreSkuIds();
+			if (StrUtil.isEmpty(preSkuIds)) {
+				throw BusinessRuntimeException.getInstance("请选择对应规格id");
+			}
+			String[] split = preSkuIds.split(",");
+			String skuSetStr = Arrays.stream(split).distinct().collect(Collectors.joining(","));
+			account.setPreSkuIds(skuSetStr);
+		}
+		accountService.save(account);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
 	/**
 	 * 批量导入系统邮箱
 	 */
@@ -953,4 +1209,59 @@ public class CmsAccountController {
 		sysEmailMapper.deleteById(id);
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
+
+	/**
+	 * 批量导入被封禁平台账号
+	 */
+	@PostMapping("/batch/import/blocked")
+	public Result<String> batchImportBlockedAccount(MultipartFile file, Long goodsId) throws IOException {
+		Assert.notNull(goodsId, "请选择对应平台");
+		List<Object> accountBlockedList = EasyExcel.read(file.getInputStream()).sheet().headRowNumber(0).doReadSync();
+		accountService.batchImportBlockedAccount(goodsId, accountBlockedList);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 删除封禁平台账号
+	 */
+	@DeleteMapping("/delete/blocked/{id}")
+	public Result<String> deleteBlockedAccount(@PathVariable Long id) throws IOException {
+		accountBlockedReplaceRecordMapper.deleteById(id);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 被封禁账号列表
+	 */
+	@GetMapping("/get/blocked")
+	public Result<SearchResult<AccountBlockedReplaceRecord>> getBlockedAccount() {
+		SearchResult<AccountBlockedReplaceRecord> search = beanSearcher.search(AccountBlockedReplaceRecord.class, MapUtils.flatBuilder(request.getParameterMap())
+				.orderBy(AccountBlockedReplaceRecord::getId).desc()
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 禁用账号
+	 */
+	@PutMapping("/update/disable/{accountId}")
+	@Log(module = "平台管理/禁用账号", businessType = BusinessType.PUT, isSaveRequestData = true)
+	public Result<String> updateDisableAccount(@PathVariable Long accountId) {
+		Optional.ofNullable(accountService.getById(accountId))
+				.ifPresent(e -> {
+					e.setIsDisable(!e.getIsDisable());
+					accountService.updateById(e);
+				});
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 账号禁用列表
+	 */
+	@GetMapping("/get/disable/acount")
+	public Result<SearchResult<AccountDisableView>> getDisableAccount() {
+		SearchResult<AccountDisableView> search = beanSearcher.search(AccountDisableView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(AccountDisableView::getIsDisable, 1).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
 }

+ 64 - 72
netflix-web/src/main/java/com/cyksj/web/controller/manage/coupon/CouponController.java

@@ -1,5 +1,6 @@
 package com.cyksj.web.controller.manage.coupon;
 
+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;
@@ -15,6 +16,8 @@ import com.cyksj.model.request.CouponClassificationReq;
 import com.cyksj.model.request.CouponDistributeReq;
 import com.cyksj.model.views.*;
 import com.cyksj.service.mange.coupon.CouponCommonService;
+import com.cyksj.service.translations.BackInfoTranslationsFrontService;
+import com.cyksj.service.translations.BackInfoTranslationsService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.util.MapUtils;
@@ -27,8 +30,11 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
-import javax.validation.constraints.Min;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.List;
+import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 /*
@@ -60,6 +66,10 @@ public class CouponController {
 
 	private final CouponClassificationMapper couponClassificationMapper;
 
+	private final BackInfoTranslationsService backInfoTranslationsService;
+
+	private final BackInfoTranslationsFrontService backInfoTranslationsFrontService;
+
 	private final OrderDonMapper orderDonMapper;
 
 	private final HttpServletRequest request;
@@ -95,7 +105,12 @@ public class CouponController {
 	@PutMapping
 	@Log(module = "优惠券/编辑优惠券", businessType = BusinessType.PUT, isSaveRequestData = true)
 	public Result<String> putCoupon(@RequestBody @Validated Coupon coupon) throws Exception {
-		couponCommonService.updateCoupon(coupon);
+		String lang = request.getHeader("lang");
+		if (!StrUtil.equals(UserPageLanguage.Language.zh_HK.name(), lang)) {
+			backInfoTranslationsService.saveOrUpdateBackInfoTranslations(BackInfoTranslations.Type.coupon, coupon.getId(), coupon, lang);
+		} else {
+			couponCommonService.updateCoupon(coupon);
+		}
 		return GatewayResponse.SUCCESS.newBuilder().toResult("修改优惠券成功");
 	}
 
@@ -109,15 +124,6 @@ public class CouponController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult("发放优惠券成功");
 	}
 
-	/**
-	 * 优惠券 设置为推荐优惠券
-	 */
-	@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("推荐优惠券成功");
-	}
 
 	/**
 	 * 优惠券关联固定推广者
@@ -144,7 +150,7 @@ public class CouponController {
 	public Result<SearchResult<CouponDistributePopularizeView>> getRelationList(HttpServletRequest request) {
 		SearchResult<CouponDistributePopularizeView> search = beanSearcher.search(CouponDistributePopularizeView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
 		search.getDataList().forEach(data -> {
-			Integer usedNum = orderDonMapper.selectCouponCodeUserNum(data.getId(), Constant.noOrderAllStatus);
+			Integer usedNum = orderDonMapper.selectCouponCodeUserNum(data.getId(), data.getExCode(), Constant.noOrderAllStatus);
 			data.setUsedNum(usedNum);
 		});
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
@@ -164,16 +170,21 @@ public class CouponController {
 	 */
 	@GetMapping
 	public Result<SearchResult<CouponView>> couponList(HttpServletRequest request) {
+		String lang = request.getHeader("lang");
 		SearchResult<CouponView> search = beanSearcher.search(CouponView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
 		search.getDataList().forEach(data -> {
 			data.setRelationNum(couponDistributePopularizeMapper.selectCount(Wrappers.lambdaQuery(CouponDistributePopularize.class).eq(CouponDistributePopularize::getCouponId, data.getId())));
 
-			Integer usedNum = couponUserMapper.selectCount(Wrappers.lambdaQuery(CouponUser.class)
-					.eq(CouponUser::getCouponId, data.getId()).eq(CouponUser::getStatus, CouponUser.Status.used));
+			Map<String, Long> couponUserNumData = couponUserMapper.selectCouponUserNumData(data.getId());
+			Integer usedNum = Integer.parseInt(couponUserNumData.get("usedNum").toString());
 			data.setUsedNum(usedNum);
-
+			Integer receiptNum = Integer.parseInt(couponUserNumData.get("receiptNum").toString());
+			data.setReceiptNum(receiptNum);
 			List<GoodsDonSkuView> skuViewList = couponSkuMapper.selectGoodsSkuViewList(data.getId());
 			data.setSkuViewList(skuViewList);
+			if (!StrUtil.equals(UserPageLanguage.Language.zh_HK.name(), lang)) {
+				backInfoTranslationsFrontService.setCouponLanguage(data, lang);
+			}
 		});
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
@@ -245,62 +256,6 @@ public class CouponController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult("失效发放优惠券成功");
 	}
 
-
-	/**
-	 * 推荐发放列表
-	 */
-	@GetMapping("/recommend/list")
-	public Result<SearchResult<CouponRecommendView>> couponRecommendList(HttpServletRequest request) {
-		SearchResult<CouponRecommendView> search = beanSearcher.search(CouponRecommendView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
-		search.getDataList().forEach(data -> {
-			Integer usedNum = couponUserMapper.selectCount(Wrappers.lambdaQuery(CouponUser.class)
-					.eq(CouponUser::getRecommendId, data.getId()).eq(CouponUser::getStatus, CouponUser.Status.used));
-			Integer receiptNum = couponUserMapper.selectCount(Wrappers.lambdaQuery(CouponUser.class)
-					.eq(CouponUser::getRecommendId, data.getId()));
-			data.setReceiptNum(receiptNum);
-			data.setUsedNum(usedNum);
-
-			List<GoodsDonSkuView> skuViewList = couponSkuMapper.selectGoodsSkuViewList(data.getCouponId());
-			data.setSkuViewList(skuViewList);
-		});
-		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
-	}
-
-	/**
-	 * 推荐优惠券设置/取消推荐
-	 */
-	@PutMapping("/recommend/putStatus/{recommendId}")
-	public Result<String> putRecommendStatusById(@PathVariable Long recommendId) {
-		CouponRecommend couponRecommend = couponRecommendMapper.selectById(recommendId);
-		if (couponRecommend == null || !couponRecommend.getDeleted()) {
-			throw BusinessRuntimeException.getInstance("该推荐优惠券不存在");
-		}
-		couponRecommend.setStatus(!couponRecommend.getStatus());
-		couponRecommendMapper.updateById(couponRecommend);
-		return GatewayResponse.SUCCESS.newBuilder().toResult("操作成功");
-	}
-
-	/**
-	 * 删除推荐优惠券
-	 */
-	@DeleteMapping("/recommend/del/{recommendId}")
-	public Result<String> deleteRecommendById(@PathVariable Long recommendId) {
-		CouponRecommend couponRecommend = couponRecommendMapper.selectById(recommendId);
-		if (couponRecommend == null || !couponRecommend.getDeleted()) {
-			throw BusinessRuntimeException.getInstance("该推荐优惠券不存在");
-		}
-		if (couponRecommend.getStatus()) {
-			throw BusinessRuntimeException.getInstance("取消推荐优惠券,才可删除");
-		}
-		couponRecommendMapper.deleteById(recommendId);
-		Coupon coupon = couponMapper.selectById(couponRecommend.getCouponId());
-		if (coupon != null && coupon.getDeleted()) {
-			coupon.setHotStatus(false);
-			couponMapper.updateById(coupon);
-		}
-		return GatewayResponse.SUCCESS.newBuilder().toResult("删除推荐优惠券成功");
-	}
-
 	/**
 	 * 新增优惠券分类
 	 */
@@ -358,13 +313,19 @@ public class CouponController {
 	 */
 	@PutMapping("/update/classification")
 	public Result<String> updateClassification(@RequestBody @Validated CouponClassification classification) {
+		String lang = request.getHeader("lang");
 		Long classificationId = classification.getId();
 		Assert.notNull(classificationId, "分类id为空");
 		CouponClassification couponClassification = couponClassificationMapper.selectById(classificationId);
 		if (couponClassification == null) {
 			throw BusinessRuntimeException.getInstance("该分类不存在");
 		}
-		couponClassificationMapper.updateById(classification);
+		//多语言设置
+		if (!StrUtil.equals(UserPageLanguage.Language.zh_HK.name(), lang)) {
+			backInfoTranslationsService.saveOrUpdateBackInfoTranslations(BackInfoTranslations.Type.coupon_classification, classification.getId(), classification, lang);
+		} else {
+			couponClassificationMapper.updateById(classification);
+		}
 		return GatewayResponse.SUCCESS.newBuilder().toResult("编辑分类成功");
 	}
 
@@ -385,4 +346,35 @@ public class CouponController {
 		List<CouponClassification> CouponClassifications = beanSearcher.searchAll(CouponClassification.class, MapUtils.flatBuilder(request.getParameterMap()).build());
 		return GatewayResponse.SUCCESS.newBuilder().toResult(CouponClassifications);
 	}
+
+	/**
+	 * 优惠券领取详情
+	 */
+	@GetMapping("/get/receipt/detail/{couponId}")
+	public Result<SearchResult<CouponReceiptDetailView>> getReceiptDetail(@PathVariable Long couponId) {
+		SearchResult<CouponReceiptDetailView> search = beanSearcher.search(CouponReceiptDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.put("cid",String.format("and id = %s", couponId))
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 优惠券使用详情
+	 */
+	@GetMapping("/get/used/detail/{couponId}")
+	public Result<SearchResult<CouponUsedDetailView>> getUsedDetail(@PathVariable Long couponId) {
+		SearchResult<CouponUsedDetailView> search = beanSearcher.search(CouponUsedDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.put("cid",String.format("and id = %s", couponId))
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 使用优惠券订单金额
+	 */
+	@GetMapping("/get/used/money/{couponId}")
+	public Result<BigDecimal> getUsedMoney(@PathVariable Long couponId) {
+		BigDecimal money = Optional.ofNullable(orderDonMapper.getCouponUsedMoney(couponId)).orElse(BigDecimal.ZERO);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(money.divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN));
+	}
 }