feat(technique) : ProviderProvider + ProviderProcessor + cloisonnement site (ERP-134)
Coeur API du repertoire prestataires (M3), jumeau du M2 fournisseurs : - ProviderProvider : liste paginee (Paginator ORM), filtres search/categoryCode/siteId/includeArchived, tri companyName ASC, exclusion archives + soft-deletes (RG-3.16). Cloisonnement par site pilote par l'utilisateur (RG-3.17 / § 2.13) : liste restreinte au currentSite avant pagination (totalItems = perimetre), detail hors perimetre -> 404, bypass via sites.bypass_scope. - ProviderProcessor : normalisation companyName (RG-3.11), POST formulaire principal (companyName + categories + sites), PATCH partiels par groupe en mode strict (RG-3.15, 403 sur tout le payload), archivage (RG-3.13/3.14), 409 doublon de nom (RG-3.10), garde d'ecriture cloisonnee des sites (RG-3.03/3.17, 422 sur sites pour les users sites.read_ref). - ProviderReadGroupContextBuilder : gating comptabilite par AJOUT du groupe provider:read:accounting si accounting.view (jamais par retrait). - ProviderFieldNormalizer : miroir SupplierFieldNormalizer. - ApiResource cable (provider + processor) sur l'entite Provider. Tests : ProviderApiTest, ProviderListTest, ProviderRbacGatingTest, ProviderSiteScopeTest (26 tests). Suite complete verte (612 tests).
This commit is contained in:
@@ -13,6 +13,8 @@ use App\Module\Commercial\Domain\Entity\Bank;
|
||||
use App\Module\Commercial\Domain\Entity\PaymentDelay;
|
||||
use App\Module\Commercial\Domain\Entity\PaymentType;
|
||||
use App\Module\Commercial\Domain\Entity\TvaMode;
|
||||
use App\Module\Technique\Infrastructure\ApiPlatform\State\Processor\ProviderProcessor;
|
||||
use App\Module\Technique\Infrastructure\ApiPlatform\State\Provider\ProviderProvider;
|
||||
use App\Module\Technique\Infrastructure\Doctrine\DoctrineProviderRepository;
|
||||
use App\Shared\Domain\Attribute\Auditable;
|
||||
use App\Shared\Domain\Contract\BlamableInterface;
|
||||
@@ -53,11 +55,12 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
* reference de donnees de reference, pas de logique inter-module.
|
||||
*
|
||||
* Contrat de serialisation (RETEX M1, 3 maillons — spec § 4.0) : les read-groups
|
||||
* sont poses ICI (source unique). L'#[ApiResource] est ici un SQUELETTE (operations
|
||||
* + contextes + security) ; le ProviderProvider (liste paginee anti-N+1, exclusion
|
||||
* archives, cloisonnement site, gating accounting) et le ProviderProcessor
|
||||
* (normalisation, archivage, 409 doublon, RG-3.07 / RG-3.08) sont cables au ticket
|
||||
* suivant (ERP-134) — ils ne sont volontairement PAS references ici.
|
||||
* sont poses ICI (source unique). L'#[ApiResource] cable (ERP-134) le ProviderProvider
|
||||
* (liste paginee anti-N+1, exclusion archives, cloisonnement site lecture + detail
|
||||
* 404) et le ProviderProcessor (normalisation, archivage, mode strict par groupe,
|
||||
* cloisonnement site ecriture, 409 doublon). Le groupe provider:read:accounting est
|
||||
* ajoute dynamiquement au contexte par le ProviderReadGroupContextBuilder selon la
|
||||
* permission accounting.view (ERP-134) — jamais pose en dur sur l'operation.
|
||||
*
|
||||
* Audite (#[Auditable], tous champs — y compris RIB embarques, § 2.7) +
|
||||
* Timestampable / Blamable via le trait Shared.
|
||||
@@ -69,17 +72,18 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
// La liste embarque les categories (code/name, groupe category:read) et
|
||||
// les sites du prestataire (name/postalCode, groupe site:read — relation
|
||||
// DIRECTE provider.sites, RG-3.03). Maillon (c) : category:read +
|
||||
// site:read presents dans le contexte. L'hydratation anti-N+1 sera
|
||||
// cablee par le ProviderProvider (ERP-134, cf. DoctrineProviderRepository).
|
||||
// site:read presents dans le contexte. Hydratation anti-N+1 cablee par
|
||||
// le ProviderProvider (cf. DoctrineProviderRepository::hydrateListCollections).
|
||||
normalizationContext: ['groups' => ['provider:read', 'category:read', 'site:read', 'default:read']],
|
||||
provider: ProviderProvider::class,
|
||||
),
|
||||
new Get(
|
||||
security: "is_granted('technique.providers.view')",
|
||||
// Detail : prestataire + sous-collections embarquees (contacts, adresses
|
||||
// + leurs sites/categories/contacts) + RIB (gates compta). Le groupe
|
||||
// provider:read:accounting est volontairement ABSENT : il sera ajoute au
|
||||
// contexte par le ProviderProvider / ReadGroupContextBuilder selon la
|
||||
// permission accounting.view (ERP-134, parade fuite IBAN/BIC — bug #4 M1).
|
||||
// provider:read:accounting est volontairement ABSENT : il est ajoute au
|
||||
// contexte par le ProviderReadGroupContextBuilder selon la permission
|
||||
// accounting.view (parade fuite IBAN/BIC — bug #4 M1).
|
||||
normalizationContext: ['groups' => [
|
||||
'provider:read',
|
||||
'provider:item:read',
|
||||
@@ -87,11 +91,13 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
'site:read',
|
||||
'default:read',
|
||||
]],
|
||||
provider: ProviderProvider::class,
|
||||
),
|
||||
new Post(
|
||||
security: "is_granted('technique.providers.manage')",
|
||||
normalizationContext: ['groups' => ['provider:read', 'category:read', 'site:read', 'default:read']],
|
||||
denormalizationContext: ['groups' => ['provider:write:main']],
|
||||
processor: ProviderProcessor::class,
|
||||
),
|
||||
new Patch(
|
||||
// Security elargie : `manage` OU `accounting.manage` — le role Compta n'a
|
||||
@@ -105,6 +111,8 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
'provider:write:accounting',
|
||||
'provider:write:archive',
|
||||
]],
|
||||
provider: ProviderProvider::class,
|
||||
processor: ProviderProcessor::class,
|
||||
),
|
||||
// Pas de Delete au M3 (HP M4). Archivage via PATCH { isArchived: true }.
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user