fix(budget): assigner suggéré doit créer une transaction de transfert depuis "À assigner" #5

Closed
opened 2026-09-02 23:08:29 +02:00 by alexis · 0 comments
Owner

Contexte

Le bouton « Assigner suggéré » (BudgetScreen.kt CategoryRow TextButton, CategoryDialog aussi) appelle Store.setAssigned(c.id, month, assignedAmt + sug) qui ne fait qu’incrémenter le budget assigné du mois. Aucun mouvement de fonds réel n’est tracé.

Repro

  1. Compte courant, solde 1843,27 € — 0 revenu ce mois
  2. Catégorie « Vacances », objectif 60 € échéance dans 4 mois
  3. Cliquer « Assigner 15 € »
  4. → Budget.assignments[2026-09][vacances] passe à 15 €
  5. → Solde du compte reste 1843,27 €
  6. → RTA « Prêt à assigner » descend de 15 €
  7. → Aucune transaction n’a été créée

Problème

  • L’argent « apparaît » dans l’enveloppe sans provenance identifiable.
  • L’utilisateur ne peut pas modifier ou supprimer l’assignation via l’écran Transactions (il n’y a rien à modifier).
  • En YNAB, « assigner » n’est qu’une répartition du revenu déjà encaissé : chaque euro passe de « À assigner » vers une enveloppe. Chez nous, l’assignation n’a pas de source.
  • Le bouton « Enregistrer » de CategoryDialog (ligne 1115) appelle aussi setAssigned sans transaction, même bug.

Attendu (spec YNAB)

  • Quand l’assignation augmente et qu’il y a du RTA positif sur le mois, créer une transaction virtuelle de type Transfert :
    • payee: « Vers ${category.name} »
    • amount: sug (négatif côté source « À assigner », positif côté enveloppe — ou un seul txn lié)
    • date: 1er du mois courant
    • categoryId: la catégorie cible
    • accountId: compte courant (CHEQUE) par défaut
  • Modèle : Txn avec nouveau champ assignmentRef: Long? (FK vers le budget assigné), ou bien un type TxnType.ASSIGNMENT.
  • Suppression / édition possible depuis l’onglet Transactions comme une transaction normale.
  • Persistance: v4 → v5 tolérant (assignmentRef absent ⇒ v4 legacy).
  • Store.setAssigned devient transactionnel : crée le txn + maj budget + markSuggestedUsed en un seul persist().

Acceptance

  • Cliquer « Assigner X » crée une transaction visible dans Transactions, modifiable/supprimable
  • Solde du compte CHEQUE reste cohérent (si RTA=0 avant, solde ne bouge pas — l’argent n’est pas dépensé mais réparti)
  • readyToAssign recalcule correctement (txn de répartition ne compte pas dans le revenu)
  • deleteTxn de cette transaction restaure l’assignation (rollback cohérent)
  • Persistance v5 tolère v4 et reset propre en cas de corruption
  • hasTxnsThisMonth (audit PR #3) se base désormais sur des txns réelles, pas le net d’activité

Notes

  • Le fix #2 (one-shot suggestedUsed) reste valide — il empêche le spam, pas la traçabilité.
  • Envisager un toggle « Mode YNAB strict » dans Réglages pour les utilisateurs qui veulent l’assignation libre (comportement actuel).
  • Priorité: HIGH (modèle de données), MEDIUM (UX edge cases).

Refs: PR #2 (one-shot), PR #3 (note sheet), PR #4 (merge précédent).

## Contexte Le bouton « Assigner suggéré » (`BudgetScreen.kt` CategoryRow TextButton, `CategoryDialog` aussi) appelle `Store.setAssigned(c.id, month, assignedAmt + sug)` qui ne fait qu’**incrémenter le budget assigné** du mois. Aucun mouvement de fonds réel n’est tracé. ### Repro 1. Compte courant, solde 1843,27 € — 0 revenu ce mois 2. Catégorie « Vacances », objectif 60 € échéance dans 4 mois 3. Cliquer « Assigner 15 € » 4. → Budget.assignments[2026-09][vacances] passe à 15 € 5. → Solde du compte reste 1843,27 € 6. → RTA « Prêt à assigner » descend de 15 € 7. → Aucune transaction n’a été créée ### Problème - L’argent « apparaît » dans l’enveloppe sans provenance identifiable. - L’utilisateur ne peut pas **modifier** ou **supprimer** l’assignation via l’écran Transactions (il n’y a rien à modifier). - En YNAB, « assigner » n’est qu’une *répartition* du revenu déjà encaissé : chaque euro passe de « À assigner » vers une enveloppe. Chez nous, l’assignation n’a pas de source. - Le bouton « Enregistrer » de `CategoryDialog` (ligne 1115) appelle aussi `setAssigned` sans transaction, même bug. ### Attendu (spec YNAB) - Quand l’assignation augmente et qu’il y a du RTA positif sur le mois, créer une **transaction virtuelle de type Transfert** : - payee: `« Vers ${category.name} »` - amount: `sug` (négatif côté source « À assigner », positif côté enveloppe — ou un seul txn lié) - date: 1er du mois courant - categoryId: la catégorie cible - accountId: compte courant (CHEQUE) par défaut - Modèle : `Txn` avec nouveau champ `assignmentRef: Long?` (FK vers le budget assigné), ou bien un type `TxnType.ASSIGNMENT`. - Suppression / édition possible depuis l’onglet Transactions comme une transaction normale. - Persistance: v4 → v5 tolérant (`assignmentRef` absent ⇒ v4 legacy). - `Store.setAssigned` devient transactionnel : crée le txn + maj budget + `markSuggestedUsed` en un seul `persist()`. ### Acceptance - [ ] Cliquer « Assigner X » crée une transaction visible dans Transactions, modifiable/supprimable - [ ] Solde du compte CHEQUE reste cohérent (si RTA=0 avant, solde ne bouge pas — l’argent n’est pas dépensé mais réparti) - [ ] `readyToAssign` recalcule correctement (txn de répartition ne compte pas dans le revenu) - [ ] `deleteTxn` de cette transaction restaure l’assignation (rollback cohérent) - [ ] Persistance v5 tolère v4 et reset propre en cas de corruption - [ ] `hasTxnsThisMonth` (audit PR #3) se base désormais sur des txns réelles, pas le net d’activité ### Notes - Le fix #2 (one-shot `suggestedUsed`) reste valide — il empêche le spam, pas la traçabilité. - Envisager un toggle « Mode YNAB strict » dans Réglages pour les utilisateurs qui veulent l’assignation libre (comportement actuel). - Priorité: HIGH (modèle de données), MEDIUM (UX edge cases). Refs: PR #2 (one-shot), PR #3 (note sheet), PR #4 (merge précédent).
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
alexis/demo_m3#5
No description provided.