Projet Site Maison Crosnier · 10 août 2026 · Remplace la v0 (« cache caisse »).
Cible technique : Laravel + Eloquent + MySQL,
back-office Filament. Le site est
autonome (il fait autorité sur ces données) et
caisse-ready : chaque entité mappable porte un champ
refCaisse (nullable, indexé), et les accès
passent par des repositories (ports) pour brancher un
adaptateur caisse plus tard.
Conventions : toute table a id, created_at,
updated_at. Montants en decimal(8,2). Pas de
gestion de stock (la disponibilité est calculée, cf.
§Disponibilité).
| Champ | Type | Notes |
|---|---|---|
| id | bigint | |
| parent_id | fk Categorie | null | arborescence (univers → sous-catégorie) |
| nom | string | |
| slug | string unique | URL / SEO |
| ordre | int | tri d'affichage |
| actif | bool |
| Champ | Type | Notes |
|---|---|---|
| id | bigint | |
| code | string unique | pain, viennoiserie,
patisserie, snacking |
| libelle | string | |
| politique_type | enum(veille,delai) |
mode de calcul de l'heure limite |
| heure_limite | time | null | pour veille (ex. 10:00) |
| delai_minutes | int | null | pour delai (ex. 180) |
| retrait_au_plus_tot | enum(J+0,J+1) |
horizon minimum |
| retrait_avant | time | null | fenêtre de retrait spécifique (ex. viennoiserie < 09:00) |
| Champ | Type | Notes |
|---|---|---|
| id | bigint | |
| refCaisse | string | null (indexé) | correspondance caisse (vide au lancement) |
| famille_id | fk Famille | politique de commande |
| type | enum(simple,formule) |
formule = offre composée à prix fixe (voir
§Formule) |
| nom | string | |
| slug | string unique | |
| description | text | |
| prix_base | decimal | prix si pas de déclinaison |
| actif | bool | |
| mis_en_avant | bool | merchandising |
| meta_seo | json | title, description |
Relations : belongsToMany Categorie ·
hasMany Declinaison · hasMany GroupeChoix ·
hasMany Media.
| Champ | Type | Notes |
|---|---|---|
| id | bigint | |
| produit_id | fk Produit | |
| refCaisse | string | null | |
| libelle | string | ex. « 6 parts » |
| prix | decimal | prix absolu de la déclinaison |
| ordre | int | |
| actif | bool |
Si un produit a des déclinaisons, le client en choisit une (prix =
declinaison.prix) ; sinon prix =produit.prix_base.
GroupeChoix : id,
produit_id, libelle (ex. « Bougies », «
Parfums »), min (int), max (int),
obligatoire (bool), ordre.
Option : id, groupe_choix_id,
refCaisse (null), libelle,
prix_delta (decimal, ex. +2,00), ordre,
actif.
Une formule est un Produit de
type = formule, à prix fixe (porté par
prix_base), composée de plusieurs groupes de
composition : pour chaque groupe, le client choisit un nombre
défini de produits parmi une liste éligible. Le prix ne dépend pas des
produits choisis. Exemple : « Formule à 15 € : 3 produits, un choisi
dans chacun de 3 groupes ».
GroupeComposition : id,
produit_id (la formule), libelle,
quantite (nb à choisir, défaut 1), ordre.
GroupeComposition_Produit (pivot) :
groupe_composition_id, produit_id (produits
éligibles).
Disponibilité d'une formule : elle suit la règle du panier mixte (§4/§7) appliquée aux produits choisis — la famille la plus contraignante fixe le créneau. (Micro-point à préciser : une formule a-t-elle sa propre famille, ou hérite-t-elle de ses composants ? proposé : héritée.)
id, produit_id (null), chemin,
alt, type (image…), ordre.
id, cible
(produit|famille|categorie),
cible_id, type
(pourcentage|montant), valeur,
debut, fin, actif.
Prix affiché = prix (base ou déclinaison) éventuellement minoré par une promotion active.
PointDeRetrait : id, nom,
adresse, duree_creneau_minutes (défaut 30),
actif. HoraireOuverture : id,
point_id, jour (enum lundi…dimanche),
plages (json : [{debut, fin}]).
FermetureExceptionnelle : id,
point_id, date, type
(ferme|horaires_speciaux), plages
(json|null).
Créneau : non stocké — généré à la volée. Le créneau choisi est figé (heure de début
T) sur le panier / la commande.
commandable(famille, T, maintenant) ⇔ maintenant ≤ deadline(famille, T)
; pour un panier, valable si toutes les familles
présentes le sont. Aucune table ; service de calcul (voir §9).
Panier : id, client_id
(null), session_token, point_id,
creneau_debut (datetime|null), statut
(actif|converti|abandonne).
LignePanier : id, panier_id,
produit_id, declinaison_id (null),
quantite, prix_unitaire_snapshot (decimal,
promo incluse). LignePanierOption (pivot) :
ligne_panier_id, option_id,
prix_delta_snapshot.
LignePanierComposition (formule) :
ligne_panier_id, groupe_composition_id,
produit_choisi_id.
Commande : id,
**refCaisse** (null), client_id,
point_id, creneau_debut, statut,
montant_total, jalons (creee_le,
payee_le, preparee_le,
retiree_le, annulee_le). Statuts (pilotés par
le back-office de préparation) : creee → payee
→ en_preparation → preparee →
retiree ; ou annulee /
non_retiree. LigneCommande : snapshot figé
(libellé produit, déclinaison, options, quantité, prix) — pour
l'intégrité de l'historique.
Paiement : id,
commande_id, type
(paiement|remboursement),
prestataire (payplug), reference,
montant, statut, date.
Avoir (crédit boutique, site-owned) : id,
**refCaisse** (null), client_id,
code (unique, présentable), format_code
(code_barres|qr_code|code),
montant_initial, solde_restant,
origine_commande_id, statut
(actif|epuise|expire|edite_boutique),
edite_le, montant_edite,
expire_le.
Client : id, **refCaisse**
(null), email, nom, telephone,
mot_de_passe_hash (null pour invité), type
(invite|enregistre). Favori :
id, client_id, produit_id.
Utilisateur (admin — modèle Filament, distinct du
Client) : id, nom, email,
mot_de_passe_hash, role
(admin|preparateur), actif.
Page (CMS — pages éditoriales) : id,
titre, slug (unique), contenu
(html), meta_seo (json), statut
(brouillon|publie), ordre.
CalculDisponibilite · GenerationCreneaux · ApplicationPromo · RattachementInvite (commande invité → compte, même e-mail) · EditionAvoir (édition auto-décrémentante pour usage boutique).
Interfaces (contrats) : CatalogueRepository,
CommandeRepository, AvoirRepository,
ClientRepository. Implémentation Eloquent (base du
site) aujourd'hui ; adaptateur caisse demain,
branché via le conteneur de services Laravel — sans toucher à la logique
métier. Le refCaisse porté par les entités permet la
réconciliation.
Micro-point restant : famille (politique de commande) d'une formule — propre ou héritée de ses composants (proposé : héritée).