Règles — Taux de change
BR-FX-001 — Taux de change stocké à la date de transaction [DB]
Transaction.fxRate Decimal @db.Decimal(18,8) @default(1)
Snapshot.fxRate Decimal @db.Decimal(18,8) @default(1)
Le taux EUR appliqué au moment de l'import est stocké avec la transaction (et le snapshot). Ce taux est immutable une fois persisté — il ne suit pas les fluctuations futures du marché.
Précision : Decimal(18,8) permet de stocker des taux avec 8 décimales (utile pour les cryptos et les paires exotiques).
BR-FX-002 — Champs amountEur et balanceEur [DB]
Chaque transaction et snapshot stocke deux montants :
| Champ | Contenu |
|---|---|
amount / balance | Montant dans la devise native du compte |
amountEur / balanceEur | Équivalent en EUR au taux fxRate |
Les calculs de net worth et d'analytics utilisent exclusivement amountEur / balanceEur pour agréger des comptes en devises différentes.
BR-FX-003 — État V1 : pas de conversion FX réelle [APP]
En V1, fxRate = 1 et amountEur = amount pour toutes les transactions et tous les snapshots. La gestion multi-devises est prévue en V2 :
// V1 — pas de conversion
balanceEur: data.balance // TODO V2 : conversion FX si currency !== "EUR"
Les comptes en devise étrangère (crypto, devises) auront donc un balanceEur incorrect en V1 — le solde est affiché dans la devise native sans conversion.
BR-FX-004 — Pas de recalcul rétroactif [APP]
Une fois un taux stocké avec une transaction, il ne sera pas recalculé si les taux de change évoluent. C'est cohérent avec la philosophie de Patrimo : chaque transaction est un événement historique figé.
BR-FX-005 — Comparaisons de montants via Prisma [APP]
Pour éviter les erreurs de virgule flottante lors de la détection de transferts internes, la comparaison de montants Decimal utilise le mécanisme Prisma plutôt qu'une comparaison JavaScript :
// Détection contrepartie interne
amount: { equals: oppositeAmount } // comparaison Decimal côté DB