34 lines
1.3 KiB
Python
34 lines
1.3 KiB
Python
"""Short emails about reopen requests, sent through the configured account when email is on.
|
|
|
|
Best effort: a failure is written to the mail log and never blocks the action itself.
|
|
"""
|
|
from sqlalchemy import select
|
|
from sqlalchemy.orm import Session
|
|
|
|
from . import mailer
|
|
from .models import BudgetYear, MailSettings, User
|
|
|
|
|
|
def _ready(db: Session) -> MailSettings | None:
|
|
cfg = db.get(MailSettings, 1)
|
|
return cfg if cfg and mailer.is_ready(cfg) else None
|
|
|
|
|
|
def reopeners(db: Session, budget: BudgetYear) -> list[User]:
|
|
"""Who can reopen the budget: administrators and the department's approvers."""
|
|
users = db.scalars(select(User).where(User.active)).all()
|
|
return [u for u in users if u.role == "admin" or (u.role == "approver" and u.department_id == budget.department_id)]
|
|
|
|
|
|
def send(db: Session, actor: User, budget: BudgetYear, to: list[User], subject: str, body: str) -> None:
|
|
cfg = _ready(db)
|
|
addresses = sorted({u.email for u in to if u.email and u.id != actor.id})
|
|
if not cfg or not addresses:
|
|
return
|
|
try:
|
|
addresses = mailer.clean_addresses(addresses)
|
|
except mailer.MailError:
|
|
return
|
|
mailer.send(db, actor, cfg, to=addresses, cc=[], subject=subject, body=body, attachments=[], kind="notice",
|
|
year_id=budget.id, context=f"{budget.department.name} {budget.year}")
|