fix: 加固会员回滚命令,有未过期充值单绝不收回

增加 repair 指纹校验;减会员后重新付费不再误收。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-08 16:20:33 +08:00
parent 7c3f04e7f3
commit c464c31140
3 changed files with 347 additions and 39 deletions

View File

@@ -673,6 +673,77 @@ def user_has_active_czjilu_entitlement(yonghu_id, huiyuan_id, club_id=None):
return False
def _paid_member_orders_for(yonghu_id, huiyuan_id):
from jituan.services.huiyuan_bundle import huiyuan_ids_match
return [
o for o in Czjilu.query.filter(
yonghuid=yonghu_id,
leixing=MEMBER_LEIXING,
zhuangtai=MEMBER_PAID_STATUS,
)
if huiyuan_ids_match(o.huiyuan_id, huiyuan_id)
]
def order_purchase_days_locked(order, club_id=None):
"""充值单锁定的有效天数(与履约/repair 同源)。"""
cid = getattr(order, 'club_id', None) or club_id or CLUB_ID_DEFAULT
is_trial = _order_is_trial_like(order, cid)
days = int(getattr(order, 'purchase_days', None) or 0)
if days <= 0:
_, _, days = club_huiyuan_sellable(cid, order.huiyuan_id, is_trial=is_trial)
return max(int(days or 0), 1)
def is_suspected_bug_repair_restore(rec, since=None):
"""
Bug repair 指纹UpdateTime 时将 daoqi 设为 UpdateTime+days
且存在匹配充值单的原定期限在 UpdateTime 之前已结束。
正常续费:必有未过期充值单支撑,或 daoqi 与充值单原定期限一致。
"""
from jituan.services.huiyuan_bundle import _normalize_datetime_for_compare
updated = _normalize_datetime_for_compare(rec.UpdateTime)
if since and updated < _normalize_datetime_for_compare(since):
return None
daoqi = _normalize_datetime_for_compare(rec.daoqi_time)
gap_days = (daoqi - updated).days
if gap_days < 1 or gap_days > 400:
return None
for order in _paid_member_orders_for(rec.yonghu_id, rec.huiyuan_id):
if _czjilu_entitlement_revoked(order):
continue
days = order_purchase_days_locked(order, rec.club_id)
if abs(days - gap_days) > 2:
continue
if _czjilu_entitlement_end(order, rec.club_id) < updated:
return order.dingdan_id
return None
def should_rollback_erroneous_membership(rec, since=None, require_repair_signature=True):
"""
是否应收回错误恢复的会员(保守策略,优先不误伤正常付费用户)。
硬性豁免:任意未过期已付充值单支撑 → 绝不收回。
"""
if rec.jiance_shifou_daoqi() or rec.huiyuan_zhuangtai != 1:
return False, None
if user_has_active_czjilu_entitlement(rec.yonghu_id, rec.huiyuan_id, rec.club_id):
return False, '有未过期充值单支撑'
orders = _paid_member_orders_for(rec.yonghu_id, rec.huiyuan_id)
if not orders:
return False, '无充值单不自动处理'
if require_repair_signature:
dingdan_id = is_suspected_bug_repair_restore(rec, since=since)
if not dingdan_id:
return False, '不符合 bug repair 指纹'
return True, dingdan_id
return True, None
def expire_huiyuangoumai_record(rec, reason=''):
"""将会员记录置为已过期(不删行,便于审计)。"""
from jituan.services.huiyuan_bundle import _normalize_datetime_for_compare