Issue #29: feat: Validation des quotes-parts unitaires (total = 100%)
- State:
CLOSED
- Milestone:
Jalon 2: Conformité Légale Belge 📋
- Labels:
enhancement,phase:vps track:software,priority:high
- Assignees:
Unassigned
- Created:
2025-10-27
- Updated:
2025-11-17
- URL:
Description
## Context
Dans une copropriété, la somme des quotes-parts (`ownership_percentage`) de tous les copropriétaires actifs d'un même lot doit toujours égaler 100% (1.0 en décimal).
## Problème actuel
- Aucune validation côté backend lors de la création/modification de `unit_owners`
- Possible de créer des situations incohérentes (total ≠ 100%)
- L'UI affiche un warning mais n'empêche pas la sauvegarde
## Solution proposée
### Backend validation
1. Créer une fonction `validate_unit_ownership_total(unit_id)`
2. Vérifier dans les handlers:
- `add_owner_to_unit`
- `update_unit_owner`
- `remove_owner_from_unit`
3. Retourner erreur 400 si total ≠ 1.0 (avec tolérance de 0.001 pour les arrondis)
### Contrainte database
Ajouter un CHECK constraint via trigger PostgreSQL:
```sql
CREATE OR REPLACE FUNCTION check_unit_ownership_total()
RETURNS TRIGGER AS $$
DECLARE
total DECIMAL(5,4);
BEGIN
SELECT COALESCE(SUM(ownership_percentage), 0) INTO total
FROM unit_owners
WHERE unit_id = NEW.unit_id AND end_date IS NULL;
IF total > 1.0001 OR total < 0.9999 THEN
RAISE EXCEPTION 'Total ownership for unit % must equal 100%% (got %)', NEW.unit_id, total * 100;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER validate_unit_ownership
AFTER INSERT OR UPDATE ON unit_owners
FOR EACH ROW EXECUTE FUNCTION check_unit_ownership_total();
```
### Frontend improvements
- Bloquer la sauvegarde si total ≠ 100%
- Afficher calcul en temps réel lors de l'édition
- Suggérer ajustements automatiques
## Tâches
- [ ] Créer migration avec trigger PostgreSQL
- [ ] Ajouter validation dans `unit_owner_handlers.rs`
- [ ] Tests unitaires pour cas limites (99.99%, 100.01%, etc.)
- [ ] Améliorer UX frontend (bloquer sauvegarde + suggestions)
- [ ] Documenter règle métier dans CLAUDE.md
## Cas particuliers
- Tolérance de ±0.01% pour arrondis
- Validation uniquement pour `end_date IS NULL` (actifs)
- Permettre états transitoires (ajout séquentiel avec total temporaire ≠ 100%)