Commit 7e886ec1 by Damien Moulard

Merge branch '7381-calculate-allocation-with-simplified-household' into 'sprint-2-montpellier'

calculate allocation with simplified household process

See merge request !123
parents 588199a5 70f43ef3
...@@ -50,6 +50,7 @@ PRESTA_SELF_INIT_AND_EVAL=0 ...@@ -50,6 +50,7 @@ PRESTA_SELF_INIT_AND_EVAL=0
AUTOMATISATION_RECONVERSION=0 AUTOMATISATION_RECONVERSION=0
PRESTA_EXTRA_DATA=0 PRESTA_EXTRA_DATA=0
HOUSEHOLD_BASED_ALLOWANCE=0 HOUSEHOLD_BASED_ALLOWANCE=0
SIMPLIFIED_HOUSEHOLD_BASED_ALLOWANCE=0
SSA_FRIENDLY_FLUX_TYPE_NAMES=0 SSA_FRIENDLY_FLUX_TYPE_NAMES=0
CCAS_MODE=0 CCAS_MODE=0
EXTRA_SECURITY_ADMIN_PASSWORD=ChangeMe EXTRA_SECURITY_ADMIN_PASSWORD=ChangeMe
......
...@@ -57,7 +57,8 @@ Copier le fichier .env.dist en .env et configurer : ...@@ -57,7 +57,8 @@ Copier le fichier .env.dist en .env et configurer :
- en environnement TAV, pour activer le parcours d'inscription autonomisé qui intègre la réponse à une questionnaire d'auto-évaluation pour les points de vente, passer PRESTA_SELF_INIT_AND_EVAL à 1 - en environnement TAV, pour activer le parcours d'inscription autonomisé qui intègre la réponse à une questionnaire d'auto-évaluation pour les points de vente, passer PRESTA_SELF_INIT_AND_EVAL à 1
- en environnement TAV, la variable AUTOMATISATION_RECONVERSION permet d'activer l'automatisation des reconversions - en environnement TAV, la variable AUTOMATISATION_RECONVERSION permet d'activer l'automatisation des reconversions
- en environnement TAV, la variable PRESTA_EXTRA_DATA permet d'indiquer puis d'afficher publiquement plus de données concernant les prestataires (e.g. familles de produits) - en environnement TAV, la variable PRESTA_EXTRA_DATA permet d'indiquer puis d'afficher publiquement plus de données concernant les prestataires (e.g. familles de produits)
- en environnement TAV, la variable HOUSEHOLD_BASED_ALLOWANCE permet d'activer un mode de cotisations libres et d'allocations basées sur la composition du foyer - en environnement TAV, la variable HOUSEHOLD_BASED_ALLOWANCE permet d'activer un mode de cotisation libre (avec valeur minimum) et d'allocations basées sur la composition du foyer. Active également la possibilité pour l'admin de renseigner un quartier ainsi qu'un territoire à une fiche adhérent, rajoute l'information "Solde & plafond" dans la liste des adhérents (plafond défini à 2x le montant de l'allocation), ainsi que la possibilité de corriger le solde d'un adhérent.
- en environnement TAV, la variable SIMPLIFIED_HOUSEHOLD_BASED_ALLOWANCE permet d'activer un mode simplifié d'allocation en fonction de la composition du foyer (pas de minimum de cotisation, moins de détails dans la composition du foyer de l'adhérent, pas de renseignement de territoire dans la fiche adhérent, calcul de l'allocation simplifié, pas de plafond de solde). /!\ Requiert l'activation de HOUSEHOLD_BASED_ALLOWANCE.
- en environnement TAV, la variable SSA_FRIENDLY_FLUX_TYPE_NAMES permet d'adapter le nommage des types de flux et les écrans de visualisation des flux à un projet de type SSA - en environnement TAV, la variable SSA_FRIENDLY_FLUX_TYPE_NAMES permet d'adapter le nommage des types de flux et les écrans de visualisation des flux à un projet de type SSA
- en environnement TAV, la varialble CCAS_MODE permet d'activer les fonctionnalités de branchement avec une CCAS. Attention : Pour activer CCAS_MODE, le paramètre AUTOMATISATION_RECONVERSION doit OBLIGATOIREMENT être activé. - en environnement TAV, la varialble CCAS_MODE permet d'activer les fonctionnalités de branchement avec une CCAS. Attention : Pour activer CCAS_MODE, le paramètre AUTOMATISATION_RECONVERSION doit OBLIGATOIREMENT être activé.
......
...@@ -17,6 +17,7 @@ parameters: ...@@ -17,6 +17,7 @@ parameters:
automatisation_reconversion: '%env(AUTOMATISATION_RECONVERSION)%' automatisation_reconversion: '%env(AUTOMATISATION_RECONVERSION)%'
presta_extra_data: '%env(PRESTA_EXTRA_DATA)%' presta_extra_data: '%env(PRESTA_EXTRA_DATA)%'
household_based_allowance: '%env(HOUSEHOLD_BASED_ALLOWANCE)%' household_based_allowance: '%env(HOUSEHOLD_BASED_ALLOWANCE)%'
simplified_household_based_allowance: '%env(SIMPLIFIED_HOUSEHOLD_BASED_ALLOWANCE)%'
ssa_friendly_flux_type_names: '%env(SSA_FRIENDLY_FLUX_TYPE_NAMES)%' ssa_friendly_flux_type_names: '%env(SSA_FRIENDLY_FLUX_TYPE_NAMES)%'
extra_security_admin_password: '%env(EXTRA_SECURITY_ADMIN_PASSWORD)%' extra_security_admin_password: '%env(EXTRA_SECURITY_ADMIN_PASSWORD)%'
ccas_mode: '%env(CCAS_MODE)%' ccas_mode: '%env(CCAS_MODE)%'
...@@ -130,7 +131,7 @@ services: ...@@ -130,7 +131,7 @@ services:
class: App\Utils\TAVCotisationUtils class: App\Utils\TAVCotisationUtils
autowire: false autowire: false
public: true public: true
arguments: ['@app.utils.custom_entity_manager', '@security.helper', '@app.utils.operations'] arguments: ['@app.utils.custom_entity_manager', '@security.helper', '@app.utils.operations', '@service_container']
app.utils.payment: app.utils.payment:
class: App\Utils\PaymentUtils class: App\Utils\PaymentUtils
......
...@@ -164,6 +164,7 @@ class AdherentAdmin extends AbstractAdmin ...@@ -164,6 +164,7 @@ class AdherentAdmin extends AbstractAdmin
// params // params
$tav_env = $this->getConfigurationPool()->getContainer()->getParameter('tav_env'); $tav_env = $this->getConfigurationPool()->getContainer()->getParameter('tav_env');
$household_based_allowance = $this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance'); $household_based_allowance = $this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance');
$simplified_household_based_allowance = $this->getConfigurationPool()->getContainer()->getParameter('simplified_household_based_allowance');
$formMapper $formMapper
->tab('General') ->tab('General')
...@@ -178,7 +179,10 @@ class AdherentAdmin extends AbstractAdmin ...@@ -178,7 +179,10 @@ class AdherentAdmin extends AbstractAdmin
'required' => true, 'required' => true,
'with_geoloc' => false, 'with_geoloc' => false,
'with_latlon' => false, 'with_latlon' => false,
'with_subterritory' => $tav_env && $household_based_allowance, 'with_subterritory' =>
$tav_env
&& $household_based_allowance
&& !$simplified_household_based_allowance,
'with_quartier' => $tav_env && $household_based_allowance 'with_quartier' => $tav_env && $household_based_allowance
]) ])
->end() ->end()
...@@ -213,11 +217,44 @@ class AdherentAdmin extends AbstractAdmin ...@@ -213,11 +217,44 @@ class AdherentAdmin extends AbstractAdmin
} }
/** /**
* In TAV env, 2 allowance processes possible: * In TAV env, 3 allowance processes possible:
* - household based (if param set) * - household based (if param set)
* - simplified household based (if both params set)
* - cotisation profile and rate based (default) * - cotisation profile and rate based (default)
*/ */
if ($household_based_allowance) { if ($household_based_allowance) {
if ($simplified_household_based_allowance) {
$formMapper
->tab('General')
->with('Foyer', ['class' => 'col-md-7'])
->add('householdComposition',ChoiceType::class, [
'choices' => [
"Personne seule" => "Personne seule",
"Famille mono-parentale" => "Famille mono-parentale",
"Couple" => "Couple",
"Couple avec enfant(s)" => "Couple avec enfant(s)",
"Colocation" => "Colocation"
],
'label' => "Composition du foyer (pour information)",
'required' => true,
'attr' => [
'autocomplete' => 'off'
],
'placeholder' => "Choix de la composition du foyer",
])
->add('householdCount',IntegerType::class, [
'label' => "Nombre total de personnes que vous souhaitez engager dans l'expérimentation",
'constraints' => [
new GreaterThanOrEqual(['value' => 0]),
],
'required' => true,
'attr' => [
'autocomplete' => 'off'
]
])
->end()
->end();
} else {
$formMapper $formMapper
->tab('General') ->tab('General')
->with('Foyer', ['class' => 'col-md-7']) ->with('Foyer', ['class' => 'col-md-7'])
...@@ -240,7 +277,7 @@ class AdherentAdmin extends AbstractAdmin ...@@ -240,7 +277,7 @@ class AdherentAdmin extends AbstractAdmin
], ],
'required' => true, 'required' => true,
'attr' => [ 'attr' => [
'autocomplete' => false 'autocomplete' => 'off'
] ]
]) ])
->add('dependentChildren', CollectionType::class, [ ->add('dependentChildren', CollectionType::class, [
...@@ -257,6 +294,7 @@ class AdherentAdmin extends AbstractAdmin ...@@ -257,6 +294,7 @@ class AdherentAdmin extends AbstractAdmin
]) ])
->end() ->end()
->end(); ->end();
}
// Add cotisation info // Add cotisation info
$formMapper $formMapper
...@@ -264,7 +302,7 @@ class AdherentAdmin extends AbstractAdmin ...@@ -264,7 +302,7 @@ class AdherentAdmin extends AbstractAdmin
->with('Informations de cotisation', ['class' => 'col-md-5']) ->with('Informations de cotisation', ['class' => 'col-md-5'])
->add('cotisationAmount', NumberType::class, [ ->add('cotisationAmount', NumberType::class, [
'label' => 'Montant de la cotisation (en €)', 'label' => 'Montant de la cotisation (en €)',
'help' => 'Montant minimum : 10€ par foyer + 5€/personne supplémentaire du foyer' 'help' => $simplified_household_based_allowance ? '' : 'Montant minimum : 10€ par foyer + 5€/personne supplémentaire du foyer'
]) ])
->add('allocationAmount', NumberType::class, [ ->add('allocationAmount', NumberType::class, [
'label' => 'Montant d\'allocation prévu en fonction du foyer (en MonA)', 'label' => 'Montant d\'allocation prévu en fonction du foyer (en MonA)',
...@@ -379,6 +417,7 @@ class AdherentAdmin extends AbstractAdmin ...@@ -379,6 +417,7 @@ class AdherentAdmin extends AbstractAdmin
]) ])
->end() ->end()
->end(); ->end();
//Add form part allowing super admin to fix balance //Add form part allowing super admin to fix balance
if($this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance') if($this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance')
&& $this->security->isGranted('ROLE_SUPER_ADMIN')) { && $this->security->isGranted('ROLE_SUPER_ADMIN')) {
...@@ -461,6 +500,7 @@ class AdherentAdmin extends AbstractAdmin ...@@ -461,6 +500,7 @@ class AdherentAdmin extends AbstractAdmin
} }
if ($this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance')) { if ($this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance')) {
if (!$this->getConfigurationPool()->getContainer()->getParameter('simplified_household_based_allowance')) {
// check cotisation amount // check cotisation amount
$adultsCount = $adherent->getHouseholdAdultCount(); $adultsCount = $adherent->getHouseholdAdultCount();
$dependentChildrenCount = count($adherent->getDependentChildren()); $dependentChildrenCount = count($adherent->getDependentChildren());
...@@ -469,6 +509,7 @@ class AdherentAdmin extends AbstractAdmin ...@@ -469,6 +509,7 @@ class AdherentAdmin extends AbstractAdmin
if ($adherent->getCotisationAmount() < $minCotisationAmount) { if ($adherent->getCotisationAmount() < $minCotisationAmount) {
$event->getForm()->get('cotisationAmount')->addError(new FormError('Le montant minimum est de ' . $minCotisationAmount . '€ (selon les données du foyer indiquées)')); $event->getForm()->get('cotisationAmount')->addError(new FormError('Le montant minimum est de ' . $minCotisationAmount . '€ (selon les données du foyer indiquées)'));
} }
}
// try to fix balance if required // try to fix balance if required
if( if(
...@@ -580,7 +621,9 @@ class AdherentAdmin extends AbstractAdmin ...@@ -580,7 +621,9 @@ class AdherentAdmin extends AbstractAdmin
$em->persist($account); $em->persist($account);
} }
if ($this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance')) { if ($this->getConfigurationPool()->getContainer()->getParameter('simplified_household_based_allowance')) {
$this->tavCotisationUtils->calculateAllowanceAccordingToHouseholdSimplified($adherent);
} else if ($this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance')) {
$this->tavCotisationUtils->calculateAllowanceAccordingToHousehold($adherent); $this->tavCotisationUtils->calculateAllowanceAccordingToHousehold($adherent);
} }
...@@ -798,6 +841,7 @@ class AdherentAdmin extends AbstractAdmin ...@@ -798,6 +841,7 @@ class AdherentAdmin extends AbstractAdmin
); );
if( if(
$this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance') $this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance')
&& !$this->getConfigurationPool()->getContainer()->getParameter('simplified_household_based_allowance')
&& ( && (
$this->security->isGranted('ROLE_SUPER_ADMIN') $this->security->isGranted('ROLE_SUPER_ADMIN')
|| $this->security->isGranted('ROLE_ADMIN_SIEGE') || $this->security->isGranted('ROLE_ADMIN_SIEGE')
...@@ -849,7 +893,8 @@ class AdherentAdmin extends AbstractAdmin ...@@ -849,7 +893,8 @@ class AdherentAdmin extends AbstractAdmin
parent::configureRoutes($collection); parent::configureRoutes($collection);
$collection $collection
->remove('delete') ->remove('delete')
->add('withdrawDownToTheCeiling', $this->getRouterIdParameter() . '/withdrawDownToTheCeiling'); ->add('withdrawDownToTheCeiling', $this->getRouterIdParameter() . '/withdrawDownToTheCeiling')
->add('recalculateHouseholdAllocations', 'recalculateHouseholdAllocations');
} }
public function getBatchActions() public function getBatchActions()
...@@ -939,5 +984,19 @@ class AdherentAdmin extends AbstractAdmin ...@@ -939,5 +984,19 @@ class AdherentAdmin extends AbstractAdmin
} }
return $res; return $res;
} }
public function configureActionButtons($action, $object = null)
{
$list = parent::configureActionButtons($action, $object);
$household_based_allowance = $this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance');
$simplified_household_based_allowance = $this->getConfigurationPool()->getContainer()->getParameter('simplified_household_based_allowance');
if ($household_based_allowance || $simplified_household_based_allowance) {
$list['test']['template'] = '@kohinos/tav/block/admin_recalculate_allocations.html.twig';
}
return $list;
}
} }
...@@ -175,7 +175,11 @@ class FluxAdmin extends AbstractAdmin ...@@ -175,7 +175,11 @@ class FluxAdmin extends AbstractAdmin
]) ])
; ;
if($this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance')) { // In household based allowance (but not simplified) add filter on adherent territory
$household_based_allowance = $this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance');
$simplified_household_based_allowance = $this->getConfigurationPool()->getContainer()->getParameter('simplified_household_based_allowance');
if($household_based_allowance && !$simplified_household_based_allowance) {
$datagridMapper->add('territory', CallbackFilter::class, [ $datagridMapper->add('territory', CallbackFilter::class, [
'callback' => [$this, 'getTerritoryFilter'], 'callback' => [$this, 'getTerritoryFilter'],
'field_type' => SChoiceType::class, 'field_type' => SChoiceType::class,
......
...@@ -70,7 +70,12 @@ class OperationAdherentAdmin extends OperationAdmin ...@@ -70,7 +70,12 @@ class OperationAdherentAdmin extends OperationAdmin
'advanced_filter' => false, 'advanced_filter' => false,
'show_filter' => true, 'show_filter' => true,
]); ]);
if($this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance')) {
// In household based allowance (but not simplified) add filter on adherent territory
$household_based_allowance = $this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance');
$simplified_household_based_allowance = $this->getConfigurationPool()->getContainer()->getParameter('simplified_household_based_allowance');
if($household_based_allowance && !$simplified_household_based_allowance) {
$datagridMapper->add('account.adherent.geoloc.subterritory', null, [ $datagridMapper->add('account.adherent.geoloc.subterritory', null, [
'label' => 'Territoire', 'label' => 'Territoire',
'advanced_filter' => false, 'advanced_filter' => false,
......
...@@ -11,6 +11,8 @@ use Symfony\Component\HttpFoundation\Request; ...@@ -11,6 +11,8 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
use Symfony\Component\Routing\Annotation\Route;
use App\Entity\Adherent;
class AdherentAdminController extends CRUDController class AdherentAdminController extends CRUDController
{ {
...@@ -54,4 +56,52 @@ class AdherentAdminController extends CRUDController ...@@ -54,4 +56,52 @@ class AdherentAdminController extends CRUDController
$this->admin->generateUrl('list', ['filter' => $this->admin->getFilterParameters()]) $this->admin->generateUrl('list', ['filter' => $this->admin->getFilterParameters()])
); );
} }
/**
* Recalculate household allocation in case of switching between household allocation methods.
*
* @param Request $request
* @IsGranted({"ROLE_SUPER_ADMIN", "ROLE_ADMIN_SIEGE", "ROLE_TRESORIER"})
* @return Response
*/
public function recalculateHouseholdAllocationsAction(Request $request): Response
{
$qb = $this->em->getRepository(Adherent::class)->createQueryBuilder('a');
if ($this->getParameter('simplified_household_based_allowance')) {
$adherents = $qb->where($qb->expr()->isNotNull("a.householdCount"))
->andWhere($qb->expr()->isNotNull("a.cotisationAmount"))
->getQuery()
->getResult();
;
foreach ($adherents as $adherent) {
$this->tavCotisationUtils->calculateAllowanceAccordingToHouseholdSimplified($adherent);
$this->em->persist($adherent);
}
} else if ($this->getParameter('household_based_allowance')) {
$adherents = $qb->where($qb->expr()->isNotNull("a.householdAdultCount"))
->andWhere($qb->expr()->isNotNull("a.cotisationAmount"))
->getQuery()
->getResult();
;
foreach ($adherents as $adherent) {
$this->tavCotisationUtils->calculateAllowanceAccordingToHousehold($adherent);
$this->em->persist($adherent);
}
}
$this->em->flush();
$this->addFlash(
'sonata_flash_success',
'Allocation recalculées avec succès'
);
return new RedirectResponse(
$this->admin->generateUrl('list', ['filter' => $this->admin->getFilterParameters()])
);
}
} }
...@@ -90,7 +90,7 @@ class FluxController extends AbstractController ...@@ -90,7 +90,7 @@ class FluxController extends AbstractController
SessionInterface $session, SessionInterface $session,
Environment $templating, Environment $templating,
OperationUtils $operationUtils, OperationUtils $operationUtils,
TAVCotisationUtils $tavCotisationsUtils, TAVCotisationUtils $tavCotisationUtils,
TokenGeneratorInterface $tokenGenerator, TokenGeneratorInterface $tokenGenerator,
ValidatorInterface $validator, ValidatorInterface $validator,
CsrfTokenManagerInterface $tokenManager, CsrfTokenManagerInterface $tokenManager,
...@@ -107,7 +107,7 @@ class FluxController extends AbstractController ...@@ -107,7 +107,7 @@ class FluxController extends AbstractController
$this->tokenGenerator = $tokenGenerator; $this->tokenGenerator = $tokenGenerator;
$this->validator = $validator; $this->validator = $validator;
$this->tokenManager = $tokenManager; $this->tokenManager = $tokenManager;
$this->tavCotisationsUtils = $tavCotisationsUtils; $this->tavCotisationUtils = $tavCotisationUtils;
$this->userManager = $userManager; $this->userManager = $userManager;
$this->router = $router; $this->router = $router;
} }
......
...@@ -130,12 +130,19 @@ class UserAdherentController extends FluxController ...@@ -130,12 +130,19 @@ class UserAdherentController extends FluxController
private function paiementCotisTavValidation($flux) { private function paiementCotisTavValidation($flux) {
$destinataire = $flux->getDestinataire(); $destinataire = $flux->getDestinataire();
if($reason = $this->tavCotisationsUtils->preventCotisationDuplication($destinataire)) { if($reason = $this->tavCotisationUtils->preventCotisationDuplication($destinataire)) {
return $reason; return $reason;
} }
// Look for cotisation data depending on active process // Look for cotisation data depending on active process
if (true == $this->getParameter('household_based_allowance')) { if (true == $this->getParameter('simplified_household_based_allowance')) {
$cotisationAmount = $destinataire->getCotisationAmount();
// Use ProfilDeCotisation if set & conditions for simplified_household_based_allowance not met
if ((is_null($cotisationAmount) || is_null($destinataire->getHouseholdCount())) && is_null($destinataire->getProfilDeCotisation())) {
return "Opération impossible : votre profil est incomplet, informations de cotisation manquantes. Veuillez contacter un administrateur.";
}
} else if (true == $this->getParameter('household_based_allowance')) {
$cotisationAmount = $destinataire->getCotisationAmount(); $cotisationAmount = $destinataire->getCotisationAmount();
if (is_null($cotisationAmount) || is_null($destinataire->getHouseholdAdultCount())) { if (is_null($cotisationAmount) || is_null($destinataire->getHouseholdAdultCount())) {
...@@ -189,12 +196,20 @@ class UserAdherentController extends FluxController ...@@ -189,12 +196,20 @@ class UserAdherentController extends FluxController
'type' => Payment::TYPE_PAIEMENT_COTISATION_TAV 'type' => Payment::TYPE_PAIEMENT_COTISATION_TAV
]); ]);
/* For test purposes, comment redirection and uncomment following part to skip payment */ /* For test purposes, comment redirection above and uncomment following part to skip payment */
// $this->em->persist($flux); // $this->em->persist($flux);
// $this->operationUtils->executeOperations($flux); // $this->operationUtils->executeOperations($flux);
// // Apply cotisation rate, create new flux // // Apply cotisation rate, create new flux
// $this->tavCotisationsUtils->applyTauxCotisation($flux); // $destinataire = $flux->getDestinataire();
// $allocationMethod = $this->tavCotisationUtils->getAppropriateAllocationMethod($destinataire);
// // Create new flux for cotisation, depending on process
// if ($this->getParameter('household_based_allowance') || $this->getParameter('simplified_household_based_allowance')) {
// $this->tavCotisationUtils->applyHouseholdAllowance($flux);
// } else {
// $this->tavCotisationUtils->applyTauxCotisation($flux);
// }
// $this->em->flush(); // $this->em->flush();
// $this->addFlash( // $this->addFlash(
......
...@@ -205,7 +205,7 @@ class UserComptoirController extends FluxController ...@@ -205,7 +205,7 @@ class UserComptoirController extends FluxController
$flux = $form->getData(); $flux = $form->getData();
// Look for existing cotisation // Look for existing cotisation
if ($reason = $this->tavCotisationsUtils->preventCotisationDuplication($flux->getDestinataire())) { if ($reason = $this->tavCotisationUtils->preventCotisationDuplication($flux->getDestinataire())) {
$this->addFlash( $this->addFlash(
'error', 'error',
$this->translator->trans($reason) $this->translator->trans($reason)
...@@ -216,12 +216,15 @@ class UserComptoirController extends FluxController ...@@ -216,12 +216,15 @@ class UserComptoirController extends FluxController
$destinataire = $flux->getDestinataire(); $destinataire = $flux->getDestinataire();
if ($this->getParameter('household_based_allowance') == true) { $allocationMethod = $this->tavCotisationUtils->getAppropriateAllocationMethod($destinataire);
/* Process: allowance based on household */
// Some code duplication between household_based_allowance && simplified_household_based_allowance, for better readability
if ($allocationMethod == 'simplified_household_based_allowance') {
/* Process: simplified allowance based on household */
$cotisationAmount = $destinataire->getCotisationAmount(); $cotisationAmount = $destinataire->getCotisationAmount();
// Verifications // Verifications
if (is_null($cotisationAmount) || is_null($destinataire->getHouseholdAdultCount())) { if (is_null($cotisationAmount) || is_null($destinataire->getHouseholdCount()) ) {
$this->addFlash( $this->addFlash(
'error', 'error',
$this->translator->trans("Opération impossible : le profil de l'habitant.e est incomplet, veuillez le compléter dans l'interface d'administration.") $this->translator->trans("Opération impossible : le profil de l'habitant.e est incomplet, veuillez le compléter dans l'interface d'administration.")
...@@ -230,17 +233,32 @@ class UserComptoirController extends FluxController ...@@ -230,17 +233,32 @@ class UserComptoirController extends FluxController
return $this->redirectToRoute('index'); return $this->redirectToRoute('index');
} }
if (is_null($destinataire->getAllocationAmount())) { $flux->setMontant($cotisationAmount);
$this->tavCotisationUtils->calculateAllowanceAccordingToHousehold($destinataire); $this->em->persist($flux);
$this->em->persist($destinataire); $this->operationUtils->executeOperations($flux);
// Create new flux based on difference with cotisation amount
$this->tavCotisationUtils->applyHouseholdAllowance($flux);
} else if ($allocationMethod == 'household_based_allowance') {
/* Process: allowance based on household */
$cotisationAmount = $destinataire->getCotisationAmount();
// Verifications
if (is_null($cotisationAmount) || is_null($destinataire->getHouseholdAdultCount()) ) {
$this->addFlash(
'error',
$this->translator->trans("Opération impossible : le profil de l'habitant.e est incomplet, veuillez le compléter dans l'interface d'administration.")
);
return $this->redirectToRoute('index');
} }
$flux->setMontant($cotisationAmount); $flux->setMontant($cotisationAmount);
$this->em->persist($flux); $this->em->persist($flux);
$this->operationUtils->executeOperations($flux); $this->operationUtils->executeOperations($flux);
// Apply cotisation rate, create new flux // Create new flux based on difference with cotisation amount
$this->tavCotisationsUtils->applyHouseholdAllowance($flux); $this->tavCotisationUtils->applyHouseholdAllowance($flux);
} else { } else {
/* Process: allowance based on cotisation profile with cotisation rate */ /* Process: allowance based on cotisation profile with cotisation rate */
$profile = $destinataire->getProfilDeCotisation(); $profile = $destinataire->getProfilDeCotisation();
...@@ -261,7 +279,7 @@ class UserComptoirController extends FluxController ...@@ -261,7 +279,7 @@ class UserComptoirController extends FluxController
$this->operationUtils->executeOperations($flux); $this->operationUtils->executeOperations($flux);
// Apply cotisation rate, create new flux // Apply cotisation rate, create new flux
$this->tavCotisationsUtils->applyTauxCotisation($flux); $this->tavCotisationUtils->applyTauxCotisation($flux);
} }
$this->em->flush(); $this->em->flush();
......
...@@ -125,11 +125,18 @@ class Adherent extends AccountableObject implements AccountableInterface ...@@ -125,11 +125,18 @@ class Adherent extends AccountableObject implements AccountableInterface
private $householdComposition; private $householdComposition;
/** /**
* @ORM\Column(type="integer", length=255, nullable=true) * @ORM\Column(type="integer", nullable=true)
*/ */
private $householdAdultCount; private $householdAdultCount;
/** /**
* In simplified household based allocation process, don't keep track of adults & children in the household
*
* @ORM\Column(type="integer", nullable=true)
*/
private $householdCount;
/**
* On household based allowance process, define a cotisation amount for each adherent. * On household based allowance process, define a cotisation amount for each adherent.
* *
* @ORM\Column(type="float", nullable=true) * @ORM\Column(type="float", nullable=true)
...@@ -137,7 +144,7 @@ class Adherent extends AccountableObject implements AccountableInterface ...@@ -137,7 +144,7 @@ class Adherent extends AccountableObject implements AccountableInterface
private $cotisationAmount; private $cotisationAmount;
/** /**
* On household based allowance process, the allowance amountis calculated based on household data. * On household based allowance process, the allowance amount is calculated based on household data.
* Calculate and save the allocation amount when the household data is updated. * Calculate and save the allocation amount when the household data is updated.
* *
* @ORM\Column(type="float", nullable=true) * @ORM\Column(type="float", nullable=true)
...@@ -384,6 +391,18 @@ class Adherent extends AccountableObject implements AccountableInterface ...@@ -384,6 +391,18 @@ class Adherent extends AccountableObject implements AccountableInterface
return $this; return $this;
} }
public function getHouseholdCount(): ?int
{
return $this->householdCount;
}
public function setHouseholdCount(?int $householdCount): self
{
$this->householdCount = $householdCount;
return $this;
}
public function getMailRappelCotisation(): ?bool public function getMailRappelCotisation(): ?bool
{ {
return $this->mailRappelCotisation; return $this->mailRappelCotisation;
......
...@@ -24,7 +24,7 @@ class PaymentStatusExtension implements ExtensionInterface ...@@ -24,7 +24,7 @@ class PaymentStatusExtension implements ExtensionInterface
private $serializer; private $serializer;
private $userManager; private $userManager;
private $operationUtils; private $operationUtils;
private $tavCotisationsUtils; private $tavCotisationUtils;
private $container; private $container;
private $paymentUtils; private $paymentUtils;
...@@ -39,7 +39,7 @@ class PaymentStatusExtension implements ExtensionInterface ...@@ -39,7 +39,7 @@ class PaymentStatusExtension implements ExtensionInterface
SerializerInterface $serializer, SerializerInterface $serializer,
UserManagerInterface $userManager, UserManagerInterface $userManager,
OperationUtils $operationUtils, OperationUtils $operationUtils,
TAVCotisationUtils $tavCotisationsUtils, TAVCotisationUtils $tavCotisationUtils,
ContainerInterface $container, ContainerInterface $container,
PaymentUtils $paymentUtils PaymentUtils $paymentUtils
) { ) {
...@@ -48,7 +48,7 @@ class PaymentStatusExtension implements ExtensionInterface ...@@ -48,7 +48,7 @@ class PaymentStatusExtension implements ExtensionInterface
$this->serializer = $serializer; $this->serializer = $serializer;
$this->userManager = $userManager; $this->userManager = $userManager;
$this->operationUtils = $operationUtils; $this->operationUtils = $operationUtils;
$this->tavCotisationsUtils = $tavCotisationsUtils; $this->tavCotisationUtils = $tavCotisationUtils;
$this->container = $container; $this->container = $container;
$this->paymentUtils = $paymentUtils; $this->paymentUtils = $paymentUtils;
} }
......
...@@ -37,7 +37,21 @@ class AchatMonnaieFormType extends FluxFormType ...@@ -37,7 +37,21 @@ class AchatMonnaieFormType extends FluxFormType
if ($this->container->getParameter('tav_env')) { if ($this->container->getParameter('tav_env')) {
$montant = 0; $montant = 0;
if ($this->container->getParameter('household_based_allowance')) { if ($this->container->getParameter('simplified_household_based_allowance')) {
// if no cotisation amount, get amount from profil de cotisation instead if set
// (for transition purposes from other allocation process)
$cosisationMontant = $this->security->getUser()->getAdherent()->getCotisationAmount();
if (null != $cosisationMontant) {
$montant = $cosisationMontant;
} else {
$profilDeCotisation = $this->security->getUser()->getAdherent()->getProfilDeCotisation();
if (null != $profilDeCotisation) {
$montant = $profilDeCotisation->getMontant();
} else {
$montant = false;
}
}
} else if ($this->container->getParameter('household_based_allowance')) {
$cosisationMontant = $this->security->getUser()->getAdherent()->getCotisationAmount(); $cosisationMontant = $this->security->getUser()->getAdherent()->getCotisationAmount();
if (null != $cosisationMontant) { if (null != $cosisationMontant) {
$montant = $cosisationMontant; $montant = $cosisationMontant;
......
...@@ -24,7 +24,14 @@ class EncaisserCotisationAdherentFormType extends VenteEmlcAdherentFormType ...@@ -24,7 +24,14 @@ class EncaisserCotisationAdherentFormType extends VenteEmlcAdherentFormType
foreach ($adherents as $adh) { foreach ($adherents as $adh) {
$montant = null; $montant = null;
if ($this->container->getParameter('household_based_allowance') && !is_null($adh->getCotisationAmount())) { if ($this->container->getParameter('simplified_household_based_allowance')) {
if (!is_null($adh->getCotisationAmount())) {
$montant = $adh->getCotisationAmount();
} else if (!is_null($adh->getProfilDeCotisation())) {
// For transition purposes, if adherent doesn't have a cotisation amount set but has a ProfilDeCotisation, use ProfilDeCotisation amount
$montant = $adh->getProfilDeCotisation()->getMontant();
}
} if ($this->container->getParameter('household_based_allowance') && !is_null($adh->getCotisationAmount())) {
$montant = $adh->getCotisationAmount(); $montant = $adh->getCotisationAmount();
} else if (!$this->container->getParameter('household_based_allowance') && !is_null($adh->getProfilDeCotisation())) { } else if (!$this->container->getParameter('household_based_allowance') && !is_null($adh->getProfilDeCotisation())) {
$montant = $adh->getProfilDeCotisation()->getMontant(); $montant = $adh->getProfilDeCotisation()->getMontant();
......
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20250107110839 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE adherent ADD household_count INT DEFAULT NULL');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE adherent DROP household_count');
}
}
...@@ -27,7 +27,7 @@ class PaymentUtils ...@@ -27,7 +27,7 @@ class PaymentUtils
private $serializer; private $serializer;
private $userManager; private $userManager;
private $operationUtils; private $operationUtils;
private $tavCotisationsUtils; private $tavCotisationUtils;
private $container; private $container;
/** /**
...@@ -38,14 +38,14 @@ class PaymentUtils ...@@ -38,14 +38,14 @@ class PaymentUtils
SerializerInterface $serializer, SerializerInterface $serializer,
UserManagerInterface $userManager, UserManagerInterface $userManager,
OperationUtils $operationUtils, OperationUtils $operationUtils,
TAVCotisationUtils $tavCotisationsUtils, TAVCotisationUtils $tavCotisationUtils,
ContainerInterface $container ContainerInterface $container
) { ) {
$this->em = $em; $this->em = $em;
$this->serializer = $serializer; $this->serializer = $serializer;
$this->userManager = $userManager; $this->userManager = $userManager;
$this->operationUtils = $operationUtils; $this->operationUtils = $operationUtils;
$this->tavCotisationsUtils = $tavCotisationsUtils; $this->tavCotisationUtils = $tavCotisationUtils;
$this->container = $container; $this->container = $container;
} }
...@@ -248,11 +248,13 @@ class PaymentUtils ...@@ -248,11 +248,13 @@ class PaymentUtils
$this->operationUtils->executeOperations($flux); $this->operationUtils->executeOperations($flux);
if (Payment::TYPE_PAIEMENT_COTISATION_TAV == $type || Payment::TYPE_PAIEMENT_RECURRENT_COTISATION_TAV == $type) { if (Payment::TYPE_PAIEMENT_COTISATION_TAV == $type || Payment::TYPE_PAIEMENT_RECURRENT_COTISATION_TAV == $type) {
$allocationMethod = $this->tavCotisationUtils->getAppropriateAllocationMethod($flux->getDestinataire());
// Create new flux for cotisation, depending on process // Create new flux for cotisation, depending on process
if ($this->container->getParameter('household_based_allowance')) { if ($allocationMethod == 'household_based_allowance' || $allocationMethod == 'simplified_household_based_allowance') {
$this->tavCotisationsUtils->applyHouseholdAllowance($flux); $this->tavCotisationUtils->applyHouseholdAllowance($flux);
} else { } else {
$this->tavCotisationsUtils->applyTauxCotisation($flux); $this->tavCotisationUtils->applyTauxCotisation($flux);
} }
} }
} }
......
...@@ -16,21 +16,25 @@ use App\Repository\PaymentRepository; ...@@ -16,21 +16,25 @@ use App\Repository\PaymentRepository;
use App\Utils\CustomEntityManager; use App\Utils\CustomEntityManager;
use Payum\Core\Request\GetHumanStatus; use Payum\Core\Request\GetHumanStatus;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
use Symfony\Component\DependencyInjection\ContainerInterface;
class TAVCotisationUtils class TAVCotisationUtils
{ {
private $em; private $em;
private $security; private $security;
private $operationUtils; private $operationUtils;
private $container;
public function __construct ( public function __construct (
CustomEntityManager $em, CustomEntityManager $em,
Security $security, Security $security,
OperationUtils $operationUtils OperationUtils $operationUtils,
ContainerInterface $container
) { ) {
$this->em = $em; $this->em = $em;
$this->security = $security; $this->security = $security;
$this->operationUtils = $operationUtils; $this->operationUtils = $operationUtils;
$this->container = $container;
} }
/** /**
...@@ -211,6 +215,35 @@ class TAVCotisationUtils ...@@ -211,6 +215,35 @@ class TAVCotisationUtils
} }
/** /**
* Third method to calculate allowance. Based on household as well, but in a simplified manner.
*
* Rules as follow:
* 1 person: 100 emlc
* 2 person: 150 emlc
* 3 person: 180 emlc
* 4+ person: 220 emlc
*/
public function calculateAllowanceAccordingToHouseholdSimplified(&$adherent) {
$householdCount = $adherent->getHouseholdCount();
if (is_null($householdCount) || $householdCount == 0) {
return;
}
if ($householdCount == 1) {
$mlcAllowanceAmount = 100;
} else if ($householdCount == 2) {
$mlcAllowanceAmount = 150;
} else if ($householdCount == 3) {
$mlcAllowanceAmount = 180;
} else {
$mlcAllowanceAmount = 220;
}
$adherent->setAllocationAmount($mlcAllowanceAmount);
}
/**
* Method called to create Flux based on allowance amount (for household based allowance). * Method called to create Flux based on allowance amount (for household based allowance).
* Only create flux if amount paid != allowance amount. * Only create flux if amount paid != allowance amount.
*/ */
...@@ -222,6 +255,17 @@ class TAVCotisationUtils ...@@ -222,6 +255,17 @@ class TAVCotisationUtils
// get the mlc amount the user is supposed to receive // get the mlc amount the user is supposed to receive
$mlcAllowanceAmount = $adherent->getAllocationAmount(); $mlcAllowanceAmount = $adherent->getAllocationAmount();
// if allocation amount is null (as a security but should not occur), calculate here before applying & creating flux
if (is_null($mlcAllowanceAmount)) {
if ($this->container->getParameter('simplified_household_based_allowance')) {
$this->calculateAllowanceAccordingToHouseholdSimplified($adherent);
} else {
$this->calculateAllowanceAccordingToHousehold($adherent);
}
$this->em->persist($adherent);
$mlcAllowanceAmount = $adherent->getAllocationAmount();
}
// get the difference between what the user paid and what he•she's supposed to receive // get the difference between what the user paid and what he•she's supposed to receive
$amountDiff = $mlcAllowanceAmount - $cotisationAmount; $amountDiff = $mlcAllowanceAmount - $cotisationAmount;
...@@ -372,4 +416,30 @@ class TAVCotisationUtils ...@@ -372,4 +416,30 @@ class TAVCotisationUtils
} }
$this->em->flush(); $this->em->flush();
} }
/**
* Check parameters and Adherent data in order to detect the right allocation method to use.
*
* Specific rule: if simplified_household_based_allowance is active BUT adherent's profile is incomplete for this method AND (s)he has a ProfilDeCotisation set, use ProfilDeCotisation
* (allows flowless transition from ProfilDeCotisation to simplified_household_based_allowance)
*
* @param Adherent $adherent
* @return String 'cotisation_profile' | 'household_based_allowance' | 'simplified_household_based_allowance
*/
public function getAppropriateAllocationMethod($adherent) {
if ($this->container->getParameter('simplified_household_based_allowance')) {
if (
(is_null($adherent->getCotisationAmount()) || is_null($adherent->getHouseholdCount()))
&& !is_null($adherent->getProfilDeCotisation())
) {
return 'cotisation_profile';
} else {
return 'simplified_household_based_allowance';
}
} else if ($this->container->getParameter('household_based_allowance')) {
return 'household_based_allowance';
} else {
return 'cotisation_profile';
}
}
} }
<li>
<a class="sonata-action-element" href="{{ admin.generateUrl('recalculateHouseholdAllocations') }}"
title="Nécessaire uniquement à la suite d'un basculement entre deux modes de calcul de l'allocation basés sur le foyer. Le montant d'allocation est en effet recalculé automatiquement à chaque changement de montant sur un profil d'un adhérent.">
<i class="fa fa-calculator"></i> {{ 'Recalculer les allocations en fonction du foyer'|trans() }}
</a>
</li>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment