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