Files
compositor/tmp/generate_cdc.py
Guillaume Dugas 628028750c
Some checks failed
Maven build / build (push) Failing after 20s
Init (1)
2026-02-19 22:13:52 +01:00

564 lines
24 KiB
Python

from docx import Document
from docx.shared import Pt, Cm, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from datetime import date
doc = Document()
style = doc.styles['Normal']
font = style.font
font.name = 'Calibri'
font.size = Pt(11)
# ── Page de garde ──
for _ in range(6):
doc.add_paragraph()
title = doc.add_paragraph()
title.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = title.add_run("Cahier des Charges")
run.bold = True
run.font.size = Pt(28)
run.font.color.rgb = RGBColor(0x1A, 0x3C, 0x6E)
subtitle = doc.add_paragraph()
subtitle.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = subtitle.add_run("Plateforme de Billetterie pour le Tourisme Parisien\nPortail B2B à destination des professionnels du tourisme")
run.font.size = Pt(14)
run.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
doc.add_paragraph()
meta = doc.add_paragraph()
meta.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = meta.add_run(f"Version 1.0 — {date.today().strftime('%d/%m/%Y')}\nDocument confidentiel")
run.font.size = Pt(10)
run.font.color.rgb = RGBColor(0x99, 0x99, 0x99)
doc.add_page_break()
# ── Historique des révisions ──
doc.add_heading("Historique des révisions", level=1)
table = doc.add_table(rows=2, cols=4)
table.style = 'Light Grid Accent 1'
table.alignment = WD_TABLE_ALIGNMENT.CENTER
headers = ["Version", "Date", "Auteur", "Description"]
for i, h in enumerate(headers):
table.rows[0].cells[i].text = h
row = table.rows[1]
row.cells[0].text = "1.0"
row.cells[1].text = date.today().strftime("%d/%m/%Y")
row.cells[2].text = "[À compléter]"
row.cells[3].text = "Rédaction initiale du cahier des charges"
doc.add_page_break()
# ── Table des matières (placeholder) ──
doc.add_heading("Table des matières", level=1)
p = doc.add_paragraph("[Insérer la table des matières automatique depuis Word : Références > Table des matières]")
p.italic = True
doc.add_page_break()
# ═══════════════════════════════════════
# 1. CONTEXTE ET OBJECTIFS
# ═══════════════════════════════════════
doc.add_heading("1. Contexte et objectifs", level=1)
doc.add_heading("1.1 Contexte du projet", level=2)
doc.add_paragraph(
"Le présent cahier des charges décrit les spécifications fonctionnelles et techniques "
"d'une plateforme de billetterie en ligne dédiée au tourisme parisien. Cette plateforme "
"s'adresse exclusivement aux professionnels du secteur touristique : agences de voyages, "
"tour-opérateurs, réceptifs, autocaristes, comités d'entreprise et organisateurs d'événements."
)
doc.add_paragraph(
"La plateforme doit permettre à ces professionnels de rechercher, réserver et gérer "
"des billets pour l'ensemble des sites touristiques, musées, monuments, croisières, "
"spectacles et expériences disponibles sur la région parisienne."
)
doc.add_heading("1.2 Objectifs stratégiques", level=2)
items = [
"Centraliser l'offre touristique parisienne sur un portail B2B unique",
"Simplifier le processus de réservation pour les professionnels",
"Offrir des tarifs négociés et des conditions commerciales adaptées au B2B",
"Fournir des outils d'aide à la vente (contenus, médias, suggestions IA)",
"Assurer une visibilité optimale via une stratégie SEO avancée",
"Garantir une expérience utilisateur fluide sur tous les supports (responsive design)",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("1.3 Périmètre", level=2)
doc.add_paragraph(
"Le périmètre couvre la conception, le développement, le déploiement et la maintenance "
"corrective de la plateforme (application web responsive, back-office d'administration, "
"APIs d'intégration). Les applications mobiles natives sont exclues de cette première version "
"mais pourront faire l'objet d'une évolution ultérieure."
)
# ═══════════════════════════════════════
# 2. PUBLIC CIBLE
# ═══════════════════════════════════════
doc.add_heading("2. Public cible et personas", level=1)
doc.add_heading("2.1 Utilisateurs principaux", level=2)
table = doc.add_table(rows=5, cols=3)
table.style = 'Light Grid Accent 1'
headers = ["Persona", "Profil", "Besoins clés"]
for i, h in enumerate(headers):
table.rows[0].cells[i].text = h
data = [
("Agent de voyage", "Employé d'agence, réserve pour le compte de ses clients", "Recherche rapide, devis, réservation groupée"),
("Tour-opérateur", "Conçoit des packages touristiques incluant Paris", "API d'intégration, tarifs volume, allotements"),
("Réceptif / DMC", "Gère l'accueil de groupes sur Paris", "Planning, gestion de groupes, billetterie multi-sites"),
("Administrateur", "Gestionnaire de la plateforme", "Back-office, statistiques, gestion des contenus"),
]
for idx, (persona, profil, besoins) in enumerate(data):
row = table.rows[idx + 1]
row.cells[0].text = persona
row.cells[1].text = profil
row.cells[2].text = besoins
# ═══════════════════════════════════════
# 3. ESPACE PUBLIC
# ═══════════════════════════════════════
doc.add_heading("3. Espace public", level=1)
doc.add_heading("3.1 Page d'accueil", level=2)
items = [
"Présentation de la plateforme et de sa proposition de valeur",
"Mise en avant des offres phares et des nouveautés (carrousel, bannières)",
"Moteur de recherche principal (par type d'activité, date, lieu, thématique)",
"Accès aux catégories principales (musées, monuments, croisières, spectacles, etc.)",
"Témoignages et références clients professionnels",
"Call-to-action vers l'inscription / la demande de compte professionnel",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("3.2 Catalogue des offres", level=2)
items = [
"Navigation par catégorie, thématique, arrondissement ou popularité",
"Fiches produit détaillées : description, photos, informations pratiques, conditions tarifaires",
"Système de filtres avancés (prix, disponibilité, accessibilité PMR, langue)",
"Affichage des disponibilités en temps réel (sous réserve de connexion fournisseur)",
"Suggestions de produits complémentaires (cross-selling assisté par IA)",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("3.3 Pages institutionnelles", level=2)
items = [
"À propos / Qui sommes-nous",
"Conditions générales de vente (CGV) et mentions légales",
"Politique de confidentialité (RGPD)",
"FAQ et centre d'aide",
"Page contact avec formulaire",
"Blog / Actualités du tourisme parisien (levier SEO)",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
# ═══════════════════════════════════════
# 4. ESPACE PRIVÉ
# ═══════════════════════════════════════
doc.add_heading("4. Espace privé (utilisateurs authentifiés)", level=1)
doc.add_heading("4.1 Inscription et authentification", level=2)
items = [
"Formulaire d'inscription avec validation manuelle ou automatique (numéro SIRET, licence d'agence)",
"Authentification sécurisée (email/mot de passe, SSO, 2FA optionnel)",
"Gestion des rôles : administrateur agence, agent, comptable (lecture seule)",
"Récupération et réinitialisation de mot de passe",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("4.2 Dashboard", level=2)
items = [
"Vue d'ensemble de l'activité : réservations récentes, chiffre d'affaires, alertes",
"Indicateurs clés de performance (KPI) personnalisables",
"Raccourcis vers les actions fréquentes (nouvelle réservation, devis en cours)",
"Notifications et messages de la plateforme",
"Calendrier des réservations à venir",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("4.3 Gestion des réservations", level=2)
items = [
"Panier multi-produits avec récapitulatif avant validation",
"Réservation instantanée ou sur demande (selon le fournisseur)",
"Historique complet des réservations avec statuts (confirmée, en attente, annulée)",
"Modification et annulation en ligne selon les conditions tarifaires",
"Téléchargement des billets (PDF, e-tickets, QR codes)",
"Génération de bons de commande et factures",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("4.4 Contenus exclusifs", level=2)
items = [
"Accès à des tarifs préférentiels et promotions réservées aux professionnels",
"Médiathèque professionnelle (photos HD, vidéos, descriptifs éditoriaux libres de droits)",
"Guides et supports de vente téléchargeables (PDF, présentations)",
"Webinaires et formations en ligne sur les produits touristiques",
"Alertes personnalisées sur les nouvelles offres et les disponibilités",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("4.5 Gestion du compte", level=2)
items = [
"Modification des informations de la société et des utilisateurs",
"Gestion des moyens de paiement (prélèvement, virement, carte bancaire, crédit)",
"Consultation du relevé de compte et de l'encours",
"Paramétrage des préférences de notification",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
# ═══════════════════════════════════════
# 5. BACK-OFFICE
# ═══════════════════════════════════════
doc.add_heading("5. Back-office d'administration", level=1)
doc.add_heading("5.1 Gestion des utilisateurs", level=2)
items = [
"CRUD complet sur les comptes professionnels (création, validation, suspension, suppression)",
"Affectation de rôles et permissions granulaires",
"Historique des connexions et journal d'audit",
"Système de validation des inscriptions (workflow d'approbation)",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("5.2 Gestion du catalogue", level=2)
items = [
"Création et édition des fiches produit (WYSIWYG, médias, métadonnées SEO)",
"Gestion des catégories, tags et thématiques",
"Paramétrage des tarifs, allotements et règles de disponibilité",
"Import/export en masse (CSV, XML, API fournisseurs)",
"Gestion des fournisseurs et des contrats associés",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("5.3 Gestion des commandes et de la facturation", level=2)
items = [
"Tableau de bord des commandes avec filtres avancés",
"Validation, modification et annulation de commandes",
"Génération automatique de factures et avoirs",
"Suivi des paiements et relances automatiques",
"Export comptable (formats standards : FEC, CSV)",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("5.4 Gestion des contenus éditoriaux (CMS)", level=2)
items = [
"Éditeur de pages (WYSIWYG) pour les contenus institutionnels et le blog",
"Gestion des bannières, carrousels et mises en avant",
"Planification de publication (programmation à date)",
"Gestion multilingue (français, anglais a minima ; extensible)",
"Prévisualisation avant publication",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("5.5 Statistiques et reporting", level=2)
items = [
"Tableaux de bord analytiques (ventes, CA, taux de conversion, panier moyen)",
"Rapports exportables (PDF, Excel)",
"Suivi du trafic et du comportement utilisateur (intégration analytics)",
"Rapports par fournisseur, par produit, par client",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
# ═══════════════════════════════════════
# 6. DESIGN RESPONSIVE
# ═══════════════════════════════════════
doc.add_heading("6. Prérequis de design responsive", level=1)
doc.add_heading("6.1 Approche Mobile-First", level=2)
doc.add_paragraph(
"La plateforme doit être conçue selon une approche Mobile-First, garantissant une "
"expérience optimale sur tous les terminaux. L'interface doit s'adapter de manière fluide "
"aux résolutions suivantes :"
)
table = doc.add_table(rows=5, cols=3)
table.style = 'Light Grid Accent 1'
headers = ["Breakpoint", "Résolution", "Cible"]
for i, h in enumerate(headers):
table.rows[0].cells[i].text = h
data = [
("Mobile", "320px — 767px", "Smartphones"),
("Tablette", "768px — 1023px", "Tablettes, iPad"),
("Desktop", "1024px — 1439px", "Ordinateurs portables"),
("Large Desktop", "≥ 1440px", "Écrans larges, moniteurs"),
]
for idx, (bp, res, cible) in enumerate(data):
row = table.rows[idx + 1]
row.cells[0].text = bp
row.cells[1].text = res
row.cells[2].text = cible
doc.add_heading("6.2 Exigences d'accessibilité", level=2)
items = [
"Conformité RGAA (Référentiel Général d'Amélioration de l'Accessibilité) niveau AA",
"Navigation au clavier complète",
"Contrastes de couleur conformes aux normes WCAG 2.1",
"Textes alternatifs sur tous les médias",
"Structure sémantique HTML5 (balises header, nav, main, article, etc.)",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("6.3 Performance d'affichage", level=2)
items = [
"Temps de chargement initial (LCP) inférieur à 2,5 secondes sur mobile 4G",
"Score Lighthouse performance ≥ 90",
"Optimisation des images (formats WebP/AVIF, lazy loading, srcset responsive)",
"Mise en cache front-end (Service Worker optionnel pour le mode hors-ligne partiel)",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("6.4 Charte graphique et UI/UX", level=2)
items = [
"Design system documenté (composants, typographie, couleurs, iconographie)",
"Maquettes à fournir pour les 4 breakpoints définis",
"Prototypage interactif (Figma ou équivalent) pour validation avant développement",
"Tests utilisateurs à prévoir sur un panel de professionnels du tourisme",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
# ═══════════════════════════════════════
# 7. OPTIMISATION IA
# ═══════════════════════════════════════
doc.add_heading("7. Outillage pour l'optimisation IA", level=1)
doc.add_heading("7.1 Recommandations intelligentes", level=2)
items = [
"Moteur de recommandation basé sur le comportement utilisateur (historique de réservations, recherches)",
"Suggestions de cross-selling et up-selling contextualisées",
"Personnalisation dynamique de la page d'accueil selon le profil du professionnel",
"Scoring de pertinence des offres en fonction de la saisonnalité et des tendances",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("7.2 Assistance à la rédaction et au contenu", level=2)
items = [
"Génération assistée de descriptions produit (fiches, accroches commerciales)",
"Traduction automatique des contenus avec relecture humaine",
"Suggestion de mots-clés et optimisation sémantique des fiches produit",
"Résumé automatique des avis et retours clients",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("7.3 Chatbot et assistance conversationnelle", level=2)
items = [
"Chatbot intelligent pour l'aide à la recherche et à la réservation",
"Support multilingue (français, anglais, espagnol, allemand a minima)",
"Escalade vers un agent humain si le chatbot ne peut pas répondre",
"Base de connaissances alimentée par les FAQ et la documentation produit",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("7.4 Analyse prédictive", level=2)
items = [
"Prévision de la demande par produit et par période",
"Détection d'anomalies (pics ou creux inhabituels)",
"Optimisation tarifaire dynamique (yield management assisté)",
"Segmentation automatique des clients professionnels",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
# ═══════════════════════════════════════
# 8. OPTIMISATION SEO
# ═══════════════════════════════════════
doc.add_heading("8. Outillage pour l'optimisation SEO", level=1)
doc.add_heading("8.1 SEO technique", level=2)
items = [
"Rendu côté serveur (SSR) ou pré-rendu statique (SSG) pour l'indexabilité des pages",
"URLs propres, lisibles et canoniques (ex: /musees/louvre-billets-coupe-file)",
"Balisage sémantique HTML5 et données structurées Schema.org (Product, Offer, Event, BreadcrumbList)",
"Sitemap XML dynamique et fichier robots.txt configurables depuis le back-office",
"Gestion automatique des redirections 301 lors de modifications d'URL",
"Temps de réponse serveur (TTFB) inférieur à 200ms",
"Support natif du protocole HTTPS et HTTP/2",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("8.2 SEO on-page", level=2)
items = [
"Balises title et meta description éditables par page depuis le back-office",
"Gestion des balises Hn (H1 unique par page, hiérarchie respectée)",
"Attributs alt éditables sur toutes les images",
"Fil d'Ariane (breadcrumb) sur toutes les pages avec balisage structuré",
"Pagination SEO-friendly (rel=prev/next, canonical)",
"Gestion du contenu dupliqué (canonical, hreflang pour le multilingue)",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("8.3 SEO éditorial", level=2)
items = [
"Module de blog intégré avec catégorisation et maillage interne",
"Outils d'analyse sémantique intégrés (densité de mots-clés, lisibilité)",
"Suggestions IA de mots-clés longue traîne liés au tourisme parisien",
"Gestion du maillage interne assistée (suggestions de liens contextuels)",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("8.4 Suivi et monitoring SEO", level=2)
items = [
"Intégration Google Search Console et Google Analytics 4",
"Tableau de bord SEO dans le back-office (positions, impressions, CTR)",
"Alertes automatiques en cas de dégradation (erreurs 404, chute de trafic, pages non indexées)",
"Audit SEO automatisé périodique avec recommandations",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
# ═══════════════════════════════════════
# 9. EXIGENCES TECHNIQUES
# ═══════════════════════════════════════
doc.add_heading("9. Exigences techniques", level=1)
doc.add_heading("9.1 Architecture", level=2)
items = [
"Architecture microservices ou modulaire découplée",
"API REST et/ou GraphQL documentée (OpenAPI / Swagger)",
"Séparation front-end / back-end (headless CMS recommandé)",
"Conteneurisation (Docker) et orchestration (Kubernetes ou équivalent)",
"Infrastructure cloud (AWS, GCP ou Azure) avec auto-scaling",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("9.2 Sécurité", level=2)
items = [
"Chiffrement des données en transit (TLS 1.3) et au repos",
"Conformité RGPD : consentement, droit à l'oubli, portabilité des données",
"Protection OWASP Top 10 (injection SQL, XSS, CSRF, etc.)",
"Authentification OAuth 2.0 / OpenID Connect",
"Audits de sécurité annuels et tests de pénétration",
"Journalisation des accès et des actions sensibles",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("9.3 Performance et disponibilité", level=2)
items = [
"Disponibilité cible : 99,9% (hors maintenance planifiée)",
"Capacité de montée en charge : supporter 10 000 utilisateurs simultanés",
"CDN pour les ressources statiques",
"Stratégie de cache multi-niveaux (CDN, reverse proxy, applicatif)",
"Plan de reprise d'activité (PRA) et plan de continuité d'activité (PCA)",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_heading("9.4 Intégrations tierces", level=2)
items = [
"Passerelle de paiement (Stripe, Adyen ou équivalent) — CB, SEPA, virement",
"Connecteurs fournisseurs (APIs billetterie des sites touristiques)",
"Intégration CRM (Salesforce, HubSpot ou équivalent)",
"Outils d'emailing transactionnel et marketing (SendGrid, Brevo, etc.)",
"Intégration comptable (export FEC, connecteur ERP optionnel)",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
# ═══════════════════════════════════════
# 10. LIVRABLES ET PLANNING
# ═══════════════════════════════════════
doc.add_heading("10. Livrables attendus", level=1)
table = doc.add_table(rows=9, cols=3)
table.style = 'Light Grid Accent 1'
headers = ["Livrable", "Format", "Phase"]
for i, h in enumerate(headers):
table.rows[0].cells[i].text = h
data = [
("Spécifications techniques détaillées", "Document (PDF/DOCX)", "Conception"),
("Maquettes UI/UX", "Figma", "Conception"),
("Prototype interactif", "Figma / URL de staging", "Conception"),
("Code source", "Dépôt Git", "Développement"),
("Documentation technique (API, architecture)", "Markdown / Swagger", "Développement"),
("Jeux de tests (unitaires, intégration, E2E)", "Code source", "Développement"),
("Guide d'administration du back-office", "PDF / Wiki", "Livraison"),
("Plan de mise en production", "Document", "Livraison"),
]
for idx, (livrable, fmt, phase) in enumerate(data):
row = table.rows[idx + 1]
row.cells[0].text = livrable
row.cells[1].text = fmt
row.cells[2].text = phase
# ═══════════════════════════════════════
# 11. CRITÈRES D'ACCEPTATION
# ═══════════════════════════════════════
doc.add_heading("11. Critères d'acceptation", level=1)
items = [
"L'ensemble des fonctionnalités décrites dans ce cahier des charges est opérationnel",
"Les tests automatisés couvrent au minimum 80% du code métier",
"Le score Lighthouse est supérieur ou égal à 90 sur les 4 métriques (Performance, Accessibilité, SEO, Best Practices)",
"Les temps de réponse sont conformes aux seuils définis (TTFB < 200ms, LCP < 2,5s)",
"La plateforme est conforme au RGAA niveau AA",
"Un audit de sécurité a été réalisé sans vulnérabilité critique ou haute non corrigée",
"La documentation technique et utilisateur est complète et à jour",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
# ═══════════════════════════════════════
# 12. ANNEXES
# ═══════════════════════════════════════
doc.add_heading("12. Annexes", level=1)
items = [
"Annexe A — Glossaire des termes métier",
"Annexe B — Liste des sites touristiques et fournisseurs cibles",
"Annexe C — Benchmark concurrentiel",
"Annexe D — Wireframes préliminaires",
"Annexe E — Matrice des rôles et permissions",
]
for item in items:
doc.add_paragraph(item, style='List Bullet')
doc.add_paragraph()
p = doc.add_paragraph("[Contenus des annexes à compléter]")
p.italic = True
# ── Sauvegarde ──
output_path = "/Users/guillaume/workspace/codeanddata.fr/projects/uBlock/tmp/CDC_Billetterie_Tourisme_Paris.docx"
doc.save(output_path)
print(f"Document généré : {output_path}")