diff --git a/config/modules.php b/config/modules.php index 15f2ccc..9a03656 100644 --- a/config/modules.php +++ b/config/modules.php @@ -7,6 +7,7 @@ declare(strict_types=1); * Activer/désactiver un module = ajouter/commenter sa ligne. Exposé par GET /api/modules. */ +use App\Module\Absence\AbsenceModule; use App\Module\Core\CoreModule; use App\Module\ProjectManagement\ProjectManagementModule; use App\Module\TimeTracking\TimeTrackingModule; @@ -15,4 +16,5 @@ return [ CoreModule::class, TimeTrackingModule::class, ProjectManagementModule::class, + AbsenceModule::class, ]; diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml index af7da9c..6b872cf 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -48,6 +48,11 @@ doctrine: is_bundle: false dir: '%kernel.project_dir%/src/Module/ProjectManagement/Domain/Entity' prefix: 'App\Module\ProjectManagement\Domain\Entity' + Absence: + type: attribute + is_bundle: false + dir: '%kernel.project_dir%/src/Module/Absence/Domain/Entity' + prefix: 'App\Module\Absence\Domain\Entity' controller_resolver: auto_mapping: false diff --git a/config/services.yaml b/config/services.yaml index 9d4c54d..c722b23 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -57,11 +57,11 @@ services: arguments: $avatarUploadDir: '%avatar_upload_dir%' - App\Controller\Absence\AbsenceJustificationUploadController: + App\Module\Absence\Infrastructure\Controller\AbsenceJustificationUploadController: arguments: $uploadDir: '%absence_justification_upload_dir%' - App\Controller\Absence\AbsenceJustificationDownloadController: + App\Module\Absence\Infrastructure\Controller\AbsenceJustificationDownloadController: arguments: $uploadDir: '%absence_justification_upload_dir%' @@ -93,4 +93,10 @@ services: App\Module\ProjectManagement\Domain\Repository\TaskRecurrenceRepositoryInterface: '@App\Module\ProjectManagement\Infrastructure\Doctrine\DoctrineTaskRecurrenceRepository' + App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface: '@App\Module\Absence\Infrastructure\Doctrine\DoctrineAbsenceRequestRepository' + + App\Module\Absence\Domain\Repository\AbsencePolicyRepositoryInterface: '@App\Module\Absence\Infrastructure\Doctrine\DoctrineAbsencePolicyRepository' + + App\Module\Absence\Domain\Repository\AbsenceBalanceRepositoryInterface: '@App\Module\Absence\Infrastructure\Doctrine\DoctrineAbsenceBalanceRepository' + App\Shared\Domain\Contract\NotifierInterface: '@App\Module\Core\Infrastructure\Notifier' diff --git a/config/sidebar.php b/config/sidebar.php index 1147980..7bee8f3 100644 --- a/config/sidebar.php +++ b/config/sidebar.php @@ -30,7 +30,7 @@ return [ 'icon' => 'mdi:cog-outline', 'roles' => ['ROLE_ADMIN'], 'items' => [ - ['label' => 'sidebar.admin.teamAbsences', 'to' => '/team-absences', 'icon' => 'mdi:calendar-account-outline'], + ['label' => 'sidebar.admin.teamAbsences', 'to' => '/team-absences', 'icon' => 'mdi:calendar-account-outline', 'module' => 'absence'], ['label' => 'sidebar.admin.administration', 'to' => '/admin', 'icon' => 'mdi:cog-outline', 'permission' => 'core.users.view'], ], ], diff --git a/migrations/Version20260620170000.php b/migrations/Version20260620170000.php new file mode 100644 index 0000000..71896e8 --- /dev/null +++ b/migrations/Version20260620170000.php @@ -0,0 +1,81 @@ +addSql('ALTER TABLE absence_balance ADD created_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL'); + $this->addSql('ALTER TABLE absence_balance ADD updated_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL'); + $this->addSql('ALTER TABLE absence_balance ADD created_by INT DEFAULT NULL'); + $this->addSql('ALTER TABLE absence_balance ADD updated_by INT DEFAULT NULL'); + $this->addSql('ALTER TABLE absence_balance ADD CONSTRAINT FK_65723A76DE12AB56 FOREIGN KEY (created_by) REFERENCES "user" (id) ON DELETE SET NULL NOT DEFERRABLE'); + $this->addSql('ALTER TABLE absence_balance ADD CONSTRAINT FK_65723A7616FE72E1 FOREIGN KEY (updated_by) REFERENCES "user" (id) ON DELETE SET NULL NOT DEFERRABLE'); + $this->addSql('CREATE INDEX IDX_65723A76DE12AB56 ON absence_balance (created_by)'); + $this->addSql('CREATE INDEX IDX_65723A7616FE72E1 ON absence_balance (updated_by)'); + $this->addSql("COMMENT ON COLUMN absence_balance.created_at IS 'Creation timestamp (Timestampable, set on prePersist)'"); + $this->addSql("COMMENT ON COLUMN absence_balance.updated_at IS 'Last update timestamp (Timestampable, set on prePersist/preUpdate)'"); + $this->addSql("COMMENT ON COLUMN absence_balance.created_by IS 'User who created the entry (Blamable, FK user.id, SET NULL on delete)'"); + $this->addSql("COMMENT ON COLUMN absence_balance.updated_by IS 'User who last updated the entry (Blamable, FK user.id, SET NULL on delete)'"); + + // absence_policy + $this->addSql('ALTER TABLE absence_policy ADD created_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL'); + $this->addSql('ALTER TABLE absence_policy ADD updated_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL'); + $this->addSql('ALTER TABLE absence_policy ADD created_by INT DEFAULT NULL'); + $this->addSql('ALTER TABLE absence_policy ADD updated_by INT DEFAULT NULL'); + $this->addSql('ALTER TABLE absence_policy ADD CONSTRAINT FK_7A780B65DE12AB56 FOREIGN KEY (created_by) REFERENCES "user" (id) ON DELETE SET NULL NOT DEFERRABLE'); + $this->addSql('ALTER TABLE absence_policy ADD CONSTRAINT FK_7A780B6516FE72E1 FOREIGN KEY (updated_by) REFERENCES "user" (id) ON DELETE SET NULL NOT DEFERRABLE'); + $this->addSql('CREATE INDEX IDX_7A780B65DE12AB56 ON absence_policy (created_by)'); + $this->addSql('CREATE INDEX IDX_7A780B6516FE72E1 ON absence_policy (updated_by)'); + $this->addSql("COMMENT ON COLUMN absence_policy.created_at IS 'Creation timestamp (Timestampable, set on prePersist)'"); + $this->addSql("COMMENT ON COLUMN absence_policy.updated_at IS 'Last update timestamp (Timestampable, set on prePersist/preUpdate)'"); + $this->addSql("COMMENT ON COLUMN absence_policy.created_by IS 'User who created the entry (Blamable, FK user.id, SET NULL on delete)'"); + $this->addSql("COMMENT ON COLUMN absence_policy.updated_by IS 'User who last updated the entry (Blamable, FK user.id, SET NULL on delete)'"); + } + + public function down(Schema $schema): void + { + // absence_balance + $this->addSql('ALTER TABLE absence_balance DROP CONSTRAINT FK_65723A76DE12AB56'); + $this->addSql('ALTER TABLE absence_balance DROP CONSTRAINT FK_65723A7616FE72E1'); + $this->addSql('DROP INDEX IDX_65723A76DE12AB56'); + $this->addSql('DROP INDEX IDX_65723A7616FE72E1'); + $this->addSql('ALTER TABLE absence_balance DROP created_at'); + $this->addSql('ALTER TABLE absence_balance DROP updated_at'); + $this->addSql('ALTER TABLE absence_balance DROP created_by'); + $this->addSql('ALTER TABLE absence_balance DROP updated_by'); + + // absence_policy + $this->addSql('ALTER TABLE absence_policy DROP CONSTRAINT FK_7A780B65DE12AB56'); + $this->addSql('ALTER TABLE absence_policy DROP CONSTRAINT FK_7A780B6516FE72E1'); + $this->addSql('DROP INDEX IDX_7A780B65DE12AB56'); + $this->addSql('DROP INDEX IDX_7A780B6516FE72E1'); + $this->addSql('ALTER TABLE absence_policy DROP created_at'); + $this->addSql('ALTER TABLE absence_policy DROP updated_at'); + $this->addSql('ALTER TABLE absence_policy DROP created_by'); + $this->addSql('ALTER TABLE absence_policy DROP updated_by'); + } +} diff --git a/src/DataFixtures/AppFixtures.php b/src/DataFixtures/AppFixtures.php index 00adb95..7ad5264 100644 --- a/src/DataFixtures/AppFixtures.php +++ b/src/DataFixtures/AppFixtures.php @@ -4,15 +4,15 @@ declare(strict_types=1); namespace App\DataFixtures; -use App\Entity\AbsenceBalance; -use App\Entity\AbsencePolicy; -use App\Entity\AbsenceRequest; use App\Entity\Client; use App\Entity\MailConfiguration; use App\Entity\ZimbraConfiguration; -use App\Enum\AbsenceStatus; -use App\Enum\AbsenceType; use App\Enum\ContractType; +use App\Module\Absence\Domain\Entity\AbsenceBalance; +use App\Module\Absence\Domain\Entity\AbsencePolicy; +use App\Module\Absence\Domain\Entity\AbsenceRequest; +use App\Module\Absence\Domain\Enum\AbsenceStatus; +use App\Module\Absence\Domain\Enum\AbsenceType; use App\Module\Core\Application\Rbac\RbacSeeder; use App\Module\Core\Domain\Entity\User; use App\Module\ProjectManagement\Domain\Entity\Project; diff --git a/src/Mcp/Tool/Serializer.php b/src/Mcp/Tool/Serializer.php index 2003aa6..c4f4dff 100644 --- a/src/Mcp/Tool/Serializer.php +++ b/src/Mcp/Tool/Serializer.php @@ -4,10 +4,10 @@ declare(strict_types=1); namespace App\Mcp\Tool; -use App\Entity\AbsenceBalance; -use App\Entity\AbsencePolicy; -use App\Entity\AbsenceRequest; use App\Entity\Client; +use App\Module\Absence\Domain\Entity\AbsenceBalance; +use App\Module\Absence\Domain\Entity\AbsencePolicy; +use App\Module\Absence\Domain\Entity\AbsenceRequest; use App\Module\Core\Domain\Entity\User; use App\Module\ProjectManagement\Domain\Entity\Project; use App\Module\ProjectManagement\Domain\Entity\Task; diff --git a/src/Module/Absence/AbsenceModule.php b/src/Module/Absence/AbsenceModule.php new file mode 100644 index 0000000..10eac76 --- /dev/null +++ b/src/Module/Absence/AbsenceModule.php @@ -0,0 +1,43 @@ + + */ + public static function permissions(): array + { + return [ + ['code' => 'absence.requests.view', 'label' => 'Voir les demandes d\'absence'], + ['code' => 'absence.requests.manage', 'label' => 'Gérer les demandes d\'absence'], + ['code' => 'absence.policies.manage', 'label' => 'Gérer les règles d\'absence'], + ['code' => 'absence.balances.manage', 'label' => 'Gérer les soldes d\'absence'], + ]; + } +} diff --git a/src/Service/AbsenceBalanceService.php b/src/Module/Absence/Application/Service/AbsenceBalanceService.php similarity index 79% rename from src/Service/AbsenceBalanceService.php rename to src/Module/Absence/Application/Service/AbsenceBalanceService.php index a258b30..0c56363 100644 --- a/src/Service/AbsenceBalanceService.php +++ b/src/Module/Absence/Application/Service/AbsenceBalanceService.php @@ -2,13 +2,14 @@ declare(strict_types=1); -namespace App\Service; +namespace App\Module\Absence\Application\Service; -use App\Entity\AbsenceBalance; -use App\Entity\AbsenceRequest; -use App\Enum\AbsenceType; -use App\Module\Core\Domain\Entity\User; -use App\Repository\AbsenceBalanceRepository; +use App\Module\Absence\Domain\Entity\AbsenceBalance; +use App\Module\Absence\Domain\Entity\AbsenceRequest; +use App\Module\Absence\Domain\Enum\AbsenceType; +use App\Module\Absence\Domain\Repository\AbsenceBalanceRepositoryInterface; +use App\Shared\Domain\Contract\LeaveProfileInterface; +use App\Shared\Domain\Contract\UserInterface; use DateTimeInterface; use Doctrine\ORM\EntityManagerInterface; @@ -21,21 +22,24 @@ final readonly class AbsenceBalanceService { public function __construct( private EntityManagerInterface $entityManager, - private AbsenceBalanceRepository $balanceRepository, + private AbsenceBalanceRepositoryInterface $balanceRepository, ) {} /** * Reference period string for a request: paid leave follows the employee's * reference period (e.g. "2025-2026"), other types are tracked yearly. */ - public function periodFor(User $user, AbsenceType $type, DateTimeInterface $date): string + public function periodFor(UserInterface $user, AbsenceType $type, DateTimeInterface $date): string { if (AbsenceType::PaidLeave !== $type) { return $date->format('Y'); } - $year = (int) $date->format('Y'); - $startMonthDay = $user->getReferencePeriodStart(); // e.g. "06-01" + $year = (int) $date->format('Y'); + // The reference-period start (e.g. "06-01") is an HR profile field, + // accessed through the LeaveProfileInterface contract to keep the + // Absence module decoupled from the concrete Core User entity. + $startMonthDay = $user instanceof LeaveProfileInterface ? $user->getReferencePeriodStart() : '01-01'; $currentMonthDay = $date->format('m-d'); $startYear = $currentMonthDay >= $startMonthDay ? $year : $year - 1; @@ -43,7 +47,7 @@ final readonly class AbsenceBalanceService return sprintf('%d-%d', $startYear, $startYear + 1); } - public function getOrCreateBalance(User $user, AbsenceType $type, string $period): AbsenceBalance + public function getOrCreateBalance(UserInterface $user, AbsenceType $type, string $period): AbsenceBalance { $balance = $this->balanceRepository->findOneForPeriod($user, $type, $period); @@ -85,7 +89,7 @@ final readonly class AbsenceBalanceService return null; } - /** @var User $user */ + /** @var UserInterface $user */ $user = $request->getUser(); $period = $this->periodFor($user, $request->getType(), $request->getStartDate()); $balance = $this->balanceRepository->findOneForPeriod($user, $request->getType(), $period); @@ -128,7 +132,7 @@ final readonly class AbsenceBalanceService private function balanceForRequest(AbsenceRequest $request): AbsenceBalance { - /** @var User $user */ + /** @var UserInterface $user */ $user = $request->getUser(); $type = $request->getType(); $period = $this->periodFor($user, $type, $request->getStartDate()); diff --git a/src/Entity/AbsenceBalance.php b/src/Module/Absence/Domain/Entity/AbsenceBalance.php similarity index 89% rename from src/Entity/AbsenceBalance.php rename to src/Module/Absence/Domain/Entity/AbsenceBalance.php index 9164973..3de6a16 100644 --- a/src/Entity/AbsenceBalance.php +++ b/src/Module/Absence/Domain/Entity/AbsenceBalance.php @@ -2,16 +2,19 @@ declare(strict_types=1); -namespace App\Entity; +namespace App\Module\Absence\Domain\Entity; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Patch; -use App\Enum\AbsenceType; -use App\Repository\AbsenceBalanceRepository; +use App\Module\Absence\Domain\Enum\AbsenceType; +use App\Module\Absence\Infrastructure\ApiPlatform\State\AbsenceBalanceProvider; +use App\Module\Absence\Infrastructure\Doctrine\DoctrineAbsenceBalanceRepository; +use App\Shared\Domain\Contract\BlamableInterface; +use App\Shared\Domain\Contract\TimestampableInterface; use App\Shared\Domain\Contract\UserInterface; -use App\State\AbsenceBalanceProvider; +use App\Shared\Domain\Trait\TimestampableBlamableTrait; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Attribute\Groups; @@ -35,11 +38,13 @@ use Symfony\Component\Serializer\Attribute\Groups; normalizationContext: ['groups' => ['absence_balance:read']], denormalizationContext: ['groups' => ['absence_balance:write']], )] -#[ORM\Entity(repositoryClass: AbsenceBalanceRepository::class)] +#[ORM\Entity(repositoryClass: DoctrineAbsenceBalanceRepository::class)] #[ORM\Table(name: 'absence_balance')] #[ORM\UniqueConstraint(name: 'uniq_absence_balance_user_type_period', columns: ['user_id', 'type', 'period'])] -class AbsenceBalance +class AbsenceBalance implements TimestampableInterface, BlamableInterface { + use TimestampableBlamableTrait; + #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] diff --git a/src/Entity/AbsencePolicy.php b/src/Module/Absence/Domain/Entity/AbsencePolicy.php similarity index 89% rename from src/Entity/AbsencePolicy.php rename to src/Module/Absence/Domain/Entity/AbsencePolicy.php index 00abb17..16612a3 100644 --- a/src/Entity/AbsencePolicy.php +++ b/src/Module/Absence/Domain/Entity/AbsencePolicy.php @@ -2,14 +2,17 @@ declare(strict_types=1); -namespace App\Entity; +namespace App\Module\Absence\Domain\Entity; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Patch; -use App\Enum\AbsenceType; -use App\Repository\AbsencePolicyRepository; +use App\Module\Absence\Domain\Enum\AbsenceType; +use App\Module\Absence\Infrastructure\Doctrine\DoctrineAbsencePolicyRepository; +use App\Shared\Domain\Contract\BlamableInterface; +use App\Shared\Domain\Contract\TimestampableInterface; +use App\Shared\Domain\Trait\TimestampableBlamableTrait; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Attribute\Groups; @@ -31,11 +34,13 @@ use Symfony\Component\Serializer\Attribute\Groups; denormalizationContext: ['groups' => ['absence_policy:write']], order: ['type' => 'ASC'], )] -#[ORM\Entity(repositoryClass: AbsencePolicyRepository::class)] +#[ORM\Entity(repositoryClass: DoctrineAbsencePolicyRepository::class)] #[ORM\Table(name: 'absence_policy')] #[ORM\UniqueConstraint(name: 'uniq_absence_policy_type', columns: ['type'])] -class AbsencePolicy +class AbsencePolicy implements TimestampableInterface, BlamableInterface { + use TimestampableBlamableTrait; + #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] diff --git a/src/Entity/AbsenceRequest.php b/src/Module/Absence/Domain/Entity/AbsenceRequest.php similarity index 92% rename from src/Entity/AbsenceRequest.php rename to src/Module/Absence/Domain/Entity/AbsenceRequest.php index 7daefd8..55ce07a 100644 --- a/src/Entity/AbsenceRequest.php +++ b/src/Module/Absence/Domain/Entity/AbsenceRequest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Entity; +namespace App\Module\Absence\Domain\Entity; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; @@ -10,15 +10,15 @@ use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Post; -use App\Enum\AbsenceStatus; -use App\Enum\AbsenceType; -use App\Enum\HalfDay; -use App\Repository\AbsenceRequestRepository; +use App\Module\Absence\Domain\Enum\AbsenceStatus; +use App\Module\Absence\Domain\Enum\AbsenceType; +use App\Module\Absence\Domain\Enum\HalfDay; +use App\Module\Absence\Infrastructure\ApiPlatform\State\AbsenceCancelProcessor; +use App\Module\Absence\Infrastructure\ApiPlatform\State\AbsenceRequestProcessor; +use App\Module\Absence\Infrastructure\ApiPlatform\State\AbsenceRequestProvider; +use App\Module\Absence\Infrastructure\ApiPlatform\State\AbsenceReviewProcessor; +use App\Module\Absence\Infrastructure\Doctrine\DoctrineAbsenceRequestRepository; use App\Shared\Domain\Contract\UserInterface; -use App\State\AbsenceCancelProcessor; -use App\State\AbsenceRequestProcessor; -use App\State\AbsenceRequestProvider; -use App\State\AbsenceReviewProcessor; use DateTimeImmutable; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; @@ -64,7 +64,7 @@ use Symfony\Component\Validator\Constraints as Assert; denormalizationContext: ['groups' => ['absence_request:write']], order: ['createdAt' => 'DESC'], )] -#[ORM\Entity(repositoryClass: AbsenceRequestRepository::class)] +#[ORM\Entity(repositoryClass: DoctrineAbsenceRequestRepository::class)] #[ORM\Table(name: 'absence_request')] class AbsenceRequest { diff --git a/src/Enum/AbsenceStatus.php b/src/Module/Absence/Domain/Enum/AbsenceStatus.php similarity index 91% rename from src/Enum/AbsenceStatus.php rename to src/Module/Absence/Domain/Enum/AbsenceStatus.php index ce45714..2fc35c8 100644 --- a/src/Enum/AbsenceStatus.php +++ b/src/Module/Absence/Domain/Enum/AbsenceStatus.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Enum; +namespace App\Module\Absence\Domain\Enum; enum AbsenceStatus: string { diff --git a/src/Enum/AbsenceType.php b/src/Module/Absence/Domain/Enum/AbsenceType.php similarity index 96% rename from src/Enum/AbsenceType.php rename to src/Module/Absence/Domain/Enum/AbsenceType.php index 0406dcb..1fafb53 100644 --- a/src/Enum/AbsenceType.php +++ b/src/Module/Absence/Domain/Enum/AbsenceType.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Enum; +namespace App\Module\Absence\Domain\Enum; enum AbsenceType: string { diff --git a/src/Enum/HalfDay.php b/src/Module/Absence/Domain/Enum/HalfDay.php similarity index 87% rename from src/Enum/HalfDay.php rename to src/Module/Absence/Domain/Enum/HalfDay.php index fa868f3..fed94ca 100644 --- a/src/Enum/HalfDay.php +++ b/src/Module/Absence/Domain/Enum/HalfDay.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Enum; +namespace App\Module\Absence\Domain\Enum; enum HalfDay: string { diff --git a/src/Module/Absence/Domain/Repository/AbsenceBalanceRepositoryInterface.php b/src/Module/Absence/Domain/Repository/AbsenceBalanceRepositoryInterface.php new file mode 100644 index 0000000..e2dffd2 --- /dev/null +++ b/src/Module/Absence/Domain/Repository/AbsenceBalanceRepositoryInterface.php @@ -0,0 +1,24 @@ + $criteria + * @param null|array $orderBy + * + * @return AbsenceBalance[] + */ + public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array; + + public function findOneForPeriod(UserInterface $user, AbsenceType $type, string $period): ?AbsenceBalance; +} diff --git a/src/Module/Absence/Domain/Repository/AbsencePolicyRepositoryInterface.php b/src/Module/Absence/Domain/Repository/AbsencePolicyRepositoryInterface.php new file mode 100644 index 0000000..21a1330 --- /dev/null +++ b/src/Module/Absence/Domain/Repository/AbsencePolicyRepositoryInterface.php @@ -0,0 +1,23 @@ + $criteria + * @param null|array $orderBy + * + * @return AbsencePolicy[] + */ + public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array; + + public function findOneByType(AbsenceType $type): ?AbsencePolicy; +} diff --git a/src/Module/Absence/Domain/Repository/AbsenceRequestRepositoryInterface.php b/src/Module/Absence/Domain/Repository/AbsenceRequestRepositoryInterface.php new file mode 100644 index 0000000..5a648a5 --- /dev/null +++ b/src/Module/Absence/Domain/Repository/AbsenceRequestRepositoryInterface.php @@ -0,0 +1,45 @@ +security->getUser(); assert($user instanceof UserInterface); - $repo = $this->entityManager->getRepository(AbsenceBalance::class); $isAdmin = $this->security->isGranted('ROLE_ADMIN'); if (isset($uriVariables['id'])) { - $balance = $repo->find($uriVariables['id']); + $balance = $this->balanceRepository->findById((int) $uriVariables['id']); if (null === $balance) { return null; } @@ -41,7 +42,8 @@ final readonly class AbsenceBalanceProvider implements ProviderInterface return $balance; } - $qb = $repo->createQueryBuilder('b') + $qb = $this->entityManager->getRepository(AbsenceBalance::class) + ->createQueryBuilder('b') ->orderBy('b.type', 'ASC') ; diff --git a/src/State/AbsenceCancelProcessor.php b/src/Module/Absence/Infrastructure/ApiPlatform/State/AbsenceCancelProcessor.php similarity index 92% rename from src/State/AbsenceCancelProcessor.php rename to src/Module/Absence/Infrastructure/ApiPlatform/State/AbsenceCancelProcessor.php index 59b9e0f..c960b23 100644 --- a/src/State/AbsenceCancelProcessor.php +++ b/src/Module/Absence/Infrastructure/ApiPlatform/State/AbsenceCancelProcessor.php @@ -2,13 +2,13 @@ declare(strict_types=1); -namespace App\State; +namespace App\Module\Absence\Infrastructure\ApiPlatform\State; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProcessorInterface; -use App\Entity\AbsenceRequest; -use App\Enum\AbsenceStatus; -use App\Service\AbsenceBalanceService; +use App\Module\Absence\Application\Service\AbsenceBalanceService; +use App\Module\Absence\Domain\Entity\AbsenceRequest; +use App\Module\Absence\Domain\Enum\AbsenceStatus; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; diff --git a/src/State/AbsenceRequestProcessor.php b/src/Module/Absence/Infrastructure/ApiPlatform/State/AbsenceRequestProcessor.php similarity index 83% rename from src/State/AbsenceRequestProcessor.php rename to src/Module/Absence/Infrastructure/ApiPlatform/State/AbsenceRequestProcessor.php index 2e08eb5..5dabdf8 100644 --- a/src/State/AbsenceRequestProcessor.php +++ b/src/Module/Absence/Infrastructure/ApiPlatform/State/AbsenceRequestProcessor.php @@ -2,17 +2,17 @@ declare(strict_types=1); -namespace App\State; +namespace App\Module\Absence\Infrastructure\ApiPlatform\State; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProcessorInterface; -use App\Entity\AbsenceRequest; -use App\Enum\AbsenceStatus; -use App\Enum\AbsenceType; -use App\Repository\AbsencePolicyRepository; -use App\Repository\AbsenceRequestRepository; -use App\Service\AbsenceBalanceService; -use App\Service\AbsenceDayCalculator; +use App\Module\Absence\Application\Service\AbsenceBalanceService; +use App\Module\Absence\Domain\Entity\AbsenceRequest; +use App\Module\Absence\Domain\Enum\AbsenceStatus; +use App\Module\Absence\Domain\Enum\AbsenceType; +use App\Module\Absence\Domain\Repository\AbsencePolicyRepositoryInterface; +use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface; +use App\Module\Absence\Domain\Service\AbsenceDayCalculator; use App\Shared\Domain\Contract\UserInterface; use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; @@ -32,8 +32,8 @@ final readonly class AbsenceRequestProcessor implements ProcessorInterface private EntityManagerInterface $entityManager, private Security $security, private AbsenceDayCalculator $calculator, - private AbsencePolicyRepository $policyRepository, - private AbsenceRequestRepository $requestRepository, + private AbsencePolicyRepositoryInterface $policyRepository, + private AbsenceRequestRepositoryInterface $requestRepository, private AbsenceBalanceService $balanceService, ) {} diff --git a/src/State/AbsenceRequestProvider.php b/src/Module/Absence/Infrastructure/ApiPlatform/State/AbsenceRequestProvider.php similarity index 83% rename from src/State/AbsenceRequestProvider.php rename to src/Module/Absence/Infrastructure/ApiPlatform/State/AbsenceRequestProvider.php index 8287b37..854cc29 100644 --- a/src/State/AbsenceRequestProvider.php +++ b/src/Module/Absence/Infrastructure/ApiPlatform/State/AbsenceRequestProvider.php @@ -2,11 +2,12 @@ declare(strict_types=1); -namespace App\State; +namespace App\Module\Absence\Infrastructure\ApiPlatform\State; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProviderInterface; -use App\Entity\AbsenceRequest; +use App\Module\Absence\Domain\Entity\AbsenceRequest; +use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface; use App\Shared\Domain\Contract\UserInterface; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\SecurityBundle\Security; @@ -18,6 +19,7 @@ final readonly class AbsenceRequestProvider implements ProviderInterface { public function __construct( private EntityManagerInterface $entityManager, + private AbsenceRequestRepositoryInterface $requestRepository, private Security $security, ) {} @@ -26,12 +28,11 @@ final readonly class AbsenceRequestProvider implements ProviderInterface $user = $this->security->getUser(); assert($user instanceof UserInterface); - $repo = $this->entityManager->getRepository(AbsenceRequest::class); $isAdmin = $this->security->isGranted('ROLE_ADMIN'); // Single item: owner or admin only if (isset($uriVariables['id'])) { - $request = $repo->find($uriVariables['id']); + $request = $this->requestRepository->findById((int) $uriVariables['id']); if (null === $request) { return null; } @@ -42,7 +43,8 @@ final readonly class AbsenceRequestProvider implements ProviderInterface return $request; } - $qb = $repo->createQueryBuilder('a') + $qb = $this->entityManager->getRepository(AbsenceRequest::class) + ->createQueryBuilder('a') ->orderBy('a.createdAt', 'DESC') ; diff --git a/src/State/AbsenceReviewProcessor.php b/src/Module/Absence/Infrastructure/ApiPlatform/State/AbsenceReviewProcessor.php similarity index 93% rename from src/State/AbsenceReviewProcessor.php rename to src/Module/Absence/Infrastructure/ApiPlatform/State/AbsenceReviewProcessor.php index 4f40863..01853ae 100644 --- a/src/State/AbsenceReviewProcessor.php +++ b/src/Module/Absence/Infrastructure/ApiPlatform/State/AbsenceReviewProcessor.php @@ -2,13 +2,13 @@ declare(strict_types=1); -namespace App\State; +namespace App\Module\Absence\Infrastructure\ApiPlatform\State; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProcessorInterface; -use App\Entity\AbsenceRequest; -use App\Enum\AbsenceStatus; -use App\Service\AbsenceBalanceService; +use App\Module\Absence\Application\Service\AbsenceBalanceService; +use App\Module\Absence\Domain\Entity\AbsenceRequest; +use App\Module\Absence\Domain\Enum\AbsenceStatus; use App\Shared\Domain\Contract\UserInterface; use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; diff --git a/src/Command/AccrueLeaveCommand.php b/src/Module/Absence/Infrastructure/Command/AccrueLeaveCommand.php similarity index 83% rename from src/Command/AccrueLeaveCommand.php rename to src/Module/Absence/Infrastructure/Command/AccrueLeaveCommand.php index 8fe502f..7257dc8 100644 --- a/src/Command/AccrueLeaveCommand.php +++ b/src/Module/Absence/Infrastructure/Command/AccrueLeaveCommand.php @@ -2,12 +2,13 @@ declare(strict_types=1); -namespace App\Command; +namespace App\Module\Absence\Infrastructure\Command; -use App\Enum\AbsenceType; -use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; -use App\Repository\AbsenceBalanceRepository; -use App\Service\AbsenceBalanceService; +use App\Module\Absence\Application\Service\AbsenceBalanceService; +use App\Module\Absence\Domain\Enum\AbsenceType; +use App\Module\Absence\Domain\Repository\AbsenceBalanceRepositoryInterface; +use App\Module\Core\Domain\Repository\UserRepositoryInterface; +use App\Shared\Domain\Contract\LeaveProfileInterface; use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; use Exception; @@ -37,8 +38,8 @@ use function sprintf; class AccrueLeaveCommand extends Command { public function __construct( - private readonly DoctrineUserRepository $userRepository, - private readonly AbsenceBalanceRepository $balanceRepository, + private readonly UserRepositoryInterface $userRepository, + private readonly AbsenceBalanceRepositoryInterface $balanceRepository, private readonly AbsenceBalanceService $balanceService, private readonly EntityManagerInterface $entityManager, ) { @@ -88,7 +89,14 @@ class AccrueLeaveCommand extends Command $skipped = 0; foreach ($employees as $user) { - $rate = ($user->getAnnualLeaveDays() / 12) * $user->getWorkTimeRatio(); + // RH leave profile fields are read through the contract to keep the + // Absence module decoupled from the concrete Core User entity. + $profile = $user instanceof LeaveProfileInterface ? $user : null; + if (null === $profile) { + continue; + } + + $rate = ($profile->getAnnualLeaveDays() / 12) * $profile->getWorkTimeRatio(); $period = $this->balanceService->periodFor($user, AbsenceType::PaidLeave, $firstDay); $balance = $this->balanceRepository->findOneForPeriod($user, AbsenceType::PaidLeave, $period); @@ -104,7 +112,7 @@ class AccrueLeaveCommand extends Command ? $this->balanceRepository->findOneForPeriod($user, AbsenceType::PaidLeave, $previousPeriod) : null; $balance->setAcquired( - null !== $previousBalance ? $previousBalance->getAcquiring() : $user->getInitialLeaveBalance(), + null !== $previousBalance ? $previousBalance->getAcquiring() : $profile->getInitialLeaveBalance(), ); } @@ -119,7 +127,7 @@ class AccrueLeaveCommand extends Command $balance->setLastAccruedMonth($monthKey); ++$accrued; - $seeded = $isNew && (null !== self::previousPeriod($period) || $user->getInitialLeaveBalance() > 0); + $seeded = $isNew && (null !== self::previousPeriod($period) || $profile->getInitialLeaveBalance() > 0); $rows[] = [ $user->getUsername(), $period, diff --git a/src/Controller/Absence/AbsenceCalendarController.php b/src/Module/Absence/Infrastructure/Controller/AbsenceCalendarController.php similarity index 86% rename from src/Controller/Absence/AbsenceCalendarController.php rename to src/Module/Absence/Infrastructure/Controller/AbsenceCalendarController.php index aec8f07..766c8f9 100644 --- a/src/Controller/Absence/AbsenceCalendarController.php +++ b/src/Module/Absence/Infrastructure/Controller/AbsenceCalendarController.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace App\Controller\Absence; +namespace App\Module\Absence\Infrastructure\Controller; -use App\Repository\AbsenceRequestRepository; +use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface; use DateTimeImmutable; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; @@ -19,7 +19,7 @@ use Symfony\Component\Security\Http\Attribute\IsGranted; class AbsenceCalendarController extends AbstractController { public function __construct( - private readonly AbsenceRequestRepository $requestRepository, + private readonly AbsenceRequestRepositoryInterface $requestRepository, ) {} #[Route('/api/admin/absences/calendar', name: 'absence_calendar', methods: ['GET'], priority: 1)] diff --git a/src/Controller/Absence/AbsenceJustificationDownloadController.php b/src/Module/Absence/Infrastructure/Controller/AbsenceJustificationDownloadController.php similarity index 89% rename from src/Controller/Absence/AbsenceJustificationDownloadController.php rename to src/Module/Absence/Infrastructure/Controller/AbsenceJustificationDownloadController.php index 3a48dd8..05bf4af 100644 --- a/src/Controller/Absence/AbsenceJustificationDownloadController.php +++ b/src/Module/Absence/Infrastructure/Controller/AbsenceJustificationDownloadController.php @@ -2,10 +2,9 @@ declare(strict_types=1); -namespace App\Controller\Absence; +namespace App\Module\Absence\Infrastructure\Controller; -use App\Entity\AbsenceRequest; -use Doctrine\ORM\EntityManagerInterface; +use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\HttpFoundation\BinaryFileResponse; @@ -21,7 +20,7 @@ use Symfony\Component\Security\Http\Attribute\IsGranted; class AbsenceJustificationDownloadController extends AbstractController { public function __construct( - private readonly EntityManagerInterface $entityManager, + private readonly AbsenceRequestRepositoryInterface $requestRepository, private readonly Security $security, private readonly string $uploadDir, ) {} @@ -30,7 +29,7 @@ class AbsenceJustificationDownloadController extends AbstractController #[IsGranted('ROLE_USER')] public function __invoke(int $id): BinaryFileResponse { - $absence = $this->entityManager->getRepository(AbsenceRequest::class)->find($id); + $absence = $this->requestRepository->findById($id); if (null === $absence) { throw new NotFoundHttpException('Absence request not found.'); } diff --git a/src/Controller/Absence/AbsenceJustificationUploadController.php b/src/Module/Absence/Infrastructure/Controller/AbsenceJustificationUploadController.php similarity index 92% rename from src/Controller/Absence/AbsenceJustificationUploadController.php rename to src/Module/Absence/Infrastructure/Controller/AbsenceJustificationUploadController.php index 5cfaa20..3f2afcb 100644 --- a/src/Controller/Absence/AbsenceJustificationUploadController.php +++ b/src/Module/Absence/Infrastructure/Controller/AbsenceJustificationUploadController.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace App\Controller\Absence; +namespace App\Module\Absence\Infrastructure\Controller; -use App\Entity\AbsenceRequest; +use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\SecurityBundle\Security; @@ -34,6 +34,7 @@ class AbsenceJustificationUploadController extends AbstractController public function __construct( private readonly EntityManagerInterface $entityManager, + private readonly AbsenceRequestRepositoryInterface $requestRepository, private readonly Security $security, private readonly string $uploadDir, ) {} @@ -42,7 +43,7 @@ class AbsenceJustificationUploadController extends AbstractController #[IsGranted('ROLE_USER')] public function __invoke(int $id, Request $request): JsonResponse { - $absence = $this->entityManager->getRepository(AbsenceRequest::class)->find($id); + $absence = $this->requestRepository->findById($id); if (null === $absence) { throw new NotFoundHttpException('Absence request not found.'); } diff --git a/src/Controller/Absence/AbsencePreviewController.php b/src/Module/Absence/Infrastructure/Controller/AbsencePreviewController.php similarity index 85% rename from src/Controller/Absence/AbsencePreviewController.php rename to src/Module/Absence/Infrastructure/Controller/AbsencePreviewController.php index 32ec5a8..887fcec 100644 --- a/src/Controller/Absence/AbsencePreviewController.php +++ b/src/Module/Absence/Infrastructure/Controller/AbsencePreviewController.php @@ -2,14 +2,14 @@ declare(strict_types=1); -namespace App\Controller\Absence; +namespace App\Module\Absence\Infrastructure\Controller; -use App\Enum\AbsenceType; -use App\Enum\HalfDay; -use App\Repository\AbsenceBalanceRepository; -use App\Repository\AbsencePolicyRepository; -use App\Service\AbsenceBalanceService; -use App\Service\AbsenceDayCalculator; +use App\Module\Absence\Application\Service\AbsenceBalanceService; +use App\Module\Absence\Domain\Enum\AbsenceType; +use App\Module\Absence\Domain\Enum\HalfDay; +use App\Module\Absence\Domain\Repository\AbsenceBalanceRepositoryInterface; +use App\Module\Absence\Domain\Repository\AbsencePolicyRepositoryInterface; +use App\Module\Absence\Domain\Service\AbsenceDayCalculator; use App\Shared\Domain\Contract\UserInterface; use DateTimeImmutable; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -30,8 +30,8 @@ class AbsencePreviewController extends AbstractController public function __construct( private readonly Security $security, private readonly AbsenceDayCalculator $calculator, - private readonly AbsencePolicyRepository $policyRepository, - private readonly AbsenceBalanceRepository $balanceRepository, + private readonly AbsencePolicyRepositoryInterface $policyRepository, + private readonly AbsenceBalanceRepositoryInterface $balanceRepository, private readonly AbsenceBalanceService $balanceService, ) {} diff --git a/src/Controller/Absence/PublicHolidayController.php b/src/Module/Absence/Infrastructure/Controller/PublicHolidayController.php similarity index 92% rename from src/Controller/Absence/PublicHolidayController.php rename to src/Module/Absence/Infrastructure/Controller/PublicHolidayController.php index 5c308fa..9e0ae37 100644 --- a/src/Controller/Absence/PublicHolidayController.php +++ b/src/Module/Absence/Infrastructure/Controller/PublicHolidayController.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace App\Controller\Absence; +namespace App\Module\Absence\Infrastructure\Controller; -use App\Service\PublicHolidayProvider; +use App\Module\Absence\Domain\Service\PublicHolidayProvider; use DateTimeImmutable; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; diff --git a/src/Repository/AbsenceBalanceRepository.php b/src/Module/Absence/Infrastructure/Doctrine/DoctrineAbsenceBalanceRepository.php similarity index 59% rename from src/Repository/AbsenceBalanceRepository.php rename to src/Module/Absence/Infrastructure/Doctrine/DoctrineAbsenceBalanceRepository.php index 2b16bf0..7a3d7fe 100644 --- a/src/Repository/AbsenceBalanceRepository.php +++ b/src/Module/Absence/Infrastructure/Doctrine/DoctrineAbsenceBalanceRepository.php @@ -2,10 +2,11 @@ declare(strict_types=1); -namespace App\Repository; +namespace App\Module\Absence\Infrastructure\Doctrine; -use App\Entity\AbsenceBalance; -use App\Enum\AbsenceType; +use App\Module\Absence\Domain\Entity\AbsenceBalance; +use App\Module\Absence\Domain\Enum\AbsenceType; +use App\Module\Absence\Domain\Repository\AbsenceBalanceRepositoryInterface; use App\Shared\Domain\Contract\UserInterface; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; @@ -13,13 +14,18 @@ use Doctrine\Persistence\ManagerRegistry; /** * @extends ServiceEntityRepository */ -class AbsenceBalanceRepository extends ServiceEntityRepository +class DoctrineAbsenceBalanceRepository extends ServiceEntityRepository implements AbsenceBalanceRepositoryInterface { public function __construct(ManagerRegistry $registry) { parent::__construct($registry, AbsenceBalance::class); } + public function findById(int $id): ?AbsenceBalance + { + return $this->find($id); + } + public function findOneForPeriod(UserInterface $user, AbsenceType $type, string $period): ?AbsenceBalance { return $this->findOneBy([ diff --git a/src/Repository/AbsencePolicyRepository.php b/src/Module/Absence/Infrastructure/Doctrine/DoctrineAbsencePolicyRepository.php similarity index 51% rename from src/Repository/AbsencePolicyRepository.php rename to src/Module/Absence/Infrastructure/Doctrine/DoctrineAbsencePolicyRepository.php index b1467a7..4f1d64a 100644 --- a/src/Repository/AbsencePolicyRepository.php +++ b/src/Module/Absence/Infrastructure/Doctrine/DoctrineAbsencePolicyRepository.php @@ -2,23 +2,29 @@ declare(strict_types=1); -namespace App\Repository; +namespace App\Module\Absence\Infrastructure\Doctrine; -use App\Entity\AbsencePolicy; -use App\Enum\AbsenceType; +use App\Module\Absence\Domain\Entity\AbsencePolicy; +use App\Module\Absence\Domain\Enum\AbsenceType; +use App\Module\Absence\Domain\Repository\AbsencePolicyRepositoryInterface; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; /** * @extends ServiceEntityRepository */ -class AbsencePolicyRepository extends ServiceEntityRepository +class DoctrineAbsencePolicyRepository extends ServiceEntityRepository implements AbsencePolicyRepositoryInterface { public function __construct(ManagerRegistry $registry) { parent::__construct($registry, AbsencePolicy::class); } + public function findById(int $id): ?AbsencePolicy + { + return $this->find($id); + } + public function findOneByType(AbsenceType $type): ?AbsencePolicy { return $this->findOneBy(['type' => $type]); diff --git a/src/Repository/AbsenceRequestRepository.php b/src/Module/Absence/Infrastructure/Doctrine/DoctrineAbsenceRequestRepository.php similarity index 87% rename from src/Repository/AbsenceRequestRepository.php rename to src/Module/Absence/Infrastructure/Doctrine/DoctrineAbsenceRequestRepository.php index bca61e3..a3bc830 100644 --- a/src/Repository/AbsenceRequestRepository.php +++ b/src/Module/Absence/Infrastructure/Doctrine/DoctrineAbsenceRequestRepository.php @@ -2,11 +2,12 @@ declare(strict_types=1); -namespace App\Repository; +namespace App\Module\Absence\Infrastructure\Doctrine; -use App\Entity\AbsenceRequest; -use App\Enum\AbsenceStatus; -use App\Enum\AbsenceType; +use App\Module\Absence\Domain\Entity\AbsenceRequest; +use App\Module\Absence\Domain\Enum\AbsenceStatus; +use App\Module\Absence\Domain\Enum\AbsenceType; +use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface; use App\Shared\Domain\Contract\UserInterface; use DateTimeInterface; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; @@ -15,13 +16,18 @@ use Doctrine\Persistence\ManagerRegistry; /** * @extends ServiceEntityRepository */ -class AbsenceRequestRepository extends ServiceEntityRepository +class DoctrineAbsenceRequestRepository extends ServiceEntityRepository implements AbsenceRequestRepositoryInterface { public function __construct(ManagerRegistry $registry) { parent::__construct($registry, AbsenceRequest::class); } + public function findById(int $id): ?AbsenceRequest + { + return $this->find($id); + } + /** * Whether the user already has a PENDING or APPROVED absence that overlaps * the given date range. Two ranges overlap when start_a <= end_b and diff --git a/src/Mcp/Tool/Absence/CancelAbsenceRequestTool.php b/src/Module/Absence/Infrastructure/Mcp/Tool/CancelAbsenceRequestTool.php similarity index 83% rename from src/Mcp/Tool/Absence/CancelAbsenceRequestTool.php rename to src/Module/Absence/Infrastructure/Mcp/Tool/CancelAbsenceRequestTool.php index d946bae..5dd3ea3 100644 --- a/src/Mcp/Tool/Absence/CancelAbsenceRequestTool.php +++ b/src/Module/Absence/Infrastructure/Mcp/Tool/CancelAbsenceRequestTool.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace App\Mcp\Tool\Absence; +namespace App\Module\Absence\Infrastructure\Mcp\Tool; -use App\Enum\AbsenceStatus; use App\Mcp\Tool\Serializer; -use App\Repository\AbsenceRequestRepository; -use App\Service\AbsenceBalanceService; +use App\Module\Absence\Application\Service\AbsenceBalanceService; +use App\Module\Absence\Domain\Enum\AbsenceStatus; +use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface; use Doctrine\ORM\EntityManagerInterface; use InvalidArgumentException; use Mcp\Capability\Attribute\McpTool; @@ -21,7 +21,7 @@ class CancelAbsenceRequestTool { public function __construct( private readonly EntityManagerInterface $entityManager, - private readonly AbsenceRequestRepository $requestRepository, + private readonly AbsenceRequestRepositoryInterface $requestRepository, private readonly AbsenceBalanceService $balanceService, private readonly Security $security, ) {} @@ -32,7 +32,7 @@ class CancelAbsenceRequestTool throw new AccessDeniedException('Access denied: ROLE_USER required.'); } - $request = $this->requestRepository->find($id); + $request = $this->requestRepository->findById($id); if (null === $request) { throw new InvalidArgumentException(sprintf('AbsenceRequest with ID %d not found.', $id)); } diff --git a/src/Mcp/Tool/Absence/CreateAbsenceRequestTool.php b/src/Module/Absence/Infrastructure/Mcp/Tool/CreateAbsenceRequestTool.php similarity index 82% rename from src/Mcp/Tool/Absence/CreateAbsenceRequestTool.php rename to src/Module/Absence/Infrastructure/Mcp/Tool/CreateAbsenceRequestTool.php index 5d58d30..97ac0f6 100644 --- a/src/Mcp/Tool/Absence/CreateAbsenceRequestTool.php +++ b/src/Module/Absence/Infrastructure/Mcp/Tool/CreateAbsenceRequestTool.php @@ -2,18 +2,18 @@ declare(strict_types=1); -namespace App\Mcp\Tool\Absence; +namespace App\Module\Absence\Infrastructure\Mcp\Tool; -use App\Entity\AbsenceRequest; -use App\Enum\AbsenceStatus; -use App\Enum\AbsenceType; -use App\Enum\HalfDay; use App\Mcp\Tool\Serializer; -use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; -use App\Repository\AbsencePolicyRepository; -use App\Repository\AbsenceRequestRepository; -use App\Service\AbsenceBalanceService; -use App\Service\AbsenceDayCalculator; +use App\Module\Absence\Application\Service\AbsenceBalanceService; +use App\Module\Absence\Domain\Entity\AbsenceRequest; +use App\Module\Absence\Domain\Enum\AbsenceStatus; +use App\Module\Absence\Domain\Enum\AbsenceType; +use App\Module\Absence\Domain\Enum\HalfDay; +use App\Module\Absence\Domain\Repository\AbsencePolicyRepositoryInterface; +use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface; +use App\Module\Absence\Domain\Service\AbsenceDayCalculator; +use App\Module\Core\Domain\Repository\UserRepositoryInterface; use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; use InvalidArgumentException; @@ -28,9 +28,9 @@ class CreateAbsenceRequestTool { public function __construct( private readonly EntityManagerInterface $entityManager, - private readonly DoctrineUserRepository $userRepository, - private readonly AbsencePolicyRepository $policyRepository, - private readonly AbsenceRequestRepository $requestRepository, + private readonly UserRepositoryInterface $userRepository, + private readonly AbsencePolicyRepositoryInterface $policyRepository, + private readonly AbsenceRequestRepositoryInterface $requestRepository, private readonly AbsenceDayCalculator $calculator, private readonly AbsenceBalanceService $balanceService, private readonly Security $security, @@ -49,7 +49,7 @@ class CreateAbsenceRequestTool throw new AccessDeniedException('Access denied: ROLE_USER required.'); } - $user = $this->userRepository->find($userId) + $user = $this->userRepository->findById($userId) ?? throw new InvalidArgumentException(sprintf('User with ID %d not found.', $userId)); $typeEnum = AbsenceType::tryFrom($type) diff --git a/src/Mcp/Tool/Absence/DeleteAbsenceRequestTool.php b/src/Module/Absence/Infrastructure/Mcp/Tool/DeleteAbsenceRequestTool.php similarity index 81% rename from src/Mcp/Tool/Absence/DeleteAbsenceRequestTool.php rename to src/Module/Absence/Infrastructure/Mcp/Tool/DeleteAbsenceRequestTool.php index 2048ba3..eb917f9 100644 --- a/src/Mcp/Tool/Absence/DeleteAbsenceRequestTool.php +++ b/src/Module/Absence/Infrastructure/Mcp/Tool/DeleteAbsenceRequestTool.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace App\Mcp\Tool\Absence; +namespace App\Module\Absence\Infrastructure\Mcp\Tool; -use App\Repository\AbsenceRequestRepository; +use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface; use Doctrine\ORM\EntityManagerInterface; use InvalidArgumentException; use Mcp\Capability\Attribute\McpTool; @@ -17,7 +17,7 @@ use function sprintf; class DeleteAbsenceRequestTool { public function __construct( - private readonly AbsenceRequestRepository $requestRepository, + private readonly AbsenceRequestRepositoryInterface $requestRepository, private readonly EntityManagerInterface $entityManager, private readonly Security $security, ) {} @@ -28,7 +28,7 @@ class DeleteAbsenceRequestTool throw new AccessDeniedException('Access denied: ROLE_ADMIN required.'); } - $request = $this->requestRepository->find($id); + $request = $this->requestRepository->findById($id); if (null === $request) { throw new InvalidArgumentException(sprintf('AbsenceRequest with ID %d not found.', $id)); } diff --git a/src/Mcp/Tool/Absence/GetAbsenceRequestTool.php b/src/Module/Absence/Infrastructure/Mcp/Tool/GetAbsenceRequestTool.php similarity index 76% rename from src/Mcp/Tool/Absence/GetAbsenceRequestTool.php rename to src/Module/Absence/Infrastructure/Mcp/Tool/GetAbsenceRequestTool.php index eb0d2aa..d7f6b14 100644 --- a/src/Mcp/Tool/Absence/GetAbsenceRequestTool.php +++ b/src/Module/Absence/Infrastructure/Mcp/Tool/GetAbsenceRequestTool.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace App\Mcp\Tool\Absence; +namespace App\Module\Absence\Infrastructure\Mcp\Tool; use App\Mcp\Tool\Serializer; -use App\Repository\AbsenceRequestRepository; +use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface; use InvalidArgumentException; use Mcp\Capability\Attribute\McpTool; use Symfony\Bundle\SecurityBundle\Security; @@ -17,7 +17,7 @@ use function sprintf; class GetAbsenceRequestTool { public function __construct( - private readonly AbsenceRequestRepository $requestRepository, + private readonly AbsenceRequestRepositoryInterface $requestRepository, private readonly Security $security, ) {} @@ -27,7 +27,7 @@ class GetAbsenceRequestTool throw new AccessDeniedException('Access denied: ROLE_USER required.'); } - $request = $this->requestRepository->find($id); + $request = $this->requestRepository->findById($id); if (null === $request) { throw new InvalidArgumentException(sprintf('AbsenceRequest with ID %d not found.', $id)); } diff --git a/src/Mcp/Tool/Absence/ListAbsenceBalancesTool.php b/src/Module/Absence/Infrastructure/Mcp/Tool/ListAbsenceBalancesTool.php similarity index 77% rename from src/Mcp/Tool/Absence/ListAbsenceBalancesTool.php rename to src/Module/Absence/Infrastructure/Mcp/Tool/ListAbsenceBalancesTool.php index 253e0fb..61415cd 100644 --- a/src/Mcp/Tool/Absence/ListAbsenceBalancesTool.php +++ b/src/Module/Absence/Infrastructure/Mcp/Tool/ListAbsenceBalancesTool.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace App\Mcp\Tool\Absence; +namespace App\Module\Absence\Infrastructure\Mcp\Tool; -use App\Enum\AbsenceType; use App\Mcp\Tool\Serializer; -use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; -use App\Repository\AbsenceBalanceRepository; +use App\Module\Absence\Domain\Enum\AbsenceType; +use App\Module\Absence\Domain\Repository\AbsenceBalanceRepositoryInterface; +use App\Module\Core\Domain\Repository\UserRepositoryInterface; use InvalidArgumentException; use Mcp\Capability\Attribute\McpTool; use Symfony\Bundle\SecurityBundle\Security; @@ -19,8 +19,8 @@ use function sprintf; class ListAbsenceBalancesTool { public function __construct( - private readonly AbsenceBalanceRepository $balanceRepository, - private readonly DoctrineUserRepository $userRepository, + private readonly AbsenceBalanceRepositoryInterface $balanceRepository, + private readonly UserRepositoryInterface $userRepository, private readonly Security $security, ) {} @@ -32,7 +32,7 @@ class ListAbsenceBalancesTool $criteria = []; if (null !== $userId) { - $user = $this->userRepository->find($userId); + $user = $this->userRepository->findById($userId); if (null === $user) { throw new InvalidArgumentException(sprintf('User with ID %d not found.', $userId)); } diff --git a/src/Mcp/Tool/Absence/ListAbsencePoliciesTool.php b/src/Module/Absence/Infrastructure/Mcp/Tool/ListAbsencePoliciesTool.php similarity index 81% rename from src/Mcp/Tool/Absence/ListAbsencePoliciesTool.php rename to src/Module/Absence/Infrastructure/Mcp/Tool/ListAbsencePoliciesTool.php index 491aed0..4d2507d 100644 --- a/src/Mcp/Tool/Absence/ListAbsencePoliciesTool.php +++ b/src/Module/Absence/Infrastructure/Mcp/Tool/ListAbsencePoliciesTool.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace App\Mcp\Tool\Absence; +namespace App\Module\Absence\Infrastructure\Mcp\Tool; use App\Mcp\Tool\Serializer; -use App\Repository\AbsencePolicyRepository; +use App\Module\Absence\Domain\Repository\AbsencePolicyRepositoryInterface; use Mcp\Capability\Attribute\McpTool; use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\Security\Core\Exception\AccessDeniedException; @@ -14,7 +14,7 @@ use Symfony\Component\Security\Core\Exception\AccessDeniedException; class ListAbsencePoliciesTool { public function __construct( - private readonly AbsencePolicyRepository $policyRepository, + private readonly AbsencePolicyRepositoryInterface $policyRepository, private readonly Security $security, ) {} diff --git a/src/Mcp/Tool/Absence/ListAbsenceRequestsTool.php b/src/Module/Absence/Infrastructure/Mcp/Tool/ListAbsenceRequestsTool.php similarity index 80% rename from src/Mcp/Tool/Absence/ListAbsenceRequestsTool.php rename to src/Module/Absence/Infrastructure/Mcp/Tool/ListAbsenceRequestsTool.php index 1f09368..af4c701 100644 --- a/src/Mcp/Tool/Absence/ListAbsenceRequestsTool.php +++ b/src/Module/Absence/Infrastructure/Mcp/Tool/ListAbsenceRequestsTool.php @@ -2,13 +2,13 @@ declare(strict_types=1); -namespace App\Mcp\Tool\Absence; +namespace App\Module\Absence\Infrastructure\Mcp\Tool; -use App\Enum\AbsenceStatus; -use App\Enum\AbsenceType; use App\Mcp\Tool\Serializer; -use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; -use App\Repository\AbsenceRequestRepository; +use App\Module\Absence\Domain\Enum\AbsenceStatus; +use App\Module\Absence\Domain\Enum\AbsenceType; +use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface; +use App\Module\Core\Domain\Repository\UserRepositoryInterface; use DateTimeImmutable; use InvalidArgumentException; use Mcp\Capability\Attribute\McpTool; @@ -21,8 +21,8 @@ use function sprintf; class ListAbsenceRequestsTool { public function __construct( - private readonly AbsenceRequestRepository $requestRepository, - private readonly DoctrineUserRepository $userRepository, + private readonly AbsenceRequestRepositoryInterface $requestRepository, + private readonly UserRepositoryInterface $userRepository, private readonly Security $security, ) {} @@ -39,7 +39,7 @@ class ListAbsenceRequestsTool $user = null; if (null !== $userId) { - $user = $this->userRepository->find($userId) + $user = $this->userRepository->findById($userId) ?? throw new InvalidArgumentException(sprintf('User with ID %d not found.', $userId)); } diff --git a/src/Mcp/Tool/Absence/ReviewAbsenceRequestTool.php b/src/Module/Absence/Infrastructure/Mcp/Tool/ReviewAbsenceRequestTool.php similarity index 89% rename from src/Mcp/Tool/Absence/ReviewAbsenceRequestTool.php rename to src/Module/Absence/Infrastructure/Mcp/Tool/ReviewAbsenceRequestTool.php index d81fb0f..1ddd61f 100644 --- a/src/Mcp/Tool/Absence/ReviewAbsenceRequestTool.php +++ b/src/Module/Absence/Infrastructure/Mcp/Tool/ReviewAbsenceRequestTool.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace App\Mcp\Tool\Absence; +namespace App\Module\Absence\Infrastructure\Mcp\Tool; -use App\Enum\AbsenceStatus; use App\Mcp\Tool\Serializer; -use App\Repository\AbsenceRequestRepository; -use App\Service\AbsenceBalanceService; +use App\Module\Absence\Application\Service\AbsenceBalanceService; +use App\Module\Absence\Domain\Enum\AbsenceStatus; +use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface; use App\Shared\Domain\Contract\UserInterface; use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; @@ -24,7 +24,7 @@ class ReviewAbsenceRequestTool { public function __construct( private readonly EntityManagerInterface $entityManager, - private readonly AbsenceRequestRepository $requestRepository, + private readonly AbsenceRequestRepositoryInterface $requestRepository, private readonly AbsenceBalanceService $balanceService, private readonly Security $security, ) {} @@ -39,7 +39,7 @@ class ReviewAbsenceRequestTool throw new InvalidArgumentException('decision must be "approve" or "reject".'); } - $request = $this->requestRepository->find($id); + $request = $this->requestRepository->findById($id); if (null === $request) { throw new InvalidArgumentException(sprintf('AbsenceRequest with ID %d not found.', $id)); } diff --git a/src/Mcp/Tool/Absence/UpdateAbsenceBalanceTool.php b/src/Module/Absence/Infrastructure/Mcp/Tool/UpdateAbsenceBalanceTool.php similarity index 84% rename from src/Mcp/Tool/Absence/UpdateAbsenceBalanceTool.php rename to src/Module/Absence/Infrastructure/Mcp/Tool/UpdateAbsenceBalanceTool.php index 069d764..2c06144 100644 --- a/src/Mcp/Tool/Absence/UpdateAbsenceBalanceTool.php +++ b/src/Module/Absence/Infrastructure/Mcp/Tool/UpdateAbsenceBalanceTool.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace App\Mcp\Tool\Absence; +namespace App\Module\Absence\Infrastructure\Mcp\Tool; use App\Mcp\Tool\Serializer; -use App\Repository\AbsenceBalanceRepository; +use App\Module\Absence\Domain\Repository\AbsenceBalanceRepositoryInterface; use Doctrine\ORM\EntityManagerInterface; use InvalidArgumentException; use Mcp\Capability\Attribute\McpTool; @@ -18,7 +18,7 @@ use function sprintf; class UpdateAbsenceBalanceTool { public function __construct( - private readonly AbsenceBalanceRepository $balanceRepository, + private readonly AbsenceBalanceRepositoryInterface $balanceRepository, private readonly EntityManagerInterface $entityManager, private readonly Security $security, ) {} @@ -33,7 +33,7 @@ class UpdateAbsenceBalanceTool throw new AccessDeniedException('Access denied: ROLE_ADMIN required.'); } - $balance = $this->balanceRepository->find($id); + $balance = $this->balanceRepository->findById($id); if (null === $balance) { throw new InvalidArgumentException(sprintf('AbsenceBalance with ID %d not found.', $id)); } diff --git a/src/Mcp/Tool/Absence/UpdateAbsencePolicyTool.php b/src/Module/Absence/Infrastructure/Mcp/Tool/UpdateAbsencePolicyTool.php similarity index 88% rename from src/Mcp/Tool/Absence/UpdateAbsencePolicyTool.php rename to src/Module/Absence/Infrastructure/Mcp/Tool/UpdateAbsencePolicyTool.php index 7ff6274..0e803fe 100644 --- a/src/Mcp/Tool/Absence/UpdateAbsencePolicyTool.php +++ b/src/Module/Absence/Infrastructure/Mcp/Tool/UpdateAbsencePolicyTool.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace App\Mcp\Tool\Absence; +namespace App\Module\Absence\Infrastructure\Mcp\Tool; use App\Mcp\Tool\Serializer; -use App\Repository\AbsencePolicyRepository; +use App\Module\Absence\Domain\Repository\AbsencePolicyRepositoryInterface; use Doctrine\ORM\EntityManagerInterface; use InvalidArgumentException; use Mcp\Capability\Attribute\McpTool; @@ -18,7 +18,7 @@ use function sprintf; class UpdateAbsencePolicyTool { public function __construct( - private readonly AbsencePolicyRepository $policyRepository, + private readonly AbsencePolicyRepositoryInterface $policyRepository, private readonly EntityManagerInterface $entityManager, private readonly Security $security, ) {} @@ -36,7 +36,7 @@ class UpdateAbsencePolicyTool throw new AccessDeniedException('Access denied: ROLE_ADMIN required.'); } - $policy = $this->policyRepository->find($id); + $policy = $this->policyRepository->findById($id); if (null === $policy) { throw new InvalidArgumentException(sprintf('AbsencePolicy with ID %d not found.', $id)); } diff --git a/src/Module/Core/Domain/Entity/User.php b/src/Module/Core/Domain/Entity/User.php index 8a9dd35..6c35a12 100644 --- a/src/Module/Core/Domain/Entity/User.php +++ b/src/Module/Core/Domain/Entity/User.php @@ -18,6 +18,7 @@ use App\Module\Core\Infrastructure\ApiPlatform\State\UserPasswordHasherProcessor use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; use App\Shared\Domain\Attribute\Auditable; use App\Shared\Domain\Attribute\AuditIgnore; +use App\Shared\Domain\Contract\LeaveProfileInterface; use App\Shared\Domain\Contract\UserInterface as SharedUserInterface; use DateTimeImmutable; use Doctrine\Common\Collections\ArrayCollection; @@ -63,7 +64,7 @@ use Symfony\Component\Serializer\Attribute\Groups; #[Auditable] #[ORM\Entity(repositoryClass: DoctrineUserRepository::class)] #[ORM\Table(name: '`user`')] -class User implements UserInterface, PasswordAuthenticatedUserInterface, SharedUserInterface +class User implements UserInterface, PasswordAuthenticatedUserInterface, SharedUserInterface, LeaveProfileInterface { #[ORM\Id] #[ORM\GeneratedValue] diff --git a/src/Module/Core/Domain/Repository/UserRepositoryInterface.php b/src/Module/Core/Domain/Repository/UserRepositoryInterface.php index 6f45735..4545c08 100644 --- a/src/Module/Core/Domain/Repository/UserRepositoryInterface.php +++ b/src/Module/Core/Domain/Repository/UserRepositoryInterface.php @@ -9,6 +9,8 @@ use DateTimeInterface; interface UserRepositoryInterface { + public function findById(int $id): ?UserInterface; + /** * @return list */ diff --git a/src/Module/Core/Infrastructure/Doctrine/DoctrineUserRepository.php b/src/Module/Core/Infrastructure/Doctrine/DoctrineUserRepository.php index c688df0..c1d9777 100644 --- a/src/Module/Core/Infrastructure/Doctrine/DoctrineUserRepository.php +++ b/src/Module/Core/Infrastructure/Doctrine/DoctrineUserRepository.php @@ -21,6 +21,11 @@ class DoctrineUserRepository extends ServiceEntityRepository implements UserRepo parent::__construct($registry, User::class); } + public function findById(int $id): ?UserInterface + { + return $this->find($id); + } + /** * @return list */ diff --git a/src/Shared/Domain/Contract/LeaveProfileInterface.php b/src/Shared/Domain/Contract/LeaveProfileInterface.php new file mode 100644 index 0000000..b8656b8 --- /dev/null +++ b/src/Shared/Domain/Contract/LeaveProfileInterface.php @@ -0,0 +1,24 @@ +employee->getId(), $data['user']['id']); - $balance = self::getContainer()->get(AbsenceBalanceRepository::class) + $balance = self::getContainer()->get(DoctrineAbsenceBalanceRepository::class) ->findOneForPeriod($this->employee, AbsenceType::PaidLeave, '2026-2027') ; self::assertNotNull($balance); @@ -113,7 +113,7 @@ class AbsenceRequestLifecycleTest extends KernelTestCase self::assertSame('approved', $data['status']); self::assertSame($this->admin->getId(), $data['reviewedBy']['id']); - $balance = self::getContainer()->get(AbsenceBalanceRepository::class) + $balance = self::getContainer()->get(DoctrineAbsenceBalanceRepository::class) ->findOneForPeriod($this->employee, AbsenceType::PaidLeave, '2026-2027') ; self::assertSame(0.0, $balance->getPending()); @@ -128,7 +128,7 @@ class AbsenceRequestLifecycleTest extends KernelTestCase ); // Shrink the entitlement below the 5 requested days. - $balance = self::getContainer()->get(AbsenceBalanceRepository::class) + $balance = self::getContainer()->get(DoctrineAbsenceBalanceRepository::class) ->findOneForPeriod($this->employee, AbsenceType::PaidLeave, '2026-2027') ; $balance->setAcquired(2.0); @@ -158,7 +158,7 @@ class AbsenceRequestLifecycleTest extends KernelTestCase $data = json_decode(($this->cancelTool($this->admin))($created['id']), true); self::assertSame('cancelled', $data['status']); - $balance = self::getContainer()->get(AbsenceBalanceRepository::class) + $balance = self::getContainer()->get(DoctrineAbsenceBalanceRepository::class) ->findOneForPeriod($this->employee, AbsenceType::PaidLeave, '2026-2027') ; self::assertSame(0.0, $balance->getTaken()); @@ -195,7 +195,7 @@ class AbsenceRequestLifecycleTest extends KernelTestCase ); self::assertSame('pending', $data['status']); - $balance = self::getContainer()->get(AbsenceBalanceRepository::class) + $balance = self::getContainer()->get(DoctrineAbsenceBalanceRepository::class) ->findOneForPeriod($this->employee, AbsenceType::Bereavement, '2026') ; self::assertNull($balance, 'Bereavement must not create or touch any balance.'); @@ -217,8 +217,8 @@ class AbsenceRequestLifecycleTest extends KernelTestCase return new CreateAbsenceRequestTool( $c->get(EntityManagerInterface::class), $c->get(DoctrineUserRepository::class), - $c->get(AbsencePolicyRepository::class), - $c->get(AbsenceRequestRepository::class), + $c->get(DoctrineAbsencePolicyRepository::class), + $c->get(DoctrineAbsenceRequestRepository::class), $c->get(AbsenceDayCalculator::class), $c->get(AbsenceBalanceService::class), $this->securityFor($actor), @@ -231,7 +231,7 @@ class AbsenceRequestLifecycleTest extends KernelTestCase return new ReviewAbsenceRequestTool( $c->get(EntityManagerInterface::class), - $c->get(AbsenceRequestRepository::class), + $c->get(DoctrineAbsenceRequestRepository::class), $c->get(AbsenceBalanceService::class), $this->securityFor($actor), ); @@ -243,7 +243,7 @@ class AbsenceRequestLifecycleTest extends KernelTestCase return new CancelAbsenceRequestTool( $c->get(EntityManagerInterface::class), - $c->get(AbsenceRequestRepository::class), + $c->get(DoctrineAbsenceRequestRepository::class), $c->get(AbsenceBalanceService::class), $this->securityFor($actor), ); diff --git a/tests/Unit/Service/AbsenceDayCalculatorTest.php b/tests/Unit/Service/AbsenceDayCalculatorTest.php index 33b96a3..6aa6347 100644 --- a/tests/Unit/Service/AbsenceDayCalculatorTest.php +++ b/tests/Unit/Service/AbsenceDayCalculatorTest.php @@ -4,9 +4,9 @@ declare(strict_types=1); namespace App\Tests\Unit\Service; -use App\Enum\HalfDay; -use App\Service\AbsenceDayCalculator; -use App\Service\PublicHolidayProvider; +use App\Module\Absence\Domain\Enum\HalfDay; +use App\Module\Absence\Domain\Service\AbsenceDayCalculator; +use App\Module\Absence\Domain\Service\PublicHolidayProvider; use DateTimeImmutable; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/Service/PublicHolidayProviderTest.php b/tests/Unit/Service/PublicHolidayProviderTest.php index ff1716c..f59084f 100644 --- a/tests/Unit/Service/PublicHolidayProviderTest.php +++ b/tests/Unit/Service/PublicHolidayProviderTest.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Tests\Unit\Service; -use App\Service\PublicHolidayProvider; +use App\Module\Absence\Domain\Service\PublicHolidayProvider; use DateTimeImmutable; use PHPUnit\Framework\TestCase;