Initial import: 10 Radix skills across 3 categories

Kategoriserer danske regnskabs-/ERP-skills, ERP-data-afstemnings-
skill og to devops-workflows (gitea-issue-agent, kanban-workflows)
som Radix-medlemmers AI-agenter kan dele.

Struktur:
  skills/<kategori>/<skill-navn>/SKILL.md
  skills/<kategori>/<skill-navn>/{references,templates,scripts}/

Indekseret af index.json (genereret af scripts/rebuild_index.py).
Kør `python3 scripts/rebuild_index.py --check` i CI for at fange
synkroniseringsfejl.
This commit is contained in:
2026-06-15 14:41:04 +02:00
commit 236053cd7f
30 changed files with 4460 additions and 0 deletions
@@ -0,0 +1,122 @@
# Django Accounting UI Formatting
Former skill: `django-accounting-ui-formatting`.
Use this when changing how money, balances, invoices, payments, totals, or differences are displayed in a Django accounting/reconciliation webapp.
## Core rule
Accounting amounts must be formatted deliberately and consistently. Do not rely on ad-hoc `floatformat:2` everywhere if the app has locale-specific expectations.
For Danish Radix accounting/reconciliation UIs, render amounts with:
- thousands separator: `.`
- decimal separator: `,`
- exactly 2 decimals
- minus sign before the formatted number
Example:
```text
1234567.89 -> 1.234.567,89
-1234567.89 -> -1.234.567,89
0 -> 0,00
```
## Recommended Django implementation
Create a shared template filter in a common app, e.g.:
```text
backend/apps/common/templatetags/amount_format.py
```
Example filter:
```python
from decimal import Decimal, InvalidOperation, ROUND_HALF_UP
from django import template
register = template.Library()
@register.filter
def amount_dk(value):
if value is None or value == "":
return "0,00"
try:
amount = Decimal(str(value)).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
except (InvalidOperation, ValueError, TypeError):
return value
sign = "-" if amount < 0 else ""
amount = abs(amount)
formatted = f"{amount:,.2f}"
return sign + formatted.replace(",", "X").replace(".", ",").replace("X", ".")
```
Ensure `templatetags/__init__.py` exists.
In templates:
```django
{% load amount_format %}
{{ amount|amount_dk }} kr
```
## What to update
Search all relevant templates for amount displays, especially:
- `floatformat:2`
- table columns named Beløb, Sum, Difference, Rest, Betalt
- dashboard cards
- report tables
- invoice/payment status pages
- transaction detail pages
Replace monetary `floatformat:2` with the shared amount filter. Leave percentages, scores, counts, and raw JSON/raw imported data alone unless the user explicitly asks otherwise.
## Tests
Follow TDD for behavior changes:
1. Add a failing unit/template test for the filter:
```python
template = Template("{% load amount_format %}{{ value|amount_dk }}")
assert template.render(Context({"value": Decimal("1234567.89")})) == "1.234.567,89"
```
2. Add at least one rendered-page regression test for the main UI path, asserting:
- formatted amount is present, e.g. `1.234.567,89`
- raw unformatted amount is absent, e.g. `1234567.89`
3. Run the relevant app tests and system check in the project runtime, usually Docker Compose for Radix internal apps:
```bash
docker compose exec -T web python manage.py test apps.core --settings=config.settings.test -v 2
docker compose exec -T web python manage.py check
```
## Verification
Before finalizing:
- Confirm there are no remaining monetary `|floatformat:2` usages in the changed templates.
- Confirm templates that use `amount_dk` include `{% load amount_format %}`.
- Restart the web container if the running app needs to load a new template tag module:
```bash
docker compose restart web
```
## Pitfalls
- Do not alter raw JSON/raw import displays; those are audit data and should preserve original values.
- Do not apply money formatting to percentages or match scores.
- Avoid Python float math for money formatting; use `Decimal` to avoid binary rounding surprises.
- If the app already has a localization/formatting utility, extend that instead of adding a second competing filter.