Commit d10d9f80 by Yvon Kerdoncuff

Merge branch 'develop' into 7923-presta-operation-export-by-caissier

parents f5ea40c7 4c2b3755
......@@ -137,6 +137,12 @@ services:
class: App\Utils\PaymentUtils
autowire: true
app.utils.moyens:
class: App\Utils\MoyensUtils
autowire: true
public: true
arguments: ['@app.utils.custom_entity_manager']
app.twig.main.extension:
class: App\Twig\AppExtension
autowire: false
......
......@@ -334,7 +334,10 @@ class AdherentAdmin extends AbstractAdmin
$minCotisationAmount = $em->getRepository(GlobalParameter::class)
->val(GlobalParameter::SSA_HOUSEHOLD_COTISATION_MINIMUM);
$minCotisationMsg = (null !== $minCotisationAmount) ? "Montant minimum : {$minCotisationAmount}€ par foyer." : '';
$minimumByShare = $em->getRepository(GlobalParameter::class)
->val(GlobalParameter::SSA_HOUSEHOLD_COTIS_MINIMUM_BY_SHARE);
$minGranularity = ('true' === $minimumByShare) ? 'part' : 'foyer';
$minCotisationMsg = (null !== $minCotisationAmount) ? "Montant minimum : {$minCotisationAmount}€ par {$minGranularity}." : '';
// Add cotisation info
$formMapper
......@@ -563,9 +566,27 @@ class AdherentAdmin extends AbstractAdmin
// check cotisation amount above minimum if activated
$minCotisationAmount = $em->getRepository(GlobalParameter::class)
->val(GlobalParameter::SSA_HOUSEHOLD_COTISATION_MINIMUM);
if (null !== $minCotisationAmount && $adherent->getCotisationAmount() < (int) $minCotisationAmount) {
$event->getForm()->get('cotisationAmount')->addError(new FormError('Champ invalide'));
if (null !== $minCotisationAmount) {
// if minimum by share is activated
$minimumByShare = $em->getRepository(GlobalParameter::class)
->val(GlobalParameter::SSA_HOUSEHOLD_COTIS_MINIMUM_BY_SHARE);
if ('true' === $minimumByShare) {
$cotisationBaseAmount = $em->getRepository(GlobalParameter::class)
->val(GlobalParameter::SSA_HOUSEHOLD_BASE_AMOUNT);
$calculatedAllocationAmount = $this->tavCotisationUtils->getCalculatedHouseholdAllowanceValue($adherent);
$sharesNb = round($calculatedAllocationAmount / $cotisationBaseAmount, 2);
$minAmountByShares = ((int) $minCotisationAmount) * $sharesNb;
if ($adherent->getCotisationAmount() < $minAmountByShares) {
$event->getForm()->get('cotisationAmount')->addError(new FormError("Montant invalide : le minimum est de {$minAmountByShares}€"));
}
} else if ($adherent->getCotisationAmount() < (int) $minCotisationAmount) {
$event->getForm()->get('cotisationAmount')->addError(new FormError('Montant invalide'));
}
}
// try to fix balance if required
......
......@@ -290,6 +290,7 @@ class FluxController extends AbstractController
'Date' => 'createdAt',
'Expediteur' => 'flux.expediteur',
'Destinataire' => 'flux.destinataire',
'Operateur' => 'flux.operateur',
'Montant' => 'montant',
'Type parent' => 'flux.parenttype',
'Type' => 'flux.type',
......
......@@ -68,10 +68,14 @@ class GlobalParameter
const SSA_HOUSEHOLD_USE_SHARED_CUSTODY = 'SSA_HOUSEHOLD_USE_SHARED_CUSTODY';
const SSA_HOUSEHOLD_MAX_ALLOCATION_AMOUNT = 'SSA_HOUSEHOLD_MAX_ALLOCATION_AMOUNT';
const SSA_HOUSEHOLD_COTISATION_MINIMUM = 'SSA_HOUSEHOLD_COTISATION_MINIMUM';
const ALTERNATE_AVAILABLE_PAYMENT_TYPES_COMPTOIR = 'ALTERNATE_AVAILABLE_PAYMENT_TYPES_COMPTOIR';
const SSA_HOUSEHOLD_WITH_QUARTIER = 'SSA_HOUSEHOLD_WITH_QUARTIER';
const SSA_HOUSEHOLD_QUARTIER_LIST_VALUES = 'SSA_HOUSEHOLD_QUARTIER_LIST_VALUES';
const SSA_HOUSEHOLD_WITH_SUBTERRITORY = 'SSA_HOUSEHOLD_WITH_SUBTERRITORY';
const SSA_HOUSEHOLD_COTIS_MINIMUM_BY_SHARE = 'SSA_HOUSEHOLD_COTIS_MINIMUM_BY_SHARE';
const GEOLOC_WITH_QUARTIER = 'GEOLOC_WITH_QUARTIER';
const GEOLOC_QUARTIER_LIST_VALUES = 'GEOLOC_QUARTIER_LIST_VALUES';
const GEOLOC_WITH_SUBTERRITORY = 'GEOLOC_WITH_SUBTERRITORY';
const COMPTOIR_PAYMENT_TYPES = 'COMPTOIR_PAYMENT_TYPES';
/**
* @var \Ramsey\Uuid\UuidInterface
......
......@@ -40,35 +40,6 @@ abstract class MoyenEnum
}
/**
* Return available type for Comptoir.
*
* @return array<string>
*/
public static function getAvailableTypesComptoir()
{
return [
self::MOYEN_ESPECE,
self::MOYEN_CHEQUE,
self::MOYEN_AUTRE,
];
}
/**
* Return another set of available types for Comptoir.
* For Comptoirs not accepting checks
*
* @return array<string>
*/
public static function getAlternateAvailableTypesComptoir()
{
return [
self::MOYEN_VIREMENT,
self::MOYEN_ESPECE,
self::MOYEN_AUTRE,
];
}
/**
* Return all available type of moyen.
*
* @return array<string>
......
......@@ -24,11 +24,10 @@ class ComptoirEncaisserDonAdherentFormType extends FluxFormType
throw new \Exception('[FORM COMPTOIR ENCAISSEMENT DON ADHERENT] Opération impossible !');
}
$alternatePaymentTypes = $this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::ALTERNATE_AVAILABLE_PAYMENT_TYPES_COMPTOIR);
$builder
->add('moyen', ChoiceType::class, [
'required' => true,
'choices' => ('true' === $alternatePaymentTypes) ? MoyenEnum::getAlternateAvailableTypesComptoir() : MoyenEnum::getAvailableTypesComptoir(),
'choices' => $this->moyensUtils->getAvailableTypesComptoir(),
'choice_label' => function ($choice) {
return MoyenEnum::getTypeName($choice);
},
......
......@@ -5,6 +5,7 @@ namespace App\Form\Type;
use App\Entity\Flux;
use App\Entity\User;
use App\Enum\MoyenEnum;
use App\Utils\MoyensUtils;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\AbstractType;
......@@ -27,17 +28,20 @@ class FluxFormType extends AbstractType
protected $security;
protected $container;
protected $session;
protected $moyensUtils;
public function __construct(
EntityManagerInterface $em,
Security $security,
ContainerInterface $container,
SessionInterface $session
SessionInterface $session,
MoyensUtils $moyensUtils
) {
$this->em = $em;
$this->security = $security;
$this->container = $container;
$this->session = $session;
$this->moyensUtils = $moyensUtils;
}
public function buildForm(FormBuilderInterface $builder, array $options)
......
......@@ -22,11 +22,10 @@ class VenteEmlcFormType extends FluxFormType
throw new \Exception('[FORM VENTE EMLC] Opération impossible !');
}
$alternatePaymentTypes = $this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::ALTERNATE_AVAILABLE_PAYMENT_TYPES_COMPTOIR);
$builder
->add('moyen', ChoiceType::class, [
'required' => true,
'choices' => ('true' === $alternatePaymentTypes) ? MoyenEnum::getAlternateAvailableTypesComptoir() : MoyenEnum::getAvailableTypesComptoir(),
'choices' => $this->moyensUtils->getAvailableTypesComptoir(),
'choice_label' => function ($choice) {
return MoyenEnum::getTypeName($choice);
},
......
......@@ -11,11 +11,10 @@ class VenteFormType extends TicketFormType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$alternatePaymentTypes = $this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::ALTERNATE_AVAILABLE_PAYMENT_TYPES_COMPTOIR);
$builder
->add('moyen', ChoiceType::class, [
'required' => true,
'choices' => ('true' === $alternatePaymentTypes) ? MoyenEnum::getAlternateAvailableTypesComptoir() : MoyenEnum::getAvailableTypesComptoir(),
'choices' => $this->moyensUtils->getAvailableTypesComptoir(),
'choice_label' => function ($choice) {
return MoyenEnum::getTypeName($choice);
},
......
<?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 Version20250417105302 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("INSERT INTO global_parameter (id, name, description, value, mandatory) VALUES (UUID(), 'SSA_HOUSEHOLD_COTIS_MINIMUM_BY_SHARE', 'Si la valeur est à true et que SSA_HOUSEHOLD_COTISATION_MINIMUM est défini, active un minimum de cotisation par part plutôt que par foyer. Une part est un montant correspondant à la valeur de SSA_HOUSEHOLD_BASE_AMOUNT, et on calcule le nombre de parts dans le montant d\'allocation prévu (avant application éventuelle de SSA_FORCE_ALLOCATION_AMOUNT ou SSA_HOUSEHOLD_MAX_ALLOCATION_AMOUNT). Le minimum est alors SSA_HOUSEHOLD_COTISATION_MINIMUM * nb de parts.', null, '0')");
}
public function down(Schema $schema) : void
{
$this->addSql("DELETE FROM global_parameter where name='SSA_HOUSEHOLD_COTIS_MINIMUM_BY_SHARE'");
// this down() migration is auto-generated, please modify it to your needs
}
}
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use App\Entity\GlobalParameter;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20250502111501 extends AbstractMigration implements ContainerAwareInterface
{
/**
* @var ObjectManager
*/
protected $em;
public function setContainer(ContainerInterface $container = null)
{
$this->em = $container->get('doctrine')->getManager();
}
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
$containerName = trim(file_get_contents('/etc/hostname'));
if (str_contains($containerName, 'casparis20')) {
$defaultValue = 'MOYEN_VIREMENT,MOYEN_ESPECE,MOYEN_AUTRE';
} else {
$defaultValue = 'MOYEN_ESPECE,MOYEN_CHEQUE,MOYEN_AUTRE';
}
$this->addSql("INSERT INTO global_parameter (id, name, description, value, mandatory) VALUES (UUID(), 'COMPTOIR_PAYMENT_TYPES', 'Définit la liste des paiements disponible aux comptoirs. Insérer les valeurs désirées dans l\'ordre séparées par une virgule sans espace. Valeurs possibles : MOYEN_CB, MOYEN_ESPECE, MOYEN_CHEQUE, MOYEN_VIREMENT, MOYEN_HELLOASSO, MOYEN_EMLC, MOYEN_MLC, MOYEN_AUTRE.', '$defaultValue', '0')");
$this->addSql("DELETE FROM global_parameter where name='ALTERNATE_AVAILABLE_PAYMENT_TYPES_COMPTOIR'");
}
public function down(Schema $schema) : void
{
$this->addSql("DELETE FROM global_parameter where name='COMPTOIR_PAYMENT_TYPES'");
$this->addSql("INSERT INTO global_parameter (id, name, description, value, mandatory) VALUES (UUID(), 'ALTERNATE_AVAILABLE_PAYMENT_TYPES_COMPTOIR', 'Active un set de moyens de paiement disponibles alternatif pour les comptoirs. Par défaut : Espèce, Chèque, Autre. Avec ce paramètre activé : Virement, Espèce, Autre.', 'false', '1')");
}
}
<?php
namespace App\Utils;
use App\Entity\GlobalParameter;
use App\Utils\CustomEntityManager;
use App\Enum\MoyenEnum;
class MoyensUtils
{
private $em;
public function __construct(CustomEntityManager $em) {
$this->em = $em;
}
/**
* Return available payment types for Comptoir from configuration param value.
*
* @return array<string>
*/
public function getAvailableTypesComptoir()
{
$paymentTypes = $this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::COMPTOIR_PAYMENT_TYPES);
if (null == $paymentTypes) {
return $this->getDefaultAvailableTypesComptoir();
}
$paymentTypesArr = explode(",", $paymentTypes);
try {
$res = array_map(function ($val) {
return constant("App\\Enum\\MoyenEnum::$val");
}, $paymentTypesArr);
} catch (\Exception $e) {
// Error in parameter definition
$res = $this->getDefaultAvailableTypesComptoir();
}
return $res;
}
public function getDefaultAvailableTypesComptoir() {
return [
MoyenEnum::MOYEN_ESPECE,
MoyenEnum::MOYEN_CHEQUE,
MoyenEnum::MOYEN_AUTRE,
];
}
}
\ No newline at end of file
......@@ -171,8 +171,7 @@ class TAVCotisationUtils
}
/**
* Second method to calculate allowance:
* allowance based on user's household.
* Calculate & return allowance value in household mode.
*
* Rules are as follow:
* - [SSA_HOUSEHOLD_BASE_AMOUNT] emlc for the first person in user's household
......@@ -185,21 +184,12 @@ class TAVCotisationUtils
* - if SSA_HOUSEHOLD_USE_SHARED_CUSTODY is true:
* apply a percentage if the child is in shared custody: 25%, 50% or 75% depending on the shared custody arrangement
*
* @param Adherent $adherent (by ref)
* @param Adherent $adherent
*/
public function calculateAllowanceAccordingToHousehold(&$adherent) {
// TODO base amounts to param in .env, or in global params ?
$forcedAmount = (int) $this->em->getRepository(GlobalParameter::class)
->val(GlobalParameter::SSA_FORCE_ALLOCATION_AMOUNT);
if($forcedAmount > 0) {
$adherent->setAllocationAmount($forcedAmount);
return;
}
public function getCalculatedHouseholdAllowanceValue($adherent) {
$adultsCount = $adherent->getHouseholdAdultCount();
if ($adultsCount == null) {
return;
return null;
}
// base allowance, for the first adult
......@@ -239,10 +229,38 @@ class TAVCotisationUtils
$mlcAllowanceAmount += $childAllowanceAmount;
}
return $mlcAllowanceAmount;
}
/**
* Second method to calculate allowance:
* allowance based on user's household.
*
* See @getCalculatedHouseholdAllowanceValue() for calculations implentation without verifications
*
* @param Adherent $adherent (by ref)
*/
public function calculateAllowanceAccordingToHousehold(&$adherent) {
// If forced amount activated, set value
$forcedAmount = (int) $this->em->getRepository(GlobalParameter::class)
->val(GlobalParameter::SSA_FORCE_ALLOCATION_AMOUNT);
if($forcedAmount > 0) {
$adherent->setAllocationAmount($forcedAmount);
return;
}
// Calculation
$mlcAllowanceAmount = $this->getCalculatedHouseholdAllowanceValue($adherent);
// Null returned in case of missing necessary param: exit
if ($mlcAllowanceAmount === null) {
return;
}
// Apply cap if activated in configuration
$maxAllocationAmount = $this->em->getRepository(GlobalParameter::class)
->val(GlobalParameter::SSA_HOUSEHOLD_MAX_ALLOCATION_AMOUNT);
// Apply cap if activated in configuration
if (null !== $maxAllocationAmount && 0 !== intval($maxAllocationAmount) && $mlcAllowanceAmount > intval($maxAllocationAmount)) {
$mlcAllowanceAmount = intval($maxAllocationAmount);
}
......
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