Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions PROJECTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

## 🔍 Recent Activity

- **2026-07-30 — Focus Queue: real undo, "due today," and `is_focus` retirement (issue #281)**: three related fixes to `/focus/`. (1) The complete checkbox only ever called `mark_completed()` — an accidental click had no way back; it now toggles complete/incomplete and swaps just that row so a just-completed task stays visible (struck through, still checked) as an immediate undo. (2) `due_date` used to only decorate a row; a new "📅 Today" button sets it, and due-today-or-overdue tasks now always sort ahead of the rest of the queue regardless of priority. (3) `is_focus` (P-028, week-scoped, dashboard-only) is retired — its only "add to focus" UI path was lost back in P-050 phase 4, leaving no way to set it at all. Rather than restoring a second star toggle, the dashboard's weekly widget now lists `due_date <= today` tasks, sharing the Focus Queue's own signal (migration `0018_remove_practicetodo_is_focus`); resolves the overlap issue #281 flagged.
- **2026-07-24 — Configurable overdue-invoice threshold (issue #195)**: the "sent invoice counts as overdue" cutoff was hardcoded to 30 days in three separate places (`InvoiceActionsWidgetBuilder.get_overdue_invoices()`, feeding both the dashboard and the Focus Queue's `invoice_unpaid` task; `ClientDetailContextBuilder`'s payment-reminder urgency, which also had a hardcoded 14-day "medium" tier). Added `Practice.overdue_after_days` (default 30, admin-editable in the existing "Payment Terms" fieldset) and wired all three call sites to it; the medium tier now reuses the existing `payment_terms_days` field instead of a second hardcoded 14. The `bank_import_reminder_days` half of #195 turned out to be moot — that widget (`BankImportReminderWidgetBuilder`) was already deleted as dead code during P-050 phase 4. Also fixed a migration-graph conflict (duplicate `0015` leaves) left behind when PRs #270 and #271 merged independently.
- **2026-07-30 — v0.4.1 patch release**: GebüH invoices gained a per-client `gebueh_no_diagnosis` opt-out (checkbox on the client edit page) to suppress the diagnosis line while keeping the Ziffern breakdown — came up as a special case for one client. Bundled with the rest of the week's Focus Queue/P-050 follow-ups (supervision topics materialized as tasks, daily sync timer, real undo + "due today" + `is_focus` retirement), a time-off workday-counting fix (#278), and an analytics/client-detail/Focus-Queue N+1 query cleanup (4,088 → 87 queries on `/analytics/`, #276). Full list: [docs/CHANGELOG.md](docs/CHANGELOG.md).
- **2026-07-29–30 — Focus Queue: supervision materialization, daily sync, real undo, "due today," `is_focus` retirement (issue #280, #281)**: `sync_focus_queue_tasks` now also materializes open (`offen`) `SupervisionItem`s as tasks (auto-closed on `besprochen`) and runs on its own daily systemd timer instead of only on manual invocation. Separately, three fixes to `/focus/` itself: (1) the complete checkbox only ever called `mark_completed()` — an accidental click had no way back; it now toggles complete/incomplete and swaps just that row so a just-completed task stays visible (struck through, still checked) as an immediate undo. (2) `due_date` used to only decorate a row; a new "📅 Today" button sets it, and due-today-or-overdue tasks now always sort ahead of the rest of the queue regardless of priority. (3) `is_focus` (P-028, week-scoped, dashboard-only) is retired — its only "add to focus" UI path was lost back in P-050 phase 4, leaving no way to set it at all. Rather than restoring a second star toggle, the dashboard's weekly widget now lists `due_date <= today` tasks, sharing the Focus Queue's own signal (migration `0018_remove_practicetodo_is_focus`); resolves the overlap issue #281 flagged. `RECURRING_REVIEW` (the other half of #280) remains undesigned.

> Ältere Einträge: [docs/CHANGELOG.md](docs/CHANGELOG.md)

Expand Down
2 changes: 1 addition & 1 deletion app/my_practice/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = "v0.4.0"
VERSION = "v0.4.1"
2 changes: 1 addition & 1 deletion docker-compose.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ services:
retries: 5

django:
image: ghcr.io/dholbach/my-practice:v0.4.0
image: ghcr.io/dholbach/my-practice:v0.4.1
container_name: my-practice-django
restart: unless-stopped
ports:
Expand Down
11 changes: 11 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

Major features and milestones in chronological order.

## 2026-07-30 — v0.4.1 patch release

- **Feature — GebüH invoice "no diagnosis" opt-out** (#287): some GebüH clients need the fee-schedule breakdown but must not have a diagnosis line on their invoice. Added a per-client `gebueh_no_diagnosis` checkbox (default off, in the client edit page's GebüH section) that suppresses just that line on both the invoice PDF and the web invoice detail view — the Ziffern/fee-schedule table itself is unaffected.
- **Feature — Focus Queue: open supervision topics materialized** (#282): `sync_focus_queue_tasks` now creates one task per open (`offen`) `SupervisionItem`, auto-closed once marked `besprochen`, reusing the existing materialize-and-reconcile pattern already used for missing session logs and unpaid/unsent invoices. The dedicated `/supervision/` queue is unchanged — the Focus Queue now just also surfaces the same open items. Closes the "supervision" half of #280 (`RECURRING_REVIEW` remains open, needs its own design).
- **Feature — Focus Queue real undo, "due today," and `is_focus` retirement** (issue #281, #283/#284/#286): the complete checkbox only ever called `mark_completed()` with no way back; it now toggles complete/incomplete and swaps just the affected row so a just-completed task stays visible in place as an immediate undo. A new "📅 Today" quick action sets `due_date`, and due-today-or-overdue tasks now always sort ahead of the rest of the queue regardless of priority. `is_focus` (P-028, week-scoped, dashboard-only) is retired outright — its only "add to focus" UI path had already been lost in P-050 phase 4 — and the dashboard's weekly widget now lists `due_date <= today` tasks instead, sharing the Focus Queue's own signal (migration `0018_remove_practicetodo_is_focus`).
- **Chore — Focus Queue sync on a daily timer** (#279): `sync_focus_queue_tasks` previously only refreshed materialized tasks when run manually; added `my-practice-sync-focus-queue.service`/`.timer` following the existing pattern used by `backup`/`fetch-calendar-events`/`update-client-tags`.
- **Fix — time-off duration counted in workdays, not calendar days** (#278): `TimeOff.duration_days` and the analytics "Time Off by Year" breakdown used naive `(end_date - start_date).days` arithmetic, over/under-counting periods that span weekends or Berlin public holidays. Switched to `DateRangeHelper.count_working_days` + `berlin_public_holidays` (M-PAT-05); relabeled the affected UI from "days"/"Tage" to "workdays"/"Arbeitstage" to match the new semantics.
- **Perf — N+1 query cleanup on analytics, client detail, and Focus Queue** (#276): `/analytics/` fired 4,088 queries (2.3s) per page load from several distinct causes — missing `service_type` in two analytics helpers' `select_related`, a capacity-trends loop re-querying every month despite a docstring claiming otherwise, two monthly-trend calculators aggregating per-month in Python instead of one grouped query, and a yearly-comparison helper recomputing the same totals twice. Fixed all four (4,088 → 87 queries); the same missing-`service_type` gap also hit the analytics heatmap (598 → 87) and the client-detail page's invoice-item prefetch (53 → 37), and the Focus Queue's task queryset had no `select_related`/`prefetch_related` at all (53 → 17).
- **Chore — Dependabot pins now fixable directly** (#277): replaced `requirements-dev.txt`'s `-r requirements.txt` include with duplicated pins, since Dependabot's security-update PR generation doesn't resolve `-r` includes — every runtime CVE alert was stuck against a file it had no way to patch. Both files now note they must be kept in sync by hand.
- **Deps**: `ruff` 0.16.0 (#275), `uvicorn` 0.52.0 (#288).

## 2026-07-24 — v0.4.0 minor release

- **Feature — Focus Queue** (P-050, #264–#270): New unified task system replacing the old `/todos/` list and the dashboard's "Needs Action" pane. `PracticeTodo` extended into a full `Task` model (`task_type`, `snoozed_until`, generic `related_object` FK to Client/Invoice/Session) and a `sync_focus_queue_tasks` management command materializes derived signals — missing session logs, unpaid/unsent invoices, pending operational checklists — as real, closeable rows instead of live-computed widgets or ad-hoc client tags. The new `/focus/` page shows manual and materialized tasks side by side, with a type filter (color-coded pill buttons matching each task type's badge color) and a reference date per row (invoice date, session date, or task creation date, whichever is most relevant). The dashboard narrows down to a pure overview — its redundant "Today" agenda widget was removed once confirmed the "This Week" widget already highlights today's sessions.
Expand Down
7 changes: 5 additions & 2 deletions docs/FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ Complete feature list for the Therapy Practice Management System.
- ✅ Invoice detail page (web view) mirrors the same headline-row + collapsed detail-line layout as the PDF, instead of a separate row per code plus subtotal/remaining rows; totals block also shows the running "GebüH gesamt" alongside the invoice grand total, matching the PDF
- ✅ Recorded Ziffer amount capped at what's actually charged (`min(satz_max, vereinbarter_betrag)`) rather than always showing the code's ceiling rate
- ✅ Probatorik callout — Profil tab hint when diagnosis not yet set; escalates to warning badge after 5+ diagnostic Ziffern recorded
- ✅ `Client.gebueh_no_diagnosis` opt-out — per-client checkbox to omit the diagnosis line from GebüH invoices (PDF and web invoice detail) while keeping the Ziffern/fee-schedule breakdown

### Session Tracking
- ✅ Historical session data import
Expand Down Expand Up @@ -177,7 +178,7 @@ Complete feature list for the Therapy Practice Management System.
- ✅ Vacation/Sick leave/Holiday tracking
- ✅ Date range with duration calculation
- ✅ Year-spanning periods supported
- ✅ Workday calculations (5/7 formula)
- ✅ Workday calculations — real Berlin public holidays (`DateRangeHelper.count_working_days`), not the old 5/7 calendar approximation; "Duration"/"Wk." columns relabeled "workdays"/"Arbeitstage" to match
- ✅ Capacity impact analysis
- ✅ Period-based calculations
- ✅ Calendar integration
Expand Down Expand Up @@ -349,8 +350,10 @@ Complete feature list for the Therapy Practice Management System.

## 🚀 Recent Additions (Juli 2026)

### Focus Queue improvements (30. Juli)
### Focus Queue improvements (29.–30. Juli)

- **Open supervision topics materialized as tasks** — `sync_focus_queue_tasks` now creates a Focus Queue task per open (`offen`) `SupervisionItem`, auto-closed once marked `besprochen`; the dedicated `/supervision/` queue is unchanged, the Focus Queue just also surfaces the same open items
- **Sync runs on a daily timer** — `sync_focus_queue_tasks` (materializes missing session logs, unpaid/unsent invoices, checklists, supervision topics) now has its own systemd timer, matching the other periodic jobs, instead of only refreshing when run manually
- **Checkbox now really toggles** — previously only ever marked a task complete; an accidental click had no way back short of Django admin. It now toggles complete/incomplete, and the just-completed row stays visible in place (struck through, still checked) as an immediate undo
- **"📅 Today" quick action** — sets a task's due date to today in one click; due-today-or-overdue tasks now always sort ahead of the rest of the queue regardless of priority
- **`is_focus` retired, merged into `due_date`** — the dashboard's weekly widget star toggle had no working "add" path left (only "remove"); rather than restoring it, the widget now lists tasks due today or overdue, sharing the same signal the Focus Queue sorts on
Expand Down
2 changes: 1 addition & 1 deletion prod.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import time
import urllib.request

VERSION = "v0.4.0" # updated each release — keeps prod.py and docker-compose.prod.yml in sync
VERSION = "v0.4.1" # updated each release — keeps prod.py and docker-compose.prod.yml in sync

COMPOSE_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "docker-compose.prod.yml")
COMPOSE = ["docker", "compose", "-f", COMPOSE_FILE]
Expand Down