|
|
@@ -8,6 +8,7 @@ import com.xuekairui.user.dto.GrantMembershipRequest;
|
|
|
import com.xuekairui.user.dto.LevelPricingPlan;
|
|
|
import com.xuekairui.user.dto.MembershipBenefitResponse;
|
|
|
import com.xuekairui.user.dto.MembershipResponse;
|
|
|
+import com.xuekairui.user.dto.MembershipUserResponse;
|
|
|
import com.xuekairui.user.dto.UserLevelResponse;
|
|
|
import com.xuekairui.user.entity.MembershipBenefit;
|
|
|
import com.xuekairui.user.entity.User;
|
|
|
@@ -362,6 +363,71 @@ public class MembershipService {
|
|
|
return responsePage;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 会员用户快照列表(用户维度,查 t_user + 当前会员)
|
|
|
+ */
|
|
|
+ public Page<MembershipUserResponse> listMembershipUsers(Integer pageNum, Integer pageSize,
|
|
|
+ String phone, String level) {
|
|
|
+ Page<User> page = new Page<>(pageNum, pageSize);
|
|
|
+ LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ if (phone != null && !phone.isBlank()) {
|
|
|
+ wrapper.like(User::getPhone, phone);
|
|
|
+ }
|
|
|
+ if (level != null && !level.isBlank()) {
|
|
|
+ MembershipLevel ml = MembershipLevel.fromCode(level);
|
|
|
+ if (ml != null) {
|
|
|
+ wrapper.eq(User::getMembershipLevel, ml);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ wrapper.orderByDesc(User::getCreateTime);
|
|
|
+ Page<User> result = userMapper.selectPage(page, wrapper);
|
|
|
+
|
|
|
+ // 批量查活跃会员记录,取 source
|
|
|
+ List<Long> userIds = result.getRecords().stream().map(User::getId).toList();
|
|
|
+ Map<Long, String> sourceMap = userIds.isEmpty() ? Map.of()
|
|
|
+ : userMembershipMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<UserMembership>()
|
|
|
+ .in(UserMembership::getUserId, userIds)
|
|
|
+ .eq(UserMembership::getStatus, 1))
|
|
|
+ .stream().collect(Collectors.toMap(
|
|
|
+ UserMembership::getUserId,
|
|
|
+ UserMembership::getSource,
|
|
|
+ (a, b) -> a));
|
|
|
+
|
|
|
+ List<MembershipUserResponse> list = result.getRecords().stream().map(u -> {
|
|
|
+ MembershipLevel currentLevel = u.getMembershipLevel() != null
|
|
|
+ ? u.getMembershipLevel() : MembershipLevel.PLUS;
|
|
|
+ String levelCode = currentLevel.getCode();
|
|
|
+ boolean isPlus = currentLevel == MembershipLevel.PLUS;
|
|
|
+ LocalDateTime expireAt = isPlus ? null : u.getMembershipExpireAt();
|
|
|
+ int daysRemaining;
|
|
|
+ if (isPlus) {
|
|
|
+ daysRemaining = -1;
|
|
|
+ } else if (expireAt != null && expireAt.isAfter(LocalDateTime.now())) {
|
|
|
+ daysRemaining = (int) ChronoUnit.DAYS.between(LocalDateTime.now(), expireAt);
|
|
|
+ } else {
|
|
|
+ daysRemaining = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return MembershipUserResponse.builder()
|
|
|
+ .userId(u.getId())
|
|
|
+ .phone(u.getPhone())
|
|
|
+ .nickname(u.getNickname())
|
|
|
+ .wechatNickname(u.getWechatNickname())
|
|
|
+ .level(levelCode)
|
|
|
+ .levelName(currentLevel.getDescription())
|
|
|
+ .source(isPlus ? "SYSTEM" : sourceMap.getOrDefault(u.getId(), ""))
|
|
|
+ .expireAt(expireAt)
|
|
|
+ .daysRemaining(daysRemaining)
|
|
|
+ .createTime(u.getCreateTime())
|
|
|
+ .build();
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+
|
|
|
+ Page<MembershipUserResponse> responsePage = new Page<>(pageNum, pageSize, result.getTotal());
|
|
|
+ responsePage.setRecords(list);
|
|
|
+ return responsePage;
|
|
|
+ }
|
|
|
+
|
|
|
private MembershipResponse toResponse(UserMembership membership) {
|
|
|
if (membership == null) {
|
|
|
return null;
|
|
|
@@ -402,6 +468,7 @@ public class MembershipService {
|
|
|
.membershipExpireAt(membership.getEffectiveTo())
|
|
|
.status(membership.getStatus())
|
|
|
.remark(membership.getRemark())
|
|
|
+ .wechatNickname(user != null ? user.getWechatNickname() : null)
|
|
|
.createTime(membership.getCreateTime())
|
|
|
.build();
|
|
|
}
|