Add cron container and per-household timezone for auto-reminders
CI / test-and-package (push) Successful in 36s

- docker-compose.yml: meal-cron service loops send_reminders_cron.py every 60s
- send_reminders_cron.py: checks each household's local time, sends ntfy
  reminders at 10:00 (lunch) and 16:00 (dinner), guarded against duplicates
- models.py: timezone, last_lunch_reminder, last_dinner_reminder on households
- meals.py: /admin/timezone route for admins to set household timezone
- dashboard: timezone selector (20 common zones) in Account Settings
- i18n: 5 new translation keys for timezone strings
- Dockerfile: copy send_reminders_cron.py
- tests: 4 new timezone tests (admin set, non-admin denied, default UTC, auth)
- docs: updated AGENTS.md
This commit is contained in:
agentbox
2026-08-01 06:23:33 +00:00
parent 3681f9dfce
commit 2cd435daf2
9 changed files with 248 additions and 2 deletions
+62
View File
@@ -229,3 +229,65 @@ class TestNtfyTestEndpoint:
"ntfy_url": "https://ntfy.sh/test",
})
assert resp.status_code == 302
class TestTimezoneSettings:
def test_admin_can_set_timezone(self, admin_client):
resp = admin_client.post("/admin/timezone", data={
"timezone": "Europe/Zurich",
}, follow_redirects=True)
assert resp.status_code == 200
from models import get_db
db = get_db()
row = db.execute(
"SELECT timezone FROM households WHERE name = ?", ("Admin Household",)
).fetchone()
assert row["timezone"] == "Europe/Zurich"
def test_non_admin_cannot_set_timezone(self, client):
# Register a regular user in an existing household
client.post("/register", data={
"username": "admin_tz",
"password": "admin_tz_pass",
"confirm": "admin_tz_pass",
"household_action": "create",
"new_household_name": "TZ Household",
}, follow_redirects=True)
client.get("/logout")
from models import get_household_by_name
hh = get_household_by_name("TZ Household")
client.post("/register", data={
"username": "regular_tz",
"password": "regular_tz_pass",
"confirm": "regular_tz_pass",
"household_action": "join",
"household_id": str(hh["id"]),
}, follow_redirects=True)
resp = client.post("/admin/timezone", data={
"timezone": "Europe/Zurich",
}, follow_redirects=True)
assert resp.status_code == 200
# Timezone should NOT have changed
from models import get_db
db = get_db()
row = db.execute(
"SELECT timezone FROM households WHERE id = ?", (hh["id"],)
).fetchone()
assert row["timezone"] == "UTC" # unchanged
def test_default_timezone_is_utc(self, admin_client):
from models import get_db
db = get_db()
row = db.execute(
"SELECT timezone FROM households WHERE name = ?", ("Admin Household",)
).fetchone()
assert row["timezone"] == "UTC"
def test_timezone_requires_login(self, client):
resp = client.post("/admin/timezone", data={
"timezone": "Europe/Zurich",
})
assert resp.status_code == 302