import logging from rq import get_current_job logger = logging.getLogger(__name__) def send_event_invitations(event_id, initiated_by_id=None): from app import create_app app = create_app() with app.app_context(): return send_event_invitations_in_context(event_id, initiated_by_id) def send_event_invitations_in_context(event_id, initiated_by_id=None): from app import db from app.models import AuditLog, Event, Guest, User from app.services.email_service import send_invitation from app.services.qr_service import generate_qr_for_guest event = db.session.get(Event, event_id) if not event: raise RuntimeError(f"Мероприятие {event_id} не найдено") guests = Guest.query.filter_by(event_id=event.id, is_active=True, invitation_sent=False).order_by(Guest.id).all() total = len(guests) sent = failed = 0 job = get_current_job() for processed, guest in enumerate(guests, start=1): if not guest.qr_filename: generate_qr_for_guest(guest) try: send_invitation(guest) sent += 1 except Exception as exc: failed += 1 logger.warning("Invitation delivery failed for guest %s: %s", guest.id, exc) db.session.commit() if job: job.meta.update({"event_id": event.id, "total": total, "processed": processed, "sent": sent, "failed": failed}) job.save_meta() initiator = db.session.get(User, initiated_by_id) if initiated_by_id else None db.session.add(AuditLog( user_id=initiator.id if initiator else None, username=initiator.username if initiator else "system", action="event_send_invitations", target_type="event", target_id=str(event.id), details=f"Фоновая рассылка завершена: отправлено {sent}, ошибок {failed}", )) db.session.commit() return {"event_id": event.id, "total": total, "sent": sent, "failed": failed}