|
|
@@ -10,6 +10,7 @@ import com.etotem.cfc.mapper.*;
|
|
|
import com.etotem.cfc.dto.TaskReviewDTO;
|
|
|
import com.etotem.cfc.service.TaskService;
|
|
|
import com.etotem.cfc.service.UserService;
|
|
|
+import com.etotem.cfc.service.MembershipService;
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.TypeReference;
|
|
|
import javax.annotation.Resource;
|
|
|
@@ -87,6 +88,9 @@ public class AdminController {
|
|
|
@Resource
|
|
|
private LifetimeStatsMapper lifetimeStatsMapper;
|
|
|
|
|
|
+ @Resource
|
|
|
+ private MembershipService membershipService;
|
|
|
+
|
|
|
// 终身会员达标阈值(分)
|
|
|
private static final long LIFETIME_CONSUME_THRESHOLD = 100_000_000L; // 消费 ≥ 100万元
|
|
|
private static final long LIFETIME_SALES_THRESHOLD = 200_000_000L; // 销售 ≥ 200万元
|
|
|
@@ -1627,11 +1631,12 @@ public class AdminController {
|
|
|
}
|
|
|
String fromLevel = user.getMemberLevel() != null ? user.getMemberLevel() : "FREE";
|
|
|
|
|
|
- // 1. 升级用户为 LIFETIME(memberExpireTime=null 永久有效)
|
|
|
- user.setMemberLevel("LIFETIME");
|
|
|
- user.setMemberExpireTime(null);
|
|
|
- user.setUpdatedAt(new Date());
|
|
|
- userMapper.updateById(user);
|
|
|
+ // 1. 方案B:会员属于家庭 — 写入 family_memberships 事实源并同步全家 users 缓存。
|
|
|
+ // 原先只直写 users.member_level,导致读 family_memberships 的付费墙(如健康方案生成)误判 FREE。
|
|
|
+ // LIFETIME 以远期到期时间表示永久(getCurrentLevel 依赖 endDate 判定有效性)。
|
|
|
+ Long familyId = membershipService.getOrCreateUserFamilyId(targetUserId);
|
|
|
+ membershipService.setFamilyMembershipLevel(familyId, "LIFETIME", resolveGrantExpireTime("LIFETIME"),
|
|
|
+ "admin", "lifetime-grant:" + adminUserId);
|
|
|
|
|
|
// 2. 写入升级记录 upgradeType='lifetime'
|
|
|
MemberUpgradeRecord record = new MemberUpgradeRecord();
|
|
|
@@ -1650,6 +1655,16 @@ public class AdminController {
|
|
|
return Result.success();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 后台授予会员的目标到期时间:LIFETIME 用远期时间表示永久,其余等级默认 365 天(与支付/赠送默认一致)。
|
|
|
+ */
|
|
|
+ private Date resolveGrantExpireTime(String levelCode) {
|
|
|
+ if ("LIFETIME".equals(levelCode)) {
|
|
|
+ return java.sql.Timestamp.valueOf(java.time.LocalDateTime.of(2099, 12, 31, 23, 59, 59));
|
|
|
+ }
|
|
|
+ return new Date(System.currentTimeMillis() + 365L * 24 * 60 * 60 * 1000);
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 会员维护:按用户ID修改会员等级和推荐人
|
|
|
* body: { userId, memberLevel?, referrerId? }
|
|
|
@@ -1674,6 +1689,8 @@ public class AdminController {
|
|
|
StringBuilder changes = new StringBuilder();
|
|
|
String oldLevel = user.getMemberLevel() != null ? user.getMemberLevel() : "FREE";
|
|
|
String newLevel = null;
|
|
|
+ // 用户行仅剩「推荐人」「无家庭时的 FREE 回退」需要直写;会员等级统一走家庭维度(方案B)
|
|
|
+ boolean userRowChanged = false;
|
|
|
LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
|
|
|
wrapper.eq(User::getId, targetUserId);
|
|
|
|
|
|
@@ -1683,6 +1700,7 @@ public class AdminController {
|
|
|
if (user.getReferrerId() != null) {
|
|
|
wrapper.set(User::getReferrerId, null);
|
|
|
changes.append("清除推荐人; ");
|
|
|
+ userRowChanged = true;
|
|
|
}
|
|
|
} else {
|
|
|
try {
|
|
|
@@ -1692,6 +1710,7 @@ public class AdminController {
|
|
|
}
|
|
|
wrapper.set(User::getReferrerId, referrerId);
|
|
|
changes.append("推荐人=").append(referrerId).append("; ");
|
|
|
+ userRowChanged = true;
|
|
|
} catch (NumberFormatException e) {
|
|
|
return Result.error("推荐人ID格式不正确");
|
|
|
}
|
|
|
@@ -1715,47 +1734,76 @@ public class AdminController {
|
|
|
return Result.error("无效的会员等级: " + level);
|
|
|
}
|
|
|
newLevel = level;
|
|
|
- wrapper.set(User::getMemberLevel, newLevel);
|
|
|
- if ("LIFETIME".equals(newLevel)) {
|
|
|
- wrapper.set(User::getMemberExpireTime, null);
|
|
|
- }
|
|
|
if (!oldLevel.equals(newLevel)) {
|
|
|
changes.append("等级=").append(oldLevel).append("->").append(newLevel).append("; ");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (changes.length() > 0) {
|
|
|
+ // 会员等级变更:写入事实源 family_memberships 并同步全家 users 缓存(方案B:会员属于家庭)。
|
|
|
+ // 不再直写 users.member_level,否则读 family_memberships 的付费墙会误判 FREE(如 /api/health/plan/generate 报 4001)。
|
|
|
+ if (newLevel != null) {
|
|
|
+ Long targetFamilyId = user.getFamilyId();
|
|
|
+ if (!"FREE".equals(newLevel) && (targetFamilyId == null || targetFamilyId == 0L)) {
|
|
|
+ // 无家庭自动建家:会员以家庭为单位,无家庭无法承载会员权益
|
|
|
+ targetFamilyId = membershipService.getOrCreateUserFamilyId(targetUserId);
|
|
|
+ changes.append("已自动创建家庭id=").append(targetFamilyId).append("; ");
|
|
|
+ }
|
|
|
+ if ("FREE".equals(newLevel)) {
|
|
|
+ if (targetFamilyId != null && targetFamilyId != 0L) {
|
|
|
+ // 注意:家庭会员为全家共享,改用户为 FREE 会撤销整个家庭的会员并全家降级
|
|
|
+ String desc = membershipService.setFamilyMembershipLevel(
|
|
|
+ targetFamilyId, "FREE", null, "admin", "admin:" + adminUserId);
|
|
|
+ if (desc != null && !desc.isEmpty()) {
|
|
|
+ changes.append(desc).append("; ");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 无家庭:无可撤销的家庭会员,直接降级用户缓存(兼容旧行为)
|
|
|
+ wrapper.set(User::getMemberLevel, "FREE");
|
|
|
+ userRowChanged = true;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ String desc = membershipService.setFamilyMembershipLevel(
|
|
|
+ targetFamilyId, newLevel, resolveGrantExpireTime(newLevel),
|
|
|
+ "admin", "admin:" + adminUserId);
|
|
|
+ if (desc != null && !desc.isEmpty()) {
|
|
|
+ changes.append(desc).append("; ");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (userRowChanged) {
|
|
|
wrapper.set(User::getUpdatedAt, new Date());
|
|
|
userMapper.update(null, wrapper);
|
|
|
+ }
|
|
|
|
|
|
- if (newLevel != null && !oldLevel.equals(newLevel)) {
|
|
|
- MemberUpgradeRecord record = new MemberUpgradeRecord();
|
|
|
- record.setUserId(targetUserId);
|
|
|
- record.setFromLevel(oldLevel);
|
|
|
- record.setToLevel(newLevel);
|
|
|
- record.setUpgradeType("admin");
|
|
|
- record.setApproveUserId(adminUserId);
|
|
|
- record.setApproveStatus("approved");
|
|
|
- record.setApproveTime(new Date());
|
|
|
- record.setApproveRemark("管理员会员维护");
|
|
|
- record.setCreatedAt(new Date());
|
|
|
- memberUpgradeRecordMapper.insert(record);
|
|
|
-
|
|
|
- // 升级到付费等级(非 FREE)时自动发放 JOIN 赠券(幂等:family_coupon 唯一键防重)
|
|
|
- if (!"FREE".equals(newLevel)) {
|
|
|
- User changedUser = userMapper.selectById(targetUserId);
|
|
|
- if (changedUser != null && changedUser.getFamilyId() != null) {
|
|
|
- try {
|
|
|
- couponService.grantFamilyJoinCoupons(
|
|
|
- changedUser.getFamilyId(), newLevel,
|
|
|
- "admin:" + adminUserId);
|
|
|
- changes.append("发放").append(newLevel).append("JOIN券; ");
|
|
|
- } catch (Exception ex) {
|
|
|
- changes.append("发放").append(newLevel).append("JOIN券异常:").append(ex.getMessage()).append("; ");
|
|
|
- }
|
|
|
- } else {
|
|
|
- changes.append("升级").append(newLevel).append("(无家庭,跳过发券); ");
|
|
|
+ if (newLevel != null && !oldLevel.equals(newLevel)) {
|
|
|
+ MemberUpgradeRecord record = new MemberUpgradeRecord();
|
|
|
+ record.setUserId(targetUserId);
|
|
|
+ record.setFromLevel(oldLevel);
|
|
|
+ record.setToLevel(newLevel);
|
|
|
+ record.setUpgradeType("admin");
|
|
|
+ record.setApproveUserId(adminUserId);
|
|
|
+ record.setApproveStatus("approved");
|
|
|
+ record.setApproveTime(new Date());
|
|
|
+ record.setApproveRemark("管理员会员维护");
|
|
|
+ record.setCreatedAt(new Date());
|
|
|
+ memberUpgradeRecordMapper.insert(record);
|
|
|
+
|
|
|
+ // 升级到付费等级(非 FREE)时自动发放 JOIN 赠券(幂等:family_coupon 唯一键防重)
|
|
|
+ if (!"FREE".equals(newLevel)) {
|
|
|
+ User changedUser = userMapper.selectById(targetUserId);
|
|
|
+ Long changedFamilyId = changedUser != null ? changedUser.getFamilyId() : null;
|
|
|
+ if (changedFamilyId != null && changedFamilyId != 0L) {
|
|
|
+ try {
|
|
|
+ couponService.grantFamilyJoinCoupons(
|
|
|
+ changedFamilyId, newLevel,
|
|
|
+ "admin:" + adminUserId);
|
|
|
+ changes.append("发放").append(newLevel).append("JOIN券; ");
|
|
|
+ } catch (Exception ex) {
|
|
|
+ changes.append("发放").append(newLevel).append("JOIN券异常:").append(ex.getMessage()).append("; ");
|
|
|
}
|
|
|
+ } else {
|
|
|
+ changes.append("升级").append(newLevel).append("(无家庭,跳过发券); ");
|
|
|
}
|
|
|
}
|
|
|
}
|