whisper-money/config
Víctor Falcón 02b6892489
feat(currencies): add the Danish Krone (DKK) (#754)
## What

Adds the **Danish Krone (DKK)** as both a user primary currency and an
account currency.

Per `docs/adding-a-currency.md` this is a config change — validation
(`ProfileUpdateRequest`, `StoreAccountRequest`, `UpdateAccountRequest`),
the Inertia dropdown props and conversion all derive from
`config/currencies.php`.

Both pre-checks in the doc pass:

- `DKK` is the current ISO 4217 code (no deprecated-code trap like
`GHC`/`GHS`).
- The provider covers it: `EUR→DKK = 7.4754`, consistent with the ERM II
peg (~7.46).

## Closing the translation gap

Currency names are translated in PHP by `CurrencyOptions`, so they never
appear as literal `__()` keys in the TS/TSX source — `LocalizationTest`
never saw them, and a missing Spanish name silently shipped the English
one. The doc even warned about it.

`LocalizationTest` now feeds the configured currency names into its
translatable-key check, so Spanish is enforced and French warns, exactly
like every other key. That surfaced pre-existing gaps, now filled:

- Spanish: PKR, BRL, DOP, SAR
- French: those four plus NGN

## Also

Dropped the docs' "add a symbol" step. `getCurrencySymbol` has no
callers left — every consumer of `utils/currency` imports
`formatCurrency` only — so entries in its map change nothing on screen.
Removing the function itself is a separate cleanup.

## QA

Real browser QA against the running app, in Spanish:

- `DKK - Corona danesa` appears in the profile currency select; saving
persists `users.currency_code = 'DKK'` and survives a reload.
- `DKK - Corona danesa` appears in the create-account currency select;
created a `Danske Bank Private` account and confirmed
`accounts.currency_code = 'DKK'`.
- Conversion both ways: `100 EUR → 747.68 DKK`, `100 DKK → 13.38 EUR`.
- `LocalizationTest` + `CurrencyConversionServiceTest` green; `pint`,
`phpstan`, `prettier`, `eslint` clean.

## Demo

<!-- PLACEHOLDER: drag the video here -->
**⬆️ Attach `~/Downloads/dkk-currency-qa.mp4` here.**

## Follow-up (out of scope)

Prod already holds accounts and users on currencies that aren't in the
config (PLN, MAD, PHP).
`AccountUserCurrencyService::resolveImportedCurrency` accepts whatever a
bank reports and `forceFill`s it onto `users.currency_code`, bypassing
validation — so those users can't save **any** profile change, and their
currency select renders empty. Worth a separate issue: either
validate/fall back on import, or make the selects tolerate an
out-of-list current value.
2026-08-10 12:08:56 +02:00
..
ai_categorization.php feat(ai): make the AI provider configurable (any laravel/ai provider, incl. local Ollama) (#718) 2026-07-22 09:01:51 +02:00
ai_reports.php feat(stats): post the Discord stats reports in Spanish, opened by an AI summary (#752) 2026-08-10 10:13:40 +02:00
ai_suggestions.php feat(ai): make the AI provider configurable (any laravel/ai provider, incl. local Ollama) (#718) 2026-07-22 09:01:51 +02:00
app.php feat(demo): gate demo account access behind a config flag (#580) 2026-06-22 11:01:27 +00:00
auth.php fix(auth): make build deterministic when REGISTRATION_ENABLED=false (#720) 2026-07-22 07:04:20 +00:00
cache.php chore: upgrade Laravel 12 to 13 (#242) 2026-03-25 12:56:33 +00:00
cashier.php feat(pricing): dynamic Stripe pricing with locale-aware formatting (#204) 2026-03-05 11:41:59 +00:00
currencies.php feat(currencies): add the Danish Krone (DKK) (#754) 2026-08-10 12:08:56 +02:00
database.php feat(console): add agent:db command for querying local and prod DB (#522) 2026-06-12 18:35:14 +02:00
filesystems.php Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
fortify.php fix(auth): make build deterministic when REGISTRATION_ENABLED=false (#720) 2026-07-22 07:04:20 +00:00
inertia.php Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
logging.php fix(logging): keep laravel.log writable across container UIDs (#451) 2026-05-29 15:10:50 +02:00
mail.php feat(mail): use AWS SES for email delivery (#422) 2026-05-25 10:59:57 +02:00
mcp.php fix(mcp): serve OAuth authorize on a dedicated host so the PWA can't capture it (#709) 2026-07-21 13:51:03 +02:00
passport.php feat(mcp): add OAuth 2.1 for Claude Desktop & ChatGPT connectors (Phase 3) (#691) 2026-07-17 19:10:48 +02:00
pennant.php Add Cashflow Analytics Feature (#49) 2026-01-05 13:06:50 +01:00
queue.php fix(queue): raise retry_after above the longest job timeout (PHP-LARAVEL-2D) (#645) 2026-07-05 09:31:23 +00:00
sanctum.php feat(mcp): read-only MCP server for Pro accounts (#689) 2026-07-17 16:54:15 +02:00
sentry.php fix(sentry): only report errors in production (#467) 2026-06-01 12:41:31 +02:00
services.php feat(mcp): serve the ChatGPT app directory domain challenge (#749) 2026-08-10 07:46:49 +00:00
session.php Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
subscriptions.php feat(subscriptions): trial/pricing A/B/C experiment (#600) 2026-06-27 18:00:15 +02:00