169 lines
5.4 KiB
Python
169 lines
5.4 KiB
Python
"""俱乐部上下文解析与查询辅助。"""
|
||
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 order_scope_qs(request=None):
|
||
"""
|
||
订单列表作用域 QuerySet。
|
||
request 为 None 时不按俱乐部过滤(旧 /yonghu 订单列表,与改造前一致)。
|
||
"""
|
||
from orders.models import Order
|
||
qs = Order.query.all()
|
||
if request is not None:
|
||
qs = filter_queryset_by_club(qs, request, club_field='ClubID')
|
||
return qs
|
||
|
||
|
||
def count_order_status_buckets(q_conditions, request=None):
|
||
"""
|
||
统计各状态订单数。
|
||
每次从全新 FluentQuery 起链,避免 FluentQuery.filter 原地累积导致列表被滤空。
|
||
"""
|
||
from django.db.models import Q
|
||
|
||
buckets = (
|
||
('1,7', Q(Status__in=[1, 7])),
|
||
('2', Q(Status=2)),
|
||
('8', Q(Status=8)),
|
||
('3', Q(Status=3)),
|
||
('4', Q(Status=4)),
|
||
('5', Q(Status=5)),
|
||
('6', Q(Status=6)),
|
||
)
|
||
counts = {'all': order_scope_qs(request).filter(q_conditions).count()}
|
||
for key, status_q in buckets:
|
||
counts[key] = order_scope_qs(request).filter(q_conditions & status_q).count()
|
||
return counts
|
||
|
||
|
||
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))
|