FengChaoYu 2 هفته پیش
والد
کامیت
77fdafb19f
100فایلهای تغییر یافته به همراه9235 افزوده شده و 23 حذف شده
  1. 6 0
      pom.xml
  2. 23 0
      src/main/java/com/gree/mall/contest/bean/activity/PromotionGoods.java
  3. 21 0
      src/main/java/com/gree/mall/contest/bean/activity/PromotionGroupBean.java
  4. 36 0
      src/main/java/com/gree/mall/contest/bean/activity/PromotionGroupDetail.java
  5. 26 0
      src/main/java/com/gree/mall/contest/bean/activity/PromotionGroupList.java
  6. 6 0
      src/main/java/com/gree/mall/contest/bean/admin/AdminUserCom.java
  7. 17 0
      src/main/java/com/gree/mall/contest/bean/coupon/BuyGoodsInfo.java
  8. 22 0
      src/main/java/com/gree/mall/contest/bean/coupon/CouponBean.java
  9. 24 0
      src/main/java/com/gree/mall/contest/bean/coupon/CouponDataBean.java
  10. 23 0
      src/main/java/com/gree/mall/contest/bean/coupon/CouponDetailBean.java
  11. 56 0
      src/main/java/com/gree/mall/contest/bean/coupon/CouponExportBean.java
  12. 22 0
      src/main/java/com/gree/mall/contest/bean/coupon/CouponPageBean.java
  13. 21 0
      src/main/java/com/gree/mall/contest/bean/coupon/CouponTagBean.java
  14. 33 0
      src/main/java/com/gree/mall/contest/bean/coupon/CouponUserBean.java
  15. 17 0
      src/main/java/com/gree/mall/contest/bean/coupon/CouponUserTypeBean.java
  16. 16 0
      src/main/java/com/gree/mall/contest/bean/coupon/ReissueCouponBean.java
  17. 19 0
      src/main/java/com/gree/mall/contest/bean/coupon/UserCouponBean.java
  18. 44 0
      src/main/java/com/gree/mall/contest/bean/goods/GoodsBean.java
  19. 22 0
      src/main/java/com/gree/mall/contest/bean/goods/GoodsCategoryUpdateBean.java
  20. 15 0
      src/main/java/com/gree/mall/contest/bean/goods/GoodsFreightBean.java
  21. 20 0
      src/main/java/com/gree/mall/contest/bean/goods/GoodsPackageBean.java
  22. 36 0
      src/main/java/com/gree/mall/contest/bean/goods/GoodsPackageList.java
  23. 19 0
      src/main/java/com/gree/mall/contest/bean/goods/GoodsPackagePopBean.java
  24. 44 0
      src/main/java/com/gree/mall/contest/bean/goods/GoodsSortBean.java
  25. 58 0
      src/main/java/com/gree/mall/contest/bean/goods/GoodsSpecBean.java
  26. 16 0
      src/main/java/com/gree/mall/contest/bean/goods/GoodsTemplateBean.java
  27. 24 0
      src/main/java/com/gree/mall/contest/bean/goods/GoodsTypeCount.java
  28. 8 0
      src/main/java/com/gree/mall/contest/bean/member/MemberBean.java
  29. 39 0
      src/main/java/com/gree/mall/contest/bean/member/MemberSortBean.java
  30. 15 0
      src/main/java/com/gree/mall/contest/bean/order/BatchRemarkBean.java
  31. 23 0
      src/main/java/com/gree/mall/contest/bean/order/DeliverGoodsBean.java
  32. 41 0
      src/main/java/com/gree/mall/contest/bean/order/OrderDetailBean.java
  33. 140 0
      src/main/java/com/gree/mall/contest/bean/order/OrderDetailListBean.java
  34. 27 0
      src/main/java/com/gree/mall/contest/bean/order/OrderRefundDetailBean.java
  35. 144 0
      src/main/java/com/gree/mall/contest/bean/order/OrderShareReportBean.java
  36. 26 0
      src/main/java/com/gree/mall/contest/bean/user/UserWxBean.java
  37. 39 0
      src/main/java/com/gree/mall/contest/commonmapper/CouponDateMapper.java
  38. 13 0
      src/main/java/com/gree/mall/contest/commonmapper/CoustomUserCouponMapper.java
  39. 105 0
      src/main/java/com/gree/mall/contest/commonmapper/CustomGoodsMapper.java
  40. 16 0
      src/main/java/com/gree/mall/contest/commonmapper/CustomMemberMapper.java
  41. 13 0
      src/main/java/com/gree/mall/contest/commonmapper/CustomWebsitMapper.java
  42. 14 0
      src/main/java/com/gree/mall/contest/commonmapper/GoodsCheckMapper.java
  43. 22 0
      src/main/java/com/gree/mall/contest/commonmapper/OrderMapper.java
  44. 16 0
      src/main/java/com/gree/mall/contest/commonmapper/OrderRefundInfoMapper.java
  45. 18 0
      src/main/java/com/gree/mall/contest/commonmapper/OrderShareReportMapper.java
  46. 37 0
      src/main/java/com/gree/mall/contest/commonmapper/PromotionMapper.java
  47. 35 7
      src/main/java/com/gree/mall/contest/config/wx/WxConfiguration.java
  48. 15 0
      src/main/java/com/gree/mall/contest/constant/Constant.java
  49. 4 4
      src/main/java/com/gree/mall/contest/controller/pc/goods/GoodsCategoryController.java
  50. 292 0
      src/main/java/com/gree/mall/contest/controller/pc/goods/GoodsController.java
  51. 278 0
      src/main/java/com/gree/mall/contest/controller/pc/order/OrderController.java
  52. 118 0
      src/main/java/com/gree/mall/contest/controller/pc/order/OrderRefundController.java
  53. 128 0
      src/main/java/com/gree/mall/contest/controller/pc/order/OrderShareController.java
  54. 5 0
      src/main/java/com/gree/mall/contest/enums/FreightTypeEnum.java
  55. 14 0
      src/main/java/com/gree/mall/contest/enums/GoodsTypeEnum.java
  56. 5 0
      src/main/java/com/gree/mall/contest/enums/OrderExamineEnum.java
  57. 16 0
      src/main/java/com/gree/mall/contest/enums/OrderRefundTypeEnum.java
  58. 16 0
      src/main/java/com/gree/mall/contest/enums/OrderShareStatusEnum.java
  59. 22 0
      src/main/java/com/gree/mall/contest/enums/OrderStatusEnum.java
  60. 14 0
      src/main/java/com/gree/mall/contest/enums/PayTypeEnum.java
  61. 15 0
      src/main/java/com/gree/mall/contest/enums/RefundFlagEnum.java
  62. 51 0
      src/main/java/com/gree/mall/contest/enums/UMSDiscountCodeEnum.java
  63. 21 0
      src/main/java/com/gree/mall/contest/enums/UserTypeEnum.java
  64. 31 0
      src/main/java/com/gree/mall/contest/enums/WXShareFailReasonEnum.java
  65. 19 0
      src/main/java/com/gree/mall/contest/enums/WXShareResultEnum.java
  66. 17 0
      src/main/java/com/gree/mall/contest/enums/WXShareStatusEnum.java
  67. 13 0
      src/main/java/com/gree/mall/contest/enums/coupon/CouponActiveTypeEnum.java
  68. 14 0
      src/main/java/com/gree/mall/contest/enums/coupon/CouponCrowdEnum.java
  69. 16 0
      src/main/java/com/gree/mall/contest/enums/coupon/CouponFlagEnum.java
  70. 16 0
      src/main/java/com/gree/mall/contest/enums/coupon/CouponTypeEnum.java
  71. 77 0
      src/main/java/com/gree/mall/contest/logic/ExpressLogic.java
  72. 99 0
      src/main/java/com/gree/mall/contest/logic/StorageLogic.java
  73. 524 0
      src/main/java/com/gree/mall/contest/logic/activity/PromotionGroupLogic.java
  74. 27 1
      src/main/java/com/gree/mall/contest/logic/common/CommonLogic.java
  75. 165 0
      src/main/java/com/gree/mall/contest/logic/common/WechatLogic.java
  76. 618 0
      src/main/java/com/gree/mall/contest/logic/coupon/CouponLogic.java
  77. 1146 0
      src/main/java/com/gree/mall/contest/logic/goods/GoodsLogic.java
  78. 106 0
      src/main/java/com/gree/mall/contest/logic/order/CommentTagLogic.java
  79. 943 0
      src/main/java/com/gree/mall/contest/logic/order/OrderLogic.java
  80. 342 0
      src/main/java/com/gree/mall/contest/logic/order/OrderRefundLogic.java
  81. 488 0
      src/main/java/com/gree/mall/contest/logic/order/OrderShareLogic.java
  82. 108 0
      src/main/java/com/gree/mall/contest/logic/user/MsgSubscriptLogic.java
  83. 621 0
      src/main/java/com/gree/mall/contest/logic/user/UserLogic.java
  84. 150 0
      src/main/java/com/gree/mall/contest/utils/ArithUtils.java
  85. 245 0
      src/main/java/com/gree/mall/contest/utils/excel/ExcelUtils.java
  86. 7 0
      src/main/resources/application-dev.properties
  87. 5 0
      src/main/resources/application-prd.properties
  88. 5 0
      src/main/resources/application-test.properties
  89. 4 11
      src/main/resources/application.properties
  90. 39 0
      src/main/resources/ehcache.xml
  91. 212 0
      src/main/resources/mapper/CouponDateMapper.xml
  92. 21 0
      src/main/resources/mapper/CoustomUserCouponMapper.xml
  93. 216 0
      src/main/resources/mapper/CustomGoodsMapper.xml
  94. 31 0
      src/main/resources/mapper/CustomMemberMapper.xml
  95. 22 0
      src/main/resources/mapper/CustomWebsitMapper.xml
  96. 31 0
      src/main/resources/mapper/GoodsCheckMapper.xml
  97. 118 0
      src/main/resources/mapper/OrderMapper.xml
  98. 77 0
      src/main/resources/mapper/OrderRefundInfoMapper.xml
  99. 117 0
      src/main/resources/mapper/OrderShareReportMapper.xml
  100. 54 0
      src/main/resources/mapper/PromotionMapper.xml

+ 6 - 0
pom.xml

@@ -36,6 +36,7 @@
         <aliyun.oss.version>3.8.1</aliyun.oss.version>
         <ali.easyexcel.version>3.3.2</ali.easyexcel.version>
         <poi.version>3.17</poi.version>
+        <bitwalker.version>1.21</bitwalker.version>
     </properties>
 
     <dependencies>
@@ -217,6 +218,11 @@
 <!--            <artifactId>poi-ooxml</artifactId>-->
 <!--            <version>${poi.version}</version>-->
 <!--        </dependency>-->
+        <dependency>
+            <groupId>eu.bitwalker</groupId>
+            <artifactId>UserAgentUtils</artifactId>
+            <version>${bitwalker.version}</version>
+        </dependency>
     </dependencies>
     <build>
         <plugins>

+ 23 - 0
src/main/java/com/gree/mall/contest/bean/activity/PromotionGoods.java

@@ -0,0 +1,23 @@
+package com.gree.mall.contest.bean.activity;
+
+import com.gree.mall.contest.plus.entity.PromotionGroupSpec;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class PromotionGoods {
+
+    @Schema(description = "商品id")
+    private String goodsId;
+    @Schema(description = "商品名称")
+    private String goodsName;
+    @Schema(description = "商品图")
+    private String goodsImgSrc;
+    @Schema(description = "活动规格列表")
+    private List<PromotionGroupSpec> specs;
+    @Schema(description = "排序")
+    private Integer sortNum;
+
+}

+ 21 - 0
src/main/java/com/gree/mall/contest/bean/activity/PromotionGroupBean.java

@@ -0,0 +1,21 @@
+package com.gree.mall.contest.bean.activity;
+
+import com.gree.mall.contest.plus.entity.PromotionGroup;
+import com.gree.mall.contest.plus.entity.PromotionGroupUser;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PromotionGroupBean extends PromotionGroup {
+
+    @Schema(description = "商品详情")
+    private List<PromotionGoods> goods;
+
+    @Schema(description = "团员id")
+    private List<PromotionGroupUser> promotionGroupUsers;
+
+}

+ 36 - 0
src/main/java/com/gree/mall/contest/bean/activity/PromotionGroupDetail.java

@@ -0,0 +1,36 @@
+package com.gree.mall.contest.bean.activity;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+public class PromotionGroupDetail {
+
+    @Schema(description = "用户id")
+    private String userId;
+    @Schema(description = "团长名称")
+    private String nickName;
+    @Schema(description = "所属网点")
+    private String websitName;
+    @Schema(description = "职务")
+    private String position;
+    @Schema(description = "手机号码")
+    private String phone;
+    @Schema(description = "首次分享时间")
+    private Date firstTime;
+    @Schema(description = "分享次数")
+    private Integer shareNum;
+    @Schema(description = "订单数量")
+    private Integer orderNum;
+    @Schema(description = "订单台数")
+    private Integer goodsNum;
+    @Schema(description = "成交金额")
+    private BigDecimal orderTotalAmount;
+    @Schema(description = "团长分佣总额")
+    private BigDecimal shareTotalAmount;
+    @Schema(description = "团长已分佣金额")
+    private BigDecimal settledAmount;
+}

+ 26 - 0
src/main/java/com/gree/mall/contest/bean/activity/PromotionGroupList.java

@@ -0,0 +1,26 @@
+package com.gree.mall.contest.bean.activity;
+
+import com.gree.mall.contest.plus.entity.PromotionGroup;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PromotionGroupList extends PromotionGroup {
+
+    @Schema(description = "参数产品数量")
+    private Integer goodsNum;
+    @Schema(description = "订单数量")
+    private Integer orderNum;
+    @Schema(description = "订单台数")
+    private Integer orderDetailNum;
+    @Schema(description = "订单总金额")
+    private BigDecimal orderTotalAmount;
+    @Schema(description = "团长分佣总额")
+    private BigDecimal shareTotalAmount;
+
+
+}

+ 6 - 0
src/main/java/com/gree/mall/contest/bean/admin/AdminUserCom.java

@@ -5,9 +5,11 @@ import com.gree.mall.contest.plus.entity.AdminUser;
 import com.gree.mall.contest.plus.entity.AdminWebsit;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 import java.util.List;
 
+@EqualsAndHashCode(callSuper = true)
 @Data
 public class AdminUserCom extends AdminUser {
 
@@ -21,6 +23,10 @@ public class AdminUserCom extends AdminUser {
     private List<String> companyWechatIds;
     @Schema(description = "当前登录人所使用的商户信息")
     private AdminCompanyWechat adminCompanyWechat;
+    @Schema(description = "当前登录人所使用的商户id")
+    private String loginCompanyWechatId;
+    @Schema(description = "当前登录人所使用的商户名称")
+    private String loginCompanyName;
 
     @Schema(description = "所有区id(平台业务员用)")
     private List<String> areaIds;

+ 17 - 0
src/main/java/com/gree/mall/contest/bean/coupon/BuyGoodsInfo.java

@@ -0,0 +1,17 @@
+package com.gree.mall.contest.bean.coupon;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+public class BuyGoodsInfo {
+
+    @Schema(description = "商品名称")
+    private String goodsName;
+
+    @Schema(description = "商品件数")
+    private int goodsCount;
+
+    @Schema(description = "商品件数")
+    private int memberCount;
+}

+ 22 - 0
src/main/java/com/gree/mall/contest/bean/coupon/CouponBean.java

@@ -0,0 +1,22 @@
+package com.gree.mall.contest.bean.coupon;
+
+import com.gree.mall.contest.plus.entity.Coupon;
+import com.gree.mall.contest.plus.entity.CouponGoods;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CouponBean extends Coupon {
+
+    @Schema(description = "商品列表")
+    private List<CouponGoods> goodsList;
+
+    @Schema(description = "待发券用户列表")
+    private List<CouponUserTypeBean> userList;
+
+
+}

+ 24 - 0
src/main/java/com/gree/mall/contest/bean/coupon/CouponDataBean.java

@@ -0,0 +1,24 @@
+package com.gree.mall.contest.bean.coupon;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+public class CouponDataBean {
+
+    @Schema(description = "用券总成交额")
+    private BigDecimal totalSaleValue;
+
+    @Schema(description = "优惠总金额")
+    private BigDecimal totalDiscountValue;
+
+    @Schema(description = "购买商品件数")
+    private int buyGoodsCount;
+
+    @Schema(description = "购买商品明细")
+    private List<BuyGoodsInfo> buyGoodsInfoList;
+
+}

+ 23 - 0
src/main/java/com/gree/mall/contest/bean/coupon/CouponDetailBean.java

@@ -0,0 +1,23 @@
+package com.gree.mall.contest.bean.coupon;
+
+import com.gree.mall.contest.plus.entity.Coupon;
+import com.gree.mall.contest.plus.entity.CouponGoods;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CouponDetailBean extends Coupon {
+    @Schema(description = "商品列表")
+    private List<CouponGoods> goodsList;
+
+    @Schema(description = "待发券标签列表")
+    private List<CouponTagBean> tagList;
+
+    @Schema(description = "待发券用户列表")
+    private List<CouponUserBean> userList;
+}

+ 56 - 0
src/main/java/com/gree/mall/contest/bean/coupon/CouponExportBean.java

@@ -0,0 +1,56 @@
+package com.gree.mall.contest.bean.coupon;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+
+@Data
+public class CouponExportBean {
+    @Schema(description = "领取时间")
+    private Date receiveTime;
+
+    @Schema(description = "优惠券名称")
+    private String couponName;
+
+    @Schema(description ="发放总量")
+    private Integer couponAmount;
+
+    @Schema(description ="领取数量")
+    private Integer receiveAmount;
+
+    @Schema(description ="使用数量")
+    private Integer usedAmount;
+
+    @Schema(description ="优惠券金额")
+    private Integer couponValue;
+
+    @Schema(description = "状态")
+    private Boolean status;
+
+    @Schema(description = "使用时间")
+    private Date usedTime;
+
+    @Schema(description = "订单id")
+    private String orderId;
+
+    @Schema(description = "订单金额")
+    private BigDecimal payAmount;
+
+    @Schema(description = "用户昵称")
+    private String nickName;
+
+    @Schema(description = "手机")
+    private String mobile;
+
+    @Schema(description = "业务员手机")
+    private String workPhone;
+
+    @Schema(description = "业务员名称")
+    private String workName;
+
+    @Schema(description = "网点名称")
+    private String websitName;
+}

+ 22 - 0
src/main/java/com/gree/mall/contest/bean/coupon/CouponPageBean.java

@@ -0,0 +1,22 @@
+package com.gree.mall.contest.bean.coupon;
+
+import com.gree.mall.contest.plus.entity.Coupon;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CouponPageBean extends Coupon {
+
+    @Schema(description = "领取数量")
+    private Integer receivedCount;
+
+    @Schema(description = "使用数量")
+    private Integer usedCount;
+
+    @Schema(description = "优惠券状态")
+    private String releaseFlag;
+
+
+}

+ 21 - 0
src/main/java/com/gree/mall/contest/bean/coupon/CouponTagBean.java

@@ -0,0 +1,21 @@
+package com.gree.mall.contest.bean.coupon;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+public class CouponTagBean {
+
+    @Schema(description = "tag分组id")
+    private String couponTagId;
+    @Schema(description = "tag分组id")
+    private String groupId;
+    @Schema(description = "tag分组名")
+    private String groupName;
+    @Schema(description = "tag名")
+    private String name;
+    @Schema(description = "tag Id")
+    private String tagId;
+
+
+}

+ 33 - 0
src/main/java/com/gree/mall/contest/bean/coupon/CouponUserBean.java

@@ -0,0 +1,33 @@
+package com.gree.mall.contest.bean.coupon;
+
+import com.gree.mall.contest.plus.entity.CouponUser;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+public class CouponUserBean extends CouponUser {
+    @Schema(description = "用户昵称")
+    private String nickName;
+
+    @Schema(description = "手机号")
+    private String mobile;
+
+    @Schema(description = "性别")
+    private String sex;
+
+    @Schema(description = "头像")
+    private String avatar;
+
+    @Schema(description = "用户类型")
+    private String type;
+
+    @Schema(description = "国家")
+    private String country;
+
+    @Schema(description = "省")
+    private String province;
+
+    @Schema(description = "市")
+    private String city;
+
+}

+ 17 - 0
src/main/java/com/gree/mall/contest/bean/coupon/CouponUserTypeBean.java

@@ -0,0 +1,17 @@
+package com.gree.mall.contest.bean.coupon;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+public class CouponUserTypeBean {
+
+    @Schema(description = "用户id")
+    private String userId;
+
+    @Schema(description = "用户名")
+    private String userName;
+
+    @Schema(description = "角色 GENERAL=普通用户 SERVICE=业务员")
+    private String type;
+}

+ 16 - 0
src/main/java/com/gree/mall/contest/bean/coupon/ReissueCouponBean.java

@@ -0,0 +1,16 @@
+package com.gree.mall.contest.bean.coupon;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+
+@Data
+public class ReissueCouponBean {
+    @Schema(description = "优惠券id")
+    private  String couponId;
+
+    @Schema(description = "用户列表")
+    private List<CouponUserTypeBean> userIds;
+}

+ 19 - 0
src/main/java/com/gree/mall/contest/bean/coupon/UserCouponBean.java

@@ -0,0 +1,19 @@
+package com.gree.mall.contest.bean.coupon;
+
+import com.gree.mall.contest.plus.entity.UserCoupon;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class UserCouponBean extends UserCoupon {
+
+    //商品券所对应的goodsId
+    private String goodsId;
+    @Schema(description ="用户昵称")
+    private String userName;
+    @Schema(description ="用户手机号")
+    private String mobile;
+
+}

+ 44 - 0
src/main/java/com/gree/mall/contest/bean/goods/GoodsBean.java

@@ -0,0 +1,44 @@
+package com.gree.mall.contest.bean.goods;
+
+import com.gree.mall.contest.plus.entity.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class GoodsBean extends Goods {
+
+    @Schema(description = "商品规格")
+    private List<GoodsSpec> goodsSpecs;
+
+    @Schema(description = "轮播图")
+    private List<CommonFile> images;
+
+    private String category1;
+    private String category2;
+    private String mainName;
+    private String smallName;
+    private Boolean isVr;
+
+    @Schema(description = "商品库存")
+    private Integer stock;
+    @Schema(description = "商品说明模板id")
+    private String templateId;
+    @Schema(description = "属性标签")
+    private List<String> tags;
+
+    @Schema(description = "标签")
+    private List<String> tagsLabel;
+
+    @Schema(description = "套购配置的比例商品")
+    private List<GoodsPackagePop> goodsPackagePops;
+    @Schema(description = "套购配置的指定用户-新增/编辑用")
+    private List<GoodsPackageUserRela> goodsPackageUserRelas;
+
+    @Schema(description = "套购商品配置的用户列表-详情用")
+    private List<User> users;
+
+}

+ 22 - 0
src/main/java/com/gree/mall/contest/bean/goods/GoodsCategoryUpdateBean.java

@@ -0,0 +1,22 @@
+package com.gree.mall.contest.bean.goods;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 批量修改商品分类
+ * @author :lijh
+ * @description:TODO
+ * @date :2024/5/8 10:27
+ */
+@Data
+public class GoodsCategoryUpdateBean {
+    @Schema(description = "商品id")
+    private List<String> goodsIds;
+    @Schema(description = "分类id")
+    private String categoryId;
+
+
+}

+ 15 - 0
src/main/java/com/gree/mall/contest/bean/goods/GoodsFreightBean.java

@@ -0,0 +1,15 @@
+package com.gree.mall.contest.bean.goods;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class GoodsFreightBean {
+    @Schema(description = "运费模板id")
+    private String freightTemplateId;
+
+    @Schema(description = "商品id列表")
+    private List<String> goodsIdList;
+}

+ 20 - 0
src/main/java/com/gree/mall/contest/bean/goods/GoodsPackageBean.java

@@ -0,0 +1,20 @@
+package com.gree.mall.contest.bean.goods;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class GoodsPackageBean {
+
+    @Schema(description = "商品名称")
+    private String goodsName;
+    @Schema(description = "图片")
+    private String imgUrl;
+    @Schema(description = "规格")
+    private List<GoodsPackagePopBean> goodsPackagePopList;
+    @Schema(description = "排序")
+    private Integer sortNum;
+
+}

+ 36 - 0
src/main/java/com/gree/mall/contest/bean/goods/GoodsPackageList.java

@@ -0,0 +1,36 @@
+package com.gree.mall.contest.bean.goods;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class GoodsPackageList {
+
+    @Schema( description = "商品id")
+    private String goodsId;
+    @Schema( description = "商品图")
+    private String imgUrl;
+    @Schema( description = "商品名称")
+    private String goodsName;
+    @Schema( description = "状态true=是 false=否")
+    private Boolean status;
+    @Schema( description = "参与产品数量")
+    private Integer goodsNums;
+    @Schema( description = "最低销售价")
+    private BigDecimal packageMinAmount;
+    @Schema( description = "最低分佣金额")
+    private BigDecimal packageMinShareAmount;
+    @Schema( description = "使用优惠券 0=不可使用 1=所有优惠券 2=满减券 3=商品券")
+    private Integer useCoupon;
+    @Schema( description = "适用范围 0=指定人员 1=所有人 2=普通用户 3=业务员")
+    private Integer packageUserType;
+    @Schema( description = "订单数量")
+    private Integer orderNums;
+    @Schema( description = "订单总金额")
+    private BigDecimal orderPayAmount;
+    @Schema( description = "商户")
+    private String companyName;
+
+}

+ 19 - 0
src/main/java/com/gree/mall/contest/bean/goods/GoodsPackagePopBean.java

@@ -0,0 +1,19 @@
+package com.gree.mall.contest.bean.goods;
+
+import com.gree.mall.contest.plus.entity.GoodsPackagePop;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class GoodsPackagePopBean extends GoodsPackagePop {
+
+    @Schema(description = "库存")
+    private Integer stock;
+    @Schema(description = "规格名称")
+    private String specName;
+    @Schema(description ="规格值")
+    private String specValue;
+
+}

+ 44 - 0
src/main/java/com/gree/mall/contest/bean/goods/GoodsSortBean.java

@@ -0,0 +1,44 @@
+package com.gree.mall.contest.bean.goods;
+
+import cn.hutool.json.JSONArray;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+
+@Data
+public class GoodsSortBean {
+
+    @Schema(description = "商品排序对应值 PRICE=销售价格 SHARE=分销金额 SOLD=销量 STOCK=库存")
+    private String sortColumn;
+    @Schema(description = "true=升序 false=倒序")
+    private boolean type = true ;
+
+
+    public static String convertColumn(JSONArray goodsSortBeanArray) {
+        StringBuilder sb = new StringBuilder();
+
+        for(int i = 0; i < goodsSortBeanArray.size(); i++) {
+            GoodsSortBean goodsSortBean = goodsSortBeanArray.getBean(i, GoodsSortBean.class);
+            switch (goodsSortBean.getSortColumn()) {
+                case "PRICE" :
+                    sb.append("t2.price ").append(goodsSortBean.isType() ? "ASC," : "DESC,");
+                    break;
+                case "SHARE" :
+                    sb.append("t2.share_amount ").append(goodsSortBean.isType() ? "ASC," : "DESC,");
+                    break;
+                case "SOLD" :
+                    sb.append("t2.sold_num ").append(goodsSortBean.isType() ? "ASC," : "DESC,");
+                    break;
+                case "STOCK" :
+                    sb.append("t2.stock_num ").append(goodsSortBean.isType() ? "ASC," : "DESC,");
+                    break;
+                default :
+            }
+        }
+        if(sb.toString().length() == 0) {
+            return null;
+        }
+        String resStr = sb.toString();
+        return resStr.substring(0, resStr.length() - 1);
+    }
+}

+ 58 - 0
src/main/java/com/gree/mall/contest/bean/goods/GoodsSpecBean.java

@@ -0,0 +1,58 @@
+package com.gree.mall.contest.bean.goods;
+
+import com.gree.mall.contest.plus.entity.Goods;
+import com.gree.mall.contest.plus.entity.GoodsSpec;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class GoodsSpecBean extends Goods {
+
+    @Schema(description = "商品规格id")
+    private String goodsSpecId;
+
+    @Schema(description = "规格值")
+    private String specValue;
+
+    @Schema(description = "图片")
+    private String specImgUrl;
+
+    @Schema(description = "成本价")
+    private BigDecimal costPrice;
+
+    @Schema(description = "销售价")
+    private BigDecimal price;
+
+    @Schema(description = "划线价格")
+    private BigDecimal orgPrice;
+
+    @Schema(description = "分销金额")
+    private BigDecimal shareAmount;
+
+    @Schema(description = "分销比例")
+    private Double sharePercent;
+
+    @Schema(description = "内部分销金额")
+    private BigDecimal innerShareAmount;
+
+    @Schema(description = "内部分销比列")
+    private Double innerSharePercent;
+
+    @Schema(description = "库存")
+    private Integer stockNum;
+
+    @Schema(description = "商品类别名称")
+    private String categoryName;
+
+    @Schema(description = "条形码")
+    private String barCode;
+
+    @Schema(description ="商品规格列表")
+    private List<GoodsSpec> goodsSpecs;
+
+}

+ 16 - 0
src/main/java/com/gree/mall/contest/bean/goods/GoodsTemplateBean.java

@@ -0,0 +1,16 @@
+package com.gree.mall.contest.bean.goods;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class GoodsTemplateBean {
+
+    @Schema(description = "模板id")
+    private String templateId;
+
+    @Schema(description = "商品id列表")
+    private List<String> goodsIdList;
+}

+ 24 - 0
src/main/java/com/gree/mall/contest/bean/goods/GoodsTypeCount.java

@@ -0,0 +1,24 @@
+package com.gree.mall.contest.bean.goods;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * 商品分类统计
+ */
+@Data
+public class GoodsTypeCount {
+
+    @Schema(description = "全部")
+    private Integer total;
+    @Schema(description = "出售中")
+    private Integer csz;
+    @Schema(description = "仓库中")
+    private Integer ckz;
+    @Schema(description = "活动中")
+    private Integer hdz;
+    @Schema(description = "已售罄")
+    private Integer ysq;
+
+
+}

+ 8 - 0
src/main/java/com/gree/mall/contest/bean/member/MemberBean.java

@@ -0,0 +1,8 @@
+package com.gree.mall.contest.bean.member;
+
+import com.gree.mall.contest.plus.entity.User;
+import lombok.Data;
+
+@Data
+public class MemberBean extends User {
+}

+ 39 - 0
src/main/java/com/gree/mall/contest/bean/member/MemberSortBean.java

@@ -0,0 +1,39 @@
+package com.gree.mall.contest.bean.member;
+
+import cn.hutool.json.JSONArray;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.gree.mall.contest.plus.entity.User;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+public class MemberSortBean {
+
+    @Schema(description = "会员排序对应值 ID=编号 SEX=性别 CREATE=注册时间 STATUS=状态")
+    private String sortColumn;
+    @Schema(description = "true=升序 false=倒序")
+    private boolean type = true ;
+
+
+    public static void convertColumn(JSONArray array, LambdaQueryWrapper<User> memberLambdaQueryWrapper) {
+
+        for(int i = 0; i < array.size(); i++) {
+            MemberSortBean bean = array.getBean(i, MemberSortBean.class);
+            switch (bean.getSortColumn()) {
+                case "ID" :
+                    memberLambdaQueryWrapper.orderBy(true, bean.isType(), User::getUserId);
+                    break;
+                case "SEX" :
+                    memberLambdaQueryWrapper.orderBy(true, bean.isType(), User::getSex);
+                    break;
+                case "CREATE" :
+                    memberLambdaQueryWrapper.orderBy(true, bean.isType(), User::getCreateTime);
+                    break;
+                case "STATUS" :
+                    memberLambdaQueryWrapper.orderBy(true, bean.isType(), User::getStatus);
+                    break;
+                default :
+            }
+        }
+    }
+}

+ 15 - 0
src/main/java/com/gree/mall/contest/bean/order/BatchRemarkBean.java

@@ -0,0 +1,15 @@
+package com.gree.mall.contest.bean.order;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class BatchRemarkBean {
+
+    @Schema(description = "订单号列表")
+    private List<String> orderIds;
+    @Schema(description = "备注信息")
+    private String remark;
+}

+ 23 - 0
src/main/java/com/gree/mall/contest/bean/order/DeliverGoodsBean.java

@@ -0,0 +1,23 @@
+package com.gree.mall.contest.bean.order;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+public class DeliverGoodsBean {
+
+    @Schema(description = "订单号")
+    private String orderId;
+    @Schema(description = "物流单号")
+    private String logisticsNo;
+    @Schema(description = "物流公司")
+    private String expressCorp;
+    @Schema(description = "仓库")
+    private String warehouse;
+    @Schema(description = "是否派单")
+    private Boolean send;
+    @Schema(description = "是否退换货")
+    private Boolean exchangeOrder;
+
+
+}

+ 41 - 0
src/main/java/com/gree/mall/contest/bean/order/OrderDetailBean.java

@@ -0,0 +1,41 @@
+package com.gree.mall.contest.bean.order;
+
+import com.gree.mall.contest.plus.entity.OrderComment;
+import com.gree.mall.contest.plus.entity.OrderDetail;
+import com.gree.mall.contest.plus.entity.OrderInfo;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class OrderDetailBean extends OrderInfo {
+
+    @Schema(description = "订单详情")
+    private List<OrderDetail> orderDetails;
+    @Schema(description = "卖家备注")
+    private String merchantRemark;
+    @Schema(description = "是否部分退款")
+    private String refund;
+    @Schema(description = "退款总金额")
+    private BigDecimal refundTotal;
+    @Schema(description = "是否可退款")
+    private Boolean refundAble;
+    @Schema(description = "派单成功(true=是 false=否)")
+    private Boolean toWorkOrder = false;
+    @Schema(description = "订单评价")
+    private OrderComment orderComment;
+    @Schema(description = "订单评价标签")
+    private List<String> orderCommentTags;
+    @Schema(description = "订单评价图片")
+    private List<String> orderCommentImgs;
+    @Schema(description = "团长名称")
+    private String promotionGroupUserName;
+    @Schema(description = "团长手机号")
+    private String promotionGroupMobile;
+
+
+}

+ 140 - 0
src/main/java/com/gree/mall/contest/bean/order/OrderDetailListBean.java

@@ -0,0 +1,140 @@
+package com.gree.mall.contest.bean.order;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+public class OrderDetailListBean {
+
+
+    @Schema(description = "订单号")
+    private String orderId;
+
+    @Schema(description = "商品名称")
+    private String goodsName;
+
+    private String goodsCode;
+
+    @Schema(description = "规格型号")
+    private String goodsSpecValue;
+
+    @Schema(description = "数量")
+    private Integer num;
+
+    @Schema(description = "销售单价")
+    private String price;
+
+    @Schema(description = "实际支付价格")
+    private BigDecimal payAmount;
+
+    @Schema(description = "支付总额(实际支付价格*数量)")
+    private BigDecimal totalPrice;
+
+    @Schema(description = "收货人名称")
+    private String receUserName;
+
+    @Schema(description = "收货人电话")
+    private String recePhone;
+
+    @Schema(description = "收货人地址")
+    private String address;
+
+    @Schema(description = "订单状态")
+    private String orderStatus;
+
+    @Schema(description = "退款标记")
+    private String refundFlag;
+
+    @Schema(description = "退款金额")
+    private String refundAmount;
+
+    @Schema(description = "退款数量")
+    private String refundNum;
+
+    @Schema(description = "备注")
+    private String remark;
+
+    @Schema(description = "下单时间")
+    private Date createTime;
+
+    private Date payTime;
+
+    @Schema(description = "买家昵称")
+    private String userName;
+
+    @Schema(description = "购买渠道")
+    private String workerName;
+
+    @Schema(description = "买家备注")
+    private String buyerMsg;
+
+    @Schema(description = "网点")
+    private String websitName;
+
+    @Schema(description = "业务员/网点")
+    private String workerNameWithWebsitName;
+
+    @Schema(description = "业务员手机号")
+    private String workerPhone;
+
+    @Schema(description = "分佣金额")
+    private String shareAmount;
+
+    @Schema(description = "团长名称")
+    private String nickName;
+
+    @Schema(description = "团长手机号")
+    private String mobile;
+
+    @Schema(description = "卖家留言")
+    private String refundMessage;
+
+    @Schema(description = "团购活动id")
+    private String promotionGroupId;
+
+    @Schema(description = "工单编号")
+    private String workerOrderNo;
+
+    @Schema(description = "评价商品的星数(0未评价)")
+    private Integer commentGoods;
+
+    @Schema(description = "评价服务的星数(0未评价)")
+    private Integer commentService;
+
+    @Schema(description = "评价物流的星数(0未评价)")
+    private Integer commentExpress;
+
+    @Schema(description = "退货说明")
+    private String refundExplain;
+
+    @Schema(description = "INSTALL和REPAIR")
+    private String workOrderType;
+
+    @Schema(description = "是否已入驻企业微信")
+    private Boolean isAddCorp;
+
+    @Schema(description = "是否为套购商品")
+    private Boolean promotionPackageGoods;
+
+    @Schema(description = "购买人姓名")
+    private String buyerName;
+
+    @Schema(description = "购买人手机")
+    private String buyerMobile;
+
+    @Schema(description = "购买人身份证")
+    private String buyerIdCard;
+
+    @Schema(description = "国补金额")
+    private BigDecimal couponMerchantContribute;
+
+    @Schema(description = "条形码")
+    private String barCode;
+
+    @Schema(description = "交易流水号")
+    private String transactionId;
+
+}

+ 27 - 0
src/main/java/com/gree/mall/contest/bean/order/OrderRefundDetailBean.java

@@ -0,0 +1,27 @@
+package com.gree.mall.contest.bean.order;
+
+import com.gree.mall.contest.plus.entity.CommonFile;
+import com.gree.mall.contest.plus.entity.OrderDetail;
+import com.gree.mall.contest.plus.entity.OrderRefund;
+import com.gree.mall.contest.plus.entity.OrderRequest;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class OrderRefundDetailBean extends OrderRefund {
+
+    @Schema(description = "订单详情")
+    private List<OrderDetail> orderDetails;
+    @Schema(description = "物流凭证")
+    private List<CommonFile> files;
+    @Schema(description = "退款凭证")
+    private List<CommonFile> tkFiles;
+    @Schema(description = "工单信息")
+    private List<OrderRequest> orderRequests;
+    private Boolean toWorkOrder = false;
+
+}

+ 144 - 0
src/main/java/com/gree/mall/contest/bean/order/OrderShareReportBean.java

@@ -0,0 +1,144 @@
+package com.gree.mall.contest.bean.order;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+public class OrderShareReportBean {
+
+    @Schema(description = "商城名称")
+    private String shopName;
+
+    @Schema(description = "结算编号")
+    private String orderShareId;
+
+    @Schema(description = "订单号")
+    private String orderId;
+
+   /* @ApiModelProperty("商品名")
+    private String goodsName;*/
+
+    /*@ApiModelProperty("单价")
+    private BigDecimal price;*/
+
+    /*@ApiModelProperty("数量")
+    private Integer num;*/
+
+    @Schema(description = "总价")
+    private BigDecimal totalPrice;
+    @Schema(description = "实付金额")
+    private BigDecimal payAmount;
+    @Schema(description = "运费")
+    private BigDecimal freight;
+
+    @Schema(description = "订单状态,是否售后")
+    private String orderStatus;
+    @Schema(description = "退款标记ING(退款中),PARTLY(部分退),ALL(全部退),COMMONLY(正常状态)")
+    private String refundFlag;
+
+    @Schema(description = "下单用户账号")
+    private String userId;
+
+    @Schema(description = "下单时间")
+    private Date createTime;
+
+    @Schema(description = "支付方式")
+    private String payType;
+
+    @Schema(description = "支付时间")
+    private Date payTime;
+
+    @Schema(description = "买家备注")
+    private String remark;
+
+    @Schema(description = "收货人")
+    private String receUserName;
+
+    @Schema(description = "收货电话")
+    private String recePhone;
+
+    @Schema(description = "收货地址")
+    private String address;
+
+    @Schema(description = "物流单号")
+    private String logisticsNo;
+
+    @Schema(description = "物流公司")
+    private String name;
+
+    @Schema(description = "发票类型")
+    private Boolean type;
+
+    @Schema(description = "发票抬头")
+    private String taxName;
+
+    @Schema(description = "发票内容")
+    private String content;
+
+    @Schema(description = "纳税人识别号")
+    private String taxNo;
+
+    @Schema(description = "公司注册地址")
+    private String registerAddress;
+
+    @Schema(description = "公司注册电话")
+    private String registerPhone;
+
+    @Schema(description = "开户行")
+    private String bank;
+
+    @Schema(description = "开户账号")
+    private String account;
+
+    @Schema(description = "接收邮箱")
+    private String receiverEmail;
+
+    @Schema(description = "接收手机号")
+    private String receiverPhone;
+
+    @Schema(description = "发票收件人")
+    private String receiverName;
+
+    @Schema(description = "发票收件地址")
+    private String receiverAddress;
+
+    @Schema(description = "折扣金额")
+    private BigDecimal discountAmount;
+
+    @Schema(description = "优惠券名称")
+    private String couponName;
+
+    @Schema(description = "交易号")
+    private String transactionId;
+
+    @Schema(description = "佣金结算状态")
+    private String shareStatus;
+
+    @Schema(description = "分销员")
+    private String workUserName;
+
+    @Schema(description = "所属网点")
+    private String websitName;
+
+/*
+    @Schema(description = "商品佣金")
+    private BigDecimal shareAmount;
+*/
+
+    @Schema(description = "订单佣金")
+    private BigDecimal amount;
+
+    @Schema(description = "结算时间")
+    private Date settleTime;
+
+
+    @Schema(description = "职位")
+    private String position;
+/*    @Schema(description = "大类编号")
+    private String mainNumber;*/
+
+
+}

+ 26 - 0
src/main/java/com/gree/mall/contest/bean/user/UserWxBean.java

@@ -0,0 +1,26 @@
+package com.gree.mall.contest.bean.user;
+
+import com.gree.mall.contest.plus.entity.User;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class UserWxBean extends User {
+
+    @Schema(description = "收益总额")
+    private BigDecimal totalAmount = new BigDecimal(0);
+    @Schema(description = "客户数量")
+    private Integer customerNums = 0;
+    @Schema(description = "绑定的业务员电话")
+    private String servicePhone;
+    @Schema(description = "绑定的业务员名称")
+    private String serviceName;
+    @Schema(description = "业务员自己真实名称")
+    private String workerName;
+    @Schema(description = "业务员自己电话")
+    private String workerPhone;
+}

+ 39 - 0
src/main/java/com/gree/mall/contest/commonmapper/CouponDateMapper.java

@@ -0,0 +1,39 @@
+package com.gree.mall.contest.commonmapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.contest.bean.coupon.*;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface CouponDateMapper {
+
+    /**
+     * 券数据
+     * @param couponId
+     * @return
+     */
+    @InterceptorIgnore(tenantLine = "true")
+    CouponDataBean data(@Param("couponId")String couponId);
+
+    @InterceptorIgnore(tenantLine = "true")
+    List<CouponUserBean> couponTagUser(@Param("couponId")String couponId);
+
+    @InterceptorIgnore(tenantLine = "true")
+    List<CouponUserTypeBean> reissueCouponUser(@Param("companyWechatId")String companyWechatId, @Param("couponId")String couponId);
+
+    @InterceptorIgnore(tenantLine = "true")
+    IPage<CouponPageBean> pageCoupon(Page<CouponPageBean> objectPage, @Param("companyWechatIds")List<String> companyWechatIds,
+                                     @Param("couponName")String couponName, @Param("couponType")String couponType, @Param("flag")String flag);
+
+
+    @InterceptorIgnore(tenantLine = "true")
+    List<CouponExportBean> exportCoupon(@Param("companyWechatIds")List<String> companyWechatIds,
+                                        @Param("couponName")String couponName, @Param("couponType")String couponType, @Param("flag")String flag);
+
+    @InterceptorIgnore(tenantLine = "true")
+    List<CouponExportBean> exportSelfCoupon(@Param("companyWechatIds")List<String> companyWechatIds,
+                                            @Param("couponName")String couponName, @Param("couponType")String couponType, @Param("flag")String flag);
+}

+ 13 - 0
src/main/java/com/gree/mall/contest/commonmapper/CoustomUserCouponMapper.java

@@ -0,0 +1,13 @@
+package com.gree.mall.contest.commonmapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import org.apache.ibatis.annotations.Param;
+
+public interface CoustomUserCouponMapper {
+
+    @InterceptorIgnore(tenantLine = "true")
+    void decreaseLeftTimes(@Param("id") String id);
+
+    @InterceptorIgnore(tenantLine = "true")
+    void increaseLeftTimes(@Param("id") String id);
+}

+ 105 - 0
src/main/java/com/gree/mall/contest/commonmapper/CustomGoodsMapper.java

@@ -0,0 +1,105 @@
+package com.gree.mall.contest.commonmapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.contest.bean.goods.GoodsPackageList;
+import com.gree.mall.contest.bean.goods.GoodsSpecBean;
+import com.gree.mall.contest.bean.goods.GoodsTypeCount;
+import com.gree.mall.contest.plus.entity.Goods;
+import com.gree.mall.contest.plus.entity.GoodsCategory;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+public interface CustomGoodsMapper {
+
+    /**
+     * 商品列表
+     *
+     * @param objectPage
+     * @param flag
+     * @param keyword
+     * @param startPrice
+     * @param endPrice
+     * @param startShare
+     * @param endShare
+     * @param sortStr
+     * @param categoryId
+     * @param status
+     * @return
+     */
+    @InterceptorIgnore(tenantLine = "true")
+    IPage<GoodsSpecBean> pageList(Page<GoodsSpecBean> objectPage,
+                                  @Param("flag") String flag,
+                                  @Param("keyword") String keyword,
+                                  @Param("startPrice") BigDecimal startPrice,
+                                  @Param("endPrice") BigDecimal endPrice,
+                                  @Param("startShare") BigDecimal startShare,
+                                  @Param("endShare") BigDecimal endShare,
+                                  @Param("sortStr") String sortStr,
+                                  @Param("categoryId") List<String> categoryId,
+                                  @Param("status") Boolean status,
+                                  @Param("goodsTypes") List<String> goodsTypes,
+                                  @Param("companyWechatIds")List<String> companyWechatIds);
+
+    @InterceptorIgnore(tenantLine = "true")
+    List<GoodsSpecBean> list(@Param("commonTemplateId") String commonTemplateId);
+
+
+    /**
+     * 根据商品类型统计
+     *
+     * @return
+     */
+    @InterceptorIgnore(tenantLine = "true")
+    GoodsTypeCount countByType(@Param("companyWechatIds") List<String> companyWechatIds);
+
+    /**
+     * 获取活动中的商品数量
+     *
+     * @return
+     */
+    @InterceptorIgnore(tenantLine = "true")
+    Integer countByFlag(@Param("companyWechatIds") List<String> companyWechatIds);
+
+    /**
+     * 已售罄商品数量
+     *
+     * @return
+     */
+    @InterceptorIgnore(tenantLine = "true")
+    Integer ysq(@Param("companyWechatIds") List<String> companyWechatIds);
+
+    /**
+     * 查询我的收藏
+     */
+    @Select("select b.goods_id,b.img_url,b.goods_name,b.goods_price,b.status,a.create_time from goods_favorite a join goods b on a.goods_id=b.goods_id where a.user_id=#{userId} order by a.create_time desc")
+    IPage<Goods> myGoodsFavorite(Page page, @Param("userId") String userId);
+
+    /**
+     * 查询商品分类
+     */
+    @InterceptorIgnore(tenantLine = "true")
+    GoodsCategory queryGoodsCategoryByGoodsId(@Param("goodsId") String goodsId);
+
+    /**
+     * 用 商品规格的 分销金额 覆盖其 为null的 内部分销金额
+     */
+    void syncGoodsSpecInnerShareMsg(@Param("companyWechatId") String companyWechatId);
+
+
+    IPage<GoodsPackageList> queryGoodsPackageList(Page objectPage,
+                                                  @Param("keyword") String keyword,
+                                                  @Param("startPrice") BigDecimal startPrice,
+                                                  @Param("endPrice") BigDecimal endPrice,
+                                                  @Param("startShare") BigDecimal startShare,
+                                                  @Param("endShare") BigDecimal endShare,
+                                                  @Param("sortStr") String sortStr,
+                                                  @Param("categoryId") List<String> categoryId,
+                                                  @Param("status") Boolean status,
+                                                  @Param("companyWechatIds")List<String> companyWechatIds);
+
+}

+ 16 - 0
src/main/java/com/gree/mall/contest/commonmapper/CustomMemberMapper.java

@@ -0,0 +1,16 @@
+package com.gree.mall.contest.commonmapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.gree.mall.contest.bean.member.MemberBean;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface CustomMemberMapper {
+    @InterceptorIgnore(tenantLine = "true")
+    List<MemberBean> queryUser(@Param("type") String type, @Param("keyword") String keyword,
+                               @Param("websitNos") List<String> websitNos, @Param("startTime") String startTime,
+                               @Param("endTime") String endTime, @Param("companyWechatIds") List<String> companyWechatIds);
+}

+ 13 - 0
src/main/java/com/gree/mall/contest/commonmapper/CustomWebsitMapper.java

@@ -0,0 +1,13 @@
+package com.gree.mall.contest.commonmapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface CustomWebsitMapper {
+    @InterceptorIgnore(tenantLine = "true")
+    List<String> queryById(@Param("id")String id);
+}

+ 14 - 0
src/main/java/com/gree/mall/contest/commonmapper/GoodsCheckMapper.java

@@ -0,0 +1,14 @@
+package com.gree.mall.contest.commonmapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface GoodsCheckMapper {
+    @InterceptorIgnore(tenantLine = "true")
+    Integer checkGoodsSec(@Param("goodsId")String goodsId);
+
+    @InterceptorIgnore(tenantLine = "true")
+    List<String> checkGoodsSecBatch(@Param("goodsIds")List<String> goodsIds);
+}

+ 22 - 0
src/main/java/com/gree/mall/contest/commonmapper/OrderMapper.java

@@ -0,0 +1,22 @@
+package com.gree.mall.contest.commonmapper;
+
+import com.gree.mall.contest.bean.order.OrderDetailListBean;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface OrderMapper {
+
+    /*通过查询信息查询下载的报表信息*/
+    List<OrderDetailListBean> selectByQueryMsg(
+            @Param("userId") String userId,  @Param("orderId")String orderId,  @Param("productName")String productName,  @Param("userName")String userName,
+            @Param("phone")String phone,  @Param("exchangeCode")String exchangeCode,  @Param("orderStatus")String orderStatus,
+            @Param("startCreateTime")String startCreateTime,  @Param("endCreateTime")String endCreateTime,
+            @Param("startPayTime")String startPayTime,  @Param("endPayTime")String endPayTime,  @Param("promotionGroupUserName")String promotionGroupUserName,
+            @Param("promotionGroupId")String promotionGroupId,@Param("promotionGroupUserId") String promotionGroupUserId,@Param("websitId") String websitId,
+            @Param("goodsId") String goodsId,
+            @Param("companyWechatIds") List<String> companyWechatIds,@Param("websitIds") List<String> websitIds
+    );
+}

+ 16 - 0
src/main/java/com/gree/mall/contest/commonmapper/OrderRefundInfoMapper.java

@@ -0,0 +1,16 @@
+package com.gree.mall.contest.commonmapper;
+
+import com.gree.mall.contest.bean.order.OrderDetailListBean;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+
+public interface OrderRefundInfoMapper {
+
+    List<OrderDetailListBean> getOrderRefundDetailList(
+            @Param("orderId") String orderId, @Param("orderRefundId")String orderRefundId, @Param("userName")String userName,
+            @Param("phone")String phone, @Param("orderStatus")String orderStatus, @Param("startCreateTime")String startCreateTime,
+            @Param("endCreateTime")String endCreateTime, @Param("startExamineTime")String startExamineTime, @Param("endExamineTime")String endExamineTime,
+            @Param("companyWechatIds") List<String> companyWechatIds,@Param("websitIds") List<String> websitIds);
+}

+ 18 - 0
src/main/java/com/gree/mall/contest/commonmapper/OrderShareReportMapper.java

@@ -0,0 +1,18 @@
+package com.gree.mall.contest.commonmapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.gree.mall.contest.bean.order.OrderShareReportBean;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface OrderShareReportMapper {
+
+    @InterceptorIgnore(tenantLine = "true")
+    List<OrderShareReportBean> queryReport(@Param("orderIds") List<String> orderIds);
+
+    @InterceptorIgnore(tenantLine = "true")
+    List<OrderShareReportBean> queryReport2(@Param("orderShareIdList") List<String> orderShareIdList);
+}

+ 37 - 0
src/main/java/com/gree/mall/contest/commonmapper/PromotionMapper.java

@@ -0,0 +1,37 @@
+package com.gree.mall.contest.commonmapper;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.gree.mall.contest.bean.activity.PromotionGroupDetail;
+import com.gree.mall.contest.plus.entity.PromotionGroupSpecUser;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.math.BigDecimal;
+
+@Mapper
+public interface PromotionMapper {
+
+    /**
+     * 查询团购活动订单总金额
+     */
+    BigDecimal queryOrderTotalAmount(@Param("promotionGroupId") String promotionGroupId);
+    /**
+     * 查询团购活动的分佣总金额
+     */
+    BigDecimal queryTotalShareAmount(@Param("status") String status,@Param("promotionGroupId") String promotionGroupId,@Param("userId") String userId);
+    /**
+     * 订单台数
+     */
+    Integer queryTotalGoodsNum(@Param("promotionGroupId") String promotionGroupId,@Param("userId") String userId);
+    /**
+     * 查询参与了该活动的团长列表
+     */
+    IPage<PromotionGroupSpecUser> queryGroupSpecUser(IPage page, @Param("promotionGroupId") String promotionGroupId);
+    /**
+     * 团购活动统计
+     */
+    PromotionGroupDetail queryPtDetail(@Param("promotionGroupId") String promotionGroupId, @Param("userId") String userId);
+
+
+
+}

+ 35 - 7
src/main/java/com/gree/mall/contest/config/wx/WxConfiguration.java

@@ -3,6 +3,9 @@ package com.gree.mall.contest.config.wx;
 import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
 import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
 import com.google.common.collect.Maps;
 import com.gree.mall.contest.logic.wxmp.WxMpMessageLogic;
 import com.gree.mall.contest.plus.entity.AdminCompanyWechat;
@@ -16,6 +19,7 @@ import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
 import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.stereotype.Component;
 
@@ -30,6 +34,8 @@ import java.util.Map;
 public class WxConfiguration {
 
     private final static String keyPath = "classpath:/static/apiclient_cert.p12";
+    @Value("${wechat.payment.notifyUrl}")
+    private String notifyUrl;
 
     //小程序服务
     public static Map<String, WxMaService> wxMaService = Maps.newConcurrentMap();
@@ -37,9 +43,11 @@ public class WxConfiguration {
     public static Map<String, WxMpService> wxMpServices = Maps.newConcurrentMap();
     //微信公众号推送消息
     public static Map<String, WxMpMessageRouter> wxMpMessageRouters = Maps.newConcurrentMap();
+    //微信支付服务 key = companyWechatId
+    public static Map<String, WxPayService> wxPayServices = Maps.newConcurrentMap();
+    //发货模板  key = companyWechatId
+    public static Map<String, String> temFhNotice = Maps.newConcurrentMap();
 
-    //    @Value("${wechat.payment.refundNotifyUrl}")
-//    private String refundNotifyUrl;
     @Autowired
     RedisUtil redisUtil;
     @Autowired
@@ -51,6 +59,7 @@ public class WxConfiguration {
         //查询企业微信配置
         List<AdminCompanyWechat> list = AdminCompanyWechatService.list();
         reloadWxConfig(list);
+
     }
 
     public void reloadWxConfig(List<AdminCompanyWechat> list) {
@@ -59,15 +68,12 @@ public class WxConfiguration {
             if (StringUtils.isBlank(companyWechat.getSubAppId()) || StringUtils.isBlank(companyWechat.getSubSecret())) {
                 continue;
             }
-            //初始化企业微信服务
-            //initCpService(companyWechat,redisUtil);
-            //初始化微信支付服务
-            //initWxPayService(companyWechat,notifyUrl);
-            //initWxSubPayService(companyWechat,notifyUrl);
             //初始化微信小程序服务
             initWxMaService(companyWechat, redisUtil);
             //初始化微信公众号服务
             initWxMpService(companyWechat, redisUtil);
+            //初始化微信支付服务
+            initWxPayService(companyWechat, keyPath, notifyUrl);
         }
     }
 
@@ -85,6 +91,7 @@ public class WxConfiguration {
         WxMaService service = new WxMaServiceImpl();
         service.setWxMaConfig(config);
         wxMaService.put(companyWechat.getSubAppId(), service);
+        temFhNotice.put(companyWechat.getCompanyWechatId(), companyWechat.getTemplate());
     }
 
     /**
@@ -116,4 +123,25 @@ public class WxConfiguration {
         log.info("结束初始化微信公众号服务");
     }
 
+    /**
+     * 初始化微信支付服务
+     *
+     * @param companyWechat
+     */
+    private static void initWxPayService(AdminCompanyWechat companyWechat, String keyPath, String notifyUrl) {
+
+        String path = keyPath.toLowerCase();
+        WxPayConfig wxPayConfig = new WxPayConfig();
+        wxPayConfig.setAppId(companyWechat.getPubAppId());
+        wxPayConfig.setMchId(companyWechat.getMchId());
+        wxPayConfig.setMchKey(companyWechat.getMchKey());
+        wxPayConfig.setSubAppId(companyWechat.getSubAppId());
+        wxPayConfig.setSubMchId(companyWechat.getSubMchId());
+        wxPayConfig.setNotifyUrl(notifyUrl);
+        wxPayConfig.setKeyPath(path);
+        WxPayService wxPayService = new WxPayServiceImpl();
+        wxPayService.setConfig(wxPayConfig);
+        wxPayServices.put(companyWechat.getCompanyWechatId(), wxPayService);
+    }
+
 }

+ 15 - 0
src/main/java/com/gree/mall/contest/constant/Constant.java

@@ -59,5 +59,20 @@ public class Constant {
         public final static String CLIENT = "mall:contest:client:";
     }
 
+    public class Img {
+        //订单售后 退款凭证
+        public final static String ORDER_REFUND_TKPZ = "order_refund_tkpz";
+        //订单售后 退货物流凭证
+        public final static String ORDER_REFUND_WLPZ = "order_refund_wlpz";
+        //商品轮播图
+        public final static String GOODS_IMG = "goods_img_cm";
+        //评价图片
+        public final static String ORDER_COMMENT = "order_comment";
+        //营销素材内容文件
+        public final static String MARKETING_CONTENT_FILE = "marketing_content_file";
+        //营销素材封面图
+        public final static String MARKETING_SHOW_IMAGE = "marketing_show_image";
+    }
+
     public final static Integer PAGE_SIZE = 100000;
 }

+ 4 - 4
src/main/java/com/gree/mall/contest/controller/pc/goods/GoodsCategoryController.java

@@ -18,7 +18,7 @@ import java.util.List;
 @Slf4j
 @RestController
 @Tag(name = "分类管理", description = "分类管理")
-@RequestMapping(value = "/goods/category", produces = "application/json; charset=utf-8")
+@RequestMapping(value = "/pc/goods/category", produces = "application/json; charset=utf-8")
 @RequiredArgsConstructor
 public class GoodsCategoryController {
 
@@ -27,9 +27,9 @@ public class GoodsCategoryController {
     @GetMapping("/list")
     @Operation(summary = "分类管理列表")
     public ResponseHelper<List<GoodsCategoryBean>> page(
-            @Parameter(name = "层级",required = false) @RequestParam(required = false, defaultValue = "1") Integer categoryLevel,
-            @Parameter(name = "分类名称",required = false) @RequestParam(required = false) String name,
-            @Parameter(name = "状态(true:显示 false:隐藏",required = false) @RequestParam(required = false) Boolean status,
+            @Parameter(description = "层级",required = false) @RequestParam(required = false, defaultValue = "1") Integer categoryLevel,
+            @Parameter(description = "分类名称",required = false) @RequestParam(required = false) String name,
+            @Parameter(description = "状态(true:显示 false:隐藏",required = false) @RequestParam(required = false) Boolean status,
             HttpServletRequest request
     ) throws RemoteServiceException {
         List<GoodsCategoryBean> list = goodsCategoryLogic.list(categoryLevel,name,status,request);

+ 292 - 0
src/main/java/com/gree/mall/contest/controller/pc/goods/GoodsController.java

@@ -0,0 +1,292 @@
+package com.gree.mall.contest.controller.pc.goods;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.gree.mall.contest.bean.goods.*;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.helper.ResponseHelper;
+import com.gree.mall.contest.logic.goods.GoodsLogic;
+import com.gree.mall.contest.plus.entity.User;
+import com.gree.mall.contest.utils.excel.ExcelUtils;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.util.List;
+
+@Slf4j
+@RestController
+@Tag(name = "商品列表", description = "商品列表")
+@RequestMapping(value = "/goods", produces = "application/json; charset=utf-8")
+@RequiredArgsConstructor
+public class GoodsController {
+
+    private final GoodsLogic goodsLogic;
+
+    @GetMapping("/count")
+    @Operation(summary = "分类统计")
+    public ResponseHelper<GoodsTypeCount> count(HttpServletRequest request){
+        GoodsTypeCount goodsTypeCount = goodsLogic.countByType(request);
+        return ResponseHelper.success(goodsTypeCount);
+    }
+
+    @GetMapping("/list/page")
+    @Operation(summary = "商品列表")
+    public ResponseHelper<IPage<GoodsSpecBean>> page(
+            @Parameter(description = "商品标志 S=出售中 O=售罄 W=仓库中 A=活动中") @RequestParam(required = false) String flag,
+            @Parameter(description = "商品关键字") @RequestParam(required = false) String keyword,
+            @Parameter(description = "销售价格开始区间") @RequestParam(required = false) BigDecimal startPrice,
+            @Parameter(description = "销售价格结束区间") @RequestParam(required = false) BigDecimal endPrice,
+            @Parameter(description = "分销金额开始区间") @RequestParam(required = false) BigDecimal startShare,
+            @Parameter(description = "分销金额开始区间") @RequestParam(required = false) BigDecimal endShare,
+            @Parameter(description = "排序json格式[{sortColumn: 'PRICE', type: true },...] " +
+                    "sortColumn:商品排序对应值 PRICE=销售价格 SHARE=分销金额 SOLD=销量 STOCK=库存, " +
+                    "type: true=升序 false=倒序")
+            @RequestParam(required = false) String sortJson,
+            @Parameter(description = "商品分类 传入商品小类") @RequestParam(required = false) String categoryId,
+            @Parameter(description = "商品状态 true:上架  false:下架") @RequestParam(required = false) Boolean status,
+            @Parameter(description = "商品类型:COMMON=普通商品 PACKAGE=套购商品,不传默认为普通商品,支持传多个",required = false)
+            @RequestParam(required = false) List<String> goodsTypes,
+            @Parameter(description = "页号",required = true) @RequestParam Integer pageNum,
+            @Parameter(description = "页大小",required = true) @RequestParam Integer pageSize,
+            HttpServletRequest request
+    ) throws Exception {
+        IPage<GoodsSpecBean> goodsSpecBeanIPage = goodsLogic.page(flag, keyword, startPrice, endPrice,
+                startShare, endShare, sortJson, categoryId, status,goodsTypes, pageNum, pageSize , request);
+        return ResponseHelper.success(goodsSpecBeanIPage);
+    }
+
+    @GetMapping("/list/export")
+    @Operation(summary = "导出excel")
+    public void downloadFile (HttpServletRequest request, HttpServletResponse response,
+                              @Parameter(description = "商品标志 S=出售中 O=售罄 W=仓库中 A=活动中") @RequestParam(required = false) String flag,
+                              @Parameter(description = "商品关键字") @RequestParam(required = false) String keyword,
+                              @Parameter(description = "销售价格开始区间") @RequestParam(required = false) BigDecimal startPrice,
+                              @Parameter(description = "销售价格结束区间") @RequestParam(required = false) BigDecimal endPrice,
+                              @Parameter(description = "分销金额开始区间") @RequestParam(required = false) BigDecimal startShare,
+                              @Parameter(description = "分销金额开始区间") @RequestParam(required = false) BigDecimal endShare,
+                              @Parameter(description = "排序json格式[{sortColumn: 'PRICE', type: true },...] " +
+                                      "sortColumn:商品排序对应值 PRICE=销售价格 SHARE=分销金额 SOLD=销量 STOCK=库存, " +
+                                      "type: true=升序 false=倒序")
+                                  @RequestParam(required = false) String sortJson,
+                              @Parameter(description = "商品分类 传入商品小类") @RequestParam(required = false) String categoryId,
+                              @Parameter(description = "商品状态 true:上架  false:下架") @RequestParam(required = false) Boolean status,
+                              @Parameter(description = "商品类型:COMMON=普通商品 PACKAGE=套购商品,不传默认为普通商品,支持传多个",required = false) @RequestParam(required = false) List<String> goodsTypes
+    ) throws Exception {
+        goodsLogic.export( request,  response, flag, keyword, startPrice, endPrice,
+                startShare, endShare, sortJson, categoryId, status,goodsTypes);
+    }
+
+
+    @GetMapping("/package/list")
+    @Operation(summary = "套餐商品-列表")
+    public ResponseHelper<IPage<GoodsPackageList>> packageList(
+            @Parameter(description = "商品关键字") @RequestParam(required = false) String keyword,
+            @Parameter(description = "销售价格开始区间") @RequestParam(required = false) BigDecimal startPrice,
+            @Parameter(description = "销售价格结束区间") @RequestParam(required = false) BigDecimal endPrice,
+            @Parameter(description = "分销金额开始区间") @RequestParam(required = false) BigDecimal startShare,
+            @Parameter(description = "分销金额开始区间") @RequestParam(required = false) BigDecimal endShare,
+            @Parameter(description = "排序json格式[{sortColumn: 'PRICE', type: true },...] " +
+                    "sortColumn:商品排序对应值 PRICE=销售价格 SHARE=分销金额 SOLD=销量 STOCK=库存, " +
+                    "type: true=升序 false=倒序")
+            @RequestParam(required = false) String sortJson,
+            @Parameter(description = "商品分类 传入商品小类") @RequestParam(required = false) String categoryId,
+            @Parameter(description = "商品状态 true:上架  false:下架") @RequestParam(required = false) Boolean status,
+            @Parameter(description = "页号",required = true) @RequestParam Integer pageNum,
+            @Parameter(description = "页大小",required = true) @RequestParam Integer pageSize,
+            HttpServletRequest request
+    ) throws Exception {
+        IPage<GoodsPackageList> goodsPackageListIPage = goodsLogic.packageList(keyword, startPrice, endPrice,
+                startShare, endShare, sortJson, categoryId, status, pageNum, pageSize, request);
+        return ResponseHelper.success(goodsPackageListIPage);
+    }
+
+
+
+    @GetMapping("/listbycategory")
+    @Operation(summary = "商品详情")
+    public ResponseHelper<List<GoodsSpecBean>> listbycategory(
+            @Parameter(description = "商品分类 传入商品小类") @RequestParam(required = false) List<String> categoryIds,
+            HttpServletRequest request
+    ) throws RemoteServiceException {
+        List<GoodsSpecBean> listbycategory = goodsLogic.listbycategory(categoryIds,request);
+        return ResponseHelper.success(listbycategory);
+    }
+
+    @PostMapping("/batch/category/update")
+    @Operation(summary = "批量修改分类")
+    public ResponseHelper batchUpdate(@RequestBody GoodsCategoryUpdateBean goodsCategoryUpdateBean){
+        goodsLogic.updateCategory(goodsCategoryUpdateBean);
+        return ResponseHelper.success();
+    }
+
+
+    @GetMapping("/detail")
+    @Operation(summary = "商品详情")
+    public ResponseHelper<GoodsBean> detail(
+            @Parameter(description = "id",required = true) @RequestParam String goodsId
+    ) throws RemoteServiceException {
+        GoodsBean detail = goodsLogic.detail(goodsId);
+        return ResponseHelper.success(detail);
+    }
+
+
+    @GetMapping("/package/poplist")
+    @Operation(summary = "套购商品-配置商品列表")
+    public ResponseHelper<List<GoodsPackageBean>> popList(
+            @Parameter(description = "商品id",required = true) @RequestParam String goodsId,
+            @Parameter(description = "第几个商品框",required = true) @RequestParam Integer type
+    ) throws RemoteServiceException {
+        List<GoodsPackageBean> goodsPackageBeans = goodsLogic.popList(goodsId, type);
+        return ResponseHelper.success(goodsPackageBeans);
+    }
+
+    @PostMapping("/add")
+    @Operation(summary = "新增商品")
+    public ResponseHelper add(
+            @Parameter(description = "object",required = true) @RequestBody GoodsBean goodsBean,HttpServletRequest request)
+            throws RemoteServiceException {
+        goodsLogic.add(goodsBean,request);
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/update")
+    @Operation(summary = "修改商品")
+    public ResponseHelper update(
+            @Parameter(description = "object",required = true) @RequestBody GoodsBean goodsBean,HttpServletRequest request)
+            throws RemoteServiceException {
+        goodsLogic.update(goodsBean,request);
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/status/update")
+    @Operation(summary = "商品上下架")
+    public ResponseHelper change(
+            @Parameter(description = "商品id",required = true) @RequestParam String goodsId,
+            @Parameter(description = "商品状态:true上架 false下架",required = true) @RequestParam Boolean status
+    ) throws RemoteServiceException {
+        goodsLogic.updateStatus(goodsId, status);
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/delete")
+    @Operation(summary = "删除商品")
+    public ResponseHelper delete(
+            @Parameter(description = "商品id",required = true) @RequestParam String goodsId
+    ) throws RemoteServiceException {
+        goodsLogic.delete(goodsId);
+        return ResponseHelper.success();
+    }
+    @PostMapping("/clone")
+    @Operation(summary = "克隆商品")
+    public ResponseHelper clone(
+            @Parameter(description = "商品id",required = true) @RequestParam String goodsId
+    ) throws RemoteServiceException {
+        return ResponseHelper.success(goodsLogic.clone(goodsId));
+    }
+
+
+    @PostMapping("/goods/off/check")
+    @Operation(summary = "下架商品前,检测是否秒杀商品")
+    public ResponseHelper SecCheck(
+            @Parameter(description = "商品id",required = true) @RequestParam String goodsId)
+            throws RemoteServiceException {
+        return ResponseHelper.success(goodsLogic.secCheck(goodsId));
+    }
+
+    @PostMapping("/goods/off/check/batch")
+    @Operation(summary = "下架商品前,批量检测是否秒杀商品,返回秒杀的商品id列表")
+    public ResponseHelper SecCheckBatch(
+            @Parameter(description = "商品id",required = true) @RequestBody List<String> goodsIdList)
+            throws RemoteServiceException {
+        return ResponseHelper.success(goodsLogic.secCheckBatch(goodsIdList));
+    }
+
+
+
+    @PostMapping("/goods/on")
+    @Operation(summary = "批量上架商品")
+    public ResponseHelper goodsOn(
+            @Parameter(description = "object",required = true) @RequestBody List<String> goodsIdList)
+            throws RemoteServiceException {
+        goodsLogic.goodsOnOff(goodsIdList,true);
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/goods/off")
+    @Operation(summary = "批量下架商品")
+    public ResponseHelper goodsOf(
+            @Parameter(description = "object",required = true) @RequestBody List<String> goodsIdList)
+            throws RemoteServiceException {
+        goodsLogic.goodsOnOff(goodsIdList,false);
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/goods/template")
+    @Operation(summary = "批量修改商品模板")
+    public ResponseHelper goodsTemplate(
+            @Parameter(description = "object",required = true) @RequestBody GoodsTemplateBean goodsTemplateBean,HttpServletRequest request)
+            throws RemoteServiceException {
+        goodsLogic.goodsTemplate(goodsTemplateBean,request);
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/goods/batch/freight")
+    @Operation(summary = "批量修改运费模板")
+    public ResponseHelper goodsFreight(
+            @Parameter(description = "object",required = true) @RequestBody GoodsFreightBean goodsFreightBean)
+            throws RemoteServiceException {
+        goodsLogic.goodsFreight(goodsFreightBean);
+        return ResponseHelper.success();
+    }
+
+
+    @GetMapping("/package/user")
+    @Operation(summary = "套购商品-指定人员列表")
+    public ResponseHelper<List<User>> packageUserList(
+            @Parameter(description = "商品id",required = true) @RequestParam(required = true) String goodsId,
+            @Parameter(description = "商品id",required = false) @RequestParam(required = false) String mobile
+    ) throws Exception {
+        List<User> packageUseUserList = goodsLogic.getPackageUseUserList(goodsId, mobile);
+        return ResponseHelper.success(packageUseUserList);
+    }
+
+
+    @PostMapping("/package/import")
+    @Operation(summary = "套购商品-导入指定人员")
+    public ResponseHelper<List<User>> packageUserList(
+            MultipartFile multipartFile
+    ) throws Exception {
+        List<Object> objects = ExcelUtils.importExcel(multipartFile);
+        List<User> users = goodsLogic.importPackageUser(objects);
+        return ResponseHelper.success(users);
+    }
+
+    @Operation(summary = "复制分类商品信息")
+    @GetMapping("/copy/categoryAndGoods")
+    public ResponseHelper categoryAndGoods(
+            @RequestParam String sourceCompanyId,
+            @RequestParam String targetCompanyId,
+            @RequestParam String targetCompanyName
+    ){
+        goodsLogic.categoryAndGoods(sourceCompanyId, targetCompanyId, targetCompanyName);
+        return ResponseHelper.success();
+    }
+
+    @Operation(summary = "复制运费信息")
+    @GetMapping("/copy/freightTemplate")
+    public ResponseHelper copyFreightTemplate(
+            @RequestParam String sourceCompanyId,
+            @RequestParam String targetCompanyId,
+            @RequestParam String targetCompanyName
+    ){
+        goodsLogic.copyFreightTemplate(sourceCompanyId, targetCompanyId, targetCompanyName);
+        return ResponseHelper.success();
+    }
+}

+ 278 - 0
src/main/java/com/gree/mall/contest/controller/pc/order/OrderController.java

@@ -0,0 +1,278 @@
+package com.gree.mall.contest.controller.pc.order;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.gree.mall.contest.bean.order.BatchRemarkBean;
+import com.gree.mall.contest.bean.order.OrderDetailBean;
+import com.gree.mall.contest.constant.Constant;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.helper.ResponseHelper;
+import com.gree.mall.contest.logic.order.OrderLogic;
+import com.gree.mall.contest.plus.entity.OrderInfo;
+import com.gree.mall.contest.plus.entity.OrderRefundCliaims;
+import com.gree.mall.contest.utils.CommonUtils;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.integration.redis.util.RedisLockRegistry;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+
+@Slf4j
+@RestController
+@Tag(name = "订单管理", description = "订单管理")
+@RequestMapping(value = "/order", produces = "application/json; charset=utf-8")
+@RequiredArgsConstructor
+public class OrderController {
+
+    private final OrderLogic orderLogic;
+    private final RedisLockRegistry redisLockRegistry;
+
+    @GetMapping("/list")
+    @Operation(summary ="列表")
+    public ResponseHelper<Page<OrderDetailBean>> list(
+            @Parameter(description = "用户id", required = false) @RequestParam(required = false) String userId,
+            @Parameter(description = "订单号", required = false) @RequestParam(required = false) String orderId,
+            @Parameter(description = "产品名称", required = false) @RequestParam(required = false) String productName,
+            @Parameter(description = "用户名", required = false) @RequestParam(required = false) String userName,
+            @Parameter(description = "手机号", required = false) @RequestParam(required = false) String phone,
+            @Parameter(description = "兑换码", required = false) @RequestParam(required = false) String exchangeCode,
+            @Parameter(description = "订单状态 NOPAY:待付款 DFH:待发货 YFH:已发货 OVER:已完成 CLOSE:已关闭", required = false) @RequestParam(required = false) String orderStatus,
+            @Parameter(description = "开始创建时间", required = false) @RequestParam(required = false) String startCreateTime,
+            @Parameter(description = "结束创建时间", required = false) @RequestParam(required = false) String endCreateTime,
+            @Parameter(description = "开始支付时间", required = false) @RequestParam(required = false) String startPayTime,
+            @Parameter(description = "结束支付时间", required = false) @RequestParam(required = false) String endPayTime,
+            @Parameter(description = "网点id", required = false) @RequestParam(required = false) String websitId,
+            @Parameter(description = "页号", required = true) @RequestParam(required = true) Integer pageNum,
+            @Parameter(description = "页大小", required = true) @RequestParam(required = true) Integer pageSize,
+            @Parameter(description = "是否是差评订单0:未评价订单 1:差评订单 2:好评订单 3:已评价订单  不传都有", required = false) @RequestParam(required = false) String isNegative,
+            @Parameter(description = "派工异常 true为派工异常订单", required = false) @RequestParam(required = false) String abnormalDispatch,
+            @Parameter(description = "信息编号", required = false) @RequestParam(required = false) String workerOrderNo,
+            @Parameter(description = "套购商品id", required = false) @RequestParam(required = false) String goodsId,
+             HttpServletRequest request
+    ) throws RemoteServiceException {
+        IPage<OrderDetailBean> list = orderLogic
+                .list(request,userId,orderId, productName, userName, phone,exchangeCode, orderStatus, startCreateTime,
+                        endCreateTime, startPayTime, endPayTime,websitId,pageNum, pageSize,isNegative,abnormalDispatch,workerOrderNo,goodsId);
+        return ResponseHelper.success(list);
+    }
+
+    @GetMapping("/detail")
+    @Operation(summary ="订单详情")
+    public ResponseHelper<OrderDetailBean> detail(
+            @Parameter(description = "订单号", required = true) @RequestParam(required = true) String orderId
+    ) {
+        OrderDetailBean detail = orderLogic.detail(orderId);
+        return ResponseHelper.success(detail);
+    }
+
+
+    @PostMapping("/comment/show")
+    @Operation(summary ="显示评价")
+    public ResponseHelper showComment(
+            @Parameter(description = "订单号", required = true) @RequestParam(required = true) String orderId,
+            @Parameter(description = "true=显示 false=不显示", required = true) @RequestParam(required = true) Boolean isShow
+    ) {
+        orderLogic.updateShowComment(orderId,isShow);
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/remark")
+    @Operation(summary ="备注")
+    public ResponseHelper remark(
+            @Parameter(description = "订单号", required = true) @RequestParam(required = true) String orderId,
+            @Parameter(description = "备注", required = true) @RequestParam(required = true) String remark
+    ) {
+        orderLogic.remark(orderId, remark);
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/express/update")
+    @Operation(summary ="修改物流单号")
+    public ResponseHelper updateExpress(
+            @Parameter(description = "订单号", required = true) @RequestParam(required = true) String orderId,
+            @Parameter(description = "物流单号", required = true) @RequestParam(required = true) String logisticsNo,
+            @Parameter(description = "物流公司code", required = true) @RequestParam(required = true) String companyCode
+    ) throws RemoteServiceException {
+        orderLogic.updateExpress(orderId, logisticsNo,companyCode);
+        return ResponseHelper.success();
+    }
+
+    @GetMapping("/expressInfo/select")
+    @Operation(summary ="查看物流")
+    public ResponseHelper queryExpressInfo(
+            @Parameter(description = "物流单号", required = true) @RequestParam(required = true) String logisticsNo
+    ) throws RemoteServiceException {
+        orderLogic.queryExpressInfo(logisticsNo);
+        return ResponseHelper.success();
+    }
+
+
+    @PostMapping("/cancel")
+    @Operation(summary ="取消订单")
+    public ResponseHelper remark(
+            @Parameter(description = "订单号", required = true) @RequestParam(required = true) String orderId
+    ) throws RemoteServiceException, WxPayException {
+        orderLogic.cancel(orderId);
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/ack")
+    @Operation(summary ="确认收款")
+    public ResponseHelper ack(
+            @Parameter(description = "订单号", required = true) @RequestParam(required = true) String orderId
+    ) {
+        orderLogic.ackPay(orderId);
+        return ResponseHelper.success();
+    }
+
+
+
+    @PostMapping("/detail/refund")
+    @Operation(summary ="订单详情主动退款")
+    public ResponseHelper<BigDecimal> notice(
+            @Parameter(description = "订单详情id",required = true) @RequestParam String orderDetailId,
+            @Parameter(description = "数量",required = true) @RequestParam Integer num,
+            @Parameter(description = "退款密码") @RequestParam(required = false) String refundPassword
+    ) throws Exception {
+        BigDecimal refund = orderLogic.refund(orderDetailId, num, refundPassword);
+        return ResponseHelper.success(refund);
+    }
+
+    @GetMapping("/cliaims/list")
+    @Operation(summary ="理赔列表")
+    public ResponseHelper<List<OrderRefundCliaims>> cliaimslist(
+            @Parameter(description = "订单id",required = true) @RequestParam String orderId
+    ) throws RemoteServiceException, WxPayException {
+        List<OrderRefundCliaims> orderRefundCliaims = orderLogic.cliaimsList(orderId);
+        return ResponseHelper.success(orderRefundCliaims);
+    }
+
+    @PostMapping("/cliaims/refund")
+    @Operation(summary ="订单详情理赔")
+    public ResponseHelper refundcliaims(
+            @Parameter(description = "订单详情id",required = true) @RequestParam String orderDetailId,
+            @Parameter(description = "数量",required = true) @RequestParam Integer num,
+            @Parameter(description = "退款金额",required = true) @RequestParam BigDecimal refundAmount,
+            @Parameter(description = "登录人帐号id",required = true) @RequestParam String adminUserId,
+            @Parameter(description = "理赔备注",required = true) @RequestParam String remark,
+            @Parameter(description = "退款密码") @RequestParam(required = false) String refundPassword
+    ) throws Exception {
+        orderLogic.refundCliaims(orderDetailId, num, refundAmount, adminUserId, remark, refundPassword);
+        return ResponseHelper.success();
+    }
+
+
+    @PostMapping("/price/update")
+    @Operation(summary ="修改价格")
+    public ResponseHelper upatePrice(
+            @Parameter(description = "订单号", required = true) @RequestParam(required = true) String orderId,
+            @Parameter(description = "价格", required = true) @RequestParam(required = true) BigDecimal price
+    ) throws RemoteServiceException {
+        orderLogic.updatePrice(orderId, price);
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/rece/info/update")
+    @Operation(summary ="收货信息修改")
+    public ResponseHelper updateReceInfo(
+            @Parameter(description = "订单", required = true) @RequestBody OrderInfo orderInfo
+    ) throws RemoteServiceException {
+        orderLogic.updateReceInfo(orderInfo);
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/goods/deliver")
+    @Operation(summary ="发货")
+    public ResponseHelper deliverGoods(
+            @Parameter(description = "订单号", required = true) @RequestParam(required = true) String orderId,
+            @Parameter(description = "快递单号", required = true) @RequestParam(required = true) String logisticsNo,
+            @Parameter(description = "货仓id", required = true) @RequestParam(required = true) String storageId,
+            @Parameter(description = "快递公司编号", required = true) @RequestParam(required = true) String companyCode,
+            @Parameter(description = "是否需要派单 true=是 false=否", required = false) @RequestParam(required = false) Boolean workOrder,
+            @Parameter(description = "是否退换单 true=是 false=否", required = false) @RequestParam(required = false) Boolean exchange
+    ) throws Exception {
+        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER + orderId);
+        if(!obtain.tryLock(10,TimeUnit.SECONDS)){
+            return ResponseHelper.error("系统繁忙,请稍后再试");
+        }
+        try {
+            orderLogic.deliverGoods(orderId, logisticsNo, companyCode, storageId, workOrder, exchange);
+        }finally {
+            obtain.unlock();
+        }
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/goods/batch/deliver")
+    @Operation(summary ="批量发货")
+    public ResponseHelper deliverBatchGoods(
+            HttpServletRequest request,
+            @Parameter(required = true, description = "excel文件") @RequestParam(required = true) MultipartFile file
+    ) throws Exception {
+        orderLogic.deliverBatchGoods(request, file);
+        return ResponseHelper.success();
+    }
+
+
+    @GetMapping("/goods/deliver/excel")
+    @Operation(summary ="批量发货excel示例表格下载")
+    public void excelDownload(
+            HttpServletResponse response
+    ) throws RemoteServiceException, IOException {
+        CommonUtils.downloadFile("/static/批量发货模板.xlsx", response);
+    }
+
+
+    @PostMapping("/batch/remark")
+    @Operation(summary ="卖家批量设置备注")
+    public ResponseHelper batchRemark(
+            @Parameter(description = "备注信息", required = true) @RequestBody BatchRemarkBean batchRemarkBean
+    ) throws RemoteServiceException {
+        orderLogic.batchRemark(batchRemarkBean);
+        return ResponseHelper.success();
+    }
+
+
+    @GetMapping("/export")
+    @Operation(summary ="导出excel")
+    public void downloadFile2 (HttpServletRequest request, HttpServletResponse response,
+                               @Parameter(description = "用户id", required = false) @RequestParam(required = false) String userId,
+                               @Parameter(description = "订单号", required = false) @RequestParam(required = false) String orderId,
+                               @Parameter(description = "产品名称", required = false) @RequestParam(required = false) String productName,
+                               @Parameter(description = "用户名", required = false) @RequestParam(required = false) String userName,
+                               @Parameter(description = "手机号", required = false) @RequestParam(required = false) String phone,
+                               @Parameter(description = "兑换码", required = false) @RequestParam(required = false) String exchangeCode,
+                               @Parameter(description = "订单状态 NOPAY:待付款 DFH:待发货 YFH:已发货 OVER:已完成 CLOSE:已关闭", required = false)
+                                   @RequestParam(required = false) String orderStatus,
+                               @Parameter(description = "开始创建时间", required = false) @RequestParam(required = false) String startCreateTime,
+                               @Parameter(description = "结束创建时间", required = false) @RequestParam(required = false) String endCreateTime,
+                               @Parameter(description = "开始支付时间", required = false) @RequestParam(required = false) String startPayTime,
+                               @Parameter(description = "结束支付时间", required = false) @RequestParam(required = false) String endPayTime,
+                               @Parameter(description = "团购团长名称", required = false) @RequestParam(required = false) String promotionGroupUser,
+                               @Parameter(description = "团购活动id", required = false) @RequestParam(required = false) String promotionGroupId,
+                               @Parameter(description = "团购团长id", required = false) @RequestParam(required = false) String promotionGroupUserId,
+                               @Parameter(description = "网点id", required = false) @RequestParam(required = false) String websitId,
+                               @Parameter(description = "商品id", required = false) @RequestParam(required = false) String goodsId
+
+    ) throws Exception {
+
+        orderLogic.export2( request,  response,
+                userId,  orderId,  productName,  userName,
+                phone,  exchangeCode,  orderStatus,
+                startCreateTime,  endCreateTime,
+                startPayTime,  endPayTime,  promotionGroupUser,promotionGroupId,promotionGroupUserId,websitId,goodsId);
+    }
+
+}

+ 118 - 0
src/main/java/com/gree/mall/contest/controller/pc/order/OrderRefundController.java

@@ -0,0 +1,118 @@
+package com.gree.mall.contest.controller.pc.order;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.contest.bean.order.OrderRefundDetailBean;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.helper.ResponseHelper;
+import com.gree.mall.contest.logic.order.OrderRefundLogic;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Slf4j
+@RestController
+@Tag(name = "订单售后管理", description = "订单售后管理")
+@RequestMapping(value = "/order/refund", produces = "application/json; charset=utf-8")
+@RequiredArgsConstructor
+public class OrderRefundController {
+
+    private final OrderRefundLogic orderRefundLogic;
+
+    @GetMapping("/list")
+    @Operation(summary = "列表")
+    public ResponseHelper<Page<OrderRefundDetailBean>> list(HttpServletRequest request,
+                                                            @Parameter(description = "订单号",required = false) @RequestParam(required = false) String orderId,
+                                                            @Parameter(description = "售后订单号",required = false) @RequestParam(required = false) String orderRefundId,
+                                                            @Parameter(description = "用户名",required = false) @RequestParam(required = false) String userName,
+                                                            @Parameter(description = "手机号",required = false) @RequestParam(required = false) String phone,
+                                                            @Parameter(description = "订单状态 DSJCL=待商家处理  DSJFH=待商家发货 DMJCL=待买家处理 OVER=已完成",required = false) @RequestParam(required = false) String orderStatus,
+                                                            @Parameter(description = "开始申请时间",required = false) @RequestParam(required = false) String startCreateTime,
+                                                            @Parameter(description = "结束申请时间",required = false) @RequestParam(required = false) String endCreateTime,
+                                                            @Parameter(description = "开始处理时间",required = false) @RequestParam(required = false) String startExamineTime,
+                                                            @Parameter(description = "结束处理时间",required = false) @RequestParam(required = false) String endExamineTime,
+                                                            @Parameter(description = "页号",required = true) @RequestParam(required = true) Integer pageNum,
+                                                            @Parameter(description = "页大小",required = true) @RequestParam(required = true) Integer pageSize
+    ) throws RemoteServiceException {
+        IPage<OrderRefundDetailBean> list = orderRefundLogic
+                .list(request,orderId, orderRefundId, userName, phone, orderStatus, startCreateTime, endCreateTime, startExamineTime, endExamineTime, pageNum, pageSize);
+        return ResponseHelper.success(list);
+    }
+
+    @GetMapping("/refund/detail")
+    @Operation(summary = "售后订单-订单退款详情")
+    public ResponseHelper<OrderRefundDetailBean> refundDetail(
+            @Parameter(description = "售后订单id",required = true) @RequestParam String orderRefundId
+    ){
+        OrderRefundDetailBean orderRefundDetailBean = orderRefundLogic.orderRefundDetail(orderRefundId);
+        return ResponseHelper.success(orderRefundDetailBean);
+    }
+
+    @GetMapping("/expressInfo/select")
+    @Operation(summary = "售后订单-查看物流")
+    public ResponseHelper queryExpressInfo(
+            @Parameter(description = "物流单号", required = true) @RequestParam(required = true) String logisticsNo
+    ) throws RemoteServiceException {
+        orderRefundLogic.queryExpressInfo(logisticsNo);
+        return ResponseHelper.success();
+    }
+
+
+    @PostMapping("/examine")
+    @Operation(summary = "审核")
+    public ResponseHelper examine(
+            @Parameter(description = "售后单号",required = true) @RequestParam(required = true) String orderRefundId,
+            @Parameter(description = "OK=同意  FAIL=不同意",required = true) @RequestParam(required = true) String examineStatus,
+            @Parameter(description = "卖家留言",required = false) @RequestParam(required = false) String refundMessage,
+            @Parameter(description = "退款密码") @RequestParam(required = false) String refundPassword
+    ) throws Exception {
+        orderRefundLogic.examine(orderRefundId, examineStatus, refundMessage, refundPassword);
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/ack")
+    @Operation(summary = "商家确认收货")
+    public ResponseHelper examine(
+            @Parameter(description = "售后单号",required = true) @RequestParam(required = true) String orderRefundId
+    ) throws Exception {
+        orderRefundLogic.ack(orderRefundId);
+        return ResponseHelper.success();
+    }
+
+
+    @PostMapping("/remark")
+    @Operation(summary = "备注")
+    public ResponseHelper remark(
+            @Parameter(description = "售后单号",required = true) @RequestParam(required = true) String orderRefundId,
+            @Parameter(description = "备注",required = true) @RequestParam(required = true) String remark
+    ){
+        orderRefundLogic.remark(orderRefundId,remark);
+        return ResponseHelper.success();
+    }
+
+
+
+
+    @GetMapping("/downLoadExcel")
+    @Operation(summary = "导出售后报表")
+    public void downLoadExcel(HttpServletRequest request, HttpServletResponse response,
+                                         @Parameter(description = "订单号",required = false) @RequestParam(required = false) String orderId,
+                                         @Parameter(description = "售后订单号",required = false) @RequestParam(required = false) String orderRefundId,
+                                         @Parameter(description = "用户名",required = false) @RequestParam(required = false) String userName,
+                                         @Parameter(description = "手机号",required = false) @RequestParam(required = false) String phone,
+                                         @Parameter(description = "订单状态 DSJCL=待商家处理  DSJFH=待商家发货 DMJCL=待买家处理 OVER=已完成",required = false) @RequestParam(required = false) String orderStatus,
+                                         @Parameter(description = "开始申请时间",required = false) @RequestParam(required = false) String startCreateTime,
+                                         @Parameter(description = "结束申请时间",required = false) @RequestParam(required = false) String endCreateTime,
+                                         @Parameter(description = "开始处理时间",required = false) @RequestParam(required = false) String startExamineTime,
+                                         @Parameter(description = "结束处理时间",required = false) @RequestParam(required = false) String endExamineTime
+    ) throws Exception {
+        orderRefundLogic.downLoadOrderRefundExcel(request,response,orderId,orderRefundId,userName,phone,orderStatus,startCreateTime,endCreateTime,startExamineTime,endExamineTime);
+    }
+
+}

+ 128 - 0
src/main/java/com/gree/mall/contest/controller/pc/order/OrderShareController.java

@@ -0,0 +1,128 @@
+package com.gree.mall.contest.controller.pc.order;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.contest.annotation.ApiNotAuth;
+import com.gree.mall.contest.enums.OrderShareStatusEnum;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.helper.ResponseHelper;
+import com.gree.mall.contest.logic.order.OrderShareLogic;
+import com.gree.mall.contest.plus.entity.OrderShare;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Slf4j
+@RestController
+@Tag(name = "订单结算管理", description = "订单结算管理")
+@RequestMapping(value = "/order/share", produces = "application/json; charset=utf-8")
+@RequiredArgsConstructor
+public class OrderShareController {
+
+    private final OrderShareLogic orderShareLogic;
+
+
+    @GetMapping("/list")
+    @Operation(summary = "列表")
+    public ResponseHelper<Page<OrderShare>> list(
+            HttpServletRequest request,
+            @Parameter(description = "用户id", required = false) @RequestParam(required = false) String userId,
+            @Parameter(description = "网点id", required = false) @RequestParam(required = false) String websitId,
+            @Parameter(description = "分销结算id", required = false) @RequestParam(required = false) String orderShareId,
+            @Parameter(description = "订单号", required = false) @RequestParam(required = false) String orderId,
+            @Parameter(description = "用户名", required = false) @RequestParam(required = false) String workUserName,
+            @Parameter(description = "手机号", required = false) @RequestParam(required = false) String phone,
+            @Parameter(description = "结算状态: ING=结算中  OVER=已结算  CANCEL=已取消 EXCEPTION=异常结算", required = false) @RequestParam(required = false) String status,
+            @Parameter(description = "开始创建时间", required = false) @RequestParam(required = false) String startTime,
+            @Parameter(description = "结束创建时间", required = false) @RequestParam(required = false) String endTime,
+            @Parameter(description = "开始结算时间", required = false) @RequestParam(required = false) String startSettleTime,
+            @Parameter(description = "结束结算时间", required = false) @RequestParam(required = false) String endSettleTime,
+            @Parameter(description = "支付开始时间", required = false) @RequestParam(required = false) String startPayTime,
+            @Parameter(description = "结束开始时间", required = false) @RequestParam(required = false) String endPayTime,
+            @Parameter(description = "支付方式", required = false) @RequestParam(required = false) String payType,
+            @Parameter(description = "页号", required = true) @RequestParam(required = true) Integer pageNum,
+            @Parameter(description = "页大小", required = true) @RequestParam(required = true) Integer pageSize,
+            @Parameter(description = "职位", required = false) @RequestParam(required = false) String position
+    ) throws RemoteServiceException {
+        IPage<OrderShare> list = orderShareLogic.list(request, userId, websitId, orderShareId, orderId, workUserName,
+                phone, status, startTime, endTime, startSettleTime, endSettleTime, position, startPayTime, endPayTime,
+                payType, pageNum, pageSize);
+        return ResponseHelper.success(list);
+    }
+
+    @GetMapping("/confirm")
+    @Operation(summary = "管理员手动确认分佣")
+    public ResponseHelper confirm(@Parameter(description = "订单号", required = false) @RequestParam(required = false) String orderId) throws RemoteServiceException {
+        orderShareLogic.confirm(orderId);
+        return ResponseHelper.success();
+    }
+
+
+    @PostMapping("/remark")
+    @Operation(summary = "备注")
+    public ResponseHelper remark(
+            @Parameter(description = "结算id", required = true) @RequestParam(required = true) String orderShareId,
+            @Parameter(description = "备注内容", required = true) @RequestParam(required = true) String remark
+    ) throws RemoteServiceException {
+        orderShareLogic.remark(orderShareId, remark);
+        return ResponseHelper.success();
+    }
+
+
+    @GetMapping("/export")
+    @Operation(summary = "结算导出")
+    public void export(HttpServletRequest request, HttpServletResponse response,
+                       @Parameter(description = "用户id", required = false) @RequestParam(required = false) String userId,
+                       @Parameter(description = "分销结算id", required = false) @RequestParam(required = false) String orderShareId,
+                       @Parameter(description = "订单号", required = false) @RequestParam(required = false) String orderId,
+                       @Parameter(description = "网点id", required = false) @RequestParam(required = false) String websitId,
+                       @Parameter(description = "用户名", required = false) @RequestParam(required = false) String workUserName,
+                       @Parameter(description = "手机号", required = false) @RequestParam(required = false) String phone,
+                       @Parameter(description = "结算状态: ING=结算中  OVER=已结算  CANCEL=已取消 EXCEPTION=异常结算", required = false) @RequestParam(required = false) String status,
+                       @Parameter(description = "开始创建时间", required = false) @RequestParam(required = false) String startTime,
+                       @Parameter(description = "结束创建时间", required = false) @RequestParam(required = false) String endTime,
+                       @Parameter(description = "开始结算时间", required = false) @RequestParam(required = false) String startSettleTime,
+                       @Parameter(description = "结束结算时间", required = false) @RequestParam(required = false) String endSettleTime,
+                       @Parameter(description = "支付开始时间", required = false) @RequestParam(required = false) String startPayTime,
+                       @Parameter(description = "结束开始时间", required = false) @RequestParam(required = false) String endPayTime,
+                       @Parameter(description = "职位", required = false) @RequestParam(required = false) String position,
+                       @Parameter(description = "支付方式", required = false) @RequestParam(required = false) String payType
+    ) throws Exception {
+        orderShareLogic.export2(request, response, userId, websitId, orderShareId, orderId, workUserName, phone, status,
+                startTime, endTime, startSettleTime, endSettleTime, position, payType, startPayTime, endPayTime);
+    }
+
+
+    @ApiNotAuth
+    @GetMapping("/worker/ordernum")
+    @Operation(summary = "师傅本月的有效订单数量")
+    public ResponseHelper<Long> workerOrderNum(
+            @Parameter(description = "师傅手机号", required = true) @RequestParam(required = true) String mobile
+    ) throws RemoteServiceException {
+        Long shareNum = orderShareLogic.getShareNum(mobile);
+        return ResponseHelper.success(shareNum);
+    }
+
+    @PostMapping("/status")
+    @Operation(summary = "变更状态-线下结算-取消结算")
+    public ResponseHelper status(
+            @Parameter(description = "结算id", required = true) @RequestParam(required = true) String orderShareId,
+            @Parameter(description = "OFFLINE=线下结算 CANCEL=取消结算", required = true) @RequestParam(required = true) OrderShareStatusEnum orderShareStatus
+    ) {
+        orderShareLogic.updateOrderStatus(orderShareId, orderShareStatus.toString());
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/query/max/share/rate")
+    @Operation(summary = "查询最大分账比例")
+    public ResponseHelper<String> queryMaxShareRate(@Parameter(description = "商户id") @RequestParam(required = false) String id) throws Exception {
+        String result = orderShareLogic.queryMaxShareRate(id);
+        return ResponseHelper.success(result);
+    }
+}

+ 5 - 0
src/main/java/com/gree/mall/contest/enums/FreightTypeEnum.java

@@ -0,0 +1,5 @@
+package com.gree.mall.contest.enums;
+
+public enum FreightTypeEnum {
+    UNIFIED,TEMPLATE
+}

+ 14 - 0
src/main/java/com/gree/mall/contest/enums/GoodsTypeEnum.java

@@ -0,0 +1,14 @@
+package com.gree.mall.contest.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum GoodsTypeEnum {
+    COMMON("普通商品"),
+    PACKAGE("套餐商品");
+
+    GoodsTypeEnum(String name) {
+        this.name = name;
+    }
+    private String name;
+}

+ 5 - 0
src/main/java/com/gree/mall/contest/enums/OrderExamineEnum.java

@@ -0,0 +1,5 @@
+package com.gree.mall.contest.enums;
+
+public enum OrderExamineEnum {
+    WAIT,OK,FAIL
+}

+ 16 - 0
src/main/java/com/gree/mall/contest/enums/OrderRefundTypeEnum.java

@@ -0,0 +1,16 @@
+package com.gree.mall.contest.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum OrderRefundTypeEnum {
+
+    REFUND_AMOUNT("仅退款"),
+    REFUND_GOODS("退货退款");
+
+    OrderRefundTypeEnum(String name)  {
+        this.name = name;
+    }
+    private String name;
+
+}

+ 16 - 0
src/main/java/com/gree/mall/contest/enums/OrderShareStatusEnum.java

@@ -0,0 +1,16 @@
+package com.gree.mall.contest.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum OrderShareStatusEnum {
+    ING("结算中"),
+    OVER("已结算"),
+    EXCEPTION("异常结算"),
+    CANCEL("已取消");
+
+    OrderShareStatusEnum(String name) {
+        this.name = name;
+    }
+    private String name;
+}

+ 22 - 0
src/main/java/com/gree/mall/contest/enums/OrderStatusEnum.java

@@ -0,0 +1,22 @@
+package com.gree.mall.contest.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum OrderStatusEnum {
+    NOPAY("待付款"),
+    DFH("待发货"),
+    YFH("已发货"),
+    OVER("已完成"),
+    TIMEOUT("超时取消"),
+    CLOSE("已取消"),
+    REFUND("售后"),
+    DSJCL("待商家处理"),
+    DMJCL("待买家处理"),
+    DSJSH("待商家收货");
+
+    OrderStatusEnum(String name) {
+        this.name = name;
+    }
+    private String name;
+}

+ 14 - 0
src/main/java/com/gree/mall/contest/enums/PayTypeEnum.java

@@ -0,0 +1,14 @@
+package com.gree.mall.contest.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum PayTypeEnum {
+    WEIXIN("微信"),
+    UNIONPAY("云闪付"),;
+
+    PayTypeEnum(String name) {
+        this.name = name;
+    }
+    private final String name;
+}

+ 15 - 0
src/main/java/com/gree/mall/contest/enums/RefundFlagEnum.java

@@ -0,0 +1,15 @@
+package com.gree.mall.contest.enums;
+
+public enum RefundFlagEnum {
+    ING("退款中"), PARTLY("部分退款"), ALL("全部退款"), COMMONLY("无");
+
+    private String name;
+
+    RefundFlagEnum(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+}

+ 51 - 0
src/main/java/com/gree/mall/contest/enums/UMSDiscountCodeEnum.java

@@ -0,0 +1,51 @@
+package com.gree.mall.contest.enums;
+
+import cn.hutool.core.util.EnumUtil;
+import lombok.Getter;
+
+import java.util.Map;
+
+@Getter
+public enum UMSDiscountCodeEnum {
+    GDYJKT(1, "一级能效空调", "GDYJKT"),
+    GDEJKT(2, "二级能效空调", "GDEJKT"),
+    GDYJDS(3, "一级能效电视", "GDYJDS"),
+    GENERAL(4, "二级能效电视", "GDEJDS"),
+    GDEJDS(5, "一级能效冰箱", "GDYJBX"),
+    GDEJBX(6, "二级能效冰箱", "GDEJBX"),
+    GDYJXYJ(7, "一级能效洗衣机", "GDYJXYJ"),
+    GDEJXYJ(8, "二级能效洗衣机", "GDEJXYJ"),
+    GDYJXYYJ(9, "一级能效吸油烟机", "GDYJXYYJ"),
+    GDEJXYYJ(10, "二级能效吸油烟机", "GDEJXYYJ"),
+    GDYJDZ(11, "一级能效家用灶具", "GDYJDZ"),
+    GDEJDZ(12, "二级能效家用灶具", "GDEJDZ"),
+    GDYJRSQ(13, "一级能效热水器", "GDYJRSQ"),
+    GDEJRSQ(14, "二级能效热水器", "GDEJRSQ"),
+    GDYJDN(15, "一级能效电脑", "GDYJDN"),
+    GDEJDN(16, "二级能效电脑", "GDEJDN"),
+    GDYJCSJ(17, "一级能效除湿机", "GDYJCSJ"),
+    GDEJCSJ(18, "二级能效除湿机", "GDEJCSJ"),
+    GDYJJSQ(19, "一级能效净水器", "GDYJJSQ"),
+    GDEJJSQ(20, "二级能效净水器", "GDEJJSQ"),
+    ;
+
+    UMSDiscountCodeEnum(Integer index, String name, String code) {
+        this.index = index;
+        this.name = name;
+        this.code = code;
+    }
+
+    private Integer index;
+    private String name;
+    private String code;
+
+    public static boolean existDiscountCodeByCode(String code) {
+        return EnumUtil.getFieldValues(UMSDiscountCodeEnum.class, "code").contains(code);
+    }
+
+    public static String findNameByCode(String code) {
+        final Map<String, Object> fieldMap = EnumUtil.getNameFieldMap(UMSDiscountCodeEnum.class, "name");
+
+        return fieldMap.containsKey(code) ? fieldMap.get(code).toString() : "";
+    }
+}

+ 21 - 0
src/main/java/com/gree/mall/contest/enums/UserTypeEnum.java

@@ -0,0 +1,21 @@
+package com.gree.mall.contest.enums;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.gree.mall.contest.enums.base.BaseEnum;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@Getter
+@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+public enum UserTypeEnum implements BaseEnum {
+    GENERAL("GENERAL", "普通用户"),
+    SERVICE("SERVICE", "业务员");
+
+    @EnumValue
+    @JsonValue
+    private final String key;
+    private final String remark;
+
+}

+ 31 - 0
src/main/java/com/gree/mall/contest/enums/WXShareFailReasonEnum.java

@@ -0,0 +1,31 @@
+package com.gree.mall.contest.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum WXShareFailReasonEnum {
+
+    ACCOUNT_ABNORMAL("分账接收账户异常"),
+
+    NO_RELATION("分账关系已解除"),
+
+    RECEIVER_HIGH_RISK("高风险接收方"),
+
+    RECEIVER_REAL_NAME_NOT_VERIFIED("接收方未实名"),
+
+    NO_AUTH("分账权限已解除"),
+
+    RECEIVER_RECEIPT_LIMIT("接收方已达收款限额"),
+
+    PAYER_ACCOUNT_ABNORMAL("分出方账户异常"),
+
+    INVALID_REQUEST("描述参数设置失败"),
+    ;
+
+    WXShareFailReasonEnum(String name) {
+        this.name = name;
+    }
+
+    private final String name;
+
+}

+ 19 - 0
src/main/java/com/gree/mall/contest/enums/WXShareResultEnum.java

@@ -0,0 +1,19 @@
+package com.gree.mall.contest.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum WXShareResultEnum {
+    PENDING("待分账"),
+
+    SUCCESS("分账成功"),
+
+    CLOSED("分账失败已关闭"),;
+
+    WXShareResultEnum(String name) {
+        this.name = name;
+    }
+
+    private final String name;
+
+}

+ 17 - 0
src/main/java/com/gree/mall/contest/enums/WXShareStatusEnum.java

@@ -0,0 +1,17 @@
+package com.gree.mall.contest.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum WXShareStatusEnum {
+    PROCESSING("处理中"),
+
+    FINISHED("处理完成"),;
+
+    WXShareStatusEnum(String name) {
+        this.name = name;
+    }
+
+    private final String name;
+
+}

+ 13 - 0
src/main/java/com/gree/mall/contest/enums/coupon/CouponActiveTypeEnum.java

@@ -0,0 +1,13 @@
+package com.gree.mall.contest.enums.coupon;
+
+public enum CouponActiveTypeEnum {
+    COMMON(1),TODAY(2),NEXTDAY(3);
+    private final Integer activeType;
+    CouponActiveTypeEnum(Integer activeType){
+        this.activeType = activeType;
+    }
+
+    public Integer getActiveType() {
+        return activeType;
+    }
+}

+ 14 - 0
src/main/java/com/gree/mall/contest/enums/coupon/CouponCrowdEnum.java

@@ -0,0 +1,14 @@
+package com.gree.mall.contest.enums.coupon;
+
+public enum CouponCrowdEnum {
+    TAG(1),SPECIFY(2),ALL_SERVICE(3),ALL_GENRERAL(4);
+    private Integer flag;
+    CouponCrowdEnum(Integer flag){
+        this.flag = flag;
+    }
+
+    public Integer getFlag(){
+        return flag;
+    }
+
+}

+ 16 - 0
src/main/java/com/gree/mall/contest/enums/coupon/CouponFlagEnum.java

@@ -0,0 +1,16 @@
+package com.gree.mall.contest.enums.coupon;
+
+import lombok.Getter;
+
+@Getter
+public enum CouponFlagEnum {
+    WAIT("待发布"),
+    START("进行中"),
+    END("结束"),
+    CANCEL("取消");
+
+    CouponFlagEnum(String name)  {
+        this.name = name;
+    }
+    private String name;
+}

+ 16 - 0
src/main/java/com/gree/mall/contest/enums/coupon/CouponTypeEnum.java

@@ -0,0 +1,16 @@
+package com.gree.mall.contest.enums.coupon;
+
+public enum CouponTypeEnum {
+
+    SATISFY("SATISFY"),DISCOUNT("DISCOUNT"),RANDOM("RANDOM"),GOODS("GOODS");
+
+    private String name;
+
+    CouponTypeEnum(String name) {
+        this.name = name;
+    }
+
+    public String getName(){
+        return name;
+    }
+}

+ 77 - 0
src/main/java/com/gree/mall/contest/logic/ExpressLogic.java

@@ -0,0 +1,77 @@
+package com.gree.mall.contest.logic;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.gree.mall.contest.plus.entity.ExpressCompany;
+import com.gree.mall.contest.plus.entity.ExpressInfo;
+import com.gree.mall.contest.plus.service.ExpressCompanyService;
+import com.gree.mall.contest.plus.service.ExpressInfoService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * 快递物流
+ * created by lijh
+ * 2019-07-23
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class ExpressLogic {
+
+//    private final static String expressQueryUrl = "https://poll.kuaidi100.com/poll/query.do";
+//    private final static String expressPollUrl = "https://poll.kuaidi100.com/poll";
+    //    private final static String callBackUrl = "http://121.43.111.127:9003/common/express/callback";
+//    private final static String customer = "4A7813B781DCAB6D1975A79DF86B96ED";
+//    private final static String key = "yzXRZXXI1802";
+//    @Value("${express.callback}")
+//    private String callBackUrl;
+
+    private final ExpressInfoService expressInfoService;
+    private final ExpressCompanyService expressCompanyService;
+
+    /**
+     * 查询所有物流公司
+     */
+    public List<ExpressCompany> expressCompanyList() {
+        return expressCompanyService.list();
+    }
+
+    /**
+     * 根据code查询公司
+     */
+    public String expressCompanyName(String code) {
+        return expressCompanyService.lambdaQuery().eq(ExpressCompany::getCode, code).one().getName();
+    }
+
+    /**
+     * 根据name查询公司
+     */
+    public ExpressCompany expressCompany(String name) {
+        return expressCompanyService.lambdaQuery().eq(ExpressCompany::getName, name).one();
+    }
+
+    public List<ExpressInfo> queryExpress(String logisticsNo, String company) {
+
+        if (StringUtils.isEmpty(logisticsNo)) {
+            return new ArrayList<>();
+        }
+
+        //先查询本地数据库是否有已签收数据
+        List<ExpressInfo> list = expressInfoService.lambdaQuery()
+                .eq(ExpressInfo::getLogisticsNo, logisticsNo)
+                .eq(StringUtils.isNotEmpty(company),ExpressInfo::getCom, company)
+                .list();
+        if (CollectionUtil.isNotEmpty(list)) {
+            return list;
+        } else {
+            return null;
+        }
+    }
+
+}

+ 99 - 0
src/main/java/com/gree/mall/contest/logic/StorageLogic.java

@@ -0,0 +1,99 @@
+package com.gree.mall.contest.logic;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.aliyuncs.utils.StringUtils;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.contest.bean.admin.AdminUserCom;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.logic.common.CommonLogic;
+import com.gree.mall.contest.plus.entity.Storage;
+import com.gree.mall.contest.plus.service.StorageService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Date;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class StorageLogic {
+
+
+    private final CommonLogic commonLogic;
+    private final StorageService storageService;
+
+    /**
+     * 仓储列表
+     *
+     * @param pageNum
+     * @param pageSize
+     * @return
+     */
+    public IPage<Storage> page(Integer pageNum, Integer pageSize, HttpServletRequest request) {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+
+        return storageService.lambdaQuery()
+                .in(CollectionUtil.isNotEmpty(adminUser.getCompanyWechatIds()),Storage::getCompanyWechatId,adminUser.getCompanyWechatIds())
+                .page(new Page<>(pageNum, pageSize));
+    }
+
+    /**
+     * 仓储详情
+     *
+     * @param id
+     * @return
+     */
+    public Storage detail(String id) {
+        return storageService.getById(id);
+    }
+
+    public Storage detailByName(String companyWechatId,String name) {
+        return storageService
+                .lambdaQuery()
+                .eq(Storage::getCompanyWechatId, companyWechatId)
+                .eq(Storage::getStorageName,name)
+                .one();
+    }
+
+    /**
+     * 新增仓储
+     *
+     * @param storage
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void add(HttpServletRequest request,Storage storage) {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        if(StringUtils.isEmpty(adminUser.getLoginCompanyWechatId())){
+            throw new RemoteServiceException("无效企业微信id");
+        }
+        storage.setCreateTime(new Date());
+        storage.setCompanyWechatId(adminUser.getLoginCompanyWechatId());
+        storage.setCompanyName(adminUser.getLoginCompanyName());
+        storageService.save(storage);
+    }
+
+    /**
+     * 修改仓储
+     *
+     * @param storage
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void update(Storage storage) {
+        storage.setCreateTime(null);
+        storageService.updateById(storage);
+    }
+
+    /**
+     * 删除仓储
+     *
+     * @param storageId
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void delete(String storageId) {
+        storageService.removeById(storageId);
+    }
+}

+ 524 - 0
src/main/java/com/gree/mall/contest/logic/activity/PromotionGroupLogic.java

@@ -0,0 +1,524 @@
+package com.gree.mall.contest.logic.activity;
+
+import com.aliyuncs.utils.StringUtils;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.contest.bean.activity.PromotionGoods;
+import com.gree.mall.contest.bean.activity.PromotionGroupBean;
+import com.gree.mall.contest.bean.activity.PromotionGroupDetail;
+import com.gree.mall.contest.bean.activity.PromotionGroupList;
+import com.gree.mall.contest.bean.admin.AdminUserCom;
+import com.gree.mall.contest.commonmapper.PromotionMapper;
+import com.gree.mall.contest.enums.OrderShareStatusEnum;
+import com.gree.mall.contest.enums.OrderStatusEnum;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.logic.common.CommonLogic;
+import com.gree.mall.contest.plus.entity.*;
+import com.gree.mall.contest.plus.service.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class PromotionGroupLogic {
+
+    private final CommonLogic commonLogic;
+    private final PromotionGroupService promotionGroupService;
+    private final PromotionGroupSpecService promotionGroupSpecService;
+    private final PromotionGroupSpecUserService promotionGroupSpecUserService;
+    private final PromotionGroupUserService promotionGroupUserService;
+    private final OrderInfoService orderInfoService;
+    private final OrderDetailService orderDetailService;
+    private final OrderShareService orderShareService;
+    private final PromotionMapper promotionMapper;
+    private final UserService userService;
+    private final GoodsVisitService goodsVisitService;
+    private final GoodsService goodsService;
+    private final UserVisitService userVisitService;
+
+    /**
+     * 团购分类统计
+     */
+    public Map<String, Long> count(HttpServletRequest request) {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        //已结束
+        Long count = promotionGroupService.lambdaQuery()
+                .in(CollectionUtils.isNotEmpty(adminUser.getCompanyWechatIds()), PromotionGroup::getCompanyWechatId, adminUser.getCompanyWechatIds())
+                .eq(PromotionGroup::getStatus, false).count();
+        //进行中
+        Long count2 = promotionGroupService.lambdaQuery()
+                .in(CollectionUtils.isNotEmpty(adminUser.getCompanyWechatIds()), PromotionGroup::getCompanyWechatId, adminUser.getCompanyWechatIds())
+                .eq(PromotionGroup::getStatus, true).count();
+        Map<String, Long> map = new HashMap<>();
+        map.put("all", count + count2);
+        map.put("jxz", count2);
+        map.put("yjs", count);
+        return map;
+    }
+
+    /**
+     * 团购活动列表
+     *
+     * @param status
+     * @param pageNo
+     * @param pageSize
+     * @return
+     */
+    public IPage<PromotionGroupList> list(Boolean status, Integer pageNo, Integer pageSize, HttpServletRequest request) {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+
+        IPage page = promotionGroupService.lambdaQuery()
+                .eq(status != null, PromotionGroup::getStatus, status)
+                .in(CollectionUtils.isNotEmpty(adminUser.getCompanyWechatIds()), PromotionGroup::getCompanyWechatId, adminUser.getCompanyWechatIds())
+                .orderByDesc(PromotionGroup::getCreateTime)
+                .page(new Page<>(pageNo, pageSize));
+        //组装数据
+        List<PromotionGroupList> list = new ArrayList<>();
+        for (Object o : page.getRecords()) {
+            PromotionGroup promotionGroup = (PromotionGroup) o;
+            PromotionGroupList promotionGroupList = new PromotionGroupList();
+            BeanUtils.copyProperties(promotionGroup, promotionGroupList);
+            //参与商品数量
+            Long count = promotionGroupSpecService.lambdaQuery().eq(PromotionGroupSpec::getPromotionGroupId, promotionGroup.getPromotionGroupId()).count();
+            promotionGroupList.setGoodsNum(Math.toIntExact(count));
+            //订单数量
+            Long orderNum = orderInfoService.lambdaQuery()
+                    .notIn(OrderInfo::getOrderStatus, Arrays.asList(OrderStatusEnum.CLOSE.toString(), OrderStatusEnum.TIMEOUT.toString()))
+                    .eq(OrderInfo::getPromotionGroupId, promotionGroup.getPromotionGroupId()).count();
+            promotionGroupList.setOrderNum(Math.toIntExact(orderNum));
+            //订单台数
+            Integer orderDetilNum = promotionMapper.queryTotalGoodsNum(promotionGroup.getPromotionGroupId(), null);
+            promotionGroupList.setOrderDetailNum(orderDetilNum);
+            //订单总金额
+            BigDecimal totalAmount = promotionMapper.queryOrderTotalAmount(promotionGroup.getPromotionGroupId());
+            promotionGroupList.setOrderTotalAmount(totalAmount);
+            //团长分佣总额
+            BigDecimal totalOrderShareAmount = promotionMapper.queryTotalShareAmount(null, promotionGroup.getPromotionGroupId(), null);
+            promotionGroupList.setShareTotalAmount(totalOrderShareAmount);
+            list.add(promotionGroupList);
+        }
+        page.setRecords(list);
+        return page;
+    }
+
+
+    /**
+     * 团购详情
+     */
+    public PromotionGroupBean detail(String promotionGroupId) {
+        PromotionGroup promotionGroup = promotionGroupService.getById(promotionGroupId);
+        PromotionGroupBean bean = new PromotionGroupBean();
+        BeanUtils.copyProperties(promotionGroup, bean);
+        //商品
+        List<PromotionGoods> goods = new ArrayList<>();
+        //商品规格
+        List<PromotionGroupSpec> specList = promotionGroupSpecService.lambdaQuery()
+                .eq(PromotionGroupSpec::getPromotionGroupId, promotionGroupId).list();
+
+        Map<String, List<PromotionGroupSpec>> map = new LinkedHashMap<>();
+        for (PromotionGroupSpec promotionGroupSpec : specList) {
+            String goodsId = promotionGroupSpec.getGoodsId();
+            List<PromotionGroupSpec> promotionGroupSpecs = map.get(goodsId);
+            if (promotionGroupSpecs == null) {
+                promotionGroupSpecs = new ArrayList<>();
+            }
+            promotionGroupSpecs.add(promotionGroupSpec);
+            map.put(goodsId, promotionGroupSpecs);
+        }
+        for (String goodsId : map.keySet()) {
+            PromotionGroupSpec promotionGroupSpec = map.get(goodsId).get(0);
+            PromotionGoods promotionGoods = new PromotionGoods();
+            promotionGoods.setGoodsId(promotionGroupSpec.getGoodsId());
+            promotionGoods.setGoodsImgSrc(promotionGroupSpec.getGoodsImgSrc());
+            promotionGoods.setGoodsName(promotionGroupSpec.getGoodsName());
+            promotionGoods.setSpecs(map.get(goodsId));
+            promotionGoods.setSortNum(promotionGroupSpec.getSortNum());
+            goods.add(promotionGoods);
+        }
+        bean.setGoods(goods);
+        //查询活动团长列表
+        List<PromotionGroupUser> list = promotionGroupUserService.lambdaQuery().eq(PromotionGroupUser::getPromotionGroupId, promotionGroupId).list();
+        bean.setPromotionGroupUsers(list);
+        return bean;
+    }
+
+
+    /**
+     * 新增团购活动
+     */
+    @Transactional
+    public String add(PromotionGroupBean promotionGroupBean, HttpServletRequest request) {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        //活动团长
+        List<PromotionGroupUser> promotionGroupUsers = promotionGroupBean.getPromotionGroupUsers();
+        List<String> userIds = promotionGroupUsers.stream().map(PromotionGroupUser::getUserId).collect(Collectors.toList());
+        //1.保存团购活动
+        promotionGroupBean.setCompanyWechatId(adminUser.getLoginCompanyWechatId());
+        promotionGroupBean.setCompanyName(adminUser.getLoginCompanyName());
+        promotionGroupBean.setCreateTime(new Date());
+        promotionGroupService.save(promotionGroupBean);
+        String promotionGroupId = promotionGroupBean.getPromotionGroupId();
+
+        //2.团购商品集合
+        List<PromotionGoods> goods = promotionGroupBean.getGoods();
+        List<String> goodsIds = goods.stream().map(PromotionGoods::getGoodsId).collect(Collectors.toList());
+        Long count = promotionGroupSpecService.lambdaQuery().in(PromotionGroupSpec::getGoodsId, goodsIds).count();
+        if (count > 0) {
+            throw new RemoteServiceException("存在商品已被添加到其他活动");
+        }
+        for (PromotionGoods pGoods : goods) {
+            for (PromotionGroupSpec promotionGroupSpec : pGoods.getSpecs()) {
+                promotionGroupSpec.setStartTime(promotionGroupBean.getStartTime());
+                promotionGroupSpec.setEndTime(promotionGroupBean.getEndTime());
+                promotionGroupSpec.setCompanyWechatId(promotionGroupBean.getCompanyWechatId());
+                promotionGroupSpec.setCompanyName(promotionGroupBean.getCompanyName());
+                promotionGroupSpec.setSortNum(pGoods.getSortNum());
+                promotionGroupSpec.setCreateTime(new Date());
+            }
+        }
+
+        //3 清空活动团长
+        promotionGroupUserService.lambdaUpdate().eq(PromotionGroupUser::getPromotionGroupId, promotionGroupId).remove();
+
+        //新增团购活动规格和初始化团长
+        this.addSpecUser(adminUser, promotionGroupBean, goods, userIds);
+
+        return promotionGroupBean.getPromotionGroupId();
+    }
+
+    /**
+     * 修改团购活动
+     */
+    @Transactional
+    public void update(HttpServletRequest request, PromotionGroupBean promotionGroupBean) {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+
+        String promotionGroupId = promotionGroupBean.getPromotionGroupId();
+        List<String> userIds = promotionGroupBean.getPromotionGroupUsers().stream().map(PromotionGroupUser::getUserId).collect(Collectors.toList());
+        //1.修改团购活动
+        promotionGroupService.updateById(promotionGroupBean);
+        //此次提交的所有活动规格id
+        List<String> promotionGroupSpecIds = new ArrayList<>();
+        //此次提交的所有活动商品id
+        List<String> goodsId = new ArrayList<>();
+        //d需要新增的商品
+        List<PromotionGoods> promotionGoodsAdd = new ArrayList<>();
+        //修改旧的商品规格
+        for (PromotionGoods promotionGoods : promotionGroupBean.getGoods()) {
+            for (PromotionGroupSpec promotionGroupSpec : promotionGoods.getSpecs()) {
+
+                promotionGroupSpec.setStartTime(promotionGroupBean.getStartTime());
+                promotionGroupSpec.setEndTime(promotionGroupBean.getEndTime());
+                promotionGroupSpec.setSortNum(promotionGoods.getSortNum());
+                if (StringUtils.isNotEmpty(promotionGroupSpec.getPromotionGroupSpecId())) {
+                    promotionGroupSpecService.updateById(promotionGroupSpec);
+
+                    promotionGroupSpecIds.add(promotionGroupSpec.getPromotionGroupSpecId());
+
+                    goodsId.add(promotionGroupSpec.getGoodsId());
+                } else {
+                    promotionGoodsAdd.add(promotionGoods);
+                }
+            }
+        }
+        promotionGoodsAdd = promotionGoodsAdd.stream().filter(distinctByKey(PromotionGoods::getGoodsId)).collect(Collectors.toList());
+
+        List<String> goodsIds = promotionGoodsAdd.stream().map(PromotionGoods::getGoodsId).collect(Collectors.toList());
+        if (goodsIds.size() > 0) {
+            Long count = promotionGroupSpecService.lambdaQuery().in(PromotionGroupSpec::getGoodsId, goodsIds)
+                    .ne(PromotionGroupSpec::getPromotionGroupId, promotionGroupId).count();
+            if (count > 0) {
+                throw new RemoteServiceException("存在商品已被添加到其他活动");
+            }
+        }
+
+        //记录需要还原的商品(去除活动标志)
+        List<PromotionGroupSpec> goodsIdListFalse = promotionGroupSpecService.lambdaQuery()
+                .select(PromotionGroupSpec::getGoodsId)
+                .notIn(CollectionUtils.isNotEmpty(promotionGroupSpecIds), PromotionGroupSpec::getPromotionGroupSpecId, promotionGroupSpecIds)
+                .eq(PromotionGroupSpec::getPromotionGroupId, promotionGroupId)
+                .list();
+
+        //删除此次提交的活动规格之外的规格AAAA
+        promotionGroupSpecService.lambdaUpdate()
+                .notIn(CollectionUtils.isNotEmpty(promotionGroupSpecIds), PromotionGroupSpec::getPromotionGroupSpecId, promotionGroupSpecIds)
+                .eq(PromotionGroupSpec::getPromotionGroupId, promotionGroupId)
+                .remove();
+
+        //删除此次活动规格的团长
+        promotionGroupSpecUserService.lambdaUpdate()
+                .eq(PromotionGroupSpecUser::getPromotionGroupId, promotionGroupId)
+                .remove();
+
+        List<String> goodsIdsFalse = goodsIdListFalse.stream().map(PromotionGroupSpec::getGoodsId).collect(Collectors.toList());
+        if (goodsIdsFalse.size() > 0) {
+            goodsService.lambdaUpdate()
+                    .set(Goods::getPromotionGroup, false)
+                    .in(Goods::getGoodsId, goodsIdsFalse).update();
+        }
+
+        //清空团购活动团长
+        promotionGroupUserService.lambdaUpdate().eq(PromotionGroupUser::getPromotionGroupId, promotionGroupId).remove();
+
+        //5.新增新的商品规格和初始化团长
+        this.addSpecUser(adminUser, promotionGroupBean, promotionGoodsAdd, userIds);
+    }
+
+    /**
+     * 关闭活动
+     */
+    public void close() {
+        //查询过期了的活动
+        List<PromotionGroup> list = promotionGroupService.lambdaQuery()
+                .le(PromotionGroup::getEndTime, new Date())
+                //.ge(PromotionGroup::getStartTime, new Date())
+                .eq(PromotionGroup::getStatus, true)
+                .list();
+
+        List<String> promotionGroupIds = list.stream().map(PromotionGroup::getPromotionGroupId).collect(Collectors.toList());
+
+        for (String promotionGroupId : promotionGroupIds) {
+            this.updateStatus(promotionGroupId, false);
+        }
+
+    }
+
+    /**
+     * 修改活动状态
+     */
+    @Transactional
+    public void updateStatus(String promotionGroupId, Boolean status) {
+        promotionGroupService.lambdaUpdate()
+                .set(PromotionGroup::getStatus, status)
+                .eq(PromotionGroup::getPromotionGroupId, promotionGroupId)
+                .update();
+        //如果是关闭活动,则将里面的商品都剔除团购商品并下架
+        if (!status) {
+            List<PromotionGroupSpec> list = promotionGroupSpecService.lambdaQuery().eq(PromotionGroupSpec::getPromotionGroupId, promotionGroupId).list();
+            List<String> goodsIds = list.stream().map(PromotionGroupSpec::getGoodsId).collect(Collectors.toList());
+//            goodsService.lambdaUpdate()
+//                    .set(Goods::getPromotionGroup,false)
+//                    .set(Goods::getStatus,false)
+//                    .in(Goods::getGoodsId,goodsIds).update();
+            goodsService.lambdaUpdate().in(Goods::getGoodsId, goodsIds).remove();
+
+        }
+    }
+
+
+    private static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
+        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
+        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
+    }
+
+    /**
+     * 新增新的商品规格和初始化团长
+     */
+    private void addSpecUser(AdminUserCom adminUser, PromotionGroup promotionGroup, List<PromotionGoods> goods, List<String> userIds) {
+        String promotionGroupId = promotionGroup.getPromotionGroupId();
+        //团购商品规格集合
+        List<PromotionGroupSpec> promotionGroupSpecs = new ArrayList<>();
+        List<String> promotionGroupSpecIds = new ArrayList<>();
+        List<String> goodsIds = new ArrayList<>();
+        for (PromotionGoods good : goods) {
+            for (PromotionGroupSpec promotionGroupSpec : good.getSpecs()) {
+                promotionGroupSpec.setPromotionGroupSpecId(IdWorker.getIdStr());
+                promotionGroupSpec.setGoodsId(good.getGoodsId());
+                promotionGroupSpec.setGoodsName(good.getGoodsName());
+                promotionGroupSpec.setGoodsImgSrc(good.getGoodsImgSrc());
+                promotionGroupSpec.setPromotionGroupId(promotionGroupId);
+                promotionGroupSpec.setCompanyWechatId(adminUser.getLoginCompanyWechatId());
+                promotionGroupSpec.setCompanyName(adminUser.getLoginCompanyName());
+                promotionGroupSpecs.add(promotionGroupSpec);
+
+                promotionGroupSpecIds.add(promotionGroupSpec.getPromotionGroupSpecId());
+                goodsIds.add(good.getGoodsId());
+            }
+        }
+        //2.保存购商品规格
+        promotionGroupSpecService.saveBatch(promotionGroupSpecs);
+        //3.初始化团长
+        if (CollectionUtils.isNotEmpty(userIds)) {
+
+            List<User> users = userService.lambdaQuery().in(User::getUserId, userIds).eq(User::getPromotionGroupLeader, true).list();
+            List<PromotionGroupSpec> list1 = promotionGroupSpecService.lambdaQuery().eq(PromotionGroupSpec::getPromotionGroupId, promotionGroupId).list();
+            List<PromotionGroupSpecUser> specUsers = new ArrayList<>();
+            if (list1.size() == 0 || users.size() == 0) {
+                return;
+            }
+            //组装活动团长
+            List<PromotionGroupUser> promotionGroupUsers = new ArrayList<>();
+            for (User user : users) {
+                PromotionGroupUser promotionGroupUser = new PromotionGroupUser();
+                promotionGroupUser.setPromotionGroupId(promotionGroup.getPromotionGroupId());
+                promotionGroupUser.setPromotionName(promotionGroup.getName());
+                promotionGroupUser.setUserId(user.getUserId());
+                promotionGroupUser.setNickName(user.getNickName());
+                promotionGroupUser.setMobile(user.getMobile());
+                promotionGroupUser.setAvatar(user.getAvatar());
+                promotionGroupUser.setCreateTime(new Date());
+                promotionGroupUser.setCompanyWechatId(adminUser.getLoginCompanyWechatId());
+                promotionGroupUser.setCompanyName(adminUser.getLoginCompanyName());
+                promotionGroupUsers.add(promotionGroupUser);
+            }
+            promotionGroupUserService.saveBatch(promotionGroupUsers);
+
+            //初始化商品规格的团长
+            for (PromotionGroupSpec promotionGroupSpec : list1) {
+                for (User user : users) {
+                    PromotionGroupSpecUser promotionGroupSpecUser = new PromotionGroupSpecUser();
+                    BeanUtils.copyProperties(promotionGroupSpec, promotionGroupSpecUser);
+                    promotionGroupSpecUser.setUserId(user.getUserId());
+                    promotionGroupSpecUser.setUserName(user.getNickName());
+                    promotionGroupSpecUser.setUserPhone(user.getMobile());
+                    promotionGroupSpecUser.setCreateTime(new Date());
+                    promotionGroupSpecUser.setGroupPrice(promotionGroupSpec.getComGroupPrice());
+                    promotionGroupSpecUser.setShareAmount(promotionGroupSpec.getComShareAmount());
+                    promotionGroupSpecUser.setCompanyWechatId(adminUser.getLoginCompanyWechatId());
+                    promotionGroupSpecUser.setCompanyName(adminUser.getLoginCompanyName());
+                    specUsers.add(promotionGroupSpecUser);
+
+                }
+            }
+            promotionGroupSpecUserService.saveBatch(specUsers);
+        }
+
+        //4.设置为团购活动商品
+        if (goodsIds.size() > 0) {
+            goodsService.lambdaUpdate()
+                    .set(Goods::getPromotionGroup, true)
+                    .in(Goods::getGoodsId, goodsIds)
+                    .update();
+        }
+    }
+
+
+    public void addGroupUser(User user) {
+        //1.remove
+        this.deleteGroupUser(user);
+        //2.add
+        List<PromotionGroupSpec> list = promotionGroupSpecService.list();
+        List<PromotionGroupSpecUser> specUsers = new ArrayList<>();
+        for (PromotionGroupSpec promotionGroupSpec : list) {
+            PromotionGroupSpecUser promotionGroupSpecUser = new PromotionGroupSpecUser();
+            BeanUtils.copyProperties(promotionGroupSpec, promotionGroupSpecUser);
+            promotionGroupSpecUser.setUserId(user.getUserId());
+            promotionGroupSpecUser.setUserName(user.getNickName());
+            promotionGroupSpecUser.setUserPhone(user.getMobile());
+            promotionGroupSpecUser.setCreateTime(new Date());
+            promotionGroupSpecUser.setGroupPrice(promotionGroupSpec.getComGroupPrice());
+            promotionGroupSpecUser.setShareAmount(promotionGroupSpec.getComShareAmount());
+            promotionGroupSpecUser.setCompanyWechatId(user.getCompanyWechatId());
+            promotionGroupSpecUser.setCompanyName(user.getCompanyName());
+            specUsers.add(promotionGroupSpecUser);
+        }
+        promotionGroupSpecUserService.saveBatch(specUsers);
+    }
+
+    public void deleteGroupUser(User user) {
+        promotionGroupSpecUserService.lambdaUpdate()
+                .eq(PromotionGroupSpecUser::getUserId, user.getUserId())
+                .eq(StringUtils.isNotEmpty(user.getCompanyWechatId()), PromotionGroupSpecUser::getCompanyWechatId, user.getCompanyWechatId())
+                .remove();
+        promotionGroupUserService.lambdaUpdate().eq(PromotionGroupUser::getUserId, user.getUserId()).remove();
+    }
+
+
+    /**
+     * 拼团详情
+     */
+    public IPage<PromotionGroupDetail> ptDetail(String promotionGroupId, String mobile, Integer pageNum, Integer pageSize) {
+        //查询所有团长
+        IPage page = promotionGroupUserService.lambdaQuery()
+                .eq(PromotionGroupUser::getPromotionGroupId, promotionGroupId)
+                .like(StringUtils.isNotEmpty(mobile), PromotionGroupUser::getMobile, mobile)
+                .page(new Page<>(pageNum, pageSize));
+
+        List<PromotionGroupDetail> list = new ArrayList<>();
+        for (Object o : page.getRecords()) {
+            PromotionGroupUser user = (PromotionGroupUser) o;
+            PromotionGroupDetail promotionGroupDetail = promotionMapper.queryPtDetail(promotionGroupId, user.getUserId());
+            promotionGroupDetail.setNickName(user.getNickName());
+            promotionGroupDetail.setWebsitName("团长");
+            promotionGroupDetail.setPosition("团长");
+            promotionGroupDetail.setPhone(user.getMobile());
+            promotionGroupDetail.setUserId(user.getUserId());
+
+            //首次访问时间
+            IPage<GoodsVisit> page1 = goodsVisitService.lambdaQuery()
+                    .eq(GoodsVisit::getShareUserId, user.getUserId())
+                    .eq(GoodsVisit::getPromotionGroupId, promotionGroupId)
+                    .orderByAsc(GoodsVisit::getCreateTime)
+                    .page(new Page<>(1, 1));
+            if (page1.getTotal() > 0) {
+                promotionGroupDetail.setFirstTime(page1.getRecords().get(0).getCreateTime());
+            }
+            //总访问次数
+            Long count = goodsVisitService.lambdaQuery()
+                    .eq(GoodsVisit::getShareUserId, user.getUserId())
+                    .eq(GoodsVisit::getPromotionGroupId, promotionGroupId)
+                    .count();
+            promotionGroupDetail.setShareNum(Math.toIntExact(count));
+            //订单数量
+            Long orderNum = orderInfoService.lambdaQuery()
+                    .notIn(OrderInfo::getOrderStatus, Arrays.asList(OrderStatusEnum.CLOSE.toString(), OrderStatusEnum.TIMEOUT.toString()))
+                    .eq(OrderInfo::getPromotionGroupId, promotionGroupId)
+                    .eq(OrderInfo::getPromotionGroupUserId, user.getUserId()).count();
+            promotionGroupDetail.setOrderNum(Math.toIntExact(orderNum));
+            //订单台数
+            Integer orderDetilNum = promotionMapper.queryTotalGoodsNum(promotionGroupId, user.getUserId());
+            promotionGroupDetail.setGoodsNum(orderDetilNum);
+            //分佣金额
+            promotionGroupDetail.setShareTotalAmount(promotionMapper.queryTotalShareAmount(null, promotionGroupId, user.getUserId()));
+            //已结算金额
+            promotionGroupDetail.setSettledAmount(promotionMapper.queryTotalShareAmount(OrderShareStatusEnum.OVER.toString(), promotionGroupId, user.getUserId()));
+            list.add(promotionGroupDetail);
+        }
+        page.setRecords(list);
+        return page;
+    }
+
+    /**
+     * 拼团订单明细
+     */
+    public IPage<OrderInfo> queryOrderList(String promotionGroupId, String userId, Integer pageNo, Integer pageSize) {
+        IPage<OrderInfo> page = orderInfoService.lambdaQuery()
+                .eq(OrderInfo::getPromotionGroupId, promotionGroupId)
+                .eq(OrderInfo::getPromotionGroupUserId, userId)
+                .orderByDesc(OrderInfo::getCreateTime)
+                .page(new Page<>(pageNo, pageSize));
+        return page;
+    }
+
+    /**
+     * 拼团分享明细
+     */
+    public IPage<GoodsVisit> queryGoodsVisit(String promotionGroupId, String userId, Integer pageNo, Integer pageSize, HttpServletRequest request) {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        List<String> companyWechatIds = adminUser.getCompanyWechatIds();
+
+        IPage<GoodsVisit> page = goodsVisitService.lambdaQuery()
+                .in(CollectionUtils.isNotEmpty(companyWechatIds), GoodsVisit::getCompanyWechatId, companyWechatIds)
+                .eq(GoodsVisit::getPromotionGroupId, promotionGroupId)
+                .eq(GoodsVisit::getShareUserId, userId)
+                .orderByDesc(GoodsVisit::getCreateTime)
+                .page(new Page<>(pageNo, pageSize));
+        return page;
+    }
+
+
+}

+ 27 - 1
src/main/java/com/gree/mall/contest/logic/common/CommonLogic.java

@@ -15,6 +15,7 @@ import com.gree.mall.contest.utils.RedisUtil;
 import com.gree.mall.contest.utils.oss.OSSUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.DateUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -104,7 +105,6 @@ public class CommonLogic {
         }
         return userService.lambdaQuery()
                 .eq(User::getMobile, mobile)
-                .eq(User::getFlag, flag)
                 .one();
     }
 
@@ -149,6 +149,11 @@ public class CommonLogic {
             return account2;
         }
         adminUserCom.setCompanyWechatIds(ListUtil.toList("1"));
+        // TODO 写死后期处理
+        AdminCompanyWechat adminCompanyWechat = adminCompanyWechatService.getById("1");
+        adminUserCom.setAdminCompanyWechat(adminCompanyWechat);
+        adminUserCom.setLoginCompanyWechatId(adminCompanyWechat.getCompanyWechatId());
+        adminUserCom.setLoginCompanyName(adminCompanyWechat.getCompanyName());
         //暂不过滤权限
         return adminUserCom;
     }
@@ -316,4 +321,25 @@ public class CommonLogic {
         }
         return commonFiles.stream().map(CommonFile::getUrl).collect(Collectors.toList());
     }
+
+    /**
+     * 附件归属绑定
+     */
+    public void bindFile(String objId,String objType,List<String> fileIds){
+        //先删除后绑定
+        commonFileService.lambdaUpdate()
+                .eq(CommonFile::getObjId,objId)
+                .eq(CommonFile::getObjType,objType)
+                .notIn(CommonFile::getId,fileIds).remove();
+
+        for(int i =0;i< fileIds.size();i++) {
+            //这里分开每次存储的时候,每个图片创建时间加1秒,方便图片排序用
+            commonFileService.lambdaUpdate()
+                    .set(CommonFile::getObjId, objId)
+                    .set(CommonFile::getObjType, objType)
+                    .set(CommonFile::getCreateTime, DateUtils.addSeconds(new Date(),i))
+                    .eq(CommonFile::getId, fileIds.get(i))
+                    .update();
+        }
+    }
 }

+ 165 - 0
src/main/java/com/gree/mall/contest/logic/common/WechatLogic.java

@@ -2,13 +2,23 @@ package com.gree.mall.contest.logic.common;
 
 import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.IdUtil;
 import cn.hutool.json.JSONUtil;
+import com.github.binarywang.wxpay.bean.profitsharing.*;
+import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.ProfitSharingService;
+import com.github.binarywang.wxpay.service.WxPayService;
 import com.gree.mall.contest.bean.common.WechatOpenBean;
 import com.gree.mall.contest.config.wx.WxConfiguration;
 import com.gree.mall.contest.constant.Constant;
 import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.plus.entity.OrderShare;
 import com.gree.mall.contest.plus.entity.WxScene;
 import com.gree.mall.contest.plus.service.WxSceneService;
+import com.gree.mall.contest.utils.ArithUtils;
 import com.gree.mall.contest.utils.oss.OSSUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -33,7 +43,9 @@ import org.springframework.stereotype.Component;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.math.BigDecimal;
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * Created by lijh on 19/06/28.
@@ -51,6 +63,9 @@ public class WechatLogic {
     private final OSSUtil ossUtil;
     private final WxSceneService wxSceneService;
 
+    public WxPayService getPayService(String companyWechatId){
+        return WxConfiguration.wxPayServices.get(companyWechatId);
+    }
     /**
      * 微信小程序服务
      * @return
@@ -91,6 +106,10 @@ public class WechatLogic {
         return this.getMaService().getAccessToken();
     }
 
+    public String getAccessToken(String companyWechatId) throws RemoteServiceException, WxErrorException {
+        return this.getMaService(companyWechatId).getAccessToken();
+    }
+
     /**
      * 小程序授权openid
      * @param code
@@ -240,4 +259,150 @@ public class WechatLogic {
         return ticket;
     }
 
+    /**
+     * 分账
+     *
+     * @param orderId
+     * @param transactionId
+     * @param orderShares
+     * @throws WxPayException
+     */
+    public void shareAmount(String orderId, String transactionId, List<OrderShare> orderShares, String companyWechatId) throws WxPayException {
+        //开始分账
+        profitSharing(orderId, transactionId, orderShares, companyWechatId);
+    }
+
+    private void profitSharing(String orderSharingId, String transactionId, List<OrderShare> orderShares, String companyWechatId) throws WxPayException {
+
+        log.info("【准备结算】:" + JSONUtil.toJsonStr(orderShares));
+        orderShares = orderShares.stream().filter(v -> v.getAmount().doubleValue() > 0).collect(Collectors.toList());
+        log.info("【准备结算2】:" + JSONUtil.toJsonStr(orderShares));
+        if (CollectionUtil.isEmpty(orderShares)) {
+            return;
+        }
+
+        List<String> openIds = orderShares.stream().map(OrderShare::getOpenId).distinct().collect(Collectors.toList());
+        List<Map<String, Object>> list = new ArrayList<>();
+
+        for (String openId : openIds) {
+            //添加分账人
+            addShareReveiver(openId, companyWechatId);
+
+            BigDecimal shareAmount = orderShares.stream().filter(v -> v.getOpenId().equals(openId)).map(OrderShare::getAmount)
+                    .reduce(BigDecimal::add).orElse(BigDecimal.valueOf(0));
+            String workerUserPhone = orderShares.stream().filter(v -> v.getOpenId().equals(openId)).map(OrderShare::getWorkUserPhone).collect(Collectors.toList()).get(0);
+            if (shareAmount.doubleValue() == 0) {
+                continue;
+            }
+            Map<String, Object> receiver = new HashMap<>();
+            receiver.put("type", "PERSONAL_SUB_OPENID");
+            receiver.put("account", openId);
+            receiver.put("amount", ProfitSharingReceiverRequest.yuanToFen(shareAmount.toString()));
+            receiver.put("description", "销售返佣给" + workerUserPhone + ",金额:" + shareAmount + "元");
+            list.add(receiver);
+        }
+
+        ProfitSharingRequest profitSharingRequest = new ProfitSharingRequest();
+        profitSharingRequest.setOutOrderNo(orderSharingId);
+        profitSharingRequest.setTransactionId(transactionId);
+        profitSharingRequest.setReceivers(JSONUtil.toJsonStr(list));
+
+        ProfitSharingService profitSharingService = this.getPayService(companyWechatId).getProfitSharingService();
+        //请求单次分账
+        log.info("【开始分账】request:{}", JSONUtil.toJsonStr(profitSharingRequest));
+        ProfitSharingResult profitSharingResult = profitSharingService.profitSharing(profitSharingRequest);
+        log.info("【开始分账】result:{}", JSONUtil.toJsonStr(profitSharingResult));
+
+    }
+
+    public ProfitSharingQueryResult profitSharingResult(OrderShare orderShare) throws WxPayException {
+        if (StringUtils.isBlank(orderShare.getCompanyWechatId())) {
+            return null;
+        }
+        ProfitSharingService profitSharingService = this.getPayService(orderShare.getCompanyWechatId()).getProfitSharingService();
+
+        ProfitSharingQueryRequest profitSharingRequest = new ProfitSharingQueryRequest();
+        profitSharingRequest.setOutOrderNo(orderShare.getOrderId());
+        profitSharingRequest.setTransactionId(orderShare.getTransactionId());
+        // 请求查询分账结果
+        log.info("【查询分账结果】request:{}", JSONUtil.toJsonStr(profitSharingRequest));
+        ProfitSharingQueryResult profitSharingQueryResult = profitSharingService.profitSharingQuery(profitSharingRequest);
+        log.info("【查询分账结果】result:{}", JSONUtil.toJsonStr(profitSharingQueryResult));
+        return profitSharingQueryResult;
+    }
+
+    private boolean addShareReveiver(String openId,String companyWechatId) {
+        Map<String, Object> receiver = new HashMap<>();
+        /**
+         *  MERCHANT_ID:商户号
+         *  PERSONAL_OPENID:个人openId(由父商户号APPID转换得到)
+         *  PERSONAL_SUB_OPENID:个人sub_openid(由子商户APPID转换得到)
+         */
+        receiver.put("type", "PERSONAL_SUB_OPENID");
+        /**
+         * 分账接收方类型为MERCHANT_ID时,分账接收方账号为商户号
+         * 分账接收方类型为PERSONAL_OPENID时,分账接收方账号为个人openid
+         * 分账接收方类型为PERSONAL_SUB_OPENID时,分账接收方账号为个人sub_openid
+         */
+        receiver.put("account", openId);
+        //receiver.put("name",name);
+        receiver.put("relation_type", "STAFF");
+        //添加分账人
+        ProfitSharingService profitSharingService = this.getPayService(companyWechatId).getProfitSharingService();
+
+        ProfitSharingReceiverRequest profitSharingReceiverRequest = new ProfitSharingReceiverRequest();
+        profitSharingReceiverRequest.setReceiver(JSONUtil.toJsonStr(receiver));
+        ProfitSharingReceiverResult result = null;
+        try {
+            result = profitSharingService.addReceiver(profitSharingReceiverRequest);
+            if (result.getReturnCode().equals("SUCCESS")) {
+                return true;
+
+            }
+        } catch (WxPayException e) {
+            e.printStackTrace();
+        }
+        return false;
+    }
+
+    public String queryMaxShareRate(String id) throws WxPayException {
+        final ProfitSharingService sharingService = this.getPayService(id).getProfitSharingService();
+        ProfitSharingMerchantRatioQueryRequest request = new ProfitSharingMerchantRatioQueryRequest();
+        final ProfitSharingMerchantRatioQueryResult result = sharingService.profitSharingMerchantRatioQuery(request);
+        if (!result.getReturnCode().equals("SUCCESS")) {
+            return "";
+        }
+        Map<String, Object> repMap = new HashMap<>();
+        repMap.put("商户号", result.getMchId());
+        repMap.put("子商户号", result.getSubMchId());
+        repMap.put("最大分账比例", result.getMaxRatio());
+        return JSONUtil.toJsonStr(repMap);
+    }
+
+    /**
+     * 服务商退款
+     */
+    public void refund(String orderId, String refundNo, Double totalFee, Double refundFee,String companyWechatId) throws  RemoteServiceException {
+        WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
+        wxPayRefundRequest.setOutTradeNo(orderId);
+        wxPayRefundRequest.setOutRefundNo(refundNo);
+        wxPayRefundRequest.setRefundFee((int) ArithUtils.mul(refundFee, 100));
+        wxPayRefundRequest.setTotalFee((int) ArithUtils.mul(totalFee, 100));
+        wxPayRefundRequest.setNonceStr(IdUtil.simpleUUID());
+//        wxPayRefundRequest.setNotifyUrl(refundNotifyUrl);
+
+        log.info("【申请微信退款】request=" + JSONUtil.toJsonStr(wxPayRefundRequest));
+        try {
+            WxPayRefundResult refund = this.getPayService(companyWechatId).refund(wxPayRefundRequest);
+            log.info("【申请微信退款】result=" + JSONUtil.toJsonStr(refund));
+
+            if (!StringUtils.equals(refund.getReturnCode(), "SUCCESS")) {
+                throw new RemoteServiceException(refund.getReturnCode() + refund.getReturnMsg());
+            }
+        }catch (WxPayException ex){
+            throw new RemoteServiceException("退款失败:"+ex.getMessage());
+        }
+
+
+    }
 }

+ 618 - 0
src/main/java/com/gree/mall/contest/logic/coupon/CouponLogic.java

@@ -0,0 +1,618 @@
+package com.gree.mall.contest.logic.coupon;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.contest.bean.ExcelData;
+import com.gree.mall.contest.bean.admin.AdminUserCom;
+import com.gree.mall.contest.bean.coupon.*;
+import com.gree.mall.contest.commonmapper.CouponDateMapper;
+import com.gree.mall.contest.enums.UserTypeEnum;
+import com.gree.mall.contest.enums.coupon.CouponActiveTypeEnum;
+import com.gree.mall.contest.enums.coupon.CouponCrowdEnum;
+import com.gree.mall.contest.enums.coupon.CouponFlagEnum;
+import com.gree.mall.contest.enums.coupon.CouponTypeEnum;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.logic.common.CommonLogic;
+import com.gree.mall.contest.plus.entity.*;
+import com.gree.mall.contest.plus.service.*;
+import com.gree.mall.contest.utils.excel.ExcelUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class CouponLogic {
+
+    private final CouponService couponService;
+    private final CouponGoodsService couponGoodsService;
+    private final CouponDateMapper couponDateMapper;
+    private final UserCouponService userCouponService;
+    private final CouponUserService couponUserService;
+    private final UserService userService;
+    private final CommonLogic commonLogic;
+
+    /**
+     * 优惠券列表
+     */
+    public IPage<CouponPageBean> page(String couponName, String couponType, String flag, Integer pageNum, Integer pageSize, HttpServletRequest request) {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        List<String> companyWechatIds = adminUser.getCompanyWechatIds();
+
+        return couponDateMapper.pageCoupon(new Page<>(pageNum, pageSize), companyWechatIds, couponName, couponType, flag);
+    }
+
+
+    public void export(HttpServletRequest request, HttpServletResponse response, String couponName, String couponType, String flag) throws Exception {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        List<String> companyWechatIds = adminUser.getCompanyWechatIds();
+
+        List<CouponExportBean> couponExportBeans = couponDateMapper.exportCoupon(companyWechatIds, couponName, couponType, flag);
+        //List<CouponExportBean> couponSelfBeans =  couponDateMapper.exportSelfCoupon(companyWechatIds, couponName, couponType, flag);
+//        if(CollectionUtils.isNotEmpty(couponSelfBeans)){
+//            couponExportBeans.addAll(couponSelfBeans);
+//        }
+
+        String[] titles = {"优惠券名称", "发放数量", "领取数量", "使用数量", "优惠券金额", "领取来源-网点名称", "领取来源-业务员昵称", "领取来源-业务员电话", "优惠券状态", "领券客户昵称", "领券客户电话",
+                "用券时间", "订单号", "订单实付金额"};
+        ExcelData excelData = new ExcelData();
+        List<List<Object>> rows = new ArrayList<>();
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        for (CouponExportBean couponExportBean : couponExportBeans) {
+            List<Object> row = new ArrayList<>();
+            row.add(couponExportBean.getCouponName());
+            row.add(couponExportBean.getCouponAmount());
+            row.add(couponExportBean.getReceiveAmount());
+            row.add(couponExportBean.getUsedAmount());
+            row.add(couponExportBean.getCouponValue());
+            row.add(couponExportBean.getWebsitName());
+            row.add(couponExportBean.getWorkName());
+            row.add(couponExportBean.getWorkPhone());
+            row.add(couponExportBean.getStatus() ? "已使用" : "未使用");
+            row.add(couponExportBean.getNickName());
+            row.add(couponExportBean.getMobile());
+            row.add(couponExportBean.getUsedTime() == null ? "" : simpleDateFormat.format(couponExportBean.getUsedTime()));
+            row.add(couponExportBean.getOrderId());
+            row.add(couponExportBean.getPayAmount() == null ? "" : couponExportBean.getPayAmount().toString());
+            rows.add(row);
+        }
+        String fileName = String.format("优惠券导出_%s.xlsx", simpleDateFormat.format(new Date()));
+        excelData.setTitles(Arrays.asList(titles));
+        excelData.setName("优惠券");
+        excelData.setRows(rows);
+        ExcelUtils.exportExcel(request, response, fileName, excelData, -1, null);
+    }
+
+    /**
+     * 券详情
+     *
+     * @param couponId
+     * @return
+     */
+    public CouponDetailBean detail(String couponId) {
+        Coupon coupon = couponService.getById(couponId);
+        CouponDetailBean couponBean = new CouponDetailBean();
+        BeanUtils.copyProperties(coupon, couponBean);
+        couponBean.setGoodsList(couponGoodsService.lambdaQuery().eq(CouponGoods::getCouponId, couponId).list());
+        return couponBean;
+    }
+
+    /**
+     * 新增券
+     *
+     * @param couponBean
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void add(HttpServletRequest request, CouponBean couponBean) throws RemoteServiceException {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+
+        if (couponBean.getActiveType() == 1) {
+            if (Objects.isNull(couponBean.getActiveStartTime()) || Objects.isNull(couponBean.getActiveEndTime())) {
+                throw new RemoteServiceException("使用时间区间不能为空!");
+            }
+            if (couponBean.getActiveEndTime().compareTo(couponBean.getActiveStartTime()) < 0) {
+                throw new RemoteServiceException("使用结束时间不能少于开始时间!");
+            }
+        }
+        couponBean.setFlag(CouponFlagEnum.WAIT.toString());
+        couponBean.setLeftAmount(couponBean.getCouponAmount());
+        couponBean.setCreateTime(new Date());
+        couponBean.setCompanyWechatId(adminUser.getLoginCompanyWechatId());
+        couponBean.setCompanyName(adminUser.getLoginCompanyName());
+        couponBean.setActiveType(couponBean.getActiveDay() != null ? 2 : 1);
+        couponService.save(couponBean);
+        String couponId = couponBean.getCouponId();
+        if (couponBean.getCouponType().trim().equals(CouponTypeEnum.GOODS.getName()) && couponBean.getGoodsList() != null) {
+            List<CouponGoods> couponGoodsList = new ArrayList<>();
+            for (CouponGoods couponGoods : couponBean.getGoodsList()) {
+                couponGoods.setCouponId(couponId);
+                couponGoods.setCreateTime(new Date());
+                couponGoods.setCompanyWechatId(adminUser.getLoginCompanyWechatId());
+                couponGoods.setCompanyName(adminUser.getLoginCompanyName());
+                couponGoodsList.add(couponGoods);
+            }
+            couponGoodsService.saveBatch(couponGoodsList);
+        }
+
+        //指定会员
+        if (couponBean.getReceiveCrowd().equals(CouponCrowdEnum.SPECIFY.getFlag()) && couponBean.getUserList() != null) {
+            List<CouponUser> couponUserList = new ArrayList<>();
+//            List<UserCoupon> userCouponList = new ArrayList<>();
+            for (CouponUserTypeBean couponUserTypeBean : couponBean.getUserList()) {
+                CouponUser couponUser = new CouponUser();
+                couponUser.setCouponId(couponId);
+                couponUser.setUserId(couponUserTypeBean.getUserId());
+                couponUser.setUserName(couponUserTypeBean.getUserName());
+                couponUser.setCreateTime(new Date());
+                couponUser.setCompanyName(adminUser.getLoginCompanyName());
+                couponUser.setCompanyWechatId(adminUser.getLoginCompanyWechatId());
+                couponUserList.add(couponUser);
+//                if (couponUserTypeBean.getType().equals(UserTypeEnum.SERVICE.toString())) {
+//                    userCouponList.add(assignCoupon(adminUser, couponBean, couponUserTypeBean.getUserId()));
+//                }
+
+            }
+
+            if (couponUserList.size() > 0) {
+                couponUserService.saveBatch(couponUserList);
+            }
+
+//            if (userCouponList.size() > 0) {
+//                userCouponService.saveBatch(userCouponList);
+//            }
+
+        }
+        //全部业务员
+        if (couponBean.getReceiveCrowd() == CouponCrowdEnum.ALL_SERVICE.getFlag()) {
+            List<UserCoupon> userCouponList = new ArrayList<>();
+            List<User> userList = userService.lambdaQuery()
+                    .eq(User::getType, UserTypeEnum.SERVICE.toString())
+                    .eq(User::getCompanyWechatId, adminUser.getLoginCompanyWechatId())
+                    .list();
+            List<CouponUser> couponUserList = new ArrayList<>();
+            for (User user : userList) {
+                userCouponList.add(assignCoupon(adminUser, couponBean, user.getUserId()));
+                CouponUser couponUser = new CouponUser();
+                couponUser.setCouponId(couponId);
+                couponUser.setUserId(user.getUserId());
+                couponUser.setUserName(user.getNickName());
+                couponUser.setCreateTime(new Date());
+                couponUser.setCompanyWechatId(adminUser.getLoginCompanyWechatId());
+                couponUser.setCompanyName(adminUser.getLoginCompanyName());
+                couponUserList.add(couponUser);
+            }
+            if (userCouponList.size() > 0) {
+                userCouponService.saveBatch(userCouponList);
+            }
+            if (couponUserList.size() > 0) {
+                couponUserService.saveBatch(couponUserList);
+            }
+        }
+        //全部普通用户
+        if (couponBean.getReceiveCrowd().equals(CouponCrowdEnum.ALL_GENRERAL.getFlag())) {
+            List<CouponUser> couponUserList = new ArrayList<>();
+            List<User> userList = userService.lambdaQuery()
+                    .eq(User::getType, UserTypeEnum.GENERAL.toString())
+                    .eq(User::getCompanyWechatId, adminUser.getLoginCompanyWechatId())
+                    .list();
+            for (User user : userList) {
+                CouponUser couponUser = new CouponUser();
+                couponUser.setCouponId(couponId);
+                couponUser.setUserId(user.getUserId());
+                couponUser.setUserName(user.getNickName());
+                couponUser.setCreateTime(new Date());
+                couponUser.setCompanyWechatId(adminUser.getLoginCompanyWechatId());
+                couponUser.setCompanyName(adminUser.getLoginCompanyName());
+                couponUserList.add(couponUser);
+            }
+            if (couponUserList.size() > 0) {
+                couponUserService.saveBatch(couponUserList);
+            }
+        }
+
+
+    }
+
+
+    private UserCoupon assignCoupon(AdminUserCom adminUserCom, CouponBean couponBean, String userId) {
+        UserCoupon userCoupon = new UserCoupon();
+        userCoupon.setCompanyWechatId(adminUserCom.getLoginCompanyWechatId());
+        userCoupon.setCouponName(adminUserCom.getLoginCompanyName());
+        userCoupon.setCouponId(couponBean.getCouponId());
+        userCoupon.setUserId(userId);
+        userCoupon.setReceiveTime(new Date());
+        userCoupon.setCouponName(couponBean.getCouponName());
+        userCoupon.setCouponType(couponBean.getCouponType());
+        userCoupon.setOrderAmount(couponBean.getOrderAmount());
+        userCoupon.setCouponValue(couponBean.getCouponValue());
+        userCoupon.setStatus(false);
+        //userCoupon.setTransferType(true);
+        userCoupon.setLeftShareTimes(couponBean.getShareTimes());
+        if (couponBean.getActiveDay() == null) {
+            couponBean.setActiveDay(0);
+        }
+        if (couponBean.getActiveType().equals(CouponActiveTypeEnum.COMMON.getActiveType())) {
+            userCoupon.setActiveStartTime(couponBean.getActiveStartTime());
+            userCoupon.setActiveEndTime(couponBean.getActiveEndTime());
+        }
+        //当日起多少天
+        if (couponBean.getActiveType().equals(CouponActiveTypeEnum.TODAY.getActiveType())) {
+            userCoupon.setActiveStartTime(DateUtil.parseTime(DateUtil.formatDate(DateUtil.date()) + " 00:00:00"));
+            userCoupon.setActiveEndTime(DateUtil.parseTime(DateUtil.formatDate(DateUtil.offsetDay(DateUtil.date(), couponBean.getActiveDay())) + " 23:59:59"));
+        }
+        //次日起多少天
+        if (couponBean.getActiveType().equals(CouponActiveTypeEnum.NEXTDAY.getActiveType())) {
+            userCoupon.setActiveStartTime(DateUtil.parseTime(DateUtil.formatDate(DateUtil.offsetDay(DateUtil.date(), 1)) + " 00:00:00"));
+            userCoupon.setActiveEndTime(DateUtil.parseTime(DateUtil.formatDate(DateUtil.offsetDay(DateUtil.date(), couponBean.getActiveDay() + 1)) + " 23:59:59"));
+        }
+        userCoupon.setState(new Date().before(couponBean.getActiveEndTime()) && new Date().after(couponBean.getActiveStartTime()));
+        return userCoupon;
+    }
+
+    public void reissueCoupon(HttpServletRequest request, ReissueCouponBean reissueCouponBean) throws RemoteServiceException {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        String loginCompanyWechatId = adminUser.getLoginCompanyWechatId();
+        String loginCompanyName = adminUser.getLoginCompanyName();
+
+        Coupon coupon = couponService.getById(reissueCouponBean.getCouponId());
+        if (coupon == null) {
+            throw new RemoteServiceException("优惠券不存在");
+        }
+        if (coupon.getTransferType() != null && !coupon.getTransferType()) {
+            throw new RemoteServiceException("优惠券不可以补发");
+        }
+        if (coupon.getObtainEndTime().compareTo(new Date()) <= 0) {
+            throw new RemoteServiceException("优惠券超过领取时间");
+        }
+        List<CouponUserTypeBean> userIds = reissueCouponBean.getUserIds();
+        if (CollectionUtil.isEmpty(userIds)) {
+            userIds = couponDateMapper.reissueCouponUser(loginCompanyWechatId, coupon.getCouponId());
+        }
+        List<CouponUser> couponUserList = new ArrayList<>();
+        List<UserCoupon> userCouponList = new ArrayList<>();
+        for (CouponUserTypeBean couponUserTypeBean : userIds) {
+            CouponUser couponUser = new CouponUser();
+            couponUser.setCouponId(coupon.getCouponId());
+            couponUser.setUserId(couponUserTypeBean.getUserId());
+            couponUser.setUserName(couponUserTypeBean.getUserName());
+            couponUser.setCreateTime(new Date());
+            couponUser.setCompanyWechatId(loginCompanyWechatId);
+            couponUser.setCompanyName(loginCompanyName);
+            couponUserList.add(couponUser);
+            CouponBean couponBean = new CouponBean();
+            BeanUtils.copyProperties(coupon, couponBean);
+            userCouponList.add(assignCoupon(adminUser, couponBean, couponUserTypeBean.getUserId()));
+        }
+
+        if (couponUserList.size() > 0) {
+            couponUserService.saveBatch(couponUserList);
+        }
+
+        if (userCouponList.size() > 0) {
+            userCouponService.saveBatch(userCouponList);
+        }
+
+    }
+
+
+    /**
+     * 修改券
+     *
+     * @param couponBean
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void update(HttpServletRequest request, CouponBean couponBean) throws RemoteServiceException {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        String loginCompanyName = adminUser.getLoginCompanyName();
+        String loginCompanyWechatId = adminUser.getLoginCompanyWechatId();
+
+        Coupon coupon = couponService.getById(couponBean.getCouponId());
+        couponBean.setCreateTime(null);
+        Date now = new Date();
+        if (coupon.getFlag().trim().equals(CouponFlagEnum.WAIT.toString())) {
+            //待发布处理
+            couponService.updateById(couponBean);
+            //清除商品
+            if (couponBean.getGoodsList() != null && couponBean.getGoodsList().size() > 0) {
+                couponGoodsService.lambdaUpdate()
+                        .eq(CouponGoods::getCouponId, couponBean.getCouponId()).remove();
+                for (CouponGoods couponGoods : couponBean.getGoodsList()) {
+                    couponGoods.setCouponId(couponBean.getCouponId());
+                    couponGoods.setCreateTime(now);
+                    couponGoods.setCompanyWechatId(loginCompanyWechatId);
+                    couponGoods.setCompanyName(loginCompanyName);
+                    couponGoodsService.save(couponGoods);
+                }
+            }
+
+            if (couponBean.getUserList() != null && couponBean.getUserList().size() > 0) {
+                couponUserService.lambdaUpdate()
+                        .eq(CouponUser::getCouponId, couponBean.getCouponId())
+                        .remove();
+                List<CouponUser> couponUserList = new ArrayList<>();
+                for (CouponUserTypeBean couponUserTypeBean : couponBean.getUserList()) {
+                    CouponUser couponUser = new CouponUser();
+                    couponUser.setCouponId(couponBean.getCouponId());
+                    couponUser.setUserId(couponUserTypeBean.getUserId());
+                    couponUser.setUserName(couponUserTypeBean.getUserName());
+                    couponUser.setCreateTime(new Date());
+                    couponUser.setCompanyWechatId(loginCompanyWechatId);
+                    couponUser.setCompanyName(loginCompanyName);
+                    couponUserList.add(couponUser);
+                    if (couponUserTypeBean.getType().equals(UserTypeEnum.SERVICE.toString())) {
+                        UserCoupon userCoupon = userCouponService.lambdaQuery()
+                                .eq(UserCoupon::getCouponId, couponBean.getCouponId())
+                                .eq(UserCoupon::getUserId, couponUserTypeBean.getUserId())
+                                //.eq(UserCoupon::getTransferType, true)
+                                .one();
+                        if (userCoupon == null) {
+                            userCouponService.save(assignCoupon(adminUser, couponBean, couponUserTypeBean.getUserId()));
+                        }
+
+                    }
+                }
+                if (couponUserList.size() > 0) {
+                    couponUserService.saveBatch(couponUserList);
+                }
+            }
+        } else if (!coupon.getFlag().trim().equals(CouponFlagEnum.CANCEL.toString()) && coupon.getDisplayTime().before(now) && coupon.getObtainEndTime().after(now)) {
+            //进行中处理
+            if (coupon.getCouponAmount() > couponBean.getCouponAmount()) {
+                throw new RemoteServiceException("修改优惠券发放总量时只能增加不能减少!");
+            }
+            couponService.lambdaUpdate()
+                    .eq(Coupon::getCouponId, couponBean.getCouponId())
+                    .set(StringUtils.isNotBlank(couponBean.getCouponName()), Coupon::getCouponName, couponBean.getCouponName())
+                    .set(couponBean.getCouponAmount() > coupon.getCouponAmount(), Coupon::getCouponAmount, couponBean.getCouponAmount())
+                    .set(!Objects.isNull(couponBean.getSortNum()), Coupon::getSortNum, couponBean.getSortNum())
+                    .set(StringUtils.isNotBlank(couponBean.getNote()), Coupon::getNote, couponBean.getNote())
+                    .set(StringUtils.isNotBlank(couponBean.getRemark()), Coupon::getRemark, couponBean.getRemark())
+                    .update();
+            //更改已领取的券名称
+            if (StringUtils.isNotBlank(couponBean.getCouponName())) {
+                userCouponService.lambdaUpdate()
+                        .eq(UserCoupon::getCouponId, couponBean.getCouponId())
+                        .set(UserCoupon::getCouponName, couponBean.getCouponName())
+                        .update();
+            }
+        }
+    }
+
+    /**
+     * 券标志
+     *
+     * @param couponId
+     * @param startDate
+     * @param endDate
+     * @param flag
+     */
+    public void updateFlag(String couponId, String startDate, String endDate, String flag) throws RemoteServiceException {
+        if (flag.trim().equals(CouponFlagEnum.START.toString())) {
+            if (StringUtils.isBlank(startDate) || StringUtils.isBlank(endDate)) {
+                throw new RemoteServiceException("时间不能为空!");
+            }
+            if (endDate.compareTo(startDate) < 0) {
+                throw new RemoteServiceException("结束时间不能少于开始时间!");
+            }
+
+            couponService.lambdaUpdate()
+                    .eq(Coupon::getCouponId, couponId)
+                    .set(Coupon::getReleaseStartTime, startDate)
+                    .set(Coupon::getReleaseEndTime, endDate)
+                    .set(Coupon::getFlag, CouponFlagEnum.START.toString())
+                    .update();
+        } else {
+            couponService.lambdaUpdate()
+                    .eq(Coupon::getCouponId, couponId)
+                    .set(Coupon::getFlag, CouponFlagEnum.CANCEL.toString())
+                    .update();
+
+            userCouponService.lambdaUpdate()
+                    .set(UserCoupon::getState, false)
+                    .set(UserCoupon::getLeftShareTimes, 0)
+                    .set(UserCoupon::getActiveEndTime, DateUtil.formatDate(DateUtil.date()) + " 00:00:00")
+                    .eq(UserCoupon::getCouponId, couponId)
+                    .eq(UserCoupon::getStatus, false)
+                    .update();
+        }
+    }
+
+    /**
+     * 券数据
+     *
+     * @param couponId
+     * @return
+     */
+    public CouponDataBean data(String couponId) {
+        return couponDateMapper.data(couponId);
+    }
+
+
+    /**
+     * 修改优惠券是否可以转让
+     */
+    public void updateUserCouponTransfer(List<String> userIds, Boolean transferType) {
+        userCouponService.lambdaUpdate()
+                .set(UserCoupon::getTransferType, transferType)
+                .in(UserCoupon::getUserId, userIds)
+                .update();
+    }
+
+    /**
+     * 我的优惠券
+     */
+    public IPage<UserCoupon> userCouponList(String userId, Integer pageNo, Integer pageSize) {
+        return userCouponService.lambdaQuery()
+                .eq(UserCoupon::getUserId, userId)
+                .orderByDesc(UserCoupon::getReceiveTime)
+                .page(new Page<>(pageNo, pageSize));
+    }
+
+    /**
+     * 领取优惠券明细
+     *
+     * @param userCouponId
+     * @param pageNo
+     * @param pageSize
+     * @return
+     */
+    public IPage<UserCouponBean> receiveCouponDetail(String userCouponId, Integer pageNo, Integer pageSize) {
+
+        IPage page = userCouponService.lambdaQuery()
+                .eq(UserCoupon::getTransferor, userCouponId)
+                .eq(UserCoupon::getTransferType, 0)
+                .orderByDesc(UserCoupon::getReceiveTime)
+                .page(new Page<>(pageNo, pageSize));
+
+        List<UserCouponBean> list = new ArrayList<>();
+        for (Object o : page.getRecords()) {
+            UserCoupon userCoupon = (UserCoupon) o;
+            UserCouponBean couponUser = new UserCouponBean();
+            BeanUtils.copyProperties(userCoupon, couponUser);
+            User user = userService.getById(userCoupon.getUserId());
+            couponUser.setUserName(user.getNickName());
+            couponUser.setMobile(user.getMobile());
+            list.add(couponUser);
+        }
+        page.setRecords(list);
+        return page;
+
+    }
+
+    public IPage<User> userList(HttpServletRequest request,
+                                String tel, Date registerTime, String keyword, String type, Integer pageNo, Integer pageSize) {
+
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        List<String> companyWechatIds = adminUser.getCompanyWechatIds();
+
+        return userService.lambdaQuery()
+                .in(CollectionUtil.isNotEmpty(companyWechatIds), User::getCompanyWechatId, companyWechatIds)
+                .eq(StringUtils.isNotEmpty(type), User::getType, type)
+                .ge(registerTime != null, User::getCreateTime, registerTime)
+                .like(StringUtils.isNotEmpty(tel), User::getMobile, tel.trim())
+                .like(StringUtils.isNotEmpty(keyword), User::getNickName, keyword.trim())
+                .orderByAsc(User::getCreateTime)
+                .page(new Page<>(pageNo, pageSize));
+    }
+
+    /**
+     * 订单取消,恢复优惠券
+     */
+    @Transactional
+    public void refundCoupon(String userCouponId) {
+        if (StringUtils.isEmpty(userCouponId)) {
+            return;
+        }
+        userCouponService.lambdaUpdate()
+                .set(UserCoupon::getStatus, false)
+                .set(UserCoupon::getUsedTime, null)
+                .eq(UserCoupon::getId, userCouponId)
+                .update();
+
+        if (StringUtils.isEmpty(userCouponId)) {
+            return;
+        }
+        log.info("订单取消,恢复用户优惠券id{}", userCouponId);
+        UserCoupon userCoupon = userCouponService.getById(userCouponId);
+        if (userCoupon.getTransferType() != null && userCoupon.getTransferType()) {
+            userCoupon.setLeftShareTimes(userCoupon.getLeftShareTimes() + 1);
+            userCoupon.updateById();
+        }
+    }
+
+
+    /**
+     * 导入楼小贤优惠券
+     */
+//    @Transactional
+//    public void importLxx(MultipartFile file) throws IOException, ParseException {
+//        List<Object> datas = ExcelUtils.importExcel(file);
+//        int i = 1;
+//
+//        List<Coupon> couponList = new ArrayList<>();
+//        List<CouponUser> couponUserList = new ArrayList<>();
+//        List<UserCoupon> userCouponList = new ArrayList<>();
+//        for (Object o : datas) {
+//            String companyWechatId = "1";
+//            String companyName = "嘉讯茂商城";
+//            i++;
+//            List<Object> row = (List<Object>) o;
+//            String couponName = (String) row.get(0);
+//            String mobile = (String) row.get(1);
+//            BigDecimal amount = new BigDecimal(row.get(2).toString());
+//            Date startTime = DateUtils.parseDate(row.get(3).toString());
+//            Date endTime = DateUtils.parseDate(row.get(4).toString());
+//            if (StringUtils.isEmpty(couponName) || StringUtils.isEmpty(mobile) || amount == null || startTime == null || endTime == null) {
+//                throw new RemoteServiceException("请检查第" + i + "行数据是否完整");
+//            }
+//            User user = userService.lambdaQuery().eq(User::getMobile, mobile).eq(User::getCompanyWechatId, companyWechatId).one();
+//            if (user == null)
+//                throw new RemoteServiceException("手机号为" + mobile + "的找不到对应用户");
+//
+//            //生成优惠券
+//            String couponId = "C" + com.baomidou.mybatisplus.core.toolkit.IdWorker.getIdStr();
+//            Coupon coupon = new Coupon();
+//            coupon.setCouponId(couponId);
+//            coupon.setCouponName(couponName);
+//            coupon.setCouponType(CouponTypeEnum.SATISFY.toString());
+//            coupon.setActiveStartTime(startTime);
+//            coupon.setActiveEndTime(endTime);
+//            coupon.setReceiveCrowd(2);
+//            coupon.setCouponValue(amount);
+//            coupon.setObtainStartTime(startTime);
+//            coupon.setObtainEndTime(endTime);
+//            coupon.setDisplayTime(startTime);
+//            coupon.setFlag("WAIT");
+//            coupon.setRemark(mobile);
+//            coupon.setShareTimes(1);
+//            coupon.setCompanyWechatId(companyWechatId);
+//            coupon.setCompanyName(companyName);
+//            couponList.add(coupon);
+//
+//            CouponUser couponUser = new CouponUser();
+//            couponUser.setCouponId(couponId);
+//            couponUser.setUserId(user.getUserId());
+//            couponUser.setUserName(user.getNickName());
+//            couponUser.setCreateTime(new Date());
+//            couponUser.setCompanyWechatId(companyWechatId);
+//            couponUser.setCompanyName(companyName);
+//            couponUserList.add(couponUser);
+//
+//            //发到师傅手上的券
+//            UserCoupon userCoupon = new UserCoupon();
+//            userCoupon.setUserId(user.getUserId());
+//            userCoupon.setCouponId(couponId);
+//            userCoupon.setCouponName(couponName);
+//            userCoupon.setCouponValue(coupon.getCouponValue());
+//            userCoupon.setCouponType(coupon.getCouponType());
+//            userCoupon.setStatus(false);
+//            userCoupon.setState(true);
+//            userCoupon.setReceiveTime(new Date());
+//            userCoupon.setActiveStartTime(startTime);
+//            userCoupon.setActiveEndTime(endTime);
+//            userCoupon.setCompanyWechatId(companyWechatId);
+//            userCoupon.setCompanyName(companyName);
+//            userCoupon.setTransferType(false);
+//            userCoupon.setLeftShareTimes(1);
+//            userCouponList.add(userCoupon);
+//        }
+//        //新增券
+//        couponService.saveBatch(couponList);
+//        //新增券和人对应关系
+//        couponUserService.saveBatch(couponUserList);
+//        //发券
+//        userCouponService.saveBatch(userCouponList);
+//    }
+
+}

+ 1146 - 0
src/main/java/com/gree/mall/contest/logic/goods/GoodsLogic.java

@@ -0,0 +1,1146 @@
+package com.gree.mall.contest.logic.goods;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.contest.bean.ExcelData;
+import com.gree.mall.contest.bean.admin.AdminUserCom;
+import com.gree.mall.contest.bean.goods.*;
+import com.gree.mall.contest.commonmapper.CustomGoodsMapper;
+import com.gree.mall.contest.commonmapper.GoodsCheckMapper;
+import com.gree.mall.contest.constant.Constant;
+import com.gree.mall.contest.enums.FreightTypeEnum;
+import com.gree.mall.contest.enums.GoodsTypeEnum;
+import com.gree.mall.contest.enums.UMSDiscountCodeEnum;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.logic.common.CommonLogic;
+import com.gree.mall.contest.logic.user.UserLogic;
+import com.gree.mall.contest.plus.entity.*;
+import com.gree.mall.contest.plus.service.*;
+import com.gree.mall.contest.utils.excel.ExcelUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class GoodsLogic {
+
+    private final CommonLogic commonLogic;
+    private final CustomGoodsMapper customGoodsMapper;
+    private final GoodsService goodsService;
+    private final GoodsSpecService goodsSpecService;
+    private final GoodsTagRelaService goodsTagRelaService;
+    private final GoodsCategoryService goodsCategoryService;
+    private final CarouselMapService carouselMapService;
+    private final GoodsCheckMapper goodsCheckMapper;
+    private final GoodsTemplateService goodsTemplateService;
+    private final CommonFileService commonFileService;
+    private final GoodsPackagePopService goodsPackagePopService;
+    private final GoodsPackageUserRelaService goodsPackageUserRelaService;
+    private final UserLogic userLogic;
+    private final AdminCompanyWechatService adminCompanyWechatService;
+    private final FreightTemplateService freightTemplateService;
+    private final FreightTemplateDetailService freightTemplateDetailService;
+    @Value("${goods.share.limit.percent}")
+    private String percentLimit;
+
+    /**
+     * 商品列表
+     *
+     * @param flag
+     * @param keyword
+     * @param startPrice
+     * @param endPrice
+     * @param startShare
+     * @param endShare
+     * @param goodsSortJson
+     * @param categoryId
+     * @param status
+     * @param pageNum
+     * @param pageSize
+     * @return
+     */
+    public IPage<GoodsSpecBean> page(String flag, String keyword, BigDecimal startPrice, BigDecimal endPrice,
+                                     BigDecimal startShare, BigDecimal endShare,
+                                     String goodsSortJson, String categoryId, Boolean status, List<String> goodsTypes,
+                                     Integer pageNum, Integer pageSize, HttpServletRequest request) {
+
+        //获取当前登录微信企业微信id
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        List<String> companyWechatIds = adminUser.getCompanyWechatIds();
+
+        String sortStr = null;
+        if (goodsSortJson != null && !goodsSortJson.trim().equals("")) {
+            JSONArray goodsSortBeanArray = JSONUtil.parseArray(StringEscapeUtils.unescapeJava(goodsSortJson));
+            sortStr = GoodsSortBean.convertColumn(goodsSortBeanArray);
+        }
+        List<String> categoryIds = new ArrayList<>();
+        if (StringUtils.isNotEmpty(categoryId)) {
+            categoryIds.add(categoryId);
+        }
+        if (CollectionUtils.isEmpty(goodsTypes)) {
+            goodsTypes = new ArrayList<>();
+            goodsTypes.add(GoodsTypeEnum.COMMON.toString());
+        }
+
+        IPage<GoodsSpecBean> goodsSpecBeanIPage = customGoodsMapper.pageList(new Page<>(pageNum, pageSize), flag, keyword, startPrice,
+                endPrice, startShare, endShare, sortStr, categoryIds, status, goodsTypes, companyWechatIds);
+
+        //商品规格
+        for (GoodsSpecBean goodsSpecBean : goodsSpecBeanIPage.getRecords()) {
+            String goodsId = goodsSpecBean.getGoodsId();
+            List<GoodsSpec> list = goodsSpecService.lambdaQuery().eq(GoodsSpec::getGoodsId, goodsId).list();
+            goodsSpecBean.setGoodsSpecs(list);
+        }
+        return goodsSpecBeanIPage;
+    }
+
+
+    /**
+     * 套购商品列表
+     *
+     * @param keyword
+     * @param startPrice
+     * @param endPrice
+     * @param startShare
+     * @param endShare
+     * @param goodsSortJson
+     * @param categoryId
+     * @param status
+     * @param pageNum
+     * @param pageSize
+     * @param request
+     * @return
+     */
+    public IPage<GoodsPackageList> packageList(String keyword, BigDecimal startPrice, BigDecimal endPrice,
+                                               BigDecimal startShare, BigDecimal endShare,
+                                               String goodsSortJson, String categoryId, Boolean status,
+                                               Integer pageNum, Integer pageSize, HttpServletRequest request) {
+
+        //获取当前登录微信企业微信id
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        List<String> companyWechatIds = adminUser.getCompanyWechatIds();
+
+        String sortStr = null;
+        if (goodsSortJson != null && !goodsSortJson.trim().equals("")) {
+            JSONArray goodsSortBeanArray = JSONUtil.parseArray(StringEscapeUtils.unescapeJava(goodsSortJson));
+            sortStr = GoodsSortBean.convertColumn(goodsSortBeanArray);
+        }
+        List<String> categoryIds = new ArrayList<>();
+        if (StringUtils.isNotEmpty(categoryId)) {
+            categoryIds.add(categoryId);
+        }
+
+        IPage<GoodsPackageList> goodsPackageListIPage = customGoodsMapper.queryGoodsPackageList(new Page<>(pageNum, pageSize), keyword, startPrice,
+                endPrice, startShare, endShare, sortStr, categoryIds, status, companyWechatIds);
+
+        return goodsPackageListIPage;
+    }
+
+
+    /**
+     * 根据类型查询商品
+     *
+     * @param categoryIds
+     * @param request
+     * @return
+     */
+    public List<GoodsSpecBean> listbycategory(List<String> categoryIds, HttpServletRequest request) {
+
+        //获取当前登录微信企业微信id
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        List<String> companyWechatIds = adminUser.getCompanyWechatIds();
+
+
+        IPage<GoodsSpecBean> goodsSpecBeanIPage = customGoodsMapper.pageList(new Page<>(1, -1), null, null, null,
+                null, null, null, null, categoryIds, null, null, companyWechatIds);
+        //添加规格
+        List<GoodsSpecBean> records = goodsSpecBeanIPage.getRecords();
+        for (GoodsSpecBean record : records) {
+            List<GoodsSpec> goodsSpecs = goodsSpecService.lambdaQuery()
+                    .eq(GoodsSpec::getGoodsId, record.getGoodsId())
+                    .eq(GoodsSpec::getDel, false)
+                    .list();
+            record.setGoodsSpecs(goodsSpecs);
+        }
+        goodsSpecBeanIPage.setRecords(records);
+        return goodsSpecBeanIPage.getRecords();
+    }
+
+
+    /**
+     * 商品上下架
+     *
+     * @param goodsId
+     * @param status
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void updateStatus(String goodsId, Boolean status) throws RemoteServiceException {
+        goodsService.lambdaUpdate()
+                .eq(Goods::getGoodsId, goodsId)
+                .set(Goods::getStatus, status)
+                .update();
+
+        if (!status) {
+            carouselMapService.lambdaUpdate().eq(CarouselMap::getGoodsId, goodsId).remove();
+        }
+    }
+
+
+    /**
+     * 删除商品
+     *
+     * @param goodsId
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void delete(String goodsId) throws RemoteServiceException {
+        //检查是否在上架状态
+        Long count = goodsService.lambdaQuery()
+                .eq(Goods::getGoodsId, goodsId)
+                .eq(Goods::getStatus, true)
+                .count();
+        if (count > 0) {
+            throw new RemoteServiceException("商品处于上架状态,操作删除失败!");
+        }
+
+        goodsService.lambdaUpdate()
+                .eq(Goods::getGoodsId, goodsId)
+                .remove();
+        goodsSpecService.lambdaUpdate().eq(GoodsSpec::getGoodsId, goodsId).remove();
+    }
+
+
+    /**
+     * 批量修改分类
+     *
+     * @param goodsCategoryUpdateBean
+     */
+    public void updateCategory(GoodsCategoryUpdateBean goodsCategoryUpdateBean) {
+        goodsService.lambdaUpdate()
+                .set(Goods::getCategoryId, goodsCategoryUpdateBean.getCategoryId())
+                .in(Goods::getGoodsId, goodsCategoryUpdateBean.getGoodsIds())
+                .update();
+    }
+
+    /**
+     * 商品详情
+     *
+     * @param goodsId
+     * @return
+     */
+    public GoodsBean detail(String goodsId) throws RemoteServiceException {
+        Goods goods = goodsService.getById(goodsId);
+        List<GoodsSpec> goodsSpecs = goodsSpecService.lambdaQuery()
+                .eq(GoodsSpec::getGoodsId, goodsId)
+                .eq(GoodsSpec::getDel, false)
+                .list();
+
+        //商品库存
+        Integer goodsStock = goodsSpecs.stream().collect(Collectors.summingInt(x -> x.getStockNum()));
+
+        GoodsBean goodsBean = new GoodsBean();
+        if (goods == null) {
+            throw new RemoteServiceException("商品不存在");
+        }
+        BeanUtils.copyProperties(goods, goodsBean);
+        goodsBean.setGoodsSpecs(goodsSpecs);
+        goodsBean.setImages(commonLogic.queryFileByObjId(goods.getGoodsId(), Constant.Img.GOODS_IMG));
+        goodsBean.setStock(goodsStock);
+        List<GoodsTemplate> goodsTemplates = goodsTemplateService.lambdaQuery()
+                .eq(GoodsTemplate::getGoodsId, goodsId)
+                .orderByDesc(GoodsTemplate::getCreateTime)
+                .list();
+        if (goodsTemplates != null && goodsTemplates.size() > 0) {
+            goodsBean.setTemplateId(goodsTemplates.get(0).getTemplateId());
+        }
+        //查询商品标签
+        List<GoodsTagRela> goodsTagRela = goodsTagRelaService.lambdaQuery().eq(GoodsTagRela::getGoodsId, goodsId)
+                .eq(GoodsTagRela::getType, 1).list();
+        if (goodsTagRela.size() > 0) {
+            List<String> tagList = goodsTagRela.stream().map(GoodsTagRela::getGoodsTagName).collect(Collectors.toList());
+            goodsBean.setTags(tagList);
+        }
+
+        List<GoodsTagRela> goodsTagRelas = goodsTagRelaService.lambdaQuery().eq(GoodsTagRela::getGoodsId, goodsId)
+                .eq(GoodsTagRela::getType, 2).list();
+        if (goodsTagRelas.size() > 0) {
+            List<String> tagList = goodsTagRelas.stream().map(GoodsTagRela::getGoodsTagName).collect(Collectors.toList());
+            goodsBean.setTagsLabel(tagList);
+        }
+        if (StringUtils.equals(goodsBean.getGoodsType(), GoodsTypeEnum.PACKAGE.toString())) {
+            //套购商品--指定人员列表
+            goodsBean.setUsers(this.getPackageUseUserList(goodsBean.getGoodsId(), null));
+        }
+        return goodsBean;
+    }
+
+    /**
+     * 套购商品-商品配置列表
+     */
+    public List<GoodsPackageBean> popList(String goodsId, Integer type) {
+        //套购商品
+        Goods goods = goodsService.getById(goodsId);
+        if (!StringUtils.equals(goods.getGoodsType(), GoodsTypeEnum.PACKAGE.toString())) {
+            throw new RemoteServiceException("非套餐商品");
+        }
+
+        //套购商品--商品配置
+        List<GoodsPackagePop> list = goodsPackagePopService.lambdaQuery()
+                .eq(GoodsPackagePop::getGoodsPackageId, goodsId)
+                .eq(GoodsPackagePop::getType, type).list();
+
+        Map<String, List<GoodsPackagePopBean>> map = new LinkedHashMap<>();
+        for (GoodsPackagePop bean : list) {
+            List<GoodsPackagePopBean> goodsPackagePops = map.get(bean.getGoodsId());
+            if (goodsPackagePops == null) {
+                goodsPackagePops = new ArrayList<>();
+            }
+            GoodsPackagePopBean newBean = new GoodsPackagePopBean();
+            BeanUtils.copyProperties(bean, newBean);
+
+            GoodsSpec goodsSpec = goodsSpecService.getById(bean.getGoodsSpecId());
+            newBean.setSpecName(goodsSpec.getName());
+            newBean.setSpecValue(goodsSpec.getSpecValue());
+            newBean.setStock(goodsSpec.getStockNum());
+
+            goodsPackagePops.add(newBean);
+            map.put(bean.getGoodsId(), goodsPackagePops);
+        }
+        //商品
+        List<GoodsPackageBean> goodsList = new ArrayList<>();
+        for (String gdsId : map.keySet()) {
+
+            Goods nGoods = goodsService.getById(gdsId);
+
+            GoodsPackagePopBean goodsPackagePop = map.get(gdsId).get(0);
+            GoodsPackageBean bean = new GoodsPackageBean();
+            bean.setImgUrl(nGoods.getImgUrl());
+            bean.setGoodsName(nGoods.getGoodsName());
+            bean.setGoodsPackagePopList(map.get(gdsId));
+            bean.setSortNum(goodsPackagePop.getSortNum());
+            goodsList.add(bean);
+        }
+        return goodsList;
+    }
+
+
+    /**
+     * 添加商品
+     *
+     * @param goodsBean
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void add(GoodsBean goodsBean, HttpServletRequest request) throws RemoteServiceException {
+        if (StringUtils.equals(goodsBean.getGoodsType(), GoodsTypeEnum.COMMON.toString())
+                && (goodsBean.getGoodsSpecs() == null || goodsBean.getGoodsSpecs().size() == 0)) {
+            //如果是规格没有抛出异常
+            throw new RemoteServiceException("至少要有一个规格!");
+        }
+        if (StringUtils.isNotBlank(goodsBean.getUmsDiscountCode()) && !UMSDiscountCodeEnum.existDiscountCodeByCode(goodsBean.getUmsDiscountCode())) {
+            throw new RemoteServiceException("补贴品类不存在");
+        }
+        //设置企业微信id
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        if (StringUtils.isEmpty(adminUser.getLoginCompanyWechatId())) {
+            throw new RemoteServiceException("无效微信企业id");
+        }
+        goodsBean.setCompanyWechatId(adminUser.getLoginCompanyWechatId());
+        goodsBean.setCompanyName(adminUser.getLoginCompanyName());
+
+        final AdminCompanyWechat companyWechat = adminCompanyWechatService.getById(adminUser.getLoginCompanyWechatId());
+
+        Date creatDate = new Date();
+        List<GoodsSpec> goodsSpecList = goodsBean.getGoodsSpecs();
+        if (CollectionUtils.isNotEmpty(goodsSpecList)) {
+            Collections.sort(goodsSpecList, (o1, o2) -> o1.getPrice().compareTo(o2.getPrice()));
+            goodsBean.setGoodsPrice(goodsSpecList.get(0).getPrice());
+        }
+        goodsBean.setUpdateTime(new Date());
+        goodsBean.setCreateTime(creatDate);
+        goodsService.save(goodsBean);
+
+        if (CollectionUtils.isNotEmpty(goodsBean.getGoodsSpecs())) {
+            goodsSpecList = goodsBean.getGoodsSpecs()
+                    .stream()
+                    .map(goodsSpec -> goodsSpec.setGoodsId(goodsBean.getGoodsId())
+                            .setCompanyWechatId(goodsBean.getCompanyWechatId())
+                            .setCompanyName(goodsBean.getCompanyName())
+                            .setCreateTime(creatDate).setDel(false)
+                            .setShareAmount(limitShareAmount(goodsSpec.getPrice(), goodsSpec.getShareAmount())) //限制金额40%
+                            .setShareAmount(limitShareAmount(goodsSpec.getPrice(), goodsSpec.getSharePercent() != null  //分销比列不为0覆盖分销金额
+                                    && goodsSpec.getSharePercent().compareTo(new Double("0.00")) > 0 ?
+                                    goodsSpec.getPrice().multiply(new BigDecimal(goodsSpec.getSharePercent() / 100.0))
+                                            .setScale(2, BigDecimal.ROUND_DOWN)
+                                    : goodsSpec.getShareAmount()))
+                            .setInnerShareAmount(getInnerShareAmount(goodsSpec))//需最后设置
+                    )
+                    .collect(Collectors.toList());
+        }
+
+        if (StringUtils.isNotEmpty(goodsBean.getTemplateId())) {
+            goodsTemplateService.lambdaUpdate()
+                    .eq(GoodsTemplate::getGoodsId, goodsBean.getGoodsId()).remove();
+            GoodsTemplate goodsTemplate = new GoodsTemplate();
+            goodsTemplate.setGoodsId(goodsBean.getGoodsId());
+            goodsTemplate.setTemplateId(goodsBean.getTemplateId());
+            goodsTemplate.setCreateTime(new Date());
+            goodsTemplate.setCompanyWechatId(goodsBean.getCompanyWechatId());
+            goodsTemplate.setCompanyName(goodsBean.getCompanyName());
+            goodsTemplateService.save(goodsTemplate);
+        }
+
+        //批量保存商品规格
+        if (CollectionUtils.isNotEmpty(goodsSpecList))
+            goodsSpecService.saveBatch(goodsSpecList);
+
+        //保存轮播图
+        if (goodsBean.getImages() != null && goodsBean.getImages().size() > 0) {
+            List<String> imageIdList = goodsBean.getImages().stream().map(CommonFile::getId).collect(Collectors.toList());
+            commonLogic.bindFile(goodsBean.getGoodsId(), Constant.Img.GOODS_IMG, imageIdList);
+        }
+        //save tags
+        this.saveGoodsTagRela(goodsBean.getTags(), goodsBean.getGoodsId(), 1);
+        this.saveGoodsTagRela(goodsBean.getTagsLabel(), goodsBean.getGoodsId(), 2);
+
+        //套购商品处理
+        this.saveGoodsPackage(goodsBean);
+    }
+
+    /**
+     * 保存标签
+     */
+    public void saveGoodsTagRela(List<String> tags, String goodsId, Integer type) {
+
+        if (CollectionUtils.isEmpty(tags)) {
+            goodsTagRelaService.lambdaUpdate().eq(GoodsTagRela::getGoodsId, goodsId).eq(GoodsTagRela::getType, type).remove();
+            return;
+        }
+        //先删后加
+        goodsTagRelaService.lambdaUpdate().eq(GoodsTagRela::getGoodsId, goodsId).eq(GoodsTagRela::getType, type).remove();
+        for (String tag : tags) {
+            GoodsTagRela goodsTagRela = new GoodsTagRela();
+            goodsTagRela.setGoodsTagName(tag);
+            goodsTagRela.setCreateTime(new Date());
+            goodsTagRela.setGoodsId(goodsId);
+            goodsTagRela.setType(type);
+            goodsTagRela.insert();
+        }
+
+    }
+
+
+    /**
+     * 限制最大分账
+     *
+     * @param price
+     * @param shareAmount
+     * @return
+     */
+    private BigDecimal limitShareAmount(BigDecimal price, BigDecimal shareAmount) {
+        BigDecimal shareLimit = price.multiply(new BigDecimal(percentLimit));
+        return shareAmount.compareTo(shareLimit) < 1 ?
+                shareAmount.setScale(2, BigDecimal.ROUND_DOWN)
+                : shareLimit.setScale(2, BigDecimal.ROUND_DOWN);
+    }
+
+    /**
+     * 获取内部分销金额
+     */
+    private BigDecimal getInnerShareAmount(GoodsSpec goodsSpec) {
+        BigDecimal innerShareAmount = goodsSpec.getInnerShareAmount();
+        Double innerSharePercent = goodsSpec.getInnerSharePercent();
+        BigDecimal price = goodsSpec.getPrice();
+
+        //以内部分销比列为准
+        if (innerSharePercent != null && innerSharePercent.compareTo(new Double("0.00")) > 0) {
+            // price * innerSharePercent/100 = 内部分销金额
+            innerShareAmount = price.multiply(new BigDecimal(innerSharePercent / 100.0)).setScale(2, BigDecimal.ROUND_DOWN);
+
+            return limitShareAmount(price, innerShareAmount);
+        }
+        //没有比列有金额以金额为准
+        else if (innerShareAmount != null) {
+            goodsSpec.setInnerSharePercent(new Double("0.00"));
+            return limitShareAmount(price, innerShareAmount);
+        }
+
+        goodsSpec.setInnerSharePercent(goodsSpec.getSharePercent());
+        return goodsSpec.getShareAmount();
+    }
+
+    /**
+     * 编辑商品
+     *
+     * @param goodsBean
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void update(GoodsBean goodsBean, HttpServletRequest request) throws RemoteServiceException {
+
+        //检查是否存在秒杀活动
+        if (StringUtils.equals(goodsBean.getGoodsType(), GoodsTypeEnum.COMMON.toString())
+                && (goodsBean.getGoodsSpecs() == null || goodsBean.getGoodsSpecs().size() == 0)) {
+            throw new RemoteServiceException("至少要有一个规格!");
+        }
+
+        //设置企业微信id
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        if (StringUtils.isEmpty(adminUser.getLoginCompanyWechatId())) {
+            throw new RemoteServiceException("无效微信企业id");
+        }
+        goodsBean.setCompanyWechatId(adminUser.getLoginCompanyWechatId());
+        goodsBean.setCompanyName(adminUser.getLoginCompanyName());
+
+        final AdminCompanyWechat companyWechat = adminCompanyWechatService.getById(adminUser.getLoginCompanyWechatId());
+
+        List<GoodsSpec> notRemoveList = new ArrayList<>();
+        //查找未删除的规格
+        if (CollectionUtils.isNotEmpty(goodsBean.getGoodsSpecs())) {
+            notRemoveList = goodsBean.getGoodsSpecs().stream()
+                    .filter(goodsSpec -> StringUtils.isNotEmpty(goodsSpec.getGoodsSpecId()))
+                    .map(goodsSpec -> goodsSpec.setGoodsId(goodsBean.getGoodsId())
+                            .setCompanyWechatId(goodsBean.getCompanyWechatId())
+                            .setCompanyName(goodsBean.getCompanyName())
+                            .setShareAmount(limitShareAmount(goodsSpec.getPrice(), goodsSpec.getShareAmount()))  //限制金额40%
+                            .setShareAmount(limitShareAmount(goodsSpec.getPrice(),      //比列>0 覆盖分销金额
+                                    goodsSpec.getSharePercent() != null && goodsSpec.getSharePercent().compareTo(new Double("0.00")) > 0 ?
+                                            goodsSpec.getPrice().multiply(new BigDecimal(goodsSpec.getSharePercent() / 100.0)).setScale(2, BigDecimal.ROUND_DOWN)
+                                            : goodsSpec.getShareAmount()
+                            ))
+                            .setInnerShareAmount(getInnerShareAmount(goodsSpec))//需最后设置
+                    )
+                    .collect(Collectors.toList());
+
+
+            //更新主表信息
+            List<GoodsSpec> goodsSpecList = goodsBean.getGoodsSpecs();
+            Collections.sort(goodsSpecList, Comparator.comparing(GoodsSpec::getPrice));
+
+            goodsBean.setGoodsPrice(goodsSpecList.get(0).getPrice());
+        }
+        goodsBean.setUpdateTime(new Date());
+        goodsService.updateById(goodsBean);
+
+        if (StringUtils.isNotEmpty(goodsBean.getTemplateId())) {
+            goodsTemplateService.lambdaUpdate()
+                    .eq(GoodsTemplate::getGoodsId, goodsBean.getGoodsId()).remove();
+            GoodsTemplate goodsTemplate = new GoodsTemplate();
+            goodsTemplate.setGoodsId(goodsBean.getGoodsId());
+            goodsTemplate.setTemplateId(goodsBean.getTemplateId());
+            goodsTemplate.setCreateTime(new Date());
+            goodsTemplate.setCompanyWechatId(goodsBean.getCompanyWechatId());
+            goodsTemplate.setCompanyName(goodsBean.getCompanyName());
+            goodsTemplateService.save(goodsTemplate);
+        }
+
+
+        //未删除的规格id
+        List<String> goodsSpecIds = notRemoveList.stream().map(GoodsSpec::getGoodsSpecId).collect(Collectors.toList());
+
+        //更新轮播图
+        List<String> imageIdList = goodsBean.getImages().stream()
+                .map(CommonFile::getId)
+                .collect(Collectors.toList());
+        commonLogic.bindFile(goodsBean.getGoodsId(), Constant.Img.GOODS_IMG, imageIdList);
+        //更改不在未删除规格list里面的规格id为删除状态
+        goodsSpecService.lambdaUpdate()
+                .eq(GoodsSpec::getGoodsId, goodsBean.getGoodsId())
+                .notIn(!CollectionUtils.isEmpty(goodsSpecIds), GoodsSpec::getGoodsSpecId, goodsSpecIds)
+                .set(GoodsSpec::getDel, true)
+                .update();
+
+        if (notRemoveList.size() > 0) {
+            //更改存在的规格内容
+            goodsSpecService.updateBatchById(notRemoveList);
+        }
+        //查找规格id为空的 添加到从表
+        if (CollectionUtils.isNotEmpty(goodsBean.getGoodsSpecs())) {
+            List<GoodsSpec> addGoodsSpecList = goodsBean.getGoodsSpecs().stream()
+                    .filter(goodsSpec -> StringUtils.isEmpty(goodsSpec.getGoodsSpecId()))
+                    .map(goodsSpec -> goodsSpec.setGoodsId(goodsBean.getGoodsId())
+                            .setCompanyWechatId(goodsBean.getCompanyWechatId())
+                            .setCompanyName(goodsBean.getCompanyName())
+                            .setShareAmount(limitShareAmount(goodsSpec.getPrice(), goodsSpec.getSharePercent() != null
+                                    && goodsSpec.getSharePercent().compareTo(new Double("0.00")) > 0 ?
+                                    goodsSpec.getPrice().multiply(new BigDecimal(goodsSpec.getSharePercent() / 100.0)).setScale(2, BigDecimal.ROUND_DOWN)
+                                    : goodsSpec.getShareAmount()))
+                            .setCreateTime(new Date())
+                            .setInnerShareAmount(getInnerShareAmount(goodsSpec))//需最后设置
+                    )
+                    .collect(Collectors.toList());
+            if (addGoodsSpecList.size() > 0) {
+                goodsSpecService.saveBatch(addGoodsSpecList);
+            }
+        }
+        //save tags
+        this.saveGoodsTagRela(goodsBean.getTags(), goodsBean.getGoodsId(), 1);
+        this.saveGoodsTagRela(goodsBean.getTagsLabel(), goodsBean.getGoodsId(), 2);
+
+        //套购商品处理
+        this.saveGoodsPackage(goodsBean);
+    }
+
+    /**
+     * 添加套购商品
+     */
+    public void saveGoodsPackage(GoodsBean goodsBean) {
+        if (!StringUtils.equals(goodsBean.getGoodsType(), GoodsTypeEnum.PACKAGE.toString())) {
+            return;
+        }
+        if (StringUtils.isEmpty(goodsBean.getPackagePop()) || goodsBean.getPackagePop().indexOf(":") == -1) {
+            throw new RemoteServiceException("请填写正确的比例,例如 2:1");
+        }
+        List<GoodsPackagePop> goodsPackagePops = goodsBean.getGoodsPackagePops();
+        if (CollectionUtils.isEmpty(goodsPackagePops)) {
+            throw new RemoteServiceException("请配置套购的比例商品");
+        }
+        List<GoodsPackagePop> distinctList = goodsPackagePops.stream().distinct().collect(Collectors.toList());
+        if (goodsPackagePops.size() != distinctList.size()) {
+            throw new RemoteServiceException("禁止配置重复的机型");
+        }
+        //计算最低销售价格,最低分佣金额
+        BigDecimal totalMinPrice = BigDecimal.valueOf(0);
+        BigDecimal totalMinShareAmount = BigDecimal.valueOf(0);
+        //判断条件的比例和对应的机型是否合格
+        String[] split = goodsBean.getPackagePop().split(":");
+        for (int i = 1; i <= split.length; i++) {
+            int a = i;
+            long count = goodsPackagePops.stream().filter(v -> v.getType().intValue() == a).count();
+            if (count == 0) {
+                throw new RemoteServiceException("条件比例与商品配置错误");
+            }
+            //判断比例格式是否正确
+            try {
+                int i1 = Integer.parseInt(split[i - 1]);
+            } catch (Exception e) {
+                throw new RemoteServiceException("请填写正确的比例,例如  1:2");
+            }
+            BigDecimal minPrice = null;
+            BigDecimal minShareAmount = null;
+            for (GoodsPackagePop goodsPackagePop : goodsPackagePops) {
+                if (i != goodsPackagePop.getType()) {
+                    continue;
+                }
+                //计算最低销售金额和分佣金额
+                BigDecimal minPrice2 = goodsPackagePop.getPrice().multiply(new BigDecimal(split[goodsPackagePop.getType() - 1])).setScale(2, BigDecimal.ROUND_HALF_UP);
+                if (minPrice == null || minPrice.doubleValue() > minPrice2.doubleValue()) {
+                    minPrice = minPrice2;
+                }
+                BigDecimal minShareAmount2 = minPrice2.multiply(goodsPackagePop.getShareRate()).setScale(2, BigDecimal.ROUND_HALF_UP);
+                if (minShareAmount == null || minShareAmount.doubleValue() > minShareAmount2.doubleValue()) {
+                    minShareAmount = minShareAmount2;
+                }
+            }
+            totalMinPrice = totalMinPrice.add(minPrice);
+            totalMinShareAmount = totalMinShareAmount.add(minShareAmount);
+        }
+
+        //添加配置机型
+        goodsPackagePopService.lambdaUpdate().eq(GoodsPackagePop::getGoodsPackageId, goodsBean.getGoodsId()).remove();
+        for (GoodsPackagePop goodsPackagePop : goodsPackagePops) {
+            goodsPackagePop.setGoodsPackageId(goodsBean.getGoodsId());
+        }
+        goodsPackagePopService.saveBatch(goodsPackagePops);
+        //添加指定人员
+        if (goodsBean.getPackageUserType() == 0 && CollectionUtils.isEmpty(goodsBean.getGoodsPackageUserRelas())) {
+            throw new RemoteServiceException("请选择指定用户");
+        }
+        for (GoodsPackageUserRela rela : goodsBean.getGoodsPackageUserRelas()) {
+            rela.setGoodsId(goodsBean.getGoodsId());
+            rela.setCreateTime(new Date());
+        }
+        goodsBean.setPackageMinAmount(totalMinPrice);
+        goodsBean.setPackageMinShareAmount(totalMinShareAmount);
+        goodsBean.updateById();
+
+        goodsPackageUserRelaService.lambdaUpdate().eq(GoodsPackageUserRela::getGoodsId, goodsBean.getGoodsId()).remove();
+        goodsPackageUserRelaService.saveBatch(goodsBean.getGoodsPackageUserRelas());
+    }
+
+    /**
+     * 分类统计
+     */
+    public GoodsTypeCount countByType(HttpServletRequest request) {
+        //获取当前登录微信企业微信id
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        List<String> companyWechatIds = adminUser.getCompanyWechatIds();
+
+        GoodsTypeCount goodsTypeCount = customGoodsMapper.countByType(companyWechatIds);
+        //查询已售罄的商品数量
+        goodsTypeCount.setYsq(customGoodsMapper.ysq(companyWechatIds));
+        goodsTypeCount.setHdz(customGoodsMapper.countByFlag(companyWechatIds));
+        return goodsTypeCount;
+    }
+
+    /**
+     * 商品上下架
+     *
+     * @param goodsIdList
+     * @param action
+     */
+    public void goodsOnOff(List<String> goodsIdList, Boolean action) {
+        goodsService.lambdaUpdate()
+                .in(Goods::getGoodsId, goodsIdList)
+                .set(Goods::getStatus, action)
+                .update();
+        if (!action) {
+            carouselMapService.lambdaUpdate().in(CarouselMap::getGoodsId, goodsIdList).remove();
+        }
+    }
+
+    /**
+     * 商品模板
+     *
+     * @param goodsTemplateBean
+     * @param request
+     */
+    public void goodsTemplate(GoodsTemplateBean goodsTemplateBean, HttpServletRequest request) {
+
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        if (StringUtils.isEmpty(adminUser.getLoginCompanyWechatId())) {
+            throw new RemoteServiceException("无效微信企业id");
+        }
+
+        if (goodsTemplateBean.getGoodsIdList() == null || goodsTemplateBean.getGoodsIdList().size() < 1) {
+            return;
+        }
+        List<GoodsTemplate> goodsTemplateList = new ArrayList<>();
+        for (String goodsId : goodsTemplateBean.getGoodsIdList()) {
+            GoodsTemplate goodsTemplate = new GoodsTemplate();
+            goodsTemplate.setGoodsId(goodsId);
+            goodsTemplate.setTemplateId(goodsTemplateBean.getTemplateId());
+            goodsTemplate.setCreateTime(new Date());
+            goodsTemplate.setCompanyWechatId(adminUser.getLoginCompanyWechatId());
+            goodsTemplate.setCompanyName(adminUser.getLoginCompanyName());
+            goodsTemplateList.add(goodsTemplate);
+        }
+        goodsTemplateService.saveBatch(goodsTemplateList);
+    }
+
+
+    public Integer secCheck(String goodsId) {
+        Integer count = goodsCheckMapper.checkGoodsSec(goodsId);
+        return count;
+    }
+
+    public List<String> secCheckBatch(List<String> goodsIdList) {
+        List<String> secGoodsIds = goodsCheckMapper.checkGoodsSecBatch(goodsIdList);
+        return secGoodsIds;
+    }
+
+    @Transactional
+    public Goods clone(String goodsId) {
+        Goods goods = goodsService.getById(goodsId);
+        if (goods != null) {
+            goods.setGoodsId(null);
+            goods.setCreateTime(new Date());
+            goods.setPromotionGroup(false);
+            goodsService.save(goods);
+        }
+        List<GoodsSpec> goodsSpecs = goodsSpecService.lambdaQuery()
+                .eq(GoodsSpec::getGoodsId, goodsId)
+                .list();
+        if (goodsSpecs != null && goodsSpecs.size() > 0) {
+            for (GoodsSpec goodsSpec : goodsSpecs) {
+                goodsSpec.setGoodsId(goods.getGoodsId());
+                goodsSpec.setGoodsSpecId(null);
+                goodsSpec.setCreateTime(new Date());
+                goodsSpecService.save(goodsSpec);
+            }
+        }
+        List<CommonFile> commonFiles = commonFileService.lambdaQuery()
+                .eq(CommonFile::getObjId, goodsId)
+                .eq(CommonFile::getObjType, Constant.Img.GOODS_IMG)
+                .list();
+
+        if (commonFiles != null && commonFiles.size() > 0) {
+            for (CommonFile commonFile : commonFiles) {
+                commonFile.setObjId(goods.getGoodsId());
+                commonFile.setId(null);
+                commonFile.setCreateTime(new Date());
+                commonFileService.save(commonFile);
+            }
+        }
+        List<CarouselMap> carouselMaps = carouselMapService.lambdaQuery()
+                .eq(CarouselMap::getGoodsId, goodsId)
+                .list();
+        if (carouselMaps != null && carouselMaps.size() > 0) {
+            for (CarouselMap carouselMap : carouselMaps) {
+                carouselMap.setGoodsId(goods.getGoodsId());
+                carouselMap.setId(null);
+                carouselMap.setCreateTime(new Date());
+                carouselMapService.save(carouselMap);
+            }
+        }
+        List<GoodsTemplate> goodsTemplateList = goodsTemplateService.lambdaQuery()
+                .eq(GoodsTemplate::getGoodsId, goodsId)
+                .list();
+        if (goodsTemplateList != null && goodsTemplateList.size() > 0) {
+            List<GoodsTemplate> saveGoodsTemplateList = new ArrayList<>();
+            goodsTemplateList.forEach(o -> {
+                o.setGoodsId(goods.getGoodsId()).setCreateTime(new Date()).setGoodsTemplateId(null);
+                saveGoodsTemplateList.add(o);
+            });
+            goodsTemplateService.saveBatch(saveGoodsTemplateList);
+        }
+        return goods;
+    }
+
+    @Transactional
+    public void goodsFreight(GoodsFreightBean goodsFreightBean) {
+        goodsService.lambdaUpdate()
+                .in(Goods::getGoodsId, goodsFreightBean.getGoodsIdList())
+                .set(Goods::getFreightTemplateId, goodsFreightBean.getFreightTemplateId())
+                .set(Goods::getFreightType, FreightTypeEnum.TEMPLATE.toString())
+                .update();
+    }
+
+    /**
+     * 用 商品规格的 分销金额 覆盖其 为null的 内部分销金额
+     */
+    public void syncGoodsSpecInnerShareMsg(HttpServletRequest request) {
+        String companyWechatId = commonLogic.getAdminUser(request).getLoginCompanyWechatId();
+        if (StringUtils.isEmpty(companyWechatId)) {
+            throw new RemoteServiceException("运营账号暂无权限操作");
+        }
+
+        customGoodsMapper.syncGoodsSpecInnerShareMsg(companyWechatId);
+
+    }
+
+
+    /**
+     * 修改商品水印和有效时间
+     */
+    public void updateGoodsLogo(List<String> goodsIds, String logo, String logoStartTime, String logoEndTime, boolean isChange) throws ParseException {
+        goodsService.lambdaUpdate()
+                .set(Goods::getLogo, logo)
+                .set(Goods::getLogoStartTime, StringUtils.isNotBlank(logoStartTime) ? DateUtil.parseDate(logoStartTime) : logoStartTime)
+                .set(Goods::getLogoEndTime, StringUtils.isNotBlank(logoEndTime) ? DateUtil.parseDate(logoEndTime) : logoEndTime)
+                .set(isChange, Goods::getMergeImage, null)
+                .in(Goods::getGoodsId, goodsIds)
+                .update();
+
+    }
+
+    /**
+     * 套购商品指定人员列表
+     */
+    public List<User> getPackageUseUserList(String goodsId, String mobile) {
+        List<GoodsPackageUserRela> list = goodsPackageUserRelaService.lambdaQuery()
+                .eq(GoodsPackageUserRela::getGoodsId, goodsId)
+                .like(StringUtils.isNotEmpty(mobile), GoodsPackageUserRela::getMobile, mobile).list();
+        if (CollectionUtils.isEmpty(list)) {
+            return new ArrayList<>();
+        }
+        List<String> userIds = list.stream().map(GoodsPackageUserRela::getUserId).collect(Collectors.toList());
+        List<User> users = userLogic.getById(userIds);
+        return users;
+    }
+
+    /**
+     * 套购商品-导入指定人员
+     */
+    public List<User> importPackageUser(List<Object> list) {
+        if (CollectionUtils.isEmpty(list)) {
+            return new ArrayList<>();
+        }
+        List<String> mobiles = new ArrayList<>();
+        for (Object o : list) {
+            List<Object> row = (List<Object>) o;
+            mobiles.add((String) row.get(1));
+        }
+        List<User> users = userLogic.getByMobile(mobiles);
+        return users;
+    }
+
+    public List<Goods> getById(List<String> goodsIds) {
+        List<Goods> goodsList = goodsService.lambdaQuery().in(Goods::getGoodsId, goodsIds).list();
+        return goodsList;
+    }
+
+    public List<GoodsSpec> getSpec(List<String> goodsIds) {
+        List<GoodsSpec> goodsSpecs = goodsSpecService.lambdaQuery().in(GoodsSpec::getGoodsId, goodsIds).list();
+        return goodsSpecs;
+    }
+
+
+    /**
+     * 外部商品列表
+     *
+     * @param time
+     * @return
+     */
+    public List<GoodsBean> outsideList(Date time) {
+
+        List<GoodsCategory> goodsCategoryList = goodsCategoryService.lambdaQuery().eq(GoodsCategory::getCompanyWechatId, "1").list();
+        Map<String, GoodsCategory> map = goodsCategoryList.stream().collect(Collectors.toMap(GoodsCategory::getCategoryId, Function.identity()));
+
+        List<Goods> list = goodsService.lambdaQuery().ge(time != null, Goods::getUpdateTime, time).eq(Goods::getCompanyWechatId, "1").list();
+        List<GoodsBean> goodsBeans = BeanUtil.copyToList(list, GoodsBean.class);
+        for (GoodsBean goodsBean : goodsBeans) {
+            List<GoodsSpec> list1 = goodsSpecService.lambdaQuery().eq(GoodsSpec::getGoodsId, goodsBean.getGoodsId()).list();
+            goodsBean.setGoodsSpecs(list1);
+
+            GoodsCategory goodsCategory = map.get(goodsBean.getCategoryId());
+            if (goodsCategory != null) {
+                goodsBean.setCategory2(goodsCategory.getName());
+                goodsBean.setIsVr(goodsBean.getGoodsName().indexOf("清洗") > -1);
+            }
+            GoodsCategory parentCategory = map.get(goodsCategory.getParentId());
+            if (parentCategory != null) {
+                goodsBean.setCategory1(parentCategory.getName());
+            }
+
+            goodsBean.setImages(commonLogic.queryFileByObjId(goodsBean.getGoodsId(), Constant.Img.GOODS_IMG));
+
+        }
+
+        return goodsBeans;
+    }
+
+    public void categoryAndGoods(String sourceCompanyId, String targetCompanyId, String targetCompanyName) {
+        final Long count = goodsCategoryService.lambdaQuery()
+                .eq(GoodsCategory::getCompanyWechatId, targetCompanyId)
+                .count();
+        if (count > 0) {
+            throw new RemoteServiceException("数据已存在");
+        }
+        List<GoodsCategory> parentCategoryList = goodsCategoryService.lambdaQuery()
+                .eq(GoodsCategory::getCompanyWechatId, sourceCompanyId)
+                .eq(GoodsCategory::getLevel, 1)
+                .eq(GoodsCategory::getStatus, true)
+                .list();
+
+        // 遍历源父类
+        for (GoodsCategory parentCategory : parentCategoryList) {
+            GoodsCategory copyParentCategory = new GoodsCategory();
+            // 插入目前父类
+            BeanUtils.copyProperties(parentCategory, copyParentCategory);
+            copyParentCategory.setCategoryId(IdWorker.getIdStr())
+                    .setCompanyWechatId(targetCompanyId)
+                    .setCompanyName(targetCompanyName)
+                    .setCreateTime(DateUtil.date())
+                    .insert();
+
+            // 查询源小类
+            List<GoodsCategory> categoryList = goodsCategoryService.lambdaQuery()
+                    .eq(GoodsCategory::getCompanyWechatId, sourceCompanyId)
+                    .eq(GoodsCategory::getParentId, parentCategory.getCategoryId())
+                    .eq(GoodsCategory::getLevel, 2)
+                    .eq(GoodsCategory::getStatus, true)
+                    .list();
+
+            // 遍历源小类
+            for (GoodsCategory goodsCategory : categoryList) {
+                GoodsCategory copyCategory = new GoodsCategory();
+                // 插入目前小类
+                BeanUtils.copyProperties(goodsCategory, copyCategory);
+                copyCategory.setCategoryId(IdWorker.getIdStr())
+                        .setCompanyWechatId(targetCompanyId)
+                        .setCompanyName(targetCompanyName)
+                        .setParentId(copyParentCategory.getCategoryId())
+                        .setCreateTime(DateUtil.date())
+                        .insert();
+
+                // 查询源小类关联商品
+                final List<Goods> goodsList = goodsService.lambdaQuery()
+                        .eq(Goods::getCategoryId, goodsCategory.getCategoryId())
+                        .eq(Goods::getCompanyWechatId, sourceCompanyId)
+                        .eq(Goods::getStatus, true)
+                        .list();
+
+                // 遍历源商品
+                for (Goods goods : goodsList) {
+                    Goods copyGoods = new Goods();
+                    // 插入目前商品
+                    BeanUtils.copyProperties(goods, copyGoods);
+                    copyGoods.setGoodsId(IdWorker.getIdStr())
+                            .setCompanyWechatId(targetCompanyId)
+                            .setCompanyName(targetCompanyName)
+                            .setCategoryId(copyCategory.getCategoryId())
+                            .setSoldNum(0)
+                            .setUmsDiscountCode("")
+                            .setCreateTime(DateUtil.date())
+                            .insert();
+
+                    // 查询源商品关联规格
+                    final List<GoodsSpec> goodsSpecList = goodsSpecService.lambdaQuery()
+                            .eq(GoodsSpec::getGoodsId, goods.getGoodsId())
+                            .eq(GoodsSpec::getCompanyWechatId, sourceCompanyId)
+                            .list();
+
+                    // 遍历源规格
+                    for (GoodsSpec goodsSpec : goodsSpecList) {
+                        GoodsSpec copyGoodsSpec = new GoodsSpec();
+                        // 插入目前规格
+                        BeanUtils.copyProperties(goodsSpec, copyGoodsSpec);
+                        copyGoodsSpec.setGoodsSpecId(IdWorker.getIdStr())
+                                .setGoodsId(copyGoods.getGoodsId())
+                                .setCompanyWechatId(targetCompanyId)
+                                .setCompanyName(targetCompanyName)
+                                .setShareAmount(BigDecimal.ZERO)
+                                .setSharePercent((double) 0)
+                                .setInnerShareAmount(BigDecimal.ZERO)
+                                .setInnerSharePercent((double) 0)
+                                .setStockNum(0)
+                                .setJindName("")
+                                .setJindUnit("")
+                                .setCreateTime(DateUtil.date())
+                                .insert();
+
+                    }
+
+                    // 查询源商品关联说明模板
+//                    final List<GoodsTemplate> goodsTemplateList = goodsTemplateService.lambdaQuery()
+//                            .eq(GoodsTemplate::getGoodsId, goods.getGoodsId())
+//                            .eq(GoodsTemplate::getCompanyWechatId, sourceCompanyId)
+//                            .list();
+//
+//                    // 遍历源关联说明模板
+//                    for (GoodsTemplate goodsTemplate : goodsTemplateList) {
+//                        GoodsTemplate copyGoodsTemplate = new GoodsTemplate();
+//                        // 插入目前规格
+//                        BeanUtils.copyProperties(goodsTemplate, copyGoodsTemplate);
+//                        copyGoodsTemplate.setGoodsTemplateId(IdWorker.getIdStr())
+//                                .setGoodsId(copyGoods.getGoodsId())
+//                                .setCompanyWechatId(targetCompanyId)
+//                                .setCompanyName(targetCompanyName)
+//                                .setCreateTime(DateUtil.date())
+//                                .insert();
+//                    }
+
+                    // 查询源商品关联图片
+                    final List<CommonFile> commonFileList = commonFileService.lambdaQuery()
+                            .eq(CommonFile::getObjId, goods.getGoodsId())
+                            .eq(CommonFile::getObjType, "goods_img_cm")
+                            .orderByAsc(CommonFile::getCreateTime)
+                            .list();
+
+                    // 遍历源规格
+                    for (CommonFile commonFile : commonFileList) {
+                        CommonFile copyCommonFile = new CommonFile();
+                        // 插入目前规格
+                        BeanUtils.copyProperties(commonFile, copyCommonFile);
+                        copyCommonFile.setId(IdWorker.getIdStr())
+                                .setObjId(copyGoods.getGoodsId())
+                                .setCreateTime(DateUtil.date())
+                                .insert();
+
+                    }
+                }
+            }
+        }
+    }
+
+    public void copyFreightTemplate(String sourceCompanyId, String targetCompanyId, String targetCompanyName) {
+        final Long count = freightTemplateService.lambdaQuery()
+                .eq(FreightTemplate::getCompanyWechatId, targetCompanyId)
+                .count();
+        if (count > 0) {
+            throw new RemoteServiceException("数据已存在");
+        }
+        List<FreightTemplate> freightTemplateList = freightTemplateService.lambdaQuery()
+                .eq(FreightTemplate::getCompanyWechatId, sourceCompanyId)
+                .list();
+
+        // 遍历源模板
+        for (FreightTemplate freightTemplate : freightTemplateList) {
+            FreightTemplate copyFreightTemplate = new FreightTemplate();
+            // 插入目前模板
+            BeanUtils.copyProperties(freightTemplate, copyFreightTemplate);
+            copyFreightTemplate.setFreightTemplateId(IdWorker.getIdStr())
+                    .setCompanyWechatId(targetCompanyId)
+                    .setCompanyName(targetCompanyName)
+                    .setCreateTime(DateUtil.date())
+                    .insert();
+
+            // 查询源模板关联
+            List<FreightTemplateDetail> freightTemplateDetailList = freightTemplateDetailService.lambdaQuery()
+                    .eq(FreightTemplateDetail::getCompanyWechatId, sourceCompanyId)
+                    .eq(FreightTemplateDetail::getFreightTemplateId, freightTemplate.getFreightTemplateId())
+                    .list();
+
+            goodsService.lambdaUpdate()
+                    .set(Goods::getFreightTemplateId, copyFreightTemplate.getFreightTemplateId())
+                    .eq(Goods::getFreightTemplateId, freightTemplate.getFreightTemplateId())
+                    .eq(Goods::getCompanyWechatId, targetCompanyId)
+                    .update();
+
+            // 遍历源模板关联
+            for (FreightTemplateDetail detail : freightTemplateDetailList) {
+                FreightTemplateDetail copyDetail = new FreightTemplateDetail();
+                // 插入目前模板关联
+                BeanUtils.copyProperties(detail, copyDetail);
+                copyDetail.setFreightTemplateDetailId(IdWorker.getIdStr())
+                        .setCompanyWechatId(targetCompanyId)
+                        .setCompanyName(targetCompanyName)
+                        .setFreightTemplateId(copyFreightTemplate.getFreightTemplateId())
+                        .setCreateTime(DateUtil.date())
+                        .insert();
+            }
+        }
+    }
+
+    public void export(HttpServletRequest request, HttpServletResponse response, String flag, String keyword,
+                       BigDecimal startPrice, BigDecimal endPrice, BigDecimal startShare, BigDecimal endShare,
+                       String sortJson, String categoryId, Boolean status, List<String> goodsTypes) throws Exception {
+
+        ExcelData excelData = new ExcelData();
+        String[] titles = {"商品名称", "状态", "销售价格", "分销金额", "佣金比例", "内部分销金额", "内部佣金比例", "库存",
+                "政府以旧换新补贴品类", "条形码"};
+
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String fileName = String.format("商品信息导出%s.xlsx", simpleDateFormat.format(new Date()));
+
+        final IPage<GoodsSpecBean> beanIPage = this.page(flag, keyword, startPrice, endPrice,
+                startShare, endShare, sortJson, categoryId, status, goodsTypes, 1, -1, request);
+
+        List<List<Object>> rows = new ArrayList<>();
+        if (CollectionUtil.isNotEmpty(beanIPage.getRecords())) {
+            for (GoodsSpecBean goodsSpecBean : beanIPage.getRecords()) {
+                List<Object> row = new ArrayList<>();
+                rows.add(row);
+
+                String goodsName = goodsSpecBean.getGoodsName();
+
+                row.add(goodsName);
+                row.add(goodsSpecBean.getStatus() ? "上架" : "下架");
+                row.add(goodsSpecBean.getGoodsPrice());
+                row.add(goodsSpecBean.getShareAmount());
+                row.add(goodsSpecBean.getSharePercent());
+                row.add(goodsSpecBean.getInnerShareAmount());
+                row.add(goodsSpecBean.getInnerSharePercent());
+                row.add(goodsSpecBean.getStockNum());
+                row.add(UMSDiscountCodeEnum.findNameByCode(goodsSpecBean.getUmsDiscountCode()));
+                row.add(goodsSpecBean.getBarCode());
+            }
+        }
+
+        excelData.setTitles(Arrays.asList(titles));
+        excelData.setName("商品信息");
+        excelData.setRows(rows);
+        ExcelUtils.exportExcel(request, response, fileName, excelData, -1, null);
+    }
+}

+ 106 - 0
src/main/java/com/gree/mall/contest/logic/order/CommentTagLogic.java

@@ -0,0 +1,106 @@
+package com.gree.mall.contest.logic.order;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.contest.bean.admin.AdminUserCom;
+import com.gree.mall.contest.logic.common.CommonLogic;
+import com.gree.mall.contest.plus.entity.CommentTag;
+import com.gree.mall.contest.plus.entity.OrderComment;
+import com.gree.mall.contest.plus.entity.OrderCommentTag;
+import com.gree.mall.contest.plus.service.CommentTagService;
+import com.gree.mall.contest.plus.service.OrderCommentService;
+import com.gree.mall.contest.plus.service.OrderCommentTagService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class CommentTagLogic {
+
+    private final CommonLogic commonLogic;
+    private final CommentTagService commentTagService;
+    private final OrderCommentService orderCommentService;
+    private final OrderCommentTagService orderCommentTagService;
+
+    /**
+     * 标签列表
+     * @param pageNo
+     * @param pageSize
+     * @return
+     */
+    public IPage<CommentTag> list(HttpServletRequest request, Integer pageNo, Integer pageSize){
+
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+
+        IPage<CommentTag> page = commentTagService.lambdaQuery()
+                .in(CollectionUtil.isNotEmpty(adminUser.getCompanyWechatIds()),CommentTag::getCompanyWechatId,adminUser.getCompanyWechatIds())
+                .orderByDesc(CommentTag::getCreateTime)
+                .page(new Page<>(pageNo, pageSize));
+        return page;
+    }
+
+    /**
+     * 新增标签
+     */
+    public void add(String tag,HttpServletRequest request){
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        CommentTag commentTag = new CommentTag();
+        commentTag.setTag(tag);
+        commentTag.setCompanyWechatId(adminUser.getLoginCompanyWechatId());
+        commentTag.setCreateTime(new Date());
+        commentTag.insert();
+    }
+
+    /**
+     * 修改标签
+     */
+    public void update(String commentTagId,String tag){
+        CommentTag commentTag = new CommentTag();
+        commentTag.setTag(tag);
+        commentTag.setCommentTagId(commentTagId);
+        commentTag.updateById();
+    }
+
+    /**
+     * 删除标签
+     */
+    public void delete(String commentTagId){
+        commentTagService.removeById(commentTagId);
+    }
+
+    /**
+     * 标签列表
+     */
+    public List<String> getCommentTags(String orderId){
+        List<OrderCommentTag> list = orderCommentTagService.lambdaQuery().eq(OrderCommentTag::getOrderId, orderId).list();
+        if(list.size() == 0){
+            return null;
+        }
+        return list.stream().map(OrderCommentTag::getTag).collect(Collectors.toList());
+    }
+
+    /**
+     * 评价内容
+     */
+    public OrderComment getOrderComment(String orderId){
+        return orderCommentService.lambdaQuery().eq(OrderComment::getOrderId,orderId).one();
+    }
+
+
+    /**
+     * 显示评价
+     */
+    public void updateShow(String orderId,Boolean isShow){
+        orderCommentService.lambdaUpdate().set(OrderComment::getIsShow,isShow).eq(OrderComment::getOrderId,orderId).update();
+    }
+
+
+}

+ 943 - 0
src/main/java/com/gree/mall/contest/logic/order/OrderLogic.java

@@ -0,0 +1,943 @@
+package com.gree.mall.contest.logic.order;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.IdUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.gree.mall.contest.bean.ExcelData;
+import com.gree.mall.contest.bean.admin.AdminUserCom;
+import com.gree.mall.contest.bean.order.BatchRemarkBean;
+import com.gree.mall.contest.bean.order.DeliverGoodsBean;
+import com.gree.mall.contest.bean.order.OrderDetailBean;
+import com.gree.mall.contest.bean.order.OrderDetailListBean;
+import com.gree.mall.contest.commonmapper.CoustomUserCouponMapper;
+import com.gree.mall.contest.commonmapper.CustomWebsitMapper;
+import com.gree.mall.contest.commonmapper.OrderMapper;
+import com.gree.mall.contest.constant.Constant;
+import com.gree.mall.contest.enums.OrderShareStatusEnum;
+import com.gree.mall.contest.enums.OrderStatusEnum;
+import com.gree.mall.contest.enums.RefundFlagEnum;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.logic.ExpressLogic;
+import com.gree.mall.contest.logic.StorageLogic;
+import com.gree.mall.contest.logic.common.CommonLogic;
+import com.gree.mall.contest.logic.common.WechatLogic;
+import com.gree.mall.contest.logic.user.MsgSubscriptLogic;
+import com.gree.mall.contest.logic.user.UserLogic;
+import com.gree.mall.contest.plus.entity.*;
+import com.gree.mall.contest.plus.service.*;
+import com.gree.mall.contest.utils.ArithUtils;
+import com.gree.mall.contest.utils.excel.ExcelUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.springframework.beans.BeanUtils;
+import org.springframework.integration.redis.util.RedisLockRegistry;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class OrderLogic {
+
+    private final OrderShareLogic orderShareLogic;
+    private final StorageLogic storageLogic;
+    private final MsgSubscriptLogic msgSubscriptLogic;
+    private final UserLogic userLogic;
+    private final WechatLogic wechatLogic;
+    private final RedisLockRegistry redisLockRegistry;
+    private final CommentTagLogic commentTagLogic;
+    private final CommonLogic commonLogic;
+    private final GoodsService goodsService;
+    private final OrderInfoService orderInfoService;
+    private final OrderDetailService orderDetailService;
+    private final AdminUserService adminUserService;
+    private final OrderRefundCliaimsService orderRefundCliaimsService;
+    private final OrderShareService orderShareService;
+    private final OrderRefundService orderRefundService;
+    private final UserCouponService userCouponService;
+    private final CoustomUserCouponMapper coustomUserCouponMapper;
+    private final CustomWebsitMapper customWebsitMapper;
+    private final ExpressInfoService expressInfoService;
+    private final OrderRequestService orderRequestService;
+    private final UserService userService;
+    private final OrderMapper orderMapper;
+    private final ExpressLogic expressLogic;
+    private final AdminCompanyWechatService adminCompanyWechatService;
+
+    /**
+     * 订单列表
+     *
+     * @return
+     */
+    public IPage<OrderDetailBean> list(HttpServletRequest request, String userId, String orderId, String productName, String userName, String phone,
+                                       String exchangeCode, String orderStatus, String startCreateTime, String endCreateTime, String startPayTime,
+                                       String endPayTime, String websitId,
+                                       Integer pageNum, Integer pageSize,
+                                       String isNegative, String abnormalDispatch, String workerOrderNo, String goodsId
+    ) {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+
+        List<String> orderIds = new ArrayList<>();
+        if (StringUtils.isNotEmpty(workerOrderNo)) {
+            List<OrderRequest> orderRequests = orderRequestService.lambdaQuery().eq(OrderRequest::getWorkerOrderNo, workerOrderNo).list();
+            orderIds = orderRequests.stream().map(OrderRequest::getOrderId).collect(Collectors.toList());
+        }
+
+        IPage page = orderInfoService.lambdaQuery()
+                .in(CollectionUtil.isNotEmpty(adminUser.getCompanyWechatIds()), OrderInfo::getCompanyWechatId, adminUser.getCompanyWechatIds())
+                ////.//in(CollectionUtil.isNotEmpty(adminUser.getAdminWebsitIds()),OrderInfo::getWebsitId,adminUser.getAdminWebsitIds())
+                .eq(StringUtils.isNotEmpty(userId), OrderInfo::getUserId, userId)
+                .eq(StringUtils.isNotEmpty(goodsId), OrderInfo::getPromotionPackageGoodsId, goodsId)
+                .like(StringUtils.isNotEmpty(exchangeCode), OrderInfo::getExchangeCode, exchangeCode)
+                .like(StringUtils.isNotEmpty(orderId), OrderInfo::getOrderId, orderId)
+                .like(StringUtils.isNotEmpty(productName), OrderInfo::getOrderTitle, productName)
+                .in(CollectionUtil.isNotEmpty(orderIds), OrderInfo::getOrderId, orderIds)
+                .eq(StringUtils.isNotEmpty(websitId), OrderInfo::getWebsitId, websitId)
+                .and(StringUtils.isNotEmpty(userName), v -> v.like(OrderInfo::getUserName, userName).or().like(OrderInfo::getReceUserName, userName))
+                .and(StringUtils.isNotEmpty(phone), v -> v.like(OrderInfo::getPhone, phone).or().like(OrderInfo::getRecePhone, phone).or().like(OrderInfo::getWorkerPhone, phone))
+                //      .in(!(adminWebsitBean.getType() && org.apache.commons.lang3.StringUtils.isEmpty(websitId)), OrderInfo::getWebsitNumber, websitNoList)
+                .eq(StringUtils.isNotEmpty(orderStatus), OrderInfo::getOrderStatus, orderStatus)
+                .between(StringUtils.isNotEmpty(startCreateTime) && StringUtils.isNotEmpty(endCreateTime), OrderInfo::getCreateTime, startCreateTime, endCreateTime + " 23:59:59")
+                .between(StringUtils.isNotEmpty(startPayTime) && StringUtils.isNotEmpty(endPayTime), OrderInfo::getPayTime, startPayTime, endPayTime + " 23:59:59")
+                .and(StringUtils.isNotEmpty(isNegative) && isNegative.trim().equals("2"),
+                        v -> v.gt(OrderInfo::getCommentExpress, 2).gt(OrderInfo::getCommentService, 2).gt(OrderInfo::getCommentGoods, 2))
+                .and(StringUtils.isNotEmpty(isNegative) && isNegative.trim().equals("1"), v -> v
+                        .gt(OrderInfo::getCommentExpress, 0)
+                        .gt(OrderInfo::getCommentService, 0)
+                        .gt(OrderInfo::getCommentGoods, 0)
+                        .and(vv -> vv
+                                .lt(OrderInfo::getCommentExpress, 3)
+                                .or().lt(OrderInfo::getCommentService, 3)
+                                .or().lt(OrderInfo::getCommentGoods, 3)
+                        )
+                )
+                .and(StringUtils.isNotEmpty(isNegative) && isNegative.trim().equals("0"),
+                        v -> v.eq(OrderInfo::getCommentExpress, 0).eq(OrderInfo::getCommentService, 0).eq(OrderInfo::getCommentGoods, 0))
+                .and(StringUtils.isNotEmpty(isNegative) && isNegative.trim().equals("3"),
+                        v -> v.gt(OrderInfo::getCommentExpress, 0).gt(OrderInfo::getCommentService, 0).gt(OrderInfo::getCommentGoods, 0))
+                .orderByDesc(OrderInfo::getCreateTime)
+                .page(new Page<>(pageNum, pageSize));
+
+        List<OrderDetailBean> list = new ArrayList<>();
+        for (Object o : page.getRecords()) {
+            OrderInfo orderInfo = (OrderInfo) o;
+            OrderDetailBean orderDetailBean = new OrderDetailBean();
+            BeanUtils.copyProperties(orderInfo, orderDetailBean);
+            //查询订单详情
+            List<OrderDetail> orderDetails = orderDetailService.lambdaQuery().eq(OrderDetail::getOrderId, orderInfo.getOrderId()).list();
+            OrderRefund orderRefund = orderRefundService.lambdaQuery()
+                    .eq(OrderRefund::getOrderId, orderInfo.getOrderId())
+                    .ne(OrderRefund::getRemark, "").last("limit 1").one();
+
+            Long count = orderRequestService.lambdaQuery().eq(OrderRequest::getOrderId, orderInfo.getOrderId()).count();
+            orderDetailBean.setToWorkOrder(count > 0);
+            orderDetailBean.setOrderDetails(orderDetails);
+            orderDetailBean.setMerchantRemark(orderRefund == null ? "" : orderRefund.getRemark());
+            list.add(orderDetailBean);
+        }
+        page.setRecords(list);
+        return page;
+    }
+
+    public List<OrderDetailBean> list(HttpServletRequest request, String userId, String orderId, String productName, String userName, String phone, String orderStatus,
+                                      String startCreateTime, String endCreateTime, String startPayTime, String endPayTime, String websitId) {
+
+        List<OrderInfo> orderList = orderInfoService.lambdaQuery()
+                .eq(StringUtils.isNotEmpty(userId), OrderInfo::getUserId, userId)
+                .like(StringUtils.isNotEmpty(orderId), OrderInfo::getOrderId, orderId)
+                .like(StringUtils.isNotEmpty(productName), OrderInfo::getOrderTitle, productName)
+                .like(StringUtils.isNotEmpty(userName), OrderInfo::getUserName, userName)
+                .like(StringUtils.isNotEmpty(phone), OrderInfo::getPhone, phone)
+                .eq(StringUtils.isNotEmpty(orderStatus), OrderInfo::getOrderStatus, orderStatus)
+                .between(StringUtils.isNotEmpty(startCreateTime) && StringUtils.isNotEmpty(endCreateTime), OrderInfo::getCreateTime, startCreateTime, endCreateTime + " 23:59:59")
+                .between(StringUtils.isNotEmpty(startPayTime) && StringUtils.isNotEmpty(endPayTime), OrderInfo::getPayTime, startPayTime, endPayTime + " 23:59:59")
+                .orderByDesc(OrderInfo::getCreateTime)
+                .list();
+
+        List<OrderDetailBean> list = new ArrayList<>();
+        for (Object o : orderList) {
+            OrderInfo orderInfo = (OrderInfo) o;
+            OrderDetailBean orderDetailBean = new OrderDetailBean();
+            BeanUtils.copyProperties(orderInfo, orderDetailBean);
+            //查询订单详情
+            List<OrderDetail> orderDetails = orderDetailService.lambdaQuery().eq(OrderDetail::getOrderId, orderInfo.getOrderId()).list();
+            orderDetailBean.setOrderDetails(orderDetails);
+            list.add(orderDetailBean);
+        }
+        return list;
+    }
+
+    /**
+     * 订单备注
+     */
+    public void remark(String orderId, String remark) {
+        orderInfoService.lambdaUpdate()
+                .set(OrderInfo::getRemark, remark)
+                .eq(OrderInfo::getOrderId, orderId).update();
+    }
+
+    /**
+     * 取消订单
+     */
+    public void cancel(String orderId) throws RemoteServiceException, WxPayException {
+        OrderInfo orderInfo = orderInfoService.getById(orderId);
+        if (!orderInfo.getOrderStatus().equals(OrderStatusEnum.NOPAY.toString())) {
+            throw new RemoteServiceException("订单已支付,不可取消");
+        }
+//        if(!orderInfo.getOrderStatus().equals(OrderStatusEnum.NOPAY.toString())) {
+//
+//            log.info("【退款开始:】退款金额{}", orderInfo.getPayAmount().doubleValue());
+//            wechatLogic.refund(orderInfo.getOrderId(), orderInfo.getOrderId()+"T", orderInfo.getPayAmount().doubleValue()
+//                    , orderInfo.getPayAmount().doubleValue());
+//
+//            orderShareLogic.reloadAmount(orderId, null);
+//        }
+        this.updateOrderStatus(orderId, OrderStatusEnum.CLOSE.toString());
+    }
+
+    /**
+     * 确定收款
+     */
+    public void ackPay(String orderId) {
+        return;
+//        this.updateOrderStatus(orderId, OrderStatusEnum.DFH.toString());
+    }
+
+    /**
+     * 主动退款
+     */
+    @Transactional
+    public BigDecimal refund(String orderDetailId, int num, String refundPassword) throws Exception {
+        if (num < 1) {
+            throw new RemoteServiceException("退款数量不能小于1");
+        }
+        OrderDetail orderDetail = orderDetailService.getById(orderDetailId);
+        //1=非团购商品  2=团购商品
+        int flag = StringUtils.isNotEmpty(orderDetail.getPromotionGroupId()) ? 2 : 1;
+
+        String orderId = orderDetail.getOrderId();
+
+        Long count = orderShareService.lambdaQuery()
+                .eq(OrderShare::getOrderId, orderId)
+                .eq(OrderShare::getStatus, OrderShareStatusEnum.OVER.toString())
+                .count();
+
+        if (count > 0) {
+            throw new RemoteServiceException("已结算订单,不能退款");
+        }
+        if (num + orderDetail.getRefundNum() > orderDetail.getNum()) {
+            throw new RemoteServiceException("退款数量异常");
+        }
+        //退款的数量占比
+        double div = ArithUtils.div(num, orderDetail.getNum(), 4);
+        double mul = ArithUtils.mul(orderDetail.getShareAmount().doubleValue(), div, 2);
+        //退款的金额
+        BigDecimal totalShareAmount = BigDecimal.valueOf(mul);
+        //计算需要退款的金额
+        BigDecimal refundAmount = BigDecimal.valueOf(ArithUtils.mul(orderDetail.getPayAmount().doubleValue(), div, 2));
+        OrderInfo orderInfo = orderInfoService.getById(orderId);
+        if (orderInfo.getOrderStatus().equals(OrderStatusEnum.DFH.toString()) ||
+                (orderInfo.getOrderStatus().equals(OrderStatusEnum.REFUND.toString()) &&
+                        StringUtils.isEmpty(orderInfo.getLogisticsNo()))) {//待发货状态退运费
+            BigDecimal refundFreight = BigDecimal.valueOf(ArithUtils.mul(orderDetail.getFreight().doubleValue(), div, 2));
+            if (refundFreight == null) {
+                refundFreight = new BigDecimal("0.00");
+            }
+            refundAmount = refundAmount.add(refundFreight);
+        }
+
+        orderDetail.setRefundNum(orderDetail.getRefundNum() + num);
+        orderDetail.setRefundAmount(orderDetail.getRefundAmount().add(refundAmount));
+        orderDetail.setRefundTime(new Date());
+        orderDetail.setRefund(orderDetail.getNum() - orderDetail.getRefundNum() == 0);
+        orderDetail.updateById();
+
+
+        int totalNum = orderInfo.getTotalNum();
+        List<OrderDetail> orderDetails = orderDetailService.lambdaQuery()
+                .eq(OrderDetail::getOrderId, orderId)
+                .list();
+        int refundNum = orderDetails.stream().filter(OrderDetail::getRefund).collect(Collectors.reducing(0, OrderDetail::getRefundNum, (i, j) -> i + j));
+        if (totalNum - refundNum == 0) {
+            String userCouponId = orderInfo.getUserCouponId();
+            orderInfoService.lambdaUpdate()
+                    .eq(OrderInfo::getOrderId, orderId)
+                    .set(OrderInfo::getOrderStatus, OrderStatusEnum.CLOSE.toString())
+                    .set(OrderInfo::getRefundFlag, RefundFlagEnum.ALL.toString())
+                    .update();
+            if (StringUtils.isNotEmpty(userCouponId)) {
+                UserCoupon userCoupon = userCouponService.getById(orderInfo.getUserCouponId());
+                if (userCoupon.getSelfUse() != null && userCoupon.getSelfUse()) {
+                    //todo sql处理,数量加一,删除指定记录
+                    //coustomUserCouponMapper.increaseLeftTimes(userCoupon.getTransferor());
+                    userCouponService.removeById(userCouponId);
+                } else {
+                    userCouponService.lambdaUpdate()
+                            .eq(UserCoupon::getId, userCouponId)
+                            .set(UserCoupon::getStatus, false)
+                            .update();
+                }
+            }
+
+        } else {
+            orderInfoService.lambdaUpdate()
+                    .eq(OrderInfo::getOrderId, orderId)
+                    .set(OrderInfo::getRefundFlag, RefundFlagEnum.PARTLY.toString())
+                    .update();
+        }
+        log.info("【退款开始:】重置flag={}的结算金额,需要减掉的金额{},国补金额{}", flag, totalShareAmount.doubleValue(), orderInfo.getCouponMerchantContribute().doubleValue());
+        orderShareLogic.reloadAmount(orderId, totalShareAmount, flag);
+        log.info("【退款开始:】退款金额{}", refundAmount);
+
+        wechatLogic.refund(orderId, orderId + IdUtil.simpleUUID(), orderInfo.getPayAmount().doubleValue()
+                , refundAmount.doubleValue(), orderInfo.getCompanyWechatId());
+
+        return refundAmount;
+    }
+
+    /**
+     * 理赔列表
+     */
+    public List<OrderRefundCliaims> cliaimsList(String orderId) {
+        List<OrderRefundCliaims> list = orderRefundCliaimsService.lambdaQuery()
+                .eq(OrderRefundCliaims::getOrderId, orderId).orderByDesc(OrderRefundCliaims::getCreateTime).list();
+        return list;
+    }
+
+    /**
+     * 理赔
+     */
+    @Transactional
+    public BigDecimal refundCliaims(String orderDetailId, int num, BigDecimal refundAmount, String adminUserId,
+                                    String remark, String refundPassword) throws Exception {
+//        if (num < 1) {
+//            throw new RemoteServiceException("数量错误");
+//        }
+        if (refundAmount.compareTo(new BigDecimal("0.00")) < 1) {
+            throw new RemoteServiceException("金额错误");
+        }
+        if (StringUtils.isEmpty(remark)) {
+            throw new RemoteServiceException("请填写理赔原因");
+        }
+        AdminUser adminUser = adminUserService.getById(adminUserId);
+        OrderDetail orderDetail = orderDetailService.getById(orderDetailId);
+        String orderId = orderDetail.getOrderId();
+
+        if (orderDetail.getNum() < orderDetail.getRefundNum() + num) {
+            throw new RemoteServiceException("可理赔商品数量不足");
+        }
+        if (orderDetail.getPayAmount().add(orderDetail.getFreight()).doubleValue() < (orderDetail.getRefundAmount().add(refundAmount).doubleValue())) {
+            throw new RemoteServiceException("可理赔金额不足");
+        }
+
+        //退款的数量占比
+        double div = ArithUtils.div(num, orderDetail.getNum(), 4);
+        double mul = ArithUtils.mul(orderDetail.getShareAmount().doubleValue(), div, 2);
+        //退款的金额
+        BigDecimal totalShareAmount = BigDecimal.valueOf(mul);
+        //计算需要退款的金额
+        orderDetail.setRefundNum(orderDetail.getRefundNum() + num);
+        orderDetail.setRefundAmount(orderDetail.getRefundAmount().add(refundAmount));
+        orderDetail.setRefundTime(new Date());
+        orderDetail.setRefund(orderDetail.getNum() - orderDetail.getRefundNum() == 0);
+        orderDetail.updateById();
+
+        //记录理赔数据
+        OrderRefundCliaims orderRefundCliaims = new OrderRefundCliaims();
+        orderRefundCliaims.setCreateTime(new Date());
+        orderRefundCliaims.setRefundAmount(refundAmount);
+        orderRefundCliaims.setNum(num);
+        orderRefundCliaims.setOrderId(orderId);
+        orderRefundCliaims.setOrderDetailId(orderDetailId);
+        orderRefundCliaims.setGoodsId(orderDetail.getGoodsId());
+        orderRefundCliaims.setGoodsName(orderDetail.getGoodsName());
+        orderRefundCliaims.setGoodsSpecId(orderDetail.getGoodsSpecId());
+        orderRefundCliaims.setGoodsSpecName(orderDetail.getGoodsSpecName());
+        orderRefundCliaims.setGoodsSpecValue(orderDetail.getGoodsSpecValue());
+        orderRefundCliaims.setOperatorUser(adminUser.getUserName());
+        orderRefundCliaims.setRemark(remark);
+        orderRefundCliaims.insert();
+
+        OrderInfo orderInfo = orderInfoService.getById(orderDetail.getOrderId());
+        int totalNum = orderInfo.getTotalNum();
+        List<OrderDetail> orderDetails = orderDetailService
+                .lambdaQuery()
+                .eq(OrderDetail::getOrderId, orderId)
+                .list();
+        int refundNum = orderDetails.stream().filter(OrderDetail::getRefund).collect(Collectors.reducing(0, OrderDetail::getRefundNum, (i, j) -> i + j));
+        if (totalNum - refundNum == 0) {
+            String userCouponId = orderInfo.getUserCouponId();
+            orderInfoService.lambdaUpdate()
+                    .eq(OrderInfo::getOrderId, orderId)
+                    .set(OrderInfo::getOrderStatus, OrderStatusEnum.CLOSE.toString())
+                    .set(OrderInfo::getUserCouponId, "")
+                    .set(OrderInfo::getRefundFlag, RefundFlagEnum.ALL.toString())
+                    .update();
+            if (StringUtils.isNotEmpty(userCouponId)) {
+                UserCoupon userCoupon = userCouponService.getById(orderInfo.getUserCouponId());
+                if (userCoupon.getSelfUse() != null && userCoupon.getSelfUse()) {
+                    //todo sql处理,数量加一,删除指定记录
+                    coustomUserCouponMapper.increaseLeftTimes(userCoupon.getTransferor());
+                    userCouponService.removeById(userCouponId);
+                } else {
+                    userCouponService.lambdaUpdate()
+                            .eq(UserCoupon::getId, userCouponId)
+                            .set(UserCoupon::getStatus, false)
+                            .update();
+                }
+            }
+        } else {
+            orderInfoService.lambdaUpdate()
+                    .eq(OrderInfo::getOrderId, orderId)
+                    .set(OrderInfo::getRefundFlag, RefundFlagEnum.PARTLY.toString())
+                    .update();
+        }
+
+        //1=非团购商品 2=团购商品
+        if (totalShareAmount.doubleValue() > 0) {
+            int flag = StringUtils.isNotEmpty(orderDetail.getPromotionGroupId()) ? 2 : 1;
+            log.info("【退款开始:】重置结算,order_id={},flag={}金额,需要减掉的金额{}", orderInfo.getOrderId(), flag, totalShareAmount.doubleValue());
+            orderShareLogic.reloadAmount(orderId, totalShareAmount, flag);
+        }
+        log.info("【退款开始:】退款金额{},order_id={}", refundAmount, orderInfo.getOrderId());
+
+        wechatLogic.refund(orderId, orderId + IdUtil.simpleUUID(), orderInfo.getPayAmount().doubleValue()
+                , refundAmount.doubleValue(), orderInfo.getCompanyWechatId());
+
+        return refundAmount;
+    }
+
+
+    /**
+     * 修改价格
+     */
+    public void updatePrice(String orderId, BigDecimal price) throws RemoteServiceException {
+        OrderInfo orderInfo = orderInfoService.getById(orderId);
+        if (!orderInfo.getOrderStatus().equals(OrderStatusEnum.NOPAY.toString())) {
+            throw new RemoteServiceException("非待付款订单不可修改");
+        }
+        if (orderInfo.getPayAmount().doubleValue() < price.doubleValue()) {
+            throw new RemoteServiceException("不可将价格修改的更贵");
+        }
+        if (orderInfo.getPayAmount().doubleValue() < orderInfo.getFreight().doubleValue()) {
+            throw new RemoteServiceException("不可将价格修改的比运费小");
+        }
+        orderInfo.setPayAmount(price);
+        orderInfo.updateById();
+    }
+
+    /**
+     * 修改收货人信息
+     */
+    public void updateReceInfo(OrderInfo orderInfo) throws RemoteServiceException {
+        if (orderInfo.getOrderStatus().equals(OrderStatusEnum.OVER.toString())
+                || orderInfo.getOrderStatus().equals(OrderStatusEnum.OVER.toString())) {
+            throw new RemoteServiceException("已发货、已完成订单不可修改");
+        }
+        orderInfo.updateById();
+    }
+
+    /**
+     * 批量设置备注
+     */
+    public void batchRemark(BatchRemarkBean batchRemarkBean) throws RemoteServiceException {
+        if (CollectionUtil.isEmpty(batchRemarkBean.getOrderIds())) {
+            throw new RemoteServiceException("订单号不能为空");
+        }
+        if (StringUtils.isEmpty(batchRemarkBean.getRemark())) {
+            return;
+        }
+        orderInfoService.lambdaUpdate()
+                .set(OrderInfo::getRemark, batchRemarkBean.getRemark())
+                .in(OrderInfo::getOrderId, batchRemarkBean.getOrderIds())
+                .update();
+    }
+
+    /**
+     * 发货
+     */
+    @Transactional
+    public void deliverGoods(String orderId, String logisticsNo, String companyCode, String storageId, Boolean workOrder, Boolean exchange) throws Exception {
+        OrderInfo orderInfo = orderInfoService.getById(orderId);
+        final AdminCompanyWechat companyWechat = adminCompanyWechatService.getById(orderInfo.getCompanyWechatId());
+        User user = userLogic.getById(orderInfo.getUserId());
+        if (!orderInfo.getOrderStatus().equals(OrderStatusEnum.DFH.toString())) {
+            throw new RemoteServiceException("非待发货订单不可发货");
+        }
+        //发货商
+        Storage detail = storageLogic.detail(storageId);
+        String companyName = expressLogic.expressCompanyName(companyCode);
+        orderInfo.setLogisticsNo(logisticsNo);
+        orderInfo.setCompanyCode(companyCode);
+        orderInfo.setCompanyName(companyName);
+        orderInfo.setOrderStatus(OrderStatusEnum.YFH.toString());
+        orderInfo.setStorageName(detail.getStorageName());
+        orderInfo.setStorageAddress(detail.getStorageAddress());
+        orderInfo.setStoragePhone(detail.getStorageMobile());
+        orderInfo.setDeliverTime(new Date());
+        orderInfo.setWorkOrder(workOrder);
+        orderInfo.setExchangeOrder(exchange);
+        orderInfo.updateById();
+
+        orderShareLogic.updateOrderStatus(orderId, OrderStatusEnum.YFH.toString());
+
+        //发货通知
+        if (user != null) {
+            msgSubscriptLogic.sendFhNotice(user.getUserId(), user.getOpenId(), orderInfo.getOrderId(), orderInfo.getPayAmount()
+                    , companyName, orderInfo.getLogisticsNo());
+        }
+    }
+
+
+    //@Transactional
+    public void deliverBatchGoods(HttpServletRequest request, MultipartFile file) throws Exception {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+
+        List<Object> datas = ExcelUtils.importExcel(file);
+        List<DeliverGoodsBean> deliverGoodsBeanList = new ArrayList<>();
+        for (Object object : datas) {
+            List<String> row = (List<String>) object;
+            DeliverGoodsBean deliverGoodsBean = new DeliverGoodsBean();
+            deliverGoodsBean.setOrderId(row.get(0));
+            deliverGoodsBean.setExpressCorp(row.get(1));
+            deliverGoodsBean.setLogisticsNo(row.get(2));
+            deliverGoodsBean.setWarehouse(row.get(3));
+            deliverGoodsBean.setSend("是".equals(row.get(4)));
+            deliverGoodsBean.setExchangeOrder("是".equals(row.get(5)));
+            deliverGoodsBeanList.add(deliverGoodsBean);
+        }
+        //预检查
+        String check = preCheck(adminUser, deliverGoodsBeanList);
+        if (StringUtils.isNotEmpty(check)) {
+            throw new RemoteServiceException(check);
+        }
+        for (DeliverGoodsBean deliverGoodsBean : deliverGoodsBeanList) {
+            Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER + ":" + deliverGoodsBean.getOrderId());
+            try {
+                if (!obtain.tryLock(30, TimeUnit.SECONDS)) {
+                    throw new RemoteServiceException("请勿重复操作发货,请稍后再试");
+                }
+                updateDeliverItem(adminUser, deliverGoodsBean);
+            } finally {
+                obtain.unlock();
+            }
+        }
+
+    }
+
+    private String preCheck(AdminUserCom adminUser, List<DeliverGoodsBean> deliverGoodsBeanList) {
+        String loginCompanyWechatId = adminUser.getLoginCompanyWechatId();
+        if (StringUtils.isEmpty(loginCompanyWechatId)) {
+            throw new RemoteServiceException("无效微信企业id");
+        }
+
+        StringBuffer sb = new StringBuffer();
+        int index = 0;
+        for (DeliverGoodsBean deliverGoodsBean : deliverGoodsBeanList) {
+            ++index;
+            String orderId = deliverGoodsBean.getOrderId();
+            if (StringUtils.isEmpty(orderId)) {
+                sb.append(String.format("第%d条数据订单号不能为空\n", index));
+                continue;
+            }
+            OrderInfo orderInfo = orderInfoService.lambdaQuery()
+                    .eq(OrderInfo::getOrderId, orderId)
+                    .eq(OrderInfo::getOrderStatus, OrderStatusEnum.DFH.toString())
+                    .one();
+
+            if (orderInfo == null) {
+                sb.append(String.format("第%d条数据订单号不正确或已发货,请检查\n", index));
+            }
+
+            Storage detail = storageLogic.detailByName(loginCompanyWechatId, deliverGoodsBean.getWarehouse().trim());
+            if (detail == null) {
+                sb.append(String.format("第%d条数据仓库出错,请检查\n", index));
+            }
+            ExpressCompany company = expressLogic.expressCompany(deliverGoodsBean.getExpressCorp().trim());
+            if (company == null) {
+                sb.append(String.format("第%d条数据物流公司出错,请检查\n", index));
+            }
+
+        }
+        return sb.toString();
+    }
+
+    public void updateDeliverItem(AdminUserCom adminUserCom, DeliverGoodsBean deliverGoodsBean) throws Exception {
+        String orderId = deliverGoodsBean.getOrderId();
+        OrderInfo orderInfo = orderInfoService.lambdaQuery()
+                .eq(OrderInfo::getOrderId, orderId)
+                .eq(OrderInfo::getOrderStatus, OrderStatusEnum.DFH.toString())
+                .one();
+        if (StringUtils.isEmpty(orderId)) {
+            throw new RemoteServiceException("订单号不能为空");
+        }
+        final AdminCompanyWechat companyWechat = adminCompanyWechatService.getById(orderInfo.getCompanyWechatId());
+
+        if (orderInfo == null) {
+            throw new RemoteServiceException(String.format("订单号:%s不正确或已发货,请检查", deliverGoodsBean.getOrderId()));
+        }
+
+        Storage detail = storageLogic.detailByName(adminUserCom.getLoginCompanyWechatId(), deliverGoodsBean.getWarehouse().trim());
+        if (detail == null) {
+            throw new RemoteServiceException(String.format("订单号:%s仓库出错,请检查", deliverGoodsBean.getOrderId()));
+        }
+        ExpressCompany company = expressLogic.expressCompany(deliverGoodsBean.getExpressCorp().trim());
+        if (company == null) {
+            throw new RemoteServiceException(String.format("订单号:%s物流公司出错,请检查", deliverGoodsBean.getOrderId()));
+        }
+        orderInfo.setLogisticsNo(deliverGoodsBean.getLogisticsNo());
+        orderInfo.setCompanyCode(company.getCode());
+        orderInfo.setCompanyName(company.getName());
+        orderInfo.setOrderStatus(OrderStatusEnum.YFH.toString());
+        orderInfo.setStorageName(detail.getStorageName());
+        orderInfo.setStorageAddress(detail.getStorageAddress());
+        orderInfo.setStoragePhone(detail.getStorageMobile());
+        orderInfo.setDeliverTime(new Date());
+        orderInfo.setWorkOrder(deliverGoodsBean.getSend());
+        orderInfo.setExchangeOrder(deliverGoodsBean.getExchangeOrder());
+        orderInfo.updateById();
+
+        orderShareLogic.updateOrderStatus(orderId, OrderStatusEnum.YFH.toString());
+        if (orderInfo != null) {
+            User user = userLogic.getById(orderInfo.getUserId());
+            if (user != null) {
+                msgSubscriptLogic.sendFhNotice(user.getUserId(), user.getOpenId(), orderInfo.getOrderId(), orderInfo.getPayAmount()
+                        , orderInfo.getCompanyName(), orderInfo.getLogisticsNo());
+            }
+        }
+    }
+
+
+    private String getStringValue(Cell cell) {
+        if (cell == null) {
+            return null;
+        }
+        CellType cellType = cell.getCellTypeEnum();
+        switch (cellType) {
+            case STRING:
+                return cell.getStringCellValue();
+            case NUMERIC:
+                double value = cell.getNumericCellValue();
+                return String.valueOf(Math.round(value));
+            case BOOLEAN:
+                return String.valueOf(cell.getBooleanCellValue());
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * 订单详情
+     */
+    public OrderDetailBean detail(String orderId) {
+        OrderInfo orderInfo = orderInfoService.getById(orderId);
+        //查询订单详情
+        List<OrderDetail> orderDetails = orderDetailService.lambdaQuery()
+                .eq(OrderDetail::getOrderId, orderInfo.getOrderId())
+                .list();
+        //已结算数量
+        Long count = orderShareService.lambdaQuery()
+                .eq(OrderShare::getOrderId, orderId)
+                .eq(OrderShare::getStatus, OrderShareStatusEnum.OVER.toString())
+                .count();
+        //组装数据
+        OrderDetailBean orderDetailBean = new OrderDetailBean();
+        BeanUtils.copyProperties(orderInfo, orderDetailBean);
+        orderDetailBean.setOrderDetails(orderDetails);
+        Boolean refundFlag = false;
+        if (count == 0) {
+            refundFlag = true;
+        }
+        orderDetailBean.setRefundAble(refundFlag);
+        //团长信息
+        if (StringUtils.isNotEmpty(orderInfo.getPromotionGroupUserId())) {
+            User user = userService.getById(orderInfo.getPromotionGroupUserId());
+            if (user != null) {
+                orderDetailBean.setPromotionGroupUserName(user.getNickName());
+                orderDetailBean.setPromotionGroupMobile(user.getMobile());
+            }
+        }
+        //查询订单评价
+        orderDetailBean.setOrderComment(commentTagLogic.getOrderComment(orderId));
+        orderDetailBean.setOrderCommentTags(commentTagLogic.getCommentTags(orderId));
+        orderDetailBean.setOrderCommentImgs(commonLogic.queryFileUrlsByObjId(orderId, Constant.Img.ORDER_COMMENT));
+        return orderDetailBean;
+    }
+
+    /**
+     * 是否显示评价
+     */
+    public void updateShowComment(String orderId, Boolean isShow) {
+        commentTagLogic.updateShow(orderId, isShow);
+    }
+
+
+    /**
+     * 修改订单状态,修改结算的订单状态
+     */
+    public void updateOrderStatus(String orderId, String orderStatus) {
+        orderInfoService.lambdaUpdate()
+                .set(OrderInfo::getOrderStatus, orderStatus)
+                .eq(OrderInfo::getOrderId, orderId).update();
+
+        orderShareLogic.updateOrderStatus(orderId, orderStatus);
+    }
+
+    /**
+     * 查询订单详情
+     */
+    public List<OrderDetail> queryOrderDetails(String orderId) {
+        List<OrderDetail> list = orderDetailService.lambdaQuery().in(OrderDetail::getOrderId, orderId).list();
+        return list;
+    }
+
+
+    /**
+     * 导出excel
+     *
+     * @param orderId
+     * @param orderStatus
+     */
+    public void export(HttpServletRequest request, HttpServletResponse response, String userId, String orderId, String productName, String userName, String phone, String orderStatus,
+                       String startCreateTime, String endCreateTime, String startPayTime, String endPayTime, String websitId) throws Exception {
+        List<OrderDetailBean> list = list(request, userId, orderId, productName, userName, phone, orderStatus, startCreateTime, endCreateTime, startPayTime, endPayTime, websitId);
+//        OrderDetailBean
+        String[] titles = {"订单号", "商品名称", "规格型号", "数量", "单位", "销售单价", "优惠后单价", "实际收款", "收货人姓名",
+                "手机号", "收货地址", "订单状态", "售后状态", "退款金额(小项)", "退款数量(小项)", "备注", "下单时间", "买家昵称", "购买渠道", "买家备注", "卖家备注", "网点", "业务员/网点", "分佣金额", "团长名称", "团长手机号"};
+        ExcelData excelData = new ExcelData();
+        List<List<Object>> rows = new ArrayList<>();
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        for (OrderDetailBean orderDetailBean : list) {
+
+            User user = null;
+            //查询团长
+            String promotionGroupUserId = orderDetailBean.getPromotionGroupUserId();
+            if (StringUtils.isNotEmpty(promotionGroupUserId)) {
+                user = userService.getById(promotionGroupUserId);
+            }
+
+            for (OrderDetail orderDetail : orderDetailBean.getOrderDetails()) {
+                List<Object> row = new ArrayList<>();
+                row.add(orderDetail.getOrderId());
+                row.add(orderDetail.getGoodsName());
+
+                row.add(trimStr(orderDetail.getGoodsSpecName(), "(", orderDetail.getGoodsSpecValue(), ")"));
+                row.add(orderDetail.getNum());
+                row.add("台");
+                row.add(orderDetail.getPrice());
+                row.add(orderDetail.getPayAmount().divide(new BigDecimal(orderDetail.getNum()), 2, BigDecimal.ROUND_HALF_UP));
+                row.add(orderDetail.getPayAmount());
+                row.add(orderDetailBean.getReceUserName());
+                row.add(orderDetailBean.getRecePhone());
+                row.add(trimStr(orderDetailBean.getProvince(), orderDetailBean.getCity(),
+                        orderDetailBean.getArea(), orderDetailBean.getStreet(), orderDetailBean.getReceAddress(), orderDetailBean.getHouseNo()));
+                String orderStatusName = Enum.valueOf(OrderStatusEnum.class, orderDetailBean.getOrderStatus().trim().toUpperCase()).getName();
+                if (orderDetailBean.getOrderStatus().equals(OrderStatusEnum.REFUND.toString())) {
+                    if (StringUtils.isNotEmpty(orderDetailBean.getLogisticsNo())) {
+                        orderStatusName = OrderStatusEnum.YFH.getName();
+                    } else {
+                        orderStatusName = OrderStatusEnum.DFH.getName();
+                    }
+                }
+                if (orderDetailBean.getRefundFlag().equals(RefundFlagEnum.ALL.toString())) {
+                    orderStatusName = OrderStatusEnum.CLOSE.getName();
+                }
+                row.add(orderStatusName);
+                String refundFlag = "";
+                if (orderDetailBean.getRefundFlag().equals(RefundFlagEnum.PARTLY.toString()) ||
+                        orderDetailBean.getRefundFlag().equals(RefundFlagEnum.ING.toString())
+                ) {
+                    if (orderDetail.getRefundNum() == 0) {
+                        refundFlag = RefundFlagEnum.COMMONLY.getName();
+                    } else {
+                        refundFlag = orderDetail.getNum() - orderDetail.getRefundNum() > 0 ?
+                                RefundFlagEnum.PARTLY.getName() : RefundFlagEnum.ALL.getName();
+                        if (orderDetailBean.getRefundFlag().equals(RefundFlagEnum.ING.toString())) {
+                            refundFlag = RefundFlagEnum.ING.getName();
+                        }
+                    }
+                } else {
+                    refundFlag = Enum.valueOf(RefundFlagEnum.class, orderDetailBean.getRefundFlag().trim().toUpperCase()).getName();
+                }
+                row.add(refundFlag);
+                row.add(orderDetail.getRefundAmount());
+                row.add(orderDetail.getRefundNum());
+//                row.add(orderDetailBean.getRefundTotal());
+                row.add(orderDetailBean.getRemark());
+                row.add(simpleDateFormat.format(orderDetailBean.getCreateTime()));
+                row.add(orderDetailBean.getUserName());
+                row.add(orderDetailBean.getWorkerName());
+                row.add(orderDetailBean.getBuyerMsg());
+                row.add(orderDetailBean.getRemark());
+                row.add(orderDetailBean.getWebsitName());
+                row.add(trimStr(orderDetailBean.getWorkerName(), "\r\n", orderDetailBean.getWebsitName()));
+                row.add(orderDetail.getShareAmount());
+                row.add(orderDetailBean.getPromotionGroupUserId());
+                if (user != null) {
+                    row.add(user.getNickName());
+                    row.add(user.getMobile());
+                } else {
+                    row.add("");
+                    row.add("");
+                }
+                rows.add(row);
+            }
+        }
+
+
+        String fileName = String.format("订单导出%s.xlsx", simpleDateFormat.format(new Date()));
+        excelData.setTitles(Arrays.asList(titles));
+        excelData.setName("订单");
+        excelData.setRows(rows);
+        ExcelUtils.exportExcel(request, response, fileName, excelData, -1, null);
+    }
+
+    /**
+     * 导出excel
+     */
+    public void export2(HttpServletRequest request, HttpServletResponse response,
+                        String userId, String orderId, String productName, String userName,
+                        String phone, String exchangeCode, String orderStatus,
+                        String startCreateTime, String endCreateTime,
+                        String startPayTime, String endPayTime, String promotionGroupUserName, String promotionGroupId,
+                        String promotionGroupUserId, String websitId, String goodsId) throws Exception {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        ExcelData excelData = new ExcelData();
+        String[] titles = {"订单号", "商品名称", "规格型号", "数量", "单位", "销售单价", "优惠后单价", "实际收款", "收货人姓名",
+                "手机号", "收货地址", "订单状态", "售后状态", "退款金额(小项)", "退款数量(小项)", "备注", "下单时间", "支付时间", "买家昵称", "购买渠道",
+                "买家备注", "卖家备注", "网点", "业务员/网点", "业务员手机号", "分佣金额", "团长名称", "团长手机号", "团购活动id",
+                "评价商品的星数(0未评价)", "评价服务的星数(0未评价)", "评价物流的星数(0未评价)", "信息编号", "商品类型", "网点名称", "是否已入驻企业微信",
+                "金蝶物料编号"};
+
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String fileName = String.format("订单导出%s.xlsx", simpleDateFormat.format(new Date()));
+
+        List<OrderDetailListBean> orderDetailListBeanList = orderMapper.selectByQueryMsg(userId, orderId, productName, userName,
+                phone, exchangeCode, orderStatus,
+                startCreateTime, endCreateTime,
+                startPayTime, endPayTime, promotionGroupUserName, promotionGroupId, promotionGroupUserId, websitId, goodsId, adminUser.getCompanyWechatIds(), null);
+
+        List<List<Object>> rows = new ArrayList<>();
+        for (OrderDetailListBean orderDetailListBean : orderDetailListBeanList) {
+            List<Object> row = new ArrayList<>();
+            rows.add(row);
+
+            String goodsName = orderDetailListBean.getGoodsName();
+            if (orderDetailListBean.getPromotionPackageGoods() != null && orderDetailListBean.getPromotionPackageGoods()) {
+                goodsName = "套购:" + goodsName;
+            }
+
+            row.add(orderDetailListBean.getOrderId());
+            row.add(goodsName);
+            row.add(orderDetailListBean.getGoodsSpecValue());
+            row.add(orderDetailListBean.getNum());
+            row.add("台");
+            row.add(orderDetailListBean.getPrice());
+            row.add(orderDetailListBean.getPayAmount().divide(new BigDecimal(orderDetailListBean.getNum()), 2, BigDecimal.ROUND_HALF_UP));
+            row.add(orderDetailListBean.getPayAmount());
+            row.add(orderDetailListBean.getReceUserName());
+            row.add(orderDetailListBean.getRecePhone());
+            row.add(orderDetailListBean.getAddress());
+
+            if (StringUtils.isNotEmpty(orderDetailListBean.getOrderStatus())) {
+                row.add(OrderStatusEnum.valueOf(orderDetailListBean.getOrderStatus()).getName());
+            } else {
+                row.add("");
+            }
+            if (StringUtils.isNotEmpty(orderDetailListBean.getRefundFlag())) {
+                row.add(RefundFlagEnum.valueOf(orderDetailListBean.getRefundFlag()).getName());
+            } else {
+                row.add("");
+            }
+            row.add(orderDetailListBean.getRefundAmount());
+            row.add(orderDetailListBean.getRefundNum());
+            row.add(StringUtils.isBlank(orderDetailListBean.getRemark()) ? "" : orderDetailListBean.getRemark());
+            row.add(orderDetailListBean.getCreateTime() == null ? "" : simpleDateFormat.format(orderDetailListBean.getCreateTime()));
+            row.add(orderDetailListBean.getPayTime() == null ? "" : simpleDateFormat.format(orderDetailListBean.getPayTime()));
+            row.add(StringUtils.isBlank(orderDetailListBean.getUserName()) ? "" : orderDetailListBean.getUserName());
+            row.add(StringUtils.isBlank(orderDetailListBean.getWorkerName()) ? "" : orderDetailListBean.getWorkerName());
+            row.add(StringUtils.isBlank(orderDetailListBean.getBuyerMsg()) ? "" : orderDetailListBean.getBuyerMsg());
+            row.add(StringUtils.isBlank(orderDetailListBean.getRemark()) ? "" : orderDetailListBean.getRemark());
+            row.add(StringUtils.isBlank(orderDetailListBean.getWebsitName()) ? "" : orderDetailListBean.getWebsitName());
+            row.add(StringUtils.isBlank(orderDetailListBean.getWorkerNameWithWebsitName()) ? "" : orderDetailListBean.getWorkerNameWithWebsitName());
+            row.add(StringUtils.isBlank(orderDetailListBean.getWorkerPhone()) ? "" : orderDetailListBean.getWorkerPhone());
+            row.add(orderDetailListBean.getShareAmount());
+            row.add(StringUtils.isBlank(orderDetailListBean.getNickName()) ? "" : orderDetailListBean.getNickName());
+            row.add(StringUtils.isBlank(orderDetailListBean.getMobile()) ? "" : orderDetailListBean.getMobile());
+            row.add(StringUtils.isBlank(orderDetailListBean.getPromotionGroupId()) ? "" : orderDetailListBean.getPromotionGroupId());
+            row.add(orderDetailListBean.getCommentGoods());
+            row.add(orderDetailListBean.getCommentService());
+            row.add(orderDetailListBean.getCommentExpress());
+            row.add(StringUtils.isBlank(orderDetailListBean.getWorkerOrderNo()) ? "" : orderDetailListBean.getWorkerOrderNo());
+            row.add(StringUtils.equals(orderDetailListBean.getWorkOrderType(), "INSTALL") ? "安装" : "维修");
+            row.add("");
+            row.add(orderDetailListBean.getIsAddCorp() != null && orderDetailListBean.getIsAddCorp() ? "是" : "否");
+            row.add(StringUtils.isBlank(orderDetailListBean.getGoodsCode()) ? "" : orderDetailListBean.getGoodsCode());
+            row.add(StringUtils.isBlank(orderDetailListBean.getBuyerName()) ? "" : orderDetailListBean.getBuyerName());
+            row.add(StringUtils.isBlank(orderDetailListBean.getBuyerMobile()) ? "" : orderDetailListBean.getBuyerMobile());
+            row.add(StringUtils.isBlank(orderDetailListBean.getBuyerIdCard()) ? "" : orderDetailListBean.getBuyerIdCard());
+            row.add(Objects.isNull(orderDetailListBean.getCouponMerchantContribute()) ? BigDecimal.ZERO : orderDetailListBean.getCouponMerchantContribute());
+            row.add(StringUtils.isBlank(orderDetailListBean.getBarCode()) ? "" : orderDetailListBean.getBarCode());
+            row.add(StringUtils.isBlank(orderDetailListBean.getTransactionId()) ? "" : orderDetailListBean.getTransactionId());
+        }
+
+        excelData.setTitles(Arrays.asList(titles));
+        excelData.setName("订单");
+        excelData.setRows(rows);
+        ExcelUtils.exportExcel(request, response, fileName, excelData, -1, null);
+
+    }
+
+    private String trimStr(String... str) {
+        StringBuffer sb = new StringBuffer("");
+        for (String s : str) {
+            if (s != null) {
+                sb.append(s);
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 修改物流单号
+     */
+    public void updateExpress(String orderId,String logisticsNo,String companyCode) throws RemoteServiceException {
+        //查询物流公司
+        String company = expressLogic.expressCompanyName(companyCode);
+        OrderInfo orderInfo = orderInfoService.getById(orderId);
+        if(!orderInfo.getOrderStatus().equals(OrderStatusEnum.YFH.toString())){
+            throw new RemoteServiceException("非已发货订单不可修改物流单号");
+        }
+        orderInfo.setCompanyCode(companyCode);
+        orderInfo.setCompanyName(company);
+        orderInfo.setLogisticsNo(logisticsNo);
+        orderInfo.updateById();
+    }
+
+    /**
+     * 查看物流
+     */
+    public List<ExpressInfo> queryExpressInfo(String logisticsNo){
+        List<ExpressInfo> list = expressInfoService.lambdaQuery().eq(ExpressInfo::getLogisticsNo, logisticsNo).list();
+        if (CollectionUtil.isNotEmpty(list)){
+            return list;
+        }
+        return null;
+
+    }
+}

+ 342 - 0
src/main/java/com/gree/mall/contest/logic/order/OrderRefundLogic.java

@@ -0,0 +1,342 @@
+package com.gree.mall.contest.logic.order;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.date.DateUtil;
+import com.aliyuncs.utils.StringUtils;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.gree.mall.contest.bean.ExcelData;
+import com.gree.mall.contest.bean.admin.AdminUserCom;
+import com.gree.mall.contest.bean.order.OrderDetailListBean;
+import com.gree.mall.contest.bean.order.OrderRefundDetailBean;
+import com.gree.mall.contest.commonmapper.OrderRefundInfoMapper;
+import com.gree.mall.contest.constant.Constant;
+import com.gree.mall.contest.enums.*;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.logic.common.CommonLogic;
+import com.gree.mall.contest.logic.common.WechatLogic;
+import com.gree.mall.contest.logic.coupon.CouponLogic;
+import com.gree.mall.contest.plus.entity.*;
+import com.gree.mall.contest.plus.service.*;
+import com.gree.mall.contest.utils.ArithUtils;
+import com.gree.mall.contest.utils.excel.ExcelUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class OrderRefundLogic {
+
+    private final OrderShareLogic orderShareLogic;
+    private final OrderLogic orderLogic;
+    private final WechatLogic wechatLogic;
+    private final CommonLogic commonLogic;
+    private final CouponLogic couponLogic;
+    private final OrderInfoService orderInfoService;
+    private final OrderRefundService orderRefundService;
+    private final OrderDetailService orderDetailService;
+    private final ExpressInfoService expressInfoService;
+    private final OrderRefundInfoMapper orderRefundInfoMapper;
+    private final OrderRequestService orderRequestService;
+
+    /**
+     * 订单列表
+     *
+     * @return
+     */
+    public IPage<OrderRefundDetailBean> list(HttpServletRequest request, String orderId, String orderRefundId, String userName, String phone, String orderStatus,
+                                             String startCreateTime, String endCreateTime, String startExamineTime, String endExamineTime,
+                                             Integer pageNum, Integer pageSize) {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+
+        IPage page = orderRefundService.lambdaQuery()
+                .like(StringUtils.isNotEmpty(orderId), OrderRefund::getOrderId, orderId)
+                .in(CollectionUtil.isNotEmpty(adminUser.getCompanyWechatIds()), OrderRefund::getCompanyWechatId, adminUser.getCompanyWechatIds())
+                ////.//in(CollectionUtils.isNotEmpty(adminUser.getAdminWebsitIds()),OrderRefund::getWebsitId,adminUser.getAdminWebsitIds())
+                .like(StringUtils.isNotEmpty(orderRefundId), OrderRefund::getOrderRefundId, orderRefundId)
+                .like(StringUtils.isNotEmpty(userName), OrderRefund::getUserName, userName)
+                .and(StringUtils.isNotEmpty(phone), v -> v.like(OrderRefund::getPhone, phone).or().like(OrderRefund::getRecePhone, phone))
+                .eq(StringUtils.isNotEmpty(orderStatus), OrderRefund::getOrderStatus, orderStatus)
+                .between(StringUtils.isNotEmpty(startCreateTime) && StringUtils.isNotEmpty(endCreateTime), OrderRefund::getCreateTime, startCreateTime, endCreateTime + " 23:59:59")
+                .between(StringUtils.isNotEmpty(startExamineTime) && StringUtils.isNotEmpty(endExamineTime), OrderRefund::getExamineTime, startExamineTime, endExamineTime + " 23:59:59")
+                .orderByDesc(OrderRefund::getCreateTime).page(new Page<>(pageNum, pageSize));
+
+        List<OrderRefundDetailBean> list = new ArrayList<>();
+        for (Object o : page.getRecords()) {
+            OrderRefund orderInfo = (OrderRefund) o;
+            OrderRefundDetailBean detailBean = new OrderRefundDetailBean();
+            BeanUtils.copyProperties(orderInfo, detailBean);
+            //查询订单详情
+            List<OrderDetail> orderDetails = orderDetailService.lambdaQuery().eq(OrderDetail::getOrderId, orderInfo.getOrderId()).list();
+            detailBean.setOrderDetails(orderDetails);
+
+            Long count = orderRequestService.lambdaQuery().eq(OrderRequest::getOrderId, orderInfo.getOrderId()).count();
+            detailBean.setToWorkOrder(count > 0);
+
+            list.add(detailBean);
+        }
+        page.setRecords(list);
+        return page;
+    }
+
+
+    /**
+     * 售后订单详情
+     *
+     * @param orderRefundId
+     * @return
+     */
+    public OrderRefundDetailBean orderRefundDetail(String orderRefundId) {
+        OrderRefund orderRefund = orderRefundService.getById(orderRefundId);
+        List<OrderDetail> list = orderDetailService.lambdaQuery().eq(OrderDetail::getOrderId, orderRefund.getOrderId()).list();
+
+        OrderRefundDetailBean orderRefundDetailBean = new OrderRefundDetailBean();
+        BeanUtils.copyProperties(orderRefund, orderRefundDetailBean);
+        orderRefundDetailBean.setOrderDetails(list);
+        //售后凭证
+        List<CommonFile> commonFiles = commonLogic.queryFileByObjId(orderRefund.getOrderId(), Constant.Img.ORDER_REFUND_WLPZ);
+        List<CommonFile> commonFiles2 = commonLogic.queryFileByObjId(orderRefund.getOrderId(), Constant.Img.ORDER_REFUND_TKPZ);
+        orderRefundDetailBean.setFiles(commonFiles);
+        orderRefundDetailBean.setTkFiles(commonFiles2);
+        //工单信息
+        List<OrderRequest> orderRequests = orderRequestService.lambdaQuery().eq(OrderRequest::getOrderId, orderRefund.getOrderId()).list();
+        orderRefundDetailBean.setOrderRequests(orderRequests);
+        return orderRefundDetailBean;
+    }
+
+    /**
+     * 审核
+     */
+    @Transactional
+    public void examine(String orderRefundId, String examineStatus, String refundMessage, String refundPassword) throws Exception {
+        OrderRefund orderRefund = orderRefundService.getById(orderRefundId);
+        OrderInfo orderInfo = orderInfoService.getById(orderRefund.getOrderId());
+        if (examineStatus.equals(OrderExamineEnum.FAIL.toString())) {
+            orderRefundService.lambdaUpdate()
+                    .eq(OrderRefund::getOrderRefundId, orderRefundId)
+                    .set(OrderRefund::getExamineStatus, examineStatus)
+                    .set(OrderRefund::getRefundMessage, refundMessage)
+                    .set(OrderRefund::getExamineTime, new Date())
+                    .set(OrderRefund::getOrderStatus, OrderStatusEnum.CLOSE.toString())
+                    .update();
+            orderDetailService.lambdaUpdate()
+                    .eq(OrderDetail::getOrderId, orderRefund.getOrderId())
+                    .set(OrderDetail::getRefundNum, 0)
+                    .set(OrderDetail::getRefundAmount, new BigDecimal("0.00"))
+                    .set(OrderDetail::getRefund, false)
+                    .update();
+
+            //恢复订单状态
+            orderInfo.setOrderStatus(orderInfo.getLastOrderStatus());
+            orderInfo.setRefundFlag(RefundFlagEnum.COMMONLY.toString());
+            orderInfo.updateById();
+            //恢复分佣状态
+            orderShareLogic.updateOrderShare(orderInfo.getOrderId(), OrderShareStatusEnum.ING.toString());
+            return;
+        }
+        String orderStatus = OrderStatusEnum.DMJCL.toString();
+        if (examineStatus.equals(OrderExamineEnum.OK.toString())) {
+
+            List<OrderShare> orderShareList = orderShareLogic.getOrderShareList(orderInfo.getOrderId());
+            if (orderShareList.size() > 0 && orderShareList.get(0).getStatus().equals(OrderShareStatusEnum.OVER.toString())) {
+                throw new RemoteServiceException("退款失败,订单已结算");
+            }
+
+            if (orderRefund.getRefundType().equals(OrderRefundTypeEnum.REFUND_AMOUNT.toString())) {
+                //直接退钱,并直接已完成售后订单
+                orderStatus = OrderStatusEnum.OVER.toString();
+                //退款
+                this.refund(orderRefund);
+            }
+            orderRefundService.lambdaUpdate()
+                    .eq(OrderRefund::getOrderRefundId, orderRefundId)
+                    .set(OrderRefund::getExamineStatus, examineStatus)
+                    .set(OrderRefund::getRefundMessage, refundMessage)
+                    .set(OrderRefund::getExamineTime, new Date())
+                    .set(OrderRefund::getOrderStatus, orderStatus)
+                    .update();
+
+            String orderId = orderRefund.getOrderId();
+            int totalNum = orderInfo.getTotalNum();
+            List<OrderDetail> orderDetails = orderDetailService.lambdaQuery()
+                    .eq(OrderDetail::getOrderId, orderId)
+                    .list();
+            int refundNum = orderDetails.stream().filter(OrderDetail::getRefund).collect(Collectors.reducing(0, OrderDetail::getRefundNum, (i, j) -> i + j));
+            if (totalNum - refundNum == 0) {
+                orderInfoService.lambdaUpdate()
+                        .eq(OrderInfo::getOrderId, orderId)
+                        .set(OrderInfo::getOrderStatus, OrderStatusEnum.CLOSE.toString())
+                        .set(OrderInfo::getRefundFlag, RefundFlagEnum.ALL.toString())
+                        .update();
+                //退优惠券
+                //couponLogic.update(Arrays.asList(orderId));
+                couponLogic.refundCoupon(orderInfo.getUserCouponId());
+            } else {
+                orderInfoService.lambdaUpdate()
+                        .eq(OrderInfo::getOrderId, orderId)
+                        .set(OrderInfo::getOrderStatus, orderInfo.getLastOrderStatus())
+                        .set(OrderInfo::getRefundFlag, RefundFlagEnum.PARTLY.toString())
+                        .update();
+            }
+
+        }
+
+    }
+
+    /**
+     * 商家确认收货
+     */
+    @Transactional
+    public void ack(String orderRefundId) throws Exception {
+
+        OrderRefund orderRefund = orderRefundService.getById(orderRefundId);
+
+        orderRefundService.lambdaUpdate()
+                .set(OrderRefund::getOverTime, new Date())
+                .set(OrderRefund::getOrderStatus, OrderStatusEnum.OVER.toString())
+                .eq(OrderRefund::getOrderRefundId, orderRefundId).update();
+        //退款
+        this.refund(orderRefund);
+    }
+
+    /**
+     * 查看物流
+     */
+    public List<ExpressInfo> queryExpressInfo(String logisticsNo) {
+        List<ExpressInfo> list = expressInfoService.lambdaQuery()
+                .eq(ExpressInfo::getLogisticsNo, logisticsNo).list();
+        if (CollectionUtil.isNotEmpty(list)) {
+            return list;
+        }
+        return null;
+    }
+
+
+    /**
+     * 备注
+     */
+    public void remark(String orderRefundId, String remark) {
+        orderRefundService.lambdaUpdate().set(OrderRefund::getRemark, remark).eq(OrderRefund::getOrderRefundId, orderRefundId).update();
+    }
+
+
+    /**
+     * 退款
+     *
+     * @param orderRefund
+     * @throws RemoteServiceException
+     * @throws WxPayException
+     */
+    public void refund(OrderRefund orderRefund) throws Exception {
+        String orderId = orderRefund.getOrderId();
+        List<OrderDetail> list = orderDetailService.lambdaQuery()
+                .eq(OrderDetail::getOrderId, orderId)
+                .eq(OrderDetail::getRefund, true).list();
+
+        for (OrderDetail orderDetail : list) {
+            double div = ArithUtils.div(orderDetail.getRefundNum(), orderDetail.getNum(), 4);
+            double mul = ArithUtils.mul(orderDetail.getShareAmount().doubleValue(), div, 2);
+            BigDecimal totalShareAmount = BigDecimal.valueOf(mul);
+
+            //1=非团购商品 2=团购商品
+            int flag = StringUtils.isNotEmpty(orderDetail.getPromotionGroupId()) ? 2 : 1;
+            log.info("【退款开始:】重置结算flag={}金额,需要减掉的金额{}", flag, totalShareAmount.doubleValue());
+            orderShareLogic.reloadAmount(orderId, totalShareAmount, flag);
+        }
+
+        log.info("【退款开始:】退款金额{}", orderRefund.getRefundAmount().doubleValue());
+        if (orderRefund.getPayAmount().doubleValue() == 0) {
+            return;
+        }
+        wechatLogic.refund(orderRefund.getOrderId(), orderRefund.getOrderRefundId(), orderRefund.getPayAmount().doubleValue()
+                , orderRefund.getRefundAmount().doubleValue(), orderRefund.getCompanyWechatId());
+    }
+
+
+    /**
+     * 导出报表
+     */
+    public void downLoadOrderRefundExcel(HttpServletRequest request, HttpServletResponse response,
+                                         String orderId, String orderRefundId, String userName, String phone, String orderStatus,
+                                         String startCreateTime, String endCreateTime, String startExamineTime, String endExamineTime
+    ) throws Exception {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
+        List<List<Object>> rowList = new ArrayList<>();
+
+        String[] titles = {"订单号", "商品名称", "规格型号", "数量", "单位", "销售单价", "优惠后单价", "实际收款", "收货人姓名",
+                "手机号", "收货地址", "订单状态", "售后状态", "退款金额(小项)", "退款数量(小项)", "备注", "下单时间", "买家昵称", "购买渠道",
+                "买家备注", "卖家备注", "网点", "业务员/网点", "分佣金额", "团长名称", "团长手机号", "团购活动id", "退货说明"};
+        ExcelData excelData = new ExcelData();
+        excelData.setTitles(Arrays.asList(titles));
+        excelData.setName("维权订单");
+        excelData.setRows(rowList);
+
+        List<OrderDetailListBean> orderRefundDetailList = orderRefundInfoMapper.getOrderRefundDetailList(
+                orderId, orderRefundId, userName, phone, orderStatus, startCreateTime, endCreateTime, startExamineTime, endExamineTime, adminUser.getCompanyWechatIds(), adminUser.getAdminWebsitIds());
+
+        for (OrderDetailListBean orderDetailListBean : orderRefundDetailList) {
+            List<Object> row = new ArrayList<>();
+            rowList.add(row);
+
+            row.add(orderDetailListBean.getOrderId());
+            row.add(orderDetailListBean.getGoodsName());
+            row.add(orderDetailListBean.getGoodsSpecValue());
+            row.add(orderDetailListBean.getNum());
+            row.add("台");
+            row.add(orderDetailListBean.getPrice());
+            row.add(orderDetailListBean.getPayAmount().divide(new BigDecimal(orderDetailListBean.getNum()), 2, BigDecimal.ROUND_HALF_UP));
+            row.add(orderDetailListBean.getPayAmount());
+            row.add(orderDetailListBean.getReceUserName());
+            row.add(orderDetailListBean.getRecePhone());
+            row.add(orderDetailListBean.getAddress());
+            if (StringUtils.isNotEmpty(orderDetailListBean.getOrderStatus())) {
+                row.add(Enum.valueOf(OrderStatusEnum.class, orderDetailListBean.getOrderStatus()).getName());
+            } else {
+                row.add("");
+            }
+            if (StringUtils.isNotEmpty(orderDetailListBean.getRefundFlag())) {
+                row.add(RefundFlagEnum.valueOf(orderDetailListBean.getRefundFlag()).getName());
+            } else {
+                row.add("");
+            }
+            row.add(orderDetailListBean.getRefundAmount());
+            row.add(orderDetailListBean.getRefundNum());
+            row.add(orderDetailListBean.getRemark());
+            row.add(DateUtil.formatDate(orderDetailListBean.getCreateTime()));
+            row.add(orderDetailListBean.getUserName());
+            row.add(orderDetailListBean.getWorkerName());
+            row.add(orderDetailListBean.getBuyerMsg());
+            row.add(orderDetailListBean.getRefundMessage());
+            row.add(orderDetailListBean.getWebsitName());
+            row.add(orderDetailListBean.getWorkerNameWithWebsitName());
+            row.add(orderDetailListBean.getShareAmount());
+            row.add(orderDetailListBean.getNickName());
+            row.add(orderDetailListBean.getMobile());
+            row.add(orderDetailListBean.getPromotionGroupId());
+            row.add(orderDetailListBean.getRefundExplain());
+
+        }
+
+
+        ExcelUtils.exportExcel(request, response, String.format("维权订单导出%s.xlsx", simpleDateFormat.format(new Date())), excelData);
+
+    }
+
+}

+ 488 - 0
src/main/java/com/gree/mall/contest/logic/order/OrderShareLogic.java

@@ -0,0 +1,488 @@
+package com.gree.mall.contest.logic.order;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.EnumUtil;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.binarywang.wxpay.bean.profitsharing.ProfitSharingQueryResult;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.gree.mall.contest.bean.ExcelData;
+import com.gree.mall.contest.bean.admin.AdminUserCom;
+import com.gree.mall.contest.bean.order.OrderShareReportBean;
+import com.gree.mall.contest.commonmapper.OrderShareReportMapper;
+import com.gree.mall.contest.constant.Constant;
+import com.gree.mall.contest.enums.*;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.logic.common.CommonLogic;
+import com.gree.mall.contest.logic.common.WechatLogic;
+import com.gree.mall.contest.plus.entity.OrderInfo;
+import com.gree.mall.contest.plus.entity.OrderRefund;
+import com.gree.mall.contest.plus.entity.OrderShare;
+import com.gree.mall.contest.plus.entity.User;
+import com.gree.mall.contest.plus.service.OrderInfoService;
+import com.gree.mall.contest.plus.service.OrderRefundService;
+import com.gree.mall.contest.plus.service.OrderShareService;
+import com.gree.mall.contest.plus.service.UserService;
+import com.gree.mall.contest.utils.excel.ExcelUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class OrderShareLogic {
+
+    private final WechatLogic wechatLogic;
+    private final CommonLogic commonLogic;
+    private final OrderShareService orderShareService;
+    private final UserService userService;
+    private final OrderShareReportMapper orderShareReportMapper;
+    private final OrderInfoService orderInfoService;
+    private final OrderRefundService orderRefundService;
+
+
+    public IPage<OrderShare> list(HttpServletRequest request, String userId, String websitId, String orderShareId, String orderId, String workUserName, String phone, String status,
+                                  String startTime, String endTime, String startSettleTime, String endSettleTime, String position,
+                                  String startPayTime, String endPayTime, String payType, Integer pageNo, Integer pageSize) {
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        log.info("结算管理:companyWechatId:{},adminWebsitIds:{}", JSONUtil.toJsonStr(adminUser.getCompanyWechatIds()), JSONUtil.toJsonStr((adminUser.getAdminWebsitIds())));
+        IPage<OrderShare> page = orderShareService.lambdaQuery()
+                .in(CollectionUtils.isNotEmpty(adminUser.getCompanyWechatIds()), OrderShare::getCompanyWechatId, adminUser.getCompanyWechatIds())
+                ////.//in(CollectionUtils.isNotEmpty(adminUser.getAdminWebsitIds()),OrderShare::getWebsitId,adminUser.getAdminWebsitIds())
+                .eq(StringUtils.isNotEmpty(userId), OrderShare::getUserId, userId)
+                .like(StringUtils.isNotEmpty(orderShareId), OrderShare::getOrderShareId, orderShareId)
+                .like(StringUtils.isNotEmpty(orderId), OrderShare::getOrderId, orderId)
+                .like(StringUtils.isNotEmpty(workUserName), OrderShare::getWorkUserName, workUserName)
+                .like(StringUtils.isNotEmpty(phone), OrderShare::getPhone, phone)
+                .eq(StringUtils.isNotEmpty(status), OrderShare::getStatus, status)
+                .between(StringUtils.isNotEmpty(startTime) && StringUtils.isNotEmpty(endTime), OrderShare::getCreateTime, startTime, endTime)
+                .between(StringUtils.isNotEmpty(startSettleTime) && StringUtils.isNotEmpty(endSettleTime), OrderShare::getSettleTime, startSettleTime, endSettleTime)
+                .between(StringUtils.isNotEmpty(startPayTime) && StringUtils.isNotEmpty(endPayTime), OrderShare::getPayTime, startPayTime, endPayTime)
+                .eq(StringUtils.isNotBlank(payType), OrderShare::getPayType, payType)
+                .orderByDesc(OrderShare::getCreateTime)
+                .page(new Page<>(pageNo, pageSize));
+        return page;
+    }
+
+
+    public void export(HttpServletRequest request, HttpServletResponse response, String userId, String websitId, String orderShareId, String orderId,
+                       String workUserName, String phone, String status, String startTime, String endTime, String startSettleTime, String endSettleTime,
+                       String payType,
+                       String position, String startPayTime, String endPayTime) throws Exception {
+        List<OrderShare> list = list(request, userId, websitId, orderShareId, orderId, workUserName, phone, status, startTime, endTime,
+                startSettleTime, endSettleTime, position, startPayTime, endPayTime, payType, 1, -1).getRecords();
+        String[] titles = {"序号", "结算编号", "订单类型", "订单编号", "店铺名称", "商品信息", "单价", "数量", "总金额",
+                "商品佣金", "订单佣金", "优惠金额", "结算金额", "平台优惠券名称", "交易单号",
+                "售后服务", "下单账号", "下单时间", "支付时间", "支付方式", "佣金结算状态",
+                "结算时间", "分销员", "所属网点", "商品佣金类型", "订单状态", "职位",
+                "买家备注", "收货人",
+                "手机号", "收货地址", "物流公司", "物流单号", "发票类型", "发票抬头", "发票内容",
+                "纳税人识别号", "名称", "公司注册地址", "公司注册电话", "开户银行", "银行账号", "收票人姓名",
+                "收票人地址", "收票人手机", "收票人邮箱", "商户单号",
+                "订单结算状态", "支付时间", "支付方式", "备注"};
+        ExcelData excelData = new ExcelData();
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+        if (CollectionUtils.isEmpty(list)) {
+            String fileName = String.format("结算导出_%s.xlsx", simpleDateFormat.format(new Date()));
+            excelData.setTitles(Arrays.asList(titles));
+            excelData.setName("结算订单");
+            excelData.setRows(new ArrayList<>());
+            ExcelUtils.exportExcel(request, response, fileName, excelData, -1, null);
+            return;
+        }
+
+        List<String> orderIds = list.stream().map(OrderShare::getOrderId).collect(Collectors.toList());
+
+        List<OrderShareReportBean> orderShareReportBeans = orderShareReportMapper.queryReport(orderIds);
+
+        List<List<Object>> rows = new ArrayList<>();
+
+        final String SHOP_NAME = "格匠商城";
+        for (int i = 0; i < orderShareReportBeans.size(); i++) {
+            OrderShareReportBean bean = orderShareReportBeans.get(i);
+            List<Object> row = new ArrayList<>();
+            row.add(i + 1);
+            row.add(bean.getOrderShareId());
+            // row.add(bean.getMainNumber());
+            row.add(bean.getOrderId());
+            row.add(SHOP_NAME);
+         /*   row.add(bean.getGoodsName());
+            row.add(bean.getPrice());
+            row.add(bean.getNum());*/
+            row.add(bean.getTotalPrice());
+
+            //  row.add(bean.getShareAmount());//"商品佣金"
+            row.add(bean.getAmount());//"订单佣金"
+            row.add(bean.getDiscountAmount());//优惠金额
+            // row.add(bean.getPayAmount().subtract(bean.getShareAmount()));//"结算金额"
+            row.add(bean.getCouponName());//"平台优惠券名称"
+            row.add(bean.getTransactionId());//"交易单号"
+
+            row.add(bean.getOrderStatus().equals(OrderStatusEnum.REFUND.toString()) ? "退款关闭" : "无");
+            row.add(bean.getUserId());
+            row.add(bean.getCreateTime() == null ? "" : simpleDateFormat.format(bean.getCreateTime()));
+            row.add(bean.getPayTime() == null ? "" : simpleDateFormat.format(bean.getPayTime()));
+            row.add(bean.getPayType());
+
+
+            row.add(Enum.valueOf(OrderShareStatusEnum.class, bean.getShareStatus().trim().toUpperCase()).getName());//"佣金结算状态"
+            row.add(bean.getSettleTime() == null ? "" : simpleDateFormat.format(bean.getSettleTime()));//"结算时间"
+            row.add(bean.getWorkUserName());//"分销员"
+            row.add(bean.getWebsitName());//"所属网点"
+            row.add("");//"商品佣金类型"
+            row.add(Enum.valueOf(OrderStatusEnum.class, bean.getOrderStatus().trim().toUpperCase()).getName());//"订单状态"
+            row.add(bean.getPosition());// "职位"
+
+            row.add(bean.getRemark());
+            row.add(bean.getReceUserName());
+            row.add(bean.getRecePhone());
+            row.add(bean.getAddress());
+            row.add(bean.getName());
+            row.add(bean.getLogisticsNo());
+
+            row.add(bean.getType() == null || !bean.getType() ? "个人发票" : "公司发票");
+            row.add(bean.getTaxName());
+            row.add(bean.getContent());
+            row.add(bean.getTaxNo());
+            row.add(bean.getTaxName());
+
+            row.add(bean.getRegisterAddress());
+            row.add(bean.getRegisterPhone());
+            row.add(bean.getBank());
+            row.add(bean.getAccount());
+            row.add(bean.getReceiverName());
+            row.add(bean.getReceiverAddress());
+            row.add(bean.getReceiverPhone());
+            row.add(bean.getReceiverEmail());
+
+            row.add("");
+            row.add("");
+            row.add(simpleDateFormat.format(bean.getPayTime()));
+            row.add(bean.getPayType().equals(PayTypeEnum.UNIONPAY.getName()) ? PayTypeEnum.UNIONPAY.getName() : PayTypeEnum.WEIXIN.getName());
+            row.add(bean.getRemark() == null ? "" : bean.getRemark());
+            rows.add(row);
+        }
+
+        String fileName = String.format("结算导出_%s.xlsx", simpleDateFormat.format(new Date()));
+        excelData.setTitles(Arrays.asList(titles));
+        excelData.setName("结算订单");
+        excelData.setRows(rows);
+//        final int[] mergeRows = new int[]{1,2,7, 9, 10, 11, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34, 35, 36, 41, 42, 43, 44};
+        ExcelUtils.exportExcel(request, response, fileName, excelData, -1, null);
+
+    }
+
+
+    public void export2(HttpServletRequest request, HttpServletResponse response, String userId, String websitId, String orderShareId, String orderId,
+                        String workUserName, String phone, String status, String startTime, String endTime, String startSettleTime, String endSettleTime,
+                        String position, String payType, String startPayTime, String endPayTime) throws Exception {
+
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+        String[] titles = {"序号", "商城名称", "结算编号", "订单号", "订单佣金", "总价", "折扣金额", "实付金额", "运费", "订单状态", "退款标记", "下单用户账号",
+                "下单时间", "支付方式", "支付时间", "买家备注", "收货人", "收货电话", "收货地址", "物流单号", "物流公司", "发票类型",
+                "发票抬头", "发票内容", "订单发票纳税人识别号", "订单发票公司注册地址", "订单发票公司注册电话", "订单发票开户行", "订单发票开户账号", "订单发票接收邮箱", "订单发票接收手机号",
+                "订单发票收件人", "订单发票收件地址", "优惠券名称", "订单交易号", "佣金结算状态", "分销员", "订单所属网点",
+                "结算时间", "职位", "支付方式"};
+
+        ExcelData excelData = new ExcelData();
+        String fileName = String.format("结算导出_%s.xlsx", simpleDateFormat.format(new Date()));
+        excelData.setTitles(Arrays.asList(titles));
+        excelData.setName("结算订单");
+
+        List<OrderShare> list = list(request, userId, websitId, orderShareId, orderId, workUserName, phone, status, startTime, endTime,
+                startSettleTime, endSettleTime, position, startPayTime, endPayTime, payType, 1, -1).getRecords();
+
+        if (CollectionUtils.isEmpty(list)) {
+            excelData.setRows(new ArrayList<>());
+            ExcelUtils.exportExcel(request, response, fileName, excelData, -1, null);
+            return;
+        }
+        //todo  延用原export()中的实现方案  如果出现太慢还是推荐在mybatis中设置条件
+        List<String> orderShareIdList = list.stream().map(OrderShare::getOrderShareId).collect(Collectors.toList());
+
+        List<OrderShareReportBean> orderShareReportBeans = orderShareReportMapper.queryReport2(orderShareIdList);
+
+        List<List<Object>> rows = new ArrayList<>();
+        for (int i = 0; i < orderShareReportBeans.size(); i++) {
+            OrderShareReportBean bean = orderShareReportBeans.get(i);
+            List<Object> row = new ArrayList<>();
+            rows.add(row);
+
+            row.add(i + 1);
+            row.add(bean.getShopName());
+            row.add(bean.getOrderShareId());
+            row.add(bean.getOrderId());
+            row.add(bean.getAmount());
+            row.add(bean.getTotalPrice());
+            row.add(bean.getDiscountAmount());
+            row.add(bean.getPayAmount());
+            row.add(bean.getFreight());
+            row.add(Enum.valueOf(OrderStatusEnum.class, bean.getOrderStatus().trim().toUpperCase()).getName());
+            row.add(StringUtils.isEmpty(bean.getRefundFlag()) ? "" : RefundFlagEnum.valueOf(bean.getRefundFlag()).getName());
+            row.add(bean.getUserId());
+
+            row.add(bean.getCreateTime() == null ? "" : simpleDateFormat.format(bean.getCreateTime()));
+            row.add(bean.getPayType());
+            row.add(bean.getPayTime() == null ? "" : simpleDateFormat.format(bean.getPayTime()));
+            row.add(bean.getRemark() == null ? "" : bean.getRemark());
+            row.add(bean.getReceUserName());
+            row.add(bean.getRecePhone());
+            row.add(bean.getAddress());
+            row.add(bean.getLogisticsNo());
+            row.add(bean.getName());
+            row.add(bean.getType() == null || !bean.getType() ? "个人发票" : "公司发票");
+
+            row.add(bean.getTaxName());
+            row.add(bean.getContent());
+            row.add(bean.getTaxNo());
+            row.add(bean.getRegisterAddress());
+            row.add(bean.getRegisterPhone());
+            row.add(bean.getBank());
+            row.add(bean.getAccount());
+            row.add(bean.getReceiverEmail());
+            row.add(bean.getReceiverPhone());
+
+            row.add(bean.getReceiverName());
+            row.add(bean.getReceiverAddress());
+            row.add(bean.getCouponName());
+            row.add(bean.getTransactionId());
+            row.add(Enum.valueOf(OrderShareStatusEnum.class, bean.getShareStatus().trim().toUpperCase()).getName());
+            row.add(bean.getWorkUserName());
+            row.add(bean.getWebsitName());
+
+            row.add(bean.getSettleTime() == null ? "" : simpleDateFormat.format(bean.getSettleTime()));
+            row.add(bean.getPosition());
+            row.add(bean.getPayType().equals(PayTypeEnum.UNIONPAY.getName()) ? PayTypeEnum.UNIONPAY.getName() : PayTypeEnum.WEIXIN.getName());
+
+        }
+        excelData.setRows(rows);
+        ExcelUtils.exportExcel(request, response, fileName, excelData, -1, null);
+
+    }
+
+    public void updateOrderStatus(String orderId, String orderStatus) {
+        orderShareService.lambdaUpdate()
+                .set(OrderShare::getOrderStatus, orderStatus)
+                .set(orderStatus.equals(OrderStatusEnum.CLOSE.toString()), OrderShare::getStatus, OrderShareStatusEnum.CANCEL.toString())
+                .ne(OrderShare::getStatus, OrderShareStatusEnum.OVER.toString())
+                .eq(OrderShare::getOrderId, orderId)
+                .update();
+    }
+
+    public void updateOrderShare(String orderId, String orderStatus) {
+        orderShareService.lambdaUpdate()
+                .eq(OrderShare::getOrderId, orderId)
+                .set(OrderShare::getStatus, orderStatus)
+                .set(OrderShare::getSettleTime, new Date())
+                .set(OrderShare::getShareStatus, WXShareStatusEnum.PROCESSING.toString())
+                .update();
+    }
+
+    public void remark(String orderShareId, String remark) {
+        OrderShare orderShare = orderShareService.getById(orderShareId);
+        orderShare.setRemark(remark);
+        orderShare.updateById();
+    }
+
+    /**
+     * 师傅本月的结算数
+     */
+    public Long getShareNum(String mobile) {
+        User user = userService.lambdaQuery().eq(User::getWorkPhone, mobile).eq(User::getCompanyWechatId, Constant.GD_COMPANY_WECHAT_ID).last("limit 1").one();
+        if (user == null) {
+            return 0L;
+        }
+        Date startMonth = DateUtil.beginOfMonth(DateUtil.date());
+        Date endMonth = DateUtil.endOfMonth(DateUtil.date());
+        Long count = orderShareService.lambdaQuery()
+                .eq(OrderShare::getOpenId, user.getOpenId())
+                .ne(OrderShare::getStatus, OrderShareStatusEnum.CANCEL.toString())
+                .between(OrderShare::getCreateTime, startMonth, endMonth)
+                .count();
+        return count;
+    }
+
+    /**
+     * 确认分账
+     *
+     * @param orderId
+     * @throws RemoteServiceException
+     */
+    public void confirm(String orderId) throws RemoteServiceException {
+        List<OrderShare> list = orderShareService.lambdaQuery()
+                .eq(OrderShare::getOrderId, orderId)
+                .eq(OrderShare::getStatus, OrderShareStatusEnum.ING.toString())
+                .list();
+
+        OrderInfo orderInfo = orderInfoService.getById(orderId);
+        if (orderInfo == null || !orderInfo.getOrderStatus().equals(OrderStatusEnum.OVER.toString())) {
+            throw new RemoteServiceException("订单不符合结算条件");
+        }
+        if (list.size() == 0) {
+            throw new RemoteServiceException("不存在未结算的信息");
+        }
+        try {
+            if (StringUtils.isEmpty(orderInfo.getCompanyWechatId())) {
+                return;
+            }
+            //查询是否存在未处理完成的售后单
+            Long count = orderRefundService.lambdaQuery()
+                    .eq(OrderRefund::getOrderId, orderId)
+                    .in(OrderRefund::getOrderStatus, "DSJCL", "DSJSH", "DMJCL").count();
+            if (count > 0) {
+                throw new RemoteServiceException("订单" + orderId + "存在未完结的维权订单");
+            }
+            wechatLogic.shareAmount(orderId, orderInfo.getTransactionId(), list, orderInfo.getCompanyWechatId());
+            this.updateOrderShare(orderId, OrderShareStatusEnum.OVER.toString());
+
+        } catch (WxPayException e) {
+            log.error("异常结算", e);
+            this.saveOrderShareRemark(orderId, OrderShareStatusEnum.EXCEPTION.toString(), "异常结算:" + e.getErrCodeDes());
+            throw new RemoteServiceException("转账支付失败");
+        }
+    }
+
+
+    public Boolean confirmAuto(List<OrderShare> orderShares, OrderInfo orderInfo) {
+        try {
+            if (StringUtils.isEmpty(orderInfo.getCompanyWechatId())) {
+                return false;
+            }
+
+            wechatLogic.shareAmount(orderInfo.getOrderId(), orderInfo.getTransactionId(), orderShares, orderInfo.getCompanyWechatId());
+            this.updateOrderShare(orderInfo.getOrderId(), OrderShareStatusEnum.OVER.toString());
+            return true;
+        } catch (WxPayException e) {
+            log.error("异常结算", e);
+            this.saveOrderShareRemark(orderInfo.getOrderId(), OrderShareStatusEnum.EXCEPTION.toString(), "异常结算:" + e.getErrCodeDes());
+            return false;
+        }
+
+    }
+
+    /**
+     * 用户总收益
+     *
+     * @param userId
+     * @return
+     */
+    public BigDecimal totalAmount(String userId) {
+        List<OrderShare> list = orderShareService.lambdaQuery().eq(OrderShare::getUserId, userId).list();
+        return list.stream().map(OrderShare::getAmount).reduce(BigDecimal::add).orElse(new BigDecimal(0));
+    }
+
+
+    /**
+     * 刷新分佣金额
+     *
+     * @param orderId          订单号
+     * @param totalShareAmount 总分佣金额
+     * @param flag             //1=非团购商品  2=团购商品
+     */
+    public void reloadAmount(String orderId, BigDecimal totalShareAmount, Integer flag) {
+        OrderShare orderShare = orderShareService.lambdaQuery()
+                .eq(OrderShare::getOrderId, orderId)
+                .eq(OrderShare::getFlag, flag).one();
+        if (orderShare == null) {
+            return;
+        }
+        if (orderShare.getStatus().equals(OrderShareStatusEnum.OVER.toString())) {
+            return;
+        }
+        if (totalShareAmount == null) {
+            orderShare.setStatus(OrderShareStatusEnum.CANCEL.toString());
+            orderShare.updateById();
+            return;
+        }
+        //1=非团购商品  2=团购商品
+        if (orderShare != null) {
+            OrderInfo orderInfo = orderInfoService.getById(orderShare.getOrderId());
+            orderInfo.setOrderId(orderShare.getOrderId());
+            if (orderShare.getAmount().subtract(totalShareAmount).doubleValue() <= 0.01) {
+                orderShare.setStatus(OrderShareStatusEnum.CANCEL.toString());
+                orderInfo.setTotalShareAmount(BigDecimal.valueOf(0));
+            } else {
+                orderShare.setAmount(orderShare.getAmount().subtract(totalShareAmount));
+                orderInfo.setTotalShareAmount(orderInfo.getTotalShareAmount().subtract(totalShareAmount));
+            }
+            orderShare.updateById();
+            orderInfo.updateById();
+
+        }
+    }
+
+
+    public List<OrderShare> getOrderShareList(String orderId) {
+        List<OrderShare> list = orderShareService.lambdaQuery().eq(OrderShare::getOrderId, orderId).list();
+        return list;
+    }
+
+
+    /**
+     * 记录失败原因
+     */
+    public void saveOrderShareRemark(String orderId, String orderShareStatus, String remark) {
+        orderShareService.lambdaUpdate()
+                .set(OrderShare::getStatus, orderShareStatus)
+                .set(OrderShare::getRemark, remark)
+                .eq(OrderShare::getOrderId, orderId).update();
+    }
+
+    /**
+     * 查询分账结果
+     *
+     * @param share
+     * @throws Exception
+     */
+    public void queryShareResult(OrderShare share) throws Exception {
+        ProfitSharingQueryResult result = wechatLogic.profitSharingResult(share);
+        if (Objects.isNull(result)) {
+            orderShareService.lambdaUpdate()
+                    .set(OrderShare::getShareFailReason, "缺少商户id")
+                    .set(OrderShare::getStatus, WXShareStatusEnum.FINISHED.toString())
+                    .eq(OrderShare::getOrderShareId, share.getOrderShareId())
+                    .update();
+        }
+
+        if (result.getStatus().equals(WXShareStatusEnum.FINISHED.toString())) {
+            String failReason = null;
+            final Map<String, ProfitSharingQueryResult.Receiver> receiverMap = result.getReceivers().stream()
+                    .collect(Collectors.toMap(ProfitSharingQueryResult.Receiver::getAccount, Function.identity()));
+            final ProfitSharingQueryResult.Receiver receiver = receiverMap.get(share.getOpenId());
+            if (Objects.isNull(receiver)) {
+                failReason = "未发现分给" + share.getWorkUserPhone() + "的记录";
+            } else {
+                if (receiver.getResult().equals(WXShareResultEnum.CLOSED.toString())) {
+                    final Map<String, Object> fieldMap = EnumUtil.getNameFieldMap(WXShareFailReasonEnum.class, "name");
+                    final Object o = fieldMap.get(receiver.getFailReason());
+                    failReason = Objects.nonNull(o) ? o.toString() : receiver.getResult();
+                }
+            }
+            orderShareService.lambdaUpdate()
+                    .set(OrderShare::getShareFailReason, failReason)
+                    .set(OrderShare::getShareResult, receiver.getResult())
+                    .set(StringUtils.isNotBlank(failReason), OrderShare::getStatus, OrderShareStatusEnum.EXCEPTION.toString())
+                    .set(OrderShare::getShareStatus, WXShareStatusEnum.FINISHED.toString())
+                    .eq(OrderShare::getOrderShareId, share.getOrderShareId())
+                    .update();
+        }
+    }
+
+    public String queryMaxShareRate(String id) throws Exception {
+        return wechatLogic.queryMaxShareRate(id);
+    }
+}

+ 108 - 0
src/main/java/com/gree/mall/contest/logic/user/MsgSubscriptLogic.java

@@ -0,0 +1,108 @@
+package com.gree.mall.contest.logic.user;
+
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.druid.util.StringUtils;
+import com.gree.mall.contest.config.wx.WxConfiguration;
+import com.gree.mall.contest.logic.common.WechatLogic;
+import com.gree.mall.contest.plus.entity.User;
+import com.gree.mall.contest.plus.service.UserService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 消息订阅
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class MsgSubscriptLogic {
+
+
+    //环境
+    @Value("${spring.profiles.active}")
+    public String env;
+
+    private final UserService userService;
+    private final WechatLogic wechatLogic;
+
+
+    /**
+     * 发货通知
+     * @param openId
+     * @param orderId 订单号
+     * @param orderAmount 订单金额
+     * @param expressCompany 快递公司
+     * @param expressNo 快递号
+     */
+    public void sendFhNotice(String userId, String openId, String orderId, BigDecimal orderAmount, String expressCompany, String expressNo){
+
+        //封装模版数据
+        Map<String, Object> data = new HashMap<String, Object>();
+        Map<String, String> keyword1 = new HashMap<String, String>();
+        keyword1.put("value", orderId);
+        keyword1.put("color", "#173177");
+        Map<String, String> keyword2 = new HashMap<String, String>();
+        keyword2.put("value", orderAmount.toString());
+        keyword2.put("color", "#173177");
+        Map<String, String> keyword3 = new HashMap<String, String>();
+        keyword3.put("value", expressCompany);
+        keyword3.put("color", "#173177");
+        Map<String, String> keyword4 = new HashMap<String, String>();
+        keyword4.put("value", expressNo);
+        keyword4.put("color", "#173177");
+
+        if(StringUtils.equals(env,"prd")){
+            data.put("character_string1", keyword1);
+            data.put("amount15", keyword2);
+            data.put("name3", keyword3);
+            data.put("character_string4", keyword4);
+        }else {
+            data.put("character_string2", keyword1);
+            data.put("amount7", keyword2);
+            data.put("thing4", keyword3);
+            data.put("character_string5", keyword4);
+        }
+        User user = userService.getById(userId);
+        String template = WxConfiguration.temFhNotice.get(user.getCompanyWechatId());
+        String res = sendWxMsg(openId, data, template, "pages/mine/order/detail?orderId="+orderId,user.getCompanyWechatId());
+        log.info("-----------------完成发货通知消息返回:" + res);
+    }
+
+
+    /**
+     * 推送消息
+     */
+    private String sendWxMsg(String openId, Map<String,Object> data, String templateId, String page,String companyWechatId) {
+        try {
+
+            String token = wechatLogic.getAccessToken(companyWechatId);//获取token
+            String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + token;
+
+            Map<String, Object> paramMap = new HashMap<String, Object>();
+            paramMap.put("access_token", token);
+            paramMap.put("touser", openId);//openid
+            paramMap.put("template_id", templateId);//账户变动通知模版ID
+            paramMap.put("page", page);//页面
+            //paramMap.put("form_id",uf.getFormId()); //formId
+            paramMap.put("data", data);//数据
+            // paramMap.put("emphasis_keyword","keyword1.DATA");
+            String param = JSONUtil.toJsonStr(paramMap);
+
+            String s = HttpUtil.post(url, param);
+
+            log.info("----请求推送消息返回:" + s);
+            return s;
+        }catch(Exception e){
+            log.error("小程序服务通知失败:{}",e.getMessage());
+        }
+        return "";
+    }
+
+}

+ 621 - 0
src/main/java/com/gree/mall/contest/logic/user/UserLogic.java

@@ -0,0 +1,621 @@
+package com.gree.mall.contest.logic.user;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.contest.bean.ExcelData;
+import com.gree.mall.contest.bean.admin.AdminUserCom;
+import com.gree.mall.contest.bean.member.MemberBean;
+import com.gree.mall.contest.bean.member.MemberSortBean;
+import com.gree.mall.contest.bean.user.UserWxBean;
+import com.gree.mall.contest.commonmapper.CustomGoodsMapper;
+import com.gree.mall.contest.commonmapper.CustomMemberMapper;
+import com.gree.mall.contest.commonmapper.CustomWebsitMapper;
+import com.gree.mall.contest.enums.UserTypeEnum;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.logic.activity.PromotionGroupLogic;
+import com.gree.mall.contest.logic.common.CommonLogic;
+import com.gree.mall.contest.logic.common.WechatLogic;
+import com.gree.mall.contest.logic.coupon.CouponLogic;
+import com.gree.mall.contest.logic.order.OrderShareLogic;
+import com.gree.mall.contest.plus.entity.*;
+import com.gree.mall.contest.plus.service.*;
+import com.gree.mall.contest.utils.CommonUtils;
+import com.gree.mall.contest.utils.RedisUtil;
+import com.gree.mall.contest.utils.excel.ExcelUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 小程序用户
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class UserLogic {
+
+    private final UserService userService;
+    private final UserAddressService userAddressService;
+    private final GoodsFavoriteService goodsFavoriteService;
+    private final GoodsVisitService goodsVisitService;
+    private final CustomGoodsMapper customGoodsMapper;
+    private final CustomWebsitMapper customWebsitMapper;
+    private final CustomMemberMapper customMemberMapper;
+    private final CouponLogic couponLogic;
+    private final OrderShareLogic orderShareLogic;
+    private final RedisUtil redisUtil;
+    private final WechatLogic wechatLogic;
+    private final PromotionGroupLogic promotionGroupLogic;
+    private final CommonLogic commonLogic;
+    private final UserServiceApplyService userServiceApplyService;
+    private final UserServiceWaitService userServiceWaitService;
+    private final AdminWebsitService adminWebsitService;
+
+    /**
+     * 会员列表
+     *
+     * @param keyword
+     * @param startTime
+     * @param endTime
+     * @param pageNum
+     * @param pageSize
+     * @return
+     */
+    public IPage<User> page(HttpServletRequest request, String keyword, String type, Boolean promotionGroupLeader,
+                            Boolean innerr, String startTime, String endTime, String sortJson, String websitId, Boolean isExchangeCode,
+                            Integer pageNum, Integer pageSize) {
+
+        //获取当前登录企业微信id
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        List<String> companyWechatIds = adminUser.getCompanyWechatIds();
+
+        LambdaQueryWrapper<User> memberLambdaQueryWrapper = new LambdaQueryWrapper<>();
+        memberLambdaQueryWrapper
+                .in(CollectionUtils.isNotEmpty(companyWechatIds), User::getCompanyWechatId, companyWechatIds)
+                .eq(isExchangeCode != null, User::getIsExchangeCode, isExchangeCode)
+                .eq(promotionGroupLeader != null, User::getPromotionGroupLeader, promotionGroupLeader)
+                .eq(StringUtils.isNotEmpty(type), User::getType, type)
+                .eq(innerr != null, User::getInnerr, innerr)
+                // .in(!(adminWebsitBean.getType() && org.apache.commons.lang3.StringUtils.isEmpty(websitId)), User::getWebsitNumber, websitNoList)
+                .between(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime), User::getCreateTime, startTime, endTime)
+                .and(v -> v.ne(User::getMobile, "").or().ne(User::getWorkPhone, ""))
+                .and(StringUtils.isNotBlank(keyword),
+                        memberLambdaQueryWrapper1 -> memberLambdaQueryWrapper1.like(User::getNickName, keyword)
+                                .or()
+                                .like(User::getMobile, keyword));
+        if (sortJson != null && !sortJson.trim().equals("")) {
+            JSONArray goodsSortBeanArray = JSONUtil.parseArray(StringEscapeUtils.unescapeJava(sortJson));
+            MemberSortBean.convertColumn(goodsSortBeanArray, memberLambdaQueryWrapper);
+        } else {
+            memberLambdaQueryWrapper.orderByDesc(User::getCreateTime);
+        }
+
+        return userService.page(new Page(pageNum, pageSize), memberLambdaQueryWrapper);
+    }
+
+
+    public void export(HttpServletRequest request, HttpServletResponse response, String keyword, String type, String websitId, String startTime, String endTime) throws Exception {
+
+        //获取当前登录企业微信id
+        AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        List<String> companyWechatIds = adminUser.getCompanyWechatIds();
+
+        List<MemberBean> userList = customMemberMapper.queryUser(type, keyword, null, startTime, endTime, companyWechatIds);
+
+        log.info("会员导出请求参数{},{},{},{}", type, keyword, startTime, endTime);
+        log.info("会员导出数据条数{}", userList == null ? 0 : userList.size());
+        String[] titles = {"序号", "微信手机号", "微信昵称", "企微名称", "企微手机号", "用户类型", "所属网点", "成为业务员时间", "所在地区"};
+        ExcelData excelData = new ExcelData();
+        List<List<Object>> rows = new ArrayList<>();
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        for (int i = 0; i < userList.size(); i++) {
+            MemberBean bean = userList.get(i);
+            List<Object> row = new ArrayList<>();
+            row.add(i + 1);
+            row.add(bean.getMobile());
+            row.add(bean.getNickName());
+            row.add(bean.getWorkName());
+            row.add(bean.getWorkPhone());
+            row.add(bean.getType().equals(UserTypeEnum.GENERAL.toString()) ? "普通用户" : "业务员");
+            row.add("");
+            row.add(bean.getCreateTime() == null ? "" : simpleDateFormat.format(bean.getCreateTime()));
+            String city = "";
+            row.add(city);
+            rows.add(row);
+        }
+        String fileName = String.format("用户信息导出_%s.xlsx", simpleDateFormat.format(new Date()));
+        excelData.setTitles(Arrays.asList(titles));
+        excelData.setName("用户信息");
+        excelData.setRows(rows);
+        ExcelUtils.exportExcel(request, response, fileName, excelData, -1, null);
+    }
+
+    /**
+     * 更改会员状态
+     *
+     * @param userId
+     * @param status
+     */
+    public void updateState(String userId, Boolean status) {
+        userService.lambdaUpdate()
+                .eq(User::getUserId, userId)
+                .set(User::getStatus, status)
+                .update();
+    }
+
+
+    /**
+     * 会员资料修改
+     *
+     * @param user
+     */
+    public void update(User user) {
+        user.updateById();
+    }
+
+    /**
+     * 修改会员业务状态
+     */
+    @Transactional
+    public void changeServiceUser(String userId, String websitId, String websitName, String workUserId, String workName,
+                                  String position, String mobile, Boolean isService) {
+        User user = userService.getById(userId);
+        if (user.getInnerr()) {
+            throw new RemoteServiceException("请先取消内部人员");
+        }
+
+        final List<String> userIds = Collections.singletonList(userId);
+        this.batchChangeServiceUser(userIds, isService);
+
+        if (isService) {
+            if (StringUtils.isBlank(workUserId) || StringUtils.isBlank(workName) || StringUtils.isBlank(position) ||
+                    StringUtils.isBlank(mobile) || StringUtils.isBlank(websitId) || StringUtils.isBlank(websitName)) {
+                throw new RemoteServiceException("请填写关键信息");
+            }
+            userService.lambdaUpdate()
+                    .set(User::getWorkUserId, workUserId)
+                    .set(User::getWebsitId, websitId)
+                    .set(User::getWebsitName, websitName)
+                    .set(User::getWorkName, workName)
+                    .set(User::getPosition, position)
+                    .set(User::getWorkPhone, mobile)
+                    .set(User::getWorkCreateTime, new Date())
+                    .eq(User::getUserId, user.getUserId())
+                    .update();
+        }
+    }
+
+    private void batchChangeServiceUser(List<String> userIds, Boolean isService) {
+        // 1.将用户设为业务员或非业务员
+        userService.lambdaUpdate()
+                .set(User::getType, isService ? UserTypeEnum.SERVICE.toString() : UserTypeEnum.GENERAL.toString())
+                .set(isService, User::getWorkCreateTime, DateUtil.date())
+                .set(!isService, User::getWorkCreateTime, null)
+                .in(User::getUserId, userIds)
+                .update();
+
+        // 2.启用或禁用 用户分享优惠券
+        couponLogic.updateUserCouponTransfer(userIds, isService);
+    }
+
+    /**
+     * 修改会员内部人员状态
+     */
+    public void updateUserInnerStatus(String userId, Boolean inner) {
+        Long count = userService.lambdaQuery()
+                .eq(User::getUserId, userId)
+                .eq(User::getType, UserTypeEnum.SERVICE.getKey())
+                .count();
+        if (count == 0) {
+            throw new RemoteServiceException("只有业务员才能成为内部人员");
+        }
+        userService.lambdaUpdate()
+                .set(User::getInnerr, inner)
+                .eq(User::getUserId, userId)
+                .eq(User::getType, UserTypeEnum.SERVICE)
+                .update();
+    }
+
+    /**
+     * 导入跟新内部人员状态
+     */
+    @Transactional
+    public void localUpdateInner(HttpServletRequest request, MultipartFile multipartFile) throws IOException {
+        final AdminUserCom adminUser = commonLogic.getAdminUser(request);
+        final AdminCompanyWechat companyWechat = adminUser.getAdminCompanyWechat();
+        String loginCompanyWechatId = adminUser.getLoginCompanyWechatId();
+        if (StringUtils.isEmpty(loginCompanyWechatId)) {
+            throw new RemoteServiceException("无效企业微信id");
+        }
+
+        List<Object> objects = ExcelUtils.importExcel(multipartFile);
+        List<User> phoneList = new ArrayList<>();
+        List<User> innerPhoneList = new ArrayList<>();
+        for (int i = 0; i < objects.size(); i++) {
+            List<String> rows = (List<String>) objects.get(i);
+            CommonUtils.initList(rows, 7);
+            String typeStr = Objects.isNull(rows.get(1)) ? "业务员" : rows.get(1);
+            boolean isInner = typeStr.equals("内部人员");
+            User user = new User();
+            user.setMobile(rows.get(0));
+            user.setWebsitId(StringUtils.isNotBlank(rows.get(2)) ? rows.get(2).trim() : null);
+            user.setWebsitName(StringUtils.isNotBlank(rows.get(3)) ? rows.get(3).trim() : null);
+            user.setPosition(StringUtils.isNotBlank(rows.get(4)) ? rows.get(4).trim() : null);
+            user.setWorkName(StringUtils.isNotBlank(rows.get(5)) ? rows.get(5).trim() : null);
+            user.setWorkUserId(StringUtils.isNotBlank(rows.get(6)) ? rows.get(6).trim() : null);
+            user.setWorkPhone(user.getMobile());
+            user.setInnerr(isInner);
+
+            AdminWebsit adminWebsit;
+
+                adminWebsit = adminWebsitService.lambdaQuery()
+                        .eq(AdminWebsit::getCompanyWechatId, companyWechat.getCompanyWechatId())
+                        .eq(AdminWebsit::getWebsitNumber, user.getWebsitId())
+                        .one();
+                if (Objects.isNull(adminWebsit)) {
+                    adminWebsit = adminWebsitService.lambdaQuery()
+                            .eq(AdminWebsit::getCompanyWechatId, companyWechat.getCompanyWechatId())
+                            .orderByAsc(AdminWebsit::getCreateTime)
+                            .last("limit 1")
+                            .one();
+                }
+
+            user.setWebsitId(adminWebsit.getWebsitId() + "");
+            user.setWebsitName(adminWebsit.getName());
+            if (!isInner) {
+                if (StringUtils.isBlank(user.getWorkUserId())) {
+                    throw new RemoteServiceException(user.getMobile() + "账号必填");
+                }
+                if (StringUtils.isBlank(user.getWorkName())) {
+                    throw new RemoteServiceException(user.getMobile() + "姓名必填");
+                }
+                if (StringUtils.isBlank(user.getPosition())) {
+                    throw new RemoteServiceException(user.getMobile() + "职位必填");
+                }
+                phoneList.add(user);
+            } else {
+                innerPhoneList.add(user);
+            }
+        }
+
+        // 检查业务员手机号是否有重复的
+        final Map<String, List<User>> UserGroupMap = phoneList.stream().collect(Collectors.groupingBy(User::getMobile));
+        for (Map.Entry<String, List<User>> entry : UserGroupMap.entrySet()) {
+            if (entry.getValue().size() > 1) {
+                throw new RemoteServiceException("文档“业务员”有重复手机号 " + entry.getKey());
+            }
+        }
+
+        List<User> userList = userService.lambdaQuery()
+                .in(User::getMobile, phoneList.stream()
+                        .map(User::getMobile)
+                        .collect(Collectors.toList()))
+                .eq(User::getCompanyWechatId, loginCompanyWechatId)
+                .eq(User::getType, UserTypeEnum.GENERAL)
+                .eq(User::getStatus, true)
+                .list();
+
+        // 变成业务员
+        final List<String> userIds = userList.stream().map(User::getUserId).collect(Collectors.toList());
+        List<User> upUserList = new ArrayList<>();
+
+        if (CollectionUtil.isNotEmpty(userIds)) {
+            this.batchChangeServiceUser(userIds, true);
+
+            // 更新会员资料
+            final Map<String, User> importUserMap = phoneList.stream().collect(Collectors.toMap(User::getMobile, Function.identity()));
+            for (User user : userList) {
+                if (importUserMap.containsKey(user.getMobile())) {
+                    User newUser = new User();
+                    User importUser = importUserMap.get(user.getMobile());
+                    newUser.setUserId(user.getUserId())
+                            .setMobile(user.getMobile())
+                            .setWorkUserId(importUser.getWorkUserId())
+                            .setWorkName(importUser.getWorkName())
+                            .setWorkPhone(user.getMobile())
+                            .setWorkCreateTime(new Date())
+                            .setPosition(importUser.getPosition())
+                            .setWebsitId(importUser.getWebsitId())
+                            .setWebsitName(importUser.getWebsitName());
+                    upUserList.add(newUser);
+
+                }
+            }
+            if (CollectionUtil.isNotEmpty(upUserList)) {
+                userService.saveOrUpdateBatch(upUserList);
+            }
+
+        }
+
+        // 获取已存在记录
+        final List<UserServiceWait> existWaits = userServiceWaitService.lambdaQuery()
+                .eq(UserServiceWait::getCompanyWechatId, loginCompanyWechatId)
+                .in(UserServiceWait::getMobile, phoneList.stream().map(User::getMobile).collect(Collectors.toList()))
+                .list();
+        Map<String, UserServiceWait> waitMap = existWaits.stream().collect(Collectors.toMap(UserServiceWait::getMobile, Function.identity()));
+
+        // 遍历产生待处理记录
+        List<UserServiceWait> waitList = new ArrayList<>();
+        final Map<String, User> upUserMap = upUserList.stream().collect(Collectors.toMap(User::getMobile, Function.identity()));
+        final DateTime curDate = DateUtil.date();
+        for (User waitUser : phoneList) {
+            if (waitMap.containsKey(waitUser.getMobile())) {
+                // 如果存在记录忽略生成此手机号对象
+                waitList.add(waitMap.get(waitUser.getMobile()));
+                continue;
+            }
+            UserServiceWait wait = new UserServiceWait();
+            wait.setMobile(waitUser.getMobile())
+                    .setWebsitId(waitUser.getWebsitId())
+                    .setWebsitName(waitUser.getWebsitName())
+                    .setPosition(waitUser.getPosition())
+                    .setName(waitUser.getWorkName())
+                    .setWorkerId(waitUser.getWorkUserId())
+                    .setCreateTime(curDate)
+                    .setCreateBy(adminUser.getNickName())
+                    .setCompanyWechatId(loginCompanyWechatId)
+                    .setCompanyName(adminUser.getLoginCompanyName());
+            waitList.add(wait);
+        }
+        // 待处理记录不为空批量插入
+        if (CollectionUtil.isNotEmpty(waitList)) {
+            for (UserServiceWait serviceWait : waitList) {
+                // 本次更新用户资料在历史等待处理记录匹配到手机号
+                if (upUserMap.containsKey(serviceWait.getMobile())) {
+                    final User upUser = upUserMap.get(serviceWait.getMobile());
+                    serviceWait.setUserId(upUser.getUserId())
+                            .setIsBind(true)
+                            .setUpdateTime(new Date());
+                }
+            }
+
+            userServiceWaitService.saveOrUpdateBatch(waitList);
+        }
+
+        if (CollectionUtil.isNotEmpty(innerPhoneList)) {
+            // 升级为内部业务员
+            userService.lambdaUpdate()
+                    .set(User::getInnerr, true)
+                    .in(User::getMobile, innerPhoneList.stream()
+                            .map(User::getMobile)
+                            .collect(Collectors.toList()))
+                    .eq(User::getCompanyWechatId, loginCompanyWechatId)
+                    .eq(User::getType, UserTypeEnum.SERVICE)
+                    .eq(User::getStatus, true)
+                    .update();
+        }
+    }
+
+
+    /**
+     * 设置/取消团长
+     */
+    @Transactional
+    public void groupleader(String userId, Boolean promotionGroupLeader) {
+        User user = userService.getById(userId);
+        if (user == null) {
+            throw new RemoteServiceException("用户不存在");
+        }
+        user.setUserId(userId);
+        user.setPromotionGroupLeader(promotionGroupLeader);
+        user.setPromotionGroupUserId(userId);
+        user.updateById();
+        //添加到所有团购活动里
+        if (promotionGroupLeader) {
+
+            //    promotionGroupLogic.addGroupUser(user);
+        } else {
+            promotionGroupLogic.deleteGroupUser(user);
+        }
+    }
+
+    /**
+     * 用户详情
+     */
+    public UserWxBean detail(String userId) {
+        User user = userService.getById(userId);
+
+        UserWxBean userWxBean = new UserWxBean();
+        BeanUtils.copyProperties(user, userWxBean);
+
+        AdminCompanyWechat adminCompanyWechat = commonLogic.getAdminCompanyWechat(user.getCompanyWechatId());
+
+        //查询客户数
+        Long count = userService.lambdaQuery().eq(User::getServiceId, userId).count();
+
+        userWxBean.setCustomerNums(Math.toIntExact(count));
+        userWxBean.setTotalAmount(orderShareLogic.totalAmount(userId));
+
+        if (StringUtils.isNotEmpty(user.getServiceId())) {
+            User service = userService.getById(user.getServiceId());
+            if (service != null) {
+                userWxBean.setServiceName(service.getWorkName());
+                userWxBean.setServicePhone(service.getWorkPhone());
+            }
+        }
+
+        return userWxBean;
+    }
+
+
+    /**
+     * 修改用户昵称
+     */
+    public void updateUserNickName(String userId, String newNickName) {
+
+        userService.lambdaUpdate().set(User::getNickName, newNickName).eq(User::getUserId, userId).update();
+
+    }
+
+    /**
+     * 用户地址
+     */
+    public IPage<UserAddress> addressList(String userId, Integer pageNo, Integer pageSize) {
+        IPage<UserAddress> page = userAddressService.lambdaQuery().eq(UserAddress::getUserId, userId)
+                .orderByDesc(UserAddress::getCreateTime)
+                .page(new Page<>(pageNo, pageSize));
+        return page;
+    }
+
+    /**
+     * 我的收藏
+     */
+    public IPage<Goods> goodsFavoriteList(String userId, Integer pageNo, Integer pageSize) {
+        IPage<Goods> goodsIPage = customGoodsMapper.myGoodsFavorite(new Page(pageNo, pageSize), userId);
+        return goodsIPage;
+    }
+
+    /**
+     * 我的浏览记录
+     */
+    public IPage<GoodsVisit> goodsVisitList(String userId, Integer pageNo, Integer pageSize) {
+        return goodsVisitService.lambdaQuery().eq(GoodsVisit::getUserId, userId).page(new Page<>(pageNo, pageSize));
+    }
+
+    /**
+     * 我的优惠券
+     */
+    public IPage<UserCoupon> couponList(String userId, Integer pageNo, Integer pageSize) {
+        return couponLogic.userCouponList(userId, pageNo, pageSize);
+    }
+
+    /**
+     * 用户降级
+     */
+    public void demotion(List<String> workUserIds) {
+        List<User> list = userService.lambdaQuery().in(User::getWorkUserId, workUserIds).list();
+        if (list.size() == 0) {
+            return;
+        }
+        List<String> userIds = list.stream().map(User::getUserId).collect(Collectors.toList());
+        //1.将用户设为普通用户
+        userService.lambdaUpdate()
+                .set(User::getType, UserTypeEnum.GENERAL.toString())
+                .in(User::getWorkUserId, workUserIds).update();
+
+        //2.禁止用户分享优惠券
+        couponLogic.updateUserCouponTransfer(userIds, false);
+    }
+
+
+    /**
+     * 用户升级
+     */
+    public void userLevelUp(List<String> workUserIds) {
+        List<User> list = userService.lambdaQuery().in(User::getWorkUserId, workUserIds).list();
+        if (list.size() == 0) {
+            return;
+        }
+        List<String> userIds = list.stream().map(User::getUserId).collect(Collectors.toList());
+        //1.将用户设为普通用户
+        userService.lambdaUpdate()
+                .set(User::getType, UserTypeEnum.SERVICE.toString())
+                .in(User::getWorkUserId, workUserIds)
+                .update();
+
+        //2.禁止用户分享优惠券
+        couponLogic.updateUserCouponTransfer(userIds, true);
+    }
+
+
+    public User getById(String userId) {
+        return userService.getById(userId);
+    }
+
+    public List<User> getById(List<String> userIds) {
+        if (CollectionUtils.isEmpty(userIds)) {
+            return new ArrayList<>();
+        }
+        return userService.lambdaQuery().in(User::getUserId, userIds).orderByDesc(User::getCreateTime).list();
+    }
+
+    public List<User> getByMobile(List<String> mobiles) {
+        if (CollectionUtils.isEmpty(mobiles)) {
+            return new ArrayList<>();
+        }
+        return userService.lambdaQuery().in(User::getMobile, mobiles).orderByDesc(User::getCreateTime).list();
+    }
+
+    @Transactional
+    public void examineApply(String id, String websitId, String websitName, String workUserId, String workName, String position, String mobile, Boolean isOK) {
+        AdminUserCom adminUser = commonLogic.getAdminUser();
+        UserServiceApply apply = userServiceApplyService.getById(id);
+
+        if (StringUtils.isBlank(workUserId)) {
+            throw new RemoteServiceException("账号必填");
+        }
+        if (StringUtils.isBlank(workName)) {
+            throw new RemoteServiceException("姓名必填");
+        }
+        if (StringUtils.isBlank(position)) {
+            throw new RemoteServiceException("职位必填");
+        }
+        if (StringUtils.isBlank(mobile)) {
+            throw new RemoteServiceException("手机号必填");
+        }
+        if (StringUtils.isBlank(websitId)) {
+            throw new RemoteServiceException("网点编号必填");
+        }
+        if (StringUtils.isBlank(websitName)) {
+            throw new RemoteServiceException("网点名称必填");
+        }
+
+        apply.setStatus(isOK ? "OK" : "FAIL")
+                .setUpdateTime(DateUtil.date())
+                .setUpdateBy(adminUser.getNickName())
+                .updateById();
+
+        // 通过更新用户为业务员并注入手机号
+        if (isOK) {
+            final List<String> userIds = Collections.singletonList(apply.getUserId());
+            this.batchChangeServiceUser(userIds, true);
+
+            userService.lambdaUpdate()
+                    .set(User::getWorkUserId, workUserId)
+                    .set(User::getWebsitId, websitId)
+                    .set(User::getWebsitName, websitName)
+                    .set(User::getWorkName, workName)
+                    .set(User::getPosition, position)
+                    .set(User::getWorkPhone, mobile)
+                    .set(User::getWorkCreateTime, new Date())
+                    .set(User::getMobile, apply.getMobile())
+                    .eq(User::getUserId, apply.getUserId())
+                    .update();
+        }
+    }
+
+    public IPage<UserServiceWait> importMemberList(String websitId, String websitName, String workUserId, String workName,
+                                                   String position, String mobile, Integer pageNum, Integer pageSize) {
+        AdminUserCom adminUser = commonLogic.getAdminUser();
+        return userServiceWaitService.lambdaQuery()
+                .eq(UserServiceWait::getCompanyWechatId, adminUser.getLoginCompanyWechatId())
+                .like(StringUtils.isNotBlank(websitId), UserServiceWait::getWebsitId, websitId)
+                .like(StringUtils.isNotBlank(websitName), UserServiceWait::getWebsitName, websitName)
+                .like(StringUtils.isNotBlank(workUserId), UserServiceWait::getWorkerId, workUserId)
+                .like(StringUtils.isNotBlank(workName), UserServiceWait::getName, workName)
+                .like(StringUtils.isNotBlank(position), UserServiceWait::getPosition, position)
+                .like(StringUtils.isNotBlank(mobile), UserServiceWait::getMobile, mobile)
+                .orderByDesc(UserServiceWait::getCreateTime)
+                .page(new Page<>(pageNum, pageSize));
+    }
+}

+ 150 - 0
src/main/java/com/gree/mall/contest/utils/ArithUtils.java

@@ -0,0 +1,150 @@
+package com.gree.mall.contest.utils;
+
+
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+
+public class ArithUtils {
+    // 源文件Arith.java:
+
+    /**
+     * 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精 确的浮点数运算,包括加减乘除和四舍五入。
+     */
+
+    // 默认除法运算精度
+    private static final int DEF_DIV_SCALE = 10;
+
+    // 这个类不能实例化
+    private ArithUtils() {
+    }
+
+    /**
+     * 提供精确的加法运算。
+     *
+     * @param v1
+     *            被加数
+     * @param v2
+     *            加数
+     * @return 两个参数的和
+     */
+
+    public static double add(double v1, double v2) {
+        BigDecimal b1 = new BigDecimal(Double.toString(v1));
+        BigDecimal b2 = new BigDecimal(Double.toString(v2));
+        return b1.add(b2).doubleValue();
+    }
+
+    /**
+     * 提供精确的减法运算。
+     *
+     * @param v1
+     *            被减数
+     * @param v2
+     *            减数
+     * @return 两个参数的差
+     */
+
+    public static double sub(double v1, double v2) {
+        BigDecimal b1 = new BigDecimal(Double.toString(v1));
+        BigDecimal b2 = new BigDecimal(Double.toString(v2));
+        return b1.subtract(b2).doubleValue();
+    }
+
+    /**
+     * 提供精确的乘法运算。
+     *
+     * @param v1
+     *            被乘数
+     * @param v2
+     *            乘数
+     * @return 两个参数的积
+     */
+
+    public static double mul(double v1, double v2) {
+        BigDecimal b1 = new BigDecimal(Double.toString(v1));
+        BigDecimal b2 = new BigDecimal(Double.toString(v2));
+        return b1.multiply(b2).doubleValue();
+    }
+
+    //通过除法四舍五入保留2位小数
+    public static double mul(double v1, double v2,int scale) {
+        return div(mul(v1,v2),1,scale);
+    }
+
+    /**
+     * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。
+     *
+     * @param v1
+     *            被除数
+     * @param v2
+     *            除数
+     * @return 两个参数的商
+     */
+
+    public static double div(double v1, double v2) {
+        return div(v1, v2, DEF_DIV_SCALE);
+    }
+
+
+    /**
+     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 定精度,以后的数字四舍五入。
+     *
+     * @param v1
+     *            被除数
+     * @param v2
+     *            除数
+     * @param scale
+     *            表示表示需要精确到小数点以后几位。
+     * @return 两个参数的商
+     */
+
+    public static double div(double v1, double v2, int scale) {
+        if (scale < 0) {
+            throw new IllegalArgumentException(
+                    "The   scale   must   be   a   positive   integer   or   zero");
+        }
+        BigDecimal b1 = new BigDecimal(Double.toString(v1));
+        BigDecimal b2 = new BigDecimal(Double.toString(v2));
+        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
+    }
+
+    /**
+     *
+     * 提供精确的小数位四舍五入处理。
+     *
+     * @param v
+     *            需要四舍五入的数字
+     * @param scale
+     *            小数点后保留几位
+     * @return 四舍五入后的结果
+     */
+
+    public static double round(double v, int scale) {
+        if (scale < 0) {
+            throw new IllegalArgumentException(
+                    "The   scale   must   be   a   positive   integer   or   zero");
+        }
+        BigDecimal b = new BigDecimal(Double.toString(v));
+        BigDecimal one = new BigDecimal("1");
+        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
+    }
+
+    /**
+     * 向上取整
+     * @param v1
+     * @return
+     */
+    public static int roundUp(@NotNull BigDecimal v1) {
+        return v1.setScale( 0, BigDecimal.ROUND_UP ).intValue();
+    }
+
+
+    /**
+     * 向下取整
+     * @param v1
+     * @return
+     */
+    public static int roundDown(@NotNull BigDecimal v1) {
+        return v1.setScale( 0, BigDecimal.ROUND_DOWN ).intValue();
+    }
+}

+ 245 - 0
src/main/java/com/gree/mall/contest/utils/excel/ExcelUtils.java

@@ -0,0 +1,245 @@
+package com.gree.mall.contest.utils.excel;
+
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.excel.EasyExcelFactory;
+import com.alibaba.excel.read.listener.PageReadListener;
+import com.gree.mall.contest.bean.ExcelData;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import eu.bitwalker.useragentutils.Browser;
+import eu.bitwalker.useragentutils.UserAgent;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.streaming.SXSSFSheet;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFColor;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.awt.Color;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+public class ExcelUtils {
+
+
+    //常规导出excel
+    public static void exportExcel(HttpServletRequest request, HttpServletResponse response, String fileName, ExcelData data, int idIndex, int[] mergeRows) throws Exception {
+        setResponse(request, response, fileName);
+        // 下载文件的默认名称
+        exportExcel(data, response.getOutputStream(), idIndex, mergeRows);
+    }
+
+
+    public static void exportExcel(ExcelData data, OutputStream out, int idIndex, int[] mergeRows) throws Exception {
+
+        SXSSFWorkbook wb = new SXSSFWorkbook(5000);
+        try {
+            String sheetName = data.getName();
+            if (null == sheetName) {
+                sheetName = "Sheet1";
+            }
+            SXSSFSheet sheet = wb.createSheet(sheetName);
+            writeExcel(wb, sheet, data, idIndex, mergeRows);
+
+            wb.write(out);
+        } finally {
+            wb.close();
+        }
+    }
+
+    private static void writeExcel(SXSSFWorkbook wb, Sheet sheet, ExcelData data, int idIndex, int[] mergeRows) {
+
+        int rowIndex = 0;
+
+        rowIndex = writeTitlesToExcel(wb, sheet, data.getTitles());
+        writeRowsToExcel(wb, sheet, data.getRows(), rowIndex, idIndex, mergeRows);
+        autoSizeColumns(sheet, data.getTitles().size() + 1);
+
+    }
+
+    private static int writeTitlesToExcel(SXSSFWorkbook wb, Sheet sheet, List<String> titles) {
+        int rowIndex = 0;
+        int colIndex = 0;
+
+        Font titleFont = wb.createFont();
+        titleFont.setFontName("simsun");
+        titleFont.setBold(true);
+        // titleFont.setFontHeightInPoints((short) 14);
+        titleFont.setColor(IndexedColors.BLACK.index);
+
+        CellStyle titleStyle = wb.createCellStyle();
+//        titleStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);
+//        titleStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
+        //titleStyle.setFillForegroundColor(new XSSFColor(new Color(182, 184, 192)));
+//        titleStyle.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
+        titleStyle.setFont(titleFont);
+        titleStyle.setWrapText(true);
+        setBorder(titleStyle, BorderStyle.THIN, new XSSFColor(new Color(182, 184, 192)));
+
+        Row titleRow = sheet.createRow(rowIndex);
+        // titleRow.setHeightInPoints(25);
+        colIndex = 0;
+
+        for (String field : titles) {
+            Cell cell = titleRow.createCell(colIndex);
+            cell.setCellValue(field);
+            cell.setCellStyle(titleStyle);
+            colIndex++;
+        }
+
+
+        rowIndex++;
+        return rowIndex;
+    }
+
+    private static int writeRowsToExcel(SXSSFWorkbook wb, Sheet sheet, List<List<Object>> rows, int rowIndex, int idIndex, int[] mergeRows) {
+        int colIndex = 0;
+
+        Font dataFont = wb.createFont();
+        dataFont.setFontName("simsun");
+        // dataFont.setFontHeightInPoints((short) 14);
+        dataFont.setColor(IndexedColors.BLACK.index);
+
+        CellStyle dataStyle = wb.createCellStyle();
+        dataStyle.setAlignment(HorizontalAlignment.CENTER);
+        dataStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        dataStyle.setFont(dataFont);
+        dataStyle.setWrapText(true);
+        setBorder(dataStyle, BorderStyle.THIN, new XSSFColor(new Color(0, 0, 0)));
+        String lastCellValue = "$";
+        int startRow = 0;
+        int endRow = 0;
+        for (List<Object> rowData : rows) {
+            Row dataRow = sheet.createRow(rowIndex);
+            // dataRow.setHeightInPoints(25);
+            colIndex = 0;
+
+            for (Object cellData : rowData) {
+                Cell cell = dataRow.createCell(colIndex);
+                if (cellData != null) {
+                    cell.setCellValue(cellData.toString());
+                } else {
+                    cell.setCellValue("");
+                }
+                if (mergeRows != null && colIndex != -1 && colIndex == idIndex) {
+                    if (StringUtils.isNotBlank(cellData.toString()) && cellData.toString().equals(lastCellValue)) {
+                        if (startRow == 0 && endRow == 0) {
+                            startRow = rowIndex - 1;
+                            endRow = startRow + 1;
+                        } else {
+                            endRow++;
+                        }
+                    } else {
+                        if (startRow != 0 && endRow != 0) {
+                            for (int i = 0; i < mergeRows.length; i++) {
+                                CellRangeAddress region = new CellRangeAddress(startRow, endRow, mergeRows[i], mergeRows[i]);
+                                sheet.addMergedRegion(region);
+                            }
+                        }
+                        startRow = 0;
+                        endRow = 0;
+                    }
+                    lastCellValue = cellData.toString();
+                }
+
+                cell.setCellStyle(dataStyle);
+                colIndex++;
+            }
+            rowIndex++;
+
+
+        }
+        return rowIndex;
+    }
+
+    private static void autoSizeColumns(Sheet sheet, int columnNumber) {
+
+        for (int i = 0; i < columnNumber; i++) {
+//            int orgWidth = sheet.getColumnWidth(i);
+//            sheet.autoSizeColumn(i, true);
+//            int newWidth = (int) (sheet.getColumnWidth(i) + 100);
+//            if (newWidth > orgWidth) {
+//                sheet.setColumnWidth(i, newWidth);
+//            } else {
+//                sheet.setColumnWidth(i, orgWidth);
+//            }
+            int colWidth = sheet.getColumnWidth(i) * 2;
+            if (colWidth < 255 * 256) {
+                sheet.setColumnWidth(i, colWidth < 3000 ? 3000 : colWidth);
+            } else {
+                sheet.setColumnWidth(i, 6000);
+            }
+        }
+    }
+
+    private static void setBorder(CellStyle style, BorderStyle border, XSSFColor color) {
+        style.setBorderTop(border);
+        style.setBorderLeft(border);
+        style.setBorderRight(border);
+        style.setBorderBottom(border);
+//        style.setBorderColor(BorderSide.TOP, color);
+//        style.setBorderColor(BorderSide.LEFT, color);
+//        style.setBorderColor(BorderSide.RIGHT, color);
+//        style.setBorderColor(BorderSide.BOTTOM, color);
+    }
+
+    public static List<Object> importExcel(MultipartFile file) throws IOException, RemoteServiceException {
+        log.info("【本次导入数据】开始:" + cn.hutool.core.date.DateUtil.formatDate(new Date()));
+        List<Object> datas = new ArrayList<>();
+        EasyExcelFactory.read(file.getInputStream(), new PageReadListener<Map<Integer, Object>>(v -> {
+            for (Map<Integer, Object> map : v) {
+                List<Object> list = new ArrayList<>();
+                for (Integer key : map.keySet()) {
+                    list.add(map.get(key));
+                }
+                datas.add(list);
+            }
+        })).sheet().doRead();
+        log.info("【本次导入数据】结束:" + DateUtil.formatDate(new Date()) + ",一共" + datas.size());
+        return datas;
+    }
+
+
+    private static void setResponse(HttpServletRequest request, HttpServletResponse response, String fileName) throws Exception {
+        //        fileName = URLEncoder.encode(fileName, "UTF-8");
+        // 告诉浏览器用什么软件可以打开此文件
+//        response.setHeader("content-Type", "application/vnd.ms-excel");
+//        Header("Content-type: application/octet-stream");
+        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
+        response.setCharacterEncoding("UTF-8");
+        Browser browser = UserAgent.parseUserAgentString(request.getHeader("user-agent")).getBrowser();
+        if (browser != null) {
+            if (browser == Browser.IE || browser == Browser.EDGE) {
+                response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
+            } else if (browser == Browser.OPERA || browser == Browser.CHROME) {
+                response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName);
+            } else if (browser == Browser.SAFARI) {
+                response.setHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes("UTF-8"), "ISO8859-1") + "\"");
+            } else if (browser == Browser.FIREFOX) {
+                response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName);
+            } else {
+                response.addHeader("Content-Disposition", "attachment;filename=" + new String((fileName).getBytes("gb2312"), "ISO-8859-1"));
+//                response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"; filename*=UTF-8''" + fileName);
+//                response.setContentType("application/octet-stream;charset=utf-8");
+//                response.setHeader("Content-Disposition", "attachment;filename="+ new String(fileName.getBytes(),"iso-8859-1") + ".xls");
+//                response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
+            }
+        }
+    }
+
+    public static void exportExcel(HttpServletRequest request, HttpServletResponse response, String fileName, ExcelData excelData) throws Exception {
+        setResponse(request, response, fileName);
+        // 下载文件的默认名称
+        exportExcel(excelData, response.getOutputStream(), -1, null);
+    }
+}

+ 7 - 0
src/main/resources/application-dev.properties

@@ -5,6 +5,11 @@ sys.url=${domain.url}${server.servlet.context-path}
 #定时器
 schedule.enable=false
 
+#支付回调地址
+wechat.payment.notifyUrl=
+#退款回调地址
+wechat.payment.refundNotifyUrl=
+
 ##SQL执行分析,该插件有性能损耗,不建议生产环境使用
 spring.datasource.druid.db-type=mysql
 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
@@ -76,3 +81,5 @@ jwt.expire=7200
 
 knife4j.enable=true
 knife4j.setting.language=zh_cn
+
+

+ 5 - 0
src/main/resources/application-prd.properties

@@ -5,6 +5,11 @@ sys.url=${domain.url}${server.servlet.context-path}
 #定时器
 schedule.enable=true
 
+#支付回调地址
+wechat.payment.notifyUrl=
+#退款回调地址
+wechat.payment.refundNotifyUrl=
+
 ##SQL执行分析,该插件有性能损耗,不建议生产环境使用
 spring.datasource.druid.db-type=mysql
 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

+ 5 - 0
src/main/resources/application-test.properties

@@ -5,6 +5,11 @@ sys.url=${domain.url}${server.servlet.context-path}
 #定时器
 schedule.enable=true
 
+#支付回调地址
+wechat.payment.notifyUrl=
+#退款回调地址
+wechat.payment.refundNotifyUrl=
+
 ##SQL执行分析,该插件有性能损耗,不建议生产环境使用
 spring.datasource.druid.db-type=mysql
 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

+ 4 - 11
src/main/resources/application.properties

@@ -1,8 +1,3 @@
-#nacos
-spring.cloud.nacos.config.enabled=false
-spring.cloud.nacos.discovery.enabled=false
-spring.cloud.nacos.config.file-extension=properties
-
 spring.profiles.active=dev
 spring.application.name=mall-contest-service
 spring.main.allow-bean-definition-overriding=true
@@ -15,8 +10,7 @@ server.port =23006
 server.servlet.context-path=/mall-contest-api
 spring.servlet.multipart.max-file-size=40MB
 spring.servlet.multipart.max-request-size=40MB
-#�Ƿ�ֱ��web�˴�ӡ������Ϣ
-spring.devtools.add-properties=true
+
 #echache����
 spring.cache.type=ehcache
 spring.cache.ehcache.config=classpath:ehcache.xml
@@ -33,15 +27,14 @@ server.undertow.accesslog.prefix=access_log.
 server.undertow.accesslog.rotate=true
 server.undertow.accesslog.suffix=log
 server.undertow.max-http-post-size=10240000
-#swagger-login-account
-#spring.security.user.name=admin
-#spring.security.user.password=gree2021
+
 #mybatis-plus����
 mybatis-plus.mapper-locations=classpath*:mapper/*.xml,classpath*:mapper/**/*Mapper.xml
+
 #jackson���ʱ��
 spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
 spring.jackson.time-zone=GMT+8
 spring.jackson.timeZone=GMT+08:00
 spring.jackson.serialization.write_dates_as_timestamps=false
-spring.mvc.date-format=yyyy-MM-dd HH:mm:ss
+spring.mvc.format.date=yyyy-MM-dd HH:mm:ss
 web.upload-path=${user.dir}/static/

+ 39 - 0
src/main/resources/ehcache.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ehcache  name="learncache" updateCheck="false">
+
+    <!-- 磁盘缓存位置 -->
+    <diskStore path="java.io.tmpdir"/>
+    <!--默认缓存 单位:秒-->
+    <defaultCache
+            maxElementsInMemory="1000"
+            eternal="false"
+            timeToIdleSeconds="120"
+            timeToLiveSeconds="120"
+            maxElementsOnDisk="10000000"
+            diskExpiryThreadIntervalSeconds="120"
+            memoryStoreEvictionPolicy="LRU">
+        <persistence strategy="localTempSwap"/>
+    </defaultCache>
+    <!--首页报表缓存设置 单位:秒-->
+    <cache name="exhibition"
+           maxElementsInMemory="1000"
+           eternal="false"
+           timeToIdleSeconds="120"
+           timeToLiveSeconds="120"
+           maxElementsOnDisk="10000000"
+           diskExpiryThreadIntervalSeconds="120"
+           memoryStoreEvictionPolicy="LRU">
+        <persistence strategy="localTempSwap"/>
+    </cache>
+
+    <cache name="group"
+           maxElementsInMemory="1000"
+           eternal="false"
+           timeToIdleSeconds="120"
+           timeToLiveSeconds="120"
+           maxElementsOnDisk="10000000"
+           diskExpiryThreadIntervalSeconds="120"
+           memoryStoreEvictionPolicy="LRU">
+        <persistence strategy="localTempSwap"/>
+    </cache>
+</ehcache>

+ 212 - 0
src/main/resources/mapper/CouponDateMapper.xml

@@ -0,0 +1,212 @@
+<?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.gree.mall.contest.commonmapper.CouponDateMapper">
+
+    <resultMap id="BaseResultMap" type="com.gree.mall.contest.bean.coupon.CouponDataBean">
+        <result column="totalSaleValue" property="totalSaleValue"/>
+        <result column="totalDiscountValue" property="totalDiscountValue"/>
+        <result column="buyGoodsCount" property="buyGoodsCount"/>
+        <collection property="buyGoodsInfoList" javaType="java.util.List"
+                    ofType="com.gree.mall.contest.bean.coupon.BuyGoodsInfo">
+            <result column="goodsName" property="goodsName"/>
+            <result column="goodsCount" property="goodsCount"/>
+            <result column="memberCount" property="memberCount"/>
+        </collection>
+    </resultMap>
+
+    <select id="data" resultMap="BaseResultMap">
+        SELECT t1.*,
+               t2.*
+        FROM (
+                 SELECT SUM(t1.total_amount) AS totalSaleValue,
+                        SUM(t1.coupon_value) AS totalDiscountValue,
+                        SUM(t2.num)          AS buyGoodsCount
+                 FROM order_info t1
+                          LEFT JOIN order_detail t2 ON t1.order_id = t2.order_id
+                 WHERE t1.coupon_id = #{couponId}
+                   AND t1.order_status NOT IN ('NOPAY', 'CLOSE')
+             ) t1,
+             (
+                 SELECT t2.goods_name           AS goodsName,
+                        SUM(t2.num)             AS goodsCount,
+                        COUNT(DISTINCT user_id) AS memberCount
+                 FROM order_info t1
+                          LEFT JOIN order_detail t2 ON t1.order_id = t2.order_id
+                 WHERE t1.coupon_id = #{couponId}
+                   AND t1.order_status NOT IN ('NOPAY', 'CLOSE')
+                 GROUP BY t2.goods_name
+             ) t2
+    </select>
+
+    <select id="pageCoupon" resultType="com.gree.mall.contest.bean.coupon.CouponPageBean">
+        select cp.*,count(if(uc.user_id is null,null,1)) as receivedCount, count(if(uc.status=1,1,NULL)) as usedCount,
+        CASE when cp.flag &lt;> 'CANCEL' and cp.display_time > now() then 'WAIT'
+        when cp.flag = 'CANCEL' then 'CANCEL'
+        when cp.flag &lt;> 'CANCEL' and cp.obtain_end_time &lt; now() then 'END'
+        when cp.flag &lt;> 'CANCEL' and cp.display_time &lt; now() and cp.obtain_end_time > now() then 'START'
+        end 'releaseFlag'
+        from coupon cp left join user_coupon uc on cp.coupon_id= uc.coupon_id
+        <where>
+            <if test="flag != null and flag != ''">
+                <choose>
+                    <when test='flag == "WAIT"'>
+                        cp.flag &lt;> 'CANCEL' and cp.display_time > now()
+                    </when>
+                    <when test='flag == "CANCEL"'>
+                        cp.flag = 'CANCEL'
+                    </when>
+                    <when test='flag == "END"'>
+                        cp.flag &lt;> 'CANCEL' and cp.obtain_end_time &lt; now()
+                    </when>
+                    <when test='flag == "START"'>
+                        cp.flag &lt;> 'CANCEL' and cp.display_time &lt; now() and cp.obtain_end_time > now()
+                    </when>
+
+                </choose>
+            </if>
+            <if test="couponType != null and couponType !=''">
+                cp.coupon_type = #{couponType}
+            </if>
+            <if test="couponName != null and couponName !=''">
+                cp.coupon_name like concat('%',#{couponName,jdbcType=VARCHAR},'%')
+            </if>
+            <if test="companyWechatIds != null and companyWechatIds.size > 0">
+                and cp.company_wechat_id in
+                <foreach item="item" index="index" collection="companyWechatIds" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+        </where>
+        GROUP BY cp.coupon_id ORDER BY cp.create_time DESC
+    </select>
+
+
+    <select id="exportCoupon" resultType="com.gree.mall.contest.bean.coupon.CouponExportBean">
+        select
+            cp.coupon_id,
+            cp.coupon_amount,
+            count(uc.id) receive_amount,
+            count(uc.used_time) used_amount,
+            cp.coupon_value,
+            cp.coupon_name,
+            uc.receive_time,
+            uc.status,
+            uc.used_time,
+            ur.nick_name,
+            ur.mobile
+            from user_coupon uc
+            left join coupon cp on cp.coupon_id= uc.coupon_id
+            left join user ur on ur.user_id = uc.user_id
+        <where>
+            uc.self_use &lt;> 1 and uc.transfer_type=0
+            <if test="flag != null and flag != ''">
+                <choose>
+                    <when test='flag == "WAIT"'>
+                        and cp.flag &lt;> 'CANCEL' and cp.display_time > now()
+                    </when>
+                    <when test='flag == "CANCEL"'>
+                        and cp.flag = 'CANCEL'
+                    </when>
+                    <when test='flag == "END"'>
+                        and cp.flag &lt;> 'CANCEL' and cp.obtain_end_time &lt; now()
+                    </when>
+                    <when test='flag == "START"'>
+                        and cp.flag &lt;> 'CANCEL' and cp.display_time &lt; now() and cp.obtain_end_time > now()
+                    </when>
+
+                </choose>
+            </if>
+            <if test="couponType != null and couponType !=''">
+                and cp.coupon_type = #{couponType}
+            </if>
+            <if test="couponName != null and couponName !=''">
+                and cp.coupon_name like concat('%',#{couponName,jdbcType=VARCHAR},'%')
+            </if>
+            <if test="companyWechatIds != null and companyWechatIds.size > 0">
+                and cp.company_wechat_id in
+                <foreach item="item" index="index" collection="companyWechatIds" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+        </where>
+        group by cp.coupon_id
+        ORDER BY cp.create_time DESC
+    </select>
+    <select id="exportSelfCoupon" resultType="com.gree.mall.contest.bean.coupon.CouponExportBean">
+        select uc.receive_time,uc.coupon_name, uc.status,uc.used_time,oi.order_id,oi.pay_amount,
+        ur.nick_name,ur.mobile,ur.work_name,ur.work_phone,aw.`name` as websitName
+        from user_coupon uc left join
+        order_info oi on oi.user_coupon_id=uc.id and oi.order_status&lt;>'CLOSE'
+        left join coupon cp on cp.coupon_id= uc.coupon_id
+        left join user ur on ur.user_id = uc.user_id
+        left join admin_company_wechat acw on acw.company_wechat_id = ur.company_wechat_id
+        LEFT JOIN admin_websit aw on oi.websit_id = aw.websit_id
+        <where>
+            uc.self_use = 1
+            <if test="flag != null and flag != ''">
+                <choose>
+                    <when test='flag == "WAIT"'>
+                        and cp.flag &lt;> 'CANCEL' and cp.display_time > now()
+                    </when>
+                    <when test='flag == "CANCEL"'>
+                        and cp.flag = 'CANCEL'
+                    </when>
+                    <when test='flag == "END"'>
+                        and cp.flag &lt;> 'CANCEL' and cp.obtain_end_time &lt; now()
+                    </when>
+                    <when test='flag == "START"'>
+                        and cp.flag &lt;> 'CANCEL' and cp.display_time &lt; now() and cp.obtain_end_time > now()
+                    </when>
+
+                </choose>
+            </if>
+            <if test="couponType != null and couponType !=''">
+                and cp.coupon_type = #{couponType}
+            </if>
+            <if test="couponName != null and couponName !=''">
+                and cp.coupon_name like concat('%',#{couponName,jdbcType=VARCHAR},'%')
+            </if>
+            <if test="companyWechatIds != null and companyWechatIds.size > 0">
+                and cp.company_wechat_id in
+                <foreach item="item" index="index" collection="companyWechatIds" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+        </where>
+        ORDER BY cp.create_time DESC
+    </select>
+
+    <select id="couponTagUser" resultType="com.gree.mall.contest.bean.coupon.CouponUserBean">
+        SELECT cu.*,
+               ur.nick_name,
+               ur.mobile,
+               ur.sex,
+               ur.avatar,
+               ur.type,
+               ur.country,
+               ur.province,
+               ur.city
+        from coupon_user cu
+                 LEFT JOIN user ur on cu.user_id = ur.user_id
+        where cu.coupon_id = #{couponId}
+
+    </select>
+
+
+    <select id="reissueCouponUser" resultType="com.gree.mall.contest.bean.coupon.CouponUserTypeBean">
+        SELECT ur.user_id, ur.nick_name as userName, ur.type
+        fROM user ur
+
+        where ur.type = 'SERVICE'
+         and ur.company_wechat_id = #{companyWechatId}
+         and not EXISTS(
+            select uc.user_id
+            from user_coupon uc
+            where uc.coupon_id = #{couponId}
+            and uc.transfer_type = 1
+            and uc.user_id = ur.user_id
+        )
+    </select>
+
+
+</mapper>

+ 21 - 0
src/main/resources/mapper/CoustomUserCouponMapper.xml

@@ -0,0 +1,21 @@
+<?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.gree.mall.contest.commonmapper.CoustomUserCouponMapper">
+
+
+    <update id="decreaseLeftTimes">
+        update user_coupon
+        set left_share_times = left_share_times - 1
+        where id = #{id}
+    </update>
+
+
+    <update id="increaseLeftTimes">
+        update user_coupon
+        set left_share_times = left_share_times + 1
+        where id = #{id}
+    </update>
+
+
+
+</mapper>

+ 216 - 0
src/main/resources/mapper/CustomGoodsMapper.xml

@@ -0,0 +1,216 @@
+<?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.gree.mall.contest.commonmapper.CustomGoodsMapper">
+
+    <select id="pageList" resultType="com.gree.mall.contest.bean.goods.GoodsSpecBean">
+        SELECT
+        t1.*,
+        t1.goods_name AS goodsName,
+        ifnull(t2.share_amount,0) AS shareAmount,
+        ifnull(t2.share_percent,0) AS sharePercent,
+        ifnull(t2.inner_share_amount,0) AS innerShareAmount,
+        ifnull(t2.inner_share_percent,0) AS innerSharePercent,
+        <!--sum(if(t2.del=0 and t2.sold_num is NOT NULL,t2.sold_num,0)) AS soldNum,-->
+        sum(if(t2.del=0 and t2.stock_num is NOT NULL,t2.stock_num,0)) AS stockNum,
+        t3.`name` AS categoryName,
+        t2.bar_code
+        FROM
+        goods t1
+        left join goods_spec t2 on t1.goods_id = t2.goods_id         and t2.del = 0
+        left join goods_category t3 on t3.category_id = t1.category_id
+        WHERE
+        t1.del = 0
+        <if test='companyWechatIds != null and companyWechatIds.size > 0' >
+            AND t1.company_wechat_id  in
+            <foreach collection="companyWechatIds" open="(" close=")" item="companyWechatId" separator=",">
+                #{companyWechatId}
+            </foreach>
+        </if>
+        <if test='goodsTypes != null and goodsTypes.size > 0' >
+            AND t1.goods_type  in
+            <foreach collection="goodsTypes" open="(" close=")" item="item" separator=",">
+                #{item}
+            </foreach>
+        </if>
+        <if test="flag != null">
+            <choose>
+                <when test="flag == 'S'.toString()">AND t1.status = 1</when>
+                <when test="flag == 'W'.toString()">AND t1.status = 0</when>
+                <when test="flag == 'A'.toString()">AND t2.flag = 1</when>
+                <otherwise/>
+            </choose>
+        </if>
+        <if test="keyword != null and keyword != ''">
+            AND
+            (t1.goods_id like CONCAT('%', #{keyword},'%') OR t1.goods_name like CONCAT('%',#{keyword},'%') OR t3.`name`
+            like CONCAT('%',#{keyword},'%') OR CONCAT(t1.goods_name, '(', t2.`name`,')') like
+            CONCAT('%',#{keyword},'%'))
+        </if>
+        <if test="startPrice != null and endPrice != null">
+            AND
+            t2.price BETWEEN #{startPrice} AND #{endPrice}
+        </if>
+        <if test="startShare != null and endShare != null">
+            AND
+            t2.share_amount BETWEEN #{startShare} AND #{endShare}
+        </if>
+        <if test="categoryId != null and categoryId.size() != 0">
+            AND
+            t3.category_id in
+            <foreach item="item" index="index" collection="categoryId" open="(" separator="," close=")">
+                #{item}
+            </foreach>
+        </if>
+        <if test="status != null">
+            AND
+            t1.status = #{status}
+        </if>
+        group by t1.goods_id
+        <if test="flag == 'O'.toString()">
+            having sum(t2.stock_num) = 0
+        </if>
+        <choose>
+            <when test="sortStr == null">
+                ORDER BY t1.sort_num desc,t1.create_time desc
+            </when>
+            <otherwise>
+                ORDER BY t1.sort_num desc,${sortStr},t1.create_time desc
+            </otherwise>
+        </choose>
+    </select>
+
+    <select id="list" resultType="com.gree.mall.contest.bean.goods.GoodsSpecBean">
+        SELECT t1.*,
+               t1.goods_name                                                     AS goodsName,
+               ifnull(t2.share_amount, 0)                                        AS shareAmount,
+               ifnull(t2.share_percent, 0)                                       AS sharePercent,
+               sum(IF(t2.del = 0 AND t2.sold_num IS NOT NULL, t2.sold_num, 0))   AS soldNum,
+               sum(IF(t2.del = 0 AND t2.stock_num IS NOT NULL, t2.stock_num, 0)) AS stockNum
+        FROM goods_template gt
+                 LEFT JOIN goods t1 ON gt.goods_id = t1.goods_id
+                 LEFT JOIN goods_spec t2 ON t1.goods_id = t2.goods_id
+        WHERE gt.template_id = #{commonTemplateId}
+          and t1.del = 0
+        GROUP BY t1.goods_id
+        ORDER BY t1.sort_num DESC
+    </select>
+
+
+    <select id="countByType" resultType="com.gree.mall.contest.bean.goods.GoodsTypeCount">
+        select count(1) 'total', sum(if(status = true, 1, 0)) 'csz', sum(if(status = false, 1, 0)) 'ckz'
+        from goods
+        where del = false
+        <if test=' companyWechatIds != null and companyWechatIds.size > 0' >
+            AND company_wechat_id in
+            <foreach collection="companyWechatIds" open="(" close=")" item="companyWechatId" separator=",">
+                #{companyWechatId}
+            </foreach>
+        </if>
+    </select>
+
+    <select id="ysq" resultType="java.lang.Integer">
+        select count(*) total
+        from (select sum(stock_num), goods_id
+              from goods_spec
+              where del = false
+                <if test=' companyWechatIds != null and companyWechatIds.size > 0' >
+                    AND company_wechat_id in
+                    <foreach collection="companyWechatIds" open="(" close=")" item="companyWechatId" separator=",">
+                        #{companyWechatId}
+                    </foreach>
+                </if>
+              group by goods_id
+              having sum(stock_num) = 0) t
+    </select>
+
+    <select id="countByFlag" resultType="java.lang.Integer">
+        select count(DISTINCT t1.goods_id)
+        FROM goods t1
+        left join goods_spec t2 on t1.goods_id = t2.goods_id
+        WHERE t1.del = 0
+          AND t2.flag = 1
+          and t2.del = 0
+        <if test=' companyWechatIds != null and companyWechatIds.size > 0' >
+            AND t1.company_wechat_id in
+            <foreach collection="companyWechatIds" open="(" close=")" item="companyWechatId" separator=",">
+                #{companyWechatId}
+            </foreach>
+        </if>
+    </select>
+
+
+    <select id="queryGoodsCategoryByGoodsId" resultType="com.gree.mall.contest.plus.entity.GoodsCategory">
+        select a.* from goods_category a
+            join goods b on a.category_id = b.category_id
+            where b.goods_id=#{goodsId}
+    </select>
+
+    <update id="syncGoodsSpecInnerShareMsg" parameterType="java.lang.String">
+        update goods_spec
+        set inner_share_amount = share_amount , inner_share_percent = share_percent
+        where inner_share_amount is null and inner_share_amount is null and company_wechat_id = #{companyWechatId}
+    </update>
+
+
+
+    <select id="queryGoodsPackageList" resultType="com.gree.mall.contest.bean.goods.GoodsPackageList">
+          select
+            a.goods_id,
+            a.img_url,
+            a.goods_name,
+            a.status,
+            (select count(DISTINCT goods_id) from goods_package_pop where goods_package_id= a.goods_id) 'goodsNums',
+            a.package_min_amount,
+            a.package_min_share_amount,
+            use_coupon,
+            count(DISTINCT c.order_id) 'orderNums',
+            sum(c.pay_amount) 'orderPayAmount',
+            a.package_user_type,
+            a.company_name
+
+            from goods a
+            left join order_info c on c.promotion_package_goods_id=a.goods_id and c.order_status in ('DFH','YFH','OVER')
+            where a.goods_type='PACKAGE'
+        and a.del = 0
+        <if test='companyWechatIds != null and companyWechatIds.size > 0' >
+            AND a.company_wechat_id  in
+            <foreach collection="companyWechatIds" open="(" close=")" item="companyWechatId" separator=",">
+                #{companyWechatId}
+            </foreach>
+        </if>
+        <if test="keyword != null and keyword != ''">
+            AND(a.goods_id like CONCAT('%', #{keyword},'%') OR a.goods_name like CONCAT('%',#{keyword},'%'))
+        </if>
+        <if test="startPrice != null and endPrice != null">
+            AND
+            a.package_min_amount BETWEEN #{startPrice} AND #{endPrice}
+        </if>
+        <if test="startShare != null and endShare != null">
+            AND
+            a.package_min_share_amount BETWEEN #{startShare} AND #{endShare}
+        </if>
+        <if test="categoryId != null and categoryId.size() != 0">
+            AND
+            a.category_id in
+            <foreach item="item" index="index" collection="categoryId" open="(" separator="," close=")">
+                #{item}
+            </foreach>
+        </if>
+        <if test="status != null">
+            AND
+            a.status = #{status}
+        </if>
+        group by a.goods_id
+        <choose>
+            <when test="sortStr == null">
+                ORDER BY a.sort_num desc,a.create_time desc
+            </when>
+            <otherwise>
+                ORDER BY a.sort_num desc,${sortStr},a.create_time desc
+            </otherwise>
+        </choose>
+
+    </select>
+
+
+</mapper>

+ 31 - 0
src/main/resources/mapper/CustomMemberMapper.xml

@@ -0,0 +1,31 @@
+<?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.gree.mall.contest.commonmapper.CustomMemberMapper">
+    <select id="queryUser" resultType="com.gree.mall.contest.bean.member.MemberBean">
+        select ur.*
+        from user ur
+        left join admin_websit aw on aw.websit_id = ur.websit_id
+        where
+        ur.status =1
+        <if test=' companyWechatIds != null and companyWechatIds.size > 0' >
+            and ur.company_wechat_id in
+            <foreach collection="companyWechatIds" open="(" close=")" item="companyWechatId" separator=",">
+                #{companyWechatId}
+            </foreach>
+        </if>
+        <if test="type != null and type !=''">
+            and ur.type = #{type}
+        </if>
+        <if test="startTime != null and endTime != null">
+            and ur.create_time between #{startTime} and #{endTime}
+        </if>
+        <if test="keyword != null and keyword !=''">
+            and (ur.nick_name like concat('%',#{keyword,jdbcType=VARCHAR},'%') or ur.mobile like
+            concat('%',#{keyword,jdbcType=VARCHAR},'%'))
+        </if>
+        order by ur.create_time
+    </select>
+
+
+
+</mapper>

+ 22 - 0
src/main/resources/mapper/CustomWebsitMapper.xml

@@ -0,0 +1,22 @@
+<?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.gree.mall.contest.commonmapper.CustomWebsitMapper">
+
+    <select id="queryById" resultType="java.lang.String">
+        select websit_number
+        from (
+                 select t1.id,
+                        t1.parent_id,
+                        t1.websit_number,
+                        if(find_in_set(parent_id, @pids) > 0, @pids := concat(@pids, ',', id), -1) as ischild
+                 from (
+                          select id, parent_id,websit_number
+                          from admin_websit
+                          ORDER BY id ASC) t1,
+                      (select @pids :=#{id}) t2
+             ) t3
+        where ischild != -1 or id = #{id}
+    </select>
+
+
+</mapper>

+ 31 - 0
src/main/resources/mapper/GoodsCheckMapper.xml

@@ -0,0 +1,31 @@
+<?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.gree.mall.contest.commonmapper.GoodsCheckMapper">
+
+    <select id="checkGoodsSec" resultType="java.lang.Integer">
+        SELECT count(DISTINCT ska.sec_kill_id)
+        from sec_kill_activity ska
+                 LEFT JOIN sec_kill_activity_spec skas on ska.sec_kill_id = skas.sec_kill_id
+                 left join goods gs on gs.goods_id = skas.goods_id
+        where gs.goods_id = #{goodsId}
+          and gs.del = 0
+          and gs.status = 1
+          and ska.end_time > now()
+
+    </select>
+
+
+    <select id="checkGoodsSecBatch" resultType="java.lang.String">
+        SELECT distinct gs.goods_id from sec_kill_activity ska LEFT JOIN sec_kill_activity_spec skas on
+        ska.sec_kill_id=skas.sec_kill_id
+        left join goods gs on gs.goods_id = skas.goods_id
+        where gs.goods_id in
+        <foreach item="item" index="index" collection="goodsIds" open="(" separator=","
+                 close=")">
+            #{item}
+        </foreach>
+        and gs.del = 0 and gs.status = 1
+        and ska.end_time>now()
+    </select>
+
+</mapper>

+ 118 - 0
src/main/resources/mapper/OrderMapper.xml

@@ -0,0 +1,118 @@
+<?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.gree.mall.contest.commonmapper.OrderMapper">
+
+
+    <select id="selectByQueryMsg" resultType="com.gree.mall.contest.bean.order.OrderDetailListBean">
+        select
+        o.order_id as orderId,
+        od.goods_name as goodsName,
+        CONCAT(od.goods_spec_name,'(',od.goods_spec_value,')') as goodsSpecValue,
+        od.num as num,
+        od.price as price,
+        od.pay_amount as payAmount,
+        od.work_order_type,
+        o.rece_user_name as receUserName,
+        o.rece_phone as recePhone,
+        CONCAT(o.province,o.city,o.area,o.street,o.rece_address,o.house_no) as address,
+        o.order_status as orderStatus,
+        o.refund_flag as refundFlag,
+        od.refund_amount as refundAmount,
+        od.refund_num as refundNum,
+        o.remark as remark,
+        o.create_time as createTime,
+        o.pay_time,
+        o.user_name as userName,
+        o.worker_name as workerName,
+        o.buyer_msg as buyerMsg,
+        o.remark as remark,
+        o.websit_name as websitName,
+        CONCAT( o.worker_name,'/',o.websit_name) as workerNameWithWebsitName,
+        od.share_amount as shareAmount ,
+        u.nick_name as nickName,
+        u.mobile as mobile,
+        o.promotion_group_id as promotionGroupId,
+        GROUP_CONCAT(odr.worker_order_no) workerOrderNo,
+         o.comment_goods as commentGoods,
+        o.comment_service as commentService,
+        o.comment_express as commentExpress,
+        o.worker_phone,
+        o.promotion_package_goods,
+        gs.goods_code,
+        o.is_add_corp,
+        o.buyer_name,
+        o.buyer_id_card,
+        o.buyer_mobile,
+        o.coupon_merchant_contribute,
+        gs.bar_code,
+        o.transaction_id
+
+        from order_detail od
+         join order_info o  on od.order_id = o.order_id
+        left join goods_spec gs on gs.goods_spec_id = od.goods_spec_id
+        LEFT join `user` u  on o.promotion_group_user_id=u.user_id
+        LEFT JOIN order_request odr on odr.order_id=o.order_id
+
+        <where>
+            <if test="userId != null and userId != ''">
+                and o.user_id=#{userId}
+            </if>
+            <if test="orderId != null and orderId != ''">
+                and o.order_id like  CONCAT('%',#{orderId},'%')
+            </if>
+            <if test="productName != null and productName != ''">
+                and o.order_title like  CONCAT('%',#{productName},'%')
+            </if>
+            <if test="userName != null and userName != ''">
+                and (o.rece_user_name like CONCAT('%',#{userName},'%') or o.user_name like CONCAT('%',#{userName},'%') )
+            </if>
+            <if test="phone != null and phone != ''">
+                and (o.phone like  CONCAT('%',#{phone},'%') or o.rece_phone like CONCAT('%',#{phone},'%')  or o.worker_phone like CONCAT('%',#{phone},'%'))
+            </if>
+            <if test="exchangeCode != null and exchangeCode != ''">
+                and o.exchange_code like  CONCAT('%',#{exchangeCode},'%')
+            </if>
+            <if test="orderStatus != null and orderStatus != ''">
+                and o.order_status = #{orderStatus}
+            </if>
+            <if test="orderStatus != null and orderStatus=='DFH'">
+                and od.refund_num = 0
+            </if>
+
+            <if test="startCreateTime != null and startCreateTime != '' and endCreateTime != null and endCreateTime != ''">
+                and (o.create_time between #{startCreateTime} and #{endCreateTime})
+            </if>
+
+            <if test="startPayTime != null and startPayTime != '' and endPayTime != null and endPayTime != ''">
+                and (o.pay_time between #{startPayTime} and #{endPayTime})
+            </if>
+            <if test="promotionGroupId != null and promotionGroupId != ''">
+                and o.promotion_group_id=#{promotionGroupId}
+            </if>
+            <if test="promotionGroupUserId != null and promotionGroupUserId != ''">
+                and o.promotion_group_user_id=#{promotionGroupUserId}
+            </if>
+            <if test="websitId != null and websitId !=''">
+                and o.websit_id = #{websitId}
+            </if>
+            <if test="goodsId != null and goodsId !=''">
+                and o.promotion_package_goods_id = #{goodsId}
+            </if>
+            <if test="companyWechatIds != null and companyWechatIds.size > 0">
+                and o.company_wechat_id in
+                <foreach item="item" index="index" collection="companyWechatIds" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+            <if test="websitIds != null and websitIds.size > 0">
+                and o.websit_id in
+                <foreach item="item" index="index" collection="websitIds" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+        </where>
+        GROUP BY od.order_detail_id
+        order by o.create_time desc
+    </select>
+
+</mapper>

+ 77 - 0
src/main/resources/mapper/OrderRefundInfoMapper.xml

@@ -0,0 +1,77 @@
+<?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.gree.mall.contest.commonmapper.OrderRefundInfoMapper">
+
+
+    <select id="getOrderRefundDetailList" resultType="com.gree.mall.contest.bean.order.OrderDetailListBean">
+        SELECT
+            ord.order_id as orderId,
+            od.goods_name as goodsName,
+            CONCAT(od.goods_spec_name,'(',od.goods_spec_value,')') as goodsSpecValue,
+            od.num as num,
+            od.price as price,
+            od.pay_amount as payAmount,
+            od.total_price as totalPrice,
+            ord.rece_user_name as receUserName,
+            ord.rece_phone as recePhone,
+            CONCAT(ord.province,ord.city,ord.area,ord.street,ord.rece_address,ord.house_no) as address,
+            ord.order_status as orderStatus,
+            o.refund_flag as refundFlag,
+            od.refund_amount as refundAmount,
+            od.refund_num as refundNum,
+            ord.remark as remark,
+            o.create_time as createTime,
+            ord.user_name as userName,
+            ord.worker_name as workerName,
+            o.buyer_msg as buyerMsg,
+            ord.refund_message as refundMessage,
+            ord.websit_name as websitName,
+            CONCAT( ord.worker_name,'/',ord.websit_name) as workerNameWithWebsitName,
+            od.share_amount as shareAmount ,
+            u.nick_name as nickName,
+            u.mobile as mobile,
+            od.promotion_group_id as promotionGroupId,
+            ord.refund_explain as refundExplain
+        from order_refund ord
+        LEFT JOIN `user` u on u.user_id=ord.user_id
+        LEFT JOIN order_info o on o.order_id=ord.order_id
+        LEFT JOIN order_detail od  on ord.order_id=od.order_id
+        <where>
+            <if test="orderId != null and orderId != ''">
+                and ord.order_id like CONCAT('%',#{orderId},'%')
+            </if>
+            <if test="orderRefundId != null and orderRefundId != ''">
+                and ord.order_refund_id like CONCAT('%',#{orderRefundId},'%')
+            </if>
+            <if test="userName != null and userName != ''">
+                and ord.user_name like CONCAT('%',#{userName},'%')
+            </if>
+            <if test="phone != null and phone != ''">
+                and ord.phone like CONCAT('%',#{phone},'%')
+            </if>
+            <if test="orderStatus != null and orderStatus != ''">
+                and ord.order_status=#{orderStatus}
+            </if>
+            <if test="startCreateTime != null and endCreateTime != null">
+                and ord.create_time between #{startCreateTime} and #{endCreateTime}
+            </if>
+            <if test="startExamineTime != null and endExamineTime != null">
+                and ord.examine_time between #{startExamineTime} and #{endExamineTime}
+            </if>
+            <if test="companyWechatIds != null and companyWechatIds.size > 0">
+                and ord.company_wechat_id in
+                <foreach item="item" index="index" collection="companyWechatIds" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+            <if test="websitIds != null and websitIds.size > 0">
+                and ord.websit_id in
+                <foreach item="item" index="index" collection="websitIds" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+        </where>
+        order by ord.create_time desc
+    </select>
+
+</mapper>

+ 117 - 0
src/main/resources/mapper/OrderShareReportMapper.xml

@@ -0,0 +1,117 @@
+<?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.gree.mall.contest.commonmapper.OrderShareReportMapper">
+    <select id="queryReport" resultType="com.gree.mall.contest.bean.order.OrderShareReportBean">
+        select od.order_id,
+        CONCAT(od.goods_name, '(', od.goods_spec_value, ')') as goodsName,
+        od.price,
+        od.num,
+        od.total_price,
+        oi.order_status,
+        oi.user_id,
+        oi.create_time,
+        oi.pay_amount,
+        oi.pay_type,
+        oi.freight,
+        oi.pay_time,
+        oi.remark,
+        oi.rece_user_name,
+        oi.rece_phone,
+        CONCAT(oi.province,oi.city,oi.area,oi.street,oi.rece_address,oi.house_no) as address,
+        oi.logistics_no,
+        ec.name,
+        ot.type,
+        ot.name as tax_name,
+        ot.content,
+        ot.tax_no,
+        ot.register_address,
+        ot.register_phone,
+        ot.bank,
+        ot.account,
+        ot.receiver_email,
+        ot.receiver_phone,
+        ot.receiver_name,
+        ot.receiver_address,
+        oi.discount_amount,
+        oi.coupon_name,
+        oi.transaction_id,
+        os.order_share_id,
+        os.status as shareStatus,
+        os.work_user_name,
+        aw.name as websitName,
+        od.share_amount,
+        od.main_number,
+        os.amount,
+        os.settle_time
+        from order_detail od
+        left join order_info oi on od.order_id = oi.order_id
+        LEFT JOIN order_share os on os.order_id = oi.order_id
+        LEFT JOIN order_tax ot on ot.order_id = os.order_id
+        LEFT JOIN admin_websit aw on oi.websit_id = aw.websit_id
+        LEFT JOIN express_company ec on ec.code = oi.company_code
+        where od.order_id in
+        <foreach item="item" index="index" collection="orderIds" open="(" separator=","
+                 close=")">
+            #{item}
+        </foreach>
+        order by od.order_id desc
+
+    </select>
+
+    <select id="queryReport2" resultType="com.gree.mall.contest.bean.order.OrderShareReportBean">
+        select
+        acw.company_name as shopName,
+        os.order_share_id as orderShareId,
+        os.order_id as orderId,
+        oi.total_product_amount as totalPrice,
+        oi.pay_amount as payAmount,
+        oi.freight as freight,
+        oi.order_status as orderStatus,
+        oi.refund_flag as refundFlag,
+        oi.user_id as userId,
+        oi.create_time as createTime,
+        oi.pay_type as payType,
+        oi.pay_time as payTime,
+        oi.remark as remark,
+        oi.rece_user_name as receUserName,
+        oi.rece_phone as recePhone,
+        CONCAT(oi.province,oi.city,oi.area,oi.street,oi.rece_address,oi.house_no) as address,
+        oi.logistics_no as logisticsNo,
+        ec.name as name,
+        ot.type as type,
+        ot.name as taxName,
+        ot.content as content,
+        ot.tax_no as taxNo,
+        ot.register_address as registerAddress,
+        ot.register_phone as registerPhone,
+        ot.bank as  bank,
+        ot.account as account,
+        ot.receiver_email as receiverEmail,
+        ot.receiver_phone as receiverPhone,
+        ot.receiver_name as receiverName,
+        ot.receiver_address as receiverAddress,
+        oi.discount_amount as discountAmount,
+        oi.coupon_name as couponName,
+        oi.transaction_id as transactionId,
+        os.status as shareStatus ,
+        os.work_user_name as workUserName,
+        aw.name as websitName,
+        os.amount as amount,
+        os.settle_time as settleTime
+
+        from order_share os
+        left join order_info oi  on os.order_id = oi.order_id
+        left JOIN order_tax ot on oi.order_id = ot.order_id
+        left join admin_company_wechat acw on os.company_wechat_id = acw.company_wechat_id
+        left JOIN admin_websit aw on oi.websit_id = aw.websit_id
+        left JOIN express_company ec on ec.code = oi.company_code
+        where os.order_share_id in
+        <foreach item="item" index="index" collection="orderShareIdList" open="(" separator=","
+                 close=")">
+            #{item}
+        </foreach>
+        group by os.order_share_id
+        order by os.create_time desc ,ot.create_time desc
+
+    </select>
+</mapper>

+ 54 - 0
src/main/resources/mapper/PromotionMapper.xml

@@ -0,0 +1,54 @@
+<?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.gree.mall.contest.commonmapper.PromotionMapper">
+
+    <select id="queryOrderTotalAmount" resultType="java.math.BigDecimal">
+        select ifnull(sum(b.pay_amount) - sum(b.refund_amount),0) total from order_info a
+            join order_detail b on a.order_id = b.order_id
+            where a.order_status in ('DFH','YFH','OVER','REFUND') and a.promotion_group_id=#{promotionGroupId}
+    </select>
+
+    <select id="queryTotalShareAmount" resultType="java.math.BigDecimal">
+            select sum(amount) total from order_share where 1=1
+              <if test="status == null or status ==''">
+                  and status not in ('CANCEL','TIMEOUT')
+              </if>
+              <if test="status != null and status !=''">
+                  and status = #{status}
+              </if>
+               <if test="promotionGroupId != null and promotionGroupId !=''">
+                   and promotion_group_id=#{promotionGroupId}
+               </if>
+              <if test="userId != null and userId !=''">
+                  and work_user_id =#{userId}
+              </if>
+
+    </select>
+
+    <select id="queryGroupSpecUser" resultType="com.gree.mall.contest.bean.activity.PromotionGroupDetail">
+        select  DISTINCT user_id,user_name,user_phone from promotion_group_spec_user where promotion_group_id = #{promotionGroupId}
+    </select>
+
+    <select id="queryPtDetail" resultType="com.gree.mall.contest.bean.activity.PromotionGroupDetail">
+        select
+            count(1) 'orderNum',
+            sum(total_num) 'goodsNum',
+            sum(pay_amount) 'orderTotalAmount'
+        from order_info
+        where promotion_group_user_id=#{userId} and promotion_group_id = #{promotionGroupId}
+        and order_status not in ('CLOSE','TIMEOUT')
+    </select>
+
+    <select id="queryTotalGoodsNum" resultType="java.lang.Integer">
+        select sum(b.num) - sum(b.refund_num) total from order_info a
+        join order_detail b on a.order_id=b.order_id
+        where a.order_status not in ('CLOSE','TIMEOUT')
+        <if test="promotionGroupId != null and promotionGroupId !=''">
+            and a.promotion_group_id=#{promotionGroupId}
+        </if>
+        <if test="userId != null and userId !=''">
+            and a.promotion_group_user_id =#{userId}
+        </if>
+    </select>
+
+</mapper>