feat(absences) : fondation backend du module de gestion des absences
Module type Payfit (étapes 1+2 de la spec V1) : demande d'absence, validation admin, soldes à jour. - Enums : AbsenceType, AbsenceStatus, HalfDay, ContractType, FamilySituation - Entités : AbsencePolicy, AbsenceBalance, AbsenceRequest + champs RH sur User - Services : PublicHolidayProvider (fériés FR métropole en PHP pur, Computus), AbsenceDayCalculator (décompte jours ouvrés/ouvrables + demi-journées, TDD), AbsenceBalanceService (périodes + pending/taken/recrédit) - API Platform : providers/processors (création, approve/reject/cancel) + RBAC me/admin, contrôleurs preview (dry-run), upload/download justificatif, calendrier - Migrations : une par table + colonnes RH user (DEFAULT puis DROP DEFAULT) - Fixtures : 5 policies par défaut, salariés démo, soldes et demandes - Tests unitaires : PublicHolidayProvider, AbsenceDayCalculator (12 tests) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
42
migrations/Version20260521123520.php
Normal file
42
migrations/Version20260521123520.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Absence management: create the absence_policy table.
|
||||
*/
|
||||
final class Version20260521123520 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Create absence_policy table';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql(<<<'SQL'
|
||||
CREATE TABLE absence_policy (
|
||||
id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
|
||||
type VARCHAR(32) NOT NULL,
|
||||
days_per_year DOUBLE PRECISION DEFAULT NULL,
|
||||
days_per_event DOUBLE PRECISION DEFAULT NULL,
|
||||
justification_required BOOLEAN NOT NULL,
|
||||
notice_days INT NOT NULL,
|
||||
count_working_days_only BOOLEAN NOT NULL,
|
||||
active BOOLEAN NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
)
|
||||
SQL);
|
||||
$this->addSql('CREATE UNIQUE INDEX uniq_absence_policy_type ON absence_policy (type)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP TABLE absence_policy');
|
||||
}
|
||||
}
|
||||
49
migrations/Version20260521123521.php
Normal file
49
migrations/Version20260521123521.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Absence management: create the absence_balance table.
|
||||
*/
|
||||
final class Version20260521123521 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Create absence_balance table';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql(<<<'SQL'
|
||||
CREATE TABLE absence_balance (
|
||||
id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
|
||||
type VARCHAR(32) NOT NULL,
|
||||
period VARCHAR(16) NOT NULL,
|
||||
acquired DOUBLE PRECISION NOT NULL,
|
||||
taken DOUBLE PRECISION NOT NULL,
|
||||
pending DOUBLE PRECISION NOT NULL,
|
||||
user_id INT NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
)
|
||||
SQL);
|
||||
$this->addSql('CREATE INDEX IDX_65723A76A76ED395 ON absence_balance (user_id)');
|
||||
$this->addSql('CREATE UNIQUE INDEX uniq_absence_balance_user_type_period ON absence_balance (user_id, type, period)');
|
||||
$this->addSql(<<<'SQL'
|
||||
ALTER TABLE
|
||||
absence_balance
|
||||
ADD
|
||||
CONSTRAINT FK_65723A76A76ED395 FOREIGN KEY (user_id) REFERENCES "user" (id) ON DELETE CASCADE NOT DEFERRABLE
|
||||
SQL);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE absence_balance DROP CONSTRAINT FK_65723A76A76ED395');
|
||||
$this->addSql('DROP TABLE absence_balance');
|
||||
}
|
||||
}
|
||||
64
migrations/Version20260521123522.php
Normal file
64
migrations/Version20260521123522.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Absence management: create the absence_request table.
|
||||
*/
|
||||
final class Version20260521123522 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Create absence_request table';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql(<<<'SQL'
|
||||
CREATE TABLE absence_request (
|
||||
id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
|
||||
type VARCHAR(32) NOT NULL,
|
||||
start_date DATE NOT NULL,
|
||||
end_date DATE NOT NULL,
|
||||
start_half_day VARCHAR(16) DEFAULT NULL,
|
||||
end_half_day VARCHAR(16) DEFAULT NULL,
|
||||
counted_days DOUBLE PRECISION NOT NULL,
|
||||
reason TEXT DEFAULT NULL,
|
||||
justification_file_name VARCHAR(255) DEFAULT NULL,
|
||||
status VARCHAR(16) NOT NULL,
|
||||
rejection_reason TEXT DEFAULT NULL,
|
||||
created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
|
||||
reviewed_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL,
|
||||
user_id INT NOT NULL,
|
||||
reviewed_by_id INT DEFAULT NULL,
|
||||
PRIMARY KEY (id)
|
||||
)
|
||||
SQL);
|
||||
$this->addSql('CREATE INDEX IDX_F211AA17A76ED395 ON absence_request (user_id)');
|
||||
$this->addSql('CREATE INDEX IDX_F211AA17FC6B21F1 ON absence_request (reviewed_by_id)');
|
||||
$this->addSql(<<<'SQL'
|
||||
ALTER TABLE
|
||||
absence_request
|
||||
ADD
|
||||
CONSTRAINT FK_F211AA17A76ED395 FOREIGN KEY (user_id) REFERENCES "user" (id) ON DELETE CASCADE NOT DEFERRABLE
|
||||
SQL);
|
||||
$this->addSql(<<<'SQL'
|
||||
ALTER TABLE
|
||||
absence_request
|
||||
ADD
|
||||
CONSTRAINT FK_F211AA17FC6B21F1 FOREIGN KEY (reviewed_by_id) REFERENCES "user" (id) ON DELETE SET NULL NOT DEFERRABLE
|
||||
SQL);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE absence_request DROP CONSTRAINT FK_F211AA17A76ED395');
|
||||
$this->addSql('ALTER TABLE absence_request DROP CONSTRAINT FK_F211AA17FC6B21F1');
|
||||
$this->addSql('DROP TABLE absence_request');
|
||||
}
|
||||
}
|
||||
59
migrations/Version20260521123523.php
Normal file
59
migrations/Version20260521123523.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Absence management: add HR fields to the user table.
|
||||
*
|
||||
* Columns are created with DEFAULTs so the migration applies cleanly on an
|
||||
* already-populated user table (production).
|
||||
*/
|
||||
final class Version20260521123523 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add HR / absence fields to user';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE "user" ADD is_employee BOOLEAN NOT NULL DEFAULT false');
|
||||
$this->addSql('ALTER TABLE "user" ADD hire_date DATE DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE "user" ADD end_date DATE DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE "user" ADD contract_type VARCHAR(16) DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE "user" ADD work_time_ratio DOUBLE PRECISION NOT NULL DEFAULT 1.0');
|
||||
$this->addSql('ALTER TABLE "user" ADD annual_leave_days DOUBLE PRECISION NOT NULL DEFAULT 25.0');
|
||||
$this->addSql("ALTER TABLE \"user\" ADD reference_period_start VARCHAR(5) NOT NULL DEFAULT '06-01'");
|
||||
$this->addSql('ALTER TABLE "user" ADD initial_leave_balance DOUBLE PRECISION NOT NULL DEFAULT 0');
|
||||
$this->addSql('ALTER TABLE "user" ADD family_situation VARCHAR(16) DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE "user" ADD nb_children INT NOT NULL DEFAULT 0');
|
||||
|
||||
// Defaults were only needed to backfill existing rows; the ORM mapping
|
||||
// carries no DB default, so drop them to keep the schema in sync.
|
||||
$this->addSql('ALTER TABLE "user" ALTER is_employee DROP DEFAULT');
|
||||
$this->addSql('ALTER TABLE "user" ALTER work_time_ratio DROP DEFAULT');
|
||||
$this->addSql('ALTER TABLE "user" ALTER annual_leave_days DROP DEFAULT');
|
||||
$this->addSql('ALTER TABLE "user" ALTER reference_period_start DROP DEFAULT');
|
||||
$this->addSql('ALTER TABLE "user" ALTER initial_leave_balance DROP DEFAULT');
|
||||
$this->addSql('ALTER TABLE "user" ALTER nb_children DROP DEFAULT');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE "user" DROP is_employee');
|
||||
$this->addSql('ALTER TABLE "user" DROP hire_date');
|
||||
$this->addSql('ALTER TABLE "user" DROP end_date');
|
||||
$this->addSql('ALTER TABLE "user" DROP contract_type');
|
||||
$this->addSql('ALTER TABLE "user" DROP work_time_ratio');
|
||||
$this->addSql('ALTER TABLE "user" DROP annual_leave_days');
|
||||
$this->addSql('ALTER TABLE "user" DROP reference_period_start');
|
||||
$this->addSql('ALTER TABLE "user" DROP initial_leave_balance');
|
||||
$this->addSql('ALTER TABLE "user" DROP family_situation');
|
||||
$this->addSql('ALTER TABLE "user" DROP nb_children');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user