123 lines
3.7 KiB
Python
123 lines
3.7 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 send_daily_report():
|
|||
|
|
"""发送每日报告"""
|
|||
|
|
logger.info("开始执行每日报告发送任务")
|
|||
|
|
|
|||
|
|
# 检查WeasyPrint是否可用
|
|||
|
|
if not is_weasyprint_available():
|
|||
|
|
logger.error("WeasyPrint库不可用,无法生成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
|
|||
|
|
|
|||
|
|
# 生成报告数据
|
|||
|
|
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}")
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"PDF报告生成失败: {str(e)}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
# 发送邮件
|
|||
|
|
subject = f"家庭日报 - {today_str}"
|
|||
|
|
message = f"这是您的家庭日报,日期:{today_str}"
|
|||
|
|
from_email = config.smtp_username
|
|||
|
|
recipient_list = [config.recipient_email]
|
|||
|
|
|
|||
|
|
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
|