veza/docs/V0_603_RELEASE_SCOPE.md
senke c4110fded7 docs(v0.603): scope, plan d'implémentation et smoke test
Define v0.603 release scope: automatic Stripe Connect transfers
after payment, configurable platform commission, technical debt
triage (210+ TODOs), and docs archival. Includes detailed
implementation plan (4 sprints, 19 commits) and smoke test checklist.
2026-02-23 22:48:04 +01:00

11 KiB

V0.603 Release Scope — Transfer automatique, Commission & Stabilisation

Statut : En cours Phase : 6+ Prérequis : v0.602 (taguée) Date cible : TBD Estimation : ~4 sprints (20 jours ouvrés) Précédente : v0.602


1. Objectif

Boucler la chaîne de paiement vendeur en implémentant le transfert automatique Stripe Connect après paiement réussi (reporté depuis v0.602), ajouter la commission plateforme configurable, nettoyer la dette technique (triage des 210+ TODOs, archivage docs obsolètes), et renforcer les tests du flux paiement.


2. État actuel (post-v0.602)

Composant État Détail
Stripe Connect onboarding Livré v0.602 POST /sell/connect/onboard, GET /sell/balance
seller_stripe_accounts Livré v0.602 Migration 114, modèle GORM
StripeConnectService.CreateTransfer Code existant Méthode implémentée mais jamais appelée
ProcessPaymentWebhook ⚠️ Incomplet Crée les licences mais ne déclenche pas les transferts
Commission plateforme Absente Aucune config ni calcul de commission sur ventes marketplace
Suivi des transferts Absent Pas de table ni log des transferts effectués
TODOs backend ⚠️ 210+ Triage nécessaire (supprimer obsolètes, transformer restants en tickets)
Docs obsolètes ⚠️ 82 fichiers Archiver les docs pre-v0.501 dans docs/archive/

3. Lots

Lot T1 — Transfer automatique après vente (Stripe Connect)

Objectif : Lorsqu'un paiement réussit (webhook Hyperswitch succeeded), transférer automatiquement la part vendeur vers son compte Stripe Connect.

# Tâche Fichiers impactés Effort
T1-01 Config commission plateforme — PLATFORM_FEE_RATE (default 0.10 = 10%) internal/config/config.go, .env.example S
T1-02 Migration 115_seller_transfers.sql — table de suivi des transferts migrations/115_seller_transfers.sql S
T1-03 Modèle SellerTransfer — GORM model + BeforeCreate UUID hook internal/core/marketplace/models.go S
T1-04 Interface TransferService — abstraction pour le service de transfert internal/core/marketplace/service.go S
T1-05 Option WithTransferService — injection optionnelle dans marketplace.Service internal/core/marketplace/service.go S
T1-06 Logique transfer dans ProcessPaymentWebhook — après création licences, regrouper items par vendeur, calculer montant net, appeler CreateTransfer, enregistrer SellerTransfer internal/core/marketplace/service.go L
T1-07 Endpoint GET /sell/transfers — historique des transferts pour un vendeur internal/handlers/sell_handler.go, routes M
T1-08 Frontend : SellerTransfersCard — liste des transferts dans SellerDashboard apps/web/src/features/seller/ M
T1-09 MSW handlers + Story — mock GET /sell/transfers apps/web/src/mocks/handlers.ts, stories S
T1-10 Tests unitaires — ProcessPaymentWebhook avec transfert, multi-vendeur, vendeur sans Connect internal/core/marketplace/process_webhook_test.go M

Lot DT1 — Dette technique & Nettoyage

Objectif : Réduire la dette technique accumulée, archiver les docs obsolètes.

# Tâche Fichiers impactés Effort
DT1-01 Triage TODOs backend — supprimer obsolètes, convertir pertinents en issues GitHub veza-backend-api/internal/** M
DT1-02 Archiver docs pre-v0.501 — déplacer dans docs/archive/ les scopes/plans obsolètes docs/*.mddocs/archive/ S
DT1-03 Mettre à jour PAYOUT_MANUAL.md — remplacer « procédure manuelle » par « transfert automatique v0.603 » docs/PAYOUT_MANUAL.md S
DT1-04 Nettoyer code mort marketplace — imports inutilisés, variables non référencées internal/core/marketplace/ S

Lot QA3 — Tests & Documentation de release

Objectif : Valider le flux transfer E2E, documenter, tagger.

# Tâche Fichiers impactés Effort
QA3-01 Test E2E transfer — flow complet : product → order → webhook succeeded → transfer créé → SellerTransfer enregistré internal/core/marketplace/ ou integration tests M
QA3-02 Test multi-vendeur — commande avec 2 produits de vendeurs différents → 2 transfers distincts internal/core/marketplace/process_webhook_test.go M
QA3-03 Test vendeur sans Connect — paiement réussit, licences créées, transfer ignoré (log warning) internal/core/marketplace/process_webhook_test.go S
QA3-04 Smoke test v0.603 — checklist complète docs/SMOKE_TEST_V0603.md S
QA3-05 Mise à jour PROJECT_STATE, FEATURE_STATUS, CHANGELOG docs/ S
QA3-06 Rétrospective v0.603, archivage scope, placeholder v0.604, tag docs/, Git S

4. Hors scope v0.603

Élément Version cible
Go Live (streaming vidéo) v0.703
2FA SMS / Passkeys v0.104
IaC (Terraform/Pulumi) v0.801
Migration React 19 v0.604
Payout scheduling (cron récurrent) v0.604
Dashboard transferts admin (vue admin des transferts plateforme) v0.604

5. Détail technique — Lot T1

5.1 Commission plateforme

// config.go
PlatformFeeRate float64 // PLATFORM_FEE_RATE, default 0.10 (10%)

Le calcul pour chaque item :

  • sellerAmount = item.Price * (1 - platformFeeRate)
  • Arrondi à l'unité inférieure (centimes) pour éviter les fractions
  • Les montants sont en centimes (int64) pour Stripe

5.2 Migration 115_seller_transfers.sql

CREATE TABLE IF NOT EXISTS seller_transfers (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    seller_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    order_id UUID NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
    stripe_transfer_id VARCHAR(255),
    amount_cents BIGINT NOT NULL,
    platform_fee_cents BIGINT NOT NULL,
    currency VARCHAR(3) NOT NULL DEFAULT 'EUR',
    status VARCHAR(50) NOT NULL DEFAULT 'pending',
    error_message TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_seller_transfers_seller ON seller_transfers(seller_id);
CREATE INDEX idx_seller_transfers_order ON seller_transfers(order_id);
CREATE UNIQUE INDEX idx_seller_transfers_seller_order ON seller_transfers(seller_id, order_id);

5.3 Injection dans marketplace.Service

Le StripeConnectService sera injecté via le pattern ServiceOption existant :

// TransferService abstraction pour découpler marketplace du service Stripe
type TransferService interface {
    CreateTransfer(ctx context.Context, sellerUserID uuid.UUID, amount int64, currency, orderID string) error
}

// WithTransferService injecte le service de transfert
func WithTransferService(ts TransferService, feeRate float64) ServiceOption {
    return func(s *Service) {
        s.transferService = ts
        s.platformFeeRate = feeRate
    }
}

5.4 Logique transfer dans ProcessPaymentWebhook

Après la boucle de création des licences (dans le cas succeeded), ajouter :

  1. Regrouper les items par product.SellerID
  2. Pour chaque vendeur unique : a. Calculer le montant total des items de ce vendeur b. Soustraire la commission plateforme c. Vérifier si le vendeur a un compte Connect actif (via DB) d. Si oui : appeler CreateTransfer, enregistrer un SellerTransfer avec status completed e. Si non : logger un warning, enregistrer un SellerTransfer avec status skipped f. En cas d'erreur Stripe : enregistrer avec status failed + error_message, ne pas bloquer la commande

5.5 Gestion des erreurs

  • Un échec de transfert ne doit pas annuler la commande ni les licences
  • Le transfert est enregistré en DB avec son statut pour retry ultérieur
  • Log zap.Error pour alerter l'équipe

6. Fichiers impactés (récapitulatif)

Backend Go (nouveau)

Fichier Action
migrations/115_seller_transfers.sql Nouveau — table suivi transferts

Backend Go (modifier)

Fichier Action
internal/config/config.go Ajout PlatformFeeRate
internal/core/marketplace/models.go Ajout modèle SellerTransfer
internal/core/marketplace/service.go Interface TransferService, option WithTransferService, logique transfer dans ProcessPaymentWebhook
internal/core/marketplace/process_webhook_test.go Tests transfer, multi-vendeur, vendeur sans Connect
internal/handlers/sell_handler.go GET /sell/transfers
.env.example Documenter PLATFORM_FEE_RATE

Frontend (modifier)

Fichier Action
apps/web/src/features/seller/SellerDashboardView.tsx Carte transferts
apps/web/src/mocks/handlers.ts Handler GET /sell/transfers

Documentation

Fichier Action
docs/PAYOUT_MANUAL.md Mise à jour (procédure auto)
docs/PROJECT_STATE.md Section v0.603
docs/FEATURE_STATUS.md Marketplace → transfert auto
CHANGELOG.md Section v0.603
docs/SMOKE_TEST_V0603.md Nouveau
docs/RETROSPECTIVE_V0603.md Nouveau (en fin de release)

7. Critères d'acceptation globaux

  • Transfer auto : paiement réussi (webhook) → licences créées + transfer Stripe exécuté
  • Multi-vendeur : commande multi-produit → 1 transfer par vendeur distinct
  • Commission : montant vendeur = prix - commission plateforme (configurable)
  • Résilience : échec transfer ≠ échec commande — enregistré avec status failed
  • Vendeur sans Connect : transfer ignoré (status skipped), log warning
  • GET /sell/transfers : vendeur voit historique de ses transferts
  • Frontend : carte transferts dans SellerDashboard
  • Tests : unitaires ProcessWebhook + transfer, multi-vendeur, sans Connect
  • TODOs : 50%+ des TODOs obsolètes supprimés, restants en issues
  • Tag v0.603 créé

8. Risques

Risque Mitigation
Stripe Connect rate limits (250 req/s) Batch par commande, pas par item. En prod, volume faible au démarrage
Erreur transfer après licences créées Transfer enregistré failed en DB — retry manuel ou cron v0.604
Float precision sur montants Calcul en centimes (int64) uniquement, conversion float → int64 dès l'entrée
Commission non configurable par vendeur MVP = taux unique global. Taux par vendeur/catégorie → v0.604

9. Références