From f61f789e573b268bc3efe9ebd57ccbfa532c640a Mon Sep 17 00:00:00 2001 From: Daniel Holbach Date: Thu, 30 Jul 2026 17:11:37 +0200 Subject: [PATCH] chore: bump version to v0.4.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Version bump (app/my_practice/version.py, prod.py, docker-compose.prod.yml) plus docs pass: CHANGELOG entry covering the GebΓΌH invoice "no diagnosis" opt-out (#287), Focus Queue supervision materialization + daily sync timer (#279, #282), Focus Queue real undo/"due today"/is_focus retirement (#283/#284/#286), the time-off workday-counting fix (#278), the analytics/client-detail/Focus-Queue N+1 query cleanup (#276), the Dependabot requirements-dev split (#277), and dep bumps (ruff 0.16.0, uvicorn 0.52.0). FEATURES.md and PROJECTS.md updated to match. Co-Authored-By: Claude Sonnet 5 --- PROJECTS.md | 4 ++-- app/my_practice/version.py | 2 +- docker-compose.prod.yml | 2 +- docs/CHANGELOG.md | 11 +++++++++++ docs/FEATURES.md | 7 +++++-- prod.py | 2 +- 6 files changed, 21 insertions(+), 7 deletions(-) diff --git a/PROJECTS.md b/PROJECTS.md index d0a0785..93c870f 100644 --- a/PROJECTS.md +++ b/PROJECTS.md @@ -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) diff --git a/app/my_practice/version.py b/app/my_practice/version.py index f3388f2..ad977f7 100644 --- a/app/my_practice/version.py +++ b/app/my_practice/version.py @@ -1 +1 @@ -VERSION = "v0.4.0" +VERSION = "v0.4.1" diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 8b798f3..2f8216c 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -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: diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index a0937e5..64a22e2 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -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. diff --git a/docs/FEATURES.md b/docs/FEATURES.md index 68e219e..8ee837d 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -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 @@ -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 @@ -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 diff --git a/prod.py b/prod.py index a70b8cb..8378ffa 100755 --- a/prod.py +++ b/prod.py @@ -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]