142 lines
4.2 KiB
Python
142 lines
4.2 KiB
Python
from celery import shared_task
|
||
from django.utils import timezone
|
||
from datetime import timedelta
|
||
from django.core.mail import EmailMessage
|
||
from django.conf import settings
|
||
from django.shortcuts import render
|
||
import os
|
||
from loguru import logger
|
||
|
||
# WeasyPrint可用性标记,初始为None
|
||
WEASYPRINT_AVAILABLE = None
|
||
|
||
# 获取WeasyPrint可用性
|
||
def is_weasyprint_available():
|
||
"""检查WeasyPrint是否可用"""
|
||
global WEASYPRINT_AVAILABLE
|
||
if WEASYPRINT_AVAILABLE is None:
|
||
try:
|
||
from weasyprint import HTML
|
||
WEASYPRINT_AVAILABLE = True
|
||
except ImportError:
|
||
logger.warning("WeasyPrint库无法导入,PDF功能将不可用")
|
||
WEASYPRINT_AVAILABLE = False
|
||
return WEASYPRINT_AVAILABLE
|
||
|
||
from .models import (
|
||
ReadingRecord,
|
||
InsightRecord,
|
||
FamilyTask,
|
||
TodayPlan,
|
||
SystemConfig
|
||
)
|
||
|
||
@shared_task
|
||
def generate_daily_pdf_report():
|
||
"""生成每日PDF报告"""
|
||
logger.info("开始执行每日PDF报告生成任务")
|
||
|
||
# 检查WeasyPrint是否可用
|
||
if not is_weasyprint_available():
|
||
logger.error("WeasyPrint库不可用,无法生成PDF报告")
|
||
return False
|
||
|
||
today = timezone.now().date()
|
||
today_str = today.strftime('%Y-%m-%d')
|
||
|
||
# 生成报告数据
|
||
report_date = today
|
||
yesterday = report_date - timedelta(days=1)
|
||
|
||
# 获取昨日记录
|
||
yesterday_reading = ReadingRecord.objects.filter(date=yesterday)
|
||
yesterday_insight = InsightRecord.objects.filter(date=yesterday)
|
||
|
||
# 获取今日计划
|
||
today_plan = TodayPlan.objects.filter(date=report_date)
|
||
|
||
# 获取家庭事项统计
|
||
from django.db.models import Count
|
||
family_task_stats = FamilyTask.objects.values('type').annotate(count=Count('id'))
|
||
|
||
# 准备上下文
|
||
context = {
|
||
'today': report_date,
|
||
'yesterday': yesterday,
|
||
'yesterday_reading': yesterday_reading,
|
||
'yesterday_insight': yesterday_insight,
|
||
'today_plan': today_plan,
|
||
'family_task_stats': family_task_stats,
|
||
}
|
||
|
||
# 渲染HTML模板
|
||
html_string = render(None, 'core/report_pdf.html', context).content.decode('utf-8')
|
||
|
||
# 生成PDF报告
|
||
pdf_file = f"report_{today_str}.pdf"
|
||
pdf_path = os.path.join(settings.REPORTS_ROOT, pdf_file)
|
||
|
||
# 确保报告目录存在
|
||
os.makedirs(settings.REPORTS_ROOT, exist_ok=True)
|
||
|
||
# 生成PDF - 动态导入WeasyPrint
|
||
try:
|
||
from weasyprint import HTML
|
||
HTML(string=html_string).write_pdf(pdf_path)
|
||
logger.info(f"PDF报告生成成功: {pdf_path}")
|
||
return True
|
||
except Exception as e:
|
||
logger.error(f"PDF报告生成失败: {str(e)}")
|
||
return False
|
||
|
||
@shared_task
|
||
def send_daily_report():
|
||
"""发送每日报告"""
|
||
logger.info("开始执行每日报告发送任务")
|
||
|
||
# 先生成PDF报告
|
||
pdf_generated = generate_daily_pdf_report()
|
||
if not pdf_generated:
|
||
logger.error("PDF报告生成失败,无法发送邮件")
|
||
return False
|
||
|
||
today = timezone.now().date()
|
||
today_str = today.strftime('%Y-%m-%d')
|
||
|
||
# 获取系统配置
|
||
config = SystemConfig.get_config()
|
||
|
||
# 检查邮件配置是否完整
|
||
if not all([config.smtp_server, config.smtp_username, config.smtp_password, config.recipient_email]):
|
||
logger.error("邮件配置不完整,无法发送邮件")
|
||
return False
|
||
|
||
# 发送邮件
|
||
subject = f"家庭日报 - {today_str}"
|
||
message = f"这是您的家庭日报,日期:{today_str}"
|
||
from_email = config.smtp_username
|
||
recipient_list = [config.recipient_email]
|
||
|
||
# PDF文件路径
|
||
pdf_file = f"report_{today_str}.pdf"
|
||
pdf_path = os.path.join(settings.REPORTS_ROOT, pdf_file)
|
||
|
||
try:
|
||
email = EmailMessage(
|
||
subject=subject,
|
||
body=message,
|
||
from_email=from_email,
|
||
to=recipient_list,
|
||
)
|
||
|
||
# 添加附件
|
||
with open(pdf_path, 'rb') as f:
|
||
email.attach(pdf_file, f.read(), 'application/pdf')
|
||
|
||
# 发送邮件
|
||
email.send()
|
||
logger.info(f"邮件发送成功,收件人:{config.recipient_email}")
|
||
return True
|
||
except Exception as e:
|
||
logger.error(f"邮件发送失败:{str(e)}")
|
||
return False |