Commit c51b7ec4 by Damien Moulard

add entity & command to import theoritical cotisation calculation rules

parent ae3f3033
<?php
declare(strict_types=1);
namespace App\Command;
use App\Entity\ExternalDataTheoreticalCotisationRule;
use App\Utils\CustomEntityManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Question\ConfirmationQuestion;
/**
* This command is used to import theoritical cotisation rules data from a CSV file.
* CSV file is formated as follow, with the first row as header:
* allocation_amount;income_min;income_max;coef;intercept;fixed_value
*/
class ImportTheoriticalCotisationRules extends Command
{
protected static $defaultName = 'kohinos:ssa:import-theoritical-cotisation-rules';
protected $em;
protected $io;
protected $param;
public function __construct(CustomEntityManager $em) {
$this->em = $em;
parent::__construct();
}
protected function configure()
{
$this
->setDescription('SSA : importer via CSV les données utiles au calcul d\'un montant théorique de cotisation des adhérents.')
->addArgument('filepath', InputArgument::REQUIRED, 'Chemin du fichier csv contenant les données.')
;
}
/**
* @param InputInterface $input
* @param OutputInterface $output
*
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->io = new SymfonyStyle($input, $output);
$this->io->title('START - importing theoritical cotisation rules');
$csvFilePath = $input->getArgument('filepath');
// Check if data already exist
if ($this->em->getRepository(ExternalDataTheoreticalCotisationRule::class)->findAll()) {
$helper = $this->getHelper('question');
$question = new ConfirmationQuestion('Data already exists, it will be fully removed and replaced by file content. Continue? (y/N) ', false);
if (!$helper->ask($input, $output, $question)) {
return 0;
}
// Delete all records and reimport
$this->em->getRepository(ExternalDataTheoreticalCotisationRule::class)->removeAll();
}
if (($handle = fopen($csvFilePath, "r")) !== FALSE) {
while (($row = fgetcsv($handle, 1000, ";")) !== FALSE) {
if ($row[0] === 'allocation_amount') {
// headers row
continue;
}
$data = new ExternalDataTheoreticalCotisationRule();
$data->setAllocationAmount(intval($row[0]));
if ($row[1] !== "") {
$data->setIncomeMin(floatval(str_replace(',', '.', $row[1])));
}
if ($row[2] !== "") {
$data->setIncomeMax(floatval(str_replace(',', '.', $row[2])));
}
if ($row[3] !== "") {
$data->setCoef(floatval(str_replace(',', '.', $row[3])));
}
if ($row[4] !== "") {
$data->setIntercept(floatval(str_replace(',', '.', $row[4])));
}
if ($row[5] !== "") {
$data->setFixedValue(floatval(str_replace(',', '.', $row[5])));
}
$this->em->persist($data);
}
$this->em->flush();
fclose($handle);
}
$this->io->success('Data succesfully imported');
$memoryUsage = memory_get_usage(true) / 1024 / 1024;
$this->io->text("Batch finished with memory: ${memoryUsage}M");
return 0;
}
}
<?php
namespace App\Entity;
use App\Repository\ExternalDataTheoreticalCotisationRuleRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=ExternalDataTheoreticalCotisationRuleRepository::class)
*
* This class stores data used to calculate the theoritical cotisation amount of a Adherent.
* For each allocation bracket (allocationAmount), and for each income bracket (incomeMin < x <= incomeMax),
* cotisation is calculated as such : f(x) = coef * x + intercept ;
* with x as the Adherent's monthly income.
*
* This data is used for visualisation purposes in an external Metabase instance.
*/
class ExternalDataTheoreticalCotisationRule
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="integer")
*/
private $allocationAmount;
/**
* @ORM\Column(type="decimal", precision=8, scale=2, nullable=true)
*/
private $incomeMin;
/**
* @ORM\Column(type="decimal", precision=8, scale=2, nullable=true)
*/
private $incomeMax;
/**
* @ORM\Column(type="decimal", precision=18, scale=16, nullable=true)
*/
private $coef;
/**
* @ORM\Column(type="decimal", precision=18, scale=15, nullable=true)
*/
private $intercept;
/**
* @ORM\Column(type="decimal", precision=8, scale=2, nullable=true)
*/
private $fixedValue;
public function getId(): ?int
{
return $this->id;
}
public function getAllocationAmount(): ?int
{
return $this->allocationAmount;
}
public function setAllocationAmount(int $allocationAmount): self
{
$this->allocationAmount = $allocationAmount;
return $this;
}
public function getIncomeMin(): ?float
{
return $this->incomeMin;
}
public function setIncomeMin(?float $incomeMin): self
{
$this->incomeMin = $incomeMin;
return $this;
}
public function getIncomeMax(): ?float
{
return $this->incomeMax;
}
public function setIncomeMax(?float $incomeMax): self
{
$this->incomeMax = $incomeMax;
return $this;
}
public function getCoef(): ?float
{
return $this->coef;
}
public function setCoef(float $coef): self
{
$this->coef = $coef;
return $this;
}
public function getIntercept(): ?float
{
return $this->intercept;
}
public function setIntercept(float $intercept): self
{
$this->intercept = $intercept;
return $this;
}
public function getFixedValue(): ?float
{
return $this->fixedValue;
}
public function setFixedValue(?float $fixedValue): self
{
$this->fixedValue = $fixedValue;
return $this;
}
}
<?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 Version20251105100522 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('CREATE TABLE external_data_theoretical_cotisation_rule (id INT AUTO_INCREMENT NOT NULL, allocation_amount INT NOT NULL, income_min NUMERIC(8, 2) DEFAULT NULL, income_max NUMERIC(8, 2) DEFAULT NULL, coef NUMERIC(18, 16) DEFAULT NULL, intercept NUMERIC(18, 15) DEFAULT NULL, fixed_value NUMERIC(8, 2) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_general_ci` ENGINE = InnoDB');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP TABLE external_data_theoretical_cotisation_rule');
}
}
<?php
namespace App\Repository;
use App\Entity\ExternalDataTheoreticalCotisationRule;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\ORMException;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<ExternalDataTheoreticalCotisationRule>
*
* @method ExternalDataTheoreticalCotisationRule|null find($id, $lockMode = null, $lockVersion = null)
* @method ExternalDataTheoreticalCotisationRule|null findOneBy(array $criteria, array $orderBy = null)
* @method ExternalDataTheoreticalCotisationRule[] findAll()
* @method ExternalDataTheoreticalCotisationRule[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
* @method null removeAll()
*/
class ExternalDataTheoreticalCotisationRuleRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, ExternalDataTheoreticalCotisationRule::class);
}
/**
* @throws ORMException
* @throws OptimisticLockException
*/
public function add(ExternalDataTheoreticalCotisationRule $entity, bool $flush = true): void
{
$this->_em->persist($entity);
if ($flush) {
$this->_em->flush();
}
}
/**
* @throws ORMException
* @throws OptimisticLockException
*/
public function remove(ExternalDataTheoreticalCotisationRule $entity, bool $flush = true): void
{
$this->_em->remove($entity);
if ($flush) {
$this->_em->flush();
}
}
/**
* Remove all instances of ExternalDataTheoreticalCotisationRule
*/
public function removeAll() {
return $this->createQueryBuilder('e')
->delete()
->getQuery()
->execute()
;
}
// /**
// * @return ExternalDataTheoreticalCotisationRule[] Returns an array of ExternalDataTheoreticalCotisationRule objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('e')
->andWhere('e.exampleField = :val')
->setParameter('val', $value)
->orderBy('e.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/
/*
public function findOneBySomeField($value): ?ExternalDataTheoreticalCotisationRule
{
return $this->createQueryBuilder('e')
->andWhere('e.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
}
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