release: publish saldo 0.1.0
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
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)
|
||||
Reference in New Issue
Block a user