Skip to content

fix: analytics charts — year separators, partial month, dead code, i18n#153

Merged
dholbach merged 1 commit into
mainfrom
fix/analytics-charts-year-separators-partial-month-i18n
Jul 2, 2026
Merged

fix: analytics charts — year separators, partial month, dead code, i18n#153
dholbach merged 1 commit into
mainfrom
fix/analytics-charts-year-separators-partial-month-i18n

Conversation

@dholbach

@dholbach dholbach commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • Chart correctness: Exclude current partial month from all trend charts (capacity, revenue, expenses) so the last data point is never anomalously low; fix year separator/label misalignment in all 4 line charts that use findFirstNonZeroIndex (year labels were shifted by however many leading months were trimmed)
  • Refactor: Extract _build_holiday_set() in capacity_helpers.py; replace manual month-end arithmetic with DateRangeHelper.get_last_of_month; get_capacity_trends loop delegates to _calculate_weighted_capacity instead of duplicating the formula
  • Dead JS removed: setupTooltip, setupBarChart, drawXAxisLabels, calculateYearLabels; drawSimpleBarChart inline label replaced with drawYearLabel() call; chart_tooltip.js script tag removed
  • i18n (P-039): CHART_MESSAGES JS global for canvas empty-state strings; LOCALE from navigator.language instead of hardcoded 'de-DE'; MONTH_LABELS and 'Ø' legend wrapped with {% trans %}; practice_analysis.py insight strings and "Arbeitstage" wrapped with gettext/ngettext; German translations added to django.po

Details

Partial month guard

Both get_capacity_trends (capacity_helpers.py) and _get_monthly_aggregation (analytics_utils.py) now cap end_date at the last day of the previous complete month when called with a date in the current month. A month with only 2 working days has 8 h capacity — including it makes the last chart point look like a sudden crash.

Year separator alignment

findFirstNonZeroIndex slices leading zero-months before rendering, but drawYearSeparators/drawYearLabels assumed index 0 = January of startYear. If data starts in, e.g., March 2020, the 2021 separator appeared in July 2021 instead of January 2021. All four affected charts (revenueLineChart, daysToPaymentChart, cancellationTrendsChart, capacityTrendsChart) now parse startMonth from their first label and pass it through.

revenueLineChart also had {{ month.month|slice:":3" }} which truncated "01/20" to "01/", making parseMonthString return null. Now emits full "MM/YY" labels.

Test plan

  • Analytics page renders without JS errors on all four tabs
  • Revenue trend chart year labels (2021, 2022, …) align with January of each year
  • Capacity trends chart ends at June 2026 (last complete month), not July
  • Revenue trends chart ends at June 2026
  • Year separators align correctly for all line charts
  • Canvas empty-state messages appear in German
  • Month abbreviations in the year comparison chart are German (Mär, Mai, Okt, Dez)
  • "Avg" legend label renders as "Ø" in German locale
  • ./dev.py test passes

🤖 Generated with Claude Code

Chart correctness:
- Exclude current partial month from capacity and revenue/expense trends
  so the last data point is never anomalously low (e.g. 2 days = 8 h capacity)
- Fix year separator/label misalignment in all line charts: after
  findFirstNonZeroIndex trims leading months, drawYearSeparators and
  drawYearLabels now receive startMonth so index 0 maps to the actual
  first month, not always January of startYear
- Fix revenueLineChart label: removed |slice:":3" that truncated "01/20"
  to "01/" (broke parseMonthString); chart now passes full MM/YY labels
- Add startYear/startMonth to revenueLineChart, daysToPaymentChart,
  cancellationTrendsChart (all were missing startMonth)

capacity_helpers.py refactor:
- Extract _build_holiday_set() — both callers used the same 3-line pattern
- Replace manual month-end arithmetic with DateRangeHelper.get_last_of_month
- get_capacity_trends loop delegates to _calculate_weighted_capacity instead
  of inlining the same formula

Dead JS code removed:
- setupTooltip (chart_tooltip.js) — superseded by ChartTooltip
- setupBarChart (chart_bar.js) — duplicated initializeChart
- drawXAxisLabels (chart_primitives.js) — never called
- calculateYearLabels (chart_math.js) — tested but not wired to rendering
- drawSimpleBarChart inline label replaced with drawYearLabel() call
- chart_tooltip.js script tag removed from analytics.html

i18n (P-039):
- CHART_MESSAGES JS global injected before chart scripts; chart_helpers.js
  uses it with German fallback
- LOCALE global uses navigator.language instead of hardcoded 'de-DE'
- MONTH_LABELS array uses {% trans %} with German msgstrs
- 'Ø' legend label → {% trans "Avg" %} → msgstr "Ø"
- practice_analysis.py: all insight strings and "Arbeitstage" wrapped
  with gettext/ngettext; German translations added to django.po

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dholbach dholbach merged commit 209c3ca into main Jul 2, 2026
1 check passed
@dholbach dholbach deleted the fix/analytics-charts-year-separators-partial-month-i18n branch July 2, 2026 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant