First-attempt commit3a5c6e184only captured the .gitignore change; the pre-commit hook silently dropped the 343 staged moves/deletes during lint-staged's "no matching task" path. This commit re-applies the intended J1 content on top ofbec75f143(which was pushed in parallel). Uses --no-verify because: - J1 only touches .md/.json/.log/.png/binaries — zero code that would benefit from lint-staged, typecheck, or vitest - The hook demonstrated it corrupts pure-rename commits in this repo - Explicitly authorized by user for this one commit Changes (343 total: 169 deletions + 174 renames): Binaries purged (~167 MB): - veza-backend-api/{server,modern-server,encrypt_oauth_tokens,seed,seed-v2} Generated reports purged: - 9 apps/web/lint_report*.json (~32 MB) - 8 apps/web/tsc_*.{log,txt} + ts_*.log (TS error snapshots) - 3 apps/web/storybook_*.json (1375+ stored errors) - apps/web/{build_errors*,build_output,final_errors}.txt - 70 veza-backend-api/coverage*.out + coverage_groups/ (~4 MB) - 3 veza-backend-api/internal/handlers/*.bak Root cleanup: - 54 audit-*.png (visual regression baselines, ~11 MB) - 9 stale MVP-era scripts (Jan 27, hardcoded v0.101): start_{iteration,mvp,recovery}.sh, test_{mvp_endpoints,protected_endpoints,user_journey}.sh, validate_v0101.sh, verify_logs_setup.sh, gen_hash.py Session docs archived (not deleted — preserved under docs/archive/): - 78 apps/web/*.md → docs/archive/frontend-sessions-2026/ - 43 veza-backend-api/*.md → docs/archive/backend-sessions-2026/ - 53 docs/{RETROSPECTIVE_V,SMOKE_TEST_V,PLAN_V0_,V0_*_RELEASE_SCOPE, AUDIT_,PLAN_ACTION_AUDIT,REMEDIATION_PROGRESS}*.md → docs/archive/v0-history/ README.md and CONTRIBUTING.md preserved in apps/web/ and veza-backend-api/. Note: The .gitignore rules preventing recurrence were already pushed in3a5c6e184and remain in place — this commit does not modify .gitignore. Refs: AUDIT_REPORT.md §11
6.8 KiB
Plan d'implémentation v0.901 — Marketplace Complet & Analytics Avancés
État des lieux
| Feature | Backend | Frontend | Tests |
|---|---|---|---|
| Wishlist | ✅ wishlist.go | ❌ | ❌ |
| Promotions | ❌ | ❌ | ❌ |
| Disputes | ❌ | ❌ | ❌ |
| Review reply | ❌ | ❌ | ❌ |
| Re-download | ❌ | ❌ | ❌ |
| Taxes | ❌ | ❌ | ❌ |
| Geography analytics | ❌ | ❌ | ❌ |
| Demographics | ❌ | ❌ | ❌ |
| Traffic sources | ❌ | ❌ | ❌ |
| Revenue projections | ❌ | ❌ | ❌ |
| Admin analytics | ❌ | ❌ | ❌ |
Fichiers existants clés
- Marketplace service :
service.go - Marketplace models :
models.go - Wishlist :
wishlist.go - Analytics handler :
handler.go - Frontend marketplace :
apps/web/src/features/marketplace/ - Frontend analytics :
apps/web/src/features/analytics/
Step 1 : Wishlist frontend (MK1-01, MK1-02)
Backend : Vérifier que wishlist.go expose POST /marketplace/wishlist/:productId et DELETE /marketplace/wishlist/:productId et GET /marketplace/wishlist. Ajouter les routes dans routes_marketplace.go si manquantes.
Frontend :
WishlistView— page /marketplace/wishlist, grille de ProductCard- Bouton coeur (Heart icon) sur chaque
ProductCard, toggle wishlist via service - Service :
addToWishlist(productId),removeFromWishlist(productId),getWishlist()
Commit : feat(marketplace): connect wishlist frontend with WishlistView and heart toggle
Step 2 : Promotions / Flash Sales (MK1-03, MK1-04)
Migration : migrations/126_promotions.sql
CREATE TABLE IF NOT EXISTS promotions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
product_id UUID NOT NULL REFERENCES products(id) ON DELETE CASCADE,
seller_id UUID NOT NULL REFERENCES users(id),
discount_percent INTEGER NOT NULL CHECK (discount_percent BETWEEN 1 AND 90),
starts_at TIMESTAMPTZ NOT NULL,
ends_at TIMESTAMPTZ NOT NULL,
is_active BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_promotions_product ON promotions(product_id);
CREATE INDEX idx_promotions_active ON promotions(is_active, starts_at, ends_at);
Backend : CRUD promotions — seller crée promo sur ses produits, discount appliqué dans CreateOrder
Frontend : Badge "PROMO -X%" sur ProductCard, countdown timer, page /marketplace/deals
Commit : feat(marketplace): promotions with flash sales, discount badge, deals page
Step 3 : Disputes (MK1-05)
Migration : migrations/127_disputes.sql
CREATE TABLE IF NOT EXISTS disputes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
order_id UUID NOT NULL REFERENCES orders(id),
buyer_id UUID NOT NULL REFERENCES users(id),
reason TEXT NOT NULL,
details TEXT,
status VARCHAR(20) NOT NULL DEFAULT 'open',
resolution VARCHAR(20),
resolved_by UUID REFERENCES users(id),
resolved_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
Backend : POST /marketplace/orders/:id/dispute (buyer), GET /admin/disputes, POST /admin/disputes/:id/resolve
Frontend : Bouton "Report Issue" dans PurchasesView, admin DisputesView
Commit : feat(marketplace): dispute flow with buyer creation and admin resolution
Step 4 : Review replies + Re-download + Taxes (MK1-06 to MK1-08)
Review reply : POST /marketplace/reviews/:id/reply (seller only, max 1 reply per review), migration ajout reply TEXT et replied_at sur product_reviews
Re-download : GET /marketplace/orders/:id/download — génère signed S3 URL (5min expiry) pour chaque fichier de la commande, vérifie ownership
Taxes : Config TAX_RATES JSONB dans config/DB ({"FR": 20, "US": 0, "UK": 20}), calcul auto dans CreateOrder, affichage dans OrderSummary
Commit : feat(marketplace): review replies, unlimited re-download, auto tax calculation
Step 5 : Geography analytics (AN1-01, AN1-02)
Backend :
- Middleware track listener IP → country (MaxMind GeoIP2-Lite database)
- Store country on
track_playstable (migration128_track_plays_country.sql) GET /analytics/geography— aggregate plays par country, top 20
Frontend : Carte heatmap avec react-simple-maps, tooltip country name + play count
Commit : feat(analytics): listener geography with GeoIP and map visualization
Step 6 : Demographics + Traffic + Revenue (AN1-03 to AN1-07)
Demographics : Parse user-agent sur track plays, store device_type/os/browser. GET /analytics/demographics
Traffic sources : Store referrer on track plays. GET /analytics/traffic-sources — top 10 referrers
Revenue projections : GET /analytics/revenue/projection — régression linéaire simple sur les revenus des 90 derniers jours, projections 30/60/90j
Period comparison : GET /analytics/compare?period1_start=...&period1_end=...&period2_start=...&period2_end=... — compare plays, revenue, followers entre 2 périodes
Frontend : Onglets dans analytics dashboard — Demographics (donut chart), Traffic (bar chart), Revenue (line chart + projection), Comparison (side-by-side)
Commit : feat(analytics): demographics, traffic sources, revenue projections, period comparison
Step 7 : Admin Analytics (AN2-01 to AN2-06)
Backend :
GET /admin/analytics/users— DAU/MAU basé sur last_active_atGET /admin/analytics/signups— count inscrits par jour/semaine/moisGET /admin/analytics/retention— D1/D7/D30 retention cohortsGET /admin/analytics/transactions— revenus, nombre, ticket moyenGET /admin/analytics/performance— query Prometheus API pour p50/p95 latency, error rate
Frontend : Admin analytics dashboard — widgets DAU/MAU, line chart signups, retention curve, transactions KPIs, performance metrics
Commit : feat(admin): analytics dashboard with DAU/MAU, retention, transactions, performance
Step 8 : MSW + Tests
MSW : handlers wishlist, promotions, disputes, review reply, download, analytics endpoints Tests : wishlist CRUD, promotion validity window, dispute flow, tax calculation, geography aggregation, retention cohort formula, revenue projection
Commit : test(marketplace,analytics): unit tests for wishlist, promotions, disputes, analytics
Step 9 : Documentation + release
Commit : docs: update documentation for v0.901
Step 10 : Rétrospective + archivage + tag
git tag v0.901
Validation finale
cd veza-backend-api && go build ./... && go test ./... -v
cd apps/web && npm run build
git tag v0.901