diff --git a/consumer/src/main/java/cn/shoptnt/consumer/core/receiver/MemberPointChangeDispatcher.java b/consumer/src/main/java/cn/shoptnt/consumer/core/receiver/MemberPointChangeDispatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..64f83800f41ad35fc81707c24650156cd19cc6a5 --- /dev/null +++ b/consumer/src/main/java/cn/shoptnt/consumer/core/receiver/MemberPointChangeDispatcher.java @@ -0,0 +1,47 @@ +package cn.shoptnt.consumer.core.receiver; + +import cn.shoptnt.framework.message.direct.AmqpExchange; +import cn.shoptnt.message.dispatcher.member.MemberPointChangeMessageDispatcher; +import cn.shoptnt.message.dispatcher.member.MemberSignMessageDispatcher; +import cn.shoptnt.model.base.message.MemberPointChangeMessage; +import cn.shoptnt.model.base.message.SignMessage; +import org.springframework.amqp.core.ExchangeTypes; +import org.springframework.amqp.rabbit.annotation.Exchange; +import org.springframework.amqp.rabbit.annotation.Queue; +import org.springframework.amqp.rabbit.annotation.QueueBinding; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.io.Serializable; + +/** + * @author zh + * @version 1.0 + * @title SignDispatcher + * @description + * @program: api + * 2024/3/19 14:35 + */ +@Component +public class MemberPointChangeDispatcher implements Serializable { + private static final long serialVersionUID = -6085647180206068130L; + + + @Autowired + private MemberPointChangeMessageDispatcher memberPointChangeMessageDispatcher; + + + /** + * 会员积分消息变化 + + * @param message 签到信息 + */ + @RabbitListener(bindings = @QueueBinding( + value = @Queue(value = AmqpExchange.MEMBER_POINT_CHANGE + "_QUEUE"), + exchange = @Exchange(value = AmqpExchange.MEMBER_POINT_CHANGE, type = ExchangeTypes.FANOUT) + )) + public void sendMessage(MemberPointChangeMessage message) { + memberPointChangeMessageDispatcher.dispatch(message); + } +} diff --git a/framework/src/main/java/cn/shoptnt/framework/message/direct/AmqpExchange.java b/framework/src/main/java/cn/shoptnt/framework/message/direct/AmqpExchange.java index 40776c994a0eaede709dcd69657a290640a3cc86..0ef1e56e9ddf289c9e500341273a5da86c4a4671 100644 --- a/framework/src/main/java/cn/shoptnt/framework/message/direct/AmqpExchange.java +++ b/framework/src/main/java/cn/shoptnt/framework/message/direct/AmqpExchange.java @@ -236,4 +236,9 @@ public class AmqpExchange { * 会员签到 */ public final static String MEMBER_SIGN = "MEMBER_SIGN"; + + /** + * 会员积分 变化 + */ + public final static String MEMBER_POINT_CHANGE = "MEMBER_POINT_CHANGE"; } diff --git a/manager-api/src/main/java/cn/shoptnt/api/manager/member/MemberLevelManagerController.java b/manager-api/src/main/java/cn/shoptnt/api/manager/member/MemberLevelManagerController.java new file mode 100644 index 0000000000000000000000000000000000000000..272f3b7f0c675c5a2e8f521a3f9970a054d10932 --- /dev/null +++ b/manager-api/src/main/java/cn/shoptnt/api/manager/member/MemberLevelManagerController.java @@ -0,0 +1,119 @@ +package cn.shoptnt.api.manager.member; + +import cn.shoptnt.framework.database.WebPage; +import cn.shoptnt.framework.util.BeanUtil; +import cn.shoptnt.framework.util.JsonUtil; +import cn.shoptnt.model.member.dos.Member; +import cn.shoptnt.model.member.dos.MemberLevel; +import cn.shoptnt.model.member.dto.MemberEditDTO; +import cn.shoptnt.model.member.dto.MemberLevelCondition; +import cn.shoptnt.model.member.dto.MemberQueryParam; +import cn.shoptnt.service.member.MemberLevelManager; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.hibernate.validator.constraints.Length; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import java.util.List; + + +/** + * @author zh + * @version 1.0 + * @title MemberLevelManagerController + * @description 会员等级管理类 + * @program: api + * 2024/5/20 16:36 + */ +@RestController +@RequestMapping("/admin/members/level") +@Tag(name = "会员等级相关API") +@Validated +public class MemberLevelManagerController { + + @Autowired + private MemberLevelManager memberLevelManager; + + @Operation(summary = "查询会员等级集合") + @GetMapping + public List list() { + return this.memberLevelManager.list(); + } + + + @Operation(summary = "查询会员等级详情") + @GetMapping("/{id}") + @Parameters({ + @Parameter(name = "id", description = "会员等级id", in = ParameterIn.PATH), + }) + public MemberLevelCondition get(@PathVariable Long id) { + return this.memberLevelManager.get(id); + } + + @Operation(summary = "修改会员等级") + @PutMapping("/{id}") + @Parameters({ + @Parameter(name = "id", description = "会员等级id", in = ParameterIn.PATH), + }) + public MemberLevelCondition edit(@PathVariable Long id, @RequestBody MemberLevelCondition memberLevelCondition) { + return this.memberLevelManager.edit(id, memberLevelCondition); + } + + @PostMapping + @Operation(summary = "添加会员等级") + public MemberLevel addMember(@Valid @RequestBody MemberLevelCondition memberLevelCondition) { + return memberLevelManager.add(memberLevelCondition); + } + + + @Operation(summary = "删除会员等级") + @DeleteMapping("/{id}") + @Parameters({ + @Parameter(name = "id", description = "会员等级id", in = ParameterIn.PATH), + @Parameter(name = "transfer_level_id", description = "新会员等级id", in = ParameterIn.QUERY), + }) + public void delete(@PathVariable Long id, @RequestParam(value = "transfer_level_id", required = false) Long transferLevelId) { + this.memberLevelManager.deleteLevel(id, transferLevelId); + } + + + @Operation(summary = "会员等级排序") + @PutMapping("/sort/{id}") + @Parameters({ + @Parameter(name = "id", description = "重新排序的会员等级的id", in = ParameterIn.PATH), + @Parameter(name = "target_position", description = "拖动的会员等级放置的新位置", in = ParameterIn.QUERY), + }) + public void sortOrder(@PathVariable Long id, @RequestParam(value = "target_position") Integer targetPosition) { + this.memberLevelManager.updateSortOrder(id, targetPosition); + } + + + @Operation(summary = "会员等级默认") + @PutMapping("/default/{id}") + @Parameters({ + @Parameter(name = "id", description = "重新排序的会员等级的id", in = ParameterIn.PATH) + }) + public void assignDefaultLevel(@PathVariable Long id) { + this.memberLevelManager.assignDefaultLevel(id); + } + + + @Operation(summary = "修改会员等级") + @PutMapping("/edit-level/{member_id}/{id}") + @Parameters({ + @Parameter(name = "member_id", description = "会员id", in = ParameterIn.PATH), + @Parameter(name = "id", description = "会员等级", in = ParameterIn.PATH) + }) + public void editMemberLevel(@PathVariable(value = "member_id") Long memberId, @PathVariable Long id) { + this.memberLevelManager.updateMemberLevel(memberId, id); + } + + +} diff --git a/manager-api/src/main/java/cn/shoptnt/api/manager/member/MemberPointManagerController.java b/manager-api/src/main/java/cn/shoptnt/api/manager/member/MemberPointManagerController.java index b2f2625865fad9bae4fa848e9d4ba0e3e8cac089..419cbe5d5eedc25d13b2c72ef327949e1aae19bc 100644 --- a/manager-api/src/main/java/cn/shoptnt/api/manager/member/MemberPointManagerController.java +++ b/manager-api/src/main/java/cn/shoptnt/api/manager/member/MemberPointManagerController.java @@ -51,28 +51,39 @@ public class MemberPointManagerController { MemberPointHistoryManager memberPointHistoryManager; @PutMapping(value = "/{member_id}") - @Operation(summary = "修改会消费积分") + @Operation(summary = "修改会积分") @Parameters({ - @Parameter(name = "member_id", description = "会员id", required = true, in = ParameterIn.PATH), - @Parameter(name = "point", description = "调整后的会员消费积分", required = true, in = ParameterIn.QUERY) + @Parameter(name = "member_id", description = "会员id", required = true, in = ParameterIn.PATH), + @Parameter(name = "point", description = "调整后的会员消费积分", required = true, in = ParameterIn.QUERY), + @Parameter(name = "grade_point", description = "调整后的会员等级积分", required = true, in = ParameterIn.QUERY) }) - public void editPoint(@PathVariable("member_id") Long memberId, @Min(value = 0, message = "消费积分不能小于0") Integer point) { + public void editPoint(@PathVariable("member_id") Long memberId, + @Min(value = 0, message = "消费积分不能小于0") Integer point, + @Min(value = 0, message = "等级积分不能小于0") @RequestParam(value = "grade_point") Integer gradePoint) { //获取当前会员的积分 如果当前会员积分大于调整后的积分 则为消费,反之则为新增 Member member = memberManager.getModel(memberId); Long currentPoint = member.getConsumPoint(); + Long currentGradePoint = member.getGradePoint(); //增加或者消费的积分数 Long operationPoint = point - currentPoint; + //增加或者等级的积分数 + Long operationGradePoint = gradePoint - currentGradePoint; //操作类型 1为加积分 0为减积分或无操作 Integer type = 0; if (operationPoint > 0) { type = 1; } + + Integer gradeType = 0; + if (operationGradePoint > 0) { + gradeType = 1; + } //获取管理员信息 Admin admin = AdminUserContext.getAdmin(); MemberPointHistory memberPointHistory = new MemberPointHistory(); memberPointHistory.setMemberId(memberId); - memberPointHistory.setGradePointType(0); - memberPointHistory.setGradePoint(0); + memberPointHistory.setGradePointType(gradeType); + memberPointHistory.setGradePoint(gradePoint); memberPointHistory.setConsumPoint(Math.abs(operationPoint)); memberPointHistory.setConsumPointType(type); memberPointHistory.setReason("管理员手工修改"); @@ -83,9 +94,9 @@ public class MemberPointManagerController { @Operation(summary = "查询会员积分列表") @Parameters({ - @Parameter(name = "page_no", description = "页码", required = true, in = ParameterIn.QUERY), - @Parameter(name = "page_size", description = "每页显示数量", required = true, in = ParameterIn.QUERY), - @Parameter(name = "member_id", description = "会员id", required = true, in = ParameterIn.PATH) + @Parameter(name = "page_no", description = "页码", required = true, in = ParameterIn.QUERY), + @Parameter(name = "page_size", description = "每页显示数量", required = true, in = ParameterIn.QUERY), + @Parameter(name = "member_id", description = "会员id", required = true, in = ParameterIn.PATH) }) @GetMapping("/{member_id}") public WebPage list(@PathVariable("member_id") Long memberId, @Parameter(hidden = true) @NotNull(message = "页码不能为空") Long pageNo, @Parameter(hidden = true) @NotNull(message = "每页数量不能为空") Long pageSize) { diff --git a/shoptnt-core/src/main/java/cn/shoptnt/client/member/MemberLevelClient.java b/shoptnt-core/src/main/java/cn/shoptnt/client/member/MemberLevelClient.java new file mode 100644 index 0000000000000000000000000000000000000000..6ab364b0e2bf3106036b5e4966b691b9e291ca91 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/client/member/MemberLevelClient.java @@ -0,0 +1,41 @@ +package cn.shoptnt.client.member; + +import cn.shoptnt.model.member.dos.MemberLevel; + +import java.util.List; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelClient + * @description 会员等级客户端 + * @program: api + * 2024/5/24 16:21 + */ +public interface MemberLevelClient { + + /** + * 获取所有的会员等级 + * + * @return + */ + List getList(); + + /** + * 根据id查询会员等级 + * + * @param id 会员等级id + * @return + */ + MemberLevel getById(Long id); + + /** + * 修改会员等级信息 + * + * @param memberId 会员等级 + * @param leveId 等级id + */ + void updateMemberLevel(Long memberId, Long leveId); + + +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/client/member/MemberLevelUpgradeConditionClient.java b/shoptnt-core/src/main/java/cn/shoptnt/client/member/MemberLevelUpgradeConditionClient.java new file mode 100644 index 0000000000000000000000000000000000000000..0057801c3f41fd9faafb1ac68452f28993c9ad82 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/client/member/MemberLevelUpgradeConditionClient.java @@ -0,0 +1,25 @@ +package cn.shoptnt.client.member; + +import cn.shoptnt.model.member.dos.MemberLevelUpgradeCondition; +import cn.shoptnt.model.member.enums.MemberLevelConditionType; + +import java.util.List; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelUpgradeConditionClient + * @description 会员等级升级条件 + * @program: api + * 2024/5/24 16:26 + */ +public interface MemberLevelUpgradeConditionClient { + + + /** + * 根据等级id获取升级条件 + * + * @return + */ + List getList(); +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/client/member/impl/MemberLevelClientImpl.java b/shoptnt-core/src/main/java/cn/shoptnt/client/member/impl/MemberLevelClientImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..776c13933f08c723f450fd431a6f5756f0f79b26 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/client/member/impl/MemberLevelClientImpl.java @@ -0,0 +1,39 @@ +package cn.shoptnt.client.member.impl; + +import cn.shoptnt.client.member.MemberLevelClient; +import cn.shoptnt.model.member.dos.MemberLevel; +import cn.shoptnt.service.member.MemberLevelManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelClientImpl + * @description 会员等级客户端实现类 + * @program: api + * 2024/5/24 16:22 + */ +@Service +public class MemberLevelClientImpl implements MemberLevelClient { + + @Autowired + private MemberLevelManager memberLevelManager; + + @Override + public List getList() { + return memberLevelManager.list(); + } + + @Override + public MemberLevel getById(Long id) { + return memberLevelManager.getById(id); + } + + @Override + public void updateMemberLevel(Long memberId, Long leveId) { + memberLevelManager.updateMemberLevel(memberId, leveId); + } +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/client/member/impl/MemberLevelUpgradeConditionClientImpl.java b/shoptnt-core/src/main/java/cn/shoptnt/client/member/impl/MemberLevelUpgradeConditionClientImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..48ea152599a5ec6cb26693e2de2139170df43937 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/client/member/impl/MemberLevelUpgradeConditionClientImpl.java @@ -0,0 +1,31 @@ +package cn.shoptnt.client.member.impl; + +import cn.shoptnt.client.member.MemberLevelUpgradeConditionClient; +import cn.shoptnt.model.member.dos.MemberLevelUpgradeCondition; +import cn.shoptnt.model.member.enums.MemberLevelConditionType; +import cn.shoptnt.service.member.MemberLevelUpgradeConditionManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelUpgradeConditionClientImpl + * @description 会员等级升级条件客户端 + * @program: api + * 2024/5/24 16:30 + */ + +@Service +public class MemberLevelUpgradeConditionClientImpl implements MemberLevelUpgradeConditionClient { + + @Autowired + private MemberLevelUpgradeConditionManager memberLevelUpgradeConditionManager; + + @Override + public List getList() { + return memberLevelUpgradeConditionManager.getList(); + } +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/mapper/member/MemberLevelBenefitMapper.java b/shoptnt-core/src/main/java/cn/shoptnt/mapper/member/MemberLevelBenefitMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..e2f23699dd099bfb00192de1cb3c398e67ba9ad2 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/mapper/member/MemberLevelBenefitMapper.java @@ -0,0 +1,15 @@ +package cn.shoptnt.mapper.member; + +import cn.shoptnt.model.member.dos.MemberLevelBenefit; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelMapper + * @description 会员礼物mapper + * @program: api + * 2024/5/20 16:29 + */ +public interface MemberLevelBenefitMapper extends BaseMapper { +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/mapper/member/MemberLevelMapper.java b/shoptnt-core/src/main/java/cn/shoptnt/mapper/member/MemberLevelMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..f510e0f0c14bb03817f709ca232a25a86359eab6 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/mapper/member/MemberLevelMapper.java @@ -0,0 +1,15 @@ +package cn.shoptnt.mapper.member; + +import cn.shoptnt.model.member.dos.MemberLevel; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelMapper + * @description 会员等级mapper + * @program: api + * 2024/5/20 16:29 + */ +public interface MemberLevelMapper extends BaseMapper { +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/mapper/member/MemberLevelUpgradeConditionMapper.java b/shoptnt-core/src/main/java/cn/shoptnt/mapper/member/MemberLevelUpgradeConditionMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..976e677176ac21b383d6b85091d9be3d770d2150 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/mapper/member/MemberLevelUpgradeConditionMapper.java @@ -0,0 +1,15 @@ +package cn.shoptnt.mapper.member; + +import cn.shoptnt.model.member.dos.MemberLevelUpgradeCondition; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelUpgradeConditionsMapper + * @description 会员等级升级条件Mapper + * @program: api + * 2024/5/20 21:18 + */ +public interface MemberLevelUpgradeConditionMapper extends BaseMapper { +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/message/consumer/member/MemberLevelConsumer.java b/shoptnt-core/src/main/java/cn/shoptnt/message/consumer/member/MemberLevelConsumer.java new file mode 100644 index 0000000000000000000000000000000000000000..cb2d6ef9adb491a8d8735fe2b4182c0ef49cafbd --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/message/consumer/member/MemberLevelConsumer.java @@ -0,0 +1,96 @@ +package cn.shoptnt.message.consumer.member; + +import cn.shoptnt.client.member.MemberClient; +import cn.shoptnt.client.member.MemberLevelClient; +import cn.shoptnt.client.member.MemberLevelUpgradeConditionClient; +import cn.shoptnt.message.event.MemberPointChangeEvent; +import cn.shoptnt.model.member.dos.Member; +import cn.shoptnt.model.member.dos.MemberLevel; +import cn.shoptnt.model.member.dos.MemberLevelUpgradeCondition; +import cn.shoptnt.model.member.enums.MemberLevelConditionOperator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelConsumer + * @description 会员等级消费者 + * @program: api + * 2024/5/24 15:58 + */ +@Service +public class MemberLevelConsumer implements MemberPointChangeEvent { + + @Autowired + private MemberClient memberClient; + + @Autowired + private MemberLevelClient memberLevelClient; + + @Autowired + private MemberLevelUpgradeConditionClient memberLevelUpgradeConditionClient; + + @Override + public void memberPointChange(Long memberId) { + Member member = memberClient.getModel(memberId); + //如果此会员不参与等级体系 则跳过 + if (member.getIsUpgrade().equals(-1)) { + return; + } + + //查询会员等级 + MemberLevel memberLevel = memberLevelClient.getById(member.getLevelId()); + if (memberLevel != null && member != null && member.getLevelId() != null) { + //查询所有的升级条件 + List memberLevelUpgradeConditions = memberLevelUpgradeConditionClient.getList(); + // 2. 初始化一个映射来跟踪每个等级的匹配状态 + Map levelMatched = new HashMap<>(); + /* Double dd = 222D;*/ + // 3. 根据积分和消费总额匹配等级 + for (MemberLevelUpgradeCondition condition : memberLevelUpgradeConditions) { + boolean isMatched = false; + switch (condition.getConditionType()) { + case POINTS: + isMatched = member.getGradePoint() >= condition.getConditionValueMin() && + member.getGradePoint() <= condition.getConditionValueMax(); + break; + /* case AMOUNT: + isMatched = dd >= condition.getConditionValueMin() && + dd <= condition.getConditionValueMax(); + break;*/ + } + // 更新匹配状态 + levelMatched.putIfAbsent(condition.getLevelId(), true); // 默认为true + if (condition.getConditionOperator() == MemberLevelConditionOperator.AND) { + // 对于AND条件,如果不匹配,则将该等级的状态设置为false + levelMatched.put(condition.getLevelId(), levelMatched.get(condition.getLevelId()) && isMatched); + } else if (condition.getConditionOperator() == MemberLevelConditionOperator.OR) { + // 对于OR条件,如果匹配,则保持true,否则不改变 + levelMatched.put(condition.getLevelId(), levelMatched.get(condition.getLevelId()) || isMatched); + } + } + // 找出匹配的等级ID + Long matchedLevelId = levelMatched.entrySet().stream() + .filter(Map.Entry::getValue) + .map(Map.Entry::getKey) + .findFirst() + .orElse(null); // 如果没有匹配的等级,保持为null + + //查询要升级的等级id + if (matchedLevelId != null) { + MemberLevel upgradeMemberLevel = memberLevelClient.getById(matchedLevelId); + // 4. 如果当前等级不是匹配的等级,并且我当前等级要小于升级的等级 则进行修改 + if (!member.getLevelId().equals(matchedLevelId) && memberLevel.getSortOrder() < upgradeMemberLevel.getSortOrder()) { + //修改会员等级 + memberLevelClient.updateMemberLevel(memberId, matchedLevelId); + } + } + + } + } +} \ No newline at end of file diff --git a/shoptnt-core/src/main/java/cn/shoptnt/message/consumer/orderbill/OrderBillConsumer.java b/shoptnt-core/src/main/java/cn/shoptnt/message/consumer/orderbill/OrderBillConsumer.java index aa96f580807ceda80fed9d3980280f26ac85aee5..9ed4c078396950d6327bd78483680813caa95a73 100644 --- a/shoptnt-core/src/main/java/cn/shoptnt/message/consumer/orderbill/OrderBillConsumer.java +++ b/shoptnt-core/src/main/java/cn/shoptnt/message/consumer/orderbill/OrderBillConsumer.java @@ -5,7 +5,12 @@ */ package cn.shoptnt.message.consumer.orderbill; +import cn.shoptnt.client.promotion.CouponClient; import cn.shoptnt.client.trade.AfterSaleClient; +import cn.shoptnt.client.trade.BillClient; +import cn.shoptnt.client.trade.OrderClient; +import cn.shoptnt.framework.util.CurrencyUtil; +import cn.shoptnt.framework.util.DateUtil; import cn.shoptnt.message.event.ASNewOrderEvent; import cn.shoptnt.message.event.AfterSaleChangeEvent; import cn.shoptnt.message.event.OrderStatusChangeEvent; @@ -15,17 +20,16 @@ import cn.shoptnt.model.aftersale.enums.ServiceTypeEnum; import cn.shoptnt.model.base.message.AfterSaleChangeMessage; import cn.shoptnt.model.base.message.AsOrderStatusChangeMsg; import cn.shoptnt.model.base.message.OrderStatusChangeMsg; -import cn.shoptnt.client.trade.BillClient; -import cn.shoptnt.client.promotion.CouponClient; +import cn.shoptnt.model.member.dos.Member; +import cn.shoptnt.model.member.dos.MemberLevel; import cn.shoptnt.model.orderbill.dos.BillItem; import cn.shoptnt.model.orderbill.enums.BillType; import cn.shoptnt.model.promotion.coupon.dos.CouponDO; import cn.shoptnt.model.promotion.coupon.vo.GoodsCouponPrice; -import cn.shoptnt.model.trade.order.enums.OrderStatusEnum; -import cn.shoptnt.client.trade.OrderClient; import cn.shoptnt.model.trade.order.dto.OrderDetailDTO; -import cn.shoptnt.framework.util.CurrencyUtil; -import cn.shoptnt.framework.util.DateUtil; +import cn.shoptnt.model.trade.order.enums.OrderStatusEnum; +import cn.shoptnt.service.member.MemberLevelManager; +import cn.shoptnt.service.member.MemberManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -49,6 +53,10 @@ public class OrderBillConsumer implements OrderStatusChangeEvent, ASNewOrderEven private CouponClient couponClient; @Autowired private AfterSaleClient afterSaleClient; + @Autowired + private MemberManager memberManager; + @Autowired + private MemberLevelManager memberLevelManager; /** * 订单收货生成一条结算单 @@ -70,6 +78,7 @@ public class OrderBillConsumer implements OrderStatusChangeEvent, ASNewOrderEven /** * 退货售后服务审核通过后生成一条结算单 + * * @param afterSaleChangeMessage */ @Override @@ -113,22 +122,25 @@ public class OrderBillConsumer implements OrderStatusChangeEvent, ASNewOrderEven Double couponCommission = 0D; CouponDO coupon = null; - if(goodsCouponPrices != null && goodsCouponPrices.size() != 0){ + if (goodsCouponPrices != null && goodsCouponPrices.size() != 0) { for (GoodsCouponPrice goodsCouponPrice : goodsCouponPrices) { - if(coupon == null){ + if (coupon == null) { coupon = couponClient.getModel(goodsCouponPrice.getCouponId()); } - if(coupon.getSellerId()!=0){ + if (coupon.getSellerId() != 0) { //非站点优惠券 break; } siteCouponPrice = CurrencyUtil.add(siteCouponPrice, goodsCouponPrice.getCouponPrice()); - couponCommission = CurrencyUtil.div(coupon.getShopCommission(),100); + couponCommission = CurrencyUtil.div(coupon.getShopCommission(), 100); } } + // 平台承担的会员等级折扣的优惠 + double platformMemberLevelPrice = getPlatformMemberLevelPrice(orderDetail); + BillItem item = new BillItem(); item.setAddTime(DateUtil.getDateline()); item.setItemType(billType.name()); @@ -145,9 +157,18 @@ public class OrderBillConsumer implements OrderStatusChangeEvent, ASNewOrderEven item.setShipName(orderDetail.getShipName()); item.setCouponCommission(couponCommission); item.setSiteCouponPrice(siteCouponPrice); + item.setPlatformMemberLevelPrice(platformMemberLevelPrice); return item; } + private double getPlatformMemberLevelPrice(OrderDetailDTO orderDetailDTO) { + Member member = memberManager.getModel(orderDetailDTO.getMemberId()); + MemberLevel memberLevel = memberLevelManager.getById(member.getLevelId()); + // 平台承担比例 + double platformRatio = CurrencyUtil.div(CurrencyUtil.sub(100, memberLevel.getAllocationRatio()), 100); + return CurrencyUtil.mul(orderDetailDTO.getMemberLevelDiscountPrice(), platformRatio); + } + @Override public void orderChange(AsOrderStatusChangeMsg orderMessage) { //付款后生成结算单项 diff --git a/shoptnt-core/src/main/java/cn/shoptnt/message/dispatcher/member/MemberPointChangeMessageDispatcher.java b/shoptnt-core/src/main/java/cn/shoptnt/message/dispatcher/member/MemberPointChangeMessageDispatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..b0851b28285c06298af1b3fb210f447c1d991e1a --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/message/dispatcher/member/MemberPointChangeMessageDispatcher.java @@ -0,0 +1,40 @@ +package cn.shoptnt.message.dispatcher.member; + +import cn.shoptnt.message.event.MemberPointChangeEvent; +import cn.shoptnt.message.event.MemberSignEvent; +import cn.shoptnt.model.base.message.MemberPointChangeMessage; +import cn.shoptnt.model.base.message.SignMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 会员站内消息 调度器 + * + * @author LiuXT + * @date 2022-10-21 + * @since v7.3.0 + */ +@Service +public class MemberPointChangeMessageDispatcher { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired(required = false) + private List events; + + public void dispatch(MemberPointChangeMessage message) { + if (events != null) { + for (MemberPointChangeEvent event : events) { + try { + event.memberPointChange(message.getMemberId()); + } catch (Exception e) { + logger.error("积分消息改变发送出错", e); + } + } + } + } +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/message/event/MemberPointChangeEvent.java b/shoptnt-core/src/main/java/cn/shoptnt/message/event/MemberPointChangeEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..0361e45ac4cde3d54b1fd63c56177cf0a466db99 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/message/event/MemberPointChangeEvent.java @@ -0,0 +1,20 @@ +package cn.shoptnt.message.event; + +/** + * @author zh + * @version 1.0 + * @title MemberPointChangeEvent + * @description 会员积分变化消息 + * @program: api + * 2024/5/24 15:48 + */ +public interface MemberPointChangeEvent { + + /** + * 会员积分变化事件 + * + * @param memberId 会员id + */ + void memberPointChange(Long memberId); + +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/base/message/MemberPointChangeMessage.java b/shoptnt-core/src/main/java/cn/shoptnt/model/base/message/MemberPointChangeMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..fa65b0248a53ef40155df0febea3349b516b0e07 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/base/message/MemberPointChangeMessage.java @@ -0,0 +1,38 @@ +package cn.shoptnt.model.base.message; + +import cn.shoptnt.framework.message.direct.AmqpExchange; +import cn.shoptnt.framework.message.direct.DirectMessage; + +import java.io.Serializable; + +/** + * @author zh + * @version 1.0 + * @title MemberPointChangeMessage + * @description 会员积分变化消息 + * @program: api + * 2024/5/24 15:36 + */ +public class MemberPointChangeMessage implements Serializable, DirectMessage { + private static final long serialVersionUID = -702596053091387934L; + + + private Long memberId; + + public MemberPointChangeMessage(Long memberId) { + this.memberId = memberId; + } + + public Long getMemberId() { + return memberId; + } + + public void setMemberId(Long memberId) { + this.memberId = memberId; + } + + @Override + public String getExchange() { + return AmqpExchange.MEMBER_POINT_CHANGE; + } +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/member/dos/Member.java b/shoptnt-core/src/main/java/cn/shoptnt/model/member/dos/Member.java index 9e3570e10bc2bb0bb1c51b8ae6673504eef0edb5..b79dd2e6069809b0b742744fe4c5e43875afe486 100644 --- a/shoptnt-core/src/main/java/cn/shoptnt/model/member/dos/Member.java +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/member/dos/Member.java @@ -239,6 +239,16 @@ public class Member implements Serializable { @Schema(name = "nickname", description = "昵称") private String nickname; + @Schema(name = "level_id", description = "会员等级") + private Long levelId; + + @Schema(name = "level_name", description = "等级名称") + private String levelName; + + @Schema(name = "level_icon", description = "等级图标") + private String levelIcon; + @Schema(name = "is_upgrade", description = "是否允许升级 0允许 -1不允许") + private Integer isUpgrade; @JsonIgnore @@ -252,7 +262,6 @@ public class Member implements Serializable { private Integer status; - public static long getSerialVersionUID() { return serialVersionUID; } @@ -557,6 +566,37 @@ public class Member implements Serializable { this.status = status; } + public Long getLevelId() { + return levelId; + } + + public void setLevelId(Long levelId) { + this.levelId = levelId; + } + + public String getLevelName() { + return levelName; + } + + public void setLevelName(String levelName) { + this.levelName = levelName; + } + + public String getLevelIcon() { + return levelIcon; + } + + public void setLevelIcon(String levelIcon) { + this.levelIcon = levelIcon; + } + + public Integer getIsUpgrade() { + return isUpgrade; + } + + public void setIsUpgrade(Integer isUpgrade) { + this.isUpgrade = isUpgrade; + } @Override public String toString() { @@ -758,11 +798,11 @@ public class Member implements Serializable { /** * 校验会员有效性 */ - public void checkDisable(){ - if (disabled.equals(-1)){ + public void checkDisable() { + if (disabled.equals(-1)) { throw new ServiceException(MemberErrorCode.E107.code(), "当前账号已经禁用,请联系管理员"); } - if (disabled.equals(-2)){ + if (disabled.equals(-2)) { throw new ServiceException(MemberErrorCode.E107.code(), "手机号尚未注册"); } } diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/member/dos/MemberLevel.java b/shoptnt-core/src/main/java/cn/shoptnt/model/member/dos/MemberLevel.java new file mode 100644 index 0000000000000000000000000000000000000000..dfaaaba833e81ebe21831cedb41fdee5021de032 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/member/dos/MemberLevel.java @@ -0,0 +1,164 @@ +package cn.shoptnt.model.member.dos; + +import cn.shoptnt.framework.database.annotation.Column; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; + +/** + * @author zh + * @version 1.0 + * @title MemberLevel + * @description 会员等级 + * @program: api + * 2024/5/20 16:22 + */ +@TableName("es_member_level") +@Schema +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class MemberLevel implements Serializable { + private static final long serialVersionUID = -6698537431688429877L; + + /** + * 主键ID + */ + @TableId(type = IdType.ASSIGN_ID) + @Schema(hidden = true) + private Long id; + + /** + * 等级名称 + */ + @NotBlank(message = "等级名称不能为空") + @Schema(name = "level_name", description = "等级名称") + private String levelName; + + /** + * 等级图标 + */ + @Schema(name = "level_icon", description = "等级图标") + private String levelIcon; + + /** + * 分摊比例 + */ + @Schema(name = "allocation_ratio", description = "分摊比例") + private Double allocationRatio; + + /** + * 创建时间 + */ + @Schema(name = "create_time", description = "创建时间", hidden = true) + private Long createTime; + /** + * 等级说明 + */ + @Schema(name = "description", description = "等级说明") + private String description; + /** + * 排序 + */ + @Schema(name = "sort_order", description = "排序", hidden = true) + private int sortOrder; + + /** + * 是否默认1是,0否 + */ + @Schema(name = "is_default", description = "是否默认1是,0否") + private Integer isDefault; + + + public MemberLevel() { + + } + + public MemberLevel(Long id, String name, int sortOrder) { + this.sortOrder = sortOrder; + this.id = id; + this.levelName = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getLevelName() { + return levelName; + } + + public void setLevelName(String levelName) { + this.levelName = levelName; + } + + public String getLevelIcon() { + return levelIcon; + } + + public void setLevelIcon(String levelIcon) { + this.levelIcon = levelIcon; + } + + public Double getAllocationRatio() { + return allocationRatio; + } + + public void setAllocationRatio(Double allocationRatio) { + this.allocationRatio = allocationRatio; + } + + public Long getCreateTime() { + return createTime; + } + + public void setCreateTime(Long createTime) { + this.createTime = createTime; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public int getSortOrder() { + return sortOrder; + } + + public void setSortOrder(int sortOrder) { + this.sortOrder = sortOrder; + } + + public Integer getIsDefault() { + return isDefault; + } + + public void setIsDefault(Integer isDefault) { + this.isDefault = isDefault; + } + + @Override + public String toString() { + return "MemberLevel{" + + "id=" + id + + ", levelName='" + levelName + '\'' + + ", levelIcon='" + levelIcon + '\'' + + ", allocationRatio=" + allocationRatio + + ", createTime=" + createTime + + ", description='" + description + '\'' + + ", sortOrder=" + sortOrder + + ", isDefault=" + isDefault + + '}'; + } +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/member/dos/MemberLevelBenefit.java b/shoptnt-core/src/main/java/cn/shoptnt/model/member/dos/MemberLevelBenefit.java new file mode 100644 index 0000000000000000000000000000000000000000..7020545790d9a3b712f734417f63a09b8aac7d98 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/member/dos/MemberLevelBenefit.java @@ -0,0 +1,97 @@ +package cn.shoptnt.model.member.dos; + +import cn.shoptnt.model.member.enums.MemberLevelBenefits; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.io.Serializable; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelUpgradeConditions + * @description 等级福利详情 + * @program: api + * 2024/5/20 20:49 + */ +@TableName("es_member_level_benefit") +@Schema +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class MemberLevelBenefit implements Serializable { + + private static final long serialVersionUID = -8369558751520262394L; + /** + * 主键ID + */ + @TableId(type = IdType.ASSIGN_ID) + @Schema(hidden = true) + private Long id; + + /** + * 等级id + */ + @Schema(name = "level_id", description = "等级id", hidden = true) + private Long levelId; + + /** + * 福利类型 + * + * @see cn.shoptnt.model.member.enums.MemberLevelBenefits + */ + @Schema(name = "benefit_type", description = "福利类型") + private MemberLevelBenefits benefitType; + + + /** + * 条件类型 + */ + @Schema(name = "benefit_value", description = "福利值") + private Long benefitValue; + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getLevelId() { + return levelId; + } + + public void setLevelId(Long levelId) { + this.levelId = levelId; + } + + public MemberLevelBenefits getBenefitType() { + return benefitType; + } + + public void setBenefitType(MemberLevelBenefits benefitType) { + this.benefitType = benefitType; + } + + public Long getBenefitValue() { + return benefitValue; + } + + public void setBenefitValue(Long benefitValue) { + this.benefitValue = benefitValue; + } + + @Override + public String toString() { + return "MemberLevelBenefits{" + + "id=" + id + + ", levelId='" + levelId + '\'' + + ", benefitType='" + benefitType + '\'' + + ", benefitValue='" + benefitValue + '\'' + + '}'; + } +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/member/dos/MemberLevelUpgradeCondition.java b/shoptnt-core/src/main/java/cn/shoptnt/model/member/dos/MemberLevelUpgradeCondition.java new file mode 100644 index 0000000000000000000000000000000000000000..fd3331a3b93610787bfea9237eb4356c2a818844 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/member/dos/MemberLevelUpgradeCondition.java @@ -0,0 +1,135 @@ +package cn.shoptnt.model.member.dos; + +import cn.shoptnt.model.member.enums.MemberLevelConditionOperator; +import cn.shoptnt.model.member.enums.MemberLevelConditionType; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.io.Serializable; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelUpgradeConditions + * @description 会员等级升级条件 + * @program: api + * 2024/5/20 20:49 + */ +@TableName("es_member_level_upgrade_condition") +@Schema +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class MemberLevelUpgradeCondition implements Serializable { + private static final long serialVersionUID = 1684466537187003610L; + + /** + * 主键ID + */ + @TableId(type = IdType.ASSIGN_ID) + @Schema(hidden = true) + private Long id; + + /** + * 等级id + */ + @Schema(name = "level_id", description = "等级id", hidden = true) + private Long levelId; + + /** + * 条件类型 + * + * @see cn.shoptnt.model.member.enums.MemberLevelConditionType + */ + @Schema(name = "condition_type", description = "条件类型") + private MemberLevelConditionType conditionType; + + + /** + * 条件类型 + * + * @see cn.shoptnt.model.member.enums.MemberLevelConditionOperator + */ + @Schema(name = "condition_operator", description = "条件关系") + private MemberLevelConditionOperator conditionOperator; + + + /** + * 条件最小值 + */ + @Schema(name = "condition_value_min", description = "条件最小值") + private Long conditionValueMin; + + /** + * 条件最大值 + */ + @Schema(name = "condition_value_max", description = "条件最大值") + private Long conditionValueMax; + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getLevelId() { + return levelId; + } + + public void setLevelId(Long levelId) { + this.levelId = levelId; + } + + public MemberLevelConditionType getConditionType() { + return conditionType; + } + + public void setConditionType(MemberLevelConditionType conditionType) { + this.conditionType = conditionType; + } + + public MemberLevelConditionOperator getConditionOperator() { + return conditionOperator; + } + + public void setConditionOperator(MemberLevelConditionOperator conditionOperator) { + this.conditionOperator = conditionOperator; + } + + public Long getConditionValueMin() { + return conditionValueMin; + } + + public void setConditionValueMin(Long conditionValueMin) { + this.conditionValueMin = conditionValueMin; + } + + public Long getConditionValueMax() { + return conditionValueMax; + } + + public void setConditionValueMax(Long conditionValueMax) { + this.conditionValueMax = conditionValueMax; + } + + + public boolean isWithinRange(long points) { + return points >= conditionValueMin && points <= conditionValueMax; + } + @Override + public String toString() { + return "MemberLevelUpgradeConditions{" + + "id=" + id + + ", levelId='" + levelId + '\'' + + ", conditionType='" + conditionType + '\'' + + ", conditionOperator='" + conditionOperator + '\'' + + ", conditionValueMin=" + conditionValueMin + + ", conditionValueMax=" + conditionValueMax + + '}'; + } +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/member/dto/MemberLevelCondition.java b/shoptnt-core/src/main/java/cn/shoptnt/model/member/dto/MemberLevelCondition.java new file mode 100644 index 0000000000000000000000000000000000000000..e0ea396c5e04a8cf9433c2de6f1d100ef9535d60 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/member/dto/MemberLevelCondition.java @@ -0,0 +1,52 @@ +package cn.shoptnt.model.member.dto; + +import cn.shoptnt.model.member.dos.MemberLevel; +import cn.shoptnt.model.member.dos.MemberLevelBenefit; +import cn.shoptnt.model.member.dos.MemberLevelUpgradeCondition; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.io.Serializable; +import java.util.List; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelCondition + * @description 会员等级条件dto + * @program: api + * 2024/5/20 18:12 + */ +public class MemberLevelCondition extends MemberLevel implements Serializable { + private static final long serialVersionUID = -8146121268955009250L; + + @Schema(name = "upgrade_conditions", description = "等级升级条件") + private List upgradeConditions; + + @Schema(name = "benefits", description = "等级福利") + private List benefits; + + + public List getUpgradeConditions() { + return upgradeConditions; + } + + public void setUpgradeConditions(List upgradeConditions) { + this.upgradeConditions = upgradeConditions; + } + + public List getBenefits() { + return benefits; + } + + public void setBenefits(List benefits) { + this.benefits = benefits; + } + + @Override + public String toString() { + return "MemberLevelCondition{" + + "upgradeConditions=" + upgradeConditions + + ", benefits=" + benefits + + '}'; + } +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/member/dto/MemberLevelDTO.java b/shoptnt-core/src/main/java/cn/shoptnt/model/member/dto/MemberLevelDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..63cef41ae637ce82d46018589156301956a08712 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/member/dto/MemberLevelDTO.java @@ -0,0 +1,87 @@ +package cn.shoptnt.model.member.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; + +/** + * @author zh + * @version 1.0 + * @title MemberLevel + * @description 会员等级 + * @program: api + * 2024/5/20 16:22 + */ +@Schema +@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) +public class MemberLevelDTO implements Serializable { + private static final long serialVersionUID = -6698557431688429877L; + + + + /** + * 等级名称 + */ + @NotBlank(message = "等级名称不能为空") + @Schema(name = "level_name", description = "等级名称") + private String levelName; + + /** + * 等级图标 + */ + @NotBlank(message = "等级图标不能为空") + @Schema(name = "level_icon", description = "等级图标") + private String levelIcon; + + /** + * 分摊比例 + */ + @Schema(name = "allocation_ratio", description = "分摊比例") + private Double allocationRatio; + + + /** + * 等级说明 + */ + @Schema(name = "description", description = "等级说明") + private String description; + + + public String getLevelName() { + return levelName; + } + + public void setLevelName(String levelName) { + this.levelName = levelName; + } + + public String getLevelIcon() { + return levelIcon; + } + + public void setLevelIcon(String levelIcon) { + this.levelIcon = levelIcon; + } + + public Double getAllocationRatio() { + return allocationRatio; + } + + public void setAllocationRatio(Double allocationRatio) { + this.allocationRatio = allocationRatio; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/member/enums/MemberLevelBenefits.java b/shoptnt-core/src/main/java/cn/shoptnt/model/member/enums/MemberLevelBenefits.java new file mode 100644 index 0000000000000000000000000000000000000000..1047b4ae56240a92095d6eaa0351d5672a61beea --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/member/enums/MemberLevelBenefits.java @@ -0,0 +1,41 @@ +/* + * SHOPTNT 版权所有。 + * 未经许可,您不得使用此文件。 + * 官方地址:www.shoptnt.cn + */ +package cn.shoptnt.model.member.enums; + +/** + * @author liuyulei + * @version 1.0 + * @Description: 会员等级福利类型 + * @date 2019/6/25 9:42 + * @since v7.0 + */ +public enum MemberLevelBenefits { + + /** + * 积分 + */ + POINTS("积分"), + + + /** + * 折扣 + */ + DISCOUNT("折扣"); + + private String description; + + MemberLevelBenefits(String description) { + this.description = description; + } + + public String description() { + return description; + } + + public String value() { + return this.name(); + } +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/member/enums/MemberLevelConditionOperator.java b/shoptnt-core/src/main/java/cn/shoptnt/model/member/enums/MemberLevelConditionOperator.java new file mode 100644 index 0000000000000000000000000000000000000000..c287f95ba37bda8f15957f3bc2707f219fa11183 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/member/enums/MemberLevelConditionOperator.java @@ -0,0 +1,41 @@ +/* + * SHOPTNT 版权所有。 + * 未经许可,您不得使用此文件。 + * 官方地址:www.shoptnt.cn + */ +package cn.shoptnt.model.member.enums; + +/** + * @author liuyulei + * @version 1.0 + * @Description: 会员等级条件关系 + * @date 2019/6/25 9:42 + * @since v7.0 + */ +public enum MemberLevelConditionOperator { + + /** + * 或者 + */ + OR("或者"), + + + /** + * 并且 + */ + AND("并且"); + + private String description; + + MemberLevelConditionOperator(String description) { + this.description = description; + } + + public String description() { + return description; + } + + public String value() { + return this.name(); + } +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/member/enums/MemberLevelConditionType.java b/shoptnt-core/src/main/java/cn/shoptnt/model/member/enums/MemberLevelConditionType.java new file mode 100644 index 0000000000000000000000000000000000000000..322830f0f40d52be3ea3558f97cbefe396dcd930 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/member/enums/MemberLevelConditionType.java @@ -0,0 +1,41 @@ +/* + * SHOPTNT 版权所有。 + * 未经许可,您不得使用此文件。 + * 官方地址:www.shoptnt.cn + */ +package cn.shoptnt.model.member.enums; + +/** + * @author liuyulei + * @version 1.0 + * @Description: 会员等级条件类型 + * @date 2019/6/25 9:42 + * @since v7.0 + */ +public enum MemberLevelConditionType { + + /** + * 积分 + */ + POINTS("积分"), + + + /** + * 消费金额 + */ + AMOUNT("消费金额"); + + private String description; + + MemberLevelConditionType(String description) { + this.description = description; + } + + public String description() { + return description; + } + + public String value() { + return this.name(); + } +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/orderbill/dos/Bill.java b/shoptnt-core/src/main/java/cn/shoptnt/model/orderbill/dos/Bill.java index 1879930c5b5205fc6e6a1bb9ae21f22e36840c3f..60a3603fafe679546714a85043c50e72526c71f1 100644 --- a/shoptnt-core/src/main/java/cn/shoptnt/model/orderbill/dos/Bill.java +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/orderbill/dos/Bill.java @@ -191,6 +191,9 @@ public class Bill implements Serializable { @Schema(name = "refund_total_price", description = "结算周期内订单退款总金额") private Double refundTotalPrice; + @Schema(name = "platform_member_level_price", description = "平台承担会员等级优惠金额") + private Double platformMemberLevelPrice; + @PrimaryKeyField public Long getBillId() { return billId; @@ -429,6 +432,14 @@ public class Bill implements Serializable { this.refundTotalPrice = refundTotalPrice; } + public Double getPlatformMemberLevelPrice() { + return platformMemberLevelPrice; + } + + public void setPlatformMemberLevelPrice(Double platformMemberLevelPrice) { + this.platformMemberLevelPrice = platformMemberLevelPrice; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/orderbill/dos/BillItem.java b/shoptnt-core/src/main/java/cn/shoptnt/model/orderbill/dos/BillItem.java index 3108a59be30b97e9f7baa1c445a8da7128395cd1..3b29cff9e33c8d43bcfd0f106232c2d2dcd4023d 100644 --- a/shoptnt-core/src/main/java/cn/shoptnt/model/orderbill/dos/BillItem.java +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/orderbill/dos/BillItem.java @@ -131,6 +131,12 @@ public class BillItem implements Serializable { @Schema(name = "coupon_commission", description = "站点优惠券佣金比例") private Double couponCommission; + /** + * 平台承担会员等级优惠的金额 + */ + @Schema(name = "platform_member_level_price", description = "平台承担会员等级优惠金额") + private Double platformMemberLevelPrice; + @PrimaryKeyField public Long getId() { @@ -277,6 +283,14 @@ public class BillItem implements Serializable { this.couponCommission = couponCommission; } + public Double getPlatformMemberLevelPrice() { + return platformMemberLevelPrice; + } + + public void setPlatformMemberLevelPrice(Double platformMemberLevelPrice) { + this.platformMemberLevelPrice = platformMemberLevelPrice; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/orderbill/vo/BillResult.java b/shoptnt-core/src/main/java/cn/shoptnt/model/orderbill/vo/BillResult.java index 35ff959d16ecb5bd83420b1dcf267d491f77d549..1f467b0517627c0af9a1942afd974c2f579ef648 100644 --- a/shoptnt-core/src/main/java/cn/shoptnt/model/orderbill/vo/BillResult.java +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/orderbill/vo/BillResult.java @@ -37,14 +37,18 @@ public class BillResult implements Serializable { @Schema(name = "site_coupon_commi", description = "站点优惠券佣金") private Double siteCouponCommi; + @Schema(name = "platform_member_level_price", description = "平台承担会员等级优惠金额") + private Double platformMemberLevelPrice; - public BillResult(Double onlinePrice, Double onlineRefundPrice, Double codPrice, Double codRefundPrice, Long sellerId,Double siteCouponCommi) { + + public BillResult(Double onlinePrice, Double onlineRefundPrice, Double codPrice, Double codRefundPrice, Long sellerId,Double siteCouponCommi, Double platformMemberLevelPrice) { this.onlinePrice = onlinePrice; this.onlineRefundPrice = onlineRefundPrice; this.codPrice = codPrice; this.codRefundPrice = codRefundPrice; this.sellerId = sellerId; this.siteCouponCommi = siteCouponCommi; + this.platformMemberLevelPrice = platformMemberLevelPrice; } public BillResult() { @@ -97,4 +101,12 @@ public class BillResult implements Serializable { public void setSiteCouponCommi(Double siteCouponCommi) { this.siteCouponCommi = siteCouponCommi; } + + public Double getPlatformMemberLevelPrice() { + return platformMemberLevelPrice; + } + + public void setPlatformMemberLevelPrice(Double platformMemberLevelPrice) { + this.platformMemberLevelPrice = platformMemberLevelPrice; + } } diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/trade/cart/vo/CartSkuVO.java b/shoptnt-core/src/main/java/cn/shoptnt/model/trade/cart/vo/CartSkuVO.java index 7a80d5603b6a7cf3d60c5297ecfb86d51b14bf4c..c6e077fde1ad47d0f94b4f70ad6299bffee63748 100644 --- a/shoptnt-core/src/main/java/cn/shoptnt/model/trade/cart/vo/CartSkuVO.java +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/trade/cart/vo/CartSkuVO.java @@ -160,6 +160,8 @@ public class CartSkuVO implements Serializable { private Double actualPrice; @Schema(description = "实际支付总价") private Double actualPayTotal; + @Schema(description = "会员等级优惠") + private Double memberLevelDiscountPrice; public Integer getPurchaseNum() { return purchaseNum; @@ -467,6 +469,14 @@ public class CartSkuVO implements Serializable { this.giveGift = giveGift; } + public Double getMemberLevelDiscountPrice() { + return memberLevelDiscountPrice; + } + + public void setMemberLevelDiscountPrice(Double memberLevelDiscountPrice) { + this.memberLevelDiscountPrice = memberLevelDiscountPrice; + } + @Override public String toString() { return "CartSkuVO{" + diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/trade/cart/vo/PriceDetailVO.java b/shoptnt-core/src/main/java/cn/shoptnt/model/trade/cart/vo/PriceDetailVO.java index 7fea49ebcade5ac0eb868ee9d5718e0fa6bcb1e9..b55ea1e1350d8c54b5fbaaedbc1b703e66cd6733 100644 --- a/shoptnt-core/src/main/java/cn/shoptnt/model/trade/cart/vo/PriceDetailVO.java +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/trade/cart/vo/PriceDetailVO.java @@ -74,6 +74,9 @@ public class PriceDetailVO implements Serializable { @Schema(description = "使用的积分") private Long exchangePoint; + @Schema(description = "会员等级折扣优惠金额") + private Double memberLevelDiscountPrice; + /** * 构造器,初始化默认值 */ @@ -88,6 +91,7 @@ public class PriceDetailVO implements Serializable { this.cashBack = 0D; this.originalPrice = 0D; fullMinus = 0d; + memberLevelDiscountPrice = 0d; } @@ -106,6 +110,7 @@ public class PriceDetailVO implements Serializable { this.originalPrice = 0D; this.couponPrice = 0D; fullMinus = 0d; + memberLevelDiscountPrice = 0D; } /** @@ -124,6 +129,7 @@ public class PriceDetailVO implements Serializable { double couponPrice = CurrencyUtil.add(this.couponPrice, price.getCouponPrice()); double cashBack = CurrencyUtil.add(this.cashBack, price.getCashBack()); double fullMinus = CurrencyUtil.add(this.cashBack, price.getFullMinus()); + double memberLevelDiscountPrice = CurrencyUtil.add(this.memberLevelDiscountPrice, price.getMemberLevelDiscountPrice()); Long point = this.exchangePoint + price.getExchangePoint(); PriceDetailVO newPrice = new PriceDetailVO(); @@ -138,6 +144,7 @@ public class PriceDetailVO implements Serializable { newPrice.setOriginalPrice(original); newPrice.setFullMinus(fullMinus); newPrice.setMinusPrice(this.minusPrice); + newPrice.setMemberLevelDiscountPrice(memberLevelDiscountPrice); return newPrice; } @@ -267,6 +274,14 @@ public class PriceDetailVO implements Serializable { this.couponPrice = couponPrice; } + public Double getMemberLevelDiscountPrice() { + return memberLevelDiscountPrice; + } + + public void setMemberLevelDiscountPrice(Double memberLevelDiscountPrice) { + this.memberLevelDiscountPrice = memberLevelDiscountPrice; + } + @Override public String toString() { return "PriceDetailVO{" + diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/trade/cart/vo/ScriptSkuVO.java b/shoptnt-core/src/main/java/cn/shoptnt/model/trade/cart/vo/ScriptSkuVO.java index b28cd0a72e7ff5e3a7a210580bcd841199985635..bba446e86d6889c657e25066cc370c2b4bc08061 100644 --- a/shoptnt-core/src/main/java/cn/shoptnt/model/trade/cart/vo/ScriptSkuVO.java +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/trade/cart/vo/ScriptSkuVO.java @@ -42,7 +42,7 @@ public class ScriptSkuVO implements Serializable { public ScriptSkuVO(CartSkuVO cartSkuVO) { this.$skuId = cartSkuVO.getSkuId(); this.$num = cartSkuVO.getNum(); - this.$price = cartSkuVO.getOriginalPrice(); + this.$price = cartSkuVO.getPurchasePrice(); this.$totalPrice = CurrencyUtil.mul(this.$price,this.$num); } diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/trade/order/dos/OrderDO.java b/shoptnt-core/src/main/java/cn/shoptnt/model/trade/order/dos/OrderDO.java index 923a8a987cf1d0d08dbfc8a16700e94740feb4df..536b1fd14add5d4ea208f02b2c2a8c8286ddd228 100644 --- a/shoptnt-core/src/main/java/cn/shoptnt/model/trade/order/dos/OrderDO.java +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/trade/order/dos/OrderDO.java @@ -444,6 +444,9 @@ public class OrderDO implements Serializable { @Column(name = "balance") private Double balance; + @Schema(description = "会员等级折扣优惠金额") + private Double memberLevelDiscountPrice; + @JsonIgnore protected String scanRounds; @@ -992,6 +995,13 @@ public class OrderDO implements Serializable { this.paymentMethodId = paymentMethodId; } + public Double getMemberLevelDiscountPrice() { + return memberLevelDiscountPrice; + } + + public void setMemberLevelDiscountPrice(Double memberLevelDiscountPrice) { + this.memberLevelDiscountPrice = memberLevelDiscountPrice; + } @Override public String toString() { @@ -1261,6 +1271,7 @@ public class OrderDO implements Serializable { this.weight = orderDTO.getWeight(); this.shippingId = orderDTO.getShippingId(); this.balance = 0D; + this.memberLevelDiscountPrice = priceDetail.getMemberLevelDiscountPrice(); // 卖家 this.sellerId = orderDTO.getSellerId(); diff --git a/shoptnt-core/src/main/java/cn/shoptnt/model/trade/order/dto/OrderDetailDTO.java b/shoptnt-core/src/main/java/cn/shoptnt/model/trade/order/dto/OrderDetailDTO.java index a8241fd22ff802c3894e38b857e68d7af8658c17..f0bccf1b66b0a1936b1d8690db23de8af70df59f 100644 --- a/shoptnt-core/src/main/java/cn/shoptnt/model/trade/order/dto/OrderDetailDTO.java +++ b/shoptnt-core/src/main/java/cn/shoptnt/model/trade/order/dto/OrderDetailDTO.java @@ -388,6 +388,9 @@ public class OrderDetailDTO { @Schema(description = "订单类型") private String orderType; + @Schema(description = "会员等级折扣优惠金额") + private Double memberLevelDiscountPrice; + public Integer getOrderId() { return orderId; } @@ -940,6 +943,14 @@ public class OrderDetailDTO { this.paymentName = paymentName; } + public Double getMemberLevelDiscountPrice() { + return memberLevelDiscountPrice; + } + + public void setMemberLevelDiscountPrice(Double memberLevelDiscountPrice) { + this.memberLevelDiscountPrice = memberLevelDiscountPrice; + } + public List getOrderSkuList() { if(orderSkuList==null && itemsJson!=null){ diff --git a/shoptnt-core/src/main/java/cn/shoptnt/service/member/MemberLevelBenefitManager.java b/shoptnt-core/src/main/java/cn/shoptnt/service/member/MemberLevelBenefitManager.java new file mode 100644 index 0000000000000000000000000000000000000000..e7336af2b577075f899ed920ce8a64d08f237650 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/service/member/MemberLevelBenefitManager.java @@ -0,0 +1,31 @@ +package cn.shoptnt.service.member; + +import cn.shoptnt.model.member.dos.MemberLevelBenefit; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelBenefitManager + * @description 等级赠送项 + * @program: api + * 2024/5/22 11:12 + */ +public interface MemberLevelBenefitManager extends IService { + /** + * 根据等级id查询福利详情 + * + * @param levelId 等级id + * @return 福利详情 + */ + List getByLevel(Long levelId); + + /** + * 根据会员等级删除福利 + * + * @param levelId 等级id + */ + void deleteBenefit(Long levelId); +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/service/member/MemberLevelManager.java b/shoptnt-core/src/main/java/cn/shoptnt/service/member/MemberLevelManager.java new file mode 100644 index 0000000000000000000000000000000000000000..a0a28a19c61f1ff8ff955a70cbcc18c765e12b48 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/service/member/MemberLevelManager.java @@ -0,0 +1,102 @@ +package cn.shoptnt.service.member; + +import cn.shoptnt.framework.database.WebPage; +import cn.shoptnt.model.member.dos.Member; +import cn.shoptnt.model.member.dos.MemberLevel; +import cn.shoptnt.model.member.dto.MemberLevelCondition; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelManager + * @description 会员等级业务类 + * @program: api + * 2024/5/20 16:31 + */ +public interface MemberLevelManager extends IService { + + + /** + * 获取会员等级数据 + * + * @return + */ + List list(); + + /** + * 添加会员等级 + * + * @param memberLevelCondition 会员等级信息 + * @return + */ + MemberLevel add(MemberLevelCondition memberLevelCondition); + + /** + * 查询会员等级详情 + * + * @param id 会员等级id + * @return + */ + MemberLevelCondition get(Long id); + + + /** + * 修改会员等级 + * + * @param id 会员等级id + * @param memberLevelCondition 修改参数 + * @return + */ + MemberLevelCondition edit(Long id, MemberLevelCondition memberLevelCondition); + + /** + * 查询会员默认等级详情 + * + * @return + */ + MemberLevel getDefault(); + + /** + * 删除会员等级 + * + * @param levelId 要删除的等级id + * @param transferLevelId 删除的会员等级迁移到的等级 + */ + void deleteLevel(Long levelId, Long transferLevelId); + + /** + * 迁移会员至新等级 + * + * @param members 会员 + * @param newLevel 新等级 + */ + void transferMembersToNewLevel(List members, MemberLevel newLevel); + + /** + * 会员等级排序 + * + * @param id 重新排序的会员等级的id + * @param targetPosition 拖动的会员等级放置的新位置 + */ + void updateSortOrder(Long id, Integer targetPosition); + + + /** + * 设置默认会员等级 + * + * @param id 重新排序的会员等级的id + */ + void assignDefaultLevel(Long id); + + /** + * 修改会员等级 + * + * @param memberId 会员id + * @param levelId 等级id + */ + void updateMemberLevel(Long memberId, Long levelId); + +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/service/member/MemberLevelUpgradeConditionManager.java b/shoptnt-core/src/main/java/cn/shoptnt/service/member/MemberLevelUpgradeConditionManager.java new file mode 100644 index 0000000000000000000000000000000000000000..e0ed611ff074e8f17530738a245bebf1e7ec1caa --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/service/member/MemberLevelUpgradeConditionManager.java @@ -0,0 +1,40 @@ +package cn.shoptnt.service.member; + +import cn.shoptnt.model.member.dos.MemberLevelUpgradeCondition; +import cn.shoptnt.model.member.enums.MemberLevelConditionType; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelUpgradeConditionsManager + * @description 会员等级升级条件管理类 + * @program: api + * 2024/5/20 21:20 + */ +public interface MemberLevelUpgradeConditionManager extends IService { + /** + * 根据等级id查询升级条件 + * + * @param levelId 等级id + * @return 升级条件 + */ + List getByLevelId(Long levelId); + + /** + * 根据等级id查询升级条件 + * + * @return 升级条件 + */ + List getList(); + + /** + * 根据等级id删除升级条件 + * + * @param levelId 等级id + */ + void deleteUpgradeCondition(Long levelId); + +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/service/member/MemberManager.java b/shoptnt-core/src/main/java/cn/shoptnt/service/member/MemberManager.java index 05591ae3c4099bf061e2be90f448420a1517058a..b6c6dd9ab343dfdccfbd453e9ec3979926163fdd 100644 --- a/shoptnt-core/src/main/java/cn/shoptnt/service/member/MemberManager.java +++ b/shoptnt-core/src/main/java/cn/shoptnt/service/member/MemberManager.java @@ -38,10 +38,12 @@ public interface MemberManager extends IService { /** * 修改会员登录次数 + * * @param memberId 会员id - * @param now 当前时间 + * @param now 当前时间 */ void updateLoginNum(Long memberId, Long now); + /** * 修改会员 * @@ -53,12 +55,14 @@ public interface MemberManager extends IService { /** * 禁用会员 + * * @param id 会员ID */ void disable(Long id); /** * 发送解禁会员消息 + * * @param id 会员ID */ void recoverySendMsg(Long id); @@ -129,8 +133,8 @@ public interface MemberManager extends IService { /** * 会员用户名密码登录 * - * @param username 用户名 - * @param password 密码 + * @param username 用户名 + * @param password 密码 * @param memberOrSeller 会员还是卖家,1 会员 2 卖家 * @return 是否登录成功 */ @@ -139,7 +143,7 @@ public interface MemberManager extends IService { /** * 动态登录 * - * @param phone 手机号码 + * @param phone 手机号码 * @param smsCode * @return 是否登录成功 */ @@ -153,11 +157,11 @@ public interface MemberManager extends IService { /** * 登录会员后的处理 * - * @param member 会员信息 + * @param member 会员信息 * @param memberOrSeller 会员还是卖家,1 会员 2 卖家 * @return */ - MemberVO loginHandle(Member member,Integer memberOrSeller); + MemberVO loginHandle(Member member, Integer memberOrSeller); /** * 联合登录后处理 @@ -217,18 +221,21 @@ public interface MemberManager extends IService { /** * 退出登录 + * * @param memberId 会员id */ void memberLoginout(Long memberId); /** * 查询所有会员id + * * @return */ List queryAllMemberIds(); /** * 获取会员信息 + * * @param memberId 会员ID * @return */ @@ -236,12 +243,14 @@ public interface MemberManager extends IService { /** * 休眠最后登陆时间为指定时间以前的账户 + * * @param timeStamp 时间 */ void sleepMember(Long timeStamp); /** * 会员签名数据扫描 + * * @return */ ScanResult scanModule(ScanModuleDTO scanModuleDTO); @@ -253,12 +262,14 @@ public interface MemberManager extends IService { /** * 修复会员数据 + * * @param memberId */ void repair(Long memberId); /** * 获取会员账户锁定状态 + * * @param memberId 会员id * @return true 已锁定;false 未锁定 */ @@ -266,19 +277,30 @@ public interface MemberManager extends IService { /** * 解除会员账户锁定状态 + * * @param memberId 会员id */ void unLock(Long memberId); /** * 用户注销 + * * @param smsCode 注销申请验证码 */ void logOff(String smsCode); /** * 查询会员数量 + * * @return 会员数量 */ Integer getCount(Long startTime, Long endTime); + + /** + * 根据等级id查询会员 + * + * @param levelId 等级id + * @return + */ + List getByLevelId(Long levelId); } diff --git a/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberLevelBenefitManagerImpl.java b/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberLevelBenefitManagerImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..fd4871443376616f979ab3d162cbb999f05304db --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberLevelBenefitManagerImpl.java @@ -0,0 +1,33 @@ +package cn.shoptnt.service.member.impl; + +import cn.shoptnt.mapper.member.MemberLevelBenefitMapper; +import cn.shoptnt.model.member.dos.MemberLevelBenefit; +import cn.shoptnt.service.member.MemberLevelBenefitManager; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelBenefitManagerImpl + * @description 会员等级礼物相关 + * @program: api + * 2024/5/22 11:15 + */ +@Service +public class MemberLevelBenefitManagerImpl extends ServiceImpl implements MemberLevelBenefitManager { + + + @Override + public List getByLevel(Long levelId) { + return this.list(new LambdaQueryWrapper().eq(MemberLevelBenefit::getLevelId, levelId)); + } + + @Override + public void deleteBenefit(Long levelId) { + this.remove(new LambdaQueryWrapper().eq(MemberLevelBenefit::getLevelId, levelId)); + } +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberLevelManagerImpl.java b/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberLevelManagerImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..99aff3ce2cdda7544cfcca84ab081c0c1b12862c --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberLevelManagerImpl.java @@ -0,0 +1,399 @@ +package cn.shoptnt.service.member.impl; + +import cn.shoptnt.framework.exception.ServiceException; +import cn.shoptnt.framework.util.BeanUtil; +import cn.shoptnt.framework.util.DateUtil; +import cn.shoptnt.mapper.member.MemberLevelMapper; +import cn.shoptnt.mapper.member.MemberLevelUpgradeConditionMapper; +import cn.shoptnt.model.errorcode.MemberErrorCode; +import cn.shoptnt.model.member.dos.Member; +import cn.shoptnt.model.member.dos.MemberLevel; +import cn.shoptnt.model.member.dos.MemberLevelBenefit; +import cn.shoptnt.model.member.dos.MemberLevelUpgradeCondition; +import cn.shoptnt.model.member.dto.MemberLevelCondition; +import cn.shoptnt.model.member.enums.MemberLevelConditionType; +import cn.shoptnt.service.member.MemberLevelBenefitManager; +import cn.shoptnt.service.member.MemberLevelManager; +import cn.shoptnt.service.member.MemberLevelUpgradeConditionManager; +import cn.shoptnt.service.member.MemberManager; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelManagerImpl + * @description 会员等级实现类 + * @program: api + * 2024/5/20 16:32 + */ +@Service +public class MemberLevelManagerImpl extends ServiceImpl implements MemberLevelManager { + + + @Autowired + private MemberLevelMapper memberLevelMapper; + + @Autowired + private MemberLevelBenefitManager memberLevelBenefitManager; + + @Autowired + private MemberLevelUpgradeConditionManager memberLevelUpgradeConditionManager; + + @Autowired + private MemberManager memberManager; + + + @Override + public List list() { + return memberLevelMapper.selectList(new LambdaQueryWrapper().orderByAsc(MemberLevel::getSortOrder)); + + } + + @Override + @Transactional(value = "memberTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class) + public MemberLevel add(MemberLevelCondition memberLevelCondition) { + + MemberLevel memberLevel = new MemberLevel(); + memberLevel.setLevelIcon(memberLevelCondition.getLevelIcon()); + memberLevel.setDescription(memberLevelCondition.getDescription()); + memberLevel.setAllocationRatio(memberLevelCondition.getAllocationRatio()); + memberLevel.setCreateTime(DateUtil.getDateline()); + memberLevel.setLevelName(memberLevelCondition.getLevelName()); + //校验等级名称重复 + List levels = memberLevelMapper.selectList(new LambdaQueryWrapper().eq(MemberLevel::getLevelName, memberLevelCondition.getLevelName())); + if (!levels.isEmpty()) { + throw new ServiceException(MemberErrorCode.E147.code(), "会员等级名称重复"); + } + //校验店铺分摊比例 + if (memberLevelCondition.getAllocationRatio() > 100) { + throw new ServiceException(MemberErrorCode.E147.code(), "店铺分摊比例错误"); + } + //第一个添加的等级为默认等级 + List memberLevels = memberLevelMapper.selectList(new LambdaQueryWrapper()); + if (memberLevels.isEmpty()) { + memberLevel.setIsDefault(1); + memberLevel.setSortOrder(0); + } + //处理排序字段 + int maxOrderSort = memberLevels.stream() + .max(Comparator.comparingInt(MemberLevel::getSortOrder)) + .map(MemberLevel::getSortOrder) + .orElse(0); + memberLevel.setSortOrder(maxOrderSort + 1); + //添加会员等级 + memberLevelMapper.insert(memberLevel); + //添加会员升级条件 + if (memberLevelCondition.getUpgradeConditions().isEmpty()) { + throw new ServiceException(MemberErrorCode.E147.code(), "会员升级条件缺失"); + } + //查询所有升级条件 为了校验条件是否正确 + List levelUpgradeConditionCheck = memberLevelUpgradeConditionManager.list(); + levelUpgradeConditionCheck.addAll(memberLevelCondition.getUpgradeConditions()); + boolean isValid = this.validateConditions(levelUpgradeConditionCheck); + if (!isValid) { + throw new ServiceException(MemberErrorCode.E147.code(), "区间出现重叠"); + } + //创建升级条件 + List levelUpgradeConditions = new ArrayList<>(); + for (MemberLevelUpgradeCondition memberLevelUpgradeCondition : memberLevelCondition.getUpgradeConditions()) { + if (memberLevelUpgradeCondition.getConditionValueMin() >= memberLevelUpgradeCondition.getConditionValueMax()) { + throw new ServiceException(MemberErrorCode.E147.code(), "区间填写错误,请检查后重新输入"); + } + MemberLevelUpgradeCondition levelUpgradeCondition = new MemberLevelUpgradeCondition(); + levelUpgradeCondition.setConditionType(memberLevelUpgradeCondition.getConditionType()); + levelUpgradeCondition.setLevelId(memberLevel.getId()); + levelUpgradeCondition.setConditionValueMin(memberLevelUpgradeCondition.getConditionValueMin()); + levelUpgradeCondition.setConditionValueMax(memberLevelUpgradeCondition.getConditionValueMax()); + levelUpgradeCondition.setConditionOperator(memberLevelUpgradeCondition.getConditionOperator()); + levelUpgradeConditions.add(levelUpgradeCondition); + } + memberLevelUpgradeConditionManager.saveBatch(levelUpgradeConditions); + //添加礼物项 + List memberLevelBenefits = new ArrayList<>(); + for (MemberLevelBenefit memberLevelBenefit : memberLevelCondition.getBenefits()) { + memberLevelBenefit.setLevelId(memberLevel.getId()); + memberLevelBenefits.add(memberLevelBenefit); + } + memberLevelBenefitManager.saveBatch(memberLevelBenefits); + return memberLevel; + } + + @Override + @Transactional(value = "memberTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class) + public MemberLevelCondition edit(Long id, MemberLevelCondition memberLevelCondition) { + //查询会员等级 + MemberLevel memberLevel = this.getById(id); + if (memberLevel == null) { + throw new ServiceException(MemberErrorCode.E147.code(), "会员等级不存在!"); + } + //校验名称是否重复 + List levels = memberLevelMapper.selectList(new LambdaQueryWrapper() + .eq(MemberLevel::getLevelName, memberLevelCondition.getLevelName()) + .ne(MemberLevel::getId, id)); + if (!levels.isEmpty()) { + throw new ServiceException(MemberErrorCode.E147.code(), "会员等级名称重复"); + } + //校验店铺分摊比例 + if (memberLevelCondition.getAllocationRatio() > 100) { + throw new ServiceException(MemberErrorCode.E147.code(), "店铺分摊比例错误"); + } + + BeanUtil.copyProperties(memberLevelCondition, memberLevel); + this.updateById(memberLevel); + //删除关联表 福利 + memberLevelBenefitManager.deleteBenefit(id); + + //添加 福利 + List memberLevelBenefits = new ArrayList<>(); + for (MemberLevelBenefit memberLevelBenefit : memberLevelCondition.getBenefits()) { + memberLevelBenefit.setLevelId(id); + memberLevelBenefits.add(memberLevelBenefit); + } + memberLevelBenefitManager.saveBatch(memberLevelBenefits); + //删除关联表 升级条件 + memberLevelUpgradeConditionManager.deleteUpgradeCondition(id); + //查询所有升级条件 为了校验条件是否正确 + List levelUpgradeConditionCheck = memberLevelUpgradeConditionManager.list(); + levelUpgradeConditionCheck.addAll(memberLevelCondition.getUpgradeConditions()); + boolean isValid = validateConditions(levelUpgradeConditionCheck); + if (!isValid) { + throw new ServiceException(MemberErrorCode.E147.code(), "区间填写错误,请检查后重新输入"); + } + //创建升级条件 + List levelUpgradeConditions = new ArrayList<>(); + for (MemberLevelUpgradeCondition memberLevelUpgradeCondition : memberLevelCondition.getUpgradeConditions()) { + if (memberLevelUpgradeCondition.getConditionValueMin() > memberLevelUpgradeCondition.getConditionValueMax()) { + throw new ServiceException(MemberErrorCode.E147.code(), "区间填写错误,请检查后重新输入"); + } + MemberLevelUpgradeCondition levelUpgradeCondition = new MemberLevelUpgradeCondition(); + levelUpgradeCondition.setConditionType(memberLevelUpgradeCondition.getConditionType()); + levelUpgradeCondition.setLevelId(id); + levelUpgradeCondition.setConditionValueMin(memberLevelUpgradeCondition.getConditionValueMin()); + levelUpgradeCondition.setConditionValueMax(memberLevelUpgradeCondition.getConditionValueMax()); + levelUpgradeCondition.setConditionOperator(memberLevelUpgradeCondition.getConditionOperator()); + levelUpgradeConditions.add(levelUpgradeCondition); + } + memberLevelUpgradeConditionManager.saveBatch(levelUpgradeConditions); + return memberLevelCondition; + } + + @Override + public MemberLevelCondition get(Long id) { + //查询会员等级 + MemberLevel memberLevel = this.getById(id); + if (memberLevel == null) { + throw new ServiceException(MemberErrorCode.E147.code(), "会员等级不存在!"); + } + MemberLevelCondition memberLevelCondition = new MemberLevelCondition(); + BeanUtil.copyProperties(memberLevel, memberLevelCondition); + //查询会员升级条件 + List conditions = memberLevelUpgradeConditionManager.getByLevelId(id); + if (!conditions.isEmpty()) { + memberLevelCondition.setUpgradeConditions(conditions); + } + //查询会员礼物赠送 + List benefits = memberLevelBenefitManager.getByLevel(id); + if (!benefits.isEmpty()) { + memberLevelCondition.setBenefits(benefits); + } + return memberLevelCondition; + } + + @Override + public MemberLevel getDefault() { + //这里使用list是为了避免出现数据错误(多个默认等级) + List list = lambdaQuery().eq(MemberLevel::getIsDefault, 1).list(); + if (list.isEmpty()) { + return null; + } + return list.get(0); + } + + @Override + @Transactional(value = "memberTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class) + public void deleteLevel(Long levelId, Long transferLevelId) { + MemberLevel memberLevel = this.getById(levelId); + if (memberLevel == null) { + throw new ServiceException(MemberErrorCode.E147.code(), "会员等级不存在!"); + } + if (memberLevel.getIsDefault().equals(1)) { + throw new ServiceException(MemberErrorCode.E147.code(), "默认等级无法删除!"); + } + //根据会员等级查询会员 + List members = memberManager.getByLevelId(levelId); + + // 检查是否有会员与该等级关联 + if (!members.isEmpty()) { + // 如果有会员关联,那么transferLevelId必须有值 + if (transferLevelId == null) { + throw new ServiceException(MemberErrorCode.E147.code(), "此等级已关联会员,需要选择迁移至的新等级"); + } else { + MemberLevel level = this.getById(transferLevelId); + if (level == null) { + throw new ServiceException(MemberErrorCode.E147.code(), "迁移处的新等级不存在!"); + } + // 如果transferLevelId有值,执行会员转移逻辑 + transferMembersToNewLevel(members, level); + } + } + //执行删除会员等级操作 + this.removeById(levelId); + //删除后排序规则改变 + List memberLevels = this.list(new LambdaQueryWrapper()); + //重新排序 + deleteMemberLevel(memberLevels); + //执行更改 将删除后的会员等级重新进行排序 + this.updateBatchById(memberLevels); + + //删除关联表 升级条件 + memberLevelBenefitManager.deleteBenefit(levelId); + //删除关联表 福利 + memberLevelUpgradeConditionManager.deleteUpgradeCondition(levelId); + + } + + + @Override + public void transferMembersToNewLevel(List members, MemberLevel newLevel) { + List newMembers = members.stream().map(member -> { + member.setLevelId(newLevel.getId()); + member.setLevelIcon(newLevel.getLevelIcon()); + member.setLevelName(newLevel.getLevelName()); + return member; + }).collect(Collectors.toList()); + //执行修改 + memberManager.updateBatchById(newMembers); + } + + + @Override + public void updateSortOrder(Long id, Integer targetPosition) { + List memberLevels = this.list(new LambdaQueryWrapper()); + //执行移动 + moveMemberLevel(memberLevels, id, targetPosition); + //执行修改 + this.updateBatchById(memberLevels); + } + + @Override + @Transactional(value = "memberTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class) + public void assignDefaultLevel(Long id) { + MemberLevel memberLevel = this.getById(id); + if (memberLevel == null) { + throw new ServiceException(MemberErrorCode.E147.code(), "会员等级不存在!"); + } + //修改所有等级为非默认 + List memberLevels = this.list(new LambdaQueryWrapper()); + memberLevels.stream().map(level -> { + level.setIsDefault(0); + return level; + }).collect(Collectors.toList()); + this.updateBatchById(memberLevels); + //修改当前会员等级为默认 + memberLevel.setIsDefault(1); + this.updateById(memberLevel); + } + + /** + * 移动会员等级重新排序 + * + * @param memberLevels 会员等级 + * @param levelId 等级id + * @param newSortOrder 排序 + */ + private void moveMemberLevel(List memberLevels, Long levelId, Integer newSortOrder) { + MemberLevel memberToMove = null; + for (MemberLevel member : memberLevels) { + if (member.getId().equals(levelId)) { + memberToMove = member; + break; + } + } + if (memberToMove == null) { + throw new ServiceException(MemberErrorCode.E147.code(), "参数错误!"); + } + memberLevels.remove(memberToMove); + memberLevels.add(newSortOrder, memberToMove); + // 重新分配sortOrder + for (int i = 0; i < memberLevels.size(); i++) { + memberLevels.get(i).setSortOrder(i); + } + + } + + /** + * 删除某个会员重新排序 + * + * @param memberLevels 会员等级 + */ + private void deleteMemberLevel(List memberLevels) { + + for (int i = 0; i < memberLevels.size(); i++) { + memberLevels.get(i).setSortOrder(i); + } + } + + @Override + @Transactional(value = "memberTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class) + public void updateMemberLevel(Long memberId, Long levelId) { + //查询会员信息 + Member member = memberManager.getModel(memberId); + //查询当前会员的等级 + MemberLevel currentMemberLevel = this.getById(levelId); + + //查询会员等级 + MemberLevel memberLevel = this.getById(levelId); + + if (memberLevel != null && member != null) { + //如果修改等级 降级情况下 此会员不允许在参与等级体系升级 + if (currentMemberLevel.getSortOrder() > memberLevel.getSortOrder()) { + member.setIsUpgrade(-1); + } + member.setLevelId(memberLevel.getId()); + member.setLevelIcon(memberLevel.getLevelIcon()); + member.setLevelName(memberLevel.getLevelName()); + memberManager.updateById(member); + } + } + + /** + * 校验区间正确性 + * + * @param levelUpgradeConditions 升级条件 + * @return + */ + public boolean validateConditions(List levelUpgradeConditions) { + // 按照条件类型分组 + Map> groupedConditions = levelUpgradeConditions.stream() + .collect(Collectors.groupingBy(MemberLevelUpgradeCondition::getConditionType)); + + // 对每个分组的条件进行校验 + for (Map.Entry> entry : groupedConditions.entrySet()) { + List conditionsForType = entry.getValue(); + // 按照最小值排序 + conditionsForType.sort(Comparator.comparingLong(MemberLevelUpgradeCondition::getConditionValueMin)); + + // 遍历条件列表进行校验 + long previousMax = 0; // 初始化为0,假设没有条件的最大值是小于1的 + for (MemberLevelUpgradeCondition condition : conditionsForType) { + // 如果当前条件的最小值小于或等于前一个条件的最大值,则校验失败 + if (condition.getConditionValueMin() <= previousMax) { + return false; + } + // 更新前一个条件的最大值 + previousMax = condition.getConditionValueMax(); + } + } + return true; + } + + +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberLevelUpgradeConditionsManagerImpl.java b/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberLevelUpgradeConditionsManagerImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..1a31e861b2f1a5ce7cc2cb681b0b7c4dfffe53f2 --- /dev/null +++ b/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberLevelUpgradeConditionsManagerImpl.java @@ -0,0 +1,40 @@ +package cn.shoptnt.service.member.impl; + +import cn.shoptnt.mapper.member.MemberLevelUpgradeConditionMapper; +import cn.shoptnt.model.member.dos.MemberLevelUpgradeCondition; +import cn.shoptnt.model.member.enums.MemberLevelConditionType; +import cn.shoptnt.service.member.MemberLevelUpgradeConditionManager; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author zh + * @version 1.0 + * @title MemberLevelUpgradeConditionsManagerImpl + * @description 会员等级升级条件实现管理类 + * @program: api + * 2024/5/20 21:23 + */ +@Service +public class MemberLevelUpgradeConditionsManagerImpl extends ServiceImpl implements MemberLevelUpgradeConditionManager { + + + @Override + public List getByLevelId(Long levelId) { + return this.list(new LambdaQueryWrapper().eq(MemberLevelUpgradeCondition::getLevelId, levelId)); + } + + @Override + public List getList() { + return this.list(new LambdaQueryWrapper()); + } + + @Override + public void deleteUpgradeCondition(Long levelId) { + this.remove(new LambdaQueryWrapper().eq(MemberLevelUpgradeCondition::getLevelId, levelId)); + } +} diff --git a/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberManagerImpl.java b/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberManagerImpl.java index 4b9a551c31af6d758813c430bd5e48287d390208..42ab10bcd2486fda6a7e8b6ba4b9dbe70d84e1cd 100644 --- a/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberManagerImpl.java +++ b/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberManagerImpl.java @@ -33,6 +33,7 @@ import cn.shoptnt.model.base.message.MemberRegisterMsg; import cn.shoptnt.model.errorcode.MemberErrorCode; import cn.shoptnt.model.member.dos.LogOffMember; import cn.shoptnt.model.member.dos.Member; +import cn.shoptnt.model.member.dos.MemberLevel; import cn.shoptnt.model.member.dto.MemberQueryParam; import cn.shoptnt.model.member.dto.MemberStatisticsDTO; import cn.shoptnt.model.member.vo.BackendMemberVO; @@ -46,10 +47,7 @@ import cn.shoptnt.model.support.validator.annotation.LogLevel; import cn.shoptnt.model.system.dos.SystemLogs; import cn.shoptnt.model.system.vo.AccountSetting; import cn.shoptnt.model.trade.order.enums.CommentStatusEnum; -import cn.shoptnt.service.member.LogOffMemberManager; -import cn.shoptnt.service.member.MemberCollectionGoodsManager; -import cn.shoptnt.service.member.MemberCollectionShopManager; -import cn.shoptnt.service.member.MemberManager; +import cn.shoptnt.service.member.*; import cn.shoptnt.service.shop.ClerkManager; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; @@ -108,6 +106,8 @@ public class MemberManagerImpl extends ServiceImpl impleme @Autowired private LogOffMemberManager logOffMemberManager; + @Autowired + private MemberLevelManager memberLevelManager; /** * 查询会员列表 @@ -346,6 +346,13 @@ public class MemberManagerImpl extends ServiceImpl impleme throw new ServiceException(MemberErrorCode.E117.code(), "邮箱已经被占用"); } } + //查询会员默认等级 + MemberLevel memberLevel = memberLevelManager.getDefault(); + if (memberLevel != null) { + member.setLevelId(memberLevel.getId()); + member.setLevelName(memberLevel.getLevelName()); + member.setLevelIcon(memberLevel.getLevelIcon()); + } //获取前端传入的密码 String password = member.getPassword(); //将密码+用户名进行MD5加密,然后放入会员对象中 @@ -922,4 +929,11 @@ public class MemberManagerImpl extends ServiceImpl impleme .le(endTime != null, Member::getCreateTime, endTime) .count(); } + + @Override + public List getByLevelId(Long levelId) { + return lambdaQuery() + .eq(Member::getLevelId, levelId) + .list(); + } } diff --git a/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberPointManagerImpl.java b/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberPointManagerImpl.java index e4a0b6faa171ce978422c7b0905a042644e625cc..84d71a40366d76cf70144223b0da19efa6c587a4 100644 --- a/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberPointManagerImpl.java +++ b/shoptnt-core/src/main/java/cn/shoptnt/service/member/impl/MemberPointManagerImpl.java @@ -5,6 +5,9 @@ */ package cn.shoptnt.service.member.impl; +import cn.shoptnt.framework.message.direct.DirectMessageSender; +import cn.shoptnt.model.base.message.MemberPointChangeMessage; +import cn.shoptnt.model.base.message.SignMessage; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import cn.shoptnt.mapper.member.MemberMapper; import cn.shoptnt.mapper.member.MemberPointHistoryMapper; @@ -43,7 +46,7 @@ public class MemberPointManagerImpl implements MemberPointManager { @Autowired private MemberMapper memberMapper; @Autowired - private MemberPointHistoryMapper memberPointHistoryMapper; + private DirectMessageSender messageSender; @Override @Transactional(value = "memberTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class) @@ -107,11 +110,15 @@ public class MemberPointManagerImpl implements MemberPointManager { gradeWrapper.eq("member_id", member.getMemberId()); //修改会员消费积分 memberMapper.update(null, gradeWrapper); + //发送积分变更通知 + MemberPointChangeMessage signMessage = new MemberPointChangeMessage(member.getMemberId()); + this.messageSender.send(signMessage); } /** * 检测会员积分信息 + * * @param memberPointHistory 会员积分信息 * @return */ diff --git a/shoptnt-core/src/main/java/cn/shoptnt/service/orderbill/impl/BillManagerImpl.java b/shoptnt-core/src/main/java/cn/shoptnt/service/orderbill/impl/BillManagerImpl.java index a9704824b223e244fba98eb6bebdf404cffa1d96..20e8f0b88917e5791de6ecd3b28d395c7f401fc7 100644 --- a/shoptnt-core/src/main/java/cn/shoptnt/service/orderbill/impl/BillManagerImpl.java +++ b/shoptnt-core/src/main/java/cn/shoptnt/service/orderbill/impl/BillManagerImpl.java @@ -191,7 +191,7 @@ public class BillManagerImpl implements BillManager { BillResult billRes = billMap.get(sellerId); //为空说明上个结算周期没有响应没有订单记录 if (billRes == null) { - billRes = new BillResult(0.00, 0.00, 0.00, 0.00, sellerId,0.00); + billRes = new BillResult(0.00, 0.00, 0.00, 0.00, sellerId,0.00, 0.0); } //创建结算单号 String billSn = this.createBillSn(); @@ -209,6 +209,8 @@ public class BillManagerImpl implements BillManager { Double commissionPrice = CurrencyUtil.mul(CurrencyUtil.add(onlinePrice, codPrice), commissionRate); //退还佣金 总退款金额 * 佣金比例 Double refundCommissionPrice = CurrencyUtil.mul(CurrencyUtil.add(onlineRefundPrice, codRefundPrice), commissionRate); + // 平台承担会员等级折扣优惠金额 + Double platformMemberLevelPrice = billRes.getPlatformMemberLevelPrice(); //分销商品返现 Double distributionGoodsRebate = 0d; @@ -243,6 +245,9 @@ public class BillManagerImpl implements BillManager { //最终结算金额 = 商家结算 - 分销结算 billPrice = CurrencyUtil.sub(billPrice, distributionBillPrice); + //最终结算金额需要再加上会员等级折扣优惠平台承担金额 + billPrice = CurrencyUtil.add(billPrice, platformMemberLevelPrice); + Bill bill = new Bill(); bill.setStartTime(startTime); bill.setEndTime(endTime); @@ -275,6 +280,7 @@ public class BillManagerImpl implements BillManager { bill.setDistributionReturnRebate(distributionReturnRebate); bill.setOrderTotalPrice(orderTotal); bill.setRefundTotalPrice(refundTotal); + bill.setPlatformMemberLevelPrice(platformMemberLevelPrice); this.add(bill); //更新结算项 this.billItemManager.updateBillItem(sellerId, bill.getBillId(), String.valueOf(startTime), lastTime); diff --git a/shoptnt-core/src/main/java/cn/shoptnt/service/trade/cart/cartbuilder/impl/CartPriceCalculatorImpl.java b/shoptnt-core/src/main/java/cn/shoptnt/service/trade/cart/cartbuilder/impl/CartPriceCalculatorImpl.java index 71ce8125542a83bd7ac1d45e01a0888e16e987dd..b7d56a528d4258bd3ada223f4fb5e5fa9cc6d631 100644 --- a/shoptnt-core/src/main/java/cn/shoptnt/service/trade/cart/cartbuilder/impl/CartPriceCalculatorImpl.java +++ b/shoptnt-core/src/main/java/cn/shoptnt/service/trade/cart/cartbuilder/impl/CartPriceCalculatorImpl.java @@ -5,13 +5,19 @@ */ package cn.shoptnt.service.trade.cart.cartbuilder.impl; +import cn.shoptnt.framework.context.user.UserContext; import cn.shoptnt.framework.util.CurrencyUtil; import cn.shoptnt.framework.util.JsonUtil; import cn.shoptnt.framework.util.StringUtil; +import cn.shoptnt.model.member.dos.Member; +import cn.shoptnt.model.member.dos.MemberLevelBenefit; +import cn.shoptnt.model.member.enums.MemberLevelBenefits; import cn.shoptnt.model.promotion.tool.enums.PromotionTypeEnum; import cn.shoptnt.model.promotion.tool.vo.GiveGiftVO; import cn.shoptnt.model.trade.cart.enums.CartType; import cn.shoptnt.model.trade.cart.vo.*; +import cn.shoptnt.service.member.MemberLevelBenefitManager; +import cn.shoptnt.service.member.MemberManager; import cn.shoptnt.service.trade.cart.CartPromotionManager; import cn.shoptnt.service.trade.cart.cartbuilder.CartPriceCalculator; import cn.shoptnt.service.trade.cart.cartbuilder.ScriptProcess; @@ -46,6 +52,12 @@ public class CartPriceCalculatorImpl implements CartPriceCalculator { @Autowired private ScriptProcess scriptProcess; + @Autowired + private MemberManager memberManager; + + @Autowired + private MemberLevelBenefitManager memberLevelBenefitManager; + @Override public PriceDetailVO countPrice(List cartList, Boolean includeCoupon) { @@ -80,6 +92,8 @@ public class CartPriceCalculatorImpl implements CartPriceCalculator { Map> singlePromotionMap = selectedPromotionVo.getSinglePromotionMap(); //用户选择使用的优惠券 Map couponMap = selectedPromotionVo.getCouponMap(); + // 查询会员等级的折扣优惠 + MemberLevelBenefit memberLevelDiscount = getMemberLevelDiscount(); for (CartVO cart : cartList) { //未选中的购物车不参与计算 @@ -99,6 +113,8 @@ public class CartPriceCalculatorImpl implements CartPriceCalculator { if (cartSku.getChecked() == 0) { continue; } + //计算会员等级折扣优惠 + this.calculatorMemberLevelDiscount(cartSku, memberLevelDiscount); //计算单品活动促销优惠 this.calculatorSingleScript(cart, singlePromotions, cartPrice, cartSku); if (cartSku.getGroupList().contains(groupPromotion)) { @@ -140,13 +156,38 @@ public class CartPriceCalculatorImpl implements CartPriceCalculator { calculatorCoupon(price, couponVO); } - logger.debug("计算完优惠后购物车数据为:",cartList); + logger.debug("计算完优惠后购物车数据为:", cartList); - logger.debug("价格为:",price); + logger.debug("价格为:", price); return price; } + private void calculatorMemberLevelDiscount(CartSkuVO cartSku, MemberLevelBenefit memberLevelDiscount) { + cartSku.setMemberLevelDiscountPrice(0.0); + if (memberLevelDiscount == null) { + return; + } + + // 折扣比例 + double discountRatio = CurrencyUtil.div(memberLevelDiscount.getBenefitValue(), 100); + // 成交价格 + double purchaseTotalPrice = CurrencyUtil.mul(cartSku.getSubtotal(), discountRatio); + // 会员等级优惠的价格 + double discountPrice = CurrencyUtil.sub(cartSku.getSubtotal(), purchaseTotalPrice); + + cartSku.setSubtotal(purchaseTotalPrice); + cartSku.setMemberLevelDiscountPrice(discountPrice); + cartSku.setPurchasePrice(CurrencyUtil.div(purchaseTotalPrice, cartSku.getNum())); + cartSku.setActualPrice(cartSku.getPurchasePrice()); + } + + private MemberLevelBenefit getMemberLevelDiscount() { + Member member = memberManager.getModel(UserContext.getBuyer().getUid()); + List benefitList = memberLevelBenefitManager.getByLevel(member.getLevelId()); + return benefitList.stream().filter(memberLevelBenefit -> memberLevelBenefit.getBenefitType() == MemberLevelBenefits.DISCOUNT).findFirst().orElse(null); + } + /** * 计算组合活动优惠 * @@ -171,32 +212,32 @@ public class CartPriceCalculatorImpl implements CartPriceCalculator { //优惠后总金额 cost = scriptProcess.countPrice(groupPromotion.getPromotionScript(), param); - Double surplusFmPrice=0D; + Double surplusFmPrice = 0D; //优惠金额 Double diff = CurrencyUtil.sub(sum, cost); for (int i = 0; i < collect.size(); i++) { - CartSkuVO cartSku =collect.get(i); + CartSkuVO cartSku = collect.get(i); if (i != collect.size() - 1) { //优惠的金额 公式为S1 = X A m / (A m + B n)。此时注意是先优惠金额乘SKU的金额,再除以SKU总金额。 - Double discount = CurrencyUtil.div(CurrencyUtil.mul(cartSku.getSubtotal(), diff),sum); + Double discount = CurrencyUtil.div(CurrencyUtil.mul(cartSku.getSubtotal(), diff), sum); //实际总额 double total = CurrencyUtil.sub(cartSku.getSubtotal(), discount); //商品实际支付单价 - cartSku.setActualPrice( CurrencyUtil.div(total, cartSku.getNum())); + cartSku.setActualPrice(CurrencyUtil.div(total, cartSku.getNum())); cartSku.setActualPayTotal(total); //已使用优惠金额 surplusFmPrice = CurrencyUtil.add(surplusFmPrice, discount); - }else { + } else { //剩余优惠总额 Double surplus = CurrencyUtil.sub(diff, surplusFmPrice); //实际总额 double actualPay = CurrencyUtil.sub(cartSku.getSubtotal(), surplus); cartSku.setActualPayTotal(actualPay); - cartSku.setActualPrice( CurrencyUtil.div(actualPay, cartSku.getNum())); + cartSku.setActualPrice(CurrencyUtil.div(actualPay, cartSku.getNum())); } } - + //获取赠品信息 giftJson = scriptProcess.giveGift(groupPromotion.getPromotionScript(), param); //设置购物车赠品信息 @@ -263,7 +304,7 @@ public class CartPriceCalculatorImpl implements CartPriceCalculator { cartSku.setPoint(point); cartSku.setSubtotal(cost); - cartSku.setActualPrice( CurrencyUtil.div(cost, cartSku.getNum())); + cartSku.setActualPrice(CurrencyUtil.div(cost, cartSku.getNum())); // 如果是单品立减,需要计算该活动减去了多少,并记录在 PriceDetailVO cartPrice中 if (promotionVo.getPromotionType().equals(PromotionTypeEnum.MINUS.name())) { cartPrice.setMinusPrice(CurrencyUtil.sub(skuVO.get$totalPrice(), cost)); @@ -281,8 +322,12 @@ public class CartPriceCalculatorImpl implements CartPriceCalculator { //购物车所有小计合 cartPrice.setGoodsPrice(CurrencyUtil.add(cartPrice.getGoodsPrice(), cartSku.getSubtotal())); + //会员等级优惠累计 + cartPrice.setMemberLevelDiscountPrice(CurrencyUtil.add(cartPrice.getMemberLevelDiscountPrice(), cartSku.getMemberLevelDiscountPrice())); + //购物车返现合 cartPrice.setCashBack(CurrencyUtil.add(cartPrice.getCashBack(), CurrencyUtil.sub(CurrencyUtil.mul(cartSku.getOriginalPrice(), cartSku.getNum()), cartSku.getSubtotal()))); + cartPrice.setCashBack(CurrencyUtil.sub(cartPrice.getCashBack(), cartPrice.getMemberLevelDiscountPrice())); //购物车使用积分 cartPrice.setExchangePoint(cartPrice.getExchangePoint() + cartSku.getPoint()); diff --git a/shoptnt-core/src/main/resources/mapper/trade/BillItemMapper.xml b/shoptnt-core/src/main/resources/mapper/trade/BillItemMapper.xml index 6adb0ba7d6f9479ea5c7c9b19b8909049dacf373..2e4b039e1d043576f4c25f55e1c8e5eec67c59d3 100644 --- a/shoptnt-core/src/main/resources/mapper/trade/BillItemMapper.xml +++ b/shoptnt-core/src/main/resources/mapper/trade/BillItemMapper.xml @@ -18,7 +18,8 @@ sum(case when payment_type = 'online' and item_type = 'REFUND' then price else 0 end ) online_refund_price , sum(case when payment_type = 'cod' and item_type = 'PAYMENT' then price else 0 end ) cod_price, sum(case when payment_type = 'cod' and item_type = 'REFUND' then price else 0 end ) cod_refund_price,seller_id, - sum(case when item_type = 'PAYMENT' then site_coupon_price*coupon_commission else 0 end ) as site_coupon_commi + sum(case when item_type = 'PAYMENT' then site_coupon_price*coupon_commission else 0 end ) as site_coupon_commi, + sum(case when item_type = 'PAYMENT' then platform_member_level_price else 0 end ) as platform_member_level_price from es_bill_item where `status` = 0 and (add_time < #{lastTime} and add_time >= #{startTime}) and bill_id is null group by seller_id diff --git a/sql/database.sql b/sql/database.sql index ab10791e1d44fe543f19d945ffd64284fd528292..e5561f365d61662674b92804aea02c93e5f7a262 100644 --- a/sql/database.sql +++ b/sql/database.sql @@ -372,6 +372,7 @@ CREATE TABLE `es_bill` ( `site_coupon_commi` decimal(20,2) DEFAULT '0.00' COMMENT '平台优惠券佣金', `order_total_price` decimal(20,2) DEFAULT '0.00' COMMENT '结算周期内订单付款总金额', `refund_total_price` decimal(20,2) DEFAULT '0.00' COMMENT '结算周期内订单退款总金额', + `platform_member_level_price` decimal(20,2) DEFAULT '0.00' COMMENT '平台承担会员等级优惠金额', PRIMARY KEY (`bill_id`) USING BTREE, KEY `index_bill` (`bill_id`,`bill_sn`,`status`,`bill_type`,`seller_id`,`sn`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='结算单(es_bill)'; @@ -401,6 +402,7 @@ CREATE TABLE `es_bill_item` ( `refund_time` bigint(20) DEFAULT NULL COMMENT '退货时间', `site_coupon_price` decimal(10,2) DEFAULT '0.00' COMMENT '使用平台优惠券金额', `coupon_commission` decimal(10,2) DEFAULT '0.00' COMMENT '优惠券佣金比例', + `platform_member_level_price` decimal(20,2) DEFAULT '0.00' COMMENT '平台承担会员等级优惠金额', PRIMARY KEY (`id`) USING BTREE, KEY `index_bill_item` (`id`,`order_sn`,`bill_id`,`member_id`,`status`,`seller_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='结算单项表(es_bill_item)'; @@ -2938,6 +2940,7 @@ CREATE TABLE `es_order` ( `sign` varchar(255) DEFAULT NULL, `sign_result` int(1) DEFAULT '0', `scan_rounds` varchar(50) DEFAULT NULL, + `member_level_discount_price` decimal(20,2) DEFAULT '0.00' COMMENT '会员等级优惠金额', PRIMARY KEY (`order_id`) USING BTREE, KEY `ind_order_sn` (`sn`) USING BTREE, KEY `ind_order_state` (`order_status`,`pay_status`,`ship_status`) USING BTREE,