diff --git a/PROJECTS.md b/PROJECTS.md index f4d91f8..adee2fa 100644 --- a/PROJECTS.md +++ b/PROJECTS.md @@ -31,8 +31,8 @@ grep -rho "P-[0-9]\{3\}" --include=*.md --include=*.py --include=*.html \ ## πŸ” Recent Activity +- **2026-10-27 β€” v0.9.0 released**: inquiry lapse/anonymise and charts (#533, #534), same-day session crash fix (#537), systemd timer fixes (#535), Pillow 13 / python-dateutil 3.0. Highlights in [docs/CHANGELOG.md](docs/CHANGELOG.md). - **2026-10-21 β€” Inquiry charts, lapse + anonymise**: `/inquiries` gets a monthly chart with marketing periods drawn as lanes (generic `lanes` option on `MPChart.bar`) and an open-inquiry ageing list (PR #533). Follow-up adds a *Lapsed* status and `manage.py tidy_inquiries` (lapse after 60 days without a step, anonymise closed non-client inquiries 180 days after last contact); not on the scheduled-jobs timer yet β€” the retention period is still to be confirmed with the Verband. -- **2026-10-15 β€” Screenshot refresh (#148)**: README screenshots retaken on `seed_sample_data` in the English UI, mixing light and dark theme β€” dashboard, Focus Queue, GebΓΌH invoice breakdown, client heatmap, inquiries, both diagnosis callouts (standard + escalated), batch invoicing; the analytics shot is the Capacity tab. `seed_sample_data` now seeds capacity periods and keeps its cancellations (billing them as therapy had cleared the flag), so that tab is populated; its utilisation subtitle lists the practice's own targets instead of a hardcoded history. Inquiry row actions fixed (compact `.btn`s; `.btn.btn-success` scoped like `.btn-danger`). > Γ„ltere EintrΓ€ge: [docs/CHANGELOG.md](docs/CHANGELOG.md) diff --git a/app/my_practice/version.py b/app/my_practice/version.py index 3ff6e4d..6ff3db7 100644 --- a/app/my_practice/version.py +++ b/app/my_practice/version.py @@ -1 +1 @@ -VERSION = "v0.8.1" +VERSION = "v0.9.0" diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 057cb9f..f5f4144 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.8.1 + image: ghcr.io/dholbach/my-practice:v0.9.0 container_name: my-practice-django restart: unless-stopped ports: diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 32efddd..e0f806b 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,6 +2,21 @@ Major features and milestones in chronological order. +## 2026-10-27 β€” v0.9.0 minor release + +Inquiry outcomes you can trust, a crash fix for same-day sessions, and scheduled jobs that no longer fire before the app is up. + +**Upgrading:** one migration runs on start (`0008`, adds the *Lapsed* inquiry status and an `anonymised_at` field β€” additive, nothing rewritten). If you installed the systemd units, re-run `sudo bash scripts/install-system-jobs.sh` so the corrected unit files take effect. + +- **Fix β€” same-day sessions crashed the session log and invoice lookup** (#537): a client can have several sessions on one date (the calendar import keys on date + time, and a cancel + rebook at the same slot leaves a cancelled twin). `session_log_create` and the invoice form's session attachment used `get_or_create(client, session_date)` and raised `MultipleObjectsReturned`. Both now pick from the day's non-cancelled sessions, preferring one not yet logged or billed, and only create a session when none exists. +- **Feature β€” Lapsed inquiries and `manage.py tidy_inquiries`** (#534): most open inquiries had quietly ended without a status change, so every outcome statistic read as "still open". The command (dry run unless `--apply`) closes an open inquiry with no new step for 60 days as *Lapsed* β€” outcome unknown, rather than a guessed status β€” and anonymises closed non-client inquiries 180 days after the last contact: name, contact details and notes wiped, statistics kept. Onboarded inquiries are untouched. Not on the scheduled-jobs timer yet; the retention period is still to be confirmed. +- **Feature β€” inquiry chart with marketing lanes, and open-inquiry ageing** (#533): the monthly trend is a Chart.js bar chart covering every month of the last twelve (the old CSS bars skipped empty months), with each marketing period drawn as a labelled lane above the bars. A second panel ranks open inquiries by days since their last step and highlights those past 30 days. `lanes` is a generic option on `MPChart.bar`. +- **Fix β€” scheduled jobs ran at boot before the app was up** (#535): both timers carried `Requires=` on their service, so starting a timer (every boot, every installer run) started the job immediately β€” backups failed on `pg_dump`, scheduled jobs on "No such container". The services now order `After=my-practice-app.service`. `install-system-jobs.sh` no longer detects (and suggests deleting) leftover units with a `my-practice-*` glob that also matched unrelated private units, and it starts `my-practice-app.service` as well as enabling it. +- **Fix β€” inquiry row actions** (#524): Edit/Admit/Delete rendered as an underlined link, an oversized block and an unrounded button; they are compact `.btn`s now. `.btn-success` is scoped like `.btn-danger`, which also turns the add buttons on the withdrawal and time-off lists and bank review's auto-match button green as intended. +- **Feature β€” demo data fills the Capacity tab** (#524): `seed_sample_data` seeds capacity periods and keeps its cancellations, and the utilisation subtitle lists the practice's own capacity periods instead of a hardcoded history. README screenshots retaken (#148). +- **Chore β€” dev tooling** (#530, #532): translation catalogs are recompiled on container start, before tests and after a pull, so a pull with new msgids no longer leaves English text under the German locale (re-run `./dev.py install-hooks` for the new hook types). The `flatpak-spawn` fallback is gone from `dev.py` and `prod.py`; `docker` must be on `PATH`. +- **Deps**: Pillow 13.0.0, python-dateutil 3.0.0, pypdf 6.21.2, pydyf 0.13.0, markdown 3.11.2, ruff 0.17.2, GitHub Actions `setup-python` / `docker/login-action`; Dependabot scans `/app` only, so major bumps no longer arrive twice (#528, #529, #531, #538, #540–#543). + ## 2026-10-14 β€” v0.8.1 patch release - **Fix β€” v0.8.0 could not start in production** (#523): the vendored `chart.umd.min.js` (#519) ended in a `sourceMappingURL` comment pointing to a `.map` file that was never vendored. WhiteNoise's manifest storage follows that reference during `collectstatic` and aborts, so the container exited right after `migrate` and kept restarting. The comment is gone. A new guardrail runs `collectstatic` through the production storage, since the suite and the dev stack both use plain storage and could not see it. **If you updated to v0.8.0**, the migrations already ran, so update to v0.8.1 with `./prod.py update` as usual. diff --git a/prod.py b/prod.py index b5f38ae..6713a64 100755 --- a/prod.py +++ b/prod.py @@ -19,7 +19,7 @@ import time import urllib.request -VERSION = "v0.8.1" # updated each release β€” keeps prod.py and docker-compose.prod.yml in sync +VERSION = "v0.9.0" # 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]