Files
Django/jituan/services/club_context.py

135 lines
4.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""俱乐部上下文解析与查询辅助。"""
from jituan.constants import (
CLUB_ID_DEFAULT,
CLUB_HEADER,
CLUB_SCOPE_HEADER,
DATA_SCOPE_ALL,
DATA_SCOPE_SINGLE,
)
from jituan.models import Club
def resolve_club_id_from_request(request):
"""
从请求解析 club_id。
优先级:已注入的 request.club_id > Header X-Club-Id > 默认 xq。
旧客户端不传时恒为 xq与现网行为一致。
"""
injected = getattr(request, 'club_id', None)
if injected:
return injected
header = request.META.get(f'HTTP_{CLUB_HEADER.upper().replace("-", "_")}', '')
if not header:
header = request.headers.get(CLUB_HEADER, '') if hasattr(request, 'headers') else ''
club_id = (header or '').strip() or CLUB_ID_DEFAULT
return club_id
def resolve_club_scope(request):
"""解析数据范围ALL_CLUBS集团汇总或 SINGLE_CLUB。"""
scope = getattr(request, 'club_scope', None)
if scope:
return scope
header = request.META.get(f'HTTP_{CLUB_SCOPE_HEADER.upper().replace("-", "_")}', '')
if not header:
header = request.headers.get(CLUB_SCOPE_HEADER, '') if hasattr(request, 'headers') else ''
if (header or '').strip().lower() == 'all':
return DATA_SCOPE_ALL
return DATA_SCOPE_SINGLE
def get_active_club(club_id):
try:
club = Club.query.get(club_id=club_id, status=1)
return club
except Club.DoesNotExist:
return None
def filter_club_char_field(qs, request, field='club_id'):
"""按 club_id 字符字段过滤xq 视图兼容历史空值。"""
scope = resolve_club_scope(request)
if scope == DATA_SCOPE_ALL:
return qs
if not hasattr(qs, 'filter'):
return qs
club_id = resolve_club_id_from_request(request)
if club_id == CLUB_ID_DEFAULT:
from django.db.models import Q
return qs.filter(
Q(**{field: club_id}) | Q(**{f'{field}__isnull': True}) | Q(**{field: ''})
)
return qs.filter(**{field: club_id})
def filter_queryset_by_club(qs, request, club_field='club_id'):
"""
按请求上下文过滤 QuerySet / FluentQuery。
集团 ALL_CLUBS 视图不过滤;子公司 SINGLE_CLUB 按 club_id 过滤。
历史订单 ClubID 为空时视为 xq避免列表被滤空。
"""
scope = resolve_club_scope(request)
club_id = resolve_club_id_from_request(request)
if scope == DATA_SCOPE_ALL:
return qs
if not hasattr(qs, 'filter'):
return qs
if club_field == 'ClubID' and club_id == CLUB_ID_DEFAULT:
from django.db.models import Q
return qs.filter(
Q(ClubID=club_id) | Q(ClubID__isnull=True) | Q(ClubID='')
)
return qs.filter(**{club_field: club_id})
def club_id_for_write(request):
"""写入业务流水时使用的 club_id集团汇总视图写入仍须指定目标 club"""
return resolve_club_id_from_request(request)
def orders_for_request(request):
"""按俱乐部过滤的订单 QuerySet。"""
from orders.models import Order
return filter_queryset_by_club(Order.query.all(), request, club_field='ClubID')
def paginate_fluent_query(fluent_qs, page, page_size):
"""
FluentQuery 分页。直接切片底层 Django QuerySet绕过 FluentQuery 缓存。
返回 (total, items)。
"""
page = max(1, int(page))
page_size = max(1, min(int(page_size), 100))
django_qs = fluent_qs._qs
total = django_qs.count()
start = (page - 1) * page_size
return total, list(django_qs[start:start + page_size])
def platform_order_base_q():
"""平台订单:发单平台=1兼容历史 Platform 为空。"""
from django.db.models import Q
return Q(Platform=1) | Q(Platform__isnull=True)
def merchant_order_base_q():
"""商家订单:发单平台=2。"""
from django.db.models import Q
return Q(Platform=2)
def filter_user_related_by_club(qs, request, user_club_path='user__ClubID'):
"""按 User.ClubID 过滤打手/管事/商家等关联查询。"""
scope = resolve_club_scope(request)
if scope == DATA_SCOPE_ALL:
return qs
return qs.filter(**{user_club_path: resolve_club_id_from_request(request)})
def filter_user_qs_by_club(qs, request):
"""直接过滤 User 查询集(字段 ClubID"""
scope = resolve_club_scope(request)
if scope == DATA_SCOPE_ALL:
return qs
return qs.filter(ClubID=resolve_club_id_from_request(request))