Explorar o código

完成优惠券拆分,测试完成好友赠券,新增优惠券

lutong hai 1 mes
pai
achega
6b9f1d8ed9
Modificáronse 16 ficheiros con 232 adicións e 30 borrados
  1. 8 0
      alien-entity/src/main/java/shop/alien/entity/store/LifeDiscountCoupon.java
  2. 6 0
      alien-entity/src/main/java/shop/alien/entity/store/dto/LifeDiscountCouponDto.java
  3. 6 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/LifeDiscountCouponFriendRuleVo.java
  4. 6 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/LifeDiscountCouponVo.java
  5. 3 1
      alien-entity/src/main/java/shop/alien/mapper/LifeDiscountCouponFriendRuleDetailMapper.java
  6. 2 1
      alien-entity/src/main/java/shop/alien/mapper/LifeDiscountCouponMapper.java
  7. 6 2
      alien-entity/src/main/java/shop/alien/mapper/LifeDiscountCouponStoreFriendMapper.java
  8. 3 0
      alien-entity/src/main/resources/mapper/LifeDiscountCouponMapper.xml
  9. 4 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/LifeDiscountCouponPlatformServiceImpl.java
  10. 9 7
      alien-store/src/main/java/shop/alien/store/controller/LifeDiscountCouponController.java
  11. 7 5
      alien-store/src/main/java/shop/alien/store/controller/LifeDiscountCouponStoreFriendController.java
  12. 1 1
      alien-store/src/main/java/shop/alien/store/service/LifeDiscountCouponService.java
  13. 2 1
      alien-store/src/main/java/shop/alien/store/service/LifeDiscountCouponStoreFriendService.java
  14. 36 2
      alien-store/src/main/java/shop/alien/store/service/LifeUserOrderService.java
  15. 86 5
      alien-store/src/main/java/shop/alien/store/service/impl/LifeDiscountCouponServiceImpl.java
  16. 47 5
      alien-store/src/main/java/shop/alien/store/service/impl/LifeDiscountCouponStoreFriendServiceImpl.java

+ 8 - 0
alien-entity/src/main/java/shop/alien/entity/store/LifeDiscountCoupon.java

@@ -146,6 +146,14 @@ public class LifeDiscountCoupon extends Model<LifeDiscountCoupon> {
     @TableField("valid_date")
     private LocalDate validDate;
 
+    @ApiModelProperty(value = "优惠券类型:1-满减券,2-折扣券")
+    @TableField("coupon_type")
+    private Integer couponType;
+
+    @ApiModelProperty(value = "折扣率(0-100,用于折扣券,例如80表示8折)")
+    @TableField("discount_rate")
+    private BigDecimal discountRate;
+
     @Override
     protected Serializable pkVal() {
         return this.id;

+ 6 - 0
alien-entity/src/main/java/shop/alien/entity/store/dto/LifeDiscountCouponDto.java

@@ -113,4 +113,10 @@ public class LifeDiscountCouponDto {
 
     @ApiModelProperty(value = "优惠券状态:0:草稿,1:正式")
     private Integer couponStatus;
+
+    @ApiModelProperty(value = "优惠券类型:1-满减券,2-折扣券")
+    private Integer couponType;
+
+    @ApiModelProperty(value = "折扣率(0-100,用于折扣券,例如80表示8折)")
+    private BigDecimal discountRate;
 }

+ 6 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/LifeDiscountCouponFriendRuleVo.java

@@ -58,5 +58,11 @@ public class LifeDiscountCouponFriendRuleVo extends LifeDiscountCouponFriendRule
     @ApiModelProperty(value = "有效期(优惠券/代金券的结束日期)")
     private Date validDate;
 
+    @ApiModelProperty(value = "优惠券类型:1-满减券,2-折扣券(仅优惠券有值,代金券为null)")
+    private Integer couponType;
+
+    @ApiModelProperty(value = "折扣率(0-100,用于折扣券,例如80表示8折,仅折扣券有值)")
+    private BigDecimal discountRate;
+
     private List<LifeDiscountCouponFriendRuleDetailVo> lifeDiscountCouponFriendRuleDetailVos;
 }

+ 6 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/LifeDiscountCouponVo.java

@@ -168,6 +168,12 @@ public class LifeDiscountCouponVo {
     @ApiModelProperty(value = "到期日期")
     private LocalDate expirationTime;
 
+    @ApiModelProperty(value = "优惠券类型:1-满减券,2-折扣券")
+    private Integer couponType;
+
+    @ApiModelProperty(value = "折扣率(0-100,用于折扣券,例如80表示8折)")
+    private BigDecimal discountRate;
+
     @ApiModelProperty(value = "创建时间")
     @TableField(value = "created_time")
     @JsonFormat(pattern = "yyyy/MM/dd", timezone = "GMT+8")

+ 3 - 1
alien-entity/src/main/java/shop/alien/mapper/LifeDiscountCouponFriendRuleDetailMapper.java

@@ -35,7 +35,9 @@ public interface LifeDiscountCouponFriendRuleDetailMapper extends BaseMapper<Lif
             "COALESCE(c.end_get_date, v.end_date) AS endDate, " +
             "COALESCE(c.name, v.name) AS couponName, " +
             "c.id AS couponId, " +
-            "d.voucher_id AS voucherId " +
+            "d.voucher_id AS voucherId, " +
+            "c.coupon_type AS couponType, " +
+            "c.discount_rate AS discountRate " +
             "FROM life_discount_coupon_friend_rule a " +
             "INNER JOIN life_discount_coupon_friend_rule_detail d ON d.rule_id = a.id " +
             "LEFT JOIN life_discount_coupon c ON d.coupon_id = c.id " +

+ 2 - 1
alien-entity/src/main/java/shop/alien/mapper/LifeDiscountCouponMapper.java

@@ -72,7 +72,8 @@ public interface LifeDiscountCouponMapper extends BaseMapper<LifeDiscountCoupon>
      * @param storeId      店铺ID
      * @param couponStatus 券状态
      * @param type         类型,可为 null(不按 type 过滤)
+     * @param couponType   优惠券类型:1=满减券,2=折扣券,可为 null(不按 couponType 过滤)
      * @return 符合条件的 life_discount_coupon 列表
      */
-    List<LifeDiscountCoupon> selectListSingleTable(@Param("storeId") String storeId, @Param("couponStatus") Integer couponStatus, @Param("type") Integer type);
+    List<LifeDiscountCoupon> selectListSingleTable(@Param("storeId") String storeId, @Param("couponStatus") Integer couponStatus, @Param("type") Integer type, @Param("couponType") Integer couponType);
 }

+ 6 - 2
alien-entity/src/main/java/shop/alien/mapper/LifeDiscountCouponStoreFriendMapper.java

@@ -43,7 +43,9 @@ public interface LifeDiscountCouponStoreFriendMapper extends BaseMapper<LifeDisc
             "ldc.id couponId,\n" +
             "ldcsf.single_qty couponNum,\n" +
             "1 as type,\n" +
-            "null as voucherId\n" +
+            "null as voucherId,\n" +
+            "ldc.coupon_type couponType,\n" +
+            "ldc.discount_rate discountRate\n" +
             "from  life_discount_coupon_store_friend ldcsf\n" +
             "left join life_discount_coupon ldc\n" +
             "on ldc.id = ldcsf.coupon_id and ldc.delete_flag = 0\n" +
@@ -75,7 +77,9 @@ public interface LifeDiscountCouponStoreFriendMapper extends BaseMapper<LifeDisc
             "ldc.id couponId,\n" +
             "ldcsf.single_qty couponNum,\n" +
             "1 as type,\n" +
-            "null as voucherId\n" +
+            "null as voucherId,\n" +
+            "ldc.coupon_type couponType,\n" +
+            "ldc.discount_rate discountRate\n" +
             "from  life_discount_coupon_store_friend ldcsf\n" +
             "left join life_discount_coupon ldc\n" +
             "on ldc.id = ldcsf.coupon_id and ldc.delete_flag = 0\n" +

+ 3 - 0
alien-entity/src/main/resources/mapper/LifeDiscountCouponMapper.xml

@@ -50,6 +50,9 @@
         <if test="type != null">
           AND type = #{type}
         </if>
+        <if test="couponType != null">
+          AND coupon_type = #{couponType}
+        </if>
     </select>
 
 </mapper>

+ 4 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/LifeDiscountCouponPlatformServiceImpl.java

@@ -177,6 +177,10 @@ public class LifeDiscountCouponPlatformServiceImpl extends ServiceImpl<LifeDisco
             LifeDiscountCoupon lifeDiscountCoupon = new LifeDiscountCoupon();
             lifeDiscountCoupon.setId(Integer.parseInt(lifeDiscountCouponDto.getCouponId()));
             BeanUtils.copyProperties(lifeDiscountCouponDto, lifeDiscountCoupon);
+            // 如果最低消费为null,设置为0(表示无门槛)
+            if (lifeDiscountCoupon.getMinimumSpendingAmount() == null) {
+                lifeDiscountCoupon.setMinimumSpendingAmount(BigDecimal.ZERO);
+            }
 
             // 根据开始领取时间判断可领取状态
             // 判断是否在领取时间内

+ 9 - 7
alien-store/src/main/java/shop/alien/store/controller/LifeDiscountCouponController.java

@@ -231,20 +231,22 @@ public class LifeDiscountCouponController {
         }
     }
 
-    @ApiOperation("获取该店铺所有优惠券 代金券(不分页)")
+    @ApiOperation("获取该店铺所有优惠券 代金券(不分页)。couponType=1仅满减券,couponType=2仅折扣券,不传返回全部优惠券")
     @ApiOperationSupport(order = 11)
     @GetMapping("/getStoreAllCouponListPaginateNot")
     @ApiImplicitParams({
             @ApiImplicitParam(name = "storeId", value = "商户id", dataType = "String", paramType = "query", required = true),
-            @ApiImplicitParam(name = "type", value = "类型:1-优惠券(默认),4-代金券", dataType = "Integer", paramType = "query")
+            @ApiImplicitParam(name = "type", value = "类型:1-优惠券(默认),4-代金券", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "couponType", value = "优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券(可选,仅当type不为4时有效)", dataType = "Integer", paramType = "query", required = false)
     })
     public R<List<LifeDiscountCouponVo>> getStoreAllCouponListPaginateNot(@ApiIgnore @TokenInfo UserLoginInfo userLoginInfo,
                                                                           @RequestParam(value = "storeId") String storeId,@RequestParam(value = "status", required = false) String status,
                                                                           @RequestParam(value = "couponStatus", defaultValue = "1", required = false) int couponStatus,
-                                                                          @RequestParam(value = "type", defaultValue = "1", required = false) Integer type) {
-        log.info("LifeDiscountCouponController.getStoreAllCouponListPaginateNot?storeId={}, status={}, couponStatus={}, type={}", storeId, status, couponStatus, type);
+                                                                          @RequestParam(value = "type", defaultValue = "1", required = false) Integer type,
+                                                                          @RequestParam(value = "couponType", required = false) Integer couponType) {
+        log.info("LifeDiscountCouponController.getStoreAllCouponListPaginateNot?storeId={}, status={}, couponStatus={}, type={}, couponType={}", storeId, status, couponStatus, type, couponType);
         try {
-            List<LifeDiscountCouponVo> storeCouponList = lifeDiscountCouponService.getStoreAllCouponListPaginateNot(status, storeId, userLoginInfo, couponStatus, type);
+            List<LifeDiscountCouponVo> storeCouponList = lifeDiscountCouponService.getStoreAllCouponListPaginateNot(status, storeId, userLoginInfo, couponStatus, type, couponType);
             return R.data(storeCouponList);
         } catch (Exception e) {
             log.error("LifeDiscountCouponController.getStoreAllCouponListPaginateNot ERROR Msg={}", e.getMessage());
@@ -289,7 +291,7 @@ public class LifeDiscountCouponController {
                                                                          @RequestParam(value = "couponStatus", defaultValue = "1", required = false) int couponStatus) {
         log.info("LifeDiscountCouponController.getMyCreatedDiscountCouponList?storeId={}", storeId);
         try {
-            List<LifeDiscountCouponVo> list = lifeDiscountCouponService.getStoreAllCouponListPaginateNot(status, storeId, userLoginInfo, couponStatus, 1);
+            List<LifeDiscountCouponVo> list = lifeDiscountCouponService.getStoreAllCouponListPaginateNot(status, storeId, userLoginInfo, couponStatus, 1, null);
             return R.data(list);
         } catch (Exception e) {
             log.error("LifeDiscountCouponController.getMyCreatedDiscountCouponList ERROR Msg={}", e.getMessage());
@@ -311,7 +313,7 @@ public class LifeDiscountCouponController {
                                                                  @RequestParam(value = "couponStatus", defaultValue = "1", required = false) int couponStatus) {
         log.info("LifeDiscountCouponController.getMyCreatedVoucherList?storeId={}", storeId);
         try {
-            List<LifeDiscountCouponVo> list = lifeDiscountCouponService.getStoreAllCouponListPaginateNot(status, storeId, userLoginInfo, couponStatus, 4);
+            List<LifeDiscountCouponVo> list = lifeDiscountCouponService.getStoreAllCouponListPaginateNot(status, storeId, userLoginInfo, couponStatus, 4, null);
             return R.data(list);
         } catch (Exception e) {
             log.error("LifeDiscountCouponController.getMyCreatedVoucherList ERROR Msg={}", e.getMessage());

+ 7 - 5
alien-store/src/main/java/shop/alien/store/controller/LifeDiscountCouponStoreFriendController.java

@@ -183,20 +183,22 @@ public class LifeDiscountCouponStoreFriendController {
         return R.data(lifeDiscountCouponStoreFriendService.getRuleList(storeId, acName, status));
     }
 
-    @ApiOperation("查询赠券记录(商户送给商户券)。queryType=1查询我收到的,queryType=2查询我送出的。type=4仅代金券,不传返回全部(优惠券+代金券)")
+    @ApiOperation("查询赠券记录(商户送给商户券)。queryType=1查询我收到的,queryType=2查询我送出的。type=4仅代金券,不传返回全部(优惠券+代金券)。couponType=1仅满减券,couponType=2仅折扣券,不传返回全部优惠券")
     @ApiImplicitParams({
             @ApiImplicitParam(name = "storeUserId", value = "当前登录店铺用户id(必填)", dataType = "String", paramType = "query", required = true),
             @ApiImplicitParam(name = "queryType", value = "查询类型:1=我收到的(所有好友赠送给我的),2=我送出的(我送给所有好友的)(必填)", dataType = "Integer", paramType = "query", required = true),
             @ApiImplicitParam(name = "storeName", value = "店铺名称模糊查询(可选)", dataType = "String", paramType = "query", required = false),
-            @ApiImplicitParam(name = "type", value = "4=仅代金券,不传=全部(优惠券+代金券)(可选)", dataType = "Integer", paramType = "query", required = false)
+            @ApiImplicitParam(name = "type", value = "4=仅代金券,不传=全部(优惠券+代金券)(可选)", dataType = "Integer", paramType = "query", required = false),
+            @ApiImplicitParam(name = "couponType", value = "优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券(可选,仅当type不为4时有效)", dataType = "Integer", paramType = "query", required = false)
     })
     @GetMapping("/getReceivedSendFriendCouponList")
     public R<List<LifeDiscountCouponFriendRuleVo>> getReceivedSendFriendCouponList(@RequestParam(value = "storeUserId") String storeUserId,
                                                                                    @RequestParam(value = "queryType") Integer queryType,
                                                                                    @RequestParam(value = "storeName", required = false) String storeName,
-                                                                                   @RequestParam(value = "type", required = false) Integer type) {
-        log.info("LifeDiscountCouponStoreFriendController.getReceivedSendFriendCouponList?storeUserId={},queryType={},storeName={},type={}", storeUserId, queryType, storeName, type);
-        return R.data(lifeDiscountCouponStoreFriendService.getReceivedSendFriendCouponList(storeUserId, queryType, storeName, type));
+                                                                                   @RequestParam(value = "type", required = false) Integer type,
+                                                                                   @RequestParam(value = "couponType", required = false) Integer couponType) {
+        log.info("LifeDiscountCouponStoreFriendController.getReceivedSendFriendCouponList?storeUserId={},queryType={},storeName={},type={},couponType={}", storeUserId, queryType, storeName, type, couponType);
+        return R.data(lifeDiscountCouponStoreFriendService.getReceivedSendFriendCouponList(storeUserId, queryType, storeName, type, couponType));
 
 
 

+ 1 - 1
alien-store/src/main/java/shop/alien/store/service/LifeDiscountCouponService.java

@@ -76,7 +76,7 @@ public interface LifeDiscountCouponService extends IService<LifeDiscountCoupon>
      * 获取所有优惠券列表(不分页)
      * @param type 类型:1-优惠券(默认),4-代金券
      */
-    List<LifeDiscountCouponVo> getStoreAllCouponListPaginateNot(String status, String storeId, UserLoginInfo userLoginInfo, int couponStatus, Integer type);
+    List<LifeDiscountCouponVo> getStoreAllCouponListPaginateNot(String status, String storeId, UserLoginInfo userLoginInfo, int couponStatus, Integer type, Integer couponType);
 
     /**
      * 获取优惠券规则

+ 2 - 1
alien-store/src/main/java/shop/alien/store/service/LifeDiscountCouponStoreFriendService.java

@@ -68,9 +68,10 @@ public interface LifeDiscountCouponStoreFriendService extends IService<LifeDisco
      * @param queryType 查询类型:1=我收到的(所有好友赠送给我的),2=我送出的(我送给所有好友的)(必填)
      * @param storeName 店铺名称模糊查询(可选)
      * @param type 4=仅代金券,不传=全部(优惠券+代金券)(可选)
+     * @param couponType 优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券(可选,仅当type不为4时有效)
      * @return 赠券列表
      */
-    List<LifeDiscountCouponFriendRuleVo> getReceivedSendFriendCouponList(String storeUserId, Integer queryType, String storeName, Integer type);
+    List<LifeDiscountCouponFriendRuleVo> getReceivedSendFriendCouponList(String storeUserId, Integer queryType, String storeName, Integer type, Integer couponType);
 
     /**
      * 好评送券:用户好评且AI审核通过后,按运营活动配置的优惠券/代金券ID发放到用户券包,发放成功后扣减库存;按券类型发送对应通知。

+ 36 - 2
alien-store/src/main/java/shop/alien/store/service/LifeUserOrderService.java

@@ -803,8 +803,42 @@ public class LifeUserOrderService extends ServiceImpl<LifeUserOrderMapper, LifeU
             lifeDiscountCouponUser.setUseTime(date);
             lifeDiscountCouponUserMapper.updateById(lifeDiscountCouponUser);
             lifeDiscountCoupon = lifeDiscountCouponMapper.selectById(lifeDiscountCouponUser.getCouponId());
-            avgDiscountCouponPrice = lifeDiscountCoupon.getNominalValue().divide(countDecimal, 2, RoundingMode.DOWN);
-            avgDiscountCouponLastPrice = lifeDiscountCoupon.getNominalValue().subtract(avgDiscountCouponPrice.multiply(countDecimal.subtract(BigDecimal.ONE)));
+            
+            // 根据优惠券类型计算优惠金额
+            Integer couponType = lifeDiscountCoupon.getCouponType();
+            if (couponType == null || couponType == 1) {
+                // 满减券(默认类型,兼容旧数据):直接使用面值作为减免金额
+                BigDecimal nominalValue = lifeDiscountCoupon.getNominalValue();
+                if (nominalValue == null) {
+                    nominalValue = BigDecimal.ZERO;
+                }
+                avgDiscountCouponPrice = nominalValue.divide(countDecimal, 2, RoundingMode.DOWN);
+                avgDiscountCouponLastPrice = nominalValue.subtract(avgDiscountCouponPrice.multiply(countDecimal.subtract(BigDecimal.ONE)));
+            } else if (couponType == 2) {
+                // 折扣券:根据订单金额和折扣率计算优惠金额
+                // 注意:totalPrice 是使用优惠券后的价格,需要反推原始价格
+                // 如果折扣率为 discountRate(例如80表示8折),则:
+                // 原始价格 = 优惠后价格 / (discountRate / 100)
+                // 优惠金额 = 原始价格 - 优惠后价格
+                BigDecimal discountRate = lifeDiscountCoupon.getDiscountRate();
+                if (discountRate == null || discountRate.compareTo(BigDecimal.ZERO) <= 0 || discountRate.compareTo(new BigDecimal(100)) > 0) {
+                    // 折扣率无效,使用0作为优惠金额
+                    avgDiscountCouponPrice = BigDecimal.ZERO;
+                    avgDiscountCouponLastPrice = BigDecimal.ZERO;
+                } else {
+                    // 计算原始订单总金额(使用优惠券前)
+                    BigDecimal originalTotalPrice = totalPrice.divide(discountRate.divide(new BigDecimal(100), 4, RoundingMode.HALF_UP), 2, RoundingMode.HALF_UP);
+                    // 计算总优惠金额
+                    BigDecimal totalDiscountAmount = originalTotalPrice.subtract(totalPrice);
+                    // 平均分配到每个券上
+                    avgDiscountCouponPrice = totalDiscountAmount.divide(countDecimal, 2, RoundingMode.DOWN);
+                    avgDiscountCouponLastPrice = totalDiscountAmount.subtract(avgDiscountCouponPrice.multiply(countDecimal.subtract(BigDecimal.ONE)));
+                }
+            } else {
+                // 未知类型,使用0作为优惠金额
+                avgDiscountCouponPrice = BigDecimal.ZERO;
+                avgDiscountCouponLastPrice = BigDecimal.ZERO;
+            }
         }
 
         for (int i = 0; i < buyCount; i++) {

+ 86 - 5
alien-store/src/main/java/shop/alien/store/service/impl/LifeDiscountCouponServiceImpl.java

@@ -73,9 +73,59 @@ public class LifeDiscountCouponServiceImpl extends ServiceImpl<LifeDiscountCoupo
     @Override
     public boolean addDiscountCoupon(LifeDiscountCouponDto lifeDiscountCouponDto) {
         try {
+            // 草稿状态(couponStatus == 0)时跳过详细校验,只保留基本校验
+            boolean isDraft = lifeDiscountCouponDto.getCouponStatus() != null && lifeDiscountCouponDto.getCouponStatus() == 0;
+            
+            if (!isDraft) {
+                // 非草稿状态:进行完整校验
+                // 验证优惠券类型和对应字段
+                Integer couponType = lifeDiscountCouponDto.getCouponType();
+                if (couponType == null) {
+                    throw new IllegalArgumentException("优惠券类型不能为空");
+                }
+                if (couponType == 1) {
+                    // 满减券:必须填写面值(nominalValue),最低消费可以为0(无门槛)
+                    if (lifeDiscountCouponDto.getNominalValue() == null || lifeDiscountCouponDto.getNominalValue().compareTo(BigDecimal.ZERO) <= 0) {
+                        throw new IllegalArgumentException("满减券必须填写面值(减免金额)");
+                    }
+                    // 最低消费可以为null或0(表示无门槛),但不能为负数
+                    if (lifeDiscountCouponDto.getMinimumSpendingAmount() != null && lifeDiscountCouponDto.getMinimumSpendingAmount().compareTo(BigDecimal.ZERO) < 0) {
+                        throw new IllegalArgumentException("满减券最低消费金额不能为负数");
+                    }
+                } else if (couponType == 2) {
+                    // 折扣券:必须填写折扣率(discountRate),最低消费可以为0(无门槛)
+                    if (lifeDiscountCouponDto.getDiscountRate() == null || 
+                        lifeDiscountCouponDto.getDiscountRate().compareTo(BigDecimal.ZERO) <= 0 || 
+                        lifeDiscountCouponDto.getDiscountRate().compareTo(new BigDecimal(100)) > 0) {
+                        throw new IllegalArgumentException("折扣券必须填写折扣率(0-100,例如80表示8折)");
+                    }
+                    // 最低消费可以为null或0(表示无门槛),但不能为负数
+                    if (lifeDiscountCouponDto.getMinimumSpendingAmount() != null && lifeDiscountCouponDto.getMinimumSpendingAmount().compareTo(BigDecimal.ZERO) < 0) {
+                        throw new IllegalArgumentException("折扣券最低消费金额不能为负数");
+                    }
+                } else {
+                    throw new IllegalArgumentException("优惠券类型无效,只能为1(满减券)或2(折扣券)");
+                }
+            } else {
+                // 草稿状态:只校验不能为负数(基本数据校验)
+                if (lifeDiscountCouponDto.getMinimumSpendingAmount() != null && lifeDiscountCouponDto.getMinimumSpendingAmount().compareTo(BigDecimal.ZERO) < 0) {
+                    throw new IllegalArgumentException("最低消费金额不能为负数");
+                }
+                if (lifeDiscountCouponDto.getNominalValue() != null && lifeDiscountCouponDto.getNominalValue().compareTo(BigDecimal.ZERO) < 0) {
+                    throw new IllegalArgumentException("面值不能为负数");
+                }
+                if (lifeDiscountCouponDto.getDiscountRate() != null && lifeDiscountCouponDto.getDiscountRate().compareTo(BigDecimal.ZERO) < 0) {
+                    throw new IllegalArgumentException("折扣率不能为负数");
+                }
+            }
+            
             //发布优惠券表信息
             LifeDiscountCoupon lifeDiscountCoupon = new LifeDiscountCoupon();
             BeanUtils.copyProperties(lifeDiscountCouponDto, lifeDiscountCoupon);
+            // 如果最低消费为null,设置为0(表示无门槛)
+            if (lifeDiscountCoupon.getMinimumSpendingAmount() == null) {
+                lifeDiscountCoupon.setMinimumSpendingAmount(BigDecimal.ZERO);
+            }
             // 根据开始领取时间判断可领取状态
             // 判断是否在领取时间内
 
@@ -167,6 +217,10 @@ public class LifeDiscountCouponServiceImpl extends ServiceImpl<LifeDiscountCoupo
             LifeDiscountCoupon lifeDiscountCoupon = new LifeDiscountCoupon();
             lifeDiscountCoupon.setId(Integer.parseInt(lifeDiscountCouponDto.getCouponId()));
             BeanUtils.copyProperties(lifeDiscountCouponDto, lifeDiscountCoupon);
+            // 如果最低消费为null,设置为0(表示无门槛)
+            if (lifeDiscountCoupon.getMinimumSpendingAmount() == null) {
+                lifeDiscountCoupon.setMinimumSpendingAmount(BigDecimal.ZERO);
+            }
 
             // 根据开始领取时间判断可领取状态
             // 判断是否在领取时间内
@@ -571,10 +625,16 @@ public class LifeDiscountCouponServiceImpl extends ServiceImpl<LifeDiscountCoupo
                 forbiddenRule += NOT_USE;
             }
             //添加限制金额规则
-            if (amount.compareTo(lifeDiscountCoupon.getMinimumSpendingAmount()) < 0) {
+            BigDecimal minimumSpending = lifeDiscountCoupon.getMinimumSpendingAmount();
+            if (minimumSpending != null && amount.compareTo(minimumSpending) < 0) {
                 lifeDiscountCouponVo.setDisabledStatus(false);
             }
-            forbiddenRule += MINIMUM_SPENDING_AMOUNT + lifeDiscountCoupon.getMinimumSpendingAmount();
+            // 如果最低消费为0或null,显示"无门槛"
+            if (minimumSpending == null || minimumSpending.compareTo(BigDecimal.ZERO) == 0) {
+                forbiddenRule += MINIMUM_SPENDING_AMOUNT + "无门槛";
+            } else {
+                forbiddenRule += MINIMUM_SPENDING_AMOUNT + minimumSpending;
+            }
             lifeDiscountCouponVo.setForbiddenRule(forbiddenRule);
             if (lifeDiscountCouponVo.isDisabledStatus()) {
                 canUseLifeDiscountCouponVos.add(lifeDiscountCouponVo);
@@ -983,7 +1043,7 @@ public class LifeDiscountCouponServiceImpl extends ServiceImpl<LifeDiscountCoupo
     }
 
     @Override
-    public List<LifeDiscountCouponVo> getStoreAllCouponListPaginateNot(String status, String storeId, UserLoginInfo userLoginInfo, int couponStatus, Integer type) {
+    public List<LifeDiscountCouponVo> getStoreAllCouponListPaginateNot(String status, String storeId, UserLoginInfo userLoginInfo, int couponStatus, Integer type, Integer couponType) {
         List<LifeDiscountCouponVo> result = new ArrayList<>();
         if (Integer.valueOf(4).equals(type)) {
             // type=4:直接查 life_coupon(代金券),返回代金券数据。life_coupon.type=1 为代金券,data_type 0正式/1草稿 与 couponStatus 1/0 对应
@@ -1004,7 +1064,7 @@ public class LifeDiscountCouponServiceImpl extends ServiceImpl<LifeDiscountCoupo
         }
 
         // type 不为 4:只查 life_discount_coupon 单表(优惠券列表)
-        List<LifeDiscountCoupon> lifeDiscountCoupons = lifeDiscountCouponMapper.selectListSingleTable(storeId, couponStatus, type);
+        List<LifeDiscountCoupon> lifeDiscountCoupons = lifeDiscountCouponMapper.selectListSingleTable(storeId, couponStatus, type, couponType);
         for (LifeDiscountCoupon lifeDiscountCoupon : lifeDiscountCoupons) {
             LifeDiscountCouponVo lifeDiscountCouponVo = new LifeDiscountCouponVo();
             lifeDiscountCouponVo.setCouponId(lifeDiscountCoupon.getId());
@@ -1210,7 +1270,28 @@ public class LifeDiscountCouponServiceImpl extends ServiceImpl<LifeDiscountCoupo
         if (weekLifeDiscountCouponUnavailableRules.size() > 0) {
             forbiddenRule += NOT_USE;
         }
-        forbiddenRule += MINIMUM_SPENDING_AMOUNT + lifeDiscountCoupon.getMinimumSpendingAmount();
+        
+        // 根据优惠券类型显示不同的信息
+        Integer couponType = lifeDiscountCoupon.getCouponType();
+        if (couponType != null && couponType == 2) {
+            // 折扣券:显示折扣率和最低消费
+            if (lifeDiscountCoupon.getDiscountRate() != null) {
+                forbiddenRule += "折扣率:" + lifeDiscountCoupon.getDiscountRate() + "折;";
+            }
+        } else {
+            // 满减券(默认):显示面值和最低消费
+            if (lifeDiscountCoupon.getNominalValue() != null) {
+                forbiddenRule += "面值:" + lifeDiscountCoupon.getNominalValue() + "元;";
+            }
+        }
+        
+        // 如果最低消费为0或null,显示"无门槛"
+        BigDecimal minimumSpending = lifeDiscountCoupon.getMinimumSpendingAmount();
+        if (minimumSpending == null || minimumSpending.compareTo(BigDecimal.ZERO) == 0) {
+            forbiddenRule += MINIMUM_SPENDING_AMOUNT + "无门槛";
+        } else {
+            forbiddenRule += MINIMUM_SPENDING_AMOUNT + minimumSpending;
+        }
         lifeDiscountCouponVo.setForbiddenRule(forbiddenRule);
         return forbiddenRule;
     }

+ 47 - 5
alien-store/src/main/java/shop/alien/store/service/impl/LifeDiscountCouponStoreFriendServiceImpl.java

@@ -614,7 +614,7 @@ public class LifeDiscountCouponStoreFriendServiceImpl extends ServiceImpl<LifeDi
     private static final Integer TYPE_VOUCHER = 4;
 
     @Override
-    public List<LifeDiscountCouponFriendRuleVo> getReceivedSendFriendCouponList(String storeUserId, Integer queryType, String storeName, Integer type) {
+    public List<LifeDiscountCouponFriendRuleVo> getReceivedSendFriendCouponList(String storeUserId, Integer queryType, String storeName, Integer type, Integer couponType) {
         // 参数校验
         if (StringUtils.isEmpty(storeUserId)) {
             log.warn("getReceivedSendFriendCouponList 参数错误:storeUserId 不能为空");
@@ -624,6 +624,11 @@ public class LifeDiscountCouponStoreFriendServiceImpl extends ServiceImpl<LifeDi
             log.warn("getReceivedSendFriendCouponList 参数错误:queryType 必须为 1 或 2,当前值={}", queryType);
             return new ArrayList<>();
         }
+        // 校验couponType参数(1=满减券,2=折扣券)
+        if (couponType != null && couponType != 1 && couponType != 2) {
+            log.warn("getReceivedSendFriendCouponList 参数错误:couponType 必须为 1(满减券)或 2(折扣券),当前值={}", couponType);
+            return new ArrayList<>();
+        }
 
         // 判断是否仅查询代金券
         boolean voucherOnly = TYPE_VOUCHER.equals(type);
@@ -637,7 +642,7 @@ public class LifeDiscountCouponStoreFriendServiceImpl extends ServiceImpl<LifeDi
         // queryType = 2: 我送出的(我送给所有好友的)-> friend_store_user_id = 我的店铺用户ID(我是送券的用户)
         boolean isReceivedByMe = (queryType == 1);
 
-        return queryCouponList(isReceivedByMe, storeUserId, storeName, type, voucherOnly);
+        return queryCouponList(isReceivedByMe, storeUserId, storeName, type, voucherOnly, couponType);
     }
 
     /**
@@ -648,9 +653,10 @@ public class LifeDiscountCouponStoreFriendServiceImpl extends ServiceImpl<LifeDi
      * @param storeName       店铺名称(模糊查询)
      * @param type            类型参数(4=代金券,其他=优惠券,null=全部)
      * @param voucherOnly     是否仅查询代金券
+     * @param couponType      优惠券类型(1=满减券,2=折扣券,null=全部优惠券)
      * @return 赠券列表
      */
-    private List<LifeDiscountCouponFriendRuleVo> queryCouponList(boolean isReceivedByMe, String storeUserId, String storeName, Integer type, boolean voucherOnly) {
+    private List<LifeDiscountCouponFriendRuleVo> queryCouponList(boolean isReceivedByMe, String storeUserId, String storeName, Integer type, boolean voucherOnly, Integer couponType) {
         List<LifeDiscountCouponFriendRuleVo> result;
         
         // 仅查询代金券
@@ -664,6 +670,10 @@ public class LifeDiscountCouponStoreFriendServiceImpl extends ServiceImpl<LifeDi
             // 查询优惠券
             QueryWrapper<LifeDiscountCouponFriendRuleVo> couponQuery = buildBaseQueryWrapper(isReceivedByMe, storeUserId, storeName);
             couponQuery.isNotNull("ldcsf.coupon_id");
+            // 如果指定了优惠券类型(满减券或折扣券),添加筛选条件
+            if (couponType != null) {
+                couponQuery.eq("ldc.coupon_type", couponType);
+            }
             List<LifeDiscountCouponFriendRuleVo> couponList = isReceivedByMe
                     ? lifeDiscountCouponStoreFriendMapper.getReceivedSendFriendCouponList(couponQuery)
                     : lifeDiscountCouponStoreFriendMapper.getReceivedSendFriendCouponListwzhy(couponQuery);
@@ -896,6 +906,7 @@ public class LifeDiscountCouponStoreFriendServiceImpl extends ServiceImpl<LifeDi
         int grantedVoucher = 0;
         String couponName = null;  // 优惠券名称
         String voucherName = null;  // 代金券名称
+        LifeDiscountCoupon lifeDiscountCoupon = null;  // 保存优惠券对象,用于通知消息
 
         // 按优惠券ID发放:发放1张,扣减库存,发优惠券通知
         if (couponId != null && couponId > 0) {
@@ -915,6 +926,7 @@ public class LifeDiscountCouponStoreFriendServiceImpl extends ServiceImpl<LifeDi
                     lifeDiscountCouponMapper.updateById(coupon);
                     grantedCoupon = 1;
                     couponName = coupon.getName();  // 保存优惠券名称
+                    lifeDiscountCoupon = coupon;  // 保存优惠券对象,用于通知消息
                 } catch (Exception e) {
                     log.error("发放优惠券失败,userId={}, storeId={}, couponId={}, error={}", userId, storeId, couponId, e.getMessage(), e);
                 }
@@ -953,12 +965,42 @@ public class LifeDiscountCouponStoreFriendServiceImpl extends ServiceImpl<LifeDi
                 LifeNotice couponNotice = new LifeNotice();
                 couponNotice.setSenderId("system");
                 couponNotice.setReceiverId("user_" + lifeUser.getUserPhone());
-                // 明确标注是优惠券,并包含券的具体名称
-                String couponText = "您对店铺「" + storeInfo.getStoreName() + "」的好评已通过审核,已为您发放优惠券「" + couponName + "」,快去我的券包查看吧~";
+                
+                // 构建优惠券详情信息
+                String couponDetailText = "";
+                if (lifeDiscountCoupon != null) {
+                    Integer couponType = lifeDiscountCoupon.getCouponType();
+                    if (couponType != null && couponType == 2) {
+                        // 折扣券
+                        BigDecimal discountRate = lifeDiscountCoupon.getDiscountRate();
+                        if (discountRate != null) {
+                            couponDetailText = "(" + discountRate + "折";
+                            if (lifeDiscountCoupon.getMinimumSpendingAmount() != null) {
+                                couponDetailText += ",满" + lifeDiscountCoupon.getMinimumSpendingAmount() + "可用";
+                            }
+                            couponDetailText += ")";
+                        }
+                    } else {
+                        // 满减券(默认)
+                        if (lifeDiscountCoupon.getNominalValue() != null) {
+                            couponDetailText = "(满减" + lifeDiscountCoupon.getNominalValue() + "元";
+                            if (lifeDiscountCoupon.getMinimumSpendingAmount() != null) {
+                                couponDetailText += ",满" + lifeDiscountCoupon.getMinimumSpendingAmount() + "可用";
+                            }
+                            couponDetailText += ")";
+                        }
+                    }
+                }
+                
+                // 明确标注是优惠券,并包含券的具体名称和详情
+                String couponText = "您对店铺「" + storeInfo.getStoreName() + "」的好评已通过审核,已为您发放优惠券「" + couponName + "」" + couponDetailText + ",快去我的券包查看吧~";
                 JSONObject couponJson = new JSONObject();
                 couponJson.put("message", couponText);
                 couponJson.put("couponType", "优惠券");  // 明确标识券类型
                 couponJson.put("couponName", couponName);  // 券名称
+                if (lifeDiscountCoupon != null) {
+                    couponJson.put("couponTypeValue", lifeDiscountCoupon.getCouponType());  // 优惠券类型值(1-满减券,2-折扣券)
+                }
                 couponNotice.setContext(couponJson.toJSONString());
                 couponNotice.setNoticeType(1);
                 couponNotice.setTitle("好评送优惠券");  // 标题明确标注是优惠券