"""日结模块统计服务函数""" import logging from datetime import datetime, date from django.db.models import Q, Sum, Case, When, Value, CharField, IntegerField from django.db.models.functions import Concat from printing.models import PlateOrder logger = logging.getLogger(__name__) def get_plate_order_summary_by_customer( merchant_id: int, settlement_date: date, user=None ) -> list[dict]: """ 获取按客户分组的开版订单统计 Args: merchant_id: 商户ID settlement_date: 统计日期 user: 当前用户(用于客户可见性过滤) Returns: list[dict]: 客户统计列表 """ logger.info( f'[settlement.services] 获取开版订单统计: ' f'merchant_id={merchant_id}, date={settlement_date}' ) settlement_date = _validate_and_normalize_summary_args( merchant_id=merchant_id, settlement_date=settlement_date, ) queryset = _get_plate_order_queryset(merchant_id, user) aggregated_data = _aggregate_plate_orders_by_customer_and_type( queryset, settlement_date ) return _format_plate_order_summary(aggregated_data) def _validate_and_normalize_summary_args( merchant_id: int, settlement_date: date, ) -> date: """校验并标准化统计参数。""" if not isinstance(merchant_id, int) or merchant_id <= 0: raise ValueError('merchant_id 必须为正整数') if isinstance(settlement_date, datetime): settlement_date = settlement_date.date() if not isinstance(settlement_date, date): raise ValueError('settlement_date 必须为 date 或 datetime 类型') return settlement_date def _get_plate_order_queryset(merchant_id: int, user=None): """ 获取开版订单的基础查询集 Args: merchant_id: 商户ID user: 当前用户(用于客户可见性过滤) Returns: QuerySet[PlateOrder]: 过滤后的查询集 """ queryset = PlateOrder.objects.filter( merchant_id=merchant_id, plate_type__isnull=False, production_method__isnull=False ).select_related('customer') if user and not user.is_superuser: emp = getattr(user, 'employee', None) if emp: visible_customer_filter = ( Q(customer__created_by=emp) | Q(customer__visible_employees=emp) ) no_customer_filter = Q(customer__isnull=True) queryset = queryset.filter( visible_customer_filter | no_customer_filter ).distinct() return queryset def _get_month_date_range(settlement_date: date) -> tuple[date, date]: """ 获取从月初到指定日期的日期范围 Args: settlement_date: 统计日期 Returns: tuple[date, date]: (月初日期, 统计日期) """ month_start = settlement_date.replace(day=1) return month_start, settlement_date def _aggregate_plate_orders_by_customer_and_type(queryset, settlement_date: date): """ 按客户和类型分组聚合订单数据 Args: queryset: 基础查询集 settlement_date: 统计日期 Returns: QuerySet[PlateOrder]: 添加了聚合标注的查询集 """ month_start, _ = _get_month_date_range(settlement_date) queryset = queryset.annotate( type=Concat( 'plate_type', Value('-'), 'production_method', output_field=CharField() ) ).values( 'customer__id', 'customer__name', 'type' ).annotate( today=Sum( Case( When( plate_date__date=settlement_date, then=1 ), default=0, output_field=IntegerField() ) ), current_month=Sum( Case( When( plate_date__date__gte=month_start, plate_date__date__lte=settlement_date, then=1 ), default=0, output_field=IntegerField() ) ) ).order_by('customer__name', 'customer__id', 'type') return queryset def _format_plate_order_summary(aggregated_data): """ 格式化聚合结果为 API 返回格式 Args: aggregated_data: 聚合后的查询集 Returns: list[dict]: 格式化后的数据 """ result = {} for item in aggregated_data: client_id = item['customer__id'] client_name = item['customer__name'] client_key = (client_id, client_name) if client_key not in result: result[client_key] = { 'client_id': client_id, 'client_name': client_name, 'plate_order_count': [] } plate_order_count = { 'type': item['type'], 'today': item['today'], 'current_month': item['current_month'] } result[client_key]['plate_order_count'].append(plate_order_count) for client_key in result: result[client_key]['plate_order_count'] = _filter_zero_data( result[client_key]['plate_order_count'] ) return [v for k, v in result.items() if v['plate_order_count']] def _filter_zero_data(plate_order_counts): """ 过滤全0数据 Args: plate_order_counts: 订单统计列表 Returns: list[dict]: 过滤后的列表 """ return [ item for item in plate_order_counts if item['today'] > 0 or item['current_month'] > 0 ] def calculate_plate_order_daily_summary( merchant_id: int, settlement_date: datetime.date ) -> dict: """ 计算开版订单日结汇总(空壳实现) Args: merchant_id: 商户ID settlement_date: 结算日期 Returns: dict: 统计结果(空壳) """ logger.info( f'[settlement.services] 计算开版订单日结汇总: ' f'merchant_id={merchant_id}, date={settlement_date}' ) return { 'merchant_id': merchant_id, 'settlement_date': str(settlement_date), 'total_orders': 0, 'completed_orders': 0, 'in_progress_orders': 0, } def calculate_printing_order_daily_summary( merchant_id: int, settlement_date: datetime.date ) -> dict: """ 计算生产订单日结汇总(空壳实现) Args: merchant_id: 商户ID settlement_date: 结算日期 Returns: dict: 统计结果(空壳) """ logger.info( f'[settlement.services] 计算生产订单日结汇总: ' f'merchant_id={merchant_id}, date={settlement_date}' ) return { 'merchant_id': merchant_id, 'settlement_date': str(settlement_date), 'total_orders': 0, 'completed_orders': 0, 'in_progress_orders': 0, }