Files
saldo/app/services/notification_service.py
2026-04-21 21:17:36 +02:00

65 lines
2.8 KiB
Python

from __future__ import annotations
from datetime import date, timedelta
from app.extensions import db
from app.models import InAppNotification, Month, NotificationPreference, User
class NotificationService:
def __init__(self, month_service, push_service, threshold: float):
self.month_service = month_service
self.push_service = push_service
self.threshold = threshold
def run_monthly_checks(self, today: date | None = None) -> int:
today = today or date.today()
current_month = self.month_service.ensure_month(today)
next_month_date = (today.replace(day=28) + timedelta(days=4)).replace(day=1)
next_month = Month.query.filter_by(
label=f"{next_month_date.year:04d}-{next_month_date.month:02d}"
).first()
summary = self.month_service.compute_summary(current_month)
count = 0
for user in User.query.filter_by(is_active=True).all():
pref = user.notification_preference or NotificationPreference(user_id=user.id)
if pref.id is None:
db.session.add(pref)
db.session.flush()
if pref.notify_month_end and next_month is None and today.day >= 25:
self._notify(
user,
"month_end",
"Folgemonat fehlt",
"Der nächste Monat ist noch nicht vorbereitet. Öffne Saldo und prüfe die Planung.",
"/months/",
)
count += 1
if pref.notify_missing_distribution and summary.remainder != summary.allocation_total:
self._notify(
user,
"missing_distribution",
"Restverteilung unvollständig",
"Die geplante Verteilung deckt den aktuellen Restbetrag noch nicht vollständig ab.",
f"/planning/{current_month.label}",
)
count += 1
if pref.notify_missing_values and abs(float(summary.deltas["income_delta"])) >= self.threshold:
self._notify(
user,
"income_change",
"Einkommen hat sich deutlich verändert",
"Durch eine Einkommensänderung sollten die Vorschläge und Verteilungen geprüft werden.",
f"/planning/{current_month.label}",
)
count += 1
db.session.commit()
return count
def _notify(self, user, kind: str, title: str, body: str, action_url: str) -> None:
notification = InAppNotification(
user_id=user.id, type=kind, title=title, body=body, action_url=action_url
)
db.session.add(notification)
self.push_service.send_to_user(user, title=title, body=body, url=action_url)