fix: 迁移子会员时长按总会员有效覆盖累加,避免少加天数

EOF

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-29 04:46:29 +08:00
parent 07ae350d55
commit da62ea8be9

View File

@@ -593,8 +593,74 @@ def _find_user_huiyuangoumai(uid: str, huiyuan_id: str, *, for_update: bool = Fa
return qs.first()
def _latest_effective_cover_until(uid: str, huiyuan_id: str, club_id: str, *, goumai_row=None):
"""
目标店对该会员类型的有效覆盖到期:
- 自己开通的该子会员/总会员未到期
- 或任意未到期总会员包含该子会员
用于迁移累加:总会员覆盖剩 10 天 + 迁入同子会员 10 天 → 子会员落到 20 天。
"""
from jituan.services.huiyuan_bundle import (
_included_huiyuan_id_set,
_membership_record_active,
expand_huiyuan_id_variants,
huiyuan_ids_match,
is_bundle_huiyuan,
normalize_huiyuan_id,
resolve_bundle_included_ids,
)
from products.models import Huiyuangoumai
now = _now_aware()
hid = normalize_huiyuan_id(huiyuan_id)
if not hid:
return None
req_set = {hid, hid.lstrip('0') or '0'}
for vid in expand_huiyuan_id_variants(hid):
req_set.add(vid)
req_set.add(vid.lstrip('0') or '0')
latest = None
def bump(dt):
nonlocal latest
exp = _aware(dt)
if not exp or exp <= now:
return
if latest is None or exp > latest:
latest = exp
row = goumai_row
if row is None:
row = _find_user_huiyuangoumai(uid, hid)
if row is not None and int(row.huiyuan_zhuangtai or 0) == 1:
bump(row.daoqi_time)
for rec in Huiyuangoumai.query.filter(yonghu_id=str(uid)):
if not _membership_record_active(rec):
continue
if huiyuan_ids_match(rec.huiyuan_id, hid):
bump(rec.daoqi_time)
continue
if not is_bundle_huiyuan(rec.huiyuan_id):
continue
included = resolve_bundle_included_ids(
rec.huiyuan_id,
club_id=club_id,
yonghu_id=uid,
record_club_id=getattr(rec, 'club_id', None),
)
if req_set & _included_huiyuan_id_set(included):
bump(rec.daoqi_time)
return latest
def _add_huiyuan_duration(*, to_uid: str, to_club: str, huiyuan_id: str, remain, jieshao: str, is_trial: bool, has_used_trial: bool):
"""给目标用户对应会员加时长(已有则累加剩余,否则从现在起算)。"""
"""给目标用户对应会员加时长
累加基数 = max(现在, 该会员自身到期, 覆盖它的总会员到期)。
避免:目标已有总会员覆盖子会员 10 天,迁入同子会员 10 天却只得到约 10 天(应为 20
"""
from products.models import Huiyuangoumai
now = _now_aware()
@@ -611,9 +677,12 @@ def _add_huiyuan_duration(*, to_uid: str, to_club: str, huiyuan_id: str, remain,
'zhuangtai': dst.huiyuan_zhuangtai,
'club_id': dst.club_id,
}
dst_exp = _aware(dst.daoqi_time)
base = dst_exp if (dst_exp and dst_exp > now and int(dst.huiyuan_zhuangtai or 0) == 1) else now
cover = _latest_effective_cover_until(to_uid, hid, to_club, goumai_row=dst)
base = cover if (cover and cover > now) else now
exp = base + remain
if dst:
dst.daoqi_time = exp
dst.huiyuan_zhuangtai = 1
dst.club_id = to_club
@@ -622,7 +691,6 @@ def _add_huiyuan_duration(*, to_uid: str, to_club: str, huiyuan_id: str, remain,
dst.save(update_fields=['daoqi_time', 'huiyuan_zhuangtai', 'club_id', 'jieshao', 'UpdateTime'])
return exp, before_dst
exp = now + remain
try:
Huiyuangoumai.query.create(
huiyuan_id=hid,
@@ -644,9 +712,9 @@ def _add_huiyuan_duration(*, to_uid: str, to_club: str, huiyuan_id: str, remain,
'zhuangtai': dst2.huiyuan_zhuangtai,
'club_id': dst2.club_id,
}
dst_exp = _aware(dst2.daoqi_time)
base = dst_exp if (dst_exp and dst_exp > now and int(dst2.huiyuan_zhuangtai or 0) == 1) else now
exp = base + remain
cover2 = _latest_effective_cover_until(to_uid, hid, to_club, goumai_row=dst2)
base2 = cover2 if (cover2 and cover2 > now) else now
exp = base2 + remain
dst2.daoqi_time = exp
dst2.huiyuan_zhuangtai = 1
dst2.club_id = to_club