diff --git a/backend/src/ApiResource/Demande.php b/backend/src/ApiResource/Demande.php index 6acbf43..9c36b10 100644 --- a/backend/src/ApiResource/Demande.php +++ b/backend/src/ApiResource/Demande.php @@ -12,8 +12,8 @@ namespace App\ApiResource; -use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; use ApiPlatform\Doctrine\Orm\State\Options; use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiProperty; @@ -23,6 +23,7 @@ use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Post; use ApiPlatform\OpenApi\Model\Operation; +use App\Filter\CampagneNonArchiveeFilter; use App\Filter\DemandeDisciplineSportiveFilter; use App\Filter\DemandeFormatFilter; use App\Filter\DerniereInscriptionSearchFilter; @@ -39,43 +40,43 @@ use Symfony\Component\Validator\Constraints as Assert; #[ApiResource( - operations : [ + operations: [ new Get( - uriTemplate : self::ITEM_URI, + uriTemplate: self::ITEM_URI, uriVariables: ['id'], - security : "is_granted('" . self::VOIR_DEMANDE . "', object)" + security: "is_granted('" . self::VOIR_DEMANDE . "', object)" ), new GetCollection( uriTemplate: self::COLLECTION_URI, - forceEager : false + forceEager: false ), new GetCollection( - uriTemplate : self::COLLECTION_UTILISATEUR_URI, + uriTemplate: self::COLLECTION_UTILISATEUR_URI, uriVariables: ['uid'], - security : "is_granted('ROLE_GESTIONNAIRE') or request.get('uid') == user.getUid()", - forceEager : false, - provider : DemandesUtilisateurProvider::class, + security: "is_granted('ROLE_GESTIONNAIRE') or request.get('uid') == user.getUid()", + forceEager: false, + provider: DemandesUtilisateurProvider::class, ), new Post( - uriTemplate : self::COLLECTION_URI, - denormalizationContext : ['groups' => [self::GROUP_IN]], + uriTemplate: self::COLLECTION_URI, + denormalizationContext: ['groups' => [self::GROUP_IN]], securityPostDenormalize: "is_granted('ROLE_GESTIONNAIRE') or object.demandeur.uid == user.getUid()", - read : false, - processor : PostDemandeProcessor::class, + read: false, + processor: PostDemandeProcessor::class, ), new Patch( - uriTemplate : self::ITEM_URI, - uriVariables : ['id'], - denormalizationContext : ['groups' => [self::GROUP_CHANGEMENT_ETAT]], + uriTemplate: self::ITEM_URI, + uriVariables: ['id'], + denormalizationContext: ['groups' => [self::GROUP_CHANGEMENT_ETAT]], securityPostDenormalize: "is_granted('" . self::MAJ_DEMANDE . "', [previous_object, object])", - processor : PatchDemandeProcessor::class + processor: PatchDemandeProcessor::class ), ], - normalizationContext : ['groups' => [self::GROUP_OUT]], + normalizationContext: ['groups' => [self::GROUP_OUT]], denormalizationContext: ['groups' => [self::GROUP_IN]], - openapi : new Operation(tags: ['Demandes']), - provider : DemandeProvider::class, - stateOptions : new Options(entityClass: \App\Entity\Demande::class), + openapi: new Operation(tags: ['Demandes']), + provider: DemandeProvider::class, + stateOptions: new Options(entityClass: \App\Entity\Demande::class), )] #[ApiFilter(SearchFilter::class, properties: [ 'demandeur.nom' => 'ipartial', @@ -118,6 +119,7 @@ #[ApiFilter(DemandeDisciplineSportiveFilter::class)] #[ApiFilter(OrderFilter::class, properties: ['demandeur.nom', 'dateDepot'])] #[ApiFilter(DemandeFormatFilter::class)] +#[ApiFilter(CampagneNonArchiveeFilter::class)] #[DemandeUniqueParCampagneConstraint] #[DemandeWorkflowConstraint] class Demande diff --git a/backend/src/ApiResource/TauxHoraire.php b/backend/src/ApiResource/TauxHoraire.php index 0a0e7bd..3fa194b 100644 --- a/backend/src/ApiResource/TauxHoraire.php +++ b/backend/src/ApiResource/TauxHoraire.php @@ -13,13 +13,18 @@ namespace App\ApiResource; use ApiPlatform\Doctrine\Orm\State\Options; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Post; use ApiPlatform\OpenApi\Model\Operation; +use App\Filter\TauxHoraireDateFilter; +use App\State\TauxHoraire\TauxHoraireCollectionProvider; use App\State\TauxHoraire\TauxHoraireProcessor; use App\State\TauxHoraire\TauxHoraireProvider; use DateTimeInterface; @@ -27,46 +32,54 @@ use Symfony\Component\Validator\Constraints as Assert; #[ApiResource( - operations : [ + operations: [ + new GetCollection( + uriTemplate: self::COLLECTION_URI, + uriVariables: [ + 'typeId' => new Link(fromProperty: 'id', toProperty: 'typeEvenement', fromClass: TypeEvenement::class,), + ], + provider: TauxHoraireCollectionProvider::class, + ), new Get( - uriTemplate : self::ITEM_URI, + uriTemplate: self::ITEM_URI, uriVariables: [ 'typeId', 'id', ], ), new Post( - uriTemplate : self::COLLECTION_URI, + uriTemplate: self::COLLECTION_URI, uriVariables: [ 'typeId', ], - security : "is_granted('ROLE_ADMIN')", - read : false, + security: "is_granted('ROLE_ADMIN')", + read: false, ), new Patch( - uriTemplate : self::ITEM_URI, + uriTemplate: self::ITEM_URI, uriVariables: [ 'typeId', 'id', ], - security : "is_granted('ROLE_ADMIN')", + security: "is_granted('ROLE_ADMIN')", ), new Delete( - uriTemplate : self::ITEM_URI, + uriTemplate: self::ITEM_URI, uriVariables: [ 'typeId', 'id', ], - security : "is_granted('ROLE_ADMIN')", + security: "is_granted('ROLE_ADMIN')", ), ], - normalizationContext : ['groups' => [self::GROUP_OUT]], + normalizationContext: ['groups' => [self::GROUP_OUT]], denormalizationContext: ['groups' => [self::GROUP_IN]], - openapi : new Operation(tags: ['Referentiel']), - order : ['debut' => 'DESC '], - security : "is_granted('ROLE_PLANIFICATEUR') or is_granted('ROLE_INTERVENANT')", - provider : TauxHoraireProvider::class, - processor : TauxHoraireProcessor::class, - stateOptions : new Options(entityClass: \App\Entity\TauxHoraire::class) + openapi: new Operation(tags: ['Referentiel']), + order: ['debut' => 'DESC '], + security: "is_granted('ROLE_PLANIFICATEUR') or is_granted('ROLE_INTERVENANT')", + provider: TauxHoraireProvider::class, + processor: TauxHoraireProcessor::class, + stateOptions: new Options(entityClass: \App\Entity\TauxHoraire::class) )] +#[ApiFilter(TauxHoraireDateFilter::class)] class TauxHoraire { public const string COLLECTION_URI = '/types_evenements/{typeId}/taux'; @@ -80,6 +93,7 @@ class TauxHoraire //copie juste pour gérer facilement les IRI public int $typeId; + public TypeEvenement $typeEvenement; #[Assert\NotBlank] #[Assert\Length(max: 5)] diff --git a/backend/src/Filter/CampagneNonArchiveeFilter.php b/backend/src/Filter/CampagneNonArchiveeFilter.php new file mode 100644 index 0000000..4c01d11 --- /dev/null +++ b/backend/src/Filter/CampagneNonArchiveeFilter.php @@ -0,0 +1,49 @@ +getRootAliases()[0]; + $campagneAlias = $queryNameGenerator->generateJoinAlias('campagne'); + + $queryBuilder->join(sprintf('%s.campagne', $rootAlias), $campagneAlias) + ->andWhere(sprintf('%1$s.dateArchivage IS NULL or %1$s.dateArchivage >= :now', $campagneAlias)) + ->setParameter('now', $this->now()); + } + + public function getDescription(string $resourceClass): array + { + return [ + 'archivees' => [ + 'property' => "archivees", + 'type' => Type::BUILTIN_TYPE_BOOL, + 'required' => false, + 'is_collection' => false, + 'openapi' => [ + 'description' => "inclure les demandes des campagnes archivées?", + 'name' => 'archivees', + 'type' => 'boolean', + ], + ] + ]; + } +} \ No newline at end of file diff --git a/backend/src/Filter/TauxHoraireDateFilter.php b/backend/src/Filter/TauxHoraireDateFilter.php new file mode 100644 index 0000000..ac0b953 --- /dev/null +++ b/backend/src/Filter/TauxHoraireDateFilter.php @@ -0,0 +1,53 @@ +getRootAliases()[0]; + + try { + $date = new DateTime($value); + } catch (Exception) { + throw new HttpException(400, "date mal formée"); + } + + $queryBuilder + ->andWhere(sprintf('%1$s.debut <= :date AND (%1$s.fin >= :date or %1$s.fin is null)', $rootAlias)) + ->setParameter('date', $date); + + } + + public function getDescription(string $resourceClass): array + { + return [ + 'date' => [ + 'property' => 'date', + 'type' => Type::BUILTIN_TYPE_STRING, + 'required' => false, + 'openapi' => [ + 'description' => 'Taux horaire valide pour la date passée', + 'name' => 'profil', + 'type' => 'string', + 'format' => 'date' + ], + ], + ]; + } +} \ No newline at end of file diff --git a/backend/src/State/TauxHoraire/TauxHoraireCollectionProvider.php b/backend/src/State/TauxHoraire/TauxHoraireCollectionProvider.php new file mode 100644 index 0000000..53a153f --- /dev/null +++ b/backend/src/State/TauxHoraire/TauxHoraireCollectionProvider.php @@ -0,0 +1,27 @@ +collectionProvider->provide($operation, $uriVariables, $context); + + return array_map(fn($taux) => $this->transformerService->transform($taux, TauxHoraire::class), iterator_to_array($data)); + } +} \ No newline at end of file diff --git a/backend/src/State/TauxHoraire/TauxHoraireProvider.php b/backend/src/State/TauxHoraire/TauxHoraireProvider.php index 2a28d86..461c97a 100644 --- a/backend/src/State/TauxHoraire/TauxHoraireProvider.php +++ b/backend/src/State/TauxHoraire/TauxHoraireProvider.php @@ -15,6 +15,7 @@ use ApiPlatform\Metadata\Link; use ApiPlatform\Metadata\Operation; use App\ApiResource\TauxHoraire; +use App\ApiResource\TypeEvenement; use App\State\AbstractEntityProvider; use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException; @@ -41,9 +42,9 @@ public function provide(Operation $operation, array $uriVariables = [], array $c ->withUriVariables([$link]); $taux = parent::provide( - operation : $relevantOperation, + operation: $relevantOperation, uriVariables: $relevantVariables, - context : $context + context: $context ); //devrait être une contrainte de validation @@ -65,6 +66,8 @@ public function transform($entity): TauxHoraire $resource->typeId = $entity->getTypeEvenement()->getId(); $resource->debut = $entity->getDebut(); $resource->fin = $entity->getFin(); + $resource->typeEvenement = new TypeEvenement(); + $resource->typeEvenement->id = $resource->typeId; return $resource; } } \ No newline at end of file