feat: ligne info services sous chaque client dans /admin/clients
Sous chaque ligne client, une ligne compacte affiche : - Raison sociale, SIRET, type entreprise (si disponibles) - Sites : nombre (placeholder, 0 pour l'instant) - NDD : nombre de domaines liés au client - Emails : nombre de DomainEmail liés aux domaines du client - Sign : check vert/rouge (Esy-Signature activé) - News : check vert/rouge (Esy-Mailer/Newsletter activé) - Mail : check vert/rouge (au moins 1 email Esy-Mail) - Statut paiement : OK (vert) ou IMPAYEE (rouge avec nombre) ClientsController : - index() reçoit EntityManagerInterface pour requêter Domain/DomainEmail - buildCustomersInfo() : construit les compteurs par client (domains, emails, esyMail depuis DomainEmail count > 0) - Les flags esySign/esyNewsletter/unpaid/sites seront branchés quand les entités correspondantes existeront Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,12 +23,14 @@ use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
class ClientsController extends AbstractController
|
||||
{
|
||||
#[Route('', name: 'index')]
|
||||
public function index(CustomerRepository $customerRepository): Response
|
||||
public function index(CustomerRepository $customerRepository, EntityManagerInterface $em): Response
|
||||
{
|
||||
$customers = $customerRepository->findBy([], ['createdAt' => 'DESC']);
|
||||
$customersInfo = $this->buildCustomersInfo($customers, $em);
|
||||
|
||||
return $this->render('admin/clients/index.html.twig', [
|
||||
'customers' => $customers,
|
||||
'customersInfo' => $customersInfo,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -83,6 +85,38 @@ class ClientsController extends AbstractController
|
||||
return $this->render('admin/clients/create.html.twig');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<Customer> $customers
|
||||
*
|
||||
* @return array<int, array{sites: int, domains: int, emails: int, esySign: bool, esyNewsletter: bool, esyMail: bool, unpaid: int}>
|
||||
*/
|
||||
private function buildCustomersInfo(array $customers, EntityManagerInterface $em): array
|
||||
{
|
||||
$domainRepo = $em->getRepository(\App\Entity\Domain::class);
|
||||
$emailRepo = $em->getRepository(\App\Entity\DomainEmail::class);
|
||||
$info = [];
|
||||
|
||||
foreach ($customers as $customer) {
|
||||
$domains = $domainRepo->findBy(['customer' => $customer]);
|
||||
$emailCount = 0;
|
||||
foreach ($domains as $domain) {
|
||||
$emailCount += $emailRepo->count(['domain' => $domain]);
|
||||
}
|
||||
|
||||
$info[$customer->getId()] = [
|
||||
'sites' => 0,
|
||||
'domains' => \count($domains),
|
||||
'emails' => $emailCount,
|
||||
'esySign' => false,
|
||||
'esyNewsletter' => false,
|
||||
'esyMail' => $emailCount > 0,
|
||||
'unpaid' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
private function populateCustomerData(Request $request, Customer $customer): void
|
||||
{
|
||||
$customer->setFirstName(trim($request->request->getString('firstName')));
|
||||
|
||||
@@ -44,30 +44,31 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for customer in customers %}
|
||||
<tr class="border-b border-white/20 hover:bg-white/50">
|
||||
<td class="px-4 py-3">
|
||||
{% set info = customersInfo[customer.id] ?? {} %}
|
||||
<tr class="hover:bg-white/50">
|
||||
<td class="px-4 pt-3 pb-1">
|
||||
<span class="font-bold">{{ customer.fullName }}</span>
|
||||
{% if customer.raisonSociale and customer.firstName %}
|
||||
<span class="text-[10px] text-gray-400 ml-1">{{ customer.firstName }} {{ customer.lastName }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-xs font-mono">{{ customer.email ?? customer.user.email }}</td>
|
||||
<td class="px-4 py-3">
|
||||
<td class="px-4 pt-3 pb-1 text-xs font-mono">{{ customer.email ?? customer.user.email }}</td>
|
||||
<td class="px-4 pt-3 pb-1">
|
||||
{% if customer.typeCompany %}
|
||||
<span class="px-2 py-0.5 bg-gray-100 text-gray-700 font-bold uppercase text-[10px]">{{ customer.typeCompany }}</span>
|
||||
{% else %}
|
||||
<span class="text-gray-400">—</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-xs font-mono">{{ customer.siret ?? '—' }}</td>
|
||||
<td class="px-4 py-3 text-center">
|
||||
<td class="px-4 pt-3 pb-1 text-xs font-mono">{{ customer.siret ?? '—' }}</td>
|
||||
<td class="px-4 pt-3 pb-1 text-center">
|
||||
{% if customer.stripeCustomerId %}
|
||||
<span class="px-2 py-0.5 bg-green-500/20 text-green-700 font-bold uppercase text-[10px] rounded">Lie</span>
|
||||
{% else %}
|
||||
<span class="px-2 py-0.5 bg-gray-100 text-gray-500 font-bold uppercase text-[10px]">Non</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-center">
|
||||
<td class="px-4 pt-3 pb-1 text-center">
|
||||
{% if customer.state == 'active' %}
|
||||
<span class="px-2 py-0.5 bg-green-500/20 text-green-700 font-bold uppercase text-[10px] rounded">Actif</span>
|
||||
{% elseif customer.state == 'suspended' %}
|
||||
@@ -78,8 +79,8 @@
|
||||
<span class="px-2 py-0.5 bg-red-500/20 text-red-700 font-bold uppercase text-[10px] rounded">Desactive</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-xs text-gray-500">{{ customer.createdAt|date('d/m/Y') }}</td>
|
||||
<td class="px-4 py-3 text-center">
|
||||
<td class="px-4 pt-3 pb-1 text-xs text-gray-500">{{ customer.createdAt|date('d/m/Y') }}</td>
|
||||
<td class="px-4 pt-3 pb-1 text-center">
|
||||
<div class="flex items-center justify-center gap-2">
|
||||
{% if not customer.isPendingDelete %}
|
||||
<form method="post" action="{{ path('app_admin_clients_toggle', {id: customer.id}) }}">
|
||||
@@ -98,6 +99,45 @@
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{# Ligne info services #}
|
||||
<tr class="border-b border-white/20">
|
||||
<td colspan="8" class="px-4 pb-3 pt-0">
|
||||
<div class="flex flex-wrap items-center gap-x-4 gap-y-1 text-[10px]">
|
||||
{% if customer.raisonSociale %}
|
||||
<span class="text-gray-400">{{ customer.raisonSociale }}</span>
|
||||
<span class="text-gray-300">|</span>
|
||||
{% endif %}
|
||||
{% if customer.siret %}
|
||||
<span class="text-gray-400 font-mono">{{ customer.siret }}</span>
|
||||
<span class="text-gray-300">|</span>
|
||||
{% endif %}
|
||||
{% if customer.typeCompany %}
|
||||
<span class="text-gray-400 uppercase font-bold">{{ customer.typeCompany }}</span>
|
||||
<span class="text-gray-300">|</span>
|
||||
{% endif %}
|
||||
|
||||
<span class="font-bold text-gray-500">Sites : {{ info.sites ?? 0 }}</span>
|
||||
<span class="text-gray-300">|</span>
|
||||
<span class="font-bold text-gray-500">NDD : {{ info.domains ?? 0 }}</span>
|
||||
<span class="text-gray-300">|</span>
|
||||
<span class="font-bold text-gray-500">Emails : {{ info.emails ?? 0 }}</span>
|
||||
<span class="text-gray-300">|</span>
|
||||
|
||||
{# Services checks #}
|
||||
<span class="font-bold" title="Esy-Signature">Sign {% if info.esySign ?? false %}<span class="text-green-600">✓</span>{% else %}<span class="text-red-500">✗</span>{% endif %}</span>
|
||||
<span class="font-bold" title="Esy-Mailer">News {% if info.esyNewsletter ?? false %}<span class="text-green-600">✓</span>{% else %}<span class="text-red-500">✗</span>{% endif %}</span>
|
||||
<span class="font-bold" title="Esy-Mail">Mail {% if info.esyMail ?? false %}<span class="text-green-600">✓</span>{% else %}<span class="text-red-500">✗</span>{% endif %}</span>
|
||||
|
||||
<span class="text-gray-300">|</span>
|
||||
{# Statut paiement #}
|
||||
{% if (info.unpaid ?? 0) > 0 %}
|
||||
<span class="px-1.5 py-0.5 bg-red-500/20 text-red-700 font-bold uppercase rounded">Impayee ({{ info.unpaid }})</span>
|
||||
{% else %}
|
||||
<span class="px-1.5 py-0.5 bg-green-500/20 text-green-700 font-bold uppercase rounded">OK</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="8" class="px-4 py-8 text-center text-gray-400 font-bold">Aucun client.</td>
|
||||
|
||||
@@ -57,8 +57,10 @@ class ClientsControllerTest extends TestCase
|
||||
$repo = $this->createStub(CustomerRepository::class);
|
||||
$repo->method('findBy')->willReturn([]);
|
||||
|
||||
$em = $this->createStub(EntityManagerInterface::class);
|
||||
|
||||
$controller = $this->createController();
|
||||
$response = $controller->index($repo);
|
||||
$response = $controller->index($repo, $em);
|
||||
|
||||
$this->assertInstanceOf(Response::class, $response);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user