feat: index Meilisearch customer_contact + sync contacts + onglet NDD

MeilisearchService :
- Nouvel index customer_contact (searchable: firstName, lastName, fullName,
  email, phone, role / filterable: customerId, isBillingEmail)
- indexContact(), removeContact(), searchContacts()
- serializeContact() avec tous les champs

SyncController :
- Route POST /admin/sync/contacts : sync tous les CustomerContact
  dans Meilisearch (setupIndexes + indexContact par contact)
- totalContacts ajouté dans index() via EntityManager

Template admin/sync/index.html.twig :
- Bloc "Contacts" violet avec compteur et bouton Synchroniser

Template admin/clients/show.html.twig :
- Nouvel onglet "Noms de domaine" : table des Domain liés au client
  (fqdn, registrar, Cloudflare, gestion, facturation, expiration)
- Expiration colorée : rouge si expiré, jaune si < 30j, gris sinon

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-04-04 18:00:12 +02:00
parent bf4a0fcb38
commit 619b068d9d
6 changed files with 172 additions and 3 deletions

View File

@@ -139,8 +139,12 @@ class AdminControllersTest extends TestCase
$prepo = $this->createStub(PriceAutomaticRepository::class);
$srepo = $this->createStub(StripeWebhookSecretRepository::class);
$srepo->method('findAll')->willReturn([]);
$contactRepo = $this->createStub(\Doctrine\ORM\EntityRepository::class);
$contactRepo->method('count')->willReturn(0);
$em = $this->createStub(\Doctrine\ORM\EntityManagerInterface::class);
$em->method('getRepository')->willReturn($contactRepo);
$controller = $this->createMockController(SyncController::class);
$response = $controller->index($crepo, $rrepo, $prepo, $srepo);
$response = $controller->index($crepo, $rrepo, $prepo, $srepo, $em);
$this->assertInstanceOf(Response::class, $response);
}

View File

@@ -94,7 +94,12 @@ class SyncControllerTest extends TestCase
$controller = new SyncController();
$controller->setContainer($this->createContainer());
$response = $controller->index($customerRepo, $revendeurRepo, $priceRepo, $secretRepo);
$contactRepo = $this->createStub(\Doctrine\ORM\EntityRepository::class);
$contactRepo->method('count')->willReturn(0);
$em = $this->createStub(\Doctrine\ORM\EntityManagerInterface::class);
$em->method('getRepository')->willReturn($contactRepo);
$response = $controller->index($customerRepo, $revendeurRepo, $priceRepo, $secretRepo, $em);
$this->assertSame(200, $response->getStatusCode());
}