"""总会员(包含式会员):购买一个会员,可接多个子会员类型订单。""" from products.models import Huiyuan, Huiyuangoumai def get_bundle_included_ids(club_id, bundle_huiyuan_id): from jituan.models import ClubHuiyuanBundleInclude if not club_id or not bundle_huiyuan_id: return [] return list( ClubHuiyuanBundleInclude.query.filter( club_id=club_id, bundle_huiyuan_id=bundle_huiyuan_id, ).values_list('included_huiyuan_id', flat=True) ) def is_bundle_huiyuan(huiyuan_id): try: return bool(Huiyuan.query.get(huiyuan_id=huiyuan_id).is_bundle) except Huiyuan.DoesNotExist: return False def user_has_huiyuan_access(yonghu_id, required_huiyuan_id, club_id=None): """用户是否可接要求 required_huiyuan_id 的会员单(含总会员覆盖)。""" if not required_huiyuan_id: return True req = str(required_huiyuan_id).strip() def _record_valid(rec): return ( rec and not rec.jiance_shifou_daoqi() and rec.huiyuan_zhuangtai == 1 ) try: direct = Huiyuangoumai.query.get(yonghu_id=yonghu_id, huiyuan_id=req) if _record_valid(direct): return True except Huiyuangoumai.DoesNotExist: pass bundle_ids = set( Huiyuan.query.filter(is_bundle=True).values_list('huiyuan_id', flat=True) ) if not bundle_ids: return False for rec in Huiyuangoumai.query.filter(yonghu_id=yonghu_id, huiyuan_id__in=bundle_ids): if not _record_valid(rec): continue cid = club_id or rec.club_id or '' included = get_bundle_included_ids(cid, rec.huiyuan_id) if req in {str(x) for x in included}: return True return False def enrich_clumber_item(record): """为 clumber 条目附加总会员覆盖的子会员 ID 列表(旧端忽略该字段)。""" item = { 'huiyuanid': record.huiyuan_id, 'huiyuan_id': record.huiyuan_id, 'huiyuanming': record.jieshao or f'会员{record.huiyuan_id}', 'daoqi': record.daoqi_time, 'is_trial': bool(getattr(record, 'is_trial', False)), } if is_bundle_huiyuan(record.huiyuan_id): item['is_bundle'] = True item['included_huiyuan_ids'] = get_bundle_included_ids( record.club_id or '', record.huiyuan_id, ) return item def _append_bundle_sub_clumber(items, seen, record, base_item): """总会员有效时,为抢单页展开子会员虚拟条目。""" if not base_item.get('is_bundle'): return bundle_hid = str(record.huiyuan_id) for sub_id in base_item.get('included_huiyuan_ids') or []: sid = str(sub_id).strip() if not sid or sid in seen: continue seen.add(sid) items.append({ 'huiyuanid': sid, 'huiyuan_id': sid, 'huiyuanming': base_item.get('huiyuanming', ''), 'daoqi': base_item.get('daoqi'), 'from_bundle': bundle_hid, 'is_trial': bool(getattr(record, 'is_trial', False)), }) def build_user_clumber(yonghu_id): """ 构建抢单页可用的 clumber 列表。 - 仅包含未过期且状态有效的会员(含体验会员) - 总会员自动展开所覆盖的子会员 ID - 同时返回 huiyuanid / huiyuan_id,兼容小程序各页面字段名 """ items = [] seen = set() for record in Huiyuangoumai.query.filter(yonghu_id=yonghu_id): if record.jiance_shifou_daoqi(): continue if record.huiyuan_zhuangtai != 1: continue base = enrich_clumber_item(record) hid = str(record.huiyuan_id) if hid not in seen: seen.add(hid) items.append(base) _append_bundle_sub_clumber(items, seen, record, base) return items def build_auth_clumber(yonghu_id): """登录/注册返回的 clumber:保留状态字段,并补齐抢单页所需的 huiyuanid。""" items = [] seen = set() for record in Huiyuangoumai.query.filter(yonghu_id=yonghu_id): shifou_daoqi = record.jiance_shifou_daoqi() base = enrich_clumber_item(record) base.update({ 'huiyuan_zhuangtai': record.huiyuan_zhuangtai, 'daoqi_time': record.daoqi_time.isoformat() if record.daoqi_time else None, 'shifou_daoqi': shifou_daoqi, 'jieshao': record.jieshao, }) hid = str(record.huiyuan_id) if hid not in seen: seen.add(hid) items.append(base) if not shifou_daoqi and record.huiyuan_zhuangtai == 1: _append_bundle_sub_clumber(items, seen, record, base) return items def save_bundle_includes(club_id, bundle_huiyuan_id, included_ids): """保存俱乐部总会员包含的子会员(须为本俱乐部已上架的普通会员)。""" from jituan.models import ClubHuiyuanBundleInclude, ClubHuiyuanPrice if not is_bundle_huiyuan(bundle_huiyuan_id): return None, '该会员不是总会员类型' enabled = set( ClubHuiyuanPrice.query.filter(club_id=club_id, is_enabled=True).values_list( 'huiyuan_id', flat=True, ) ) bundle_ids = set( Huiyuan.query.filter(is_bundle=True).values_list('huiyuan_id', flat=True) ) cleaned = [] for hid in included_ids or []: hid = str(hid).strip() if not hid or hid == bundle_huiyuan_id: continue if hid not in enabled: return None, f'子会员 {hid} 未在本俱乐部上架' if hid in bundle_ids: return None, '总会员不能包含另一个总会员' if not Huiyuan.query.filter(huiyuan_id=hid).exists(): return None, f'子会员 {hid} 不存在' cleaned.append(hid) if not cleaned: return None, '请至少选择一个包含的子会员' ClubHuiyuanBundleInclude.query.filter( club_id=club_id, bundle_huiyuan_id=bundle_huiyuan_id, ).delete() for hid in cleaned: ClubHuiyuanBundleInclude.query.create( club_id=club_id, bundle_huiyuan_id=bundle_huiyuan_id, included_huiyuan_id=hid, ) return {'included_huiyuan_ids': cleaned}, None