Showroom Vélos d'Occasion
  • PHP 60%
  • Twig 32.3%
  • CSS 7.6%
Find a file
6rus 5a7ae4e888 Easter egg : freedalby (image + audio) + clic pour fermer l'overlay
Ajout du code "freedalby" dans la recherche publique (image dalby.jpeg
+ audio dalby.mp3), calqué sur 31312. Un clic sur l'overlay coupe le son
et le referme, pour freedalby comme pour 31312.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 09:00:37 +02:00
assets Admin : colonne Notes internes + exclusion des bénévoles des rapports 2026-06-02 14:47:26 +02:00
bin Initial commit — showroom Symfony 7 2026-05-14 18:44:40 +02:00
config Admin users : mobile responsive, icônes actions, route /admin/users 2026-05-21 12:44:48 +02:00
migrations Nettoyage fonctionnel : vélorisable, bénéfice calculé, UX mot de passe, domaine atelier 2026-05-17 19:42:55 +02:00
public Easter egg : freedalby (image + audio) + clic pour fermer l'overlay 2026-06-10 09:00:37 +02:00
src Admin : colonne Notes internes + exclusion des bénévoles des rapports 2026-06-02 14:47:26 +02:00
templates Easter egg : freedalby (image + audio) + clic pour fermer l'overlay 2026-06-10 09:00:37 +02:00
.editorconfig Initial commit — showroom Symfony 7 2026-05-14 18:44:40 +02:00
.env Récupération de mot de passe par email 2026-05-16 22:19:22 +02:00
.env.dev Sécurité : remplacer APP_SECRET exposé dans .env.dev par un placeholder 2026-05-17 23:08:39 +02:00
.gitignore Pages d'erreur personnalisées (404 et générique) + .claude/ en gitignore 2026-05-16 23:16:11 +02:00
CLAUDE.md Initial commit — showroom Symfony 7 2026-05-14 18:44:40 +02:00
compose.override.yaml Récupération de mot de passe par email 2026-05-16 22:19:22 +02:00
compose.yaml Initial commit — showroom Symfony 7 2026-05-14 18:44:40 +02:00
composer.json Récupération de mot de passe par email 2026-05-16 22:19:22 +02:00
composer.lock Récupération de mot de passe par email 2026-05-16 22:19:22 +02:00
importmap.php Initial commit — showroom Symfony 7 2026-05-14 18:44:40 +02:00
README.md README : anonymiser le nom du serveur dans la commande de déploiement 2026-05-17 23:09:54 +02:00
symfony.lock Récupération de mot de passe par email 2026-05-16 22:19:22 +02:00

Vélos Risables — Showroom de l'Atelier du Pignon

Showroom en ligne de vélos d'occasion pour l'Atelier du Pignon (Nantes). Les vélos sont consultables publiquement et s'achètent en présentiel aux permanences — pas de paiement en ligne.

Refonte en Symfony 7 de l'application historique. Supporte plusieurs ateliers partenaires.

Stack technique

  • PHP 8.2+ / Symfony 7.4
  • SQLite via Doctrine ORM
  • Asset Mapper (pas de Node.js)
  • Symfony Mailer — réinitialisation de mot de passe par email
  • API REST JSON pour l'application Android

Prérequis

  • PHP 8.2+ avec les extensions pdo_sqlite, ctype, iconv
  • Symfony CLI
  • Composer

Installation

git clone <repo> velorisable && cd velorisable
composer install
php bin/console doctrine:migrations:migrate

Créer un premier compte admin (sans atelier pour le bootstrapping) :

php bin/console app:add-admin <login> <password>

Ce compte aura un accès global. Une fois connecté, créez un atelier via /admin/ateliers, puis assignez-le au compte via /admin/utilisateurs.

Démarrer le serveur de développement :

symfony server:start --no-tls

Configuration

Paramètre Valeur par défaut Description
DATABASE_URL sqlite:///.../var/data/velos.db Chemin de la base SQLite
upload_dir public/uploads/ Répertoire des photos (dans services.yaml)
sold_bikes_visible_days 30 Jours d'affichage des vélos vendus après vente (dans services.yaml)

Copier .env en .env.local pour surcharger les variables d'environnement.

Configuration email (réinitialisation de mot de passe)

La configuration SMTP se gère directement via l'interface admin (/admin/email) — aucun fichier de config à éditer. Les paramètres (hôte, port, identifiants, expéditeur) sont stockés dans var/email_config.json.

Un bouton de test d'envoi permet de vérifier la configuration depuis l'interface.

Commandes utiles

# Migrations
php bin/console doctrine:migrations:diff    # générer une migration
php bin/console doctrine:migrations:migrate  # appliquer les migrations

# Gestion des comptes
php bin/console app:add-admin <login> <password> [prefixe_atelier]

# Maintenance
php bin/console app:purge-benevoles         # supprimer tous les vélos bénévoles (B1, B2…)
php bin/console cache:clear

# Debug
php bin/console debug:router
php bin/console lint:twig templates/

Architecture

src/
├── Controller/
│   ├── PublicController.php        # Front-office : liste (/) et fiche (/velo/{numero})
│   ├── AdminController.php         # Back-office (/admin/**)
│   ├── AdminAtelierController.php  # Gestion des ateliers
│   ├── AdminUserController.php     # Gestion des utilisateurs
│   ├── AdminEmailController.php    # Configuration SMTP (/admin/email)
│   ├── ApiController.php           # API REST JSON (/api/**)
│   └── SecurityController.php      # Login/logout + mot de passe oublié
├── Entity/
│   ├── Velo.php                    # Catalogue de vélos
│   ├── Admin.php                   # Comptes admin (UserInterface)
│   ├── Atelier.php                 # Ateliers (multi-site)
│   └── Visite.php                  # Statistiques de visites
└── Service/
    ├── VeloService.php             # Filtrage et tri des vélos
    ├── ImageService.php            # Upload/suppression des photos
    ├── CsvService.php              # Import/export CSV
    └── EmailConfigService.php      # Lecture/écriture de la config SMTP

Ateliers (multi-site)

Chaque atelier possède :

  • un préfixe unique (13 caractères, ex : PI) — utilisé dans la numérotation des vélos
  • une couleur (code hex) — appliquée dynamiquement à l'interface
  • un logo (image uploadée) ou un cercle coloré avec le préfixe
  • un site web optionnel — le nom de l'atelier devient un lien cliquable dans le header

La suppression d'un atelier est bloquée si des vélos y sont encore rattachés.

Numérotation des vélos

Les vélos « bénévoles » sont stockés avec un offset de 10 000 en base (B1 = 10001, B2 = 10002…). La méthode Velo::getNumeroDisplay() gère la conversion pour l'affichage. Les vélos d'un atelier portent un préfixe (PI-42, PI-B3…).

Statuts d'un vélo

  • Disponible — affiché dans le catalogue
  • En pause — masqué du catalogue public, visible en admin
  • Vendu — masqué après sold_bikes_visible_days jours

Photos

Stockées dans public/uploads/{numero}/. Gérées par ImageService. L'orientation EXIF est corrigée automatiquement à l'upload.

Réinitialisation de mot de passe

Flow complet par email :

  1. Chaque admin peut renseigner son adresse email (unique) via /admin/mon-compte ou via la gestion des utilisateurs
  2. La page /admin/forgot-password accepte une adresse email et envoie un lien à usage unique (valable 1h)
  3. Le lien pointe vers /admin/reset-password/{token} pour saisir un nouveau mot de passe
  4. Le token est effacé après utilisation

La config SMTP est à renseigner une seule fois via /admin/email.

API REST

Accessible sous /api/**, authentifiée par token Bearer (Authorization: Bearer <token>).

Méthode Endpoint Description
GET /api/me Infos de l'utilisateur connecté
GET /api/velos Liste de tous les vélos
GET /api/velos/recherche?q=… Recherche dans les vélos
GET /api/velos/{numero} Détail d'un vélo
POST /api/velos Créer un vélo
PUT /api/velos/{numero} Modifier un vélo
DELETE /api/velos/{numero} Supprimer un vélo
POST /api/velos/{numero}/images Uploader une image
DELETE /api/velos/{numero}/images/{filename} Supprimer une image
POST /api/velos/{numero}/vendre Marquer un vélo comme vendu
GET /api/tailles Liste canonique des tailles (XS → XXL)
GET /api/ateliers Liste des ateliers

Le token API se gère depuis l'interface admin (page « Application Android »).

Migration depuis l'ancienne application

Le schéma SQLite est compatible. Migration en 3 étapes :

  1. Copier data/velos.dbvar/data/velos.db
  2. Copier uploads/public/uploads/
  3. Recréer les comptes admin : php bin/console app:add-admin <login> <password> <prefixe_atelier>

Déploiement

rsync -avz \
  --exclude='vendor/' --exclude='.git/' --exclude='var/' \
  --exclude='.env.local' --exclude='public/uploads/' \
  . <nom_serveur>:/var/www/velorisable/

Sur le serveur, après déploiement :

composer install --no-dev --optimize-autoloader
php bin/console doctrine:migrations:migrate --no-interaction
php bin/console cache:clear --env=prod