超级会员相关

This commit is contained in:
张松 2025-09-16 14:05:30 +08:00
parent ec1e94fdaf
commit 696ffc49ae
36 changed files with 1198 additions and 21 deletions

View File

@ -0,0 +1,46 @@
package com.czg.controller.admin;
import com.czg.market.dto.MkConsumeDiscountDTO;
import com.czg.market.service.MkConsumeDiscountService;
import com.czg.market.vo.MkConsumeDiscountVO;
import com.czg.resp.CzgResult;
import com.czg.sa.StpKit;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
/**
* 新客立减
* @author Administrator
*/
@RestController
@RequestMapping("/admin/consumeDiscount")
public class ConsumeDiscountController {
@Resource
private MkConsumeDiscountService consumeDiscountService;
/**
* 配置信息获取
* 权限标识: activate:list
*/
// @SaAdminCheckPermission(value = "member:detail", name = "会员配置列表")
@GetMapping
public CzgResult<MkConsumeDiscountVO> detail() {
return CzgResult.success(consumeDiscountService.detail(StpKit.USER.getShopId()));
}
/**
* 配置信息修改
* @return 是否成功
*/
// @SaAdminCheckPermission(value = "member:edit", name = "会员配置列表")
@PostMapping
public CzgResult<Boolean> edit(@Validated @RequestBody MkConsumeDiscountDTO consumeDiscountDTO) {
return CzgResult.success(consumeDiscountService.edit(StpKit.USER.getShopId(), consumeDiscountDTO));
}
}

View File

@ -0,0 +1,50 @@
package com.czg.controller.admin;
import com.czg.market.dto.MkShopRechargeDTO;
import com.czg.market.service.MkShopRechargeService;
import com.czg.market.vo.MkShopRechargeVO;
import com.czg.resp.CzgResult;
import com.czg.sa.StpKit;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* 智慧充值
* @author Administrator
*/
@RestController
@RequestMapping("/admin/shopRecharge")
public class ShopRechargeController {
@Resource
private MkShopRechargeService shopRechargeService;
/**
* 配置信息获取
* 权限标识: activate:list
*/
// @SaAdminCheckPermission(value = "member:detail", name = "会员配置列表")
@GetMapping
public CzgResult<MkShopRechargeVO> detail() {
if (!StpKit.USER.isManager()) {
return CzgResult.failure("无权限操作");
}
return CzgResult.success(shopRechargeService.detail(StpKit.USER.getShopId()));
}
/**
* 配置信息修改
* @return 是否成功
*/
// @SaAdminCheckPermission(value = "member:edit", name = "会员配置列表")
@PostMapping
public CzgResult<Boolean> edit(@Validated @RequestBody MkShopRechargeDTO shopRechargeDTO) {
if (!StpKit.USER.isManager()) {
return CzgResult.failure("无权限操作");
}
return CzgResult.success(shopRechargeService.edit(StpKit.USER.getShopId(), shopRechargeDTO));
}
}

View File

@ -0,0 +1,45 @@
package com.czg.task;
import cn.hutool.core.date.DateUtil;
import com.czg.account.entity.ShopUser;
import com.czg.account.service.ShopUserService;
import com.czg.constant.TableValueConstant;
import com.czg.market.service.TbMemberConfigService;
import com.czg.order.entity.OrderInfo;
import com.czg.order.service.OrderInfoService;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* 订单定时任务
*
* @author ww
* @description
*/
@Slf4j
@Component
public class MemberDeliverTask {
@Resource
private OrderInfoService orderInfoService;
@DubboReference
private ShopUserService shopUserService;
@Resource
private TbMemberConfigService memberConfigService;
/**
* order 过期
*/
// @Scheduled(cron = "0 0 1 * * ? ")
public void run() {
shopUserService.list(new QueryWrapper().eq(ShopUser::getIsVip, 1).lt(ShopUser::getNextDeliverTime, DateUtil.date().toLocalDateTime())).forEach(item -> {
memberConfigService.deliver(item.getShopId(), item.getUserId(), TableValueConstant.MemberExpFlow.Type.MEMBER_TASK, null, null, null);
});
}
}

View File

@ -135,4 +135,7 @@ public class ShopUser implements Serializable {
private Long experience;
private LocalDateTime startTime;
private LocalDateTime endTime;
private LocalDateTime deliverTime;
private LocalDateTime nextDeliverTime;
}

View File

@ -0,0 +1,17 @@
package com.czg.market.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class CouponInfoDTO implements Serializable {
/**
* 券id
*/
private Long id;
/**
* 券数量
*/
private Integer num;
}

View File

@ -7,6 +7,7 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
@ -15,7 +16,7 @@ import java.util.Map;
* @author Administrator
*/
@Data
public class MemberConfigDTO {
public class MemberConfigDTO implements Serializable {
@Data
public static class ConfigCoupon {
@Min(value = 1, message = "数量不能小于1")

View File

@ -0,0 +1,69 @@
package com.czg.market.dto;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import com.alibaba.fastjson2.annotation.JSONField;
import java.io.Serial;
import java.util.List;
import com.czg.constant.TableValueConstant;
import com.czg.market.entity.MkConsumeDiscountRandom;
import com.czg.validator.group.UpdateGroup;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 新客立减 实体类
*
* @author zs
* @since 2025-09-16
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MkConsumeDiscountDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@NotNull(message = "id不为空")
private Long id;
/**
* 是否开启
*/
@NotNull(message = "是否开启不为空")
private Integer isEnable;
/**
* 固定 FIXED 随机 RANDOM
*/
@NotEmpty(message = "减免类型不为空")
private String discountType;
/**
* 固定减免金额
*/
@DecimalMin(value = "0.01", message = "减免金额不能小于0.01")
private BigDecimal discountAmount;
/**
* 随机减免规则
*/
private List<MkConsumeDiscountRandom> randomDiscountList;
/**
* 用餐模式 堂食 dine-in 外带 take-out 外卖 take-away
*/
private List<String> useTypeList;
}

View File

@ -0,0 +1,80 @@
package com.czg.market.dto;
import java.io.Serializable;
import java.time.LocalDateTime;
import com.alibaba.fastjson2.annotation.JSONField;
import java.io.Serial;
import java.util.List;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 充值配置表 实体类
*
* @author zs
* @since 2025-09-16
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MkShopRechargeDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@NotNull(message = "ID不能为空")
private Long id;
/**
* 可用分店id
*/
private List<Long> shopIdList;
/**
* all 全部可用 part部分门店可用
*/
@NotEmpty(message = "可用类型不能为空")
private String useType;
/**
* 是否自定义金额
*/
@NotNull(message = "是否自定义金额不能为空")
private Integer isCustom;
/**
* 充值并下单
*/
@NotNull(message = "充值并下单不能为空")
private Integer isOrder;
/**
* 充值说明
*/
@NotBlank(message = "充值说明不能为空")
@Size(max = 250, message = "最大长度为250")
private String remark;
/**
* 是否开启
*/
@NotNull(message = "是否开启不能为空")
private Integer isEnable;
/**
* 充值面额
*/
private List<MkShopRechargeDetailDTO> shopRechargeDetailList;
}

View File

@ -0,0 +1,48 @@
package com.czg.market.dto;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import com.alibaba.fastjson2.annotation.JSONField;
import java.io.Serial;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 充值面额详情 实体类
*
* @author zs
* @since 2025-09-16
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MkShopRechargeDetailDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 充值金额
*/
private BigDecimal amount;
/**
* 赠送金额
*/
private BigDecimal rewardAmount;
/**
* 赠送积分
*/
private Integer rewardPoints;
/**
* 赠送优惠券信息
*/
private List<CouponInfoDTO> couponInfoList;
}

View File

@ -77,7 +77,7 @@ public class MemberLevelConfig implements Serializable {
/**
* 赠送积分
*/
private Float cycleRewardPoints;
private Integer cycleRewardPoints;
/**
* 优惠券列表

View File

@ -0,0 +1,82 @@
package com.czg.market.entity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.io.Serial;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 新客立减 实体类
*
* @author zs
* @since 2025-09-16
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("mk_consume_discount")
public class MkConsumeDiscount implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@Id(keyType = KeyType.Auto)
private Long id;
/**
* 是否开启
*/
private Integer isEnable;
/**
* 固定 FIXED 随机 RANDOM
*/
private String discountType;
/**
* 固定减免金额
*/
private BigDecimal discountAmount;
/**
* 随机减免规则
*/
private String randomDiscountList;
/**
* 用餐模式 堂食 dine-in 外带 take-out 外卖 take-away
*/
private String useTypeList;
/**
* 店铺id
*/
private Long shopId;
/**
* 创建时间
*/
@Column(onInsertValue = "now()")
private LocalDateTime createTime;
/**
* 修改时间
*/
@Column(onInsertValue = "now()", onUpdateValue = "now()")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,11 @@
package com.czg.market.entity;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class MkConsumeDiscountRandom {
private BigDecimal amount;
private BigDecimal probability;
}

View File

@ -0,0 +1,86 @@
package com.czg.market.entity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.io.Serial;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 充值配置表 实体类
*
* @author zs
* @since 2025-09-16
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("mk_shop_recharge")
public class MkShopRecharge implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@Id(keyType = KeyType.Auto)
private Long id;
/**
* 主店id
*/
private Long masterShopId;
/**
* 可用分店id
*/
private String shopIdList;
/**
* all 全部可用 part部分门店可用
*/
private String useType;
/**
* 是否自定义金额
*/
private Integer isCustom;
/**
* 充值并下单
*/
private Integer isOrder;
/**
* 充值说明
*/
private String remark;
/**
* 创建时间
*/
@Column(onInsertValue = "now()")
private LocalDateTime createTime;
/**
* 修改时间
*/
@Column(onInsertValue = "now()", onUpdateValue = "now()")
private LocalDateTime updateTime;
/**
* 是否开启
*/
private Integer isEnable;
}

View File

@ -0,0 +1,71 @@
package com.czg.market.entity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.io.Serial;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 充值面额详情 实体类
*
* @author zs
* @since 2025-09-16
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("mk_shop_recharge_detail")
public class MkShopRechargeDetail implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Id(keyType = KeyType.Auto)
private Long id;
/**
* 充值金额
*/
private BigDecimal amount;
/**
* 赠送金额
*/
private BigDecimal rewardAmount;
/**
* 赠送积分
*/
private Integer rewardPoints;
/**
* 赠送优惠券信息
*/
private String couponInfoList;
/**
* 创建时间
*/
@Column(onInsertValue = "now()")
private LocalDateTime createTime;
/**
* 修改时间
*/
@Column(onInsertValue = "now()", onUpdateValue = "now()")
private LocalDateTime updateTime;
private Long shopRechargeId;
}

View File

@ -1,5 +1,6 @@
package com.czg.market.service;
import com.czg.market.vo.MemberLevelVO;
import com.mybatisflex.core.service.IService;
import com.czg.market.entity.MemberLevelConfig;
@ -11,4 +12,5 @@ import com.czg.market.entity.MemberLevelConfig;
*/
public interface MemberLevelConfigService extends IService<MemberLevelConfig> {
MemberLevelVO detail(Long memberLevelId);
}

View File

@ -0,0 +1,20 @@
package com.czg.market.service;
import com.czg.exception.ApiNotPrintException;
import com.czg.market.dto.MkConsumeDiscountDTO;
import com.czg.market.vo.MkConsumeDiscountVO;
import com.mybatisflex.core.service.IService;
import com.czg.market.entity.MkConsumeDiscount;
/**
* 新客立减 服务层
*
* @author zs
* @since 2025-09-16
*/
public interface MkConsumeDiscountService extends IService<MkConsumeDiscount> {
MkConsumeDiscountVO detail(Long shopId);
Boolean edit(Long shopId, MkConsumeDiscountDTO consumeDiscountDTO) throws ApiNotPrintException;
}

View File

@ -0,0 +1,14 @@
package com.czg.market.service;
import com.mybatisflex.core.service.IService;
import com.czg.market.entity.MkShopRechargeDetail;
/**
* 充值面额详情 服务层
*
* @author zs
* @since 2025-09-16
*/
public interface MkShopRechargeDetailService extends IService<MkShopRechargeDetail> {
}

View File

@ -0,0 +1,20 @@
package com.czg.market.service;
import com.czg.market.dto.MkShopRechargeDTO;
import com.czg.market.vo.MkShopRechargeVO;
import com.mybatisflex.core.service.IService;
import com.czg.market.entity.MkShopRecharge;
/**
* 充值配置表 服务层
*
* @author zs
* @since 2025-09-16
*/
public interface MkShopRechargeService extends IService<MkShopRecharge> {
MkShopRechargeVO detail(Long shopId);
Boolean edit(Long shopId, MkShopRechargeDTO shopRechargeDTO);
}

View File

@ -0,0 +1,14 @@
package com.czg.market.vo;
import com.czg.market.entity.ShopCoupon;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@Accessors(chain = true)
public class CouponInfoVO implements Serializable {
private ShopCoupon coupon;
private Integer num;
}

View File

@ -62,7 +62,7 @@ public class MemberLevelVO implements Serializable {
/**
* 赠送积分
*/
private Float cycleRewardPoints;
private Integer cycleRewardPoints;
/**
* 优惠券列表

View File

@ -0,0 +1,61 @@
package com.czg.market.vo;
import com.czg.market.entity.MkConsumeDiscountRandom;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class MkConsumeDiscountVO implements Serializable {
/**
* ID
*/
private Long id;
/**
* 是否开启
*/
private Integer isEnable;
/**
* 固定 FIXED 随机 RANDOM
*/
private String discountType;
/**
* 固定减免金额
*/
private BigDecimal discountAmount;
/**
* 随机减免规则
*/
private List<MkConsumeDiscountRandom> randomDiscountList;
/**
* 用餐模式 堂食 dine-in 外带 take-out 外卖 take-away
*/
private List<String> useTypeList;
/**
* 店铺id
*/
private Long shopId;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 修改时间
*/
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,50 @@
package com.czg.market.vo;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class MkShopRechargeDetailVO implements Serializable {
private static final long serialVersionUID = 1L;
@Id(keyType = KeyType.Auto)
private Long id;
/**
* 充值金额
*/
private BigDecimal amount;
/**
* 赠送金额
*/
private BigDecimal rewardAmount;
/**
* 赠送积分
*/
private Integer rewardPoints;
/**
* 赠送优惠券信息
*/
private List<CouponInfoVO> couponInfoList;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 修改时间
*/
private LocalDateTime updateTime;
private Long shopRechargeId;
}

View File

@ -0,0 +1,64 @@
package com.czg.market.vo;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class MkShopRechargeVO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 主店id
*/
private Long masterShopId;
/**
* 可用分店id
*/
private List<Long> shopIdList;
/**
* all 全部可用 part部分门店可用
*/
private String useType;
/**
* 是否自定义金额
*/
private Integer isCustom;
/**
* 充值并下单
*/
private Integer isOrder;
/**
* 充值说明
*/
private String remark;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 修改时间
*/
private LocalDateTime updateTime;
/**
* 是否开启
*/
private Integer isEnable;
private List<MkShopRechargeDetailVO> rechargeDetailList;
}

View File

@ -11,6 +11,7 @@ public interface TableValueConstant {
enum Type {
RECHARGE("RECHARGE", "充值增积分"),
PAY("PAY", "购买会员增积分"),
MEMBER_TASK("MEMBER_TASK", "会员周奖励"),
COST("COST", "消费增积分");
private final String code;
private final String msg;
@ -22,4 +23,19 @@ public interface TableValueConstant {
}
}
interface ConsumeDiscount {
@Getter
enum DiscountType {
FIXED("fixed", "固定减免"),
RANDOM("random", "随机减免");
private final String code;
private final String msg;
DiscountType(String code, String msg) {
this.code = code;
this.msg = msg;
}
}
}
}

View File

@ -29,7 +29,7 @@ public class Main {
// String packageName = "product";
String packageName = "market";
String tableName = "tb_member_exp_flow";
String tableName = "mk_shop_recharge_detail";
String author = "zs";
//是否生成DTO实体 默认生成
boolean isGenerateDto = true;

View File

@ -0,0 +1,14 @@
package com.czg.service.market.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.market.entity.MkConsumeDiscount;
/**
* 新客立减 映射层
*
* @author zs
* @since 2025-09-16
*/
public interface MkConsumeDiscountMapper extends BaseMapper<MkConsumeDiscount> {
}

View File

@ -0,0 +1,14 @@
package com.czg.service.market.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.market.entity.MkShopRechargeDetail;
/**
* 充值面额详情 映射层
*
* @author zs
* @since 2025-09-16
*/
public interface MkShopRechargeDetailMapper extends BaseMapper<MkShopRechargeDetail> {
}

View File

@ -0,0 +1,14 @@
package com.czg.service.market.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.market.entity.MkShopRecharge;
/**
* 充值配置表 映射层
*
* @author zs
* @since 2025-09-16
*/
public interface MkShopRechargeMapper extends BaseMapper<MkShopRecharge> {
}

View File

@ -0,0 +1,75 @@
package com.czg.service.market.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.czg.constant.TableValueConstant;
import com.czg.exception.ApiNotPrintException;
import com.czg.market.dto.MkConsumeDiscountDTO;
import com.czg.market.entity.MkConsumeDiscountRandom;
import com.czg.market.vo.MkConsumeDiscountVO;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MkConsumeDiscount;
import com.czg.market.service.MkConsumeDiscountService;
import com.czg.service.market.mapper.MkConsumeDiscountMapper;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* 新客立减 服务层实现
*
* @author zs
* @since 2025-09-16
*/
@Service
public class MkConsumeDiscountServiceImpl extends ServiceImpl<MkConsumeDiscountMapper, MkConsumeDiscount> implements MkConsumeDiscountService{
@Override
public MkConsumeDiscountVO detail(Long shopId) {
MkConsumeDiscount consumeDiscount = getOne(new QueryWrapper().eq(MkConsumeDiscount::getShopId, shopId));
if (consumeDiscount == null) {
consumeDiscount = new MkConsumeDiscount();
consumeDiscount.setShopId(shopId);
save(consumeDiscount);
consumeDiscount = getOne(new QueryWrapper().eq(MkConsumeDiscount::getShopId, shopId));
}
MkConsumeDiscountVO consumeDiscountVO = BeanUtil.copyProperties(consumeDiscount, MkConsumeDiscountVO.class, "randomDiscountList", "useTypeList");
if (StrUtil.isNotBlank(consumeDiscount.getRandomDiscountList())) {
consumeDiscountVO.setRandomDiscountList(JSONArray.parseArray(consumeDiscount.getRandomDiscountList()).toList(MkConsumeDiscountRandom.class));
}
if (StrUtil.isNotBlank(consumeDiscount.getUseTypeList())) {
consumeDiscountVO.setUseTypeList(JSONArray.parseArray(consumeDiscount.getUseTypeList()).toList(String.class));
}
return consumeDiscountVO;
}
@Override
public Boolean edit(Long shopId, MkConsumeDiscountDTO consumeDiscountDTO) {
if (consumeDiscountDTO.getRandomDiscountList() == null && consumeDiscountDTO.getDiscountAmount() == null) {
throw new ApiNotPrintException("优惠金额和随机优惠金额不能同时为空");
}
if (TableValueConstant.ConsumeDiscount.DiscountType.RANDOM.getCode().equals(consumeDiscountDTO.getDiscountType())) {
if (consumeDiscountDTO.getRandomDiscountList() == null || consumeDiscountDTO.getRandomDiscountList().isEmpty()) {
throw new ApiNotPrintException("随机优惠金额不能为空");
}
}
MkConsumeDiscount consumeDiscount = getOne(new QueryWrapper().eq(MkConsumeDiscount::getShopId, shopId));
BeanUtil.copyProperties(consumeDiscountDTO, consumeDiscount);
if (consumeDiscountDTO.getRandomDiscountList() != null) {
if (consumeDiscountDTO.getRandomDiscountList().stream().map(MkConsumeDiscountRandom::getProbability).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(new BigDecimal("100")) != 0) {
throw new ApiNotPrintException("随机概率综合必须为100%");
}
consumeDiscount.setRandomDiscountList(JSONArray.toJSONString(consumeDiscountDTO.getRandomDiscountList()));
}
if (consumeDiscountDTO.getUseTypeList() != null) {
consumeDiscount.setUseTypeList(JSONArray.toJSONString(consumeDiscountDTO.getUseTypeList()));
}
return updateById(consumeDiscount);
}
}

View File

@ -0,0 +1,18 @@
package com.czg.service.market.service.impl;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MkShopRechargeDetail;
import com.czg.market.service.MkShopRechargeDetailService;
import com.czg.service.market.mapper.MkShopRechargeDetailMapper;
import org.springframework.stereotype.Service;
/**
* 充值面额详情 服务层实现
*
* @author zs
* @since 2025-09-16
*/
@Service
public class MkShopRechargeDetailServiceImpl extends ServiceImpl<MkShopRechargeDetailMapper, MkShopRechargeDetail> implements MkShopRechargeDetailService{
}

View File

@ -0,0 +1,98 @@
package com.czg.service.market.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.czg.market.dto.CouponInfoDTO;
import com.czg.market.dto.MkShopRechargeDTO;
import com.czg.market.entity.MkShopRechargeDetail;
import com.czg.market.entity.ShopCoupon;
import com.czg.market.service.MkShopRechargeDetailService;
import com.czg.market.service.ShopCouponService;
import com.czg.market.vo.CouponInfoVO;
import com.czg.market.vo.MkShopRechargeDetailVO;
import com.czg.market.vo.MkShopRechargeVO;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MkShopRecharge;
import com.czg.market.service.MkShopRechargeService;
import com.czg.service.market.mapper.MkShopRechargeMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 充值配置表 服务层实现
*
* @author zs
* @since 2025-09-16
*/
@Service
public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper, MkShopRecharge> implements MkShopRechargeService{
@Resource
private MkShopRechargeDetailService shopRechargeDetailService;
@Resource
private ShopCouponService shopCouponService;
@Override
public MkShopRechargeVO detail(Long shopId) {
MkShopRecharge shopRecharge = getOne(new QueryWrapper().eq(MkShopRecharge::getMasterShopId, shopId));
if (shopRecharge == null) {
shopRecharge = new MkShopRecharge();
shopRecharge.setMasterShopId(shopId);
save(shopRecharge);
shopRecharge = getOne(new QueryWrapper().eq(MkShopRecharge::getMasterShopId, shopId));
}
MkShopRechargeVO shopRechargeVO = BeanUtil.copyProperties(shopRecharge, MkShopRechargeVO.class, "shopIdList");
if (StrUtil.isNotBlank(shopRecharge.getShopIdList())) {
shopRechargeVO.setShopIdList(JSONArray.parseArray(shopRecharge.getShopIdList()).toList(Long.class));
}
List<MkShopRechargeDetailVO> detailList = shopRechargeDetailService.list(new QueryWrapper().eq(MkShopRechargeDetail::getShopRechargeId, shopRecharge.getId())).stream().map(mkShopRechargeDetail -> {
MkShopRechargeDetailVO detailVO = BeanUtil.copyProperties(mkShopRechargeDetail, MkShopRechargeDetailVO.class, "couponInfoList");
if (StrUtil.isNotBlank(mkShopRechargeDetail.getCouponInfoList())) {
ArrayList<CouponInfoVO> couponInfoVOS = new ArrayList<>();
List<CouponInfoDTO> couponInfoDTOS = JSONArray.parseArray(mkShopRechargeDetail.getCouponInfoList()).toJavaList(CouponInfoDTO.class);
Set<Long> couponIdList = couponInfoDTOS.stream().map(CouponInfoDTO::getId).collect(Collectors.toSet());
if (!couponIdList.isEmpty()) {
Map<Long, ShopCoupon> couponMap = shopCouponService.list(new QueryWrapper().in(ShopCoupon::getId, couponIdList)).stream().collect(Collectors.toMap(ShopCoupon::getId, v -> v));
couponInfoDTOS.forEach(item -> {
couponInfoVOS.add(new CouponInfoVO().setCoupon(couponMap.get(item.getId())).setNum(item.getNum()));
});
}
detailVO.setCouponInfoList(couponInfoVOS);
}
return detailVO;
}).collect(Collectors.toList());
shopRechargeVO.setRechargeDetailList(detailList);
return shopRechargeVO;
}
@Override
public Boolean edit(Long shopId, MkShopRechargeDTO shopRechargeDTO) {
MkShopRecharge shopRecharge = getOne(new QueryWrapper().eq(MkShopRecharge::getMasterShopId, shopId));
BeanUtil.copyProperties(shopRechargeDTO, shopRecharge);
if (shopRechargeDTO.getShopIdList() != null && !shopRechargeDTO.getShopIdList().isEmpty()) {
shopRecharge.setShopIdList(JSONArray.toJSONString(shopRechargeDTO.getShopIdList()));
}
if (shopRechargeDTO.getShopRechargeDetailList() != null && !shopRechargeDTO.getShopRechargeDetailList().isEmpty()) {
shopRechargeDetailService.remove(new QueryWrapper().eq(MkShopRechargeDetail::getShopRechargeId, shopRecharge.getId()));
shopRechargeDTO.getShopRechargeDetailList().forEach(item -> {
MkShopRechargeDetail mkShopRechargeDetail = BeanUtil.copyProperties(item, MkShopRechargeDetail.class,"couponInfoList");
mkShopRechargeDetail.setCouponInfoList(JSONArray.toJSONString(item.getCouponInfoList()));
mkShopRechargeDetail.setShopRechargeId(shopRecharge.getId());
shopRechargeDetailService.save(mkShopRechargeDetail);
});
}
return updateById(shopRecharge);
}
}

View File

@ -221,8 +221,8 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
}
MemberLevelConfig levelConfig = levelConfigService.getById(shopUser.getMemberLevelId());
if (levelConfig == null) {
MemberLevelVO levelVO = levelConfigService.detail(shopUser.getMemberLevelId());
if (levelVO == null) {
log.warn("会员等级配置不存在, 店铺id: {}, 等级id: {}", shopId, shopUser.getMemberLevelId());
return false;
}
@ -235,8 +235,8 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
exp = money.longValue() * memberConfig.getCostReward();
}
// 消费送积分
if (levelConfig.getIsCostRewardPoints() == 1 && levelConfig.getCostRewardPoints() != null) {
int points = (int) (money.floatValue() / levelConfig.getCostRewardPoints());
if (levelVO.getIsCostRewardPoints() == 1 && levelVO.getCostRewardPoints() != null) {
int points = (int) (money.floatValue() / levelVO.getCostRewardPoints());
memberPointsService.addPoints(shopUser.getId(), points, "会员消费送积分", null);
}
}
@ -246,6 +246,31 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
}
}
case PAY -> exp = expVal;
case MEMBER_TASK -> {
if (levelVO.getIsCycleReward() == 1) {
if (levelVO.getCycleRewardPoints() != null) {
int points = levelVO.getCycleRewardPoints();
memberPointsService.addPoints(shopUser.getId(), points, "会员任务奖励", null);
}
if (levelVO.getCycleRewardCouponList() != null && !levelVO.getCycleRewardCouponList().isEmpty()) {
// TODO 待办
ArrayList<MkCouponGiftDTO> giftDTOS = new ArrayList<>();
// levelVO.getCycleRewardCouponList().forEach(item -> {
// giftDTOS.add(new MkCouponGiftDTO().setCouponId(item.getCoupon().getId())
// .setCouponId(item.getCoupon().getId())
// .setCouponName(item.getCoupon().getTitle())
// .setSourceName("会员开通赠券")
// .setSourceId(shopUser)
// .setType(1)
// .setNum(item.getNum()));
// });
// couponGiftService.addCouponGift(memberOrderId, "会员开通赠券", 1, giftDTOS);
}
}
}
}
@ -263,7 +288,7 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
shopUser.setExperience(shopUser.getExperience() + exp);
// 修改会员等级
MemberLevelConfig nextConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId)
.gt(MemberLevelConfig::getExperienceValue, levelConfig.getExperienceValue()).orderBy(MemberLevelConfig::getExperienceValue, true).limit(1));
.gt(MemberLevelConfig::getExperienceValue, levelVO.getExperienceValue()).orderBy(MemberLevelConfig::getExperienceValue, true).limit(1));
if (shopUser.getExperience() >= nextConfig.getExperienceValue()) {
shopUser.setMemberLevelId(nextConfig.getId());
@ -327,17 +352,18 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
}
if (StrUtil.isNotBlank(memberOrder.getCouponList())) {
ArrayList<MkCouponGiftDTO> giftDTOS = new ArrayList<>();
JSONArray.parseArray(memberOrder.getCouponList()).toJavaList(MemberConfigDTO.ConfigCoupon.class).forEach(item -> {
giftDTOS.add(new MkCouponGiftDTO().setCouponId(item.getCoupon().getId())
.setCouponId(item.getCoupon().getId())
.setCouponName(item.getCoupon().getTitle())
.setSourceName("会员开通赠券")
.setSourceId(memberOrderId)
.setType(1)
.setNum(item.getNum()));
});
couponGiftService.addCouponGift(memberOrderId, "会员开通赠券", 1, giftDTOS);
// TODO 发券流程
// ArrayList<MkCouponGiftDTO> giftDTOS = new ArrayList<>();
// JSONArray.parseArray(memberOrder.getCouponList()).toJavaList(MemberConfigDTO.ConfigCoupon.class).forEach(item -> {
// giftDTOS.add(new MkCouponGiftDTO().setCouponId(item.getCoupon().getId())
// .setCouponId(item.getCoupon().getId())
// .setCouponName(item.getCoupon().getTitle())
// .setSourceName("会员开通赠券")
// .setSourceId(memberOrderId)
// .setType(1)
// .setNum(item.getNum()));
// });
// couponGiftService.addCouponGift(memberOrderId, "会员开通赠券", 1, giftDTOS);
}
MemberLevelConfig levelConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId).orderBy(MemberLevelConfig::getExperienceValue, true).limit(1));

View File

@ -1,11 +1,21 @@
package com.czg.service.market.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.czg.market.dto.MemberLevelDTO;
import com.czg.market.entity.ShopCoupon;
import com.czg.market.service.ShopCouponService;
import com.czg.market.vo.MemberLevelVO;
import com.czg.service.market.mapper.TbMemberLevelConfigMapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MemberLevelConfig;
import com.czg.market.service.MemberLevelConfigService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 会员等级配置 服务层实现
*
@ -14,5 +24,22 @@ import org.springframework.stereotype.Service;
*/
@Service
public class TbMemberLevelConfigServiceImpl extends ServiceImpl<TbMemberLevelConfigMapper, MemberLevelConfig> implements MemberLevelConfigService{
@Resource
private ShopCouponService shopCouponService;
@Override
public MemberLevelVO detail(Long memberLevelId) {
MemberLevelConfig memberLevelConfig = getById(memberLevelId);
if (memberLevelConfig == null) {
return null;
}
MemberLevelVO levelVO = BeanUtil.copyProperties(memberLevelConfig, MemberLevelVO.class, "cycleRewardCouponList");
if (StrUtil.isNotBlank(memberLevelConfig.getCycleRewardCouponList())) {
List<MemberLevelDTO.ConfigCoupon> coupons = JSONArray.parseArray(memberLevelConfig.getCycleRewardCouponList()).toList(MemberLevelDTO.ConfigCoupon.class);
coupons.forEach(item -> {
item.setCoupon(shopCouponService.getById(item.getCoupon().getId()));
});
levelVO.setCycleRewardCouponList(coupons);
}
return levelVO;
}
}

View File

@ -0,0 +1,7 @@
<?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.czg.service.market.mapper.MkConsumeDiscountMapper">
</mapper>

View File

@ -0,0 +1,7 @@
<?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.czg.service.market.mapper.MkShopRechargeDetailMapper">
</mapper>

View File

@ -0,0 +1,7 @@
<?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.czg.service.market.mapper.MkShopRechargeMapper">
</mapper>