Merge remote-tracking branch 'origin/dev' into test
This commit is contained in:
commit
cb00b99d00
|
|
@ -0,0 +1,103 @@
|
|||
package com.czg.controller.admin;
|
||||
|
||||
import com.czg.account.dto.MemberConfigDTO;
|
||||
import com.czg.account.dto.MemberLevelDTO;
|
||||
import com.czg.account.entity.MemberLevelConfig;
|
||||
import com.czg.account.service.TbMemberConfigService;
|
||||
import com.czg.account.vo.MemberConfigVO;
|
||||
import com.czg.account.vo.MemberLevelVO;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.validator.group.UpdateGroup;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.groups.Default;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* 会员配置管理
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/admin/member")
|
||||
public class MemberController {
|
||||
@Resource
|
||||
private TbMemberConfigService memberConfigService;
|
||||
|
||||
/**
|
||||
* 配置信息获取
|
||||
* 权限标识: activate:list
|
||||
*/
|
||||
// @SaAdminCheckPermission(value = "member:detail", name = "会员配置列表")
|
||||
@GetMapping
|
||||
public CzgResult<MemberConfigVO> detail() {
|
||||
return CzgResult.success(memberConfigService.detail(StpKit.USER.getShopId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置信息修改
|
||||
* @return 是否成功
|
||||
*/
|
||||
// @SaAdminCheckPermission(value = "member:edit", name = "会员配置列表")
|
||||
@PostMapping
|
||||
public CzgResult<Boolean> edit(@Validated @RequestBody MemberConfigDTO memberDTO) {
|
||||
return CzgResult.success(memberConfigService.edit(StpKit.USER.getShopId(), memberDTO));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 会员等级添加
|
||||
* @return 是否成功
|
||||
*/
|
||||
// @SaAdminCheckPermission(value = "member:edit", name = "会员配置列表")
|
||||
@PostMapping("/level")
|
||||
public CzgResult<Boolean> addLevel(@Validated @RequestBody MemberLevelDTO levelDTO) {
|
||||
return CzgResult.success(memberConfigService.addLevel(StpKit.USER.getShopId(), levelDTO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员等级修改
|
||||
* @return 是否成功
|
||||
*/
|
||||
// @SaAdminCheckPermission(value = "member:edit", name = "会员配置列表")
|
||||
@PutMapping("/level")
|
||||
public CzgResult<Boolean> editLevel(@Validated({UpdateGroup.class, Default.class}) @RequestBody MemberLevelDTO levelDTO) {
|
||||
return CzgResult.success(memberConfigService.editLevel(StpKit.USER.getShopId(), levelDTO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员等级删除
|
||||
* @return 是否成功
|
||||
*/
|
||||
// @SaAdminCheckPermission(value = "member:edit", name = "会员配置列表")
|
||||
@DeleteMapping("/level/{id}")
|
||||
public CzgResult<Boolean> deleteLevel(@PathVariable Long id) {
|
||||
return CzgResult.success(memberConfigService.remove(new QueryWrapper().eq(MemberLevelDTO::getId, id).eq(MemberLevelConfig::getShopId, StpKit.USER.getShopId())));
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员等级列表
|
||||
* @return 是否成功
|
||||
*/
|
||||
// @SaAdminCheckPermission(value = "member:edit", name = "会员配置列表")
|
||||
@GetMapping("/level/list")
|
||||
public CzgResult<ArrayList<MemberLevelVO>> levelList() {
|
||||
return CzgResult.success(memberConfigService.listLevel(StpKit.USER.getShopId()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 会员等级详情
|
||||
* @return 是否成功
|
||||
*/
|
||||
// @SaAdminCheckPermission(value = "member:edit", name = "会员配置列表")
|
||||
@PutMapping("/level/detail")
|
||||
public CzgResult<ArrayList<MemberLevelVO>> levelList(@RequestParam Integer id) {
|
||||
return CzgResult.success(memberConfigService.listLevel(StpKit.USER.getShopId()));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import com.czg.annotation.SaStaffCheckPermission;
|
|||
import com.czg.entity.resp.CzgBaseResp;
|
||||
import com.czg.order.entity.OrderInfo;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.service.order.dto.VipMemberPayParamDTO;
|
||||
import com.czg.service.order.dto.VipPayParamDTO;
|
||||
import com.czg.service.order.dto.VipRefundDTO;
|
||||
import com.czg.service.order.service.PayService;
|
||||
|
|
@ -69,6 +70,21 @@ public class VipPayController {
|
|||
return payService.ltPayVip(ServletUtil.getClientIP(request), payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员购买支付
|
||||
* @param request
|
||||
* @param payParam
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/ltPayMember")
|
||||
@Debounce(value = "#payParam.memberOrderId")
|
||||
public CzgResult<Map<String, Object>> ltPayMember(HttpServletRequest request, @Validated @RequestBody VipMemberPayParamDTO payParam) {
|
||||
AssertUtil.isNull(payParam.getShopUserId(), "购买失败 未指定店铺用户Id");
|
||||
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
||||
return payService.ltPayMember(ServletUtil.getClientIP(request), payParam);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 正扫
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -2,10 +2,13 @@ package com.czg.controller.user;
|
|||
|
||||
import com.czg.annotation.Debounce;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.order.dto.MemberOrderDTO;
|
||||
import com.czg.order.dto.OrderCannelDTO;
|
||||
import com.czg.order.dto.OrderInfoAddDTO;
|
||||
import com.czg.order.dto.OrderInfoQueryDTO;
|
||||
import com.czg.order.entity.MemberOrder;
|
||||
import com.czg.order.entity.OrderInfo;
|
||||
import com.czg.order.service.MemberOrderService;
|
||||
import com.czg.order.service.OrderInfoService;
|
||||
import com.czg.order.vo.HistoryOrderVo;
|
||||
import com.czg.order.vo.OrderInfoVo;
|
||||
|
|
@ -35,6 +38,8 @@ public class UserOrderController {
|
|||
@Resource
|
||||
private OrderInfoService orderInfoService;
|
||||
|
||||
@Resource
|
||||
private MemberOrderService memberOrderService;
|
||||
/**
|
||||
* 订单列表
|
||||
*/
|
||||
|
|
@ -70,6 +75,21 @@ public class UserOrderController {
|
|||
return CzgResult.success(orderInfoService.createOrder(addDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员购买
|
||||
* @param orderDTO 充值信息
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/createMemberOrder")
|
||||
public CzgResult<MemberOrder> createMemberOrder(@Validated @RequestBody MemberOrderDTO orderDTO) {
|
||||
orderDTO.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
||||
orderDTO.setUserId(StpKit.USER.getLoginIdAsLong());
|
||||
orderDTO.setShopId(StpKit.USER.getShopId());
|
||||
orderDTO.setOrderType("miniapp");
|
||||
return CzgResult.success(memberOrderService.createMemberOrder(orderDTO));
|
||||
}
|
||||
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public CzgResult<Void> upOrderIsDel(@PathVariable("id") Long id) {
|
||||
//效验数据
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
package com.czg.account.dto;
|
||||
|
||||
import com.czg.account.entity.ShopCoupon;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Administrator
|
||||
*/
|
||||
@Data
|
||||
public class MemberConfigDTO {
|
||||
@Data
|
||||
public static class ConfigList {
|
||||
@NotBlank(message = "名称不为空")
|
||||
private String name;
|
||||
@NotNull(message = "价格不能为空")
|
||||
@DecimalMin(value = "0.01", message = "价格不能小于0.01")
|
||||
private BigDecimal price;
|
||||
@Min(value = 0, message = "赠送成长值不能小于0")
|
||||
private Integer reward;
|
||||
private List<ShopCoupon> couponList;
|
||||
@NotBlank(message = "会员周期不为空")
|
||||
private String circleTime;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class condition {
|
||||
private String code;
|
||||
private String value;
|
||||
}
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@NotNull(message = "id不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 提交生日/姓名
|
||||
*/
|
||||
@NotNull(message = "提交生日/姓名不能为空")
|
||||
private Integer isSubmitInfo;
|
||||
|
||||
|
||||
/**
|
||||
* 方案列表
|
||||
*/
|
||||
@Valid
|
||||
private List<ConfigList> configList;
|
||||
|
||||
/**
|
||||
* 条件开通条件项
|
||||
*/
|
||||
@Valid
|
||||
private List<condition> conditionList;
|
||||
|
||||
/**
|
||||
* 购买开通金额
|
||||
*/
|
||||
@DecimalMin(value = "0.01", message = "金额不能小于0.01")
|
||||
private BigDecimal openAmount;
|
||||
|
||||
/**
|
||||
* 参与会员价门店
|
||||
*/
|
||||
private List<Long> memberPriceShopIdList;
|
||||
|
||||
/**
|
||||
* 是否享受会员价
|
||||
*/
|
||||
@NotNull(message = "是否享受会员价不能为空")
|
||||
private Integer isMemberPrice;
|
||||
|
||||
/**
|
||||
* 每消费一元经验值
|
||||
*/
|
||||
@Min(value = 0, message = "消费增成长值最小为0")
|
||||
private Float costReward;
|
||||
|
||||
/**
|
||||
* 每充值一元经验值
|
||||
*/
|
||||
@Min(value = 0, message = "充值增成长值最小为0")
|
||||
private Float rechargeReward;
|
||||
|
||||
/**
|
||||
* 规则说明
|
||||
*/
|
||||
@NotBlank(message = "规则说明不能为空")
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package com.czg.account.dto;
|
||||
|
||||
import com.czg.account.entity.ShopCoupon;
|
||||
import com.czg.validator.group.UpdateGroup;
|
||||
import com.czg.validator.group.member.MemberLevelCycleRewardGroup;
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class MemberLevelDTO {
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@NotNull(message = "id不为空", groups = UpdateGroup.class)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 说明
|
||||
*/
|
||||
@Size(max = 200, message = "最大长度为200")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 会员名称
|
||||
*/
|
||||
@NotBlank(message = "会员名称不为空")
|
||||
@Size(max = 30, message = "最大长度为30")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 所需成长值
|
||||
*/
|
||||
@Min(value = 0, message = "成长值不能小于0")
|
||||
@NotNull(message = "成长值不为空")
|
||||
private Long experienceValue;
|
||||
|
||||
/**
|
||||
* 会员折扣
|
||||
*/
|
||||
@NotNull(message = "会员折扣不为空")
|
||||
@Min(value = 0, message = "会员折扣不能小于0")
|
||||
private Integer discount;
|
||||
|
||||
/**
|
||||
* logo
|
||||
*/
|
||||
private String logo;
|
||||
|
||||
/**
|
||||
* 消费送积分,消费n元送1积分, 0为禁用
|
||||
*/
|
||||
@DecimalMin(value = "0.01", message = "消费送积分不能小于0.01")
|
||||
private Float costRewardPoints;
|
||||
|
||||
/**
|
||||
* 周期奖励状态 0禁用 1启用
|
||||
*/
|
||||
@NotNull(message = "周期奖励状态不为空")
|
||||
private Integer isCycleReward;
|
||||
|
||||
/**
|
||||
* 周期时间包含周 月 年 日
|
||||
*/
|
||||
@NotBlank(message = "周期时间不为空", groups = MemberLevelCycleRewardGroup.class)
|
||||
private String cycleTime;
|
||||
|
||||
/**
|
||||
* 赠送积分
|
||||
*/
|
||||
@DecimalMin(value = "0.01", message = "赠送积分不能小于0.01")
|
||||
private Float cycleRewardPoints;
|
||||
|
||||
/**
|
||||
* 优惠券列表
|
||||
*/
|
||||
private List<ShopCoupon> cycleRewardCouponList;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
|
||||
package com.czg.account.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import java.io.Serial;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 会员基础配置 实体类。
|
||||
*
|
||||
* @author zs
|
||||
* @since 2025-09-10
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TbMemberConfigDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 提交生日/姓名
|
||||
*/
|
||||
private Integer submitInfo;
|
||||
|
||||
/**
|
||||
* 购买开通PAY 条件开通CONDITION
|
||||
*/
|
||||
private String openType;
|
||||
|
||||
/**
|
||||
* 方案列表
|
||||
*/
|
||||
private String configList;
|
||||
|
||||
/**
|
||||
* 条件开通条件项
|
||||
*/
|
||||
private String conditionInfo;
|
||||
|
||||
/**
|
||||
* 购买开通金额
|
||||
*/
|
||||
private BigDecimal amount;
|
||||
|
||||
/**
|
||||
* 参与会员价门店
|
||||
*/
|
||||
private String memberPriceShopIdList;
|
||||
|
||||
/**
|
||||
* 是否享受会员价
|
||||
*/
|
||||
private Integer isMemberPrice;
|
||||
|
||||
/**
|
||||
* 每消费一元经验值
|
||||
*/
|
||||
private Float costReward;
|
||||
|
||||
/**
|
||||
* 每充值一元经验值
|
||||
*/
|
||||
private Float rechargeReward;
|
||||
|
||||
/**
|
||||
* 店铺id
|
||||
*/
|
||||
private Long shopId;
|
||||
|
||||
/**
|
||||
* 规则说明
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
|
||||
package com.czg.account.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import java.io.Serial;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 会员等级配置 实体类。
|
||||
*
|
||||
* @author zs
|
||||
* @since 2025-09-10
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TbMemberLevelConfigDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 会员名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 所需成长值
|
||||
*/
|
||||
private Long experienceValue;
|
||||
|
||||
/**
|
||||
* 会员折扣
|
||||
*/
|
||||
private Float discunt;
|
||||
|
||||
/**
|
||||
* logo
|
||||
*/
|
||||
private String logo;
|
||||
|
||||
/**
|
||||
* 消费送积分,消费n元送1积分, 0为禁用
|
||||
*/
|
||||
private Float costRewardPoints;
|
||||
|
||||
/**
|
||||
* 周期奖励状态 0禁用 1启用
|
||||
*/
|
||||
private Integer isCycleReward;
|
||||
|
||||
/**
|
||||
* 周期时间包含周 月 年 日
|
||||
*/
|
||||
private String cycleTime;
|
||||
|
||||
/**
|
||||
* 赠送积分
|
||||
*/
|
||||
private String cycleRewardPoints;
|
||||
|
||||
/**
|
||||
* 优惠券列表
|
||||
*/
|
||||
private String cycleRewardCouponList;
|
||||
|
||||
/**
|
||||
* 店铺id
|
||||
*/
|
||||
private Long shopId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
package com.czg.account.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-10
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table("tb_member_level_config")
|
||||
public class MemberLevelConfig implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Id(keyType = KeyType.Auto)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 会员名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 所需成长值
|
||||
*/
|
||||
private Long experienceValue;
|
||||
|
||||
/**
|
||||
* 会员折扣
|
||||
*/
|
||||
private Integer discount;
|
||||
|
||||
/**
|
||||
* logo
|
||||
*/
|
||||
private String logo;
|
||||
|
||||
/**
|
||||
* 消费送积分,消费n元送1积分, 0为禁用
|
||||
*/
|
||||
private Float costRewardPoints;
|
||||
|
||||
/**
|
||||
* 周期奖励状态 0禁用 1启用
|
||||
*/
|
||||
private Integer isCycleReward;
|
||||
|
||||
/**
|
||||
* 周期时间包含周 月 年 日
|
||||
*/
|
||||
private String cycleTime;
|
||||
|
||||
/**
|
||||
* 赠送积分
|
||||
*/
|
||||
private Float cycleRewardPoints;
|
||||
|
||||
/**
|
||||
* 优惠券列表
|
||||
*/
|
||||
private String cycleRewardCouponList;
|
||||
|
||||
/**
|
||||
* 店铺id
|
||||
*/
|
||||
private Long shopId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@Column(onInsertValue = "now()")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@Column(onInsertValue = "now()", onUpdateValue = "now()")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
|
|
@ -129,4 +129,8 @@ public class ShopUser implements Serializable {
|
|||
* 已经合并过来的用户信息,jsonArray格式,[{"id":1,"shopId":2,...},{"id":1,"shopId":2,...}]
|
||||
*/
|
||||
private String mergedUsers;
|
||||
|
||||
private Long memberLevelId;
|
||||
|
||||
private Long experience;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
package com.czg.account.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-10
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table("tb_member_config")
|
||||
public class TbMemberConfig implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@Id(keyType = KeyType.Auto)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 提交生日/姓名
|
||||
*/
|
||||
private Integer isSubmitInfo;
|
||||
|
||||
/**
|
||||
* 方案列表
|
||||
*/
|
||||
private String configList;
|
||||
|
||||
/**
|
||||
* 条件开通条件项
|
||||
*/
|
||||
private String conditionList;
|
||||
|
||||
/**
|
||||
* 购买开通金额
|
||||
*/
|
||||
private BigDecimal openAmount;
|
||||
|
||||
/**
|
||||
* 参与会员价门店
|
||||
*/
|
||||
private String memberPriceShopIdList;
|
||||
|
||||
/**
|
||||
* 是否享受会员价
|
||||
*/
|
||||
private Integer isMemberPrice;
|
||||
|
||||
/**
|
||||
* 每消费一元经验值
|
||||
*/
|
||||
private Long costReward;
|
||||
|
||||
/**
|
||||
* 每充值一元经验值
|
||||
*/
|
||||
private Long rechargeReward;
|
||||
|
||||
/**
|
||||
* 店铺id
|
||||
*/
|
||||
private Long shopId;
|
||||
|
||||
/**
|
||||
* 规则说明
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@Column(onInsertValue = "now()")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@Column(onInsertValue = "now()", onUpdateValue = "now()")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.czg.account.service;
|
||||
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.czg.account.entity.MemberLevelConfig;
|
||||
|
||||
/**
|
||||
* 会员等级配置 服务层。
|
||||
*
|
||||
* @author zs
|
||||
* @since 2025-09-10
|
||||
*/
|
||||
public interface MemberLevelConfigService extends IService<MemberLevelConfig> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package com.czg.account.service;
|
||||
|
||||
import com.czg.account.dto.MemberConfigDTO;
|
||||
import com.czg.account.dto.MemberLevelDTO;
|
||||
import com.czg.account.vo.MemberConfigVO;
|
||||
import com.czg.account.vo.MemberLevelVO;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.czg.account.entity.TbMemberConfig;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* 会员基础配置 服务层。
|
||||
*
|
||||
* @author zs
|
||||
* @since 2025-09-10
|
||||
*/
|
||||
public interface TbMemberConfigService extends IService<TbMemberConfig> {
|
||||
|
||||
MemberConfigVO detail(Long shopId);
|
||||
|
||||
Boolean edit(Long shopId, MemberConfigDTO memberDTO);
|
||||
|
||||
Boolean addLevel(Long shopId, MemberLevelDTO levelDTO);
|
||||
|
||||
Boolean editLevel(Long shopId, MemberLevelDTO levelDTO);
|
||||
|
||||
ArrayList<MemberLevelVO> listLevel(Long shopId);
|
||||
|
||||
/**
|
||||
* 根据传入的用户Id,校验是否符合条件,符合加入会员
|
||||
* @param shopId 店铺id
|
||||
* @param userId 用户id
|
||||
* @return 是否加入成功
|
||||
*/
|
||||
boolean joinMember(Long shopId, Long userId);
|
||||
|
||||
/**
|
||||
* 发放会员奖励
|
||||
* @param isCost 是否是消费 true 消费 false 充值
|
||||
*/
|
||||
boolean deliver(Long shopId, Long userId, BigDecimal money, boolean isCost);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
package com.czg.account.vo;
|
||||
|
||||
import com.czg.account.dto.MemberConfigDTO;
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class MemberConfigVO {
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@NotNull(message = "id不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 提交生日/姓名
|
||||
*/
|
||||
@NotNull(message = "提交生日/姓名不能为空")
|
||||
private Integer isSubmitInfo;
|
||||
|
||||
|
||||
/**
|
||||
* 方案列表
|
||||
*/
|
||||
@Valid
|
||||
private List<MemberConfigDTO.ConfigList> configList;
|
||||
|
||||
/**
|
||||
* 条件开通条件项
|
||||
*/
|
||||
@Valid
|
||||
private List<MemberConfigDTO.condition> conditionList;
|
||||
|
||||
/**
|
||||
* 购买开通金额
|
||||
*/
|
||||
@DecimalMin(value = "0.01", message = "金额不能小于0.01")
|
||||
private BigDecimal openAmount;
|
||||
|
||||
/**
|
||||
* 参与会员价门店
|
||||
*/
|
||||
private List<Long> memberPriceShopIdList;
|
||||
|
||||
/**
|
||||
* 是否享受会员价
|
||||
*/
|
||||
@NotNull(message = "是否享受会员价不能为空")
|
||||
private Integer isMemberPrice;
|
||||
|
||||
/**
|
||||
* 每消费一元经验值
|
||||
*/
|
||||
@Min(value = 0, message = "消费增成长值最小为0")
|
||||
private Long costReward;
|
||||
|
||||
/**
|
||||
* 每充值一元经验值
|
||||
*/
|
||||
@Min(value = 0, message = "充值增成长值最小为0")
|
||||
private Long rechargeReward;
|
||||
|
||||
/**
|
||||
* 规则说明
|
||||
*/
|
||||
@NotBlank(message = "规则说明不能为空")
|
||||
private String remark;
|
||||
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private LocalDateTime updateTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
package com.czg.account.vo;
|
||||
|
||||
import com.czg.account.dto.MemberConfigDTO;
|
||||
import com.czg.account.entity.ShopCoupon;
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.KeyType;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class MemberLevelVO {
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 会员名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 所需成长值
|
||||
*/
|
||||
private Long experienceValue;
|
||||
|
||||
/**
|
||||
* 会员折扣
|
||||
*/
|
||||
private Integer discount;
|
||||
|
||||
/**
|
||||
* logo
|
||||
*/
|
||||
private String logo;
|
||||
|
||||
/**
|
||||
* 消费送积分,消费n元送1积分, 0为禁用
|
||||
*/
|
||||
private Float costRewardPoints;
|
||||
|
||||
/**
|
||||
* 周期奖励状态 0禁用 1启用
|
||||
*/
|
||||
private Integer isCycleReward;
|
||||
|
||||
/**
|
||||
* 周期时间包含周 月 年 日
|
||||
*/
|
||||
private String cycleTime;
|
||||
|
||||
/**
|
||||
* 赠送积分
|
||||
*/
|
||||
private Float cycleRewardPoints;
|
||||
|
||||
/**
|
||||
* 优惠券列表
|
||||
*/
|
||||
private List<ShopCoupon> cycleRewardCouponList;
|
||||
|
||||
/**
|
||||
* 店铺id
|
||||
*/
|
||||
private Long shopId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private LocalDateTime updateTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
|
||||
package com.czg.order.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import java.io.Serial;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 会员充值订单 实体类。
|
||||
*
|
||||
* @author zs
|
||||
* @since 2025-09-11
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MemberOrderDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
/**
|
||||
* 店铺id
|
||||
*/
|
||||
@NotNull(message = "店铺id不能为空")
|
||||
private Long shopId;
|
||||
|
||||
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
@NotBlank(message = "方案名称不为空")
|
||||
private String name;
|
||||
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
@NotNull(message = "数量不为空")
|
||||
private Integer num;
|
||||
private String platformType;
|
||||
private Long userId;
|
||||
private String orderType;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
package com.czg.order.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-11
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table("tb_member_order")
|
||||
public class MemberOrder implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id(keyType = KeyType.Auto)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 订单编号
|
||||
*/
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 店铺id
|
||||
*/
|
||||
private Long shopId;
|
||||
|
||||
/**
|
||||
* 金额
|
||||
*/
|
||||
private BigDecimal amount;
|
||||
private BigDecimal price;
|
||||
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 实际支付金额
|
||||
*/
|
||||
private BigDecimal payAmount;
|
||||
|
||||
/**
|
||||
* 成长值
|
||||
*/
|
||||
private Integer reward;
|
||||
|
||||
/**
|
||||
* 会员周期
|
||||
*/
|
||||
private String circleTime;
|
||||
|
||||
/**
|
||||
* 优惠券信息
|
||||
*/
|
||||
private String couponList;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@Column(onInsertValue = "now()")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@Column(onInsertValue = "now()", onUpdateValue = "now()")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 支付时间
|
||||
*/
|
||||
private LocalDateTime payTime;
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private Integer num;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.czg.order.service;
|
||||
|
||||
import com.czg.order.dto.MemberOrderDTO;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.czg.order.entity.MemberOrder;
|
||||
|
||||
/**
|
||||
* 会员充值订单 服务层。
|
||||
*
|
||||
* @author zs
|
||||
* @since 2025-09-11
|
||||
*/
|
||||
public interface MemberOrderService extends IService<MemberOrder> {
|
||||
|
||||
MemberOrder createMemberOrder(MemberOrderDTO orderDTO);
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
|
||||
package com.czg.validator.group.member;
|
||||
|
||||
/**
|
||||
* @author admin admin@cashier.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface MemberLevelCycleRewardGroup {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.czg.service.account.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.czg.account.entity.TbMemberConfig;
|
||||
|
||||
/**
|
||||
* 会员基础配置 映射层。
|
||||
*
|
||||
* @author zs
|
||||
* @since 2025-09-10
|
||||
*/
|
||||
public interface TbMemberConfigMapper extends BaseMapper<TbMemberConfig> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.czg.service.account.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.czg.account.entity.MemberLevelConfig;
|
||||
|
||||
/**
|
||||
* 会员等级配置 映射层。
|
||||
*
|
||||
* @author zs
|
||||
* @since 2025-09-10
|
||||
*/
|
||||
public interface TbMemberLevelConfigMapper extends BaseMapper<MemberLevelConfig> {
|
||||
|
||||
}
|
||||
|
|
@ -71,6 +71,8 @@ public class ShopUserServiceImpl extends ServiceImpl<ShopUserMapper, ShopUser> i
|
|||
private FreeDineConfigService freeDineConfigService;
|
||||
@Resource
|
||||
private ShopConfigMapper shopConfigMapper;
|
||||
@DubboReference
|
||||
private TbMemberConfigService memberConfigService;
|
||||
|
||||
private ShopUser getUserInfo(Long shopId, Long shopUserId) {
|
||||
ShopUser shopUser = queryChain().eq(ShopUser::getShopId, shopId).eq(ShopUser::getId, shopUserId).one();
|
||||
|
|
@ -308,6 +310,8 @@ public class ShopUserServiceImpl extends ServiceImpl<ShopUserMapper, ShopUser> i
|
|||
shopUser.setUserId(null);
|
||||
shopUser.setShopId(null);
|
||||
}
|
||||
|
||||
memberConfigService.joinMember(shopId, userId);
|
||||
return saveOrUpdate(shopUser);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,279 @@
|
|||
package com.czg.service.account.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.account.dto.MemberConfigDTO;
|
||||
import com.czg.account.dto.MemberLevelDTO;
|
||||
import com.czg.account.entity.*;
|
||||
import com.czg.account.service.*;
|
||||
import com.czg.account.vo.MemberConfigVO;
|
||||
import com.czg.account.vo.MemberLevelVO;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.order.entity.OrderInfo;
|
||||
import com.czg.order.entity.OrderPayment;
|
||||
import com.czg.order.service.OrderInfoService;
|
||||
import com.czg.order.service.OrderPaymentService;
|
||||
import com.czg.service.order.enums.OrderStatusEnums;
|
||||
import com.czg.validator.ValidatorUtil;
|
||||
import com.czg.validator.group.member.MemberLevelCycleRewardGroup;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import com.czg.service.account.mapper.TbMemberConfigMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 会员基础配置 服务层实现。
|
||||
*
|
||||
* @author zs
|
||||
* @since 2025-09-10
|
||||
*/
|
||||
@Slf4j
|
||||
@DubboService
|
||||
public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper, TbMemberConfig> implements TbMemberConfigService {
|
||||
private final List<String> conditionMap = CollUtil.toList("BIND_PHONE", "ORDER", "COST_AMOUNT", "RECHARGE_AMOUNT");
|
||||
|
||||
@Resource
|
||||
private MemberLevelConfigService levelConfigService;
|
||||
@Resource
|
||||
private UserInfoService userInfoService;
|
||||
@Resource
|
||||
private ShopUserService shopUserService;
|
||||
@DubboReference
|
||||
private OrderInfoService orderInfoService;
|
||||
@DubboReference
|
||||
private OrderPaymentService orderPaymentService;
|
||||
@DubboReference
|
||||
private MemberPointsService memberPointsService;
|
||||
|
||||
@Override
|
||||
public MemberConfigVO detail(Long shopId) {
|
||||
TbMemberConfig memberConfig = getOne(new QueryWrapper().eq(TbMemberConfig::getShopId, shopId));
|
||||
if (memberConfig == null) {
|
||||
memberConfig = new TbMemberConfig();
|
||||
memberConfig.setShopId(shopId);
|
||||
save(memberConfig);
|
||||
memberConfig = getOne(new QueryWrapper().eq(TbMemberConfig::getShopId, shopId));
|
||||
}
|
||||
|
||||
MemberConfigVO memberConfigVO = BeanUtil.copyProperties(memberConfig, MemberConfigVO.class, "configList", "conditionList");
|
||||
if (StrUtil.isNotBlank(memberConfig.getConfigList())) {
|
||||
memberConfigVO.setConfigList(JSONArray.parseArray(memberConfig.getConfigList()).toList(MemberConfigDTO.ConfigList.class));
|
||||
}
|
||||
|
||||
if (StrUtil.isNotBlank(memberConfig.getConditionList())) {
|
||||
memberConfigVO.setConditionList(JSONArray.parseArray(memberConfig.getConditionList()).toList(MemberConfigDTO.condition.class));
|
||||
}
|
||||
|
||||
if (StrUtil.isNotBlank(memberConfig.getMemberPriceShopIdList())) {
|
||||
memberConfigVO.setMemberPriceShopIdList(JSONArray.parseArray(memberConfig.getMemberPriceShopIdList()).toList(Long.class));
|
||||
}
|
||||
|
||||
return memberConfigVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean edit(Long shopId, MemberConfigDTO memberDTO) {
|
||||
TbMemberConfig memberConfig = getOne(new QueryWrapper().eq(TbMemberConfig::getShopId, shopId));
|
||||
BeanUtil.copyProperties(memberDTO, memberConfig);
|
||||
if ((memberDTO.getConfigList() == null || memberDTO.getConfigList().isEmpty()) && memberDTO.getOpenAmount() == null) {
|
||||
throw new CzgException("会员开通方式必须选择一个");
|
||||
}
|
||||
|
||||
|
||||
if (memberDTO.getConfigList() != null && !memberDTO.getConfigList().isEmpty()) {
|
||||
memberDTO.getConfigList().forEach(item -> {
|
||||
if (item.getReward() == null && (item.getCouponList() == null || item.getCouponList().isEmpty())) {
|
||||
throw new CzgException("方案列表中赠送成长值和赠送优惠券不能同时为空");
|
||||
}
|
||||
});
|
||||
memberConfig.setConfigList(JSONObject.toJSONString(memberDTO.getConfigList()));
|
||||
memberConfig.setConditionList(null);
|
||||
}
|
||||
|
||||
if (memberConfig.getConfigList() != null && !memberConfig.getConfigList().isEmpty() && memberConfig.getOpenAmount() != null) {
|
||||
throw new CzgException("会员开通方式为单选条件");
|
||||
}
|
||||
|
||||
if (memberDTO.getConditionList() != null && !memberDTO.getConditionList().isEmpty()) {
|
||||
// ArrayList<String> conditionList = CollUtil.newArrayList(conditionMap);
|
||||
memberDTO.getConditionList().forEach(item -> {
|
||||
if (!conditionMap.contains(item.getCode())) {
|
||||
throw new CzgException("条件列表中code值错误");
|
||||
}
|
||||
});
|
||||
// conditionList.forEach(item -> {
|
||||
// memberDTO.getConditionList().add(new MemberDTO.condition(item, null));
|
||||
// });
|
||||
|
||||
memberConfig.setConditionList(JSONObject.toJSONString(memberDTO.getConditionList()));
|
||||
memberConfig.setOpenAmount(null);
|
||||
}
|
||||
|
||||
if (memberDTO.getMemberPriceShopIdList() != null && !memberDTO.getMemberPriceShopIdList().isEmpty()) {
|
||||
memberConfig.setMemberPriceShopIdList(JSONObject.toJSONString(memberDTO.getMemberPriceShopIdList()));
|
||||
}
|
||||
return updateById(memberConfig, false);
|
||||
}
|
||||
|
||||
private void checkLevelDto(Long shopId, MemberLevelDTO levelDTO) {
|
||||
long count = levelConfigService.count(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId).eq(MemberLevelConfig::getName, levelDTO.getName()).ne(MemberLevelConfig::getId, levelDTO.getId()));
|
||||
if (count > 0) {
|
||||
throw new CzgException("会员等级名称已存在");
|
||||
}
|
||||
|
||||
MemberLevelConfig lastConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId)
|
||||
.lt(MemberLevelConfig::getId, levelDTO.getId())
|
||||
.limit(1).orderBy(MemberLevelConfig::getId, false).ne(MemberLevelConfig::getId, levelDTO.getId()));
|
||||
if (lastConfig == null && levelDTO.getExperienceValue() > 0) {
|
||||
throw new CzgException("1级时本字段必须为0");
|
||||
} else if (lastConfig != null && levelDTO.getExperienceValue() <= lastConfig.getExperienceValue()) {
|
||||
throw new CzgException("会员等级经验值必须大于上一等级经验值");
|
||||
}
|
||||
|
||||
if (levelDTO.getIsCycleReward() == 1) {
|
||||
if (levelDTO.getCycleRewardPoints() == null && (levelDTO.getCycleRewardCouponList() == null || levelDTO.getCycleRewardCouponList().isEmpty())) {
|
||||
throw new CzgException("周期奖励成长值和优惠券不能同时为空");
|
||||
}
|
||||
|
||||
ValidatorUtil.validateEntity(levelDTO, MemberLevelCycleRewardGroup.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean addLevel(Long shopId, MemberLevelDTO levelDTO) {
|
||||
checkLevelDto(shopId, levelDTO);
|
||||
|
||||
MemberLevelConfig levelConfig = BeanUtil.copyProperties(levelDTO, MemberLevelConfig.class);
|
||||
levelConfig.setShopId(shopId);
|
||||
if (levelDTO.getCycleRewardCouponList() != null && !levelDTO.getCycleRewardCouponList().isEmpty()) {
|
||||
levelConfig.setCycleRewardCouponList(JSONObject.toJSONString(levelDTO.getCycleRewardCouponList()));
|
||||
}
|
||||
|
||||
return levelConfigService.save(levelConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean editLevel(Long shopId, MemberLevelDTO levelDTO) {
|
||||
MemberLevelConfig levelConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getId, levelDTO.getId()).eq(MemberLevelConfig::getShopId, shopId));
|
||||
Optional.ofNullable(levelConfig).orElseThrow(() -> new CzgException("会员等级不存在"));
|
||||
checkLevelDto(shopId, levelDTO);
|
||||
BeanUtil.copyProperties(levelDTO, levelConfig);
|
||||
|
||||
if (levelDTO.getCycleRewardCouponList() != null && !levelDTO.getCycleRewardCouponList().isEmpty()) {
|
||||
levelConfig.setCycleRewardCouponList(JSONObject.toJSONString(levelDTO.getCycleRewardCouponList()));
|
||||
} else {
|
||||
levelConfig.setCycleRewardCouponList(null);
|
||||
}
|
||||
return levelConfigService.updateById(levelConfig, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<MemberLevelVO> listLevel(Long shopId) {
|
||||
ArrayList<MemberLevelVO> memberLevelVOS = new ArrayList<>();
|
||||
levelConfigService.list(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId)).forEach(item -> {
|
||||
MemberLevelVO memberLevelVO = BeanUtil.copyProperties(item, MemberLevelVO.class, "cycleRewardCouponList");
|
||||
if (StrUtil.isNotBlank(item.getCycleRewardCouponList())) {
|
||||
memberLevelVO.setCycleRewardCouponList(JSONArray.parseArray(item.getCycleRewardCouponList()).toList(ShopCoupon.class));
|
||||
}
|
||||
memberLevelVOS.add(memberLevelVO);
|
||||
});
|
||||
|
||||
return memberLevelVOS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deliver(Long shopId, Long userId, BigDecimal money, boolean isCost) {
|
||||
ShopUser shopUser = shopUserService.getOne(new QueryWrapper().eq(ShopUser::getShopId, shopId).eq(ShopUser::getUserId, userId));
|
||||
if (shopUser == null || shopUser.getIsVip() == 0) {
|
||||
return false;
|
||||
}
|
||||
MemberConfigVO memberConfig = detail(shopId);
|
||||
if (memberConfig == null) {
|
||||
log.warn("会员配置不存在, 店铺id: {}", shopId);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (shopUser.getExperience() == null) {
|
||||
shopUser.setExperience(0L);
|
||||
}
|
||||
|
||||
// 消费经验
|
||||
if (memberConfig.getCostReward() != null && isCost) {
|
||||
shopUser.setExperience(money.longValue() * memberConfig.getCostReward() + shopUser.getExperience());
|
||||
}
|
||||
|
||||
// 充值经验
|
||||
if (memberConfig.getRechargeReward() != null && !isCost) {
|
||||
shopUser.setExperience(money.longValue() * memberConfig.getRechargeReward() + shopUser.getExperience());
|
||||
}
|
||||
|
||||
MemberLevelConfig levelConfig = levelConfigService.getById(shopUser.getMemberLevelId());
|
||||
if (levelConfig == null) {
|
||||
log.warn("会员等级配置不存在, 店铺id: {}, 等级id: {}", shopId, shopUser.getMemberLevelId());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 消费送积分
|
||||
if (isCost && levelConfig.getCostRewardPoints() != null) {
|
||||
int points = (int) (money.floatValue() / levelConfig.getCostRewardPoints());
|
||||
memberPointsService.addPoints(shopUser.getId(), points, "会员消费送积分", null);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean joinMember(Long shopId, Long userId) {
|
||||
MemberConfigVO memberConfigVO = detail(shopId);
|
||||
ShopUser shopUser = shopUserService.getOne(new QueryWrapper().eq(ShopUser::getShopId, shopId).eq(ShopUser::getUserId, userId));
|
||||
if (shopUser == null) {
|
||||
log.warn("用户不存在, 店铺id: {}, 用户id: {}", shopId, userId);
|
||||
return false;
|
||||
}
|
||||
boolean canOpen = false;
|
||||
// 条件开通
|
||||
if (memberConfigVO.getOpenAmount() == null) {
|
||||
for (MemberConfigDTO.condition item : memberConfigVO.getConditionList()) {
|
||||
canOpen = switch (item.getCode()) {
|
||||
case "BIND_PHONE" -> StrUtil.isNotBlank(shopUser.getPhone());
|
||||
case "ORDER" ->
|
||||
orderInfoService.count(new QueryWrapper().eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getUserId, userId)
|
||||
.notIn(OrderInfo::getStatus, OrderStatusEnums.UNPAID.getCode(), OrderStatusEnums.CANCELLED.getCode())) > Integer.parseInt(item.getValue());
|
||||
case "COST_AMOUNT" ->
|
||||
orderInfoService.list(new QueryWrapper().eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getUserId, userId)
|
||||
.notIn(OrderInfo::getStatus, OrderStatusEnums.UNPAID.getCode(), OrderStatusEnums.CANCELLED.getCode()))
|
||||
.stream().map(OrderInfo::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(new BigDecimal(item.getValue())) > 0;
|
||||
case "RECHARGE_AMOUNT" ->
|
||||
orderPaymentService.list(new QueryWrapper().eq(OrderPayment::getShopId, shopId)
|
||||
.eq(OrderPayment::getSourceId, shopUser.getId()).isNotNull(OrderPayment::getTradeNumber))
|
||||
.stream().map(OrderPayment::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(new BigDecimal(item.getValue())) > 0;
|
||||
default -> throw new CzgException("会员开通条件类型错误");
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// 购买开通
|
||||
} else {
|
||||
}
|
||||
|
||||
if (canOpen) {
|
||||
MemberLevelConfig levelConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId).orderBy(MemberLevelConfig::getExperienceValue, true).limit(1));
|
||||
shopUser.setMemberLevelId(levelConfig.getId());
|
||||
shopUser.setIsVip(1);
|
||||
shopUserService.updateById(shopUser);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.czg.service.account.service.impl;
|
||||
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import com.czg.account.entity.MemberLevelConfig;
|
||||
import com.czg.account.service.MemberLevelConfigService;
|
||||
import com.czg.service.account.mapper.TbMemberLevelConfigMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 会员等级配置 服务层实现。
|
||||
*
|
||||
* @author zs
|
||||
* @since 2025-09-10
|
||||
*/
|
||||
@Service
|
||||
public class TbMemberLevelConfigServiceImpl extends ServiceImpl<TbMemberLevelConfigMapper, MemberLevelConfig> implements MemberLevelConfigService{
|
||||
|
||||
}
|
||||
|
|
@ -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.account.mapper.TbMemberConfigMapper">
|
||||
|
||||
</mapper>
|
||||
|
|
@ -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.account.mapper.TbMemberLevelConfigMapper">
|
||||
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.czg.service.order.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 支付接收参数 实体类
|
||||
*
|
||||
* @author ww
|
||||
* @description
|
||||
*/
|
||||
@Data
|
||||
public class VipMemberPayParamDTO {
|
||||
@NotNull(message = "店铺不能为空")
|
||||
private Long shopId;
|
||||
@NotNull(message = "用户ID不能为空")
|
||||
private Long shopUserId;
|
||||
@NotNull(message = "会员订单id不能为空")
|
||||
private Long memberOrderId;
|
||||
/**
|
||||
* 平台类型 pc 收银机客户端 wechat 微信小程序 alipay 支付宝小程序 admin-pc PC管理端 admin-app APP管理端
|
||||
*/
|
||||
private String platformType;
|
||||
private String payType;
|
||||
private String openId;
|
||||
/**
|
||||
* 扫码支付 扫描码
|
||||
*/
|
||||
private String authCode;
|
||||
private String pwd;
|
||||
private String returnUrl;
|
||||
private String buyerRemark;
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.czg.service.order.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.czg.order.entity.MemberOrder;
|
||||
|
||||
/**
|
||||
* 会员充值订单 映射层。
|
||||
*
|
||||
* @author zs
|
||||
* @since 2025-09-11
|
||||
*/
|
||||
public interface MemberOrderMapper extends BaseMapper<MemberOrder> {
|
||||
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import com.czg.entity.resp.CzgRefundResp;
|
|||
import com.czg.order.dto.OrderInfoRefundDTO;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.service.order.dto.OrderPayParamDTO;
|
||||
import com.czg.service.order.dto.VipMemberPayParamDTO;
|
||||
import com.czg.service.order.dto.VipPayParamDTO;
|
||||
import com.czg.service.order.dto.VipRefundDTO;
|
||||
import lombok.NonNull;
|
||||
|
|
@ -119,4 +120,6 @@ public interface PayService {
|
|||
* @param refundOrderId 平台退款订单号 二选一
|
||||
*/
|
||||
CzgResult<CzgRefundResp> queryRefund(Long shopId, String mchRefundNo, String refundOrderId);
|
||||
|
||||
CzgResult<Map<String, Object>> ltPayMember(String clientIP, VipMemberPayParamDTO payParam);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
package com.czg.service.order.service.impl;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.account.dto.MemberConfigDTO;
|
||||
import com.czg.account.entity.ShopInfo;
|
||||
import com.czg.account.entity.UserInfo;
|
||||
import com.czg.account.service.ShopInfoService;
|
||||
import com.czg.account.service.ShopUserService;
|
||||
import com.czg.account.service.TbMemberConfigService;
|
||||
import com.czg.account.service.UserInfoService;
|
||||
import com.czg.account.vo.MemberConfigVO;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.order.dto.MemberOrderDTO;
|
||||
import com.czg.service.order.enums.OrderStatusEnums;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import com.czg.order.entity.MemberOrder;
|
||||
import com.czg.order.service.MemberOrderService;
|
||||
import com.czg.service.order.mapper.MemberOrderMapper;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 会员充值订单 服务层实现。
|
||||
*
|
||||
* @author zs
|
||||
* @since 2025-09-11
|
||||
*/
|
||||
@Service
|
||||
public class MemberOrderServiceImpl extends ServiceImpl<MemberOrderMapper, MemberOrder> implements MemberOrderService {
|
||||
@DubboReference
|
||||
private ShopInfoService shopInfoService;
|
||||
@DubboReference
|
||||
private UserInfoService userInfoService;
|
||||
@DubboReference
|
||||
private ShopUserService shopUserService;
|
||||
@DubboReference
|
||||
private TbMemberConfigService memberConfigService;
|
||||
|
||||
@Override
|
||||
public MemberOrder createMemberOrder(MemberOrderDTO orderDTO) {
|
||||
ShopInfo shopInfo = shopInfoService.getById(orderDTO.getShopId());
|
||||
AssertUtil.isNull(shopInfo, "生成订单失败,店铺信息不存在");
|
||||
|
||||
if (orderDTO.getUserId() != null) {
|
||||
UserInfo userInfo = userInfoService.getById(orderDTO.getUserId());
|
||||
AssertUtil.isNull(userInfo, "生成订单失败,用户信息不存在");
|
||||
}
|
||||
|
||||
MemberConfigVO memberConfigVO = memberConfigService.detail(shopInfo.getId());
|
||||
if(memberConfigVO.getConfigList() == null || memberConfigVO.getConfigList().isEmpty()) {
|
||||
throw new CzgException("会员开通方案未配置,请联系店铺");
|
||||
}
|
||||
|
||||
MemberConfigDTO.ConfigList configItem = memberConfigVO.getConfigList().stream()
|
||||
.filter(item -> item.getName().equals(orderDTO.getName()))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new CzgException("会员开通方案未配置,请联系店铺"));
|
||||
|
||||
|
||||
//生成订单
|
||||
MemberOrder orderInfo = new MemberOrder();
|
||||
|
||||
orderInfo.setOrderNo(orderDTO.getPlatformType() + IdUtil.getSnowflakeNextId());
|
||||
orderInfo.setShopId(orderDTO.getShopId());
|
||||
orderInfo.setPayAmount(BigDecimal.ZERO);
|
||||
orderInfo.setStatus(OrderStatusEnums.UNPAID.getCode());
|
||||
orderInfo.setAmount(configItem.getPrice().multiply(BigDecimal.valueOf(orderDTO.getNum())));
|
||||
orderInfo.setPrice(configItem.getPrice());
|
||||
orderInfo.setName(configItem.getName());
|
||||
orderInfo.setUserId(orderDTO.getUserId());
|
||||
orderInfo.setReward(configItem.getReward());
|
||||
orderInfo.setCircleTime(configItem.getCircleTime());
|
||||
if (configItem.getCouponList() != null && !configItem.getCouponList().isEmpty()) {
|
||||
orderInfo.setCouponList(JSONObject.toJSONString(configItem.getCouponList()));
|
||||
}
|
||||
orderInfo.setNum(orderDTO.getNum());
|
||||
save(orderInfo);
|
||||
return orderInfo;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import com.mybatisflex.spring.service.impl.ServiceImpl;
|
|||
import com.czg.order.entity.OrderPayment;
|
||||
import com.czg.order.service.OrderPaymentService;
|
||||
import com.czg.service.order.mapper.OrderPaymentMapper;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
|
|
@ -12,7 +13,7 @@ import org.springframework.stereotype.Service;
|
|||
* @author ww
|
||||
* @since 2025-02-15
|
||||
*/
|
||||
@Service
|
||||
@DubboService
|
||||
public class OrderPaymentServiceImpl extends ServiceImpl<OrderPaymentMapper, OrderPayment> implements OrderPaymentService{
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,19 +20,18 @@ import com.czg.exception.PaySuccessException;
|
|||
import com.czg.order.dto.BigDecimalDTO;
|
||||
import com.czg.order.dto.CheckOrderPay;
|
||||
import com.czg.order.dto.OrderInfoRefundDTO;
|
||||
import com.czg.order.entity.MemberOrder;
|
||||
import com.czg.order.entity.OrderDetail;
|
||||
import com.czg.order.entity.OrderInfo;
|
||||
import com.czg.order.entity.OrderPayment;
|
||||
import com.czg.order.enums.PayEnums;
|
||||
import com.czg.order.service.CreditBuyerOrderService;
|
||||
import com.czg.order.service.OrderDetailService;
|
||||
import com.czg.order.service.OrderInfoService;
|
||||
import com.czg.order.service.OrderPaymentService;
|
||||
import com.czg.order.service.*;
|
||||
import com.czg.resp.CzgRespCode;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.service.CzgPayService;
|
||||
import com.czg.service.RedisService;
|
||||
import com.czg.service.order.dto.OrderPayParamDTO;
|
||||
import com.czg.service.order.dto.VipMemberPayParamDTO;
|
||||
import com.czg.service.order.dto.VipPayParamDTO;
|
||||
import com.czg.service.order.dto.VipRefundDTO;
|
||||
import com.czg.service.order.enums.OrderStatusEnums;
|
||||
|
|
@ -101,6 +100,8 @@ public class PayServiceImpl implements PayService {
|
|||
private RedisService redisService;
|
||||
@Resource
|
||||
private RabbitPublisher rabbitPublisher;
|
||||
@Resource
|
||||
private MemberOrderService memberOrderService;
|
||||
|
||||
private final BigDecimal MONEY_RATE = new BigDecimal("100");
|
||||
|
||||
|
|
@ -390,6 +391,21 @@ public class PayServiceImpl implements PayService {
|
|||
"会员充值", payParam.getOpenId(), clintIp, payParam.getReturnUrl(), payParam.getBuyerRemark(), ""));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CzgResult<Map<String, Object>> ltPayMember(String clientIP, VipMemberPayParamDTO payParam) {
|
||||
MemberOrder memberOrder = memberOrderService.getOne(new QueryWrapper().eq(MemberOrder::getId, payParam.getMemberOrderId()));
|
||||
AssertUtil.isNull(memberOrder, "充值会员失败 该会员订单不存在");
|
||||
ShopUser shopUser = shopUserService.getById(payParam.getShopUserId());
|
||||
AssertUtil.isNull(shopUser, "充值失败 该店铺用户不存在");
|
||||
AssertUtil.isBlank(payParam.getOpenId(), "用户小程序ID不能为空");
|
||||
AssertUtil.isBlank(payParam.getPayType(), "支付方式不能为空");
|
||||
String payOrderNo = payParam.getPlatformType() + IdUtil.getSnowflakeNextId();
|
||||
initOrderPayment(new OrderPayment(payParam.getShopId(), shopUser.getId(), "memberPay", payOrderNo,
|
||||
"", memberOrder.getAmount(), payParam.getMemberOrderId()));
|
||||
return ltPay(payParam.getShopId(), payParam.getPayType(), new CzgLtPayReq(payOrderNo, memberOrder.getAmount().multiply(MONEY_RATE).longValue(),
|
||||
payParam.getPayType(), "会员充值", payParam.getOpenId(), clientIP, payParam.getReturnUrl(), payParam.getBuyerRemark(), ""));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CzgResult<Map<String, Object>> ltPayVip(String clintIp, VipPayParamDTO payParam) {
|
||||
|
|
|
|||
|
|
@ -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.order.mapper.MemberOrderMapper">
|
||||
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue