1
0
forked from erp-dev/erp
Files
erpnew/settlement/services.py

269 lines
7.0 KiB
Python

"""日结模块统计服务函数"""
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,
}