BCard - Documentation technique

CompanyRegistrationController extends AbstractController
in package

Contrôleur du tunnel d'inscription d'une entreprise à l'offre B-Card.

Il orchestre un parcours en cinq étapes : saisie de l'identité du contact et création du compte (ROLE_MANAGER), vérification de l'adresse email par code, renseignement des informations de l'entreprise, choix de l'abonnement au plan « Entreprise » puis paiement par Stripe Checkout et confirmation. L'état intermédiaire du parcours n'est pas persisté en base mais conservé en session par CompanyRegistrationService ; l'entreprise, l'abonnement et le mot de passe définitif ne sont créés qu'au retour d'un paiement effectivement encaissé, le mot de passe temporaire étant alors envoyé par email au gestionnaire.

Préfixe de route : /company. Aucun contrôle d'accès au niveau de la classe : le parcours est public puisqu'il précède l'existence d'un compte utilisable.

Attributes
#[Route]
'/company'

Table of Contents

Properties

$auditLogger  : AuditLogger
$emailVerificationService  : EmailVerificationService
$entityManager  : EntityManagerInterface
$mailerService  : MailerService
$passwordHasher  : UserPasswordHasherInterface
$paymentService  : PaymentService
$planRepository  : PlanRepository
$registrationService  : CompanyRegistrationService
$stripeService  : StripeService
$userRepository  : UserRepository
$validator  : ValidatorInterface

Methods

__construct()  : mixed
calculateAmount()  : Response
AJAX endpoint for calculating subscription amount
cancel()  : Response
Cancel registration process
confirmation()  : Response
Step 5: Confirmation and Final Processing
details()  : Response
Step 2: Company Details (after email verification)
payment()  : Response
Step 4: Payment and Address Information
paymentCancel()  : Response
Handle cancelled Stripe payment
paymentProcess()  : Response
Enregistre le moyen de paiement choisi et déclenche le paiement correspondant.
paymentSuccess()  : Response
Handle successful Stripe payment
register()  : Response
Step 1: Company Details Registration
resendVerification()  : Response
Renvoie un code de vérification d'email au contact de l'entreprise.
subscription()  : Response
Step 3: Subscription Selection
verifyEmail()  : Response
Affiche l'écran de saisie du code de vérification d'email et le valide.
redirectToStripeCheckout()  : Response
Redirect to Stripe Checkout for subscription payment
sendTemporaryPasswordEmail()  : void
Send temporary password email to user

Properties

Methods

__construct()

public __construct(CompanyRegistrationService $registrationService, PaymentService $paymentService, StripeService $stripeService, PlanRepository $planRepository, EmailVerificationService $emailVerificationService, UserRepository $userRepository, ValidatorInterface $validator, UserPasswordHasherInterface $passwordHasher, EntityManagerInterface $entityManager, MailerService $mailerService, AuditLogger $auditLogger) : mixed
Parameters
$registrationService : CompanyRegistrationService

Conserve en session les données du parcours et finalise l'inscription.

$paymentService : PaymentService

Calcule et formate le montant de l'abonnement selon le plan, le cycle et l'effectif.

$stripeService : StripeService

Crée et relit les sessions Stripe Checkout.

$planRepository : PlanRepository

Charge les plans d'abonnement, notamment le plan « Entreprise » actif.

$emailVerificationService : EmailVerificationService

Envoie et valide les codes de vérification d'email.

$userRepository : UserRepository

Recherche les utilisateurs par identifiant ou par email.

$validator : ValidatorInterface

Valide l'adresse email saisie à la première étape.

$passwordHasher : UserPasswordHasherInterface

Hache le mot de passe temporaire du compte gestionnaire créé.

$entityManager : EntityManagerInterface

Gestionnaire d'entités Doctrine (persistance de l'utilisateur).

$mailerService : MailerService

Envoie l'email contenant les identifiants de connexion.

$auditLogger : AuditLogger

Trace la création ou la mise à jour du compte gestionnaire.

calculateAmount()

AJAX endpoint for calculating subscription amount

public calculateAmount(Request $request) : Response

Calcule à la volée le montant d'un abonnement pour l'affichage dynamique du tunnel.

Lit plan_id, billing_cycle et employee_count (converti en entier, 1 par défaut) dans le corps de la requête, puis délègue le calcul et le formatage au service de paiement. Aucune donnée n'est modifiée ni stockée en session : le résultat sert uniquement à rafraîchir l'affichage côté client.

Route : /company/calculate-amount (POST), nom company_calculate_amount.

Parameters
$request : Request

Requête HTTP contenant plan_id, billing_cycle et employee_count.

Attributes
#[Route]
'/calculate-amount'
$name: 'company_calculate_amount'
$methods: ['POST']
Return values
Response

Réponse JSON array{success: true, amount: mixed, formatted_amount: string} en HTTP 200, ou array{success: false, message: string} en HTTP 400 si le calcul lève une exception (plan inconnu, cycle invalide, etc.).

cancel()

Cancel registration process

public cancel() : Response

Annule volontairement le tunnel d'inscription en cours.

Vide les données du parcours stockées en session et informe l'utilisateur. Le compte utilisateur éventuellement créé à l'étape 1 et déjà persisté en base n'est pas supprimé.

Route : /company/cancel (POST), nom company_registration_cancel.

Attributes
#[Route]
'/cancel'
$name: 'company_registration_cancel'
$methods: ['POST']
Return values
Response

Redirection vers app_home.

confirmation()

Step 5: Confirmation and Final Processing

public confirmation() : Response

Étape 5 du tunnel : affiche le récapitulatif final de l'inscription.

Relit les données d'entreprise et d'utilisateur conservées en session et les fusionne en injectant l'email et le nom du contact dans le tableau transmis au template. Malgré son intitulé, la méthode n'effectue aucun traitement final : la création effective de l'entreprise est réalisée par CompanyRegistrationController::paymentSuccess() au retour de Stripe. Aucune vérification de présence des données n'est faite, la page peut donc être atteinte avec un contexte vide.

Route : /company/confirmation (GET, POST), nom company_confirmation.

Attributes
#[Route]
'/confirmation'
$name: 'company_confirmation'
$methods: ['GET', 'POST']
Return values
Response

Page de confirmation rendue (company/registration/confirmation.html.twig, étape 5/5).

details()

Step 2: Company Details (after email verification)

public details(Request $request, int $user_id, SessionInterface $session) : Response

Étape 2 du tunnel : collecte les informations de l'entreprise et du contact.

L'accès exige un utilisateur existant ET vérifié, sinon retour à l'étape 1 ; si le compte est déjà rattaché à une entreprise, le parcours est interrompu au profit du tableau de bord. Les données de l'utilisateur sont poussées en session par le service d'inscription, et le formulaire est pré-alimenté avec le contenu déjà présent sous la clé de session company_registration, complété de l'email et du nom du contact. À la soumission valide, la position et le téléphone du contact sont écrits sur l'entité User et immédiatement persistés, tandis qu'un objet Company est seulement hydraté puis stocké en session — l'entreprise n'est pas encore enregistrée en base à ce stade.

Route : /company/details/{user_id} (GET, POST), nom company_details.

Parameters
$request : Request

Requête HTTP portant le formulaire CompanyDetailsType.

$user_id : int

Identifiant du contact/gestionnaire à l'origine de l'inscription.

$session : SessionInterface

Session utilisée pour relire les données d'inscription déjà saisies.

Attributes
#[Route]
'/details/{user_id}'
$name: 'company_details'
$methods: ['GET', 'POST']
Return values
Response

Redirection vers company_register ou app_dashboard selon les contrôles d'accès, vers company_subscription après soumission valide, sinon le formulaire rendu (company/registration/details.html.twig, étape 2/5).

payment()

Step 4: Payment and Address Information

public payment() : Response

Étape 4 du tunnel : récapitule la commande avant le choix du moyen de paiement.

Les données d'abonnement sont relues en session ; leur absence interrompt le parcours et renvoie à l'étape 1. Le nom du plan est résolu depuis son identifiant (repli sur « Entreprise » si le plan n'est plus trouvé) et le montant est formaté en francs guinéens (séparateur décimal virgule, séparateur de milliers espace, suffixe GNF). Aucune donnée n'est modifiée ni persistée.

Route : /company/payment (GET, POST), nom company_payment.

Attributes
#[Route]
'/payment'
$name: 'company_payment'
$methods: ['GET', 'POST']
Return values
Response

Redirection vers company_register si les données de souscription manquent, sinon la page de paiement rendue (company/registration/payment.html.twig, étape 4/5).

paymentCancel()

Handle cancelled Stripe payment

public paymentCancel() : Response

Traite le retour de Stripe lorsque l'utilisateur abandonne le paiement.

Purge intégralement les données du parcours conservées en session, puis affiche un avertissement invitant à réessayer. À noter : la session étant vidée, la page de paiement vers laquelle l'utilisateur est renvoyé ne retrouvera plus les données de souscription et le renverra à son tour vers le début du tunnel.

Route : /company/payment/cancel (GET), nom company_registration_payment_cancel.

Attributes
#[Route]
'/payment/cancel'
$name: 'company_registration_payment_cancel'
$methods: ['GET']
Return values
Response

Redirection vers company_payment.

paymentProcess()

Enregistre le moyen de paiement choisi et déclenche le paiement correspondant.

public paymentProcess(Request $request) : Response

Seules les valeurs card et orange_money sont acceptées ; toute autre valeur est journalisée et ramène à la page de paiement avec un message d'erreur. Le choix est conservé en session, puis le paiement par carte est délégué à CompanyRegistrationController::redirectToStripeCheckout(). Orange Money n'est pas encore implémenté : l'utilisateur est informé par un message d'information et renvoyé à l'accueil, ce qui interrompt le tunnel sans annuler les données stockées en session.

Route : /company/payment-process (POST), nom company_registration_payment_process.

Parameters
$request : Request

Requête HTTP contenant le champ method.

Attributes
#[Route]
'/payment-process'
$name: 'company_registration_payment_process'
$methods: ['POST']
Return values
Response

Redirection vers Stripe Checkout pour un paiement par carte, vers app_home pour Orange Money, ou vers company_payment si la méthode est invalide.

paymentSuccess()

Handle successful Stripe payment

public paymentSuccess(Request $request) : Response

Traite le retour de Stripe après un paiement et finalise l'inscription de l'entreprise.

Le paramètre de requête session_id est obligatoire ; la session Checkout correspondante est relue auprès de Stripe et l'inscription n'est finalisée que si son payment_status vaut paid — c'est le seul point du parcours où l'entreprise, l'abonnement et le compte définitif sont réellement créés, via CompanyRegistrationService::completeRegistration(). En cas de succès, le mot de passe temporaire est envoyé au gestionnaire par CompanyRegistrationController::sendTemporaryPasswordEmail() et l'utilisateur est redirigé vers la page de confirmation. Un paiement non confirmé, un échec de finalisation ou une exception ramènent à la page de paiement ou de confirmation avec un message flash explicatif.

Route : /company/payment/success (GET), nom company_registration_payment_success.

Parameters
$request : Request

Requête HTTP contenant le paramètre session_id fourni par Stripe.

Attributes
#[Route]
'/payment/success'
$name: 'company_registration_payment_success'
$methods: ['GET']
Return values
Response

Redirection vers company_confirmation si l'inscription est finalisée, sinon vers company_payment (session absente, paiement non confirmé, exception) ou vers company_confirmation sans succès si la finalisation échoue.

register()

Step 1: Company Details Registration

public register(Request $request) : Response

Étape 1 du tunnel : identifie le contact et crée (ou réutilise) le compte gestionnaire.

En POST, les champs email et name sont lus directement dans la requête et doivent être renseignés ; l'email est ensuite validé par les contraintes NotBlank et Email (la contrainte BusinessEmail, qui interdirait les adresses personnelles, est présente mais commentée). Trois cas se présentent ensuite : un compte existant et déjà vérifié bloque l'inscription ; un compte existant non vérifié est réutilisé, son nom étant mis à jour si nécessaire ; sinon un nouvel utilisateur est créé avec le rôle ROLE_MANAGER et un mot de passe temporaire aléatoire haché. La création ou la mise à jour est tracée au journal d'audit, puis un code de vérification est envoyé par email. Toute exception pendant cette phase est écrite dans le journal PHP et convertie en message flash, le formulaire étant alors réaffiché.

Route : /company/register (GET, POST), nom company_register.

Parameters
$request : Request

Requête HTTP contenant les champs email et name en POST.

Tags
throws
RandomException|TransportExceptionInterface
Attributes
#[Route]
'/register'
$name: 'company_register'
$methods: ['GET', 'POST']
Return values
Response

Redirection vers company_verify_email en cas de succès, sinon le formulaire rendu (company/registration/register.html.twig) avec l'état de progression (étape 1/5).

resendVerification()

Renvoie un code de vérification d'email au contact de l'entreprise.

public resendVerification(int $user_id) : Response

Refuse l'envoi si l'utilisateur est introuvable (retour à l'étape 1), s'il est déjà vérifié (passage à l'étape des informations d'entreprise) ou si le délai anti-spam de EmailVerificationService::canResendCode() n'est pas écoulé. Les échecs d'envoi sont silencieusement écrits dans le journal PHP : une exception applicative produit en plus un message flash d'erreur, tandis qu'une erreur de transport n'est que journalisée, l'utilisateur voyant alors potentiellement un message de succès trompeur.

Route : /company/resend-verification/{user_id} (GET, POST), nom company_resend_verification.

Parameters
$user_id : int

Identifiant de l'utilisateur destinataire du nouveau code.

Attributes
#[Route]
'/resend-verification/{user_id}'
$name: 'company_resend_verification'
Return values
Response

Redirection vers company_verify_email dans le cas nominal, vers company_register si l'utilisateur est introuvable ou vers company_details s'il est déjà vérifié.

subscription()

Step 3: Subscription Selection

public subscription(Request $request) : Response

Étape 3 du tunnel : choix du cycle de facturation de l'abonnement « Entreprise ».

L'effectif est repris des données d'entreprise en session (1 par défaut) et sert à dimensionner le formulaire. Seul le plan nommé « Entreprise » et actif est proposé ; s'il est absent du catalogue, un message d'erreur est affiché et l'utilisateur est renvoyé vers company_details — redirection générée sans le paramètre user_id, ce qui peut échouer si la route l'exige. À la soumission valide, le montant total est calculé par le service de paiement à partir du plan, du cycle de facturation et de l'effectif, affecté à l'abonnement, puis l'ensemble est stocké en session avant de passer au paiement. Comme à l'étape 2, aucun abonnement n'est persisté en base ici.

Route : /company/subscription (GET, POST), nom company_subscription.

Parameters
$request : Request

Requête HTTP portant le formulaire SubscriptionType.

Attributes
#[Route]
'/subscription'
$name: 'company_subscription'
$methods: ['GET', 'POST']
Return values
Response

Redirection vers company_details si le plan « Entreprise » est indisponible, vers company_payment après soumission valide, sinon le formulaire rendu (company/registration/subscription.html.twig, étape 3/5).

verifyEmail()

Affiche l'écran de saisie du code de vérification d'email et le valide.

public verifyEmail(Request $request, int $user_id) : Response

L'utilisateur est identifié par le paramètre d'URL {user_id} : s'il est introuvable, retour à l'étape 1 ; s'il est déjà vérifié, le parcours saute directement à l'étape des informations d'entreprise. En POST, un code vide produit un message d'erreur et le réaffichage du formulaire ; un code correct fait passer à company_details, un code invalide ou expiré n'affiche qu'un message flash sans limitation du nombre de tentatives. Aucun contrôle d'accès ne protège cette route : le seul identifiant numérique de l'utilisateur suffit à y accéder.

Route : /company/verify-email/{user_id} (GET, POST), nom company_verify_email.

Parameters
$request : Request

Requête HTTP contenant le champ verification_code en POST.

$user_id : int

Identifiant de l'utilisateur dont l'email doit être vérifié.

Attributes
#[Route]
'/verify-email/{user_id}'
$name: 'company_verify_email'
Return values
Response

Redirection vers company_register si l'utilisateur est introuvable, vers company_details si l'email est vérifié, sinon le formulaire rendu (company/registration/email-verification.html.twig).

redirectToStripeCheckout()

Redirect to Stripe Checkout for subscription payment

private redirectToStripeCheckout(array<string, mixed> $subscriptionData) : Response

Crée la session Stripe Checkout de l'abonnement et redirige l'utilisateur vers la page de paiement.

Construit une ligne de facturation unique libellée « Abonnement », décrivant le cycle et le nombre d'employés, en devise gnf et pour un montant transmis tel quel en unité entière. Les URL de retour absolues sont générées vers company_registration_payment_success (avec le marqueur {CHECKOUT_SESSION_ID} remplacé par Stripe) et company_registration_payment_cancel. Les données de souscription sérialisées et l'identifiant de l'utilisateur sont attachés en métadonnées Stripe ; l'absence de données utilisateur en session provoque une exception. L'identifiant de session Stripe est ensuite mémorisé en session pour la vérification ultérieure. Toute exception est journalisée et convertie en message flash.

Parameters
$subscriptionData : array<string, mixed>

Données de souscription en session : plan_id, amount, billing_cycle, employee_count.

Tags
throws
Exception

Levée en interne si les données utilisateur sont absentes de la session ; l'exception est immédiatement rattrapée par le bloc catch de la méthode.

Return values
Response

Redirection vers l'URL de la session Stripe Checkout, ou vers company_payment en cas d'erreur.

sendTemporaryPasswordEmail()

Send temporary password email to user

private sendTemporaryPasswordEmail(User $user, string $temporaryPassword) : void

Envoie au gestionnaire l'email contenant ses identifiants de connexion.

Utilise le template company_registration/temporary_password avec l'utilisateur, son entreprise, le mot de passe temporaire en clair et l'URL absolue de connexion. La méthode est volontairement tolérante aux pannes : les exceptions applicatives comme les erreurs de transport sont uniquement écrites dans le journal PHP, afin qu'un échec d'envoi ne remette pas en cause une inscription déjà payée et finalisée.

Parameters
$user : User

Gestionnaire destinataire, dont l'entreprise est jointe au message.

$temporaryPassword : string

Mot de passe temporaire en clair généré lors de la finalisation.


        
On this page

Search results