✨ feat(dashboard): Affiche des indicateurs clés et des alertes sur le tableau de bord.
🐛 fix(server.twig): Corrige le lien cassé du bouton "Ajouter un nouveau serveur". ♻️ refactor(ServerController): Intègre le client OVH pour récupérer les informations des serveurs dédiés. ✨ feat(Ovh): Ajoute un service OVH pour récupérer les informations des serveurs.
This commit is contained in:
@@ -23,7 +23,7 @@ class DashboardController extends AbstractController
|
||||
CustomerAdvertPaymentRepository $customerAdvertPaymentRepository,
|
||||
CustomerDevisRepository $customerDevisRepository,
|
||||
SignClient $signClient,
|
||||
UploaderHelper $uploaderHelper
|
||||
UploaderHelper $uploaderHelper,
|
||||
): Response
|
||||
{
|
||||
$invoiceList = [];
|
||||
@@ -31,6 +31,7 @@ class DashboardController extends AbstractController
|
||||
$devisList = [];
|
||||
$remaining_amount = 0;
|
||||
$services = [];
|
||||
$servers = [];
|
||||
if(in_array("ROLE_CUSTOMER",$this->getUser()->getRoles())) {
|
||||
/** @var Customer $customer */
|
||||
$customer = $this->getUser()->getCustomers()[0];
|
||||
@@ -94,6 +95,8 @@ class DashboardController extends AbstractController
|
||||
'status' => 'actif'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -103,6 +106,7 @@ class DashboardController extends AbstractController
|
||||
'devisList' => $devisList,
|
||||
'active_services' => $services,
|
||||
'remaining_amount' => $remaining_amount,
|
||||
'servers' => $servers,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Controller\Artemis\Infra;
|
||||
|
||||
use App\Service\Google\ComputeEngineClient;
|
||||
use App\Service\Ovh\Client;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@@ -11,13 +12,17 @@ use Symfony\Component\Routing\Attribute\Route;
|
||||
class ServerController extends AbstractController
|
||||
{
|
||||
#[Route(path: '/artemis/infra/server',name: 'artemis_infrastructure_server')]
|
||||
public function artemis(Request $request,ComputeEngineClient $computeEngineClient): Response
|
||||
public function artemis(Request $request,ComputeEngineClient $computeEngineClient,Client $client): Response
|
||||
{
|
||||
|
||||
|
||||
$lists = [];
|
||||
foreach ($computeEngineClient->list() as $instance) {
|
||||
$lists[] = $computeEngineClient->detail($instance);
|
||||
}
|
||||
foreach ($client->servers() as $instance) {
|
||||
$lists[] = $client->detail($instance);
|
||||
}
|
||||
return $this->render('artemis/infra/server.twig',[
|
||||
'lists' => $lists
|
||||
]);
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
|
||||
namespace App\Service\Ovh;
|
||||
|
||||
use App\Entity\Compute;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Ovh\Api;
|
||||
|
||||
class Client
|
||||
{
|
||||
private Api $ovhClient;
|
||||
|
||||
public function __construct()
|
||||
public function __construct(private readonly EntityManagerInterface $em)
|
||||
{
|
||||
$this->ovhClient = new Api(
|
||||
$_ENV['OVH_KEY'] ?? '',
|
||||
@@ -46,9 +48,39 @@ class Client
|
||||
}
|
||||
}
|
||||
|
||||
public function nddExpired()
|
||||
|
||||
public function servers()
|
||||
{
|
||||
$domain = $this->ovhClient->get('/domain');
|
||||
dd($domain);
|
||||
$list =[];
|
||||
$servers = $this->ovhClient->get('/dedicated/server');
|
||||
foreach ($servers as $server) {
|
||||
$compute = $this->em->getRepository(Compute::class)
|
||||
->findOneBy(['instanceId' => $server]);
|
||||
|
||||
$detail = $this->ovhClient->get('/dedicated/server/' . $server);
|
||||
if (!$compute instanceof Compute) {
|
||||
$compute = new Compute();
|
||||
$compute->setInstanceId("ovh|".$server);
|
||||
$compute->setZone($detail['region']."|".$detail['rack']);
|
||||
$compute->setInternalIp($detail['ip']);
|
||||
$compute->setExternalIp($detail['ip']);
|
||||
$compute->setStatus('down');
|
||||
}
|
||||
$this->em->persist($compute);
|
||||
$list[] = $compute;
|
||||
}
|
||||
$this->em->flush();
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function detail(Compute $compute)
|
||||
{
|
||||
$c = explode("|",$compute->getInstanceId());
|
||||
$detail = $this->ovhClient->get('/dedicated/server/' . $c[1]);
|
||||
$compute->setStatus($detail['state'] == "ok"?"RUNNING":"DOWN");
|
||||
$compute->name = $c[1];
|
||||
$compute->type = $c[0];
|
||||
return $compute;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,6 +155,187 @@
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
|
||||
|
||||
<div class="p-6 rounded-lg shadow-xl bg-white dark:bg-gray-800">
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">CA En Cours</p>
|
||||
<p class="text-2xl font-bold text-green-500">45 230 €</p>
|
||||
</div>
|
||||
|
||||
<div class="p-6 rounded-lg shadow-xl bg-white dark:bg-gray-800">
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">CA Prévu</p>
|
||||
<p class="text-2xl font-bold text-blue-400">62 500 €</p>
|
||||
</div>
|
||||
|
||||
<div class="p-6 rounded-lg shadow-xl bg-white dark:bg-gray-800">
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">Total Impayés</p>
|
||||
<p class="text-2xl font-bold text-red-500">8 120 €</p>
|
||||
</div>
|
||||
|
||||
<div class="p-6 rounded-lg shadow-xl bg-white dark:bg-gray-800 border-l-4 border-yellow-500">
|
||||
<p class="text-sm font-medium text-gray-500 dark:text-gray-400">Écart / Objectif Prévu</p>
|
||||
<p class="text-2xl font-bold text-yellow-500">
|
||||
- 17 270 €
|
||||
</p>
|
||||
<p class="text-xs text-gray-400 dark:text-gray-500 mt-1">
|
||||
(Reste à atteindre ce mois)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
|
||||
|
||||
<div class="p-6 rounded-lg shadow-xl bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100">
|
||||
<h2 class="text-xl font-semibold mb-4">🔔 Domaines à Renouveler</h2>
|
||||
<ul class="space-y-2">
|
||||
<li class="flex justify-between text-sm">
|
||||
<span>mondomaine.com</span>
|
||||
<span class="text-red-500 font-medium">J-7</span>
|
||||
</li>
|
||||
<li class="flex justify-between text-sm">
|
||||
<span>autre-site.fr</span>
|
||||
<span class="text-orange-400 font-medium">J-30</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="p-6 rounded-lg shadow-xl bg-white dark:bg-gray-800">
|
||||
<h2 class="text-xl font-semibold mb-4 text-gray-900 dark:text-gray-100">📑 Factures à Valider</h2>
|
||||
<div class="border-l-4 border-yellow-500 bg-yellow-50 dark:bg-yellow-900/50 p-3">
|
||||
<p class="text-sm font-medium text-gray-900 dark:text-yellow-100">Facture #2025-001 (Client A)</p>
|
||||
<p class="text-xs text-gray-600 dark:text-gray-300">Montant : 1 200 € - En attente</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-4 mb-6">
|
||||
|
||||
<div class="flex flex-col items-center p-3 rounded-lg shadow-md bg-white dark:bg-gray-800 border-l-4 border-green-500">
|
||||
<span class="text-sm font-semibold text-gray-900 dark:text-white truncate w-full text-center">WEB-PROD-01</span>
|
||||
<span class="mt-1 px-2 text-xs font-bold text-white bg-green-500 rounded">OK</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-center p-3 rounded-lg shadow-md bg-white dark:bg-gray-800 border-l-4 border-yellow-500">
|
||||
<span class="text-sm font-semibold text-gray-900 dark:text-white truncate w-full text-center">DB-MAIN-02</span>
|
||||
<span class="mt-1 px-2 text-xs font-bold text-gray-900 bg-yellow-500 rounded">ALERTE</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-center p-3 rounded-lg shadow-md bg-white dark:bg-gray-800 border-l-4 border-red-500">
|
||||
<span class="text-sm font-semibold text-gray-900 dark:text-white truncate w-full text-center">STAGING-03</span>
|
||||
<span class="mt-1 px-2 text-xs font-bold text-white bg-red-500 rounded">DOWN</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-center p-3 rounded-lg shadow-md bg-white dark:bg-gray-800 border-l-4 border-green-500">
|
||||
<span class="text-sm font-semibold text-gray-900 dark:text-white truncate w-full text-center">MAIL-04</span>
|
||||
<span class="mt-1 px-2 text-xs font-bold text-white bg-green-500 rounded">OK</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-center p-3 rounded-lg shadow-md bg-white dark:bg-gray-800 border-l-4 border-orange-500">
|
||||
<span class="text-sm font-semibold text-gray-900 dark:text-white truncate w-full text-center">BACKUP-05</span>
|
||||
<span class="mt-1 px-2 text-xs font-bold text-white bg-orange-500 rounded">LATENCE</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-center p-3 rounded-lg shadow-md bg-white dark:bg-gray-800 border-l-4 border-green-500">
|
||||
<span class="text-sm font-semibold text-gray-900 dark:text-white truncate w-full text-center">DEV-TEST</span>
|
||||
<span class="mt-1 px-2 text-xs font-bold text-white bg-green-500 rounded">OK</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
|
||||
|
||||
<div class="p-6 rounded-lg shadow-xl bg-white dark:bg-gray-800 border-l-4 border-orange-500">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<p class="text-sm font-medium text-gray-500 dark:text-gray-400">Ratio Coût Infra / CA</p>
|
||||
<p class="text-2xl font-bold text-orange-500 mt-1">28.5%</p>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<p class="text-sm text-red-500 font-semibold flex items-center">
|
||||
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 10l7-7m0 0l7 7m-7-7v18"></path></svg>
|
||||
+0.8 pt
|
||||
</p>
|
||||
<p class="text-xs text-gray-400 dark:text-gray-500">vs Mois Précédent</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-6 rounded-lg shadow-xl bg-white dark:bg-gray-800 border-l-4 border-teal-500">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<p class="text-sm font-medium text-gray-500 dark:text-gray-400">Ratio Coût Salarial / CA</p>
|
||||
<p class="text-2xl font-bold text-teal-500 mt-1">35.0%</p>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<p class="text-sm text-green-500 font-semibold flex items-center">
|
||||
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path></svg>
|
||||
-0.5 pt
|
||||
</p>
|
||||
<p class="text-xs text-gray-400 dark:text-gray-500">vs Mois Précédent</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-6 rounded-lg shadow-xl bg-white dark:bg-gray-800">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<p class="text-sm font-medium text-gray-500 dark:text-gray-400">Coût Google Cloud (Mois)</p>
|
||||
<p class="text-2xl font-bold text-blue-500 mt-1">1 850,00 €</p>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<p class="text-sm text-red-500 font-semibold flex items-center">
|
||||
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 10l7-7m0 0l7 7m-7-7v18"></path></svg>
|
||||
+3.5%
|
||||
</p>
|
||||
<p class="text-xs text-gray-400 dark:text-gray-500">vs Mois Précédent</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-6 rounded-lg shadow-xl bg-white dark:bg-gray-800">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<p class="text-sm font-medium text-gray-500 dark:text-gray-400">Coût OVH (Mois)</p>
|
||||
<p class="text-2xl font-bold text-purple-500 mt-1">425,50 €</p>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<p class="text-sm text-green-500 font-semibold flex items-center">
|
||||
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path></svg>
|
||||
-1.2%
|
||||
</p>
|
||||
<p class="text-xs text-gray-400 dark:text-gray-500">vs Mois Précédent</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
|
||||
|
||||
<div class="md:col-span-2 p-6 rounded-lg shadow-xl bg-white dark:bg-gray-800 border-l-4 border-green-500">
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
<p class="text-sm font-medium text-gray-500 dark:text-gray-400">Statut de Rentabilité Globale</p>
|
||||
<p class="text-3xl font-bold text-green-500 mt-1">
|
||||
🟢 RENTRABLE
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">Total Coûts / CA :</p>
|
||||
<p class="text-xl font-bold text-green-500">63.5%</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-xs text-gray-400 dark:text-gray-500 mt-3">
|
||||
(Coût Infra 28.5% + Coût Salarial 35.0%)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="md:col-span-2">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# PETIT SCRIPT JAVASCRIPT POUR FAIRE FONCTIONNER LES ONGLETS #}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<h2 class="text-3xl font-semibold text-gray-800 dark:text-gray-200">Liste des Serveurs</h2>
|
||||
<div>
|
||||
<a h class="px-4 py-2 bg-blue-600 text-white font-medium rounded-md shadow-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-900">
|
||||
<a href="" class="px-4 py-2 bg-blue-600 text-white font-medium rounded-md shadow-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-900">
|
||||
+ Ajouter un nouveau serveur
|
||||
</a>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user