diff --git a/app/config/services.yml b/app/config/services.yml
index 39b5b0a3d..26ddfe433 100644
--- a/app/config/services.yml
+++ b/app/config/services.yml
@@ -111,14 +111,6 @@ services:
             $algoliaAppId: '%algolia_app_id%'
             $algoliaFrontendApikey: '%algolia_frontend_api_key%'
 
-    AppBundle\Controller\Website\MemberShipController:
-        autowire: true
-        autoconfigure: true
-        public: false
-        arguments:
-            $storageDir: '%app.general_meetings_dir%'
-            $formLoginAuthenticator: '@security.authenticator.form_login.legacy_secured_area'
-
     AppBundle\Controller\Website\NewsletterController:
         autowire: true
         autoconfigure: true
@@ -311,12 +303,11 @@ services:
         arguments:
           - 'Afup\Site\Forum\Inscriptions'
 
+    Afup\Site\Association\CotisationsFactory:
+        autowire: true
+
     Afup\Site\Association\Cotisations:
-        factory: ['@AppBundle\LegacyModelFactory', 'createObject']
-        arguments:
-          - 'Afup\Site\Association\Cotisations'
-        calls:
-          - [setCompanyMemberRepository, ['@AppBundle\Association\Model\Repository\CompanyMemberRepository']]
+        factory: ['@Afup\Site\Association\CotisationsFactory', 'create']
 
     Parsedown:
         class: Parsedown
diff --git a/sources/Afup/Association/CotisationsFactory.php b/sources/Afup/Association/CotisationsFactory.php
new file mode 100644
index 000000000..804b0cb18
--- /dev/null
+++ b/sources/Afup/Association/CotisationsFactory.php
@@ -0,0 +1,31 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Afup\Site\Association;
+
+use Afup\Site\Utils\Utils;
+use AppBundle\Association\Model\Repository\CompanyMemberRepository;
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
+use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
+
+final readonly class CotisationsFactory
+{
+    public function __construct(
+        private TokenStorageInterface $tokenStorage,
+        private CompanyMemberRepository $companyMemberRepository,
+        private AuthorizationCheckerInterface $authorizationChecker,
+    ) {}
+
+    public function create(): Cotisations
+    {
+        $cotisations =  new Cotisations(
+            $GLOBALS['AFUP_DB'],
+            Utils::fabriqueDroits($this->tokenStorage, $this->authorizationChecker),
+        );
+
+        $cotisations->setCompanyMemberRepository($this->companyMemberRepository);
+
+        return $cotisations;
+    }
+}
diff --git a/sources/AppBundle/Association/CompanyMembership/SubscriptionManagement.php b/sources/AppBundle/Association/CompanyMembership/SubscriptionManagement.php
index 885952824..b682ef96c 100644
--- a/sources/AppBundle/Association/CompanyMembership/SubscriptionManagement.php
+++ b/sources/AppBundle/Association/CompanyMembership/SubscriptionManagement.php
@@ -7,20 +7,17 @@
 use Afup\Site\Association\Cotisations;
 use Afup\Site\Utils\Utils;
 use AppBundle\Association\Model\CompanyMember;
-use AppBundle\LegacyModelFactory;
 
-class SubscriptionManagement
+final readonly class SubscriptionManagement
 {
-    public function __construct(private readonly LegacyModelFactory $legacyModelFactory) {}
+    public function __construct(private Cotisations $cotisations) {}
 
     public function createInvoiceForInscription(CompanyMember $company, $numberOfMembers): array
     {
-        $subscription = $this->legacyModelFactory->createObject(Cotisations::class);
-
-        $endSubscription = $subscription->finProchaineCotisation(false);
+        $endSubscription = $this->cotisations->finProchaineCotisation(false);
 
         // Create the invoice
-        $subscription->ajouter(
+        $this->cotisations->ajouter(
             AFUP_PERSONNES_MORALES,
             $company->getId(),
             ceil($numberOfMembers / AFUP_PERSONNE_MORALE_SEUIL) * AFUP_COTISATION_PERSONNE_MORALE * (1 + Utils::MEMBERSHIP_FEE_VAT_RATE),
@@ -30,7 +27,7 @@ public function createInvoiceForInscription(CompanyMember $company, $numberOfMem
             $endSubscription->format('U'),
             '',
         );
-        $subscriptionArray = $subscription->obtenirDerniere(AFUP_PERSONNES_MORALES, $company->getId());
+        $subscriptionArray = $this->cotisations->obtenirDerniere(AFUP_PERSONNES_MORALES, $company->getId());
 
         if ($subscriptionArray === false) {
             throw new \RuntimeException('An error occured');
diff --git a/sources/AppBundle/Controller/Website/MemberShipController.php b/sources/AppBundle/Controller/Website/MemberShipController.php
index f141106f1..64636493f 100644
--- a/sources/AppBundle/Controller/Website/MemberShipController.php
+++ b/sources/AppBundle/Controller/Website/MemberShipController.php
@@ -45,6 +45,7 @@
 use AppBundle\Twig\ViewRenderer;
 use Assert\Assertion;
 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\DependencyInjection\Attribute\Autowire;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 use Symfony\Component\Finder\Finder;
 use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
@@ -78,6 +79,7 @@ public function __construct(
         private CompanyMemberRepository $companyMemberRepository,
         private UserService $userService,
         private UserAuthenticatorInterface $userAuthenticator,
+        #[Autowire('@security.authenticator.form_login.legacy_secured_area')]
         private FormLoginAuthenticator $formLoginAuthenticator,
         private InvitationMail $invitationMail,
         private SubscriptionManagement $subscriptionManagement,
@@ -88,12 +90,14 @@ public function __construct(
         private GeneralMeetingRepository $generalMeetingRepository,
         private GeneralMeetingQuestionRepository $generalMeetingQuestionRepository,
         private GeneralMeetingVoteRepository $generalMeetingVoteRepository,
+        #[Autowire('%app.general_meetings_dir%')]
         private string $storageDir,
         private UserPasswordHasherInterface $passwordHasher,
         private CompanyMemberInvitationRepository $companyMemberInvitationRepository,
         private TechletterSubscriptionsRepository $techletterSubscriptionsRepository,
         private TechletterUnsubscriptionsRepository $techletterUnsubscriptionsRepository,
         private SendingRepository $sendingRepository,
+        private Cotisations $cotisations,
     ) {}
 
     public function becomeMember(): Response
@@ -183,11 +187,7 @@ public function company(Request $request)
 
     public function payment(string $invoiceNumber, ?string $token): Response
     {
-        /**
-         * @var Cotisations $subscription
-         */
-        $subscription = $this->legacyModelFactory->createObject(Cotisations::class);
-        $invoice = $subscription->getByInvoice($invoiceNumber, $token);
+        $invoice = $this->cotisations->getByInvoice($invoiceNumber, $token);
         $company = $this->companyMemberRepository->get($invoice['id_personne']);
 
         if (!$invoice || $company === null) {
@@ -220,18 +220,14 @@ public function payment(string $invoiceNumber, ?string $token): Response
 
     public function invoice(string $invoiceNumber, ?string $token): Response
     {
-        /**
-         * @var Cotisations $subscription
-         */
-        $subscription = $this->legacyModelFactory->createObject(Cotisations::class);
-        $invoice = $subscription->getByInvoice($invoiceNumber, $token);
+        $invoice = $this->cotisations->getByInvoice($invoiceNumber, $token);
 
         if (!$invoice) {
             throw $this->createNotFoundException(sprintf('Could not find the invoice "%s" with token "%s"', $invoiceNumber, $token));
         }
 
         ob_start();
-        $subscription->genererFacture($invoice['id']);
+        $this->cotisations->genererFacture($invoice['id']);
         $pdf = ob_get_clean();
 
         $response = new Response($pdf);
@@ -309,11 +305,7 @@ public function slackInviteRequest(): RedirectResponse
     public function payboxCallback(Request $request)
     {
         $payboxResponse = PayboxResponseFactory::createFromRequest($request);
-        /**
-         * @var Cotisations $cotisations
-         */
-        $cotisations = $this->legacyModelFactory->createObject(Cotisations::class);
-        $cotisations->setCompanyMemberRepository($this->companyMemberRepository);
+        $this->cotisations->setCompanyMemberRepository($this->companyMemberRepository);
         $logs = $this->legacyModelFactory->createObject(Logs::class);
 
         $status = $payboxResponse->getStatus();
@@ -331,16 +323,16 @@ public function payboxCallback(Request $request)
         }
 
         if ($etat == AFUP_COTISATIONS_PAIEMENT_REGLE) {
-            $account = $cotisations->getAccountFromCmd($payboxResponse->getCmd());
-            $lastCotisation = $cotisations->obtenirDerniere($account['type'], $account['id']);
+            $account = $this->cotisations->getAccountFromCmd($payboxResponse->getCmd());
+            $lastCotisation = $this->cotisations->obtenirDerniere($account['type'], $account['id']);
 
             if ($lastCotisation === false && $account['type'] == UserRepository::USER_TYPE_PHYSICAL) {
                 $user = $this->userRepository->get($account['id']);
                 $this->eventDispatcher->dispatch(new NewMemberEvent($user));
             }
 
-            $cotisations->validerReglementEnLigne($payboxResponse->getCmd(), round($payboxResponse->getTotal() / 100, 2), $payboxResponse->getAuthorizationId(), $payboxResponse->getTransactionId());
-            $cotisations->notifierReglementEnLigneAuTresorier($payboxResponse->getCmd(), round($payboxResponse->getTotal() / 100, 2), $payboxResponse->getAuthorizationId(), $payboxResponse->getTransactionId(), $this->userRepository);
+            $this->cotisations->validerReglementEnLigne($payboxResponse->getCmd(), round($payboxResponse->getTotal() / 100, 2), $payboxResponse->getAuthorizationId(), $payboxResponse->getTransactionId());
+            $this->cotisations->notifierReglementEnLigneAuTresorier($payboxResponse->getCmd(), round($payboxResponse->getTotal() / 100, 2), $payboxResponse->getAuthorizationId(), $payboxResponse->getTransactionId(), $this->userRepository);
             $logs::log("Ajout de la cotisation " . $payboxResponse->getCmd() . " via Paybox.");
         }
         return new Response();
@@ -389,7 +381,6 @@ private function getDroits(): Droits
     public function membershipFee(): Response
     {
         $userService = $this->userService;
-        $cotisations = $this->getCotisations();
 
         $identifiant = $this->getDroits()->obtenirIdentifiant();
         $user = $this->userRepository->get($identifiant);
@@ -401,7 +392,7 @@ public function membershipFee(): Response
         if (!$cotisation) {
             $message = '';
         } else {
-            $endSubscription = $cotisations->finProchaineCotisation($cotisation);
+            $endSubscription = $this->cotisations->finProchaineCotisation($cotisation);
             $message = sprintf(
                 'Votre dernière cotisation -- %s %s -- est valable jusqu\'au %s. <br />
         Si vous renouvelez votre cotisation maintenant, celle-ci sera valable jusqu\'au %s.',
@@ -412,8 +403,8 @@ public function membershipFee(): Response
             );
         }
 
-        $cotisations_physique = $cotisations->obtenirListe(0, $user->getId());
-        $cotisations_morale = $cotisations->obtenirListe(1, $user->getCompanyId());
+        $cotisations_physique = $this->cotisations->obtenirListe(0, $user->getId());
+        $cotisations_morale = $this->cotisations->obtenirListe(1, $user->getCompanyId());
 
         if (is_array($cotisations_morale) && is_array($cotisations_physique)) {
             $liste_cotisations = array_merge($cotisations_physique, $cotisations_morale);
@@ -426,7 +417,7 @@ public function membershipFee(): Response
         }
 
         foreach ($liste_cotisations as $k => $cotisation) {
-            $liste_cotisations[$k]['telecharger_facture'] = $cotisations->isCurrentUserAllowedToReadInvoice($cotisation['id']);
+            $liste_cotisations[$k]['telecharger_facture'] = $this->cotisations->isCurrentUserAllowedToReadInvoice($cotisation['id']);
         }
 
         if ($user->getCompanyId() > 0) {
@@ -485,20 +476,19 @@ private function getCotisations(): Cotisations
 
     public function membershipFeeDownload(Request $request): BinaryFileResponse
     {
-        $cotisations = $this->getCotisations();
         $identifiant = $this->getDroits()->obtenirIdentifiant();
         $id = $request->get('id');
 
         $logs = $this->legacyModelFactory->createObject(Logs::class);
 
-        if (false === $cotisations->isCurrentUserAllowedToReadInvoice($id)) {
+        if (false === $this->cotisations->isCurrentUserAllowedToReadInvoice($id)) {
             $logs::log("L'utilisateur id: " . $identifiant . ' a tenté de voir la facture id:' . $id);
             throw $this->createAccessDeniedException('Cette facture ne vous appartient pas, vous ne pouvez la visualiser.');
         }
 
         $tempfile = tempnam(sys_get_temp_dir(), 'membership_fee_download');
-        $numeroFacture = $cotisations->genererFacture($id, $tempfile);
-        $cotisation = $cotisations->obtenir($id);
+        $numeroFacture = $this->cotisations->genererFacture($id, $tempfile);
+        $cotisation = $this->cotisations->obtenir($id);
 
         if ($cotisation['type_personne'] == AFUP_PERSONNES_MORALES) {
             $company = $this->companyMemberRepository->get($cotisation['id_personne']);
@@ -521,19 +511,18 @@ public function membershipFeeDownload(Request $request): BinaryFileResponse
 
     public function membershipFeeSendMail(Request $request): RedirectResponse
     {
-        $cotisations = $this->getCotisations();
         $identifiant = $this->getDroits()->obtenirIdentifiant();
         $id = $request->get('id');
 
         $logs = $this->legacyModelFactory->createObject(Logs::class);
         $userRepository = $this->userRepository;
 
-        if (false === $cotisations->isCurrentUserAllowedToReadInvoice($id)) {
+        if (false === $this->cotisations->isCurrentUserAllowedToReadInvoice($id)) {
             $logs::log("L'utilisateur id: " . $identifiant . ' a tenté de voir la facture id:' . $id);
             throw $this->createAccessDeniedException('Cette facture ne vous appartient pas, vous ne pouvez la visualiser.');
         }
 
-        if ($cotisations->envoyerFacture($id, $this->mailer, $userRepository)) {
+        if ($this->cotisations->envoyerFacture($id, $this->mailer, $userRepository)) {
             $logs::log('Envoi par email de la facture pour la cotisation n°' . $id);
             $this->addFlash('success', 'La facture a été envoyée par mail');
         } else {