test(technique) : couvrir RG-3.x PHPUnit + capturer le contrat JSON (ProviderSerializationContractTest, ProviderAuditTest, fixtures démo) (ERP-139)
Ajoute provider:read:accounting sur les réfs comptables partagées (TvaMode/PaymentDelay/PaymentType/Bank) pour embarquer {id,code,label} au lieu d un IRI nu (réplique fix ERP-92). Helper seedCompleteProvider, anti-N+1 + pagination=false + filtre typeCode, restauration conflit 409, fixtures démo idempotentes. Captures JSON réelles collées dans spec § 4.0.bis.
This commit is contained in:
@@ -21,7 +21,8 @@ use Symfony\Component\Serializer\Attribute\Groups;
|
||||
* Timestampable/Blamable (referentiel statique whiteliste dans
|
||||
* EntitiesAreTimestampableBlamableTest::EXCLUDED). Le groupe
|
||||
* `client:read:accounting` permet l'embarquement dans la reponse Client ;
|
||||
* `supplier:read:accounting` dans la reponse Fournisseur (M2, ERP-92 — § 4.0).
|
||||
* `supplier:read:accounting` dans la reponse Fournisseur (M2, ERP-92 — § 4.0) ;
|
||||
* `provider:read:accounting` dans la reponse Prestataire (M3, ERP-139 — § 4.0.bis).
|
||||
*/
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
@@ -48,15 +49,15 @@ class Bank
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
#[Groups(['bank:read', 'client:read:accounting', 'supplier:read:accounting'])]
|
||||
#[Groups(['bank:read', 'client:read:accounting', 'supplier:read:accounting', 'provider:read:accounting'])]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 30)]
|
||||
#[Groups(['bank:read', 'client:read:accounting', 'supplier:read:accounting'])]
|
||||
#[Groups(['bank:read', 'client:read:accounting', 'supplier:read:accounting', 'provider:read:accounting'])]
|
||||
private ?string $code = null;
|
||||
|
||||
#[ORM\Column(length: 120)]
|
||||
#[Groups(['bank:read', 'client:read:accounting', 'supplier:read:accounting'])]
|
||||
#[Groups(['bank:read', 'client:read:accounting', 'supplier:read:accounting', 'provider:read:accounting'])]
|
||||
private ?string $label = null;
|
||||
|
||||
#[ORM\Column(options: ['default' => 0])]
|
||||
|
||||
@@ -21,7 +21,8 @@ use Symfony\Component\Serializer\Attribute\Groups;
|
||||
* Timestampable/Blamable (referentiel statique whiteliste dans
|
||||
* EntitiesAreTimestampableBlamableTest::EXCLUDED). Le groupe
|
||||
* `client:read:accounting` permet l'embarquement dans la reponse Client ;
|
||||
* `supplier:read:accounting` dans la reponse Fournisseur (M2, ERP-92 — § 4.0).
|
||||
* `supplier:read:accounting` dans la reponse Fournisseur (M2, ERP-92 — § 4.0) ;
|
||||
* `provider:read:accounting` dans la reponse Prestataire (M3, ERP-139 — § 4.0.bis).
|
||||
*/
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
@@ -48,15 +49,15 @@ class PaymentDelay
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
#[Groups(['payment_delay:read', 'client:read:accounting', 'supplier:read:accounting'])]
|
||||
#[Groups(['payment_delay:read', 'client:read:accounting', 'supplier:read:accounting', 'provider:read:accounting'])]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 30)]
|
||||
#[Groups(['payment_delay:read', 'client:read:accounting', 'supplier:read:accounting'])]
|
||||
#[Groups(['payment_delay:read', 'client:read:accounting', 'supplier:read:accounting', 'provider:read:accounting'])]
|
||||
private ?string $code = null;
|
||||
|
||||
#[ORM\Column(length: 120)]
|
||||
#[Groups(['payment_delay:read', 'client:read:accounting', 'supplier:read:accounting'])]
|
||||
#[Groups(['payment_delay:read', 'client:read:accounting', 'supplier:read:accounting', 'provider:read:accounting'])]
|
||||
private ?string $label = null;
|
||||
|
||||
#[ORM\Column(options: ['default' => 0])]
|
||||
|
||||
@@ -24,7 +24,8 @@ use Symfony\Component\Serializer\Attribute\Groups;
|
||||
* Timestampable/Blamable (referentiel statique whiteliste dans
|
||||
* EntitiesAreTimestampableBlamableTest::EXCLUDED). Le groupe
|
||||
* `client:read:accounting` permet l'embarquement dans la reponse Client ;
|
||||
* `supplier:read:accounting` dans la reponse Fournisseur (M2, ERP-92 — § 4.0).
|
||||
* `supplier:read:accounting` dans la reponse Fournisseur (M2, ERP-92 — § 4.0) ;
|
||||
* `provider:read:accounting` dans la reponse Prestataire (M3, ERP-139 — § 4.0.bis).
|
||||
*/
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
@@ -51,15 +52,15 @@ class PaymentType
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
#[Groups(['payment_type:read', 'client:read:accounting', 'supplier:read:accounting'])]
|
||||
#[Groups(['payment_type:read', 'client:read:accounting', 'supplier:read:accounting', 'provider:read:accounting'])]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 30)]
|
||||
#[Groups(['payment_type:read', 'client:read:accounting', 'supplier:read:accounting'])]
|
||||
#[Groups(['payment_type:read', 'client:read:accounting', 'supplier:read:accounting', 'provider:read:accounting'])]
|
||||
private ?string $code = null;
|
||||
|
||||
#[ORM\Column(length: 120)]
|
||||
#[Groups(['payment_type:read', 'client:read:accounting', 'supplier:read:accounting'])]
|
||||
#[Groups(['payment_type:read', 'client:read:accounting', 'supplier:read:accounting', 'provider:read:accounting'])]
|
||||
private ?string $label = null;
|
||||
|
||||
#[ORM\Column(options: ['default' => 0])]
|
||||
|
||||
@@ -25,7 +25,8 @@ use Symfony\Component\Serializer\Attribute\Groups;
|
||||
* EntitiesAreTimestampableBlamableTest::EXCLUDED, comme CategoryType). Le
|
||||
* groupe `client:read:accounting` permet d'embarquer le mode dans la reponse
|
||||
* d'un Client (onglet Comptabilite) au lieu d'un IRI ; `supplier:read:accounting`
|
||||
* fait de meme dans la reponse Fournisseur (M2, ERP-92 — sinon IRI nu, § 4.0).
|
||||
* fait de meme dans la reponse Fournisseur (M2, ERP-92 — sinon IRI nu, § 4.0) ;
|
||||
* `provider:read:accounting` dans la reponse Prestataire (M3, ERP-139 — § 4.0.bis).
|
||||
*/
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
@@ -55,15 +56,15 @@ class TvaMode
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
#[Groups(['tva_mode:read', 'client:read:accounting', 'supplier:read:accounting'])]
|
||||
#[Groups(['tva_mode:read', 'client:read:accounting', 'supplier:read:accounting', 'provider:read:accounting'])]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 30)]
|
||||
#[Groups(['tva_mode:read', 'client:read:accounting', 'supplier:read:accounting'])]
|
||||
#[Groups(['tva_mode:read', 'client:read:accounting', 'supplier:read:accounting', 'provider:read:accounting'])]
|
||||
private ?string $code = null;
|
||||
|
||||
#[ORM\Column(length: 120)]
|
||||
#[Groups(['tva_mode:read', 'client:read:accounting', 'supplier:read:accounting'])]
|
||||
#[Groups(['tva_mode:read', 'client:read:accounting', 'supplier:read:accounting', 'provider:read:accounting'])]
|
||||
private ?string $label = null;
|
||||
|
||||
#[ORM\Column(options: ['default' => 0])]
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Module\Technique\Infrastructure\DataFixtures;
|
||||
|
||||
use App\Module\Catalog\Infrastructure\DataFixtures\CategoryFixtures;
|
||||
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\Commercial\Infrastructure\DataFixtures\CommercialReferentialFixtures;
|
||||
use App\Module\Sites\Infrastructure\DataFixtures\SitesFixtures;
|
||||
use App\Module\Technique\Application\Service\ProviderFieldNormalizer;
|
||||
use App\Module\Technique\Domain\Entity\Provider;
|
||||
use App\Module\Technique\Domain\Entity\ProviderAddress;
|
||||
use App\Module\Technique\Domain\Entity\ProviderContact;
|
||||
use App\Module\Technique\Domain\Entity\ProviderRib;
|
||||
use App\Shared\Domain\Contract\CategoryInterface;
|
||||
use App\Shared\Domain\Contract\SiteInterface;
|
||||
use App\Shared\Domain\Contract\SiteProviderInterface;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
|
||||
/**
|
||||
* Fixtures dev/test du module Technique : prestataires de demonstration couvrant
|
||||
* les cas metier RG-3.xx du repertoire prestataires (M3), jumelles des fixtures
|
||||
* fournisseurs (M2). Theme : prestations techniques (maintenance, nettoyage,
|
||||
* transport).
|
||||
*
|
||||
* Cas pivots couverts (§ 8.4) :
|
||||
* - prestataire COMPLET : >= 1 site sur le formulaire principal (RG-3.03), >= 1
|
||||
* contact, >= 1 adresse multi-sites (RG-3.05), comptabilite + RIB ;
|
||||
* - reglement LCR avec RIB (RG-3.08) ; reglement VIREMENT avec banque (RG-3.07) ;
|
||||
* - 1 prestataire archive (isArchived + archivedAt) pour l'exclusion de la liste
|
||||
* (RG-3.16) ;
|
||||
* - prestataires repartis sur des sites DIFFERENTS (86 / 17 / 82) pour exercer le
|
||||
* cloisonnement par site (RG-3.17) ;
|
||||
* - mono et multi-categories de type PRESTATAIRE (RG-3.09).
|
||||
*
|
||||
* Resolution inter-modules conforme a la regle n°1 (pas d'import de logique) :
|
||||
* - categories resolues via le contrat Shared CategoryInterface ;
|
||||
* - sites resolus via le contrat Shared SiteProviderInterface.
|
||||
*
|
||||
* Normalisation : valeurs fournies BRUTES, normalisees par ProviderFieldNormalizer
|
||||
* avant persist, exactement comme le ferait le ProviderProcessor via l'API
|
||||
* (companyName UPPERCASE, first/last Capitalize, telephones chiffres seuls, emails
|
||||
* lowercase — RG-3.11).
|
||||
*
|
||||
* Idempotence : lookup par companyName normalise (coherent avec l'index unique
|
||||
* partiel uq_provider_company_name_active). Un prestataire deja present n'est pas
|
||||
* reconstruit (sous-collections non redupliquees). Rejouable sans doublon.
|
||||
*
|
||||
* Portee : DONNEES DE DEMONSTRATION (dev uniquement). En environnement `test`, la
|
||||
* fixture ne charge rien : les tests seedent et nettoient leurs propres
|
||||
* prestataires et comptent sur une table `provider` vierge. Meme garde-fou que
|
||||
* SupplierFixtures / CategoryFixtures.
|
||||
*/
|
||||
class ProviderFixtures extends Fixture implements DependentFixtureInterface
|
||||
{
|
||||
/**
|
||||
* Type de categorie exige pour un prestataire et ses adresses (RG-3.09).
|
||||
* Miroir de Provider::REQUIRED_CATEGORY_TYPE_CODE (non importable — regle n°1).
|
||||
*/
|
||||
private const string PROVIDER_CATEGORY_TYPE_CODE = 'PRESTATAIRE';
|
||||
|
||||
/** Cache des categories resolues par nom. */
|
||||
private array $categoryCache = [];
|
||||
|
||||
/** Cache des sites resolus par nom. */
|
||||
private array $siteCache = [];
|
||||
|
||||
/** ObjectManager courant, capture en debut de load. */
|
||||
private ObjectManager $manager;
|
||||
|
||||
public function __construct(
|
||||
private readonly ProviderFieldNormalizer $normalizer,
|
||||
private readonly SiteProviderInterface $siteProvider,
|
||||
#[Autowire('%kernel.environment%')]
|
||||
private readonly string $environment,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @return array<int, class-string>
|
||||
*/
|
||||
public function getDependencies(): array
|
||||
{
|
||||
return [
|
||||
CategoryFixtures::class,
|
||||
SitesFixtures::class,
|
||||
CommercialReferentialFixtures::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function load(ObjectManager $manager): void
|
||||
{
|
||||
// Donnees de demo : dev uniquement. En test, on laisse la table vierge.
|
||||
if ('test' === $this->environment) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->manager = $manager;
|
||||
|
||||
// === Prestataire COMPLET — VIREMENT + banque (RG-3.07), compta + RIB, ===
|
||||
// === multi-sites sur le formulaire principal ET sur l'adresse. ===
|
||||
[$maintenance, $isNew] = $this->ensureProvider($manager, 'Maintenance Pro SAS', ['Maintenance industrielle'], ['Chatellerault', 'Saint-Jean']);
|
||||
if ($isNew) {
|
||||
$maintenance->setSiren('841611054');
|
||||
$maintenance->setAccountNumber('P0001');
|
||||
$maintenance->setTvaMode($this->tvaMode($manager, 'FRANCE_VENTES'));
|
||||
$maintenance->setNTva('FR12841611054');
|
||||
$maintenance->setPaymentDelay($this->paymentDelay($manager, 'J30'));
|
||||
$maintenance->setPaymentType($this->paymentType($manager, 'VIREMENT'));
|
||||
$maintenance->setBank($this->bank($manager, 'SG'));
|
||||
$this->addContact($maintenance, 'Marie', 'Martin', 'Responsable', '05 49 00 00 01', null, 'marie.martin@maintenance-pro.fr');
|
||||
$this->addAddress($maintenance, ['Chatellerault', 'Saint-Jean'], '86000', 'Poitiers', '12 rue des Acacias', categoryNames: ['Maintenance industrielle']);
|
||||
$this->addRib($maintenance, 'Compte principal', 'BNPAFRPPXXX', 'FR1420041010050500013M02606', 0);
|
||||
}
|
||||
|
||||
// === LCR avec RIB (RG-3.08) — site Pommevic ===
|
||||
[$nettoyage, $isNew] = $this->ensureProvider($manager, 'Nettoyage Sud-Ouest', ['Nettoyage'], ['Pommevic']);
|
||||
if ($isNew) {
|
||||
$nettoyage->setSiren('775680459');
|
||||
$nettoyage->setTvaMode($this->tvaMode($manager, 'FRANCE_VENTES'));
|
||||
$nettoyage->setPaymentDelay($this->paymentDelay($manager, 'J15'));
|
||||
$nettoyage->setPaymentType($this->paymentType($manager, 'LCR'));
|
||||
$this->addContact($nettoyage, 'Sophie', 'Marchand', 'Directrice', '05 56 10 20 30', '06 11 22 33 44', 'sophie.marchand@nettoyage-so.fr', 0);
|
||||
$this->addContact($nettoyage, 'Marc', 'Girard', 'Chef d\'equipe', '05 56 10 20 31', null, 'marc.girard@nettoyage-so.fr', 1);
|
||||
$this->addAddress($nettoyage, ['Pommevic'], '82400', 'Pommevic', '8 route des Prestations');
|
||||
$this->addRib($nettoyage, 'Compte principal', 'BNPAFRPPXXX', 'FR7630006000011234567890189', 0);
|
||||
}
|
||||
|
||||
// === Multi-categories PRESTATAIRE + reglement CHEQUE (sans banque ni RIB) ===
|
||||
[$transport, $isNew] = $this->ensureProvider($manager, 'Transport Express Atlantique', ['Transport', 'Maintenance industrielle'], ['Saint-Jean']);
|
||||
if ($isNew) {
|
||||
$transport->setPaymentDelay($this->paymentDelay($manager, 'A_RECEPTION'));
|
||||
$transport->setPaymentType($this->paymentType($manager, 'CHEQUE'));
|
||||
$this->addContact($transport, 'Thomas', 'Petit', 'Responsable logistique', '05 56 31 32 33', null, 'thomas.petit@transport-express.fr');
|
||||
$this->addAddress($transport, ['Saint-Jean'], '17400', 'Fontenet', '4 zone des Transporteurs', categoryNames: ['Transport']);
|
||||
}
|
||||
|
||||
// === Prestataire minimal — contact par le seul nom (RG-3.04), site 86 ===
|
||||
[$petit, $isNew] = $this->ensureProvider($manager, 'Atelier Soudure Locale', ['Maintenance industrielle'], ['Chatellerault']);
|
||||
if ($isNew) {
|
||||
$this->addContact($petit, null, 'Caron', 'Gerant', '05 49 81 82 83', null, 'contact@atelier-soudure.fr');
|
||||
$this->addAddress($petit, ['Chatellerault'], '86100', 'Châtellerault', '6 chemin de l\'Atelier');
|
||||
}
|
||||
|
||||
// === Prestataire archive (RG-3.16) ===
|
||||
[$ancien, $isNew] = $this->ensureProvider($manager, 'Ancien Prestataire Ferme', ['Nettoyage'], ['Chatellerault'], isArchived: true);
|
||||
if ($isNew) {
|
||||
$this->addContact($ancien, null, 'Lambert', 'Ancien contact', '05 49 99 99 99', null, 'contact@ancien-prestataire.fr');
|
||||
$this->addAddress($ancien, ['Chatellerault'], '86100', 'Châtellerault', '99 rue Fermée');
|
||||
}
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cree un prestataire (base normalisee + categories PRESTATAIRE + sites directs)
|
||||
* s'il n'existe pas, sinon retourne l'existant. Retourne [Provider, isNew] :
|
||||
* isNew=false bloque la reconstruction des sous-collections (idempotence).
|
||||
*
|
||||
* @param list<string> $categoryNames categories de type PRESTATAIRE (RG-3.09)
|
||||
* @param list<string> $siteNames sites du formulaire principal (RG-3.03, >= 1)
|
||||
*
|
||||
* @return array{0: Provider, 1: bool}
|
||||
*/
|
||||
private function ensureProvider(
|
||||
ObjectManager $manager,
|
||||
string $companyName,
|
||||
array $categoryNames,
|
||||
array $siteNames,
|
||||
bool $isArchived = false,
|
||||
): array {
|
||||
$normalizedName = (string) $this->normalizer->normalizeCompanyName($companyName);
|
||||
|
||||
$existing = $manager->getRepository(Provider::class)->findOneBy(['companyName' => $normalizedName]);
|
||||
if ($existing instanceof Provider) {
|
||||
return [$existing, false];
|
||||
}
|
||||
|
||||
$provider = new Provider();
|
||||
$provider->setCompanyName($normalizedName);
|
||||
|
||||
foreach ($categoryNames as $categoryName) {
|
||||
$provider->addCategory($this->category($manager, $categoryName));
|
||||
}
|
||||
foreach ($siteNames as $siteName) {
|
||||
$provider->addSite($this->site($siteName));
|
||||
}
|
||||
|
||||
if ($isArchived) {
|
||||
$provider->setIsArchived(true);
|
||||
$provider->setArchivedAt(new DateTimeImmutable());
|
||||
}
|
||||
|
||||
$manager->persist($provider);
|
||||
|
||||
return [$provider, true];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajoute un contact normalise au prestataire (cascade persist via
|
||||
* Provider.contacts). Au moins un champ est rempli (RG-3.04).
|
||||
*/
|
||||
private function addContact(
|
||||
Provider $provider,
|
||||
?string $firstName,
|
||||
?string $lastName,
|
||||
?string $jobTitle,
|
||||
?string $phonePrimary,
|
||||
?string $phoneSecondary,
|
||||
?string $email,
|
||||
int $position = 0,
|
||||
): void {
|
||||
$contact = new ProviderContact();
|
||||
$contact->setProvider($provider);
|
||||
$contact->setFirstName($this->normalizer->normalizePersonName($firstName));
|
||||
$contact->setLastName($this->normalizer->normalizePersonName($lastName));
|
||||
$contact->setJobTitle($jobTitle);
|
||||
$contact->setPhonePrimary($this->normalizer->normalizePhone($phonePrimary));
|
||||
$contact->setPhoneSecondary($this->normalizer->normalizePhone($phoneSecondary));
|
||||
$contact->setEmail($this->normalizer->normalizeEmail($email));
|
||||
$contact->setPosition($position);
|
||||
|
||||
$provider->addContact($contact);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajoute une adresse au prestataire (cascade persist via Provider.addresses).
|
||||
* Adresse simplifiee M3 : PAS de addressType / bennes / triageProvider. Au
|
||||
* moins un site est rattache (RG-3.05) ; categories d'adresse de type
|
||||
* PRESTATAIRE (RG-3.09).
|
||||
*
|
||||
* @param list<string> $siteNames au moins un site (RG-3.05)
|
||||
* @param list<string> $categoryNames categories de type PRESTATAIRE (RG-3.09)
|
||||
*/
|
||||
private function addAddress(
|
||||
Provider $provider,
|
||||
array $siteNames,
|
||||
string $postalCode,
|
||||
string $city,
|
||||
string $street,
|
||||
?string $streetComplement = null,
|
||||
array $categoryNames = [],
|
||||
int $position = 0,
|
||||
): void {
|
||||
$address = new ProviderAddress();
|
||||
$address->setProvider($provider);
|
||||
$address->setCountry('France');
|
||||
$address->setPostalCode($postalCode);
|
||||
$address->setCity($city);
|
||||
$address->setStreet($street);
|
||||
$address->setStreetComplement($streetComplement);
|
||||
$address->setPosition($position);
|
||||
|
||||
foreach ($siteNames as $siteName) {
|
||||
$address->addSite($this->site($siteName));
|
||||
}
|
||||
foreach ($categoryNames as $categoryName) {
|
||||
$address->addCategory($this->category($this->manager, $categoryName));
|
||||
}
|
||||
|
||||
$provider->addAddress($address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajoute un RIB au prestataire (cascade persist via Provider.ribs).
|
||||
*/
|
||||
private function addRib(Provider $provider, string $label, string $bic, string $iban, int $position = 0): void
|
||||
{
|
||||
$rib = new ProviderRib();
|
||||
$rib->setProvider($provider);
|
||||
$rib->setLabel($label);
|
||||
$rib->setBic($bic);
|
||||
$rib->setIban($iban);
|
||||
$rib->setPosition($position);
|
||||
|
||||
$provider->addRib($rib);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resout une categorie par son nom via le contrat Shared CategoryInterface,
|
||||
* sans importer le module Catalog (regle n°1). Verifie le type PRESTATAIRE
|
||||
* (RG-3.09). Mise en cache par nom.
|
||||
*/
|
||||
private function category(ObjectManager $manager, string $name): CategoryInterface
|
||||
{
|
||||
if (isset($this->categoryCache[$name])) {
|
||||
return $this->categoryCache[$name];
|
||||
}
|
||||
|
||||
$candidates = $manager->getRepository(CategoryInterface::class)->findBy([
|
||||
'name' => $name,
|
||||
'deletedAt' => null,
|
||||
]);
|
||||
|
||||
foreach ($candidates as $candidate) {
|
||||
if ($candidate instanceof CategoryInterface
|
||||
&& in_array(self::PROVIDER_CATEGORY_TYPE_CODE, $candidate->getCategoryTypeCodes(), true)) {
|
||||
return $this->categoryCache[$name] = $candidate;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf(
|
||||
'Categorie PRESTATAIRE "%s" introuvable : CategoryFixtures doit tourner avant ProviderFixtures.',
|
||||
$name,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resout un site par son nom via le contrat Shared SiteProviderInterface, sans
|
||||
* importer le module Sites (regle n°1). Mise en cache par nom.
|
||||
*/
|
||||
private function site(string $name): SiteInterface
|
||||
{
|
||||
if (isset($this->siteCache[$name])) {
|
||||
return $this->siteCache[$name];
|
||||
}
|
||||
|
||||
$site = $this->siteProvider->findByName($name);
|
||||
|
||||
if (!$site instanceof SiteInterface) {
|
||||
throw new RuntimeException(sprintf(
|
||||
'Site "%s" introuvable : SitesFixtures doit tourner avant ProviderFixtures.',
|
||||
$name,
|
||||
));
|
||||
}
|
||||
|
||||
return $this->siteCache[$name] = $site;
|
||||
}
|
||||
|
||||
private function tvaMode(ObjectManager $manager, string $code): TvaMode
|
||||
{
|
||||
$mode = $manager->getRepository(TvaMode::class)->findOneBy(['code' => $code]);
|
||||
|
||||
if (!$mode instanceof TvaMode) {
|
||||
throw new RuntimeException(sprintf(
|
||||
'TvaMode "%s" introuvable : CommercialReferentialFixtures doit tourner avant ProviderFixtures.',
|
||||
$code,
|
||||
));
|
||||
}
|
||||
|
||||
return $mode;
|
||||
}
|
||||
|
||||
private function paymentDelay(ObjectManager $manager, string $code): PaymentDelay
|
||||
{
|
||||
$delay = $manager->getRepository(PaymentDelay::class)->findOneBy(['code' => $code]);
|
||||
|
||||
if (!$delay instanceof PaymentDelay) {
|
||||
throw new RuntimeException(sprintf(
|
||||
'PaymentDelay "%s" introuvable : CommercialReferentialFixtures doit tourner avant ProviderFixtures.',
|
||||
$code,
|
||||
));
|
||||
}
|
||||
|
||||
return $delay;
|
||||
}
|
||||
|
||||
private function paymentType(ObjectManager $manager, string $code): PaymentType
|
||||
{
|
||||
$type = $manager->getRepository(PaymentType::class)->findOneBy(['code' => $code]);
|
||||
|
||||
if (!$type instanceof PaymentType) {
|
||||
throw new RuntimeException(sprintf(
|
||||
'PaymentType "%s" introuvable : CommercialReferentialFixtures doit tourner avant ProviderFixtures.',
|
||||
$code,
|
||||
));
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
private function bank(ObjectManager $manager, string $code): Bank
|
||||
{
|
||||
$bank = $manager->getRepository(Bank::class)->findOneBy(['code' => $code]);
|
||||
|
||||
if (!$bank instanceof Bank) {
|
||||
throw new RuntimeException(sprintf(
|
||||
'Bank "%s" introuvable : CommercialReferentialFixtures doit tourner avant ProviderFixtures.',
|
||||
$code,
|
||||
));
|
||||
}
|
||||
|
||||
return $bank;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user