- Ajouter
stripepour les paiements - Ajouter
telerivetouhttparty/faradaypour l'API Telerivet - Ajouter
base58ou utiliserSecureRandompour les tokens Base58 - Ajouter
sentry-rubypour l'observabilité - Ajouter
bcryptpour l'authentification admin (déjà commenté) - Note: Le PRD demande Sidekiq+Redis mais Solid Queue est déjà configuré. Garder Solid Queue sauf si requis spécifiquement.
- Vérifier que
config.time_zone = "Europe/Brussels"est présent (déjà fait) - S'assurer que la locale FR est par défaut (déjà fait)
- Pour les vues, tous les textes devront être en français
Créer les migrations dans l'ordre logique:
products (category enum: breads, dough_balls; position int; active boolean)
- name, description, category, position, active
product_variants (belongs_to product)
- product_id, name, price_cents, active, image_url
product_availabilities (belongs_to product_variant)
- product_variant_id, start_on (date), end_on (date nullable)
bake_days (baked_on unique, cut_off_at timestamptz)
- baked_on (date unique), cut_off_at (timestamptz)
customers (phone_e164 unique)
- phone_e164 (unique), first_name, last_name (nullable), email (nullable), sms_opt_out (boolean default false)
phone_verifications (OTP)
- phone_e164, code (6 digits), expires_at, attempts_count
orders (belongs_to customer, bake_day)
- customer_id, bake_day_id, status enum, total_cents, public_token (unique), order_number, payment_intent_id (pour idempotency)
order_items (belongs_to order, product_variant)
- order_id, product_variant_id, qty, unit_price_cents
payments (belongs_to order, unique)
- order_id (unique), stripe_payment_intent_id (unique), status enum
sms_messages (historique SMS)
- direction enum, to_e164, from_e164, baked_on (nullable), body, kind enum, external_id
admin_pages (CMS simple)
- slug (unique), title, body
Créer tous les modèles avec leurs associations, validations et méthodes métier:
Product,ProductVariant,Availability,BakeDay,Customer,PhoneVerification,Order,OrderItem,Payment,SmsMessage,AdminPage
Points importants:
- Product: scope pour ordre (category → position → name)
- BakeDay: méthodes pour calculer cut-offs (Tue ← Sun 18:00, Fri ← Wed 18:00)
- Order: génération
order_number(TV-YYYYMMDD-XXXX) etpublic_token(Base58 24 chars) - Customer: validation phone E.164, méthode pour vérifier opt-out SMS
- Status enums avec transitions validées
- Service
BakeDayServicepour calculer les prochains bake days et vérifier les cut-offs - Méthode
can_order_for?(date)avec validation timezone Europe/Brussels
- Service
OrderCreationServicepour créer une commande depuis le panier - Génération automatique
order_numberavec compteur quotidien - Génération
public_tokencryptographique (Base58) - Idempotency via
payment_intent_id
- Service
SmsServicepour envoyer via Telerivet API - Messages: confirmation (après paiement), ready (changement status), refund (annulation)
- Stocker tous les SMS dans
sms_messagespour traçabilité
- Service
RefundServicepour gérer les remboursements Stripe - Vérification cut-off avant remboursement
- Mise à jour Payment et Order status
- Envoi SMS de remboursement
GET /(root) → redirige vers catalog avec prochain bake dayGET /catalogavec parambake_day=YYYY-MM-DD- Filtrer les produits/variants par disponibilité selon bake_day
- Afficher produits groupés par catégorie avec ordre spécifié
- Session-based cart (pas de DB)
POST /cart/addajouter au panierGET /cartafficher le panierPATCH /cart/updatemodifier quantitésDELETE /cart/removeretirer items- Valider cut-off avant affichage checkout
GET /checkoutformulaire avec Stripe Payment ElementPOST /checkout/create_payment_intentcréer PaymentIntent Stripe- Authentification SMS OTP minimal (pas de compte utilisateur)
- Valider cut-off avant création commande
- Formulaire: phone, first_name, last_name, email (optionnel)
GET /orders/:tokenafficher commande via public_token- Lecture seule, pas de modification
- Authentification simple par mot de passe (ENV
ADMIN_PASSWORD) - Session-based, pas de modèle User
GET /admin/login,POST /admin/login,DELETE /admin/logout
- Liste des commandes avec filtres (bake_day, status)
- Détail commande
- Actions:
paid→ready(envoie SMS ready) - Actions:
ready→picked_upouno_show - Remboursement:
paid→cancelled(avant cut-off uniquement)
- CRUD Products et ProductVariants
- Gestion des disponibilités (product_availabilities)
- Upload d'images pour variants
POST /webhooks/stripe- Events:
payment_intent.succeeded,payment_intent.payment_failed,charge.refunded - Vérification signature avec
STRIPE_WEBHOOK_SECRET - Idempotency via
StripeEventmodel - Créer/update Order et Payment selon event
POST /webhooks/telerivet- Parser keyword STOP dans body
- Mettre à jour
customer.sms_opt_out = truesi STOP détecté - Stocker message inbound dans
sms_messages
- Navbar simple avec logo
- Footer
- Alerts/toasts pour messages flash
- Spinners pour loading states
catalog/indexavec grille de produits (product cards)cart/showpage panier (pas drawer)checkout/newformulaire avec Stripe Payment Element intégrécheckout/successpage de confirmationorders/showdétails commande publique- Utiliser Tailwind UI Starter pour composants
- Layout admin séparé avec sidebar/nav
admin/orders/indextable avec badges statusadmin/orders/showdétail avec actions (modales de confirmation)admin/productsCRUD interface
cart_controller.jspour ajout/retrait items (Turbo frames)checkout_controller.jspour Stripe Payment Elementadmin_controller.jspour modales et confirmations
- Intégrer Stripe.js via CDN ou importmap
- Initialiser Payment Element dans checkout form
- Gérer événements Stripe (success, error)
Créer tous les produits et variants spécifiés:
- Category Breads: Spelt (1kg 550c, 600g 350c), Wheat (1kg 450c, 600g 300c), Ancient grains (600g 550c), Walnut (1kg 550c, 600g 400c), Seeded (1kg 550c, 600g 400c), Walnut/fig (600g 400c), Choco/sugar (600g 400c)
- Category Dough balls: Take-away (200c), Private Pizza Party (500c)
- Créer quelques dates de cuisson (mardi et vendredis) avec cut-offs appropriés
- Validations et associations
- Génération order_number et public_token
- Calculs cut-offs avec timezone
- Catalog avec filtrage par bake_day
- Cart session management
- Checkout avec Stripe mock
- Admin authentication
- Cut-off edges (17:59 vs 18:01)
- Order creation idempotency
- SMS sending et opt-out
- Refund flow
- Stripe webhook signature validation
- Telerivet STOP parsing
- Idempotency des events
Documenter toutes les ENV requises:
STRIPE_PUBLIC_KEY,STRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRETTELERIVET_API_KEY,TELERIVET_PROJECT_ID,TELERIVET_PHONE_IDSENTRY_DSNACTIVE_STORAGE_SERVICETIME_ZONE=Europe/BrusselsADMIN_PASSWORD
- Ajouter rate limiting pour OTP (60s cooldown, max 5 attempts)
- Rate limiting pour checkout init
- Utiliser
rack-attackourate_limitergem
- Configurer Sentry
- Logger structuré avec masquage PII (phone numbers)
- Performance monitoring pour catalog TTFB < 300ms
- Parcourir tous les points du PRD et vérifier couverture complète
- Vérifier que tous les status transitions sont implémentés
- Vérifier messages SMS exacts selon PRD
- Vérifier format order_number et public_token
- Commenter code complexe (cut-offs, idempotency)
- README avec instructions setup
- Documentation API webhooks si nécessaire
- Vérifier accessibilité (ARIA, focus states)
- Optimiser requêtes N+1
- Cache si nécessaire pour catalog