Règles — Comptes
BR-ACCOUNT-001 — Unicité institution par utilisateur [DB]
Institution @@unique([userId, name])
Un utilisateur ne peut pas avoir deux institutions avec le même nom. La création d'une institution échoue si le nom existe déjà pour ce userId.
Enforcement : contrainte unique PostgreSQL + erreur levée dans createInstitution().
BR-ACCOUNT-002 — Ownership strict [APP]
Toute lecture ou écriture sur un compte ou une institution vérifie que account.userId === session.userId (ou institution.userId). Un compte d'un autre utilisateur retourne une erreur "Compte introuvable" — pas une 403 — pour ne pas révéler l'existence de l'objet.
Enforcement : prisma.account.findFirst({ where: { id, userId } }) systématique avant toute mutation.
BR-ACCOUNT-003 — Hiérarchie parent/enfant [APP]
Un compte peut avoir un parentAccountId optionnel qui pointe vers un autre compte du même utilisateur. Il n'y a pas de limite de profondeur enforced en DB, mais l'interface n'affiche qu'un niveau de hiérarchie.
Enforcement : relation Account.parent / Account.children dans Prisma. La suppression d'un parent ne cascade pas les enfants (relation optionnelle).
BR-ACCOUNT-004 — Devise par défaut EUR [DB]
Account.currency String @default("EUR")
Si aucune devise n'est précisée à la création, le compte est en EUR. Les conversions vers EUR sont stockées séparément (balanceEur, amountEur) — voir BR-FX-001.
BR-ACCOUNT-005 — Types de compte [DB]
L'enum AccountType définit les types valides :
| Valeur | Usage |
|---|---|
CHECKING | Compte courant |
SAVINGS | Livret A, LEP, livrets réglementés |
INVESTMENT | PEA, CTO, compte-titres |
CRYPTO | Wallets crypto |
COMMODITY | Or, matières premières |
UNLISTED | Non coté (private equity, FCPI…) |
BR-ACCOUNT-006 — Compte actif / inactif [APP]
Account.isActive contrôle la visibilité dans le dashboard et les calculs de patrimoine total. Seuls les comptes isActive = true sont inclus dans getDashboardData().
Un compte désactivé conserve ses transactions et snapshots. Il n'existe pas d'opération de suppression hard dans l'interface actuelle (soft delete via isActive).
BR-ACCOUNT-007 — Snapshot initial à la création [APP]
Si initialBalance est fourni lors de createAccount(), un snapshot est créé automatiquement à la date du jour avec source = "MANUAL". Si initialBalance est omis, aucun snapshot n'est créé : le compte apparaît sans solde jusqu'au premier import ou snapshot manuel.