forked from erp-dev/erp
feat: new module for daily settlement
This commit is contained in:
140
settlement/tasks.py
Normal file
140
settlement/tasks.py
Normal file
@@ -0,0 +1,140 @@
|
||||
"""日结模块 Celery 任务"""
|
||||
import logging
|
||||
import datetime
|
||||
|
||||
from celery import shared_task
|
||||
from django.utils import timezone
|
||||
|
||||
from .models import DailySettlementConfig, SettlementModuleEnum
|
||||
from .services import (
|
||||
calculate_plate_order_daily_summary,
|
||||
calculate_printing_order_daily_summary,
|
||||
)
|
||||
from .signals import daily_settlement_completed
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@shared_task(bind=True)
|
||||
def run_daily_settlement(self):
|
||||
"""
|
||||
执行所有商户的日结任务(固定时间触发)
|
||||
|
||||
在 settings.py 中配置的固定时间触发,
|
||||
拉取所有配置了统计模块的商户,逐个执行日结。
|
||||
"""
|
||||
from basic_info.models import Merchant
|
||||
|
||||
# 获取所有配置了统计模块的商户
|
||||
configs = DailySettlementConfig.objects.filter(
|
||||
settlement_modules__len__gt=0
|
||||
).select_related('merchant')
|
||||
|
||||
logger.info(
|
||||
f'[settlement.tasks] 开始执行日结,共 {configs.count()} 个商户需要统计'
|
||||
)
|
||||
|
||||
# 为每个商户触发日结任务
|
||||
for config in configs:
|
||||
settlement_date = timezone.localdate() - datetime.timedelta(days=1)
|
||||
run_merchant_daily_settlement.delay(
|
||||
merchant_id=config.merchant.id,
|
||||
settlement_date=str(settlement_date)
|
||||
)
|
||||
|
||||
return {
|
||||
'task_id': self.request.id,
|
||||
'total_merchants': configs.count(),
|
||||
'settlement_date': str(timezone.localdate() - datetime.timedelta(days=1)),
|
||||
}
|
||||
|
||||
|
||||
@shared_task(bind=True)
|
||||
def run_merchant_daily_settlement(
|
||||
self,
|
||||
merchant_id: int,
|
||||
settlement_date: str | None = None
|
||||
):
|
||||
"""
|
||||
执行单个商户的日结
|
||||
|
||||
Args:
|
||||
merchant_id: 商户ID
|
||||
settlement_date: 结算日期(YYYY-MM-DD),默认为昨天
|
||||
|
||||
Returns:
|
||||
dict: 包含 task_id 和执行结果的 payload
|
||||
"""
|
||||
from basic_info.models import Merchant
|
||||
|
||||
# 解析日期
|
||||
if settlement_date:
|
||||
date_obj = datetime.datetime.strptime(settlement_date, '%Y-%m-%d').date()
|
||||
else:
|
||||
date_obj = timezone.localdate() - datetime.timedelta(days=1)
|
||||
|
||||
merchant = Merchant.objects.get(id=merchant_id)
|
||||
config = merchant.settlement_config
|
||||
|
||||
modules = config.settlement_modules
|
||||
summaries = {}
|
||||
errors = {}
|
||||
overall_status = 'success'
|
||||
|
||||
logger.info(
|
||||
f'[settlement.tasks] 开始执行商户 {merchant_id} 的日结,'
|
||||
f'日期={date_obj}, 模块={modules}'
|
||||
)
|
||||
|
||||
# 执行各模块的统计
|
||||
for module in modules:
|
||||
try:
|
||||
if module == SettlementModuleEnum.PLATE_ORDER:
|
||||
summary = calculate_plate_order_daily_summary(
|
||||
merchant_id=merchant_id,
|
||||
settlement_date=date_obj
|
||||
)
|
||||
summaries['plate_order'] = summary
|
||||
|
||||
elif module == SettlementModuleEnum.PRINTING_ORDER:
|
||||
summary = calculate_printing_order_daily_summary(
|
||||
merchant_id=merchant_id,
|
||||
settlement_date=date_obj
|
||||
)
|
||||
summaries['printing_order'] = summary
|
||||
|
||||
except Exception as e:
|
||||
logger.exception(
|
||||
f'[settlement.tasks] 商户 {merchant_id} 的 {module} 统计失败: {e}'
|
||||
)
|
||||
errors[module] = str(e)
|
||||
overall_status = 'partial'
|
||||
|
||||
# 如果所有模块都失败
|
||||
if len(errors) == len(modules):
|
||||
overall_status = 'failed'
|
||||
|
||||
# 发送信号(不包含统计结果详情)
|
||||
daily_settlement_completed.send(
|
||||
sender=run_merchant_daily_settlement,
|
||||
merchant=merchant,
|
||||
settlement_date=date_obj,
|
||||
status=overall_status,
|
||||
modules=modules,
|
||||
errors=errors,
|
||||
task_id=self.request.id
|
||||
)
|
||||
|
||||
payload = {
|
||||
'task_id': self.request.id,
|
||||
'merchant_id': merchant_id,
|
||||
'settlement_date': str(date_obj),
|
||||
'status': overall_status,
|
||||
'modules': modules,
|
||||
'errors': errors,
|
||||
}
|
||||
|
||||
logger.info(
|
||||
f'[settlement.tasks] 商户 {merchant_id} 日结完成: {payload}'
|
||||
)
|
||||
return payload
|
||||
Reference in New Issue
Block a user