diff --git a/app/locale/de/LC_MESSAGES/django.po b/app/locale/de/LC_MESSAGES/django.po index 9658291..63ecf8c 100644 --- a/app/locale/de/LC_MESSAGES/django.po +++ b/app/locale/de/LC_MESSAGES/django.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: my-practice\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-10-14 10:00+0200\n" +"POT-Creation-Date: 2026-10-21 08:43+0200\n" "PO-Revision-Date: 2026-06-22 23:01+0200\n" "Language-Team: German\n" "Language: de\n" @@ -41,9 +41,9 @@ msgstr "Zuordnung" #: my_practice/admin/bank_statement.py:75 my_practice/admin/client.py:110 #: my_practice/admin/timeoff.py:42 my_practice/admin/todo.py:49 #: my_practice/models/calendar.py:140 my_practice/models/clinical.py:318 -#: my_practice/models/inquiry.py:111 my_practice/models/invoice.py:153 +#: my_practice/models/inquiry.py:111 my_practice/models/invoice.py:154 #: templates/includes/calendar_preflight_widget.html:28 -#: templates/my_practice/analytics.html:397 +#: templates/my_practice/analytics.html:347 #: templates/my_practice/bank_import.html:88 #: templates/my_practice/billing_open_overview.html:65 #: templates/my_practice/calendar_import.html:100 @@ -90,7 +90,7 @@ msgid "Match" msgstr "Zuordnung" #: my_practice/admin/bank_statement.py:129 my_practice/admin/session.py:34 -#: my_practice/models/invoice.py:196 my_practice/models/invoice.py:354 +#: my_practice/models/invoice.py:197 my_practice/models/invoice.py:355 #: templates/my_practice/bank_review.html:269 #: templates/my_practice/bank_review.html:359 #: templates/my_practice/billing_open_overview.html:64 @@ -107,7 +107,7 @@ msgstr "Rechnung" #: my_practice/models/calendar.py:126 my_practice/models/client.py:216 #: my_practice/models/client.py:270 my_practice/models/client_alias.py:32 #: my_practice/models/clinical.py:170 my_practice/models/clinical.py:306 -#: my_practice/models/clinical.py:363 my_practice/models/invoice.py:140 +#: my_practice/models/clinical.py:363 my_practice/models/invoice.py:141 #: my_practice/models/session.py:22 #: templates/my_practice/billing_open_overview.html:60 #: templates/my_practice/calendar_import.html:98 @@ -147,8 +147,8 @@ msgid "Basic Information" msgstr "Grundinformationen" #: my_practice/admin/client.py:67 my_practice/admin/practice.py:38 -#: templates/my_practice/inquiry_list.html:185 -#: templates/my_practice/inquiry_list.html:233 +#: templates/my_practice/inquiry_list.html:205 +#: templates/my_practice/inquiry_list.html:253 #: templates/my_practice/practice_form.html:100 msgid "Contact" msgstr "Kontakt" @@ -192,7 +192,7 @@ msgstr "Zeitstempel" #: my_practice/admin/client.py:114 my_practice/admin/inquiry.py:25 #: my_practice/admin/operational.py:31 my_practice/models/calendar.py:63 #: my_practice/models/client.py:186 my_practice/models/practice.py:52 -#: templates/my_practice/analytics.html:417 +#: templates/my_practice/analytics.html:367 #: templates/my_practice/client_detail.html:11 #: templates/my_practice/client_list_cards.html:34 #: templates/my_practice/dashboard.html:88 @@ -243,7 +243,7 @@ msgstr "Details" #: my_practice/import_forms.py:67 my_practice/models/bank_statement.py:128 #: my_practice/models/client.py:122 my_practice/models/client_alias.py:41 #: my_practice/models/financial.py:63 my_practice/models/inquiry.py:126 -#: my_practice/models/invoice.py:189 my_practice/models/operational.py:56 +#: my_practice/models/invoice.py:190 my_practice/models/operational.py:56 #: my_practice/models/timeoff.py:55 templates/my_practice/checklist.html:119 #: templates/my_practice/time_off_confirm_delete.html:28 #: templates/my_practice/withdrawal_list.html:62 @@ -261,7 +261,7 @@ msgstr "Arbeitsdiagnose" #: my_practice/admin/clinical.py:54 my_practice/admin/invoice.py:269 #: my_practice/models/calendar.py:148 my_practice/models/clinical.py:222 -#: my_practice/models/gebueh.py:89 my_practice/models/invoice.py:388 +#: my_practice/models/gebueh.py:89 my_practice/models/invoice.py:389 #: my_practice/models/session.py:63 msgid "Session" msgstr "Sitzung" @@ -363,7 +363,7 @@ msgstr "Allgemein" #: my_practice/forms.py:198 my_practice/import_forms.py:117 #: my_practice/models/client.py:289 my_practice/models/financial.py:150 #: my_practice/models/gebueh.py:29 my_practice/models/inquiry.py:218 -#: my_practice/models/invoice.py:396 my_practice/models/tag.py:84 +#: my_practice/models/invoice.py:397 my_practice/models/tag.py:84 #: templates/my_practice/expense_confirm_delete.html:15 #: templates/my_practice/expense_list.html:80 #: templates/my_practice/invoice_edit.html:135 @@ -423,7 +423,7 @@ msgstr "Beträge" msgid "Amounts are calculated automatically from invoice items" msgstr "Beträge werden automatisch aus den Rechnungspositionen berechnet" -#: my_practice/admin/invoice.py:203 my_practice/models/invoice.py:368 +#: my_practice/admin/invoice.py:203 my_practice/models/invoice.py:369 #: templates/my_practice/bank_review.html:77 #: templates/my_practice/invoice_detail.html:88 #: templates/my_practice/invoice_list.html:21 @@ -531,7 +531,7 @@ msgstr "Unterschrift Vorschau" msgid "No signature uploaded" msgstr "Keine Unterschrift hochgeladen" -#: my_practice/admin/service.py:19 my_practice/models/invoice.py:357 +#: my_practice/admin/service.py:19 my_practice/models/invoice.py:358 msgid "Service Type" msgstr "Leistungsart" @@ -608,7 +608,7 @@ msgstr "Aufgabe" msgid "Priority" msgstr "Priorität" -#: my_practice/admin/todo.py:116 templates/includes/focus_queue_row.html:15 +#: my_practice/admin/todo.py:116 templates/includes/focus_queue_row.html:14 msgid "Mark as completed" msgstr "Als erledigt markieren" @@ -760,8 +760,8 @@ msgstr "Honorar 90 Min (€)" #: templates/my_practice/client_detail.html:638 #: templates/my_practice/expense_confirm_delete.html:11 #: templates/my_practice/expense_list.html:79 -#: templates/my_practice/inquiry_list.html:181 -#: templates/my_practice/inquiry_list.html:229 +#: templates/my_practice/inquiry_list.html:201 +#: templates/my_practice/inquiry_list.html:249 #: templates/my_practice/invoice_confirm_delete.html:20 #: templates/my_practice/invoice_detail.html:19 #: templates/my_practice/invoice_detail.html:84 @@ -815,7 +815,7 @@ msgid "End Date" msgstr "Enddatum" #: my_practice/forms.py:220 my_practice/models/timeoff.py:46 -#: templates/my_practice/analytics.html:400 +#: templates/my_practice/analytics.html:350 #: templates/my_practice/tax_workday_audit.html:62 #: templates/my_practice/time_off_confirm_delete.html:15 #: templates/my_practice/time_off_list.html:33 @@ -965,13 +965,13 @@ msgid "Code \"%(code)s\" is already taken." msgstr "Kürzel \"%(code)s\" ist bereits vergeben." #: my_practice/inquiry_forms.py:104 my_practice/models/inquiry.py:209 -#: templates/my_practice/analytics.html:56 +#: templates/my_practice/analytics.html:49 #: templates/my_practice/marketing_period_confirm_delete.html:14 msgid "From" msgstr "Von" #: my_practice/inquiry_forms.py:105 my_practice/models/inquiry.py:213 -#: templates/my_practice/analytics.html:62 +#: templates/my_practice/analytics.html:55 #: templates/my_practice/marketing_period_confirm_delete.html:18 msgid "To" msgstr "Bis" @@ -1059,7 +1059,7 @@ msgstr "Automatisch erstellte Korrektur (Fehlbuchung)" #: my_practice/models/expense_category_rule.py:26 #: my_practice/models/financial.py:52 my_practice/models/financial.py:140 #: my_practice/models/financial.py:235 my_practice/models/inquiry.py:97 -#: my_practice/models/inquiry.py:207 my_practice/models/invoice.py:126 +#: my_practice/models/inquiry.py:207 my_practice/models/invoice.py:127 #: my_practice/models/practice.py:372 my_practice/models/practice.py:408 #: my_practice/models/service.py:17 my_practice/models/todo.py:106 #: templates/base.html:89 templates/my_practice/tax_workday_audit.html:74 @@ -1249,10 +1249,10 @@ msgstr "Importiert" msgid "Skipped" msgstr "Übersprungen" -#: my_practice/models/calendar.py:102 my_practice/models/invoice.py:117 +#: my_practice/models/calendar.py:102 my_practice/models/invoice.py:118 #: my_practice/models/session.py:37 #: templates/includes/calendar_preflight_widget.html:45 -#: templates/my_practice/analytics.html:917 +#: templates/my_practice/analytics.html:772 #: templates/my_practice/calendar_import.html:62 #: templates/my_practice/calendar_import.html:159 #: templates/my_practice/dashboard.html:126 @@ -1301,19 +1301,19 @@ msgstr "Ausstehender Kalender-Termin" msgid "Pending calendar events" msgstr "Ausstehende Kalender-Termine" -#: my_practice/models/calendar.py:185 my_practice/models/invoice.py:253 +#: my_practice/models/calendar.py:185 my_practice/models/invoice.py:254 msgid "Client does not belong to the selected practice" msgstr "Klient:in gehört nicht zur ausgewählten Praxis" #: my_practice/models/client.py:82 my_practice/models/inquiry.py:80 -#: my_practice/views/inquiry_views.py:142 +#: my_practice/views/inquiry_views.py:235 #: templates/my_practice/send_cancellation_email.html:7 #: templates/my_practice/time_off_notice_form.html:54 msgid "German" msgstr "Deutsch" #: my_practice/models/client.py:83 my_practice/models/inquiry.py:81 -#: my_practice/views/inquiry_views.py:142 +#: my_practice/views/inquiry_views.py:235 #: templates/my_practice/send_cancellation_email.html:7 #: templates/my_practice/time_off_notice_form.html:73 msgid "English" @@ -1416,10 +1416,10 @@ msgstr "Online Klient" msgid "Check if this client primarily has online sessions" msgstr "Ankreuzen, wenn dieser Klient hauptsächlich Online-Sitzungen hat" -#: my_practice/models/client.py:217 templates/base.html:128 +#: my_practice/models/client.py:217 templates/base.html:133 #: templates/includes/command_palette.html:82 -#: templates/my_practice/analytics.html:104 -#: templates/my_practice/analytics.html:594 +#: templates/my_practice/analytics.html:97 +#: templates/my_practice/analytics.html:544 #: templates/my_practice/client_list_cards.html:8 msgid "Clients" msgstr "Klient:innen" @@ -1446,7 +1446,7 @@ msgstr "Überweisung" #: my_practice/models/client.py:263 my_practice/models/financial.py:31 #: my_practice/models/financial.py:132 my_practice/models/inquiry.py:34 -#: my_practice/models/todo.py:91 my_practice/views/inquiry_views.py:255 +#: my_practice/models/todo.py:91 my_practice/views/inquiry_views.py:328 #: templates/my_practice/bank_expense_review.html:50 msgid "Other" msgstr "Sonstiges" @@ -1940,8 +1940,8 @@ msgid "Tax year notes" msgstr "Steuer-Jahresnotizen" #: my_practice/models/gebueh.py:28 my_practice/models/service.py:25 -#: templates/my_practice/analytics.html:350 -#: templates/my_practice/analytics.html:395 +#: templates/my_practice/analytics.html:300 +#: templates/my_practice/analytics.html:345 #: templates/my_practice/client_list_cards.html:107 #: templates/my_practice/invoice_detail.html:120 #: templates/my_practice/time_off_notice_form.html:29 @@ -2036,22 +2036,23 @@ msgstr "Therapeutenliste" msgid "Network / colleagues" msgstr "Netzwerk / Kolleg:innen" -#: my_practice/models/inquiry.py:53 my_practice/views/inquiry_views.py:75 -#: my_practice/views/inquiry_views.py:239 +#: my_practice/models/inquiry.py:53 my_practice/views/inquiry_views.py:168 +#: my_practice/views/inquiry_views.py:312 msgid "New" msgstr "Neu" -#: my_practice/models/inquiry.py:54 my_practice/views/inquiry_views.py:76 -#: my_practice/views/inquiry_views.py:240 +#: my_practice/models/inquiry.py:54 my_practice/views/inquiry_views.py:169 +#: my_practice/views/inquiry_views.py:313 msgid "Contacted" msgstr "Kontaktiert" -#: my_practice/models/inquiry.py:55 my_practice/views/inquiry_views.py:77 -#: my_practice/views/inquiry_views.py:241 +#: my_practice/models/inquiry.py:55 my_practice/views/inquiry_views.py:131 +#: my_practice/views/inquiry_views.py:170 +#: my_practice/views/inquiry_views.py:314 msgid "Intro meeting" msgstr "Vorgespräch" -#: my_practice/models/inquiry.py:56 my_practice/views/inquiry_views.py:78 +#: my_practice/models/inquiry.py:56 my_practice/views/inquiry_views.py:171 msgid "Waitlist" msgstr "Warteliste" @@ -2059,8 +2060,8 @@ msgstr "Warteliste" msgid "Intake in progress" msgstr "Aufnahme läuft" -#: my_practice/models/inquiry.py:58 my_practice/views/inquiry_views.py:80 -#: my_practice/views/inquiry_views.py:243 +#: my_practice/models/inquiry.py:58 my_practice/views/inquiry_views.py:173 +#: my_practice/views/inquiry_views.py:316 msgid "Onboarded" msgstr "Aufgenommen" @@ -2077,14 +2078,14 @@ msgid "Not a match" msgstr "Kein Match" #: my_practice/models/inquiry.py:99 my_practice/models/tag.py:57 -#: templates/my_practice/analytics.html:396 +#: templates/my_practice/analytics.html:346 #: templates/my_practice/bank_import.html:85 #: templates/my_practice/bank_review.html:210 #: templates/my_practice/client_list_cards.html:108 #: templates/my_practice/inquiry_confirm_delete.html:10 #: templates/my_practice/inquiry_convert_confirm.html:17 -#: templates/my_practice/inquiry_list.html:182 -#: templates/my_practice/inquiry_list.html:230 +#: templates/my_practice/inquiry_list.html:202 +#: templates/my_practice/inquiry_list.html:250 #: templates/my_practice/practice_confirm_delete.html:24 #: templates/my_practice/tag_form.html:15 #: templates/my_practice/tag_list.html:25 @@ -2094,16 +2095,16 @@ msgstr "Name" #: my_practice/models/inquiry.py:105 #: templates/my_practice/inquiry_confirm_delete.html:18 #: templates/my_practice/inquiry_convert_confirm.html:29 -#: templates/my_practice/inquiry_list.html:183 -#: templates/my_practice/inquiry_list.html:231 +#: templates/my_practice/inquiry_list.html:203 +#: templates/my_practice/inquiry_list.html:251 msgid "Source" msgstr "Quelle" #: my_practice/models/inquiry.py:121 #: templates/my_practice/client_detail.html:225 -#: templates/my_practice/inquiry_list.html:102 -#: templates/my_practice/inquiry_list.html:184 -#: templates/my_practice/inquiry_list.html:232 +#: templates/my_practice/inquiry_list.html:107 +#: templates/my_practice/inquiry_list.html:204 +#: templates/my_practice/inquiry_list.html:252 #: templates/my_practice/time_off_notice_form.html:30 msgid "Language" msgstr "Sprache" @@ -2147,8 +2148,9 @@ msgstr "Anfrage" #: my_practice/models/inquiry.py:173 templates/includes/command_palette.html:41 #: templates/my_practice/inquiry_list.html:6 -#: templates/my_practice/inquiry_list.html:9 -#: templates/my_practice/inquiry_list.html:15 +#: templates/my_practice/inquiry_list.html:14 +#: templates/my_practice/inquiry_list.html:20 +#: templates/my_practice/inquiry_list.html:128 msgid "Inquiries" msgstr "Anfragen" @@ -2173,90 +2175,90 @@ msgstr "Marketing-Zeiträume" msgid "ongoing" msgstr "laufend" -#: my_practice/models/invoice.py:114 my_practice/views/billing_views.py:219 +#: my_practice/models/invoice.py:115 my_practice/views/billing_views.py:219 #: templates/my_practice/dashboard.html:111 #: templates/my_practice/invoice_detail.html:40 #: templates/my_practice/invoice_list.html:26 msgid "Draft" msgstr "Entwurf" -#: my_practice/models/invoice.py:115 my_practice/views/billing_views.py:221 +#: my_practice/models/invoice.py:116 my_practice/views/billing_views.py:221 #: templates/my_practice/dashboard.html:116 #: templates/my_practice/invoice_detail.html:41 #: templates/my_practice/invoice_list.html:31 msgid "Sent" msgstr "Versendet" -#: my_practice/models/invoice.py:116 my_practice/views/billing_views.py:223 +#: my_practice/models/invoice.py:117 my_practice/views/billing_views.py:223 #: templates/my_practice/dashboard.html:121 #: templates/my_practice/invoice_detail.html:42 #: templates/my_practice/invoice_list.html:36 msgid "Paid" msgstr "Bezahlt" -#: my_practice/models/invoice.py:118 +#: my_practice/models/invoice.py:119 #: templates/my_practice/invoice_detail.html:44 msgid "Written off" msgstr "Abgeschrieben" -#: my_practice/models/invoice.py:133 +#: my_practice/models/invoice.py:134 #: templates/my_practice/invoice_confirm_delete.html:12 msgid "Invoice number" msgstr "Rechnungsnummer" -#: my_practice/models/invoice.py:134 +#: my_practice/models/invoice.py:135 msgid "Auto-generated (e.g., JL-5) or enter manually" msgstr "Automatisch generiert (z.B. JL-5) oder manuell eingeben" -#: my_practice/models/invoice.py:145 +#: my_practice/models/invoice.py:146 #: templates/my_practice/revenue_report.html:51 #: templates/my_practice/tax_year_summary.html:132 msgid "Invoice date" msgstr "Rechnungsdatum" -#: my_practice/models/invoice.py:146 +#: my_practice/models/invoice.py:147 msgid "Defaults to today" msgstr "Standardmäßig heute" -#: my_practice/models/invoice.py:159 +#: my_practice/models/invoice.py:160 #: templates/my_practice/invoice_detail.html:23 #: templates/my_practice/invoice_detail.html:230 #: templates/my_practice/tax_year_summary.html:133 msgid "Paid on" msgstr "Bezahlt am" -#: my_practice/models/invoice.py:160 +#: my_practice/models/invoice.py:161 msgid "Date of payment" msgstr "Datum der Bezahlung" -#: my_practice/models/invoice.py:167 +#: my_practice/models/invoice.py:168 msgid "Subtotal" msgstr "Zwischensumme" -#: my_practice/models/invoice.py:173 +#: my_practice/models/invoice.py:174 msgid "Tax rate (%)" msgstr "Steuersatz (%)" -#: my_practice/models/invoice.py:174 +#: my_practice/models/invoice.py:175 msgid "Kleinunternehmer = 0%" msgstr "Kleinunternehmer = 0%" -#: my_practice/models/invoice.py:180 +#: my_practice/models/invoice.py:181 msgid "Tax amount" msgstr "Steuerbetrag" -#: my_practice/models/invoice.py:186 +#: my_practice/models/invoice.py:187 #: templates/my_practice/bank_expense_review.html:17 #: templates/my_practice/bank_withdrawal_review.html:17 #: templates/my_practice/invoice_confirm_delete.html:30 msgid "Total amount" msgstr "Gesamtbetrag" -#: my_practice/models/invoice.py:197 templates/base.html:129 +#: my_practice/models/invoice.py:198 templates/base.html:134 #: templates/includes/command_palette.html:83 -#: templates/my_practice/analytics.html:329 +#: templates/my_practice/analytics.html:279 +#: templates/my_practice/analytics.html:301 #: templates/my_practice/analytics.html:351 -#: templates/my_practice/analytics.html:401 #: templates/my_practice/bank_review.html:28 #: templates/my_practice/bank_review.html:360 #: templates/my_practice/invoice_list.html:5 @@ -2264,79 +2266,79 @@ msgstr "Gesamtbetrag" msgid "Invoices" msgstr "Rechnungen" -#: my_practice/models/invoice.py:209 +#: my_practice/models/invoice.py:210 msgid "This invoice number already exists." msgstr "Diese Rechnungsnummer existiert bereits." -#: my_practice/models/invoice.py:233 +#: my_practice/models/invoice.py:234 #, python-format msgid "Invoice number \"%(number)s\" already exists (invoice for %(client_code)s dated %(date)s)" msgstr "Rechnungsnummer \"%(number)s\" existiert bereits (Rechnung für %(client_code)s vom %(date)s)" -#: my_practice/models/invoice.py:247 +#: my_practice/models/invoice.py:248 msgid "Payment date must not be before the invoice date" msgstr "Zahlungsdatum darf nicht vor dem Rechnungsdatum liegen" -#: my_practice/models/invoice.py:360 +#: my_practice/models/invoice.py:361 #: templates/my_practice/invoice_detail.html:87 msgid "Rate" msgstr "Honorar" -#: my_practice/models/invoice.py:366 +#: my_practice/models/invoice.py:367 #: templates/my_practice/invoice_edit.html:119 msgid "Quantity" msgstr "Menge" -#: my_practice/models/invoice.py:372 my_practice/models/session.py:43 +#: my_practice/models/invoice.py:373 my_practice/models/session.py:43 msgid "Group size" msgstr "Gruppengröße" -#: my_practice/models/invoice.py:374 +#: my_practice/models/invoice.py:375 msgid "Number of participants for group offerings (default 1 = individual session). Affects the calculation of therapist hours in analytics." msgstr "Anzahl Teilnehmer bei Gruppenangeboten (default 1 = Einzelsitzung). Beeinflusst die Berechnung der Therapeutenstunden in der Analytik." -#: my_practice/models/invoice.py:390 +#: my_practice/models/invoice.py:391 msgid "Linked session (central reference for clinical documentation + billing)" msgstr "Verknüpfte Sitzung (zentrale Referenz für Klinik + Abrechnung)" -#: my_practice/models/invoice.py:398 +#: my_practice/models/invoice.py:399 msgid "Free-text line item label, used instead of a linked session (day-rate/project billing) — only available when the practice allows free-form invoice items" msgstr "Freitext-Bezeichnung der Position, anstelle einer verknüpften Sitzung (Tagessatz-/Projektabrechnung) — nur verfügbar, wenn die Praxis Freitext-Rechnungspositionen erlaubt" -#: my_practice/models/invoice.py:409 +#: my_practice/models/invoice.py:410 msgid "Invoice item" msgstr "Rechnungsposition" -#: my_practice/models/invoice.py:410 templates/my_practice/invoice_edit.html:67 +#: my_practice/models/invoice.py:411 templates/my_practice/invoice_edit.html:67 #: templates/my_practice/invoice_form.html:68 msgid "Invoice items" msgstr "Rechnungspositionen" -#: my_practice/models/invoice.py:432 +#: my_practice/models/invoice.py:433 msgid "Invoice item needs either a linked session or a description, not both or neither." msgstr "Rechnungsposition benötigt entweder eine verknüpfte Sitzung oder eine Beschreibung, nicht beides und nicht keins von beidem." -#: my_practice/models/invoice.py:444 +#: my_practice/models/invoice.py:445 msgid "This practice doesn't allow free-form invoice items." msgstr "Diese Praxis erlaubt keine Freitext-Rechnungspositionen." #: my_practice/models/operational.py:31 -#: my_practice/utils/dashboard_widgets.py:181 +#: my_practice/utils/dashboard_widgets.py:182 msgid "Weekly backup" msgstr "Wöchentliche Sicherung" #: my_practice/models/operational.py:32 -#: my_practice/utils/dashboard_widgets.py:180 +#: my_practice/utils/dashboard_widgets.py:181 msgid "Monthly restore test" msgstr "Monatlicher Restore-Test" #: my_practice/models/operational.py:35 -#: my_practice/utils/dashboard_widgets.py:182 +#: my_practice/utils/dashboard_widgets.py:183 msgid "MicroSD offsite backup (card A/B alternating, every 2 weeks)" msgstr "MicroSD-Offsite-Backup (Karte A/B im Wechsel, alle 2 Wochen)" #: my_practice/models/operational.py:37 -#: my_practice/utils/dashboard_widgets.py:183 +#: my_practice/utils/dashboard_widgets.py:184 msgid "Annual security review" msgstr "Jährliche Sicherheitsüberprüfung" @@ -2344,7 +2346,7 @@ msgstr "Jährliche Sicherheitsüberprüfung" msgid "Checklist type" msgstr "Checklisten-Typ" -#: my_practice/models/operational.py:46 templates/my_practice/analytics.html:42 +#: my_practice/models/operational.py:46 templates/my_practice/analytics.html:35 #: templates/my_practice/tax_quarter_overview.html:77 msgid "Period" msgstr "Zeitraum" @@ -3113,25 +3115,25 @@ msgstr "Wiederherstellungscode" msgid "Recovery codes" msgstr "Wiederherstellungscodes" -#: my_practice/signals.py:27 my_practice/views/invoice_views.py:318 +#: my_practice/signals.py:27 my_practice/views/invoice_views.py:319 #, python-format msgid "Invoice %(number)s has been issued and can no longer be changed. Cancel it and create a corrected copy instead." msgstr "Rechnung %(number)s wurde bereits ausgestellt und kann nicht mehr geändert werden. Bitte stornieren Sie sie und erstellen Sie stattdessen eine korrigierte Kopie." -#: my_practice/signals.py:74 my_practice/views/invoice_views.py:438 +#: my_practice/signals.py:74 my_practice/views/invoice_views.py:439 #, python-format msgid "Invoice %(number)s has been issued and must be kept until the end of %(year)s. Cancel it instead of deleting it." msgstr "Rechnung %(number)s wurde bereits ausgestellt und muss bis Ende %(year)s aufbewahrt werden. Bitte stornieren Sie sie, statt sie zu löschen." -#: my_practice/utils/analytics_utils.py:331 +#: my_practice/utils/analytics_utils.py:332 msgid "60-min sessions" msgstr "60-Min Sitzungen" -#: my_practice/utils/analytics_utils.py:339 +#: my_practice/utils/analytics_utils.py:340 msgid "90-min sessions" msgstr "90-Min Sitzungen" -#: my_practice/utils/analytics_utils.py:347 +#: my_practice/utils/analytics_utils.py:348 msgid "Group sessions" msgstr "Gruppensitzungen" @@ -3140,6 +3142,19 @@ msgstr "Gruppensitzungen" msgid "Wrong account: the CSV file belongs to IBAN %(csv_iban)s, expected the practice IBAN %(practice_iban)s. Import aborted." msgstr "Falsches Konto: Die CSV-Datei gehört zu IBAN %(csv_iban)s, erwartet wird die Praxis-IBAN %(practice_iban)s. Import abgebrochen." +#: my_practice/utils/bank_import.py:483 +msgid "Erroneous booking / correction from private account" +msgstr "Fehlbuchung / Korrektur vom privaten Konto" + +#: my_practice/utils/bank_import.py:487 +#: templates/my_practice/bank_review.html:240 +msgid "Capital contribution from private account" +msgstr "Kapitaleinlage vom privaten Konto" + +#: my_practice/utils/bank_import.py:501 +msgid "Own payment (capital contribution), ignored automatically" +msgstr "Eigene Zahlung (Einlage), automatisch ignoriert" + #: my_practice/utils/bank_import.py:538 #, python-format msgid "Failed to parse row: %(row)s" @@ -3216,62 +3231,74 @@ msgid "Session on %(date)s was billed." msgstr "Sitzung am %(date)s wurde abgerechnet." #: my_practice/utils/chart_helpers.py:17 -#: templates/my_practice/analytics.html:759 +#: templates/my_practice/analytics.html:18 +#: templates/my_practice/inquiry_list.html:129 msgid "Jan" msgstr "Jan" #: my_practice/utils/chart_helpers.py:18 -#: templates/my_practice/analytics.html:759 +#: templates/my_practice/analytics.html:18 +#: templates/my_practice/inquiry_list.html:129 msgid "Feb" msgstr "Feb" #: my_practice/utils/chart_helpers.py:19 -#: templates/my_practice/analytics.html:759 +#: templates/my_practice/analytics.html:18 +#: templates/my_practice/inquiry_list.html:129 msgid "Mar" msgstr "Mär" #: my_practice/utils/chart_helpers.py:20 -#: templates/my_practice/analytics.html:760 +#: templates/my_practice/analytics.html:18 +#: templates/my_practice/inquiry_list.html:129 msgid "Apr" msgstr "Apr" #: my_practice/utils/chart_helpers.py:21 -#: templates/my_practice/analytics.html:760 +#: templates/my_practice/analytics.html:19 +#: templates/my_practice/inquiry_list.html:129 msgid "May" msgstr "Mai" #: my_practice/utils/chart_helpers.py:22 -#: templates/my_practice/analytics.html:760 +#: templates/my_practice/analytics.html:19 +#: templates/my_practice/inquiry_list.html:129 msgid "Jun" msgstr "Jun" #: my_practice/utils/chart_helpers.py:23 -#: templates/my_practice/analytics.html:761 +#: templates/my_practice/analytics.html:19 +#: templates/my_practice/inquiry_list.html:129 msgid "Jul" msgstr "Jul" #: my_practice/utils/chart_helpers.py:24 -#: templates/my_practice/analytics.html:761 +#: templates/my_practice/analytics.html:19 +#: templates/my_practice/inquiry_list.html:129 msgid "Aug" msgstr "Aug" #: my_practice/utils/chart_helpers.py:25 -#: templates/my_practice/analytics.html:761 +#: templates/my_practice/analytics.html:20 +#: templates/my_practice/inquiry_list.html:129 msgid "Sep" msgstr "Sep" #: my_practice/utils/chart_helpers.py:26 -#: templates/my_practice/analytics.html:762 +#: templates/my_practice/analytics.html:20 +#: templates/my_practice/inquiry_list.html:129 msgid "Oct" msgstr "Okt" #: my_practice/utils/chart_helpers.py:27 -#: templates/my_practice/analytics.html:762 +#: templates/my_practice/analytics.html:20 +#: templates/my_practice/inquiry_list.html:129 msgid "Nov" msgstr "Nov" #: my_practice/utils/chart_helpers.py:28 -#: templates/my_practice/analytics.html:762 +#: templates/my_practice/analytics.html:20 +#: templates/my_practice/inquiry_list.html:129 msgid "Dec" msgstr "Dez" @@ -3281,7 +3308,7 @@ msgid "since %(start)s" msgstr "seit %(start)s" #: my_practice/utils/client_detail_builder.py:232 -#: my_practice/views/inquiry_views.py:79 +#: my_practice/views/inquiry_views.py:172 #: templates/my_practice/client_detail.html:257 msgid "Intake" msgstr "Aufnahme" @@ -3315,8 +3342,8 @@ msgid "Due today" msgstr "Heute fällig" #: my_practice/utils/dashboard_context_builder.py:147 -#: templates/my_practice/analytics.html:107 -#: templates/my_practice/analytics.html:735 +#: templates/my_practice/analytics.html:100 +#: templates/my_practice/analytics.html:675 msgid "Capacity" msgstr "Kapazität" @@ -3499,140 +3526,155 @@ msgstr "Die Zwei-Faktor-Anmeldung ist jetzt aktiv." msgid "Two-factor sign-in is now off." msgstr "Die Zwei-Faktor-Anmeldung ist jetzt ausgeschaltet." -#: my_practice/views/bank_import_views.py:80 +#: my_practice/views/bank_import_views.py:81 #, python-format msgid "%(count)s automatically matched" msgstr "%(count)s automatisch zugeordnet" -#: my_practice/views/bank_import_views.py:81 +#: my_practice/views/bank_import_views.py:82 #, python-format msgid "%(count)s require manual review" msgstr "%(count)s benötigen manuelle Prüfung" -#: my_practice/views/bank_import_views.py:85 +#: my_practice/views/bank_import_views.py:86 #, python-format msgid "%(count)s expenses detected automatically" msgstr "%(count)s Ausgaben automatisch erkannt" -#: my_practice/views/bank_import_views.py:87 +#: my_practice/views/bank_import_views.py:88 #, python-format msgid "%(count)s ignored" msgstr "%(count)s ignoriert" -#: my_practice/views/bank_import_views.py:90 +#: my_practice/views/bank_import_views.py:91 #, python-format msgid "Import complete: %(details)s." msgstr "Import abgeschlossen: %(details)s." -#: my_practice/views/bank_import_views.py:253 +#: my_practice/views/bank_import_views.py:254 msgid "No transaction selected." msgstr "Keine Transaktion ausgewählt." -#: my_practice/views/bank_import_views.py:341 +#: my_practice/views/bank_import_views.py:342 #, python-format msgid "Auto-ignored: invoice %(number)s already paid" msgstr "Auto-ignoriert: Rechnung %(number)s bereits bezahlt" -#: my_practice/views/bank_import_views.py:351 +#: my_practice/views/bank_import_views.py:352 #, python-format msgid "✅ %(count)s transaction with already-paid invoice ignored." msgid_plural "✅ %(count)s transactions with already-paid invoices ignored." msgstr[0] "✅ %(count)s Transaktion mit bereits bezahlter Rechnung ignoriert." msgstr[1] "✅ %(count)s Transaktionen mit bereits bezahlten Rechnungen ignoriert." -#: my_practice/views/bank_import_views.py:358 +#: my_practice/views/bank_import_views.py:359 msgid "No matching transactions to ignore." msgstr "Keine passenden Transaktionen zum Ignorieren gefunden." -#: my_practice/views/bank_import_views.py:374 +#: my_practice/views/bank_import_views.py:375 #, python-format msgid "%(count)s expense ignored." msgid_plural "%(count)s expenses ignored." msgstr[0] "%(count)s Ausgabe ignoriert." msgstr[1] "%(count)s Ausgaben ignoriert." -#: my_practice/views/bank_import_views.py:394 -#: my_practice/views/bank_import_views.py:706 +#: my_practice/views/bank_import_views.py:395 +#: my_practice/views/bank_import_views.py:712 #, python-format msgid "%(count)s transaction ignored." msgid_plural "%(count)s transactions ignored." msgstr[0] "%(count)s Transaktion ignoriert." msgstr[1] "%(count)s Transaktionen ignoriert." -#: my_practice/views/bank_import_views.py:408 +#: my_practice/views/bank_import_views.py:409 msgid "Transaction ignored." msgstr "Transaktion ignoriert." -#: my_practice/views/bank_import_views.py:432 +#: my_practice/views/bank_import_views.py:433 #, python-format msgid "Transaction linked to %(number)s (already paid)." msgstr "Transaktion mit %(number)s verknüpft (bereits bezahlt)." -#: my_practice/views/bank_import_views.py:436 +#: my_practice/views/bank_import_views.py:437 msgid "Transaction confirmed (invoice already paid)." msgstr "Transaktion bestätigt (Rechnung bereits bezahlt)." -#: my_practice/views/bank_import_views.py:442 +#: my_practice/views/bank_import_views.py:443 msgid "No invoice specified." msgstr "Keine Rechnung angegeben." -#: my_practice/views/bank_import_views.py:462 +#: my_practice/views/bank_import_views.py:463 #, python-format msgid "Transaction automatically linked to %(number)s and marked as paid." msgstr "Transaktion automatisch mit %(number)s verknüpft und als bezahlt markiert." -#: my_practice/views/bank_import_views.py:471 +#: my_practice/views/bank_import_views.py:472 msgid "Error processing form." msgstr "Fehler beim Verarbeiten des Formulars." -#: my_practice/views/bank_import_views.py:476 +#: my_practice/views/bank_import_views.py:477 msgid "Please select at least one invoice." msgstr "Bitte wählen Sie mindestens eine Rechnung aus." -#: my_practice/views/bank_import_views.py:507 +#: my_practice/views/bank_import_views.py:488 +#, python-format +msgid "Combined payment for: %(numbers)s" +msgstr "Sammelzahlung für: %(numbers)s" + +#: my_practice/views/bank_import_views.py:509 #, python-format msgid "Payment successfully assigned to invoice %(number)s." msgstr "Zahlung erfolgreich der Rechnung %(number)s zugeordnet." -#: my_practice/views/bank_import_views.py:514 +#: my_practice/views/bank_import_views.py:516 #, python-format msgid "Payment successfully assigned to %(count)s invoices: %(numbers)s" msgstr "Zahlung erfolgreich %(count)s Rechnungen zugeordnet: %(numbers)s" -#: my_practice/views/bank_import_views.py:535 +#: my_practice/views/bank_import_views.py:534 +#, python-format +msgid "Created automatically on confirming the payment of %(date)s" +msgstr "Automatisch angelegt beim Bestätigen der Zahlung vom %(date)s" + +#: my_practice/views/bank_import_views.py:539 #, python-format msgid "📌 Alias '%(name)s' for %(code)s saved." msgstr "📌 Alias '%(name)s' für %(code)s gespeichert." -#: my_practice/views/bank_import_views.py:542 +#: my_practice/views/bank_import_views.py:543 +#, python-format +msgid "Created during the bank import of %(date)s" +msgstr "Angelegt beim Bankimport vom %(date)s" + +#: my_practice/views/bank_import_views.py:548 #, python-format msgid "Alias '%(name)s' for %(code)s saved." msgstr "Alias '%(name)s' für %(code)s gespeichert." -#: my_practice/views/bank_import_views.py:623 +#: my_practice/views/bank_import_views.py:629 msgid "Please select at least one transaction." msgstr "Bitte wähle mindestens eine Transaktion aus." -#: my_practice/views/bank_import_views.py:636 +#: my_practice/views/bank_import_views.py:642 msgid "No transactions found." msgstr "Keine Transaktionen gefunden." -#: my_practice/views/bank_import_views.py:722 +#: my_practice/views/bank_import_views.py:728 msgid "Bank Import - Assign Expenses" msgstr "Bank Import - Ausgaben zuordnen" -#: my_practice/views/bank_import_views.py:727 +#: my_practice/views/bank_import_views.py:733 #, python-format msgid "%(count)s transaction successfully grouped into expense: %(amount)s €" msgid_plural "%(count)s transactions successfully grouped into expense: %(amount)s €" msgstr[0] "%(count)s Transaktion erfolgreich zu Ausgabe zusammengefasst: %(amount)s €" msgstr[1] "%(count)s Transaktionen erfolgreich zu Ausgabe zusammengefasst: %(amount)s €" -#: my_practice/views/bank_import_views.py:772 +#: my_practice/views/bank_import_views.py:778 msgid "Bank Import - Assign Withdrawals" msgstr "Bank Import - Entnahmen zuordnen" -#: my_practice/views/bank_import_views.py:777 +#: my_practice/views/bank_import_views.py:783 #, python-format msgid "%(count)s transaction successfully grouped into withdrawal: %(amount)s €" msgid_plural "%(count)s transactions successfully grouped into withdrawal: %(amount)s €" @@ -3659,7 +3701,7 @@ msgstr "OK" #: my_practice/views/billing_views.py:239 #: my_practice/views/billing_views.py:368 #: my_practice/views/calendar_views.py:268 -#: my_practice/views/invoice_views.py:568 +#: my_practice/views/invoice_views.py:569 msgid "No active practice found." msgstr "Keine aktive Praxis gefunden." @@ -4036,147 +4078,159 @@ msgstr "Ausgabe zusammengeführt: %(txns)s Buchung(en) und %(receipts)s Beleg(e) msgid "Link with transaction from %(date)s removed." msgstr "Verknüpfung mit Transaktion vom %(date)s aufgehoben." -#: my_practice/views/inquiry_views.py:120 +#: my_practice/views/inquiry_views.py:129 +msgid "Received" +msgstr "Eingegangen" + +#: my_practice/views/inquiry_views.py:130 +msgid "Responded" +msgstr "Rückmeldung" + +#: my_practice/views/inquiry_views.py:132 +msgid "Decision" +msgstr "Entscheidung" + +#: my_practice/views/inquiry_views.py:213 msgid "Received → response" msgstr "Eingang → Rückmeldung" -#: my_practice/views/inquiry_views.py:121 +#: my_practice/views/inquiry_views.py:214 msgid "Response → intro meeting" msgstr "Rückmeldung → Vorgespräch" -#: my_practice/views/inquiry_views.py:122 +#: my_practice/views/inquiry_views.py:215 msgid "Intro meeting → decision" msgstr "Vorgespräch → Entscheidung" -#: my_practice/views/inquiry_views.py:123 +#: my_practice/views/inquiry_views.py:216 msgid "Decision → onboarded" msgstr "Entscheidung → Aufgenommen" -#: my_practice/views/inquiry_views.py:242 +#: my_practice/views/inquiry_views.py:315 msgid "Waitlist / intake" msgstr "Warteliste / Aufnahme" -#: my_practice/views/inquiry_views.py:244 +#: my_practice/views/inquiry_views.py:317 msgid "Closed" msgstr "Geschlossen" -#: my_practice/views/inquiry_views.py:274 +#: my_practice/views/inquiry_views.py:347 #, python-brace-format msgid "Inquiry from {obj.full_name} recorded." msgstr "Anfrage von {obj.full_name} erfasst." -#: my_practice/views/inquiry_views.py:284 +#: my_practice/views/inquiry_views.py:357 #, python-brace-format msgid "Inquiry from {obj.full_name} saved." msgstr "Anfrage von {obj.full_name} gespeichert." -#: my_practice/views/inquiry_views.py:317 +#: my_practice/views/inquiry_views.py:390 #, python-brace-format msgid "Inquiry from {obj.full_name} deleted." msgstr "Anfrage von {obj.full_name} gelöscht." -#: my_practice/views/inquiry_views.py:327 +#: my_practice/views/inquiry_views.py:400 msgid "Marketing period recorded." msgstr "Marketing-Zeitraum erfasst." -#: my_practice/views/inquiry_views.py:337 +#: my_practice/views/inquiry_views.py:410 msgid "Marketing period saved." msgstr "Marketing-Zeitraum gespeichert." -#: my_practice/views/inquiry_views.py:347 +#: my_practice/views/inquiry_views.py:420 msgid "Marketing period deleted." msgstr "Marketing-Zeitraum gelöscht." -#: my_practice/views/inquiry_views.py:407 +#: my_practice/views/inquiry_views.py:480 #, python-format msgid "Client %(name)s (%(code)s) created successfully." msgstr "Klient:in %(name)s (%(code)s) wurde erfolgreich angelegt." -#: my_practice/views/invoice_views.py:235 +#: my_practice/views/invoice_views.py:236 #, python-format msgid "Error creating invoice: %(error)s" msgstr "Fehler beim Erstellen der Rechnung: %(error)s" -#: my_practice/views/invoice_views.py:241 +#: my_practice/views/invoice_views.py:242 #, python-format msgid "Invoice %(num)s created successfully!" msgstr "Rechnung %(num)s erfolgreich erstellt!" -#: my_practice/views/invoice_views.py:251 +#: my_practice/views/invoice_views.py:252 #, python-format msgid "Item %(n)s: %(errors)s" msgstr "Position %(n)s: %(errors)s" -#: my_practice/views/invoice_views.py:256 +#: my_practice/views/invoice_views.py:257 #, python-format msgid "Formset errors: %(errors)s" msgstr "Fehler im Formset: %(errors)s" -#: my_practice/views/invoice_views.py:305 +#: my_practice/views/invoice_views.py:306 #, python-brace-format msgid "Invoice {obj.invoice_number} updated successfully!" msgstr "Rechnung {obj.invoice_number} erfolgreich aktualisiert!" -#: my_practice/views/invoice_views.py:381 +#: my_practice/views/invoice_views.py:382 #, python-format msgid "Error updating invoice: %(error)s" msgstr "Fehler beim Aktualisieren der Rechnung: %(error)s" -#: my_practice/views/invoice_views.py:397 +#: my_practice/views/invoice_views.py:398 #, python-format msgid "Item %(n)s - %(field)s: %(error)s" msgstr "Position %(n)s – %(field)s: %(error)s" -#: my_practice/views/invoice_views.py:402 +#: my_practice/views/invoice_views.py:403 #, python-format msgid "Formset: %(error)s" msgstr "Formset: %(error)s" -#: my_practice/views/invoice_views.py:411 +#: my_practice/views/invoice_views.py:412 #, python-format msgid "%(label)s: %(error)s" msgstr "%(label)s: %(error)s" -#: my_practice/views/invoice_views.py:424 +#: my_practice/views/invoice_views.py:425 msgid "Please correct the errors in the form." msgstr "Bitte korrigieren Sie die Fehler im Formular." -#: my_practice/views/invoice_views.py:455 +#: my_practice/views/invoice_views.py:456 #, python-format msgid "Invoice %(num)s for %(code)s was deleted successfully." msgstr "Rechnung %(num)s für %(code)s wurde erfolgreich gelöscht." -#: my_practice/views/invoice_views.py:483 +#: my_practice/views/invoice_views.py:484 msgid "Only a sent invoice can be cancelled and corrected." msgstr "Nur eine versendete Rechnung kann storniert und korrigiert werden." -#: my_practice/views/invoice_views.py:495 +#: my_practice/views/invoice_views.py:496 #, python-format msgid "Corrects invoice %(number)s." msgstr "Korrigiert Rechnung %(number)s." -#: my_practice/views/invoice_views.py:505 +#: my_practice/views/invoice_views.py:506 #, python-format msgid "Invoice %(old)s was cancelled. %(new)s is an editable copy — correct it and send it as usual." msgstr "Rechnung %(old)s wurde storniert. %(new)s ist eine bearbeitbare Kopie – korrigieren Sie sie und versenden Sie sie wie gewohnt." -#: my_practice/views/invoice_views.py:524 -#: my_practice/views/invoice_views.py:583 +#: my_practice/views/invoice_views.py:525 +#: my_practice/views/invoice_views.py:584 msgid "No sessions specified." msgstr "Keine Sitzungen angegeben." -#: my_practice/views/invoice_views.py:548 +#: my_practice/views/invoice_views.py:549 #, python-format msgid "%(count)s session added to %(invoice)s." msgid_plural "%(count)s sessions added to %(invoice)s." msgstr[0] "%(count)s Sitzung zu %(invoice)s hinzugefügt." msgstr[1] "%(count)s Sitzungen zu %(invoice)s hinzugefügt." -#: my_practice/views/invoice_views.py:555 +#: my_practice/views/invoice_views.py:556 msgid "No new sessions added (already billed?)." msgstr "Keine neuen Sitzungen hinzugefügt (bereits abgerechnet?)." -#: my_practice/views/invoice_views.py:607 +#: my_practice/views/invoice_views.py:608 msgid "Invoice {} with {} session created." msgid_plural "Invoice {} with {} sessions created." msgstr[0] "Rechnung {} mit {} Sitzung erstellt." @@ -4515,31 +4569,35 @@ msgstr "Praxen verwalten" msgid "Two-factor sign-in" msgstr "Zwei-Faktor-Anmeldung" -#: templates/base.html:112 +#: templates/base.html:104 +msgid "Sign out" +msgstr "Abmelden" + +#: templates/base.html:117 msgid "Toggle dark mode" msgstr "Dark Mode umschalten" -#: templates/base.html:115 +#: templates/base.html:120 msgid "Click to hide sensitive data" msgstr "Klicken zum Verbergen sensibler Daten" -#: templates/base.html:127 templates/my_practice/bank_expense_review.html:132 +#: templates/base.html:132 templates/my_practice/bank_expense_review.html:132 #: templates/my_practice/bank_withdrawal_review.html:112 #: templates/my_practice/checklist.html:16 #: templates/my_practice/client_detail.html:40 msgid "Overview" msgstr "Überblick" -#: templates/base.html:130 templates/my_practice/focus_queue.html:4 +#: templates/base.html:135 templates/my_practice/focus_queue.html:4 #: templates/my_practice/focus_queue.html:7 msgid "Focus Queue" msgstr "Im Fokus" -#: templates/base.html:146 +#: templates/base.html:151 msgid "available" msgstr "verfügbar" -#: templates/base.html:148 templates/includes/command_palette.html:86 +#: templates/base.html:153 templates/includes/command_palette.html:86 msgid "Close" msgstr "Schließen" @@ -4607,8 +4665,9 @@ msgid "hrs" msgstr "Std" #: templates/includes/capacity_monitoring_widget_content.html:27 -#: templates/my_practice/analytics.html:101 -#: templates/my_practice/analytics.html:185 +#: templates/my_practice/analytics.html:94 +#: templates/my_practice/analytics.html:181 +#: templates/my_practice/analytics.html:219 #: templates/my_practice/tax_quarter_overview.html:78 msgid "Revenue" msgstr "Umsatz" @@ -4697,17 +4756,18 @@ msgid "Bank expenses" msgstr "Bank-Ausgaben" #: templates/includes/command_palette.html:46 -#: templates/my_practice/analytics.html:142 -#: templates/my_practice/analytics.html:187 +#: templates/my_practice/analytics.html:135 +#: templates/my_practice/analytics.html:183 #: templates/my_practice/bank_review.html:24 #: templates/my_practice/withdrawal_list.html:48 msgid "Withdrawals" msgstr "Entnahmen" #: templates/includes/command_palette.html:47 -#: templates/my_practice/analytics.html:110 -#: templates/my_practice/analytics.html:139 -#: templates/my_practice/analytics.html:186 +#: templates/my_practice/analytics.html:103 +#: templates/my_practice/analytics.html:132 +#: templates/my_practice/analytics.html:182 +#: templates/my_practice/analytics.html:849 #: templates/my_practice/bank_review.html:19 #: templates/my_practice/bank_withdrawal_review.html:110 #: templates/my_practice/expense_list.html:66 @@ -4718,7 +4778,7 @@ msgstr "Ausgaben" #: templates/includes/command_palette.html:48 #: templates/my_practice/analytics.html:6 #: templates/my_practice/analytics.html:9 -#: templates/my_practice/inquiry_list.html:36 +#: templates/my_practice/inquiry_list.html:41 #: templates/my_practice/withdrawal_list.html:16 msgid "Analytics" msgstr "Analysen" @@ -4752,7 +4812,7 @@ msgid "Calendar approval" msgstr "Kalender-Genehmigung" #: templates/includes/command_palette.html:55 -#: templates/my_practice/analytics.html:665 +#: templates/my_practice/analytics.html:615 #: templates/my_practice/time_off_list.html:4 #: templates/my_practice/time_off_list.html:6 msgid "Time off" @@ -4775,8 +4835,8 @@ msgstr "E-Mail-Textbausteine" #: templates/my_practice/client_detail.html:592 #: templates/my_practice/client_detail.html:638 #: templates/my_practice/expense_list.html:86 -#: templates/my_practice/inquiry_list.html:186 -#: templates/my_practice/inquiry_list.html:234 +#: templates/my_practice/inquiry_list.html:206 +#: templates/my_practice/inquiry_list.html:254 #: templates/my_practice/invoice_list.html:171 #: templates/my_practice/monthly_billing_overview.html:54 #: templates/my_practice/tag_list.html:29 @@ -4790,7 +4850,7 @@ msgstr "Aktionen" #: templates/includes/command_palette.html:68 #: templates/my_practice/inquiry_form.html:5 #: templates/my_practice/inquiry_form.html:8 -#: templates/my_practice/inquiry_list.html:16 +#: templates/my_practice/inquiry_list.html:21 msgid "New inquiry" msgstr "Neue Anfrage" @@ -4870,45 +4930,45 @@ msgstr "Aktuell ist nichts im Fokus." msgid "Create a task" msgstr "Aufgabe erstellen" -#: templates/includes/focus_queue_row.html:15 +#: templates/includes/focus_queue_row.html:14 msgid "Mark as not done" msgstr "Als nicht erledigt markieren" -#: templates/includes/focus_queue_row.html:35 +#: templates/includes/focus_queue_row.html:34 msgid "Invoice date, session date, or when this task was added" msgstr "Rechnungsdatum, Sitzungsdatum oder wann diese Aufgabe hinzugefügt wurde" -#: templates/includes/focus_queue_row.html:41 +#: templates/includes/focus_queue_row.html:40 msgid "overdue!" msgstr "überfällig!" -#: templates/includes/focus_queue_row.html:49 +#: templates/includes/focus_queue_row.html:48 msgid "Set due today — bumps this task to the top of the queue" msgstr "Auf heute fällig setzen – befördert diese Aufgabe an die Spitze der Warteschlange" -#: templates/includes/focus_queue_row.html:49 +#: templates/includes/focus_queue_row.html:48 msgid "Today" msgstr "Heute" -#: templates/includes/focus_queue_row.html:51 +#: templates/includes/focus_queue_row.html:50 msgid "Snooze 1 day" msgstr "1 Tag zurückstellen" -#: templates/includes/focus_queue_row.html:52 +#: templates/includes/focus_queue_row.html:51 msgid "Snooze 3 days" msgstr "3 Tage zurückstellen" -#: templates/includes/focus_queue_row.html:53 +#: templates/includes/focus_queue_row.html:52 msgid "Snooze 1 week" msgstr "1 Woche zurückstellen" -#: templates/includes/focus_queue_row.html:56 +#: templates/includes/focus_queue_row.html:55 #: templates/my_practice/client_detail.html:437 #: templates/my_practice/client_detail.html:456 #: templates/my_practice/expense_list.html:128 -#: templates/my_practice/inquiry_list.html:26 -#: templates/my_practice/inquiry_list.html:206 -#: templates/my_practice/inquiry_list.html:254 +#: templates/my_practice/inquiry_list.html:31 +#: templates/my_practice/inquiry_list.html:226 +#: templates/my_practice/inquiry_list.html:274 #: templates/my_practice/invoice_detail.html:196 #: templates/my_practice/practice_management.html:44 #: templates/my_practice/tag_list.html:63 @@ -5004,12 +5064,12 @@ msgstr "Sitzungen diese Woche" msgid "No sessions this week." msgstr "Keine Sitzungen diese Woche." -#: templates/includes/weekly_focus_widget_content.html:43 +#: templates/includes/weekly_focus_widget_content.html:42 #: templates/my_practice/calendar_approval_queue.html:38 msgid "Mark as done" msgstr "Als erledigt markieren" -#: templates/includes/weekly_focus_widget_content.html:57 +#: templates/includes/weekly_focus_widget_content.html:56 #, python-format msgid "Nothing due today. Set a due date from the focus queue." msgstr "Nichts ist heute fällig. Setze ein Fälligkeitsdatum im Fokus." @@ -5063,141 +5123,138 @@ msgid "Revenue, Clients, Capacity & Expenses" msgstr "Umsatz, Klienten, Kapazität & Ausgaben" #: templates/my_practice/analytics.html:15 -#: templates/my_practice/analytics.html:272 +#: templates/my_practice/analytics.html:238 msgid "No data available" msgstr "Keine Daten verfügbar" -#: templates/my_practice/analytics.html:16 -msgid "No data in selected period" -msgstr "Keine Daten im ausgewählten Zeitraum" - -#: templates/my_practice/analytics.html:17 -msgid "No valid data available" -msgstr "Keine gültigen Daten verfügbar" - -#: templates/my_practice/analytics.html:45 +#: templates/my_practice/analytics.html:38 #, python-format msgid "All years (%(year)s–today)" msgstr "Alle Jahre (%(year)s–heute)" -#: templates/my_practice/analytics.html:46 +#: templates/my_practice/analytics.html:39 msgid "Last year" msgstr "Letztes Jahr" -#: templates/my_practice/analytics.html:47 +#: templates/my_practice/analytics.html:40 msgid "Last quarter" msgstr "Letztes Quartal" -#: templates/my_practice/analytics.html:48 +#: templates/my_practice/analytics.html:41 msgid "Last month" msgstr "Letzter Monat" -#: templates/my_practice/analytics.html:49 +#: templates/my_practice/analytics.html:42 msgid "Custom" msgstr "Benutzerdefiniert" -#: templates/my_practice/analytics.html:69 +#: templates/my_practice/analytics.html:62 msgid "Apply" msgstr "Anwenden" -#: templates/my_practice/analytics.html:73 +#: templates/my_practice/analytics.html:66 #: templates/my_practice/invoice_list.html:119 msgid "Reset" msgstr "Zurücksetzen" -#: templates/my_practice/analytics.html:117 +#: templates/my_practice/analytics.html:110 msgid "Revenue & Profit" msgstr "Umsatz & Gewinn" -#: templates/my_practice/analytics.html:122 +#: templates/my_practice/analytics.html:115 msgid "Detailed Revenue Report" msgstr "Detaillierter Umsatz-Report" -#: templates/my_practice/analytics.html:128 +#: templates/my_practice/analytics.html:121 msgid "Profit (Revenue - Expenses)" msgstr "Gewinn (Umsatz - Ausgaben)" -#: templates/my_practice/analytics.html:130 +#: templates/my_practice/analytics.html:123 #, python-format msgid "Business profit %(start_year)s–today · Cumulative development" msgstr "Geschäftsgewinn %(start_year)s–heute · Kumulative Entwicklung" -#: templates/my_practice/analytics.html:137 -#: templates/my_practice/analytics.html:662 +#: templates/my_practice/analytics.html:130 +#: templates/my_practice/analytics.html:612 #: templates/my_practice/expense_form.html:177 #: templates/my_practice/invoice_list.html:99 msgid "Year" msgstr "Jahr" -#: templates/my_practice/analytics.html:138 +#: templates/my_practice/analytics.html:131 msgid "Income" msgstr "Einnahmen" -#: templates/my_practice/analytics.html:140 +#: templates/my_practice/analytics.html:133 #: templates/my_practice/tax_year_summary.html:45 msgid "Profit" msgstr "Gewinn" -#: templates/my_practice/analytics.html:141 +#: templates/my_practice/analytics.html:134 msgid "Cumulative" msgstr "Kumulativ" -#: templates/my_practice/analytics.html:167 +#: templates/my_practice/analytics.html:160 msgid "Revenue, Expenses & Withdrawals" msgstr "Umsatz, Ausgaben & Entnahmen" -#: templates/my_practice/analytics.html:169 +#: templates/my_practice/analytics.html:162 msgid "Complete financial overview" msgstr "Vollständige Finanzübersicht" -#: templates/my_practice/analytics.html:211 +#: templates/my_practice/analytics.html:191 msgid "Revenue Trend (Monthly)" msgstr "Umsatz-Trend (Monatlich)" -#: templates/my_practice/analytics.html:213 +#: templates/my_practice/analytics.html:193 msgid "Monthly revenue development · growth visualized" msgstr "Entwicklung der monatlichen Umsätze · Wachstum visualisiert" -#: templates/my_practice/analytics.html:223 +#: templates/my_practice/analytics.html:203 #, python-format msgid "Monthly revenue · %(months)s months · Max: %(max)s" msgstr "Monatlicher Umsatz · %(months)s Monate · Max: %(max)s" -#: templates/my_practice/analytics.html:260 +#: templates/my_practice/analytics.html:218 +#: templates/my_practice/analytics.html:670 +msgid "Trend" +msgstr "Trend" + +#: templates/my_practice/analytics.html:226 msgid "Peak Months" msgstr "Stärkste Monate" -#: templates/my_practice/analytics.html:292 +#: templates/my_practice/analytics.html:258 msgid "Payment Delay (last 24 months)" msgstr "Zahlungsverzug (letzte 24 Monate)" -#: templates/my_practice/analytics.html:294 +#: templates/my_practice/analytics.html:260 msgid "Average days from invoice date to payment received" msgstr "Durchschnittliche Tage von Rechnungsdatum bis Zahlungseingang" -#: templates/my_practice/analytics.html:328 +#: templates/my_practice/analytics.html:278 msgid "days" msgstr "Tage" -#: templates/my_practice/analytics.html:339 +#: templates/my_practice/analytics.html:289 #: templates/my_practice/client_list_cards.html:6 msgid "Client overview" msgstr "Klientenübersicht" -#: templates/my_practice/analytics.html:343 +#: templates/my_practice/analytics.html:293 msgid "Top 10 Clients by Revenue" msgstr "Top 10 Klienten nach Umsatz" -#: templates/my_practice/analytics.html:349 +#: templates/my_practice/analytics.html:299 msgid "Rank" msgstr "Rang" -#: templates/my_practice/analytics.html:352 -#: templates/my_practice/analytics.html:595 +#: templates/my_practice/analytics.html:302 +#: templates/my_practice/analytics.html:545 msgid "Hours" msgstr "Stunden" -#: templates/my_practice/analytics.html:353 +#: templates/my_practice/analytics.html:303 #: templates/my_practice/client_detail.html:237 #: templates/my_practice/revenue_report.html:26 #: templates/my_practice/tax_year_summary.html:37 @@ -5205,295 +5262,296 @@ msgstr "Stunden" msgid "Total revenue" msgstr "Gesamtumsatz" -#: templates/my_practice/analytics.html:374 +#: templates/my_practice/analytics.html:324 msgid "No revenue data available" msgstr "Keine Umsatzdaten verfügbar" -#: templates/my_practice/analytics.html:381 +#: templates/my_practice/analytics.html:331 #, python-format msgid "Client Details (%(label)s)" msgstr "Klienten-Details (%(label)s)" -#: templates/my_practice/analytics.html:387 +#: templates/my_practice/analytics.html:337 msgid "Show dormant clients" msgstr "Ruhende Klienten anzeigen" -#: templates/my_practice/analytics.html:398 +#: templates/my_practice/analytics.html:348 msgid "Sessions (period)" msgstr "Sitzungen (Zeitraum)" -#: templates/my_practice/analytics.html:399 +#: templates/my_practice/analytics.html:349 msgid "Total Sessions" msgstr "Gesamt-Sitzungen" -#: templates/my_practice/analytics.html:415 +#: templates/my_practice/analytics.html:365 msgid "Probatoric" msgstr "Probatorik" -#: templates/my_practice/analytics.html:419 +#: templates/my_practice/analytics.html:369 msgid "Established" msgstr "Etabliert" -#: templates/my_practice/analytics.html:421 +#: templates/my_practice/analytics.html:371 msgid "Dormant" msgstr "Ruhend" -#: templates/my_practice/analytics.html:428 +#: templates/my_practice/analytics.html:378 #: templates/my_practice/client_detail.html:230 msgid "💻 Online" msgstr "💻 Online" -#: templates/my_practice/analytics.html:430 +#: templates/my_practice/analytics.html:380 msgid "In-person" msgstr "Präsenz" -#: templates/my_practice/analytics.html:440 +#: templates/my_practice/analytics.html:390 msgid "No client data for this period." msgstr "Keine Klientendaten für diesen Zeitraum." -#: templates/my_practice/analytics.html:469 +#: templates/my_practice/analytics.html:419 msgid "Session Type Distribution" msgstr "Sitzungstypen-Verteilung" -#: templates/my_practice/analytics.html:476 +#: templates/my_practice/analytics.html:426 msgid "Total sessions" msgstr "Gesamt Sitzungen" -#: templates/my_practice/analytics.html:495 +#: templates/my_practice/analytics.html:445 msgid "No session data available" msgstr "Keine Sitzungsdaten verfügbar" -#: templates/my_practice/analytics.html:507 +#: templates/my_practice/analytics.html:457 msgid "Capacity & Utilisation" msgstr "Kapazität & Auslastung" -#: templates/my_practice/analytics.html:513 +#: templates/my_practice/analytics.html:463 msgid "Key Insights" msgstr "Wichtige Erkenntnisse" -#: templates/my_practice/analytics.html:526 +#: templates/my_practice/analytics.html:476 msgid "Active Clients" msgstr "Aktive Klienten" -#: templates/my_practice/analytics.html:531 +#: templates/my_practice/analytics.html:481 msgid "Booked Sessions" msgstr "Gebuchte Sitzungen" -#: templates/my_practice/analytics.html:536 +#: templates/my_practice/analytics.html:486 msgid "Capacity Used" msgstr "Kapazität genutzt" -#: templates/my_practice/analytics.html:544 +#: templates/my_practice/analytics.html:494 #, python-format msgid "Bookings until %(date)s" msgstr "Buchungen bis %(date)s" -#: templates/my_practice/analytics.html:551 +#: templates/my_practice/analytics.html:501 msgid "Days Off" msgstr "Freie Tage" -#: templates/my_practice/analytics.html:557 +#: templates/my_practice/analytics.html:507 msgid "Capacity Analysis" msgstr "Kapazitätsanalyse" -#: templates/my_practice/analytics.html:557 +#: templates/my_practice/analytics.html:507 #: templates/my_practice/checklist.html:68 #, python-format msgid "until %(date)s" msgstr "bis %(date)s" -#: templates/my_practice/analytics.html:560 +#: templates/my_practice/analytics.html:510 #: templates/my_practice/tag_confirm_delete.html:24 msgid "Note:" msgstr "Hinweis:" -#: templates/my_practice/analytics.html:560 +#: templates/my_practice/analytics.html:510 #, python-format msgid "For future-oriented periods only the period until %(date)s (2 weeks from today) is considered, as most clients book at short notice." msgstr "Für zukunftsgerichtete Zeiträume wird nur der Zeitraum bis %(date)s (2 Wochen ab heute) berücksichtigt, da die meisten Klienten kurzfristig buchen." -#: templates/my_practice/analytics.html:567 +#: templates/my_practice/analytics.html:517 msgid "Available Hours" msgstr "Verfügbare Stunden" -#: templates/my_practice/analytics.html:571 +#: templates/my_practice/analytics.html:521 msgid "Booked Hours" msgstr "Gebuchte Stunden" -#: templates/my_practice/analytics.html:575 +#: templates/my_practice/analytics.html:525 msgid "Free Capacity" msgstr "Freie Kapazität" -#: templates/my_practice/analytics.html:579 +#: templates/my_practice/analytics.html:529 msgid "Working Days" msgstr "Arbeitstage" -#: templates/my_practice/analytics.html:587 +#: templates/my_practice/analytics.html:537 msgid "4-Quarter Trends" msgstr "4-Quartals-Trends" -#: templates/my_practice/analytics.html:592 +#: templates/my_practice/analytics.html:542 #: templates/my_practice/tax_quarter_overview.html:76 msgid "Quarter" msgstr "Quartal" -#: templates/my_practice/analytics.html:593 +#: templates/my_practice/analytics.html:543 #, python-format msgid "Capacity %%" msgstr "Kapazität %%" -#: templates/my_practice/analytics.html:616 +#: templates/my_practice/analytics.html:566 #, python-format msgid "Time off in %(label)s" msgstr "Urlaubszeiten in %(label)s" -#: templates/my_practice/analytics.html:622 +#: templates/my_practice/analytics.html:572 msgid "Days" msgstr "Tage" -#: templates/my_practice/analytics.html:634 +#: templates/my_practice/analytics.html:584 #, python-format msgid "Time off %(label)s" msgstr "Urlaub %(label)s" -#: templates/my_practice/analytics.html:636 +#: templates/my_practice/analytics.html:586 msgid "Days off in selected period" msgstr "Urlaubstage im ausgewählten Zeitraum" -#: templates/my_practice/analytics.html:641 +#: templates/my_practice/analytics.html:591 msgid "Total days" msgstr "Tage gesamt" -#: templates/my_practice/analytics.html:645 +#: templates/my_practice/analytics.html:595 msgid "Weeks" msgstr "Wochen" -#: templates/my_practice/analytics.html:649 +#: templates/my_practice/analytics.html:599 msgid "Working days off" msgstr "Arbeitstage frei" -#: templates/my_practice/analytics.html:657 +#: templates/my_practice/analytics.html:607 msgid "Time Off by Year" msgstr "Urlaub nach Jahren" -#: templates/my_practice/analytics.html:663 +#: templates/my_practice/analytics.html:613 msgid "Workdays" msgstr "Arbeitstage" -#: templates/my_practice/analytics.html:664 +#: templates/my_practice/analytics.html:614 msgid "Wk." msgstr "Wo." -#: templates/my_practice/analytics.html:666 +#: templates/my_practice/analytics.html:616 msgid "Training" msgstr "Fortbildung" -#: templates/my_practice/analytics.html:667 +#: templates/my_practice/analytics.html:617 msgid "Sick" msgstr "Krank" -#: templates/my_practice/analytics.html:689 +#: templates/my_practice/analytics.html:639 msgid "Capacity Utilisation Over Time" msgstr "Kapazitätsauslastung über Zeit" -#: templates/my_practice/analytics.html:641 +#: templates/my_practice/analytics.html:642 #, python-format msgid "Monthly utilisation in %% of your weekly target:" msgstr "Monatliche Auslastung in %% Ihrer Wochenzielstunden:" -#: templates/my_practice/analytics.html:642 +#: templates/my_practice/analytics.html:643 #, python-format msgid "%(hours)s h/week from %(start)s" msgstr "%(hours)s h/Woche ab %(start)s" -#: templates/my_practice/analytics.html:644 +#: templates/my_practice/analytics.html:645 msgid "No weekly target set yet." msgstr "Noch keine Wochenzielstunden festgelegt." -#: templates/my_practice/analytics.html:645 +#: templates/my_practice/analytics.html:646 msgid "Set target hours in the practice settings" msgstr "Zielstunden in den Praxiseinstellungen festlegen" -#: templates/my_practice/analytics.html:733 +#: templates/my_practice/analytics.html:671 +#: templates/my_practice/analytics.html:673 msgid "Utilisation" msgstr "Auslastung" -#: templates/my_practice/analytics.html:734 +#: templates/my_practice/analytics.html:674 msgid "Booked" msgstr "Gebucht" -#: templates/my_practice/analytics.html:745 +#: templates/my_practice/analytics.html:685 msgid "Year Comparison – Hours per Month" msgstr "Jahresvergleich – Stunden pro Monat" -#: templates/my_practice/analytics.html:747 +#: templates/my_practice/analytics.html:687 msgid "Therapy hours per calendar month (last 4 years + average)" msgstr "Therapeutenstunden pro Kalendermonat (letzte 4 Jahre + Durchschnitt)" -#: templates/my_practice/analytics.html:831 +#: templates/my_practice/analytics.html:710 msgid "Avg" msgstr "Ø" -#: templates/my_practice/analytics.html:854 +#: templates/my_practice/analytics.html:726 msgid "Seasonality" msgstr "Saisonalität" -#: templates/my_practice/analytics.html:856 +#: templates/my_practice/analytics.html:728 msgid "Average utilisation per calendar month (Ø over all years, incl. time off)" msgstr "Durchschnittliche Auslastung pro Kalendermonat (Ø über alle Jahre, inkl. Urlaub)" -#: templates/my_practice/analytics.html:878 +#: templates/my_practice/analytics.html:750 msgid "Cancellation Rate" msgstr "Ausfallquote" -#: templates/my_practice/analytics.html:880 +#: templates/my_practice/analytics.html:752 #, python-format msgid "Cancelled sessions in %% of all sessions per month" msgstr "Abgesagte Sitzungen in %% aller Sitzungen pro Monat" -#: templates/my_practice/analytics.html:881 +#: templates/my_practice/analytics.html:753 #, python-format msgid "since %(start)s, not counting cancellations during your own time off" msgstr "seit %(start)s, ohne Absagen während Ihrer eigenen Abwesenheiten" -#: templates/my_practice/analytics.html:916 +#: templates/my_practice/analytics.html:771 msgid "Cancellation rate" msgstr "Ausfallquote" -#: templates/my_practice/analytics.html:928 +#: templates/my_practice/analytics.html:783 msgid "Expense Overview" msgstr "Ausgaben-Übersicht" -#: templates/my_practice/analytics.html:933 +#: templates/my_practice/analytics.html:788 msgid "Manage Expenses" msgstr "Ausgaben verwalten" -#: templates/my_practice/analytics.html:936 +#: templates/my_practice/analytics.html:791 msgid "Manage Withdrawals" msgstr "Entnahmen verwalten" -#: templates/my_practice/analytics.html:942 +#: templates/my_practice/analytics.html:797 msgid "Expenses by Category" msgstr "Ausgaben nach Kategorie" -#: templates/my_practice/analytics.html:949 +#: templates/my_practice/analytics.html:804 msgid "Total Expenses" msgstr "Gesamtausgaben" -#: templates/my_practice/analytics.html:968 +#: templates/my_practice/analytics.html:823 msgid "No expense data available" msgstr "Keine Ausgabendaten verfügbar" -#: templates/my_practice/analytics.html:974 +#: templates/my_practice/analytics.html:829 msgid "Expense Trends" msgstr "Ausgaben-Trends" -#: templates/my_practice/analytics.html:976 +#: templates/my_practice/analytics.html:831 #, python-format msgid "Annual operating expenses %(start_year)s–today" msgstr "Jährliche Betriebsausgaben %(start_year)s–heute" -#: templates/my_practice/analytics.html:1081 +#: templates/my_practice/analytics.html:921 #: templates/my_practice/checklist.html:38 msgid "Back to overview" msgstr "Zur Übersicht" @@ -5708,10 +5766,6 @@ msgstr "wurde bereits als bezahlt markiert" msgid "This transaction can be ignored" msgstr "Diese Transaktion kann ignoriert werden" -#: templates/my_practice/bank_review.html:240 -msgid "Capital contribution from private account" -msgstr "Kapitaleinlage vom privaten Konto" - #: templates/my_practice/bank_review.html:242 msgid "This transaction was transferred from the stored private bank account." msgstr "Diese Transaktion wurde vom hinterlegten privaten Bankkonto überwiesen." @@ -6646,7 +6700,7 @@ msgid "Supervision topic or question…" msgstr "Supervisionsthema oder -frage…" #: templates/my_practice/client_detail.html:380 -#: templates/my_practice/inquiry_list.html:30 +#: templates/my_practice/inquiry_list.html:35 msgid "Add" msgstr "Hinzufügen" @@ -6944,9 +6998,9 @@ msgstr "Keine E-Mail-Adresse hinterlegt — es wird keine Benachrichtigung gesen #: templates/my_practice/client_list_cards.html:124 #: templates/my_practice/expense_form.html:103 #: templates/my_practice/expense_list.html:129 -#: templates/my_practice/inquiry_list.html:27 -#: templates/my_practice/inquiry_list.html:210 -#: templates/my_practice/inquiry_list.html:258 +#: templates/my_practice/inquiry_list.html:32 +#: templates/my_practice/inquiry_list.html:230 +#: templates/my_practice/inquiry_list.html:278 #: templates/my_practice/invoice_detail.html:217 #: templates/my_practice/invoice_edit.html:90 #: templates/my_practice/invoice_form.html:81 @@ -7451,85 +7505,96 @@ msgstr "Vorlage:" msgid "Available codes:" msgstr "Verfügbare Kürzel:" -#: templates/my_practice/inquiry_list.html:10 +#: templates/my_practice/inquiry_list.html:15 msgid "Prospective clients & inquiry management" msgstr "Interessent:innen & Anfrageverwaltung" -#: templates/my_practice/inquiry_list.html:21 +#: templates/my_practice/inquiry_list.html:26 msgid "Marketing periods:" msgstr "Marketing-Zeiträume:" -#: templates/my_practice/inquiry_list.html:38 +#: templates/my_practice/inquiry_list.html:43 msgid "total" msgstr "gesamt" -#: templates/my_practice/inquiry_list.html:40 +#: templates/my_practice/inquiry_list.html:45 msgid "closed" msgstr "geschlossen" -#: templates/my_practice/inquiry_list.html:61 +#: templates/my_practice/inquiry_list.html:66 #, python-format msgid "%(n)s closed (Declined / No match / Unreachable)" msgstr "%(n)s geschlossen (Abgelehnt / Kein Match / Nicht erreichbar)" -#: templates/my_practice/inquiry_list.html:67 +#: templates/my_practice/inquiry_list.html:72 msgid "Avg. wait (working days)" msgstr "Ø Wartezeit (Werktage)" -#: templates/my_practice/inquiry_list.html:74 +#: templates/my_practice/inquiry_list.html:79 #, python-format msgid "%(avg)s working days (n=%(n)s)" msgstr "%(avg)s Werktage (n=%(n)s)" -#: templates/my_practice/inquiry_list.html:85 +#: templates/my_practice/inquiry_list.html:90 msgid "Sources" msgstr "Quellen" -#: templates/my_practice/inquiry_list.html:120 +#: templates/my_practice/inquiry_list.html:124 msgid "Inquiries per month (last 12 months)" msgstr "Anfragen pro Monat (letzte 12 Monate)" -#: templates/my_practice/inquiry_list.html:142 +#: templates/my_practice/inquiry_list.html:136 +msgid "Open inquiries: days since last step" +msgstr "Offene Anfragen: Tage seit dem letzten Schritt" + +#: templates/my_practice/inquiry_list.html:146 +#, python-format +msgid "%(days)s day" +msgid_plural "%(days)s days" +msgstr[0] "%(days)s Tag" +msgstr[1] "%(days)s Tage" + +#: templates/my_practice/inquiry_list.html:162 msgid "All statuses" msgstr "Alle Status" -#: templates/my_practice/inquiry_list.html:148 +#: templates/my_practice/inquiry_list.html:168 msgid "All sources" msgstr "Alle Quellen" -#: templates/my_practice/inquiry_list.html:154 +#: templates/my_practice/inquiry_list.html:174 msgid "Clear filters" msgstr "Filter löschen" -#: templates/my_practice/inquiry_list.html:160 +#: templates/my_practice/inquiry_list.html:180 msgid "Hide closed" msgstr "Geschlossene ausblenden" -#: templates/my_practice/inquiry_list.html:162 +#: templates/my_practice/inquiry_list.html:182 #, python-format msgid "Show closed (%(n)s)" msgstr "Geschlossene anzeigen (%(n)s)" -#: templates/my_practice/inquiry_list.html:196 -#: templates/my_practice/inquiry_list.html:244 +#: templates/my_practice/inquiry_list.html:216 +#: templates/my_practice/inquiry_list.html:264 msgid "View client" msgstr "Klient:in anzeigen" -#: templates/my_practice/inquiry_list.html:208 -#: templates/my_practice/inquiry_list.html:256 +#: templates/my_practice/inquiry_list.html:228 +#: templates/my_practice/inquiry_list.html:276 msgid "Admit" msgstr "Aufnehmen" -#: templates/my_practice/inquiry_list.html:223 +#: templates/my_practice/inquiry_list.html:243 #, python-format msgid "%(n)s older (inactive > 30 days)" msgstr "%(n)s ältere (>30 Tage inaktiv)" -#: templates/my_practice/inquiry_list.html:272 +#: templates/my_practice/inquiry_list.html:292 msgid "No inquiries found." msgstr "Keine Anfragen gefunden." -#: templates/my_practice/inquiry_list.html:273 +#: templates/my_practice/inquiry_list.html:293 msgid "Record first inquiry" msgstr "Erste Anfrage erfassen" @@ -9233,36 +9298,11 @@ msgstr "Geben Sie den 6-stelligen Code aus der App ein" msgid "Turn on two-factor sign-in" msgstr "Zwei-Faktor-Anmeldung einschalten" -#: templates/base.html:104 -msgid "Sign out" -msgstr "Abmelden" +#~ msgid "No data in selected period" +#~ msgstr "Keine Daten im ausgewählten Zeitraum" -#: my_practice/utils/bank_import.py:483 -msgid "Erroneous booking / correction from private account" -msgstr "Fehlbuchung / Korrektur vom privaten Konto" - -#: my_practice/utils/bank_import.py:501 -msgid "Own payment (capital contribution), ignored automatically" -msgstr "Eigene Zahlung (Einlage), automatisch ignoriert" - -#: my_practice/views/bank_import_views.py:488 -#, python-format -msgid "Combined payment for: %(numbers)s" -msgstr "Sammelzahlung für: %(numbers)s" - -#: my_practice/views/bank_import_views.py:534 -#, python-format -msgid "Created automatically on confirming the payment of %(date)s" -msgstr "Automatisch angelegt beim Bestätigen der Zahlung vom %(date)s" - -#: my_practice/views/bank_import_views.py:544 -#, python-format -msgid "Created during the bank import of %(date)s" -msgstr "Angelegt beim Bankimport vom %(date)s" - -#: templates/my_practice/analytics.html:220 -msgid "Trend" -msgstr "Trend" +#~ msgid "No valid data available" +#~ msgstr "Keine gültigen Daten verfügbar" #~ msgid "Cancellation Rate (last 24 months)" #~ msgstr "Ausfallquote (letzte 24 Monate)" @@ -9418,12 +9458,6 @@ msgstr "Trend" #~ msgid "⚠️ Overdue since %(date)s" #~ msgstr "⚠️ Überfällig seit %(date)s" -#, python-format -#~ msgid "📅 Due in %(days)s day" -#~ msgid_plural "📅 Due in %(days)s days" -#~ msgstr[0] "📅 Fällig in %(days)s Tag" -#~ msgstr[1] "📅 Fällig in %(days)s Tagen" - #, python-format #~ msgid "%(count)s task" #~ msgid_plural "%(count)s tasks" diff --git a/app/locale/en/LC_MESSAGES/django.po b/app/locale/en/LC_MESSAGES/django.po index 4394305..7a3eca7 100644 --- a/app/locale/en/LC_MESSAGES/django.po +++ b/app/locale/en/LC_MESSAGES/django.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: my-practice\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-10-14 10:00+0200\n" +"POT-Creation-Date: 2026-10-21 08:43+0200\n" "PO-Revision-Date: 2026-06-22 23:01+0200\n" "Language-Team: English\n" "Language: en\n" @@ -41,9 +41,9 @@ msgstr "" #: my_practice/admin/bank_statement.py:75 my_practice/admin/client.py:110 #: my_practice/admin/timeoff.py:42 my_practice/admin/todo.py:49 #: my_practice/models/calendar.py:140 my_practice/models/clinical.py:318 -#: my_practice/models/inquiry.py:111 my_practice/models/invoice.py:153 +#: my_practice/models/inquiry.py:111 my_practice/models/invoice.py:154 #: templates/includes/calendar_preflight_widget.html:28 -#: templates/my_practice/analytics.html:397 +#: templates/my_practice/analytics.html:347 #: templates/my_practice/bank_import.html:88 #: templates/my_practice/billing_open_overview.html:65 #: templates/my_practice/calendar_import.html:100 @@ -90,7 +90,7 @@ msgid "Match" msgstr "" #: my_practice/admin/bank_statement.py:129 my_practice/admin/session.py:34 -#: my_practice/models/invoice.py:196 my_practice/models/invoice.py:354 +#: my_practice/models/invoice.py:197 my_practice/models/invoice.py:355 #: templates/my_practice/bank_review.html:269 #: templates/my_practice/bank_review.html:359 #: templates/my_practice/billing_open_overview.html:64 @@ -107,7 +107,7 @@ msgstr "" #: my_practice/models/calendar.py:126 my_practice/models/client.py:216 #: my_practice/models/client.py:270 my_practice/models/client_alias.py:32 #: my_practice/models/clinical.py:170 my_practice/models/clinical.py:306 -#: my_practice/models/clinical.py:363 my_practice/models/invoice.py:140 +#: my_practice/models/clinical.py:363 my_practice/models/invoice.py:141 #: my_practice/models/session.py:22 #: templates/my_practice/billing_open_overview.html:60 #: templates/my_practice/calendar_import.html:98 @@ -147,8 +147,8 @@ msgid "Basic Information" msgstr "" #: my_practice/admin/client.py:67 my_practice/admin/practice.py:38 -#: templates/my_practice/inquiry_list.html:185 -#: templates/my_practice/inquiry_list.html:233 +#: templates/my_practice/inquiry_list.html:205 +#: templates/my_practice/inquiry_list.html:253 #: templates/my_practice/practice_form.html:100 msgid "Contact" msgstr "" @@ -192,7 +192,7 @@ msgstr "" #: my_practice/admin/client.py:114 my_practice/admin/inquiry.py:25 #: my_practice/admin/operational.py:31 my_practice/models/calendar.py:63 #: my_practice/models/client.py:186 my_practice/models/practice.py:52 -#: templates/my_practice/analytics.html:417 +#: templates/my_practice/analytics.html:367 #: templates/my_practice/client_detail.html:11 #: templates/my_practice/client_list_cards.html:34 #: templates/my_practice/dashboard.html:88 @@ -243,7 +243,7 @@ msgstr "" #: my_practice/import_forms.py:67 my_practice/models/bank_statement.py:128 #: my_practice/models/client.py:122 my_practice/models/client_alias.py:41 #: my_practice/models/financial.py:63 my_practice/models/inquiry.py:126 -#: my_practice/models/invoice.py:189 my_practice/models/operational.py:56 +#: my_practice/models/invoice.py:190 my_practice/models/operational.py:56 #: my_practice/models/timeoff.py:55 templates/my_practice/checklist.html:119 #: templates/my_practice/time_off_confirm_delete.html:28 #: templates/my_practice/withdrawal_list.html:62 @@ -261,7 +261,7 @@ msgstr "" #: my_practice/admin/clinical.py:54 my_practice/admin/invoice.py:269 #: my_practice/models/calendar.py:148 my_practice/models/clinical.py:222 -#: my_practice/models/gebueh.py:89 my_practice/models/invoice.py:388 +#: my_practice/models/gebueh.py:89 my_practice/models/invoice.py:389 #: my_practice/models/session.py:63 msgid "Session" msgstr "" @@ -363,7 +363,7 @@ msgstr "" #: my_practice/forms.py:198 my_practice/import_forms.py:117 #: my_practice/models/client.py:289 my_practice/models/financial.py:150 #: my_practice/models/gebueh.py:29 my_practice/models/inquiry.py:218 -#: my_practice/models/invoice.py:396 my_practice/models/tag.py:84 +#: my_practice/models/invoice.py:397 my_practice/models/tag.py:84 #: templates/my_practice/expense_confirm_delete.html:15 #: templates/my_practice/expense_list.html:80 #: templates/my_practice/invoice_edit.html:135 @@ -423,7 +423,7 @@ msgstr "" msgid "Amounts are calculated automatically from invoice items" msgstr "" -#: my_practice/admin/invoice.py:203 my_practice/models/invoice.py:368 +#: my_practice/admin/invoice.py:203 my_practice/models/invoice.py:369 #: templates/my_practice/bank_review.html:77 #: templates/my_practice/invoice_detail.html:88 #: templates/my_practice/invoice_list.html:21 @@ -531,7 +531,7 @@ msgstr "" msgid "No signature uploaded" msgstr "" -#: my_practice/admin/service.py:19 my_practice/models/invoice.py:357 +#: my_practice/admin/service.py:19 my_practice/models/invoice.py:358 msgid "Service Type" msgstr "" @@ -608,7 +608,7 @@ msgstr "" msgid "Priority" msgstr "" -#: my_practice/admin/todo.py:116 templates/includes/focus_queue_row.html:15 +#: my_practice/admin/todo.py:116 templates/includes/focus_queue_row.html:14 msgid "Mark as completed" msgstr "" @@ -760,8 +760,8 @@ msgstr "" #: templates/my_practice/client_detail.html:638 #: templates/my_practice/expense_confirm_delete.html:11 #: templates/my_practice/expense_list.html:79 -#: templates/my_practice/inquiry_list.html:181 -#: templates/my_practice/inquiry_list.html:229 +#: templates/my_practice/inquiry_list.html:201 +#: templates/my_practice/inquiry_list.html:249 #: templates/my_practice/invoice_confirm_delete.html:20 #: templates/my_practice/invoice_detail.html:19 #: templates/my_practice/invoice_detail.html:84 @@ -815,7 +815,7 @@ msgid "End Date" msgstr "" #: my_practice/forms.py:220 my_practice/models/timeoff.py:46 -#: templates/my_practice/analytics.html:400 +#: templates/my_practice/analytics.html:350 #: templates/my_practice/tax_workday_audit.html:62 #: templates/my_practice/time_off_confirm_delete.html:15 #: templates/my_practice/time_off_list.html:33 @@ -965,13 +965,13 @@ msgid "Code \"%(code)s\" is already taken." msgstr "" #: my_practice/inquiry_forms.py:104 my_practice/models/inquiry.py:209 -#: templates/my_practice/analytics.html:56 +#: templates/my_practice/analytics.html:49 #: templates/my_practice/marketing_period_confirm_delete.html:14 msgid "From" msgstr "" #: my_practice/inquiry_forms.py:105 my_practice/models/inquiry.py:213 -#: templates/my_practice/analytics.html:62 +#: templates/my_practice/analytics.html:55 #: templates/my_practice/marketing_period_confirm_delete.html:18 msgid "To" msgstr "" @@ -1059,7 +1059,7 @@ msgstr "" #: my_practice/models/expense_category_rule.py:26 #: my_practice/models/financial.py:52 my_practice/models/financial.py:140 #: my_practice/models/financial.py:235 my_practice/models/inquiry.py:97 -#: my_practice/models/inquiry.py:207 my_practice/models/invoice.py:126 +#: my_practice/models/inquiry.py:207 my_practice/models/invoice.py:127 #: my_practice/models/practice.py:372 my_practice/models/practice.py:408 #: my_practice/models/service.py:17 my_practice/models/todo.py:106 #: templates/base.html:89 templates/my_practice/tax_workday_audit.html:74 @@ -1249,10 +1249,10 @@ msgstr "" msgid "Skipped" msgstr "" -#: my_practice/models/calendar.py:102 my_practice/models/invoice.py:117 +#: my_practice/models/calendar.py:102 my_practice/models/invoice.py:118 #: my_practice/models/session.py:37 #: templates/includes/calendar_preflight_widget.html:45 -#: templates/my_practice/analytics.html:917 +#: templates/my_practice/analytics.html:772 #: templates/my_practice/calendar_import.html:62 #: templates/my_practice/calendar_import.html:159 #: templates/my_practice/dashboard.html:126 @@ -1301,19 +1301,19 @@ msgstr "" msgid "Pending calendar events" msgstr "" -#: my_practice/models/calendar.py:185 my_practice/models/invoice.py:253 +#: my_practice/models/calendar.py:185 my_practice/models/invoice.py:254 msgid "Client does not belong to the selected practice" msgstr "" #: my_practice/models/client.py:82 my_practice/models/inquiry.py:80 -#: my_practice/views/inquiry_views.py:142 +#: my_practice/views/inquiry_views.py:235 #: templates/my_practice/send_cancellation_email.html:7 #: templates/my_practice/time_off_notice_form.html:54 msgid "German" msgstr "" #: my_practice/models/client.py:83 my_practice/models/inquiry.py:81 -#: my_practice/views/inquiry_views.py:142 +#: my_practice/views/inquiry_views.py:235 #: templates/my_practice/send_cancellation_email.html:7 #: templates/my_practice/time_off_notice_form.html:73 msgid "English" @@ -1416,10 +1416,10 @@ msgstr "" msgid "Check if this client primarily has online sessions" msgstr "" -#: my_practice/models/client.py:217 templates/base.html:128 +#: my_practice/models/client.py:217 templates/base.html:133 #: templates/includes/command_palette.html:82 -#: templates/my_practice/analytics.html:104 -#: templates/my_practice/analytics.html:594 +#: templates/my_practice/analytics.html:97 +#: templates/my_practice/analytics.html:544 #: templates/my_practice/client_list_cards.html:8 msgid "Clients" msgstr "" @@ -1446,7 +1446,7 @@ msgstr "" #: my_practice/models/client.py:263 my_practice/models/financial.py:31 #: my_practice/models/financial.py:132 my_practice/models/inquiry.py:34 -#: my_practice/models/todo.py:91 my_practice/views/inquiry_views.py:255 +#: my_practice/models/todo.py:91 my_practice/views/inquiry_views.py:328 #: templates/my_practice/bank_expense_review.html:50 msgid "Other" msgstr "" @@ -1940,8 +1940,8 @@ msgid "Tax year notes" msgstr "" #: my_practice/models/gebueh.py:28 my_practice/models/service.py:25 -#: templates/my_practice/analytics.html:350 -#: templates/my_practice/analytics.html:395 +#: templates/my_practice/analytics.html:300 +#: templates/my_practice/analytics.html:345 #: templates/my_practice/client_list_cards.html:107 #: templates/my_practice/invoice_detail.html:120 #: templates/my_practice/time_off_notice_form.html:29 @@ -2036,22 +2036,23 @@ msgstr "" msgid "Network / colleagues" msgstr "" -#: my_practice/models/inquiry.py:53 my_practice/views/inquiry_views.py:75 -#: my_practice/views/inquiry_views.py:239 +#: my_practice/models/inquiry.py:53 my_practice/views/inquiry_views.py:168 +#: my_practice/views/inquiry_views.py:312 msgid "New" msgstr "" -#: my_practice/models/inquiry.py:54 my_practice/views/inquiry_views.py:76 -#: my_practice/views/inquiry_views.py:240 +#: my_practice/models/inquiry.py:54 my_practice/views/inquiry_views.py:169 +#: my_practice/views/inquiry_views.py:313 msgid "Contacted" msgstr "" -#: my_practice/models/inquiry.py:55 my_practice/views/inquiry_views.py:77 -#: my_practice/views/inquiry_views.py:241 +#: my_practice/models/inquiry.py:55 my_practice/views/inquiry_views.py:131 +#: my_practice/views/inquiry_views.py:170 +#: my_practice/views/inquiry_views.py:314 msgid "Intro meeting" msgstr "" -#: my_practice/models/inquiry.py:56 my_practice/views/inquiry_views.py:78 +#: my_practice/models/inquiry.py:56 my_practice/views/inquiry_views.py:171 msgid "Waitlist" msgstr "" @@ -2059,8 +2060,8 @@ msgstr "" msgid "Intake in progress" msgstr "" -#: my_practice/models/inquiry.py:58 my_practice/views/inquiry_views.py:80 -#: my_practice/views/inquiry_views.py:243 +#: my_practice/models/inquiry.py:58 my_practice/views/inquiry_views.py:173 +#: my_practice/views/inquiry_views.py:316 msgid "Onboarded" msgstr "" @@ -2077,14 +2078,14 @@ msgid "Not a match" msgstr "" #: my_practice/models/inquiry.py:99 my_practice/models/tag.py:57 -#: templates/my_practice/analytics.html:396 +#: templates/my_practice/analytics.html:346 #: templates/my_practice/bank_import.html:85 #: templates/my_practice/bank_review.html:210 #: templates/my_practice/client_list_cards.html:108 #: templates/my_practice/inquiry_confirm_delete.html:10 #: templates/my_practice/inquiry_convert_confirm.html:17 -#: templates/my_practice/inquiry_list.html:182 -#: templates/my_practice/inquiry_list.html:230 +#: templates/my_practice/inquiry_list.html:202 +#: templates/my_practice/inquiry_list.html:250 #: templates/my_practice/practice_confirm_delete.html:24 #: templates/my_practice/tag_form.html:15 #: templates/my_practice/tag_list.html:25 @@ -2094,16 +2095,16 @@ msgstr "Name" #: my_practice/models/inquiry.py:105 #: templates/my_practice/inquiry_confirm_delete.html:18 #: templates/my_practice/inquiry_convert_confirm.html:29 -#: templates/my_practice/inquiry_list.html:183 -#: templates/my_practice/inquiry_list.html:231 +#: templates/my_practice/inquiry_list.html:203 +#: templates/my_practice/inquiry_list.html:251 msgid "Source" msgstr "Source" #: my_practice/models/inquiry.py:121 #: templates/my_practice/client_detail.html:225 -#: templates/my_practice/inquiry_list.html:102 -#: templates/my_practice/inquiry_list.html:184 -#: templates/my_practice/inquiry_list.html:232 +#: templates/my_practice/inquiry_list.html:107 +#: templates/my_practice/inquiry_list.html:204 +#: templates/my_practice/inquiry_list.html:252 #: templates/my_practice/time_off_notice_form.html:30 msgid "Language" msgstr "" @@ -2147,8 +2148,9 @@ msgstr "" #: my_practice/models/inquiry.py:173 templates/includes/command_palette.html:41 #: templates/my_practice/inquiry_list.html:6 -#: templates/my_practice/inquiry_list.html:9 -#: templates/my_practice/inquiry_list.html:15 +#: templates/my_practice/inquiry_list.html:14 +#: templates/my_practice/inquiry_list.html:20 +#: templates/my_practice/inquiry_list.html:128 msgid "Inquiries" msgstr "" @@ -2173,90 +2175,90 @@ msgstr "" msgid "ongoing" msgstr "" -#: my_practice/models/invoice.py:114 my_practice/views/billing_views.py:219 +#: my_practice/models/invoice.py:115 my_practice/views/billing_views.py:219 #: templates/my_practice/dashboard.html:111 #: templates/my_practice/invoice_detail.html:40 #: templates/my_practice/invoice_list.html:26 msgid "Draft" msgstr "" -#: my_practice/models/invoice.py:115 my_practice/views/billing_views.py:221 +#: my_practice/models/invoice.py:116 my_practice/views/billing_views.py:221 #: templates/my_practice/dashboard.html:116 #: templates/my_practice/invoice_detail.html:41 #: templates/my_practice/invoice_list.html:31 msgid "Sent" msgstr "" -#: my_practice/models/invoice.py:116 my_practice/views/billing_views.py:223 +#: my_practice/models/invoice.py:117 my_practice/views/billing_views.py:223 #: templates/my_practice/dashboard.html:121 #: templates/my_practice/invoice_detail.html:42 #: templates/my_practice/invoice_list.html:36 msgid "Paid" msgstr "" -#: my_practice/models/invoice.py:118 +#: my_practice/models/invoice.py:119 #: templates/my_practice/invoice_detail.html:44 msgid "Written off" msgstr "" -#: my_practice/models/invoice.py:133 +#: my_practice/models/invoice.py:134 #: templates/my_practice/invoice_confirm_delete.html:12 msgid "Invoice number" msgstr "" -#: my_practice/models/invoice.py:134 +#: my_practice/models/invoice.py:135 msgid "Auto-generated (e.g., JL-5) or enter manually" msgstr "" -#: my_practice/models/invoice.py:145 +#: my_practice/models/invoice.py:146 #: templates/my_practice/revenue_report.html:51 #: templates/my_practice/tax_year_summary.html:132 msgid "Invoice date" msgstr "" -#: my_practice/models/invoice.py:146 +#: my_practice/models/invoice.py:147 msgid "Defaults to today" msgstr "" -#: my_practice/models/invoice.py:159 +#: my_practice/models/invoice.py:160 #: templates/my_practice/invoice_detail.html:23 #: templates/my_practice/invoice_detail.html:230 #: templates/my_practice/tax_year_summary.html:133 msgid "Paid on" msgstr "" -#: my_practice/models/invoice.py:160 +#: my_practice/models/invoice.py:161 msgid "Date of payment" msgstr "" -#: my_practice/models/invoice.py:167 +#: my_practice/models/invoice.py:168 msgid "Subtotal" msgstr "" -#: my_practice/models/invoice.py:173 +#: my_practice/models/invoice.py:174 msgid "Tax rate (%)" msgstr "" -#: my_practice/models/invoice.py:174 +#: my_practice/models/invoice.py:175 msgid "Kleinunternehmer = 0%" msgstr "" -#: my_practice/models/invoice.py:180 +#: my_practice/models/invoice.py:181 msgid "Tax amount" msgstr "" -#: my_practice/models/invoice.py:186 +#: my_practice/models/invoice.py:187 #: templates/my_practice/bank_expense_review.html:17 #: templates/my_practice/bank_withdrawal_review.html:17 #: templates/my_practice/invoice_confirm_delete.html:30 msgid "Total amount" msgstr "Total amount" -#: my_practice/models/invoice.py:197 templates/base.html:129 +#: my_practice/models/invoice.py:198 templates/base.html:134 #: templates/includes/command_palette.html:83 -#: templates/my_practice/analytics.html:329 +#: templates/my_practice/analytics.html:279 +#: templates/my_practice/analytics.html:301 #: templates/my_practice/analytics.html:351 -#: templates/my_practice/analytics.html:401 #: templates/my_practice/bank_review.html:28 #: templates/my_practice/bank_review.html:360 #: templates/my_practice/invoice_list.html:5 @@ -2264,79 +2266,79 @@ msgstr "Total amount" msgid "Invoices" msgstr "" -#: my_practice/models/invoice.py:209 +#: my_practice/models/invoice.py:210 msgid "This invoice number already exists." msgstr "" -#: my_practice/models/invoice.py:233 +#: my_practice/models/invoice.py:234 #, python-format msgid "Invoice number \"%(number)s\" already exists (invoice for %(client_code)s dated %(date)s)" msgstr "" -#: my_practice/models/invoice.py:247 +#: my_practice/models/invoice.py:248 msgid "Payment date must not be before the invoice date" msgstr "" -#: my_practice/models/invoice.py:360 +#: my_practice/models/invoice.py:361 #: templates/my_practice/invoice_detail.html:87 msgid "Rate" msgstr "" -#: my_practice/models/invoice.py:366 +#: my_practice/models/invoice.py:367 #: templates/my_practice/invoice_edit.html:119 msgid "Quantity" msgstr "" -#: my_practice/models/invoice.py:372 my_practice/models/session.py:43 +#: my_practice/models/invoice.py:373 my_practice/models/session.py:43 msgid "Group size" msgstr "" -#: my_practice/models/invoice.py:374 +#: my_practice/models/invoice.py:375 msgid "Number of participants for group offerings (default 1 = individual session). Affects the calculation of therapist hours in analytics." msgstr "" -#: my_practice/models/invoice.py:390 +#: my_practice/models/invoice.py:391 msgid "Linked session (central reference for clinical documentation + billing)" msgstr "" -#: my_practice/models/invoice.py:398 +#: my_practice/models/invoice.py:399 msgid "Free-text line item label, used instead of a linked session (day-rate/project billing) — only available when the practice allows free-form invoice items" msgstr "" -#: my_practice/models/invoice.py:409 +#: my_practice/models/invoice.py:410 msgid "Invoice item" msgstr "" -#: my_practice/models/invoice.py:410 templates/my_practice/invoice_edit.html:67 +#: my_practice/models/invoice.py:411 templates/my_practice/invoice_edit.html:67 #: templates/my_practice/invoice_form.html:68 msgid "Invoice items" msgstr "" -#: my_practice/models/invoice.py:432 +#: my_practice/models/invoice.py:433 msgid "Invoice item needs either a linked session or a description, not both or neither." msgstr "" -#: my_practice/models/invoice.py:444 +#: my_practice/models/invoice.py:445 msgid "This practice doesn't allow free-form invoice items." msgstr "" #: my_practice/models/operational.py:31 -#: my_practice/utils/dashboard_widgets.py:181 +#: my_practice/utils/dashboard_widgets.py:182 msgid "Weekly backup" msgstr "" #: my_practice/models/operational.py:32 -#: my_practice/utils/dashboard_widgets.py:180 +#: my_practice/utils/dashboard_widgets.py:181 msgid "Monthly restore test" msgstr "" #: my_practice/models/operational.py:35 -#: my_practice/utils/dashboard_widgets.py:182 +#: my_practice/utils/dashboard_widgets.py:183 msgid "MicroSD offsite backup (card A/B alternating, every 2 weeks)" msgstr "" #: my_practice/models/operational.py:37 -#: my_practice/utils/dashboard_widgets.py:183 +#: my_practice/utils/dashboard_widgets.py:184 msgid "Annual security review" msgstr "" @@ -2344,7 +2346,7 @@ msgstr "" msgid "Checklist type" msgstr "" -#: my_practice/models/operational.py:46 templates/my_practice/analytics.html:42 +#: my_practice/models/operational.py:46 templates/my_practice/analytics.html:35 #: templates/my_practice/tax_quarter_overview.html:77 msgid "Period" msgstr "" @@ -3113,25 +3115,25 @@ msgstr "" msgid "Recovery codes" msgstr "" -#: my_practice/signals.py:27 my_practice/views/invoice_views.py:318 +#: my_practice/signals.py:27 my_practice/views/invoice_views.py:319 #, python-format msgid "Invoice %(number)s has been issued and can no longer be changed. Cancel it and create a corrected copy instead." msgstr "" -#: my_practice/signals.py:74 my_practice/views/invoice_views.py:438 +#: my_practice/signals.py:74 my_practice/views/invoice_views.py:439 #, python-format msgid "Invoice %(number)s has been issued and must be kept until the end of %(year)s. Cancel it instead of deleting it." msgstr "" -#: my_practice/utils/analytics_utils.py:331 +#: my_practice/utils/analytics_utils.py:332 msgid "60-min sessions" msgstr "" -#: my_practice/utils/analytics_utils.py:339 +#: my_practice/utils/analytics_utils.py:340 msgid "90-min sessions" msgstr "" -#: my_practice/utils/analytics_utils.py:347 +#: my_practice/utils/analytics_utils.py:348 msgid "Group sessions" msgstr "" @@ -3140,6 +3142,19 @@ msgstr "" msgid "Wrong account: the CSV file belongs to IBAN %(csv_iban)s, expected the practice IBAN %(practice_iban)s. Import aborted." msgstr "" +#: my_practice/utils/bank_import.py:483 +msgid "Erroneous booking / correction from private account" +msgstr "" + +#: my_practice/utils/bank_import.py:487 +#: templates/my_practice/bank_review.html:240 +msgid "Capital contribution from private account" +msgstr "" + +#: my_practice/utils/bank_import.py:501 +msgid "Own payment (capital contribution), ignored automatically" +msgstr "" + #: my_practice/utils/bank_import.py:538 #, python-format msgid "Failed to parse row: %(row)s" @@ -3216,62 +3231,74 @@ msgid "Session on %(date)s was billed." msgstr "Session on %(date)s was billed." #: my_practice/utils/chart_helpers.py:17 -#: templates/my_practice/analytics.html:759 +#: templates/my_practice/analytics.html:18 +#: templates/my_practice/inquiry_list.html:129 msgid "Jan" msgstr "" #: my_practice/utils/chart_helpers.py:18 -#: templates/my_practice/analytics.html:759 +#: templates/my_practice/analytics.html:18 +#: templates/my_practice/inquiry_list.html:129 msgid "Feb" msgstr "" #: my_practice/utils/chart_helpers.py:19 -#: templates/my_practice/analytics.html:759 +#: templates/my_practice/analytics.html:18 +#: templates/my_practice/inquiry_list.html:129 msgid "Mar" msgstr "" #: my_practice/utils/chart_helpers.py:20 -#: templates/my_practice/analytics.html:760 +#: templates/my_practice/analytics.html:18 +#: templates/my_practice/inquiry_list.html:129 msgid "Apr" msgstr "" #: my_practice/utils/chart_helpers.py:21 -#: templates/my_practice/analytics.html:760 +#: templates/my_practice/analytics.html:19 +#: templates/my_practice/inquiry_list.html:129 msgid "May" msgstr "" #: my_practice/utils/chart_helpers.py:22 -#: templates/my_practice/analytics.html:760 +#: templates/my_practice/analytics.html:19 +#: templates/my_practice/inquiry_list.html:129 msgid "Jun" msgstr "" #: my_practice/utils/chart_helpers.py:23 -#: templates/my_practice/analytics.html:761 +#: templates/my_practice/analytics.html:19 +#: templates/my_practice/inquiry_list.html:129 msgid "Jul" msgstr "" #: my_practice/utils/chart_helpers.py:24 -#: templates/my_practice/analytics.html:761 +#: templates/my_practice/analytics.html:19 +#: templates/my_practice/inquiry_list.html:129 msgid "Aug" msgstr "" #: my_practice/utils/chart_helpers.py:25 -#: templates/my_practice/analytics.html:761 +#: templates/my_practice/analytics.html:20 +#: templates/my_practice/inquiry_list.html:129 msgid "Sep" msgstr "" #: my_practice/utils/chart_helpers.py:26 -#: templates/my_practice/analytics.html:762 +#: templates/my_practice/analytics.html:20 +#: templates/my_practice/inquiry_list.html:129 msgid "Oct" msgstr "" #: my_practice/utils/chart_helpers.py:27 -#: templates/my_practice/analytics.html:762 +#: templates/my_practice/analytics.html:20 +#: templates/my_practice/inquiry_list.html:129 msgid "Nov" msgstr "" #: my_practice/utils/chart_helpers.py:28 -#: templates/my_practice/analytics.html:762 +#: templates/my_practice/analytics.html:20 +#: templates/my_practice/inquiry_list.html:129 msgid "Dec" msgstr "" @@ -3281,7 +3308,7 @@ msgid "since %(start)s" msgstr "" #: my_practice/utils/client_detail_builder.py:232 -#: my_practice/views/inquiry_views.py:79 +#: my_practice/views/inquiry_views.py:172 #: templates/my_practice/client_detail.html:257 msgid "Intake" msgstr "" @@ -3315,8 +3342,8 @@ msgid "Due today" msgstr "" #: my_practice/utils/dashboard_context_builder.py:147 -#: templates/my_practice/analytics.html:107 -#: templates/my_practice/analytics.html:735 +#: templates/my_practice/analytics.html:100 +#: templates/my_practice/analytics.html:675 msgid "Capacity" msgstr "" @@ -3499,140 +3526,155 @@ msgstr "" msgid "Two-factor sign-in is now off." msgstr "" -#: my_practice/views/bank_import_views.py:80 +#: my_practice/views/bank_import_views.py:81 #, python-format msgid "%(count)s automatically matched" msgstr "%(count)s automatically matched" -#: my_practice/views/bank_import_views.py:81 +#: my_practice/views/bank_import_views.py:82 #, python-format msgid "%(count)s require manual review" msgstr "%(count)s require manual review" -#: my_practice/views/bank_import_views.py:85 +#: my_practice/views/bank_import_views.py:86 #, python-format msgid "%(count)s expenses detected automatically" msgstr "%(count)s expenses detected automatically" -#: my_practice/views/bank_import_views.py:87 +#: my_practice/views/bank_import_views.py:88 #, python-format msgid "%(count)s ignored" msgstr "%(count)s ignored" -#: my_practice/views/bank_import_views.py:90 +#: my_practice/views/bank_import_views.py:91 #, python-format msgid "Import complete: %(details)s." msgstr "Import complete: %(details)s." -#: my_practice/views/bank_import_views.py:253 +#: my_practice/views/bank_import_views.py:254 msgid "No transaction selected." msgstr "No transaction selected." -#: my_practice/views/bank_import_views.py:341 +#: my_practice/views/bank_import_views.py:342 #, python-format msgid "Auto-ignored: invoice %(number)s already paid" msgstr "Auto-ignored: invoice %(number)s already paid" -#: my_practice/views/bank_import_views.py:351 +#: my_practice/views/bank_import_views.py:352 #, python-format msgid "✅ %(count)s transaction with already-paid invoice ignored." msgid_plural "✅ %(count)s transactions with already-paid invoices ignored." msgstr[0] "✅ %(count)s transaction with already-paid invoice ignored." msgstr[1] "✅ %(count)s transactions with already-paid invoices ignored." -#: my_practice/views/bank_import_views.py:358 +#: my_practice/views/bank_import_views.py:359 msgid "No matching transactions to ignore." msgstr "No matching transactions to ignore." -#: my_practice/views/bank_import_views.py:374 +#: my_practice/views/bank_import_views.py:375 #, python-format msgid "%(count)s expense ignored." msgid_plural "%(count)s expenses ignored." msgstr[0] "%(count)s expense ignored." msgstr[1] "%(count)s expenses ignored." -#: my_practice/views/bank_import_views.py:394 -#: my_practice/views/bank_import_views.py:706 +#: my_practice/views/bank_import_views.py:395 +#: my_practice/views/bank_import_views.py:712 #, python-format msgid "%(count)s transaction ignored." msgid_plural "%(count)s transactions ignored." msgstr[0] "%(count)s transaction ignored." msgstr[1] "%(count)s transactions ignored." -#: my_practice/views/bank_import_views.py:408 +#: my_practice/views/bank_import_views.py:409 msgid "Transaction ignored." msgstr "Transaction ignored." -#: my_practice/views/bank_import_views.py:432 +#: my_practice/views/bank_import_views.py:433 #, python-format msgid "Transaction linked to %(number)s (already paid)." msgstr "Transaction linked to %(number)s (already paid)." -#: my_practice/views/bank_import_views.py:436 +#: my_practice/views/bank_import_views.py:437 msgid "Transaction confirmed (invoice already paid)." msgstr "Transaction confirmed (invoice already paid)." -#: my_practice/views/bank_import_views.py:442 +#: my_practice/views/bank_import_views.py:443 msgid "No invoice specified." msgstr "No invoice specified." -#: my_practice/views/bank_import_views.py:462 +#: my_practice/views/bank_import_views.py:463 #, python-format msgid "Transaction automatically linked to %(number)s and marked as paid." msgstr "Transaction automatically linked to %(number)s and marked as paid." -#: my_practice/views/bank_import_views.py:471 +#: my_practice/views/bank_import_views.py:472 msgid "Error processing form." msgstr "Error processing form." -#: my_practice/views/bank_import_views.py:476 +#: my_practice/views/bank_import_views.py:477 msgid "Please select at least one invoice." msgstr "Please select at least one invoice." -#: my_practice/views/bank_import_views.py:507 +#: my_practice/views/bank_import_views.py:488 +#, python-format +msgid "Combined payment for: %(numbers)s" +msgstr "" + +#: my_practice/views/bank_import_views.py:509 #, python-format msgid "Payment successfully assigned to invoice %(number)s." msgstr "Payment successfully assigned to invoice %(number)s." -#: my_practice/views/bank_import_views.py:514 +#: my_practice/views/bank_import_views.py:516 #, python-format msgid "Payment successfully assigned to %(count)s invoices: %(numbers)s" msgstr "Payment successfully assigned to %(count)s invoices: %(numbers)s" -#: my_practice/views/bank_import_views.py:535 +#: my_practice/views/bank_import_views.py:534 +#, python-format +msgid "Created automatically on confirming the payment of %(date)s" +msgstr "" + +#: my_practice/views/bank_import_views.py:539 #, python-format msgid "📌 Alias '%(name)s' for %(code)s saved." msgstr "📌 Alias '%(name)s' for %(code)s saved." -#: my_practice/views/bank_import_views.py:542 +#: my_practice/views/bank_import_views.py:543 +#, python-format +msgid "Created during the bank import of %(date)s" +msgstr "" + +#: my_practice/views/bank_import_views.py:548 #, python-format msgid "Alias '%(name)s' for %(code)s saved." msgstr "Alias '%(name)s' for %(code)s saved." -#: my_practice/views/bank_import_views.py:623 +#: my_practice/views/bank_import_views.py:629 msgid "Please select at least one transaction." msgstr "Please select at least one transaction." -#: my_practice/views/bank_import_views.py:636 +#: my_practice/views/bank_import_views.py:642 msgid "No transactions found." msgstr "No transactions found." -#: my_practice/views/bank_import_views.py:722 +#: my_practice/views/bank_import_views.py:728 msgid "Bank Import - Assign Expenses" msgstr "" -#: my_practice/views/bank_import_views.py:727 +#: my_practice/views/bank_import_views.py:733 #, python-format msgid "%(count)s transaction successfully grouped into expense: %(amount)s €" msgid_plural "%(count)s transactions successfully grouped into expense: %(amount)s €" msgstr[0] "%(count)s transaction successfully grouped into expense: %(amount)s €" msgstr[1] "%(count)s transactions successfully grouped into expense: %(amount)s €" -#: my_practice/views/bank_import_views.py:772 +#: my_practice/views/bank_import_views.py:778 msgid "Bank Import - Assign Withdrawals" msgstr "" -#: my_practice/views/bank_import_views.py:777 +#: my_practice/views/bank_import_views.py:783 #, python-format msgid "%(count)s transaction successfully grouped into withdrawal: %(amount)s €" msgid_plural "%(count)s transactions successfully grouped into withdrawal: %(amount)s €" @@ -3659,7 +3701,7 @@ msgstr "" #: my_practice/views/billing_views.py:239 #: my_practice/views/billing_views.py:368 #: my_practice/views/calendar_views.py:268 -#: my_practice/views/invoice_views.py:568 +#: my_practice/views/invoice_views.py:569 msgid "No active practice found." msgstr "No active practice found." @@ -4036,147 +4078,159 @@ msgstr "" msgid "Link with transaction from %(date)s removed." msgstr "" -#: my_practice/views/inquiry_views.py:120 +#: my_practice/views/inquiry_views.py:129 +msgid "Received" +msgstr "" + +#: my_practice/views/inquiry_views.py:130 +msgid "Responded" +msgstr "" + +#: my_practice/views/inquiry_views.py:132 +msgid "Decision" +msgstr "" + +#: my_practice/views/inquiry_views.py:213 msgid "Received → response" msgstr "" -#: my_practice/views/inquiry_views.py:121 +#: my_practice/views/inquiry_views.py:214 msgid "Response → intro meeting" msgstr "" -#: my_practice/views/inquiry_views.py:122 +#: my_practice/views/inquiry_views.py:215 msgid "Intro meeting → decision" msgstr "" -#: my_practice/views/inquiry_views.py:123 +#: my_practice/views/inquiry_views.py:216 msgid "Decision → onboarded" msgstr "" -#: my_practice/views/inquiry_views.py:242 +#: my_practice/views/inquiry_views.py:315 msgid "Waitlist / intake" msgstr "" -#: my_practice/views/inquiry_views.py:244 +#: my_practice/views/inquiry_views.py:317 msgid "Closed" msgstr "" -#: my_practice/views/inquiry_views.py:274 +#: my_practice/views/inquiry_views.py:347 #, python-brace-format msgid "Inquiry from {obj.full_name} recorded." msgstr "" -#: my_practice/views/inquiry_views.py:284 +#: my_practice/views/inquiry_views.py:357 #, python-brace-format msgid "Inquiry from {obj.full_name} saved." msgstr "" -#: my_practice/views/inquiry_views.py:317 +#: my_practice/views/inquiry_views.py:390 #, python-brace-format msgid "Inquiry from {obj.full_name} deleted." msgstr "" -#: my_practice/views/inquiry_views.py:327 +#: my_practice/views/inquiry_views.py:400 msgid "Marketing period recorded." msgstr "" -#: my_practice/views/inquiry_views.py:337 +#: my_practice/views/inquiry_views.py:410 msgid "Marketing period saved." msgstr "" -#: my_practice/views/inquiry_views.py:347 +#: my_practice/views/inquiry_views.py:420 msgid "Marketing period deleted." msgstr "" -#: my_practice/views/inquiry_views.py:407 +#: my_practice/views/inquiry_views.py:480 #, python-format msgid "Client %(name)s (%(code)s) created successfully." msgstr "" -#: my_practice/views/invoice_views.py:235 +#: my_practice/views/invoice_views.py:236 #, python-format msgid "Error creating invoice: %(error)s" msgstr "" -#: my_practice/views/invoice_views.py:241 +#: my_practice/views/invoice_views.py:242 #, python-format msgid "Invoice %(num)s created successfully!" msgstr "" -#: my_practice/views/invoice_views.py:251 +#: my_practice/views/invoice_views.py:252 #, python-format msgid "Item %(n)s: %(errors)s" msgstr "" -#: my_practice/views/invoice_views.py:256 +#: my_practice/views/invoice_views.py:257 #, python-format msgid "Formset errors: %(errors)s" msgstr "" -#: my_practice/views/invoice_views.py:305 +#: my_practice/views/invoice_views.py:306 #, python-brace-format msgid "Invoice {obj.invoice_number} updated successfully!" msgstr "" -#: my_practice/views/invoice_views.py:381 +#: my_practice/views/invoice_views.py:382 #, python-format msgid "Error updating invoice: %(error)s" msgstr "" -#: my_practice/views/invoice_views.py:397 +#: my_practice/views/invoice_views.py:398 #, python-format msgid "Item %(n)s - %(field)s: %(error)s" msgstr "" -#: my_practice/views/invoice_views.py:402 +#: my_practice/views/invoice_views.py:403 #, python-format msgid "Formset: %(error)s" msgstr "" -#: my_practice/views/invoice_views.py:411 +#: my_practice/views/invoice_views.py:412 #, python-format msgid "%(label)s: %(error)s" msgstr "" -#: my_practice/views/invoice_views.py:424 +#: my_practice/views/invoice_views.py:425 msgid "Please correct the errors in the form." msgstr "" -#: my_practice/views/invoice_views.py:455 +#: my_practice/views/invoice_views.py:456 #, python-format msgid "Invoice %(num)s for %(code)s was deleted successfully." msgstr "" -#: my_practice/views/invoice_views.py:483 +#: my_practice/views/invoice_views.py:484 msgid "Only a sent invoice can be cancelled and corrected." msgstr "" -#: my_practice/views/invoice_views.py:495 +#: my_practice/views/invoice_views.py:496 #, python-format msgid "Corrects invoice %(number)s." msgstr "" -#: my_practice/views/invoice_views.py:505 +#: my_practice/views/invoice_views.py:506 #, python-format msgid "Invoice %(old)s was cancelled. %(new)s is an editable copy — correct it and send it as usual." msgstr "" -#: my_practice/views/invoice_views.py:524 -#: my_practice/views/invoice_views.py:583 +#: my_practice/views/invoice_views.py:525 +#: my_practice/views/invoice_views.py:584 msgid "No sessions specified." msgstr "" -#: my_practice/views/invoice_views.py:548 +#: my_practice/views/invoice_views.py:549 #, python-format msgid "%(count)s session added to %(invoice)s." msgid_plural "%(count)s sessions added to %(invoice)s." msgstr[0] "" msgstr[1] "" -#: my_practice/views/invoice_views.py:555 +#: my_practice/views/invoice_views.py:556 msgid "No new sessions added (already billed?)." msgstr "" -#: my_practice/views/invoice_views.py:607 +#: my_practice/views/invoice_views.py:608 msgid "Invoice {} with {} session created." msgid_plural "Invoice {} with {} sessions created." msgstr[0] "" @@ -4515,31 +4569,35 @@ msgstr "Manage practices" msgid "Two-factor sign-in" msgstr "" -#: templates/base.html:112 +#: templates/base.html:104 +msgid "Sign out" +msgstr "" + +#: templates/base.html:117 msgid "Toggle dark mode" msgstr "" -#: templates/base.html:115 +#: templates/base.html:120 msgid "Click to hide sensitive data" msgstr "" -#: templates/base.html:127 templates/my_practice/bank_expense_review.html:132 +#: templates/base.html:132 templates/my_practice/bank_expense_review.html:132 #: templates/my_practice/bank_withdrawal_review.html:112 #: templates/my_practice/checklist.html:16 #: templates/my_practice/client_detail.html:40 msgid "Overview" msgstr "" -#: templates/base.html:130 templates/my_practice/focus_queue.html:4 +#: templates/base.html:135 templates/my_practice/focus_queue.html:4 #: templates/my_practice/focus_queue.html:7 msgid "Focus Queue" msgstr "" -#: templates/base.html:146 +#: templates/base.html:151 msgid "available" msgstr "" -#: templates/base.html:148 templates/includes/command_palette.html:86 +#: templates/base.html:153 templates/includes/command_palette.html:86 msgid "Close" msgstr "" @@ -4607,8 +4665,9 @@ msgid "hrs" msgstr "" #: templates/includes/capacity_monitoring_widget_content.html:27 -#: templates/my_practice/analytics.html:101 -#: templates/my_practice/analytics.html:185 +#: templates/my_practice/analytics.html:94 +#: templates/my_practice/analytics.html:181 +#: templates/my_practice/analytics.html:219 #: templates/my_practice/tax_quarter_overview.html:78 msgid "Revenue" msgstr "" @@ -4697,17 +4756,18 @@ msgid "Bank expenses" msgstr "" #: templates/includes/command_palette.html:46 -#: templates/my_practice/analytics.html:142 -#: templates/my_practice/analytics.html:187 +#: templates/my_practice/analytics.html:135 +#: templates/my_practice/analytics.html:183 #: templates/my_practice/bank_review.html:24 #: templates/my_practice/withdrawal_list.html:48 msgid "Withdrawals" msgstr "" #: templates/includes/command_palette.html:47 -#: templates/my_practice/analytics.html:110 -#: templates/my_practice/analytics.html:139 -#: templates/my_practice/analytics.html:186 +#: templates/my_practice/analytics.html:103 +#: templates/my_practice/analytics.html:132 +#: templates/my_practice/analytics.html:182 +#: templates/my_practice/analytics.html:849 #: templates/my_practice/bank_review.html:19 #: templates/my_practice/bank_withdrawal_review.html:110 #: templates/my_practice/expense_list.html:66 @@ -4718,7 +4778,7 @@ msgstr "" #: templates/includes/command_palette.html:48 #: templates/my_practice/analytics.html:6 #: templates/my_practice/analytics.html:9 -#: templates/my_practice/inquiry_list.html:36 +#: templates/my_practice/inquiry_list.html:41 #: templates/my_practice/withdrawal_list.html:16 msgid "Analytics" msgstr "" @@ -4752,7 +4812,7 @@ msgid "Calendar approval" msgstr "" #: templates/includes/command_palette.html:55 -#: templates/my_practice/analytics.html:665 +#: templates/my_practice/analytics.html:615 #: templates/my_practice/time_off_list.html:4 #: templates/my_practice/time_off_list.html:6 msgid "Time off" @@ -4775,8 +4835,8 @@ msgstr "" #: templates/my_practice/client_detail.html:592 #: templates/my_practice/client_detail.html:638 #: templates/my_practice/expense_list.html:86 -#: templates/my_practice/inquiry_list.html:186 -#: templates/my_practice/inquiry_list.html:234 +#: templates/my_practice/inquiry_list.html:206 +#: templates/my_practice/inquiry_list.html:254 #: templates/my_practice/invoice_list.html:171 #: templates/my_practice/monthly_billing_overview.html:54 #: templates/my_practice/tag_list.html:29 @@ -4790,7 +4850,7 @@ msgstr "" #: templates/includes/command_palette.html:68 #: templates/my_practice/inquiry_form.html:5 #: templates/my_practice/inquiry_form.html:8 -#: templates/my_practice/inquiry_list.html:16 +#: templates/my_practice/inquiry_list.html:21 msgid "New inquiry" msgstr "" @@ -4870,45 +4930,45 @@ msgstr "" msgid "Create a task" msgstr "" -#: templates/includes/focus_queue_row.html:15 +#: templates/includes/focus_queue_row.html:14 msgid "Mark as not done" msgstr "" -#: templates/includes/focus_queue_row.html:35 +#: templates/includes/focus_queue_row.html:34 msgid "Invoice date, session date, or when this task was added" msgstr "" -#: templates/includes/focus_queue_row.html:41 +#: templates/includes/focus_queue_row.html:40 msgid "overdue!" msgstr "" -#: templates/includes/focus_queue_row.html:49 +#: templates/includes/focus_queue_row.html:48 msgid "Set due today — bumps this task to the top of the queue" msgstr "" -#: templates/includes/focus_queue_row.html:49 +#: templates/includes/focus_queue_row.html:48 msgid "Today" msgstr "" -#: templates/includes/focus_queue_row.html:51 +#: templates/includes/focus_queue_row.html:50 msgid "Snooze 1 day" msgstr "" -#: templates/includes/focus_queue_row.html:52 +#: templates/includes/focus_queue_row.html:51 msgid "Snooze 3 days" msgstr "" -#: templates/includes/focus_queue_row.html:53 +#: templates/includes/focus_queue_row.html:52 msgid "Snooze 1 week" msgstr "" -#: templates/includes/focus_queue_row.html:56 +#: templates/includes/focus_queue_row.html:55 #: templates/my_practice/client_detail.html:437 #: templates/my_practice/client_detail.html:456 #: templates/my_practice/expense_list.html:128 -#: templates/my_practice/inquiry_list.html:26 -#: templates/my_practice/inquiry_list.html:206 -#: templates/my_practice/inquiry_list.html:254 +#: templates/my_practice/inquiry_list.html:31 +#: templates/my_practice/inquiry_list.html:226 +#: templates/my_practice/inquiry_list.html:274 #: templates/my_practice/invoice_detail.html:196 #: templates/my_practice/practice_management.html:44 #: templates/my_practice/tag_list.html:63 @@ -5004,12 +5064,12 @@ msgstr "" msgid "No sessions this week." msgstr "No sessions this week." -#: templates/includes/weekly_focus_widget_content.html:43 +#: templates/includes/weekly_focus_widget_content.html:42 #: templates/my_practice/calendar_approval_queue.html:38 msgid "Mark as done" msgstr "" -#: templates/includes/weekly_focus_widget_content.html:57 +#: templates/includes/weekly_focus_widget_content.html:56 #, python-format msgid "Nothing due today. Set a due date from the focus queue." msgstr "" @@ -5063,141 +5123,138 @@ msgid "Revenue, Clients, Capacity & Expenses" msgstr "" #: templates/my_practice/analytics.html:15 -#: templates/my_practice/analytics.html:272 +#: templates/my_practice/analytics.html:238 msgid "No data available" msgstr "" -#: templates/my_practice/analytics.html:16 -msgid "No data in selected period" -msgstr "" - -#: templates/my_practice/analytics.html:17 -msgid "No valid data available" -msgstr "" - -#: templates/my_practice/analytics.html:45 +#: templates/my_practice/analytics.html:38 #, python-format msgid "All years (%(year)s–today)" msgstr "" -#: templates/my_practice/analytics.html:46 +#: templates/my_practice/analytics.html:39 msgid "Last year" msgstr "" -#: templates/my_practice/analytics.html:47 +#: templates/my_practice/analytics.html:40 msgid "Last quarter" msgstr "" -#: templates/my_practice/analytics.html:48 +#: templates/my_practice/analytics.html:41 msgid "Last month" msgstr "" -#: templates/my_practice/analytics.html:49 +#: templates/my_practice/analytics.html:42 msgid "Custom" msgstr "" -#: templates/my_practice/analytics.html:69 +#: templates/my_practice/analytics.html:62 msgid "Apply" msgstr "" -#: templates/my_practice/analytics.html:73 +#: templates/my_practice/analytics.html:66 #: templates/my_practice/invoice_list.html:119 msgid "Reset" msgstr "" -#: templates/my_practice/analytics.html:117 +#: templates/my_practice/analytics.html:110 msgid "Revenue & Profit" msgstr "" -#: templates/my_practice/analytics.html:122 +#: templates/my_practice/analytics.html:115 msgid "Detailed Revenue Report" msgstr "" -#: templates/my_practice/analytics.html:128 +#: templates/my_practice/analytics.html:121 msgid "Profit (Revenue - Expenses)" msgstr "" -#: templates/my_practice/analytics.html:130 +#: templates/my_practice/analytics.html:123 #, python-format msgid "Business profit %(start_year)s–today · Cumulative development" msgstr "" -#: templates/my_practice/analytics.html:137 -#: templates/my_practice/analytics.html:662 +#: templates/my_practice/analytics.html:130 +#: templates/my_practice/analytics.html:612 #: templates/my_practice/expense_form.html:177 #: templates/my_practice/invoice_list.html:99 msgid "Year" msgstr "" -#: templates/my_practice/analytics.html:138 +#: templates/my_practice/analytics.html:131 msgid "Income" msgstr "" -#: templates/my_practice/analytics.html:140 +#: templates/my_practice/analytics.html:133 #: templates/my_practice/tax_year_summary.html:45 msgid "Profit" msgstr "" -#: templates/my_practice/analytics.html:141 +#: templates/my_practice/analytics.html:134 msgid "Cumulative" msgstr "" -#: templates/my_practice/analytics.html:167 +#: templates/my_practice/analytics.html:160 msgid "Revenue, Expenses & Withdrawals" msgstr "" -#: templates/my_practice/analytics.html:169 +#: templates/my_practice/analytics.html:162 msgid "Complete financial overview" msgstr "" -#: templates/my_practice/analytics.html:211 +#: templates/my_practice/analytics.html:191 msgid "Revenue Trend (Monthly)" msgstr "" -#: templates/my_practice/analytics.html:213 +#: templates/my_practice/analytics.html:193 msgid "Monthly revenue development · growth visualized" msgstr "" -#: templates/my_practice/analytics.html:223 +#: templates/my_practice/analytics.html:203 #, python-format msgid "Monthly revenue · %(months)s months · Max: %(max)s" msgstr "" -#: templates/my_practice/analytics.html:260 +#: templates/my_practice/analytics.html:218 +#: templates/my_practice/analytics.html:670 +msgid "Trend" +msgstr "" + +#: templates/my_practice/analytics.html:226 msgid "Peak Months" msgstr "" -#: templates/my_practice/analytics.html:292 +#: templates/my_practice/analytics.html:258 msgid "Payment Delay (last 24 months)" msgstr "" -#: templates/my_practice/analytics.html:294 +#: templates/my_practice/analytics.html:260 msgid "Average days from invoice date to payment received" msgstr "" -#: templates/my_practice/analytics.html:328 +#: templates/my_practice/analytics.html:278 msgid "days" msgstr "" -#: templates/my_practice/analytics.html:339 +#: templates/my_practice/analytics.html:289 #: templates/my_practice/client_list_cards.html:6 msgid "Client overview" msgstr "" -#: templates/my_practice/analytics.html:343 +#: templates/my_practice/analytics.html:293 msgid "Top 10 Clients by Revenue" msgstr "" -#: templates/my_practice/analytics.html:349 +#: templates/my_practice/analytics.html:299 msgid "Rank" msgstr "" -#: templates/my_practice/analytics.html:352 -#: templates/my_practice/analytics.html:595 +#: templates/my_practice/analytics.html:302 +#: templates/my_practice/analytics.html:545 msgid "Hours" msgstr "" -#: templates/my_practice/analytics.html:353 +#: templates/my_practice/analytics.html:303 #: templates/my_practice/client_detail.html:237 #: templates/my_practice/revenue_report.html:26 #: templates/my_practice/tax_year_summary.html:37 @@ -5205,295 +5262,296 @@ msgstr "" msgid "Total revenue" msgstr "" -#: templates/my_practice/analytics.html:374 +#: templates/my_practice/analytics.html:324 msgid "No revenue data available" msgstr "" -#: templates/my_practice/analytics.html:381 +#: templates/my_practice/analytics.html:331 #, python-format msgid "Client Details (%(label)s)" msgstr "" -#: templates/my_practice/analytics.html:387 +#: templates/my_practice/analytics.html:337 msgid "Show dormant clients" msgstr "" -#: templates/my_practice/analytics.html:398 +#: templates/my_practice/analytics.html:348 msgid "Sessions (period)" msgstr "" -#: templates/my_practice/analytics.html:399 +#: templates/my_practice/analytics.html:349 msgid "Total Sessions" msgstr "" -#: templates/my_practice/analytics.html:415 +#: templates/my_practice/analytics.html:365 msgid "Probatoric" msgstr "" -#: templates/my_practice/analytics.html:419 +#: templates/my_practice/analytics.html:369 msgid "Established" msgstr "" -#: templates/my_practice/analytics.html:421 +#: templates/my_practice/analytics.html:371 msgid "Dormant" msgstr "" -#: templates/my_practice/analytics.html:428 +#: templates/my_practice/analytics.html:378 #: templates/my_practice/client_detail.html:230 msgid "💻 Online" msgstr "" -#: templates/my_practice/analytics.html:430 +#: templates/my_practice/analytics.html:380 msgid "In-person" msgstr "" -#: templates/my_practice/analytics.html:440 +#: templates/my_practice/analytics.html:390 msgid "No client data for this period." msgstr "" -#: templates/my_practice/analytics.html:469 +#: templates/my_practice/analytics.html:419 msgid "Session Type Distribution" msgstr "" -#: templates/my_practice/analytics.html:476 +#: templates/my_practice/analytics.html:426 msgid "Total sessions" msgstr "" -#: templates/my_practice/analytics.html:495 +#: templates/my_practice/analytics.html:445 msgid "No session data available" msgstr "" -#: templates/my_practice/analytics.html:507 +#: templates/my_practice/analytics.html:457 msgid "Capacity & Utilisation" msgstr "" -#: templates/my_practice/analytics.html:513 +#: templates/my_practice/analytics.html:463 msgid "Key Insights" msgstr "" -#: templates/my_practice/analytics.html:526 +#: templates/my_practice/analytics.html:476 msgid "Active Clients" msgstr "" -#: templates/my_practice/analytics.html:531 +#: templates/my_practice/analytics.html:481 msgid "Booked Sessions" msgstr "" -#: templates/my_practice/analytics.html:536 +#: templates/my_practice/analytics.html:486 msgid "Capacity Used" msgstr "" -#: templates/my_practice/analytics.html:544 +#: templates/my_practice/analytics.html:494 #, python-format msgid "Bookings until %(date)s" msgstr "" -#: templates/my_practice/analytics.html:551 +#: templates/my_practice/analytics.html:501 msgid "Days Off" msgstr "" -#: templates/my_practice/analytics.html:557 +#: templates/my_practice/analytics.html:507 msgid "Capacity Analysis" msgstr "" -#: templates/my_practice/analytics.html:557 +#: templates/my_practice/analytics.html:507 #: templates/my_practice/checklist.html:68 #, python-format msgid "until %(date)s" msgstr "" -#: templates/my_practice/analytics.html:560 +#: templates/my_practice/analytics.html:510 #: templates/my_practice/tag_confirm_delete.html:24 msgid "Note:" msgstr "" -#: templates/my_practice/analytics.html:560 +#: templates/my_practice/analytics.html:510 #, python-format msgid "For future-oriented periods only the period until %(date)s (2 weeks from today) is considered, as most clients book at short notice." msgstr "" -#: templates/my_practice/analytics.html:567 +#: templates/my_practice/analytics.html:517 msgid "Available Hours" msgstr "" -#: templates/my_practice/analytics.html:571 +#: templates/my_practice/analytics.html:521 msgid "Booked Hours" msgstr "" -#: templates/my_practice/analytics.html:575 +#: templates/my_practice/analytics.html:525 msgid "Free Capacity" msgstr "" -#: templates/my_practice/analytics.html:579 +#: templates/my_practice/analytics.html:529 msgid "Working Days" msgstr "" -#: templates/my_practice/analytics.html:587 +#: templates/my_practice/analytics.html:537 msgid "4-Quarter Trends" msgstr "" -#: templates/my_practice/analytics.html:592 +#: templates/my_practice/analytics.html:542 #: templates/my_practice/tax_quarter_overview.html:76 msgid "Quarter" msgstr "" -#: templates/my_practice/analytics.html:593 +#: templates/my_practice/analytics.html:543 #, python-format msgid "Capacity %%" msgstr "" -#: templates/my_practice/analytics.html:616 +#: templates/my_practice/analytics.html:566 #, python-format msgid "Time off in %(label)s" msgstr "" -#: templates/my_practice/analytics.html:622 +#: templates/my_practice/analytics.html:572 msgid "Days" msgstr "" -#: templates/my_practice/analytics.html:634 +#: templates/my_practice/analytics.html:584 #, python-format msgid "Time off %(label)s" msgstr "" -#: templates/my_practice/analytics.html:636 +#: templates/my_practice/analytics.html:586 msgid "Days off in selected period" msgstr "" -#: templates/my_practice/analytics.html:641 +#: templates/my_practice/analytics.html:591 msgid "Total days" msgstr "" -#: templates/my_practice/analytics.html:645 +#: templates/my_practice/analytics.html:595 msgid "Weeks" msgstr "" -#: templates/my_practice/analytics.html:649 +#: templates/my_practice/analytics.html:599 msgid "Working days off" msgstr "" -#: templates/my_practice/analytics.html:657 +#: templates/my_practice/analytics.html:607 msgid "Time Off by Year" msgstr "" -#: templates/my_practice/analytics.html:663 +#: templates/my_practice/analytics.html:613 msgid "Workdays" msgstr "" -#: templates/my_practice/analytics.html:664 +#: templates/my_practice/analytics.html:614 msgid "Wk." msgstr "" -#: templates/my_practice/analytics.html:666 +#: templates/my_practice/analytics.html:616 msgid "Training" msgstr "" -#: templates/my_practice/analytics.html:667 +#: templates/my_practice/analytics.html:617 msgid "Sick" msgstr "" -#: templates/my_practice/analytics.html:689 +#: templates/my_practice/analytics.html:639 msgid "Capacity Utilisation Over Time" msgstr "" -#: templates/my_practice/analytics.html:641 +#: templates/my_practice/analytics.html:642 #, python-format msgid "Monthly utilisation in %% of your weekly target:" msgstr "" -#: templates/my_practice/analytics.html:642 +#: templates/my_practice/analytics.html:643 #, python-format msgid "%(hours)s h/week from %(start)s" msgstr "" -#: templates/my_practice/analytics.html:644 +#: templates/my_practice/analytics.html:645 msgid "No weekly target set yet." msgstr "" -#: templates/my_practice/analytics.html:645 +#: templates/my_practice/analytics.html:646 msgid "Set target hours in the practice settings" msgstr "" -#: templates/my_practice/analytics.html:733 +#: templates/my_practice/analytics.html:671 +#: templates/my_practice/analytics.html:673 msgid "Utilisation" msgstr "" -#: templates/my_practice/analytics.html:734 +#: templates/my_practice/analytics.html:674 msgid "Booked" msgstr "" -#: templates/my_practice/analytics.html:745 +#: templates/my_practice/analytics.html:685 msgid "Year Comparison – Hours per Month" msgstr "" -#: templates/my_practice/analytics.html:747 +#: templates/my_practice/analytics.html:687 msgid "Therapy hours per calendar month (last 4 years + average)" msgstr "" -#: templates/my_practice/analytics.html:831 +#: templates/my_practice/analytics.html:710 msgid "Avg" msgstr "" -#: templates/my_practice/analytics.html:854 +#: templates/my_practice/analytics.html:726 msgid "Seasonality" msgstr "" -#: templates/my_practice/analytics.html:856 +#: templates/my_practice/analytics.html:728 msgid "Average utilisation per calendar month (Ø over all years, incl. time off)" msgstr "" -#: templates/my_practice/analytics.html:878 +#: templates/my_practice/analytics.html:750 msgid "Cancellation Rate" msgstr "" -#: templates/my_practice/analytics.html:880 +#: templates/my_practice/analytics.html:752 #, python-format msgid "Cancelled sessions in %% of all sessions per month" msgstr "" -#: templates/my_practice/analytics.html:881 +#: templates/my_practice/analytics.html:753 #, python-format msgid "since %(start)s, not counting cancellations during your own time off" msgstr "" -#: templates/my_practice/analytics.html:916 +#: templates/my_practice/analytics.html:771 msgid "Cancellation rate" msgstr "" -#: templates/my_practice/analytics.html:928 +#: templates/my_practice/analytics.html:783 msgid "Expense Overview" msgstr "" -#: templates/my_practice/analytics.html:933 +#: templates/my_practice/analytics.html:788 msgid "Manage Expenses" msgstr "" -#: templates/my_practice/analytics.html:936 +#: templates/my_practice/analytics.html:791 msgid "Manage Withdrawals" msgstr "" -#: templates/my_practice/analytics.html:942 +#: templates/my_practice/analytics.html:797 msgid "Expenses by Category" msgstr "" -#: templates/my_practice/analytics.html:949 +#: templates/my_practice/analytics.html:804 msgid "Total Expenses" msgstr "" -#: templates/my_practice/analytics.html:968 +#: templates/my_practice/analytics.html:823 msgid "No expense data available" msgstr "" -#: templates/my_practice/analytics.html:974 +#: templates/my_practice/analytics.html:829 msgid "Expense Trends" msgstr "" -#: templates/my_practice/analytics.html:976 +#: templates/my_practice/analytics.html:831 #, python-format msgid "Annual operating expenses %(start_year)s–today" msgstr "" -#: templates/my_practice/analytics.html:1081 +#: templates/my_practice/analytics.html:921 #: templates/my_practice/checklist.html:38 msgid "Back to overview" msgstr "" @@ -5708,10 +5766,6 @@ msgstr "" msgid "This transaction can be ignored" msgstr "" -#: templates/my_practice/bank_review.html:240 -msgid "Capital contribution from private account" -msgstr "" - #: templates/my_practice/bank_review.html:242 msgid "This transaction was transferred from the stored private bank account." msgstr "" @@ -6646,7 +6700,7 @@ msgid "Supervision topic or question…" msgstr "Supervision topic or question…" #: templates/my_practice/client_detail.html:380 -#: templates/my_practice/inquiry_list.html:30 +#: templates/my_practice/inquiry_list.html:35 msgid "Add" msgstr "Add" @@ -6944,9 +6998,9 @@ msgstr "" #: templates/my_practice/client_list_cards.html:124 #: templates/my_practice/expense_form.html:103 #: templates/my_practice/expense_list.html:129 -#: templates/my_practice/inquiry_list.html:27 -#: templates/my_practice/inquiry_list.html:210 -#: templates/my_practice/inquiry_list.html:258 +#: templates/my_practice/inquiry_list.html:32 +#: templates/my_practice/inquiry_list.html:230 +#: templates/my_practice/inquiry_list.html:278 #: templates/my_practice/invoice_detail.html:217 #: templates/my_practice/invoice_edit.html:90 #: templates/my_practice/invoice_form.html:81 @@ -7449,85 +7503,96 @@ msgstr "" msgid "Available codes:" msgstr "" -#: templates/my_practice/inquiry_list.html:10 +#: templates/my_practice/inquiry_list.html:15 msgid "Prospective clients & inquiry management" msgstr "" -#: templates/my_practice/inquiry_list.html:21 +#: templates/my_practice/inquiry_list.html:26 msgid "Marketing periods:" msgstr "" -#: templates/my_practice/inquiry_list.html:38 +#: templates/my_practice/inquiry_list.html:43 msgid "total" msgstr "" -#: templates/my_practice/inquiry_list.html:40 +#: templates/my_practice/inquiry_list.html:45 msgid "closed" msgstr "" -#: templates/my_practice/inquiry_list.html:61 +#: templates/my_practice/inquiry_list.html:66 #, python-format msgid "%(n)s closed (Declined / No match / Unreachable)" msgstr "" -#: templates/my_practice/inquiry_list.html:67 +#: templates/my_practice/inquiry_list.html:72 msgid "Avg. wait (working days)" msgstr "" -#: templates/my_practice/inquiry_list.html:74 +#: templates/my_practice/inquiry_list.html:79 #, python-format msgid "%(avg)s working days (n=%(n)s)" msgstr "" -#: templates/my_practice/inquiry_list.html:85 +#: templates/my_practice/inquiry_list.html:90 msgid "Sources" msgstr "" -#: templates/my_practice/inquiry_list.html:120 +#: templates/my_practice/inquiry_list.html:124 msgid "Inquiries per month (last 12 months)" msgstr "" -#: templates/my_practice/inquiry_list.html:142 +#: templates/my_practice/inquiry_list.html:136 +msgid "Open inquiries: days since last step" +msgstr "" + +#: templates/my_practice/inquiry_list.html:146 +#, python-format +msgid "%(days)s day" +msgid_plural "%(days)s days" +msgstr[0] "" +msgstr[1] "" + +#: templates/my_practice/inquiry_list.html:162 msgid "All statuses" msgstr "" -#: templates/my_practice/inquiry_list.html:148 +#: templates/my_practice/inquiry_list.html:168 msgid "All sources" msgstr "" -#: templates/my_practice/inquiry_list.html:154 +#: templates/my_practice/inquiry_list.html:174 msgid "Clear filters" msgstr "" -#: templates/my_practice/inquiry_list.html:160 +#: templates/my_practice/inquiry_list.html:180 msgid "Hide closed" msgstr "" -#: templates/my_practice/inquiry_list.html:162 +#: templates/my_practice/inquiry_list.html:182 #, python-format msgid "Show closed (%(n)s)" msgstr "" -#: templates/my_practice/inquiry_list.html:196 -#: templates/my_practice/inquiry_list.html:244 +#: templates/my_practice/inquiry_list.html:216 +#: templates/my_practice/inquiry_list.html:264 msgid "View client" msgstr "" -#: templates/my_practice/inquiry_list.html:208 -#: templates/my_practice/inquiry_list.html:256 +#: templates/my_practice/inquiry_list.html:228 +#: templates/my_practice/inquiry_list.html:276 msgid "Admit" msgstr "" -#: templates/my_practice/inquiry_list.html:223 +#: templates/my_practice/inquiry_list.html:243 #, python-format msgid "%(n)s older (inactive > 30 days)" msgstr "" -#: templates/my_practice/inquiry_list.html:272 +#: templates/my_practice/inquiry_list.html:292 msgid "No inquiries found." msgstr "" -#: templates/my_practice/inquiry_list.html:273 +#: templates/my_practice/inquiry_list.html:293 msgid "Record first inquiry" msgstr "" @@ -9231,37 +9296,6 @@ msgstr "" msgid "Turn on two-factor sign-in" msgstr "" -#: templates/base.html:104 -msgid "Sign out" -msgstr "" - -#: my_practice/utils/bank_import.py:483 -msgid "Erroneous booking / correction from private account" -msgstr "" - -#: my_practice/utils/bank_import.py:501 -msgid "Own payment (capital contribution), ignored automatically" -msgstr "" - -#: my_practice/views/bank_import_views.py:488 -#, python-format -msgid "Combined payment for: %(numbers)s" -msgstr "" - -#: my_practice/views/bank_import_views.py:534 -#, python-format -msgid "Created automatically on confirming the payment of %(date)s" -msgstr "" - -#: my_practice/views/bank_import_views.py:544 -#, python-format -msgid "Created during the bank import of %(date)s" -msgstr "" - -#: templates/my_practice/analytics.html:220 -msgid "Trend" -msgstr "" - #~ msgid "Error sending the email: %(error)s" #~ msgstr "Error sending the email: %(error)s" diff --git a/app/my_practice/tests/test_css_tokens.py b/app/my_practice/tests/test_css_tokens.py index a6da39f..85a1681 100644 --- a/app/my_practice/tests/test_css_tokens.py +++ b/app/my_practice/tests/test_css_tokens.py @@ -68,7 +68,6 @@ ".timeoff-table__", ".progress-bar-fill", ".chart-bar", - ".monthly-bar", ".summary-table", ".summary-cards", ".tax-summary-container", diff --git a/app/my_practice/tests/test_inquiry.py b/app/my_practice/tests/test_inquiry.py index 99bb6cf..d6f04be 100644 --- a/app/my_practice/tests/test_inquiry.py +++ b/app/my_practice/tests/test_inquiry.py @@ -13,9 +13,11 @@ ClientInquiry, InquirySource, InquiryStatus, + MarketingPeriod, Practice, UserPractice, ) +from my_practice.views.inquiry_views import _monthly_chart, _open_inquiry_ageing def _make_user_and_practice(username="testuser"): @@ -304,3 +306,87 @@ def test_convert_scoped_to_practice(self): }, ) self.assertEqual(resp.status_code, 404) + + +class InquiryChartTestCase(TestCase): + """The monthly chart data and the open-inquiry ageing list on the inquiry page.""" + + def setUp(self): + _, self.practice = _make_user_and_practice() + self.today = date(2026, 10, 21) + + def _qs(self): + return ClientInquiry.objects.filter(practice=self.practice) + + def test_monthly_chart_lists_every_month_including_empty_ones(self): + _make_inquiry(self.practice, inquiry_date=date(2026, 4, 2)) + _make_inquiry(self.practice, inquiry_date=date(2026, 4, 20)) + _make_inquiry(self.practice, inquiry_date=date(2025, 10, 31)) # before the window + chart = _monthly_chart(self._qs(), self.practice, self.today) + self.assertEqual(len(chart["labels"]), 12) + self.assertEqual(chart["labels"][0], "11/25") + self.assertEqual(chart["labels"][-1], "10/26") + self.assertEqual(chart["counts"][chart["labels"].index("04/26")], 2) + self.assertEqual(sum(chart["counts"]), 2) + + def test_monthly_chart_places_marketing_periods_in_bar_slots(self): + MarketingPeriod.objects.create( + practice=self.practice, + start_date=date(2026, 3, 1), + end_date=date(2026, 6, 30), + description="Ads", + ) + MarketingPeriod.objects.create( + practice=self.practice, start_date=date(2025, 9, 8), description="Directory" + ) + MarketingPeriod.objects.create( + practice=self.practice, + start_date=date(2024, 1, 1), + end_date=date(2024, 12, 31), + description="Long gone", + ) + lanes = _monthly_chart(self._qs(), self.practice, self.today)["lanes"] + self.assertEqual([lane["label"] for lane in lanes], ["Directory", "Ads"]) + # Started before the window and still running: spans the whole axis. + self.assertEqual((lanes[0]["from"], lanes[0]["to"]), (-0.5, 11.5)) + # March is slot 4; a whole-month period fills March through June exactly. + self.assertEqual((lanes[1]["from"], lanes[1]["to"]), (3.5, 7.5)) + + def test_monthly_chart_scoped_to_practice(self): + _, other = _make_user_and_practice(username="other") + _make_inquiry(other, inquiry_date=date(2026, 5, 1)) + MarketingPeriod.objects.create(practice=other, start_date=date(2026, 1, 1), description="X") + chart = _monthly_chart(self._qs(), self.practice, self.today) + self.assertEqual(sum(chart["counts"]), 0) + self.assertEqual(chart["lanes"], []) + + def test_ageing_uses_latest_step_and_sorts_longest_first(self): + waiting = _make_inquiry( + self.practice, + status=InquiryStatus.CONTACTED, + inquiry_date=date(2026, 8, 1), + contacted_date=date(2026, 8, 3), + ) + booked = _make_inquiry( + self.practice, + status=InquiryStatus.INTRO_MEETING, + inquiry_date=date(2026, 10, 1), + intro_date=date(2026, 10, 28), # still ahead + ) + _make_inquiry(self.practice, status=InquiryStatus.CONVERTED) + rows = _open_inquiry_ageing(self._qs(), self.today) + self.assertEqual([row["inquiry"] for row in rows], [waiting, booked]) + self.assertEqual(rows[0]["days"], 79) + self.assertEqual(rows[0]["step_date"], date(2026, 8, 3)) + self.assertTrue(rows[0]["stale"]) + self.assertEqual(rows[0]["pct"], 100) + self.assertEqual(rows[1]["days"], 0) + self.assertFalse(rows[1]["stale"]) + + def test_list_page_renders_charts(self): + user = User.objects.get(username="testuser") + self.client.force_login(user) + _make_inquiry(self.practice, inquiry_date=date(2026, 9, 1)) + resp = self.client.get(reverse("inquiry_list")) + self.assertContains(resp, 'id="inquiryMonthlyChart"') + self.assertContains(resp, "ageing-row") diff --git a/app/my_practice/views/inquiry_views.py b/app/my_practice/views/inquiry_views.py index 91a018c..0782531 100644 --- a/app/my_practice/views/inquiry_views.py +++ b/app/my_practice/views/inquiry_views.py @@ -1,5 +1,6 @@ """Views for client inquiry / lead tracking (P-031).""" +import calendar from datetime import date, timedelta from itertools import groupby from typing import cast @@ -10,6 +11,7 @@ Case, Count, IntegerField, + Q, Value, When, ) @@ -62,9 +64,101 @@ def _sub(text: str) -> str: return result +# Months shown in the monthly inquiry chart, ending with the current month. +_CHART_MONTHS = 12 + +# An open inquiry with no new step for this long counts as stale — the same +# threshold the grouped list below uses to fold rows away. +_STALE_DAYS = 30 + + +def _month_offset(first_month: date, day: date) -> float: + """Position of `day` on a month axis starting at `first_month`, in bar slots. + + Slot i is centred on i, so its month starts at i - 0.5; the day's fraction + of its month places it inside the slot. + """ + months = (day.year - first_month.year) * 12 + day.month - first_month.month + days_in_month = calendar.monthrange(day.year, day.month)[1] + return months + (day.day - 1) / days_in_month - 0.5 + + +def _monthly_chart(base_qs, practice, today: date) -> dict: + """Inquiries per month for the last 12 months, plus the marketing periods as lanes. + + Every month is listed, including empty ones — a gap in the bars is itself + the signal (e.g. volume dropping once a paid campaign ended). + """ + first_month = DateRangeHelper.add_months(date(today.year, today.month, 1), 1 - _CHART_MONTHS) + months = [DateRangeHelper.add_months(first_month, i) for i in range(_CHART_MONTHS)] + counts = { + row["month"]: row["count"] + for row in base_qs.filter(inquiry_date__gte=first_month) + .annotate(month=TruncMonth("inquiry_date")) + .values("month") + .annotate(count=Count("id")) + } + + axis_end = _CHART_MONTHS - 0.5 + lanes = [] + periods = MarketingPeriod.objects.filter(practice=practice, start_date__lte=today).filter( + Q(end_date__isnull=True) | Q(end_date__gte=first_month) + ) + for period in periods.order_by("start_date"): + start = max(_month_offset(first_month, period.start_date), -0.5) + if period.end_date is None: + end = axis_end + else: + end = min(_month_offset(first_month, period.end_date + timedelta(days=1)), axis_end) + lanes.append({"label": period.description, "from": round(start, 3), "to": round(end, 3)}) + + return { + "labels": [m.strftime("%m/%y") for m in months], + "counts": [counts.get(m, 0) for m in months], + "lanes": lanes, + } + + +def _open_inquiry_ageing(base_qs, today: date) -> list[dict]: + """Open inquiries, longest-waiting first, with the days since their latest step. + + The latest step is the newest milestone date that is set (received, + responded, intro meeting, decision). A milestone in the future — an intro + meeting already booked — counts as zero days: nothing is overdue yet. + """ + steps = [ + ("inquiry_date", _("Received")), + ("contacted_date", _("Responded")), + ("intro_date", _("Intro meeting")), + ("decision_date", _("Decision")), + ] + rows = [] + for inquiry in base_qs.open(): + step_date, step_label = max( + ((getattr(inquiry, field), label) for field, label in steps if getattr(inquiry, field)), + key=lambda pair: pair[0], + ) + days = max((today - step_date).days, 0) + rows.append( + { + "inquiry": inquiry, + "days": days, + "step": step_label, + "step_date": step_date, + "stale": days > _STALE_DAYS, + } + ) + rows.sort(key=lambda row: row["days"], reverse=True) + longest = rows[0]["days"] if rows else 0 + for row in rows: + row["pct"] = round(100 * row["days"] / longest) if longest else 0 + return rows + + def _build_inquiry_analytics(request) -> dict: """Compute funnel counts, time-in-stage averages, source breakdown, and monthly trend.""" base_qs = ClientInquiry.objects.for_current_practice(request) + today = timezone.localdate() # --- Funnel counts by status --- status_counts: dict[str, int] = { @@ -150,34 +244,14 @@ def _avg_days(from_field: str, to_field: str) -> tuple[float | None, int]: for r in lang_rows ] - # --- Monthly trend (last 12 months, by inquiry_date) --- - range_start = DateRangeHelper.add_months( - date(timezone.localdate().year, timezone.localdate().month, 1), -11 - ) - monthly_raw = ( - base_qs.filter(inquiry_date__gte=range_start) - .annotate(month=TruncMonth("inquiry_date")) - .values("month") - .annotate(count=Count("id")) - .order_by("month") - ) - max_monthly = max((row["count"] for row in monthly_raw), default=1) - monthly_trend = [ - { - "month": row["month"].strftime("%b %y"), - "count": row["count"], - "pct": round(100 * row["count"] / max_monthly), - } - for row in monthly_raw - ] - return { "funnel_stages": funnel_stages, "closed_count": closed_count, "time_in_stage": time_in_stage, "source_breakdown": source_breakdown, "language_breakdown": language_breakdown, - "monthly_trend": monthly_trend, + "monthly_chart": _monthly_chart(base_qs, request.current_practice, today), + "open_ageing": _open_inquiry_ageing(base_qs, today), "total_inquiries": sum(status_counts.values()), } diff --git a/app/static/css/tailwind.css b/app/static/css/tailwind.css index 69aacd1..093a310 100644 --- a/app/static/css/tailwind.css +++ b/app/static/css/tailwind.css @@ -892,12 +892,14 @@ .source-bar-wrap { flex: 1; background: var(--color-bg-muted); border-radius: 3px; height: 8px; overflow: hidden; } .source-bar { height: 100%; background: var(--color-badge-blue-bg); border-radius: 3px; min-width: 2px; } .source-count { font-size: 0.82rem; font-weight: 600; min-width: 1.5rem; text-align: right; } - .monthly-bars { display: flex; align-items: flex-end; gap: 0.3rem; height: 4rem; } - .monthly-bar-col { display: flex; flex-direction: column; align-items: center; flex: 1; height: 100%; justify-content: flex-end; } - .monthly-bar-wrap { width: 100%; height: 100%; display: flex; align-items: flex-end; } - .monthly-bar { width: 100%; background: var(--color-badge-blue-text, #3182ce); border-radius: 2px 2px 0 0; min-height: 2px; opacity: 0.75; } - .monthly-count { font-size: 0.7rem; font-weight: 600; color: var(--color-text-muted); line-height: 1; margin-bottom: 0.15rem; } - .monthly-label { font-size: 0.65rem; color: var(--color-text-muted); margin-top: 0.25rem; white-space: nowrap; } + .ageing-list { display: flex; flex-direction: column; gap: 0.3rem; } + .ageing-row { display: grid; grid-template-columns: minmax(8rem, 12rem) 7.5rem 1fr 10rem; align-items: center; gap: 0.6rem; font-size: 0.85rem; } + .ageing-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } + .ageing-row .status-badge { justify-self: start; font-size: 0.72rem; } + .ageing-bar { height: 100%; background: var(--color-chart-1); border-radius: 3px; min-width: 2px; } + .ageing-bar--stale { background: var(--color-warning); } + .ageing-days { font-weight: 600; white-space: nowrap; } + .ageing-step { font-weight: 400; color: var(--color-text-muted); } .milestone-dates-fieldset { border: 1px solid var(--color-border); border-radius: 6px; padding: 0.75rem 1rem; margin-bottom: 1rem; } .milestone-dates-fieldset legend { padding: 0 0.4rem; font-size: 0.85rem; font-weight: 600; color: var(--color-text-muted); } .fieldset-hint { font-weight: 400; font-size: 0.78rem; } diff --git a/app/static/js/charts.js b/app/static/js/charts.js index b146040..b424fd8 100644 --- a/app/static/js/charts.js +++ b/app/static/js/charts.js @@ -11,6 +11,11 @@ * * Labels in "MM/YY" form ("01/25") get a month axis: every January is marked * with its year and a dashed separator, other months thin out to quarters. + * + * A bar chart's `lanes` ([{label, from, to}], positions in bar slots — slot i + * spans i - 0.5 … i + 0.5) are drawn as labelled strips above the bars, one + * row each so overlapping periods stay readable, with a dashed line wherever + * a lane starts or ends inside the axis. */ (function (root) { "use strict"; @@ -101,6 +106,55 @@ Chart.defaults.animation = false; Chart.defaults.plugins.tooltip.padding = 10; + const LANE_HEIGHT = 18; + const LANE_COLOURS = ["chart3", "chart2", "chart5", "chart6"]; + + // Labelled strips above the plot area, e.g. marketing periods on a month axis. + const lanes = { + id: "lanes", + beforeDatasetsDraw: function (chart, _args, opts) { + if (!opts.items || !opts.items.length) return; + const x = chart.scales.x; + const area = chart.chartArea; + const n = chart.data.labels.length; + const step = n > 1 ? x.getPixelForValue(1) - x.getPixelForValue(0) : area.right - area.left; + const px = function (slot) { + return x.getPixelForValue(0) + slot * step; + }; + const ctx = chart.ctx; + ctx.save(); + ctx.font = "11px " + Chart.defaults.font.family; + ctx.textBaseline = "middle"; + opts.items.forEach(function (lane, row) { + const token = LANE_COLOURS[row % LANE_COLOURS.length]; + const left = px(lane.from); + const right = px(lane.to); + const top = area.top - (opts.items.length - row) * LANE_HEIGHT - 4; + ctx.fillStyle = fade(token, 0.3)(); + ctx.fillRect(left, top, right - left, LANE_HEIGHT - 3); + ctx.save(); + ctx.beginPath(); + ctx.rect(left, top, right - left, LANE_HEIGHT - 3); + ctx.clip(); + ctx.fillStyle = theme.text; + ctx.fillText(lane.label, left + 4, top + (LANE_HEIGHT - 3) / 2); + ctx.restore(); + + ctx.strokeStyle = colour(token)(); + ctx.setLineDash([3, 3]); + [lane.from, lane.to].forEach(function (slot) { + if (slot <= -0.5 || slot >= n - 0.5) return; + ctx.beginPath(); + ctx.moveTo(px(slot), top + LANE_HEIGHT - 3); + ctx.lineTo(px(slot), area.bottom); + ctx.stroke(); + }); + ctx.setLineDash([]); + }); + ctx.restore(); + }, + }; + // Dashed line before each January on a month axis. const yearSeparators = { id: "yearSeparators", @@ -270,7 +324,7 @@ }); } - /** Bar chart; several series give grouped bars with a legend. */ + /** Bar chart; several series give grouped bars with a legend. lanes: see the header. */ function bar(canvas, opts) { const datasets = opts.series.map(function (s) { return { @@ -281,13 +335,16 @@ maxBarThickness: 80, }; }); + const laneItems = opts.lanes || []; return make(canvas, { type: "bar", data: { labels: opts.labels, datasets: datasets }, options: { interaction: { mode: "index", intersect: false }, + layout: { padding: { top: laneItems.length ? laneItems.length * LANE_HEIGHT + 6 : 0 } }, scales: scales(opts), plugins: { + lanes: { items: laneItems }, legend: { display: datasets.length > 1, position: "top", @@ -297,6 +354,7 @@ tooltip: tooltip(opts), }, }, + plugins: [lanes], }); } diff --git a/app/templates/my_practice/inquiry_list.html b/app/templates/my_practice/inquiry_list.html index 23cca11..2306fc0 100644 --- a/app/templates/my_practice/inquiry_list.html +++ b/app/templates/my_practice/inquiry_list.html @@ -5,6 +5,11 @@ {% block title %}{% trans "Inquiries" %}{% endblock %} +{% block extra_head_scripts %} + + +{% endblock %} + {% block page_icon %}📬{% endblock %} {% block page_title %}{% trans "Inquiries" %}{% endblock %} {% block page_subtitle %}{% trans "Prospective clients & inquiry management" %}{% endblock %} @@ -114,18 +119,33 @@