fix: analytics charts — year separators, partial month, dead code, i18n#153
Merged
dholbach merged 1 commit intoJul 2, 2026
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
findFirstNonZeroIndex(year labels were shifted by however many leading months were trimmed)_build_holiday_set()incapacity_helpers.py; replace manual month-end arithmetic withDateRangeHelper.get_last_of_month;get_capacity_trendsloop delegates to_calculate_weighted_capacityinstead of duplicating the formulasetupTooltip,setupBarChart,drawXAxisLabels,calculateYearLabels;drawSimpleBarChartinline label replaced withdrawYearLabel()call;chart_tooltip.jsscript tag removedCHART_MESSAGESJS global for canvas empty-state strings;LOCALEfromnavigator.languageinstead of hardcoded'de-DE';MONTH_LABELSand'Ø'legend wrapped with{% trans %};practice_analysis.pyinsight strings and"Arbeitstage"wrapped withgettext/ngettext; German translations added todjango.poDetails
Partial month guard
Both
get_capacity_trends(capacity_helpers.py) and_get_monthly_aggregation(analytics_utils.py) now capend_dateat 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
findFirstNonZeroIndexslices leading zero-months before rendering, butdrawYearSeparators/drawYearLabelsassumed index 0 = January ofstartYear. 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 parsestartMonthfrom their first label and pass it through.revenueLineChartalso had{{ month.month|slice:":3" }}which truncated"01/20"to"01/", makingparseMonthStringreturn null. Now emits full"MM/YY"labels.Test plan
./dev.py testpasses🤖 Generated with Claude Code