-
{{ customer.label }}
-
{{ customer.code }}
+
{{ customer.name || "—" }}
+
{{ customer.phone || "—" }}
+
{{ customer.email || "—" }}
Adresses non chargées
diff --git a/frontend/services/dto/customer-data.ts b/frontend/services/dto/customer-data.ts
index ddaa22d..90e00a9 100644
--- a/frontend/services/dto/customer-data.ts
+++ b/frontend/services/dto/customer-data.ts
@@ -4,19 +4,22 @@ export type CustomerAddresses = AddressFormData[] | string[]
export interface CustomerData {
id: number
- label: string
- code?: string | null
+ name: string
+ phone?: string | null
+ email?: string | null
addresses: CustomerAddresses
}
export interface CustomerFormData {
- label: string
- code?: string
+ name: string
+ phone?: string
+ email?: string
addresses: AddressFormData[]
}
export type CustomerPayload = {
- label: string
- code?: string | null
+ name: string
+ phone?: string | null
+ email?: string | null
addresses?: string[]
}
diff --git a/migrations/Version20260213093000.php b/migrations/Version20260213093000.php
new file mode 100644
index 0000000..019080f
--- /dev/null
+++ b/migrations/Version20260213093000.php
@@ -0,0 +1,32 @@
+addSql('ALTER TABLE customer ADD name VARCHAR(255) DEFAULT NULL');
+ $this->addSql('ALTER TABLE customer ADD phone VARCHAR(255) DEFAULT NULL');
+ $this->addSql('ALTER TABLE customer ADD email VARCHAR(255) DEFAULT NULL');
+ $this->addSql('UPDATE customer SET name = label WHERE name IS NULL');
+ $this->addSql('ALTER TABLE customer ALTER COLUMN name SET NOT NULL');
+ }
+
+ public function down(Schema $schema): void
+ {
+ $this->addSql('ALTER TABLE customer DROP name');
+ $this->addSql('ALTER TABLE customer DROP phone');
+ $this->addSql('ALTER TABLE customer DROP email');
+ }
+}
diff --git a/migrations/Version20260213101500.php b/migrations/Version20260213101500.php
new file mode 100644
index 0000000..e5029d8
--- /dev/null
+++ b/migrations/Version20260213101500.php
@@ -0,0 +1,37 @@
+addSql('ALTER TABLE customer ALTER COLUMN name TYPE VARCHAR(180)');
+ $this->addSql('ALTER TABLE customer ALTER COLUMN email TYPE VARCHAR(180)');
+ $this->addSql('ALTER TABLE customer ALTER COLUMN phone TYPE VARCHAR(40)');
+ $this->addSql('ALTER TABLE customer DROP COLUMN label');
+ $this->addSql('ALTER TABLE customer DROP COLUMN code');
+ }
+
+ public function down(Schema $schema): void
+ {
+ $this->addSql('ALTER TABLE customer ADD label VARCHAR(255) DEFAULT NULL');
+ $this->addSql('ALTER TABLE customer ADD code VARCHAR(255) DEFAULT NULL');
+ $this->addSql('UPDATE customer SET label = name WHERE label IS NULL');
+ $this->addSql("UPDATE customer SET code = regexp_replace(upper(name), '[^A-Z0-9]+', '_', 'g') WHERE code IS NULL");
+ $this->addSql('ALTER TABLE customer ALTER COLUMN label SET NOT NULL');
+ $this->addSql('ALTER TABLE customer ALTER COLUMN code SET NOT NULL');
+ $this->addSql('ALTER TABLE customer ALTER COLUMN email TYPE VARCHAR(255)');
+ $this->addSql('ALTER TABLE customer ALTER COLUMN phone TYPE VARCHAR(255)');
+ }
+}
diff --git a/src/Command/SeedCommand.php b/src/Command/SeedCommand.php
index 0567041..a85fe52 100644
--- a/src/Command/SeedCommand.php
+++ b/src/Command/SeedCommand.php
@@ -5,12 +5,15 @@ declare(strict_types=1);
namespace App\Command;
use App\Entity\Address;
+use App\Entity\BovineType;
use App\Entity\Building;
use App\Entity\Carrier;
+use App\Entity\Customer;
use App\Entity\Driver;
use App\Entity\MerchandiseType;
use App\Entity\PelletType;
use App\Entity\ReceptionType;
+use App\Entity\ShipmentType;
use App\Entity\Supplier;
use App\Entity\Truck;
use App\Entity\Vehicle;
@@ -50,7 +53,11 @@ class SeedCommand extends Command
$this->seedPelletTypes();
$this->seedBuildings();
$this->seedReceptionTypes();
+ $this->seedBovineTypes();
+ $this->seedShipmentTypes();
$this->seedSuppliers();
+ $this->entityManager->flush();
+ $this->seedCustomers($io);
$this->entityManager->flush();
@@ -61,7 +68,7 @@ class SeedCommand extends Command
private function seedTrucks(): array
{
- $trucks = ['Citerne', 'Porteur'];
+ $trucks = ['Citerne', 'Porteur', 'Plateau', 'Remorque', 'Benne'];
$citerne = null;
$porteur = null;
foreach ($trucks as $name) {
@@ -223,6 +230,39 @@ class SeedCommand extends Command
}
}
+ private function seedBovineTypes(): void
+ {
+ $bovineTypes = [
+ ['label' => 'Limousine', 'code' => '34'],
+ ['label' => 'Charolaise', 'code' => '38'],
+ ['label' => 'Parthenaise', 'code' => '71'],
+ ];
+ foreach ($bovineTypes as $type) {
+ $this->upsertByCode(BovineType::class, $type['code'], static function (BovineType $entity) use ($type) {
+ $entity
+ ->setLabel($type['label'])
+ ->setCode($type['code'])
+ ;
+ });
+ }
+ }
+
+ private function seedShipmentTypes(): void
+ {
+ $shipmentTypes = [
+ ['label' => 'Bovin de boucherie', 'code' => 'BDB'],
+ ['label' => "Bovin d'équarrissage", 'code' => 'BE'],
+ ];
+ foreach ($shipmentTypes as $type) {
+ $this->upsertByCode(ShipmentType::class, $type['code'], static function (ShipmentType $entity) use ($type) {
+ $entity
+ ->setLabel($type['label'])
+ ->setCode($type['code'])
+ ;
+ });
+ }
+ }
+
private function seedSuppliers(): void
{
$suppliers = [
@@ -458,6 +498,130 @@ class SeedCommand extends Command
}
}
+ private function seedCustomers(SymfonyStyle $io): void
+ {
+ $addressRepo = $this->entityManager->getRepository(Address::class);
+ $customers = [
+ [
+ 'name' => 'ARNAULT EURL',
+ 'phone' => '05.49.02.65.27',
+ 'email' => 'eurl.arnault86@orange.fr',
+ 'addresses' => [
+ [
+ 'label' => 'ARNAULT EURL',
+ 'street' => 'Moulin du Guéret',
+ 'street2' => 'B.P 30425',
+ 'postalCode' => '86100',
+ 'city' => 'Antran',
+ 'countryCode' => 'FR',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'COVILIM',
+ 'phone' => '05.55.30.03.10',
+ 'email' => 'sandra.robineaux@covilim.com',
+ 'addresses' => [
+ [
+ 'label' => 'COVILIM',
+ 'street' => 'Rue de Nexon',
+ 'street2' => null,
+ 'postalCode' => '87000',
+ 'city' => 'LIMOGES',
+ 'countryCode' => 'FR',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'Les producteurs de la marche (LPM)',
+ 'phone' => '05.55.63.04.53',
+ 'email' => 'f.legalliard@lpmcoop.fr',
+ 'addresses' => [
+ [
+ 'label' => 'Les producteurs de la marche (LPM)',
+ 'street' => 'Rue de Nexon',
+ 'street2' => null,
+ 'postalCode' => '87000',
+ 'city' => 'LIMOGES',
+ 'countryCode' => 'FR',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'LORTHOLARY BETAIL',
+ 'phone' => '05.49.52.77.10',
+ 'email' => 'contact86@lortholarybetail.com',
+ 'addresses' => [
+ [
+ 'label' => 'LORTHOLARY BETAIL',
+ 'street' => 'FERME DE GENIEC',
+ 'street2' => null,
+ 'postalCode' => '86550',
+ 'city' => 'MIGNALOUX BEAUVOIR',
+ 'countryCode' => 'FR',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'TERRENA',
+ 'phone' => '02.51.67.17.98',
+ 'email' => null,
+ 'addresses' => [
+ [
+ 'label' => 'TERRENA',
+ 'street' => 'La Blanchardière',
+ 'street2' => null,
+ 'postalCode' => '44522',
+ 'city' => 'MESANGER',
+ 'countryCode' => 'FR',
+ ],
+ ],
+ ],
+ ];
+
+ foreach ($customers as $customerData) {
+ $customerName = $customerData['name'] ?? $customerData['label'] ?? null;
+ if (!$customerName) {
+ $io->warning('Customer skipped: missing "name".');
+
+ continue;
+ }
+ $customer = $this->upsertByName(Customer::class, $customerName, static function (Customer $customer) use ($customerData, $customerName) {
+ $customer
+ ->setName($customerName)
+ ->setPhone($customerData['phone'] ?? null)
+ ->setEmail($customerData['email'] ?? null)
+ ;
+ });
+
+ $addresses = [];
+ if (isset($customerData['addresses']) && is_array($customerData['addresses'])) {
+ foreach ($customerData['addresses'] as $addressData) {
+ $addresses[] = $this->upsertAddress($addressData);
+ }
+ } else {
+ // Backward compatibility for older seed format with address ids.
+ $addressIds = $customerData['addressIds'] ?? (isset($customerData['addressId']) ? [$customerData['addressId']] : []);
+ foreach ($addressIds as $addressId) {
+ $address = $addressRepo->find($addressId);
+ if (!$address instanceof Address) {
+ $io->warning(sprintf(
+ 'Customer "%s" skipped address id %d: not found.',
+ $customerName,
+ $addressId
+ ));
+
+ continue;
+ }
+ $addresses[] = $address;
+ }
+ }
+
+ $customer->setAddresses($addresses);
+ $this->entityManager->persist($customer);
+ }
+ }
+
private function upsertByCode(string $entityClass, string $code, callable $apply): object
{
$repo = $this->entityManager->getRepository($entityClass);
diff --git a/src/DataFixtures/AppFixtures.php b/src/DataFixtures/AppFixtures.php
index 260a894..f1f7544 100644
--- a/src/DataFixtures/AppFixtures.php
+++ b/src/DataFixtures/AppFixtures.php
@@ -20,7 +20,6 @@ class AppFixtures extends Fixture implements DependentFixtureInterface
return [
TransportFixtures::class,
ReferenceFixtures::class,
- SupplierFixtures::class,
UserFixtures::class,
];
}
diff --git a/src/DataFixtures/ReferenceFixtures.php b/src/DataFixtures/ReferenceFixtures.php
index 95e2af0..1fd8723 100644
--- a/src/DataFixtures/ReferenceFixtures.php
+++ b/src/DataFixtures/ReferenceFixtures.php
@@ -5,10 +5,13 @@ declare(strict_types=1);
namespace App\DataFixtures;
use App\Entity\Address;
+use App\Entity\BovineType;
use App\Entity\Building;
+use App\Entity\Customer;
use App\Entity\MerchandiseType;
use App\Entity\PelletType;
use App\Entity\ReceptionType;
+use App\Entity\ShipmentType;
use App\Entity\Supplier;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
@@ -17,6 +20,8 @@ class ReferenceFixtures extends Fixture
{
public function load(ObjectManager $manager): void
{
+ $addressIndex = [];
+
$merchandiseTypes = [
['label' => 'Foin', 'code' => 'FOIN'],
['label' => 'Paille', 'code' => 'PAILLE'],
@@ -69,6 +74,31 @@ class ReferenceFixtures extends Fixture
$manager->persist($receptionType);
}
+ $bovineTypes = [
+ ['label' => 'Limousine', 'code' => '34'],
+ ['label' => 'Charolaise', 'code' => '38'],
+ ['label' => 'Parthenaise', 'code' => '71'],
+ ];
+ foreach ($bovineTypes as $type) {
+ $bovineType = new BovineType()
+ ->setLabel($type['label'])
+ ->setCode($type['code'])
+ ;
+ $manager->persist($bovineType);
+ }
+
+ $shipmentTypes = [
+ ['label' => 'Bovin de boucherie', 'code' => 'BDB'],
+ ['label' => "Bovin d'équarrissage", 'code' => 'BE'],
+ ];
+ foreach ($shipmentTypes as $type) {
+ $shipmentType = new ShipmentType()
+ ->setLabel($type['label'])
+ ->setCode($type['code'])
+ ;
+ $manager->persist($shipmentType);
+ }
+
$suppliers = [
[
'name' => 'LIOT',
@@ -290,21 +320,129 @@ class ReferenceFixtures extends Fixture
;
foreach ($supplierData['addresses'] as $addressData) {
- $address = new Address()
- ->setLabel($addressData['label'])
- ->setStreet($addressData['street'])
- ->setStreet2($addressData['street2'])
- ->setPostalCode($addressData['postalCode'])
- ->setCity($addressData['city'])
- ->setCountryCode($addressData['countryCode'])
- ;
- $manager->persist($address);
+ $addressKey = sprintf('%s|%s', $addressData['label'], $addressData['postalCode']);
+ if (!isset($addressIndex[$addressKey])) {
+ $addressIndex[$addressKey] = new Address()
+ ->setLabel($addressData['label'])
+ ->setStreet($addressData['street'])
+ ->setStreet2($addressData['street2'])
+ ->setPostalCode($addressData['postalCode'])
+ ->setCity($addressData['city'])
+ ->setCountryCode($addressData['countryCode'])
+ ;
+ $manager->persist($addressIndex[$addressKey]);
+ }
+ $address = $addressIndex[$addressKey];
$supplier->getAddresses()->add($address);
}
$manager->persist($supplier);
}
+ $customers = [
+ [
+ 'name' => 'ARNAULT EURL',
+ 'phone' => '05.49.02.65.27',
+ 'email' => 'eurl.arnault86@orange.fr',
+ 'addresses' => [
+ [
+ 'label' => 'ARNAULT EURL',
+ 'street' => 'Moulin du Guéret',
+ 'street2' => 'B.P 30425',
+ 'postalCode' => '86100',
+ 'city' => 'Antran',
+ 'countryCode' => 'FR',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'COVILIM',
+ 'phone' => '05.55.30.03.10',
+ 'email' => 'sandra.robineaux@covilim.com',
+ 'addresses' => [
+ [
+ 'label' => 'COVILIM',
+ 'street' => 'Rue de Nexon',
+ 'street2' => null,
+ 'postalCode' => '87000',
+ 'city' => 'LIMOGES',
+ 'countryCode' => 'FR',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'Les producteurs de la marche (LPM)',
+ 'phone' => '05.55.63.04.53',
+ 'email' => 'f.legalliard@lpmcoop.fr',
+ 'addresses' => [
+ [
+ 'label' => 'Les producteurs de la marche (LPM)',
+ 'street' => 'Rue de Nexon',
+ 'street2' => null,
+ 'postalCode' => '87000',
+ 'city' => 'LIMOGES',
+ 'countryCode' => 'FR',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'LORTHOLARY BETAIL',
+ 'phone' => '05.49.52.77.10',
+ 'email' => 'contact86@lortholarybetail.com',
+ 'addresses' => [
+ [
+ 'label' => 'LORTHOLARY BETAIL',
+ 'street' => 'FERME DE GENIEC',
+ 'street2' => null,
+ 'postalCode' => '86550',
+ 'city' => 'MIGNALOUX BEAUVOIR',
+ 'countryCode' => 'FR',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'TERRENA',
+ 'phone' => '02.51.67.17.98',
+ 'email' => null,
+ 'addresses' => [
+ [
+ 'label' => 'TERRENA',
+ 'street' => 'La Blanchardière',
+ 'street2' => null,
+ 'postalCode' => '44522',
+ 'city' => 'MESANGER',
+ 'countryCode' => 'FR',
+ ],
+ ],
+ ],
+ ];
+
+ foreach ($customers as $customerData) {
+ $customer = new Customer()
+ ->setName($customerData['name'])
+ ->setPhone($customerData['phone'])
+ ->setEmail($customerData['email'])
+ ;
+
+ foreach ($customerData['addresses'] as $addressData) {
+ $addressKey = sprintf('%s|%s', $addressData['label'], $addressData['postalCode']);
+ if (!isset($addressIndex[$addressKey])) {
+ $addressIndex[$addressKey] = new Address()
+ ->setLabel($addressData['label'])
+ ->setStreet($addressData['street'])
+ ->setStreet2($addressData['street2'])
+ ->setPostalCode($addressData['postalCode'])
+ ->setCity($addressData['city'])
+ ->setCountryCode($addressData['countryCode'])
+ ;
+ $manager->persist($addressIndex[$addressKey]);
+ }
+ $customer->getAddresses()->add($addressIndex[$addressKey]);
+ }
+
+ $manager->persist($customer);
+ }
+
$manager->flush();
}
}
diff --git a/src/DataFixtures/TransportFixtures.php b/src/DataFixtures/TransportFixtures.php
index f14b9f9..1df4f94 100644
--- a/src/DataFixtures/TransportFixtures.php
+++ b/src/DataFixtures/TransportFixtures.php
@@ -15,11 +15,17 @@ class TransportFixtures extends Fixture
{
public function load(ObjectManager $manager): void
{
- $citerne = new Truck()->setName('Citerne');
- $porteur = new Truck()->setName('Porteur');
+ $citerne = new Truck()->setName('Citerne');
+ $porteur = new Truck()->setName('Porteur');
+ $plateau = new Truck()->setName('Plateau');
+ $remorque = new Truck()->setName('Remorque');
+ $benne = new Truck()->setName('Benne');
$manager->persist($citerne);
$manager->persist($porteur);
+ $manager->persist($plateau);
+ $manager->persist($remorque);
+ $manager->persist($benne);
$liot = new Carrier()
->setName('LIOT')
diff --git a/src/Entity/Customer.php b/src/Entity/Customer.php
index 286eb6b..9c430a7 100644
--- a/src/Entity/Customer.php
+++ b/src/Entity/Customer.php
@@ -47,13 +47,17 @@ class Customer
#[Groups(['shipment:read', 'customer:read'])]
private ?int $id = null;
- #[ORM\Column(length: 255)]
+ #[ORM\Column(length: 180)]
#[Groups(['customer:read', 'customer:write', 'shipment:read'])]
- private ?string $label = null;
+ private string $name = '';
- #[ORM\Column(length: 255)]
+ #[ORM\Column(length: 180, nullable: true)]
#[Groups(['customer:read', 'customer:write', 'shipment:read'])]
- private ?string $code = null;
+ private ?string $email = null;
+
+ #[ORM\Column(length: 40, nullable: true)]
+ #[Groups(['customer:read', 'customer:write', 'shipment:read'])]
+ private ?string $phone = null;
/**
* @var Collection
@@ -74,24 +78,40 @@ class Customer
return $this->id;
}
- public function getLabel(): ?string
+ public function getName(): string
{
- return $this->label;
+ return $this->name;
}
- public function setLabel(?string $label): void
+ public function setName(string $name): self
{
- $this->label = $label;
+ $this->name = $name;
+
+ return $this;
}
- public function getCode(): ?string
+ public function getEmail(): ?string
{
- return $this->code;
+ return $this->email;
}
- public function setCode(?string $code): void
+ public function setEmail(?string $email): self
{
- $this->code = $code;
+ $this->email = $email;
+
+ return $this;
+ }
+
+ public function getPhone(): ?string
+ {
+ return $this->phone;
+ }
+
+ public function setPhone(?string $phone): self
+ {
+ $this->phone = $phone;
+
+ return $this;
}
public function getAddresses(): Collection