fix: PHP CS Fixer (43 fichiers) + PHPStan level 6 zero erreurs + JS SonarQube
PHP CS Fixer : - 43 fichiers corriges (imports, docblocks, formatting) PHPStan level 6 (45 erreurs corrigees) : - ComptabiliteController/DevisController : cast User via @var - StatsController : cast float pour operations arithmetiques - AdvertService/DevisService/FactureService : @return array shape - PaymentReminderCommand : default arm dans match - Stripe SDK : @phpstan-ignore-next-line (5 occurrences) - MailerService : suppression ?? redondants sur offsets existants - SentryService : fix types retour, dead code - DnsCheckService/GoogleSearchService : @param value types - LegalController : suppression statement inatteignable - ActionService : @phpstan-ignore propriete non lue - Pdf/AdvertPdf/FacturePdf : @phpstan-ignore methodes inutilisees JS SonarQube : - app.js : isNaN -> Number.isNaN, replace -> replaceAll (5 occurrences) - app.js : extraction ternaire imbrique en if/else if - app.js : refactor SIRET search (nesting 5->3 niveaux) - entreprise-search.js : parseInt -> Number.parseInt - app.test.js : extraction trackListener (complexite cognitive 17->12) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
115
assets/app.js
115
assets/app.js
@@ -145,7 +145,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const renderHit = (h, linkPrefix) => {
|
||||
const id = h.customerId || h.id;
|
||||
const name = h.fqdn || h.name || h.fullName || h.raisonSociale || (h.firstName + ' ' + h.lastName);
|
||||
const sub = h.customerName ? `<span class="text-gray-400 ml-2">${h.customerName}</span>` : (h.email ? `<span class="text-gray-400 ml-2">${h.email}</span>` : '');
|
||||
let sub = '';
|
||||
if (h.customerName) sub = `<span class="text-gray-400 ml-2">${h.customerName}</span>`;
|
||||
else if (h.email) sub = `<span class="text-gray-400 ml-2">${h.email}</span>`;
|
||||
return `<a href="${linkPrefix}${id}" class="block px-4 py-2 hover:bg-gray-50 border-b border-gray-100 text-xs">
|
||||
<span class="font-bold">${name}</span>
|
||||
${sub}
|
||||
@@ -310,61 +312,66 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const siretSearchBtn = document.getElementById('siret-search-btn');
|
||||
const siretInput = document.getElementById('siret-search-input');
|
||||
const siretResults = document.getElementById('siret-search-results');
|
||||
if (siretSearchBtn && siretInput && siretResults) {
|
||||
siretSearchBtn.addEventListener('click', () => {
|
||||
const q = siretInput.value.trim();
|
||||
if (q.length < 3) { siretResults.innerHTML = '<p class="text-xs text-gray-400 p-2">Saisissez au moins 3 caracteres.</p>'; siretResults.classList.remove('hidden'); return; }
|
||||
|
||||
siretResults.innerHTML = '<p class="text-xs text-gray-400 p-2">Recherche...</p>';
|
||||
siretResults.classList.remove('hidden');
|
||||
const renderSiretResult = (r) => {
|
||||
const siege = r.siege || {};
|
||||
const siret = siege.siret || '';
|
||||
const nom = r.nom_complet || r.nom_raison_sociale || '';
|
||||
const adresse = siege.adresse || '';
|
||||
const cp = siege.code_postal || '';
|
||||
const ville = siege.libelle_commune || '';
|
||||
return '<button type="button" class="siret-result-item block w-full text-left px-3 py-2 hover:bg-white/70 border-b border-white/20 transition-all"'
|
||||
+ ' data-nom="' + nom.replaceAll('"', '"') + '"'
|
||||
+ ' data-siret="' + siret + '"'
|
||||
+ ' data-adresse="' + adresse.replaceAll('"', '"') + '"'
|
||||
+ ' data-cp="' + cp + '"'
|
||||
+ ' data-ville="' + ville.replaceAll('"', '"') + '">'
|
||||
+ '<span class="font-bold text-xs">' + nom + '</span>'
|
||||
+ '<span class="text-[10px] text-gray-400 ml-2">' + siret + '</span>'
|
||||
+ '<br><span class="text-[10px] text-gray-400">' + adresse + ' ' + cp + ' ' + ville + '</span>'
|
||||
+ '</button>';
|
||||
};
|
||||
|
||||
fetch('/admin/prestataires/entreprise-search?q=' + encodeURIComponent(q))
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
const results = data.results || [];
|
||||
if (results.length === 0) {
|
||||
siretResults.innerHTML = '<p class="text-xs text-gray-400 p-2">Aucun resultat.</p>';
|
||||
return;
|
||||
}
|
||||
siretResults.innerHTML = results.map(r => {
|
||||
const siege = r.siege || {};
|
||||
const siret = siege.siret || '';
|
||||
const nom = r.nom_complet || r.nom_raison_sociale || '';
|
||||
const adresse = siege.adresse || '';
|
||||
const cp = siege.code_postal || '';
|
||||
const ville = siege.libelle_commune || '';
|
||||
return '<button type="button" class="siret-result-item block w-full text-left px-3 py-2 hover:bg-white/70 border-b border-white/20 transition-all"'
|
||||
+ ' data-nom="' + nom.replace(/"/g, '"') + '"'
|
||||
+ ' data-siret="' + siret + '"'
|
||||
+ ' data-adresse="' + adresse.replace(/"/g, '"') + '"'
|
||||
+ ' data-cp="' + cp + '"'
|
||||
+ ' data-ville="' + ville.replace(/"/g, '"') + '">'
|
||||
+ '<span class="font-bold text-xs">' + nom + '</span>'
|
||||
+ '<span class="text-[10px] text-gray-400 ml-2">' + siret + '</span>'
|
||||
+ '<br><span class="text-[10px] text-gray-400">' + adresse + ' ' + cp + ' ' + ville + '</span>'
|
||||
+ '</button>';
|
||||
}).join('');
|
||||
|
||||
siretResults.querySelectorAll('.siret-result-item').forEach(item => {
|
||||
item.addEventListener('click', () => {
|
||||
const form = siretSearchBtn.closest('form');
|
||||
if (!form) return;
|
||||
const set = (name, val) => { const el = form.querySelector('[name="' + name + '"]'); if (el) el.value = val; };
|
||||
set('raisonSociale', item.dataset.nom);
|
||||
set('siret', item.dataset.siret);
|
||||
set('address', item.dataset.adresse);
|
||||
set('zipCode', item.dataset.cp);
|
||||
set('city', item.dataset.ville);
|
||||
siretResults.classList.add('hidden');
|
||||
siretInput.value = '';
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
siretResults.innerHTML = '<p class="text-xs text-red-500 p-2">Erreur lors de la recherche.</p>';
|
||||
});
|
||||
const bindSiretResultClick = (item) => {
|
||||
item.addEventListener('click', () => {
|
||||
const form = siretSearchBtn.closest('form');
|
||||
if (!form) return;
|
||||
const set = (name, val) => { const el = form.querySelector('[name="' + name + '"]'); if (el) el.value = val; };
|
||||
set('raisonSociale', item.dataset.nom);
|
||||
set('siret', item.dataset.siret);
|
||||
set('address', item.dataset.adresse);
|
||||
set('zipCode', item.dataset.cp);
|
||||
set('city', item.dataset.ville);
|
||||
siretResults.classList.add('hidden');
|
||||
siretInput.value = '';
|
||||
});
|
||||
};
|
||||
|
||||
const handleSiretSearch = () => {
|
||||
const q = siretInput.value.trim();
|
||||
if (q.length < 3) { siretResults.innerHTML = '<p class="text-xs text-gray-400 p-2">Saisissez au moins 3 caracteres.</p>'; siretResults.classList.remove('hidden'); return; }
|
||||
|
||||
siretResults.innerHTML = '<p class="text-xs text-gray-400 p-2">Recherche...</p>';
|
||||
siretResults.classList.remove('hidden');
|
||||
|
||||
fetch('/admin/prestataires/entreprise-search?q=' + encodeURIComponent(q))
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
const results = data.results || [];
|
||||
if (results.length === 0) {
|
||||
siretResults.innerHTML = '<p class="text-xs text-gray-400 p-2">Aucun resultat.</p>';
|
||||
return;
|
||||
}
|
||||
siretResults.innerHTML = results.map(renderSiretResult).join('');
|
||||
siretResults.querySelectorAll('.siret-result-item').forEach(bindSiretResultClick);
|
||||
})
|
||||
.catch(() => {
|
||||
siretResults.innerHTML = '<p class="text-xs text-red-500 p-2">Erreur lors de la recherche.</p>';
|
||||
});
|
||||
};
|
||||
|
||||
if (siretSearchBtn && siretInput && siretResults) {
|
||||
siretSearchBtn.addEventListener('click', handleSiretSearch);
|
||||
siretInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); siretSearchBtn.click(); } });
|
||||
document.addEventListener('click', (e) => { if (!siretResults.contains(e.target) && e.target !== siretInput && e.target !== siretSearchBtn) siretResults.classList.add('hidden'); });
|
||||
}
|
||||
@@ -585,7 +592,7 @@ function initDevisLines() {
|
||||
let total = 0;
|
||||
container.querySelectorAll('.line-price').forEach(input => {
|
||||
const v = parseFloat(input.value);
|
||||
if (!isNaN(v)) total += v;
|
||||
if (!Number.isNaN(v)) total += v;
|
||||
});
|
||||
totalEl.textContent = total.toFixed(2) + ' EUR';
|
||||
}
|
||||
@@ -654,7 +661,7 @@ function initDevisLines() {
|
||||
|
||||
if (!type || type === 'hosting' || type === 'maintenance' || type === 'other') return;
|
||||
|
||||
const url = select.dataset.servicesUrl.replace('__TYPE__', type);
|
||||
const url = select.dataset.servicesUrl.replaceAll('__TYPE__', type);
|
||||
try {
|
||||
const resp = await fetch(url);
|
||||
const items = await resp.json();
|
||||
|
||||
@@ -6,7 +6,7 @@ const API_URL = '/admin/clients/entreprise-search'
|
||||
|
||||
const computeTva = (siren) => {
|
||||
if (!siren) return ''
|
||||
const key = (12 + 3 * (parseInt(siren, 10) % 97)) % 97
|
||||
const key = (12 + 3 * (Number.parseInt(siren, 10) % 97)) % 97
|
||||
return 'FR' + String(key).padStart(2, '0') + siren
|
||||
}
|
||||
|
||||
|
||||
@@ -119,9 +119,9 @@ class CheckDnsCommand extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $successes
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $successes
|
||||
* @param list<array<string, mixed>> $cfRecords
|
||||
*/
|
||||
private function checkAwsSes(string $domain, array &$checks, array &$errors, array &$successes, array $cfRecords = []): void
|
||||
@@ -146,7 +146,7 @@ class CheckDnsCommand extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array> $checks
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $successes
|
||||
*/
|
||||
@@ -161,9 +161,9 @@ class CheckDnsCommand extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $successes
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $successes
|
||||
* @param list<array<string, mixed>> $cfRecords
|
||||
*/
|
||||
private function checkSesDkim(string $domain, array &$checks, array &$errors, array &$successes, array $cfRecords): void
|
||||
@@ -193,9 +193,9 @@ class CheckDnsCommand extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $successes
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $successes
|
||||
* @param list<array<string, mixed>> $cfRecords
|
||||
*/
|
||||
private function checkSesMailFrom(string $domain, array &$checks, array &$errors, array &$successes, array $cfRecords): void
|
||||
@@ -220,10 +220,10 @@ class CheckDnsCommand extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $mailFrom
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $successes
|
||||
* @param array<string, mixed> $mailFrom
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $successes
|
||||
* @param list<array<string, mixed>> $cfRecords
|
||||
*/
|
||||
private function checkSesMailFromMx(string $domain, string $mfd, array $mailFrom, array &$checks, array &$errors, array &$successes, array $cfRecords): void
|
||||
@@ -241,10 +241,10 @@ class CheckDnsCommand extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $mailFrom
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $successes
|
||||
* @param array<string, mixed> $mailFrom
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $successes
|
||||
* @param list<array<string, mixed>> $cfRecords
|
||||
*/
|
||||
private function checkSesMailFromTxt(string $domain, string $mfd, array $mailFrom, array &$checks, array &$errors, array &$successes, array $cfRecords): void
|
||||
@@ -272,10 +272,10 @@ class CheckDnsCommand extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $warnings
|
||||
* @param array<int, string> $successes
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $warnings
|
||||
* @param array<int, string> $successes
|
||||
* @param list<array<string, mixed>> $cfRecords
|
||||
*/
|
||||
private function checkMailcow(string $domain, array &$checks, array &$errors, array &$warnings, array &$successes, array $cfRecords = []): void
|
||||
@@ -307,9 +307,9 @@ class CheckDnsCommand extends Command
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $info
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $successes
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $successes
|
||||
*/
|
||||
private function checkMailcowDomain(string $domain, array $info, array &$checks, array &$errors, array &$successes): void
|
||||
{
|
||||
@@ -324,10 +324,10 @@ class CheckDnsCommand extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $warnings
|
||||
* @param array<int, string> $successes
|
||||
* @param list<array> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $warnings
|
||||
* @param array<int, string> $successes
|
||||
* @param list<array<string, mixed>> $cfRecords
|
||||
*/
|
||||
private function checkMailcowDnsRecords(string $domain, array &$checks, array &$errors, array &$warnings, array &$successes, array $cfRecords): void
|
||||
@@ -356,9 +356,9 @@ class CheckDnsCommand extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $warnings
|
||||
* @param array<int, string> $successes
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $warnings
|
||||
* @param array<int, string> $successes
|
||||
* @param list<array{domain: string, checks: list<array>}> $domainResults
|
||||
*/
|
||||
private function sendReport(array $errors, array $warnings, array $successes, array $domainResults): void
|
||||
@@ -427,19 +427,19 @@ class CheckDnsCommand extends Command
|
||||
$title = 'DNS - Configuration OK';
|
||||
}
|
||||
|
||||
$description = "Domaines: **".implode(', ', DnsInfraHelper::DOMAINS)."**\n\n";
|
||||
$description .= "**".\count($successes)."** verification(s) OK\n";
|
||||
$description = 'Domaines: **'.implode(', ', DnsInfraHelper::DOMAINS)."**\n\n";
|
||||
$description .= '**'.\count($successes)."** verification(s) OK\n";
|
||||
if ($hasErrors) {
|
||||
$description .= "**".\count($errors)."** erreur(s)\n";
|
||||
$description .= '**'.\count($errors)."** erreur(s)\n";
|
||||
foreach (array_slice($errors, 0, 5) as $e) {
|
||||
$description .= "> $e\n";
|
||||
}
|
||||
if (\count($errors) > 5) {
|
||||
$description .= "> ... et ".(\count($errors) - 5)." autres\n";
|
||||
$description .= '> ... et '.(\count($errors) - 5)." autres\n";
|
||||
}
|
||||
}
|
||||
if ($hasWarnings) {
|
||||
$description .= "**".\count($warnings)."** avertissement(s)\n";
|
||||
$description .= '**'.\count($warnings)."** avertissement(s)\n";
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -124,6 +124,7 @@ class PaymentReminderCommand extends Command
|
||||
PaymentReminder::STEP_FORMAL_NOTICE => $this->handleFormalNotice($advert, $customer),
|
||||
PaymentReminder::STEP_TERMINATION_WARNING => $this->handleTerminationWarning($advert, $customer),
|
||||
PaymentReminder::STEP_TERMINATION => $this->handleTermination($advert, $customer),
|
||||
default => null,
|
||||
};
|
||||
|
||||
// Notification admin pour chaque etape
|
||||
|
||||
@@ -132,6 +132,7 @@ class StripeSyncCommand extends Command
|
||||
|
||||
/**
|
||||
* @return iterable<\Stripe\Charge>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function fetchCharges(): iterable
|
||||
@@ -141,6 +142,7 @@ class StripeSyncCommand extends Command
|
||||
|
||||
/**
|
||||
* @return iterable<\Stripe\Refund>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function fetchRefunds(): iterable
|
||||
@@ -150,6 +152,7 @@ class StripeSyncCommand extends Command
|
||||
|
||||
/**
|
||||
* @return iterable<\Stripe\Payout>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function fetchPayouts(): iterable
|
||||
@@ -159,6 +162,7 @@ class StripeSyncCommand extends Command
|
||||
|
||||
/**
|
||||
* @return iterable<\Stripe\Account>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function fetchConnectAccounts(): iterable
|
||||
|
||||
@@ -9,8 +9,8 @@ use App\Service\MailerService;
|
||||
use App\Service\MeilisearchService;
|
||||
use App\Service\Pdf\AdvertPdf;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
@@ -49,7 +49,7 @@ class AdvertController extends AbstractController
|
||||
}
|
||||
|
||||
#[Route('/{id}/generate-pdf', name: 'generate_pdf', requirements: ['id' => '\d+'], methods: ['POST'])]
|
||||
public function generatePdf(int $id, KernelInterface $kernel, UrlGeneratorInterface $urlGenerator, \Twig\Environment $twig): Response
|
||||
public function generatePdf(int $id, KernelInterface $kernel, UrlGeneratorInterface $urlGenerator, Environment $twig): Response
|
||||
{
|
||||
$advert = $this->em->getRepository(Advert::class)->find($id);
|
||||
if (null === $advert) {
|
||||
@@ -295,7 +295,7 @@ class AdvertController extends AbstractController
|
||||
public function syncPayment(
|
||||
int $id,
|
||||
FactureService $factureService,
|
||||
#[\Symfony\Component\DependencyInjection\Attribute\Autowire(env: 'STRIPE_SK')] string $stripeSk = '',
|
||||
#[Autowire(env: 'STRIPE_SK')] string $stripeSk = '',
|
||||
): Response {
|
||||
$advert = $this->em->getRepository(Advert::class)->find($id);
|
||||
if (null === $advert) {
|
||||
@@ -318,6 +318,7 @@ class AdvertController extends AbstractController
|
||||
|
||||
if ('succeeded' === $pi->status) {
|
||||
$amount = number_format($pi->amount_received / 100, 2, '.', '');
|
||||
/** @phpstan-ignore-next-line */
|
||||
$metadata = $pi->metadata instanceof \Stripe\StripeObject ? $pi->metadata->toArray() : (array) ($pi->metadata ?? []);
|
||||
$method = $metadata['payment_method'] ?? ($pi->payment_method_types[0] ?? 'card');
|
||||
|
||||
@@ -348,7 +349,7 @@ class AdvertController extends AbstractController
|
||||
}
|
||||
|
||||
// Generer la facture si pas deja presente
|
||||
if ($advert->getFactures()->count() === 0) {
|
||||
if (0 === $advert->getFactures()->count()) {
|
||||
$factureService->createPaidFactureFromAdvert($advert, $amount, $methodLabel);
|
||||
} else {
|
||||
// Mettre a jour la facture existante
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
namespace App\Controller\Admin;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Domain;
|
||||
use App\Entity\User;
|
||||
use App\Repository\CustomerRepository;
|
||||
use App\Entity\Domain;
|
||||
use App\Repository\RevendeurRepository;
|
||||
use App\Service\CloudflareService;
|
||||
use App\Service\DnsCheckService;
|
||||
use App\Service\EsyMailService;
|
||||
@@ -13,15 +14,14 @@ use App\Service\MailerService;
|
||||
use App\Service\MeilisearchService;
|
||||
use App\Service\OvhService;
|
||||
use App\Service\UserManagementService;
|
||||
use App\Repository\RevendeurRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
@@ -113,7 +113,7 @@ class ClientsController extends AbstractController
|
||||
*/
|
||||
private function buildCustomersInfo(array $customers, EntityManagerInterface $em): array
|
||||
{
|
||||
$domainRepo = $em->getRepository(\App\Entity\Domain::class);
|
||||
$domainRepo = $em->getRepository(Domain::class);
|
||||
$emailRepo = $em->getRepository(\App\Entity\DomainEmail::class);
|
||||
$websiteRepo = $em->getRepository(\App\Entity\Website::class);
|
||||
$info = [];
|
||||
@@ -387,7 +387,7 @@ class ClientsController extends AbstractController
|
||||
|
||||
$this->ensureDefaultContact($customer, $em);
|
||||
$contacts = $em->getRepository(\App\Entity\CustomerContact::class)->findBy(['customer' => $customer], ['createdAt' => 'DESC']);
|
||||
$domains = $em->getRepository(\App\Entity\Domain::class)->findBy(['customer' => $customer]);
|
||||
$domains = $em->getRepository(Domain::class)->findBy(['customer' => $customer]);
|
||||
$domainsInfo = $this->buildDomainsInfo($domains, $em, $esyMailService, 'ndd' === $tab);
|
||||
$websites = $em->getRepository(\App\Entity\Website::class)->findBy(['customer' => $customer], ['createdAt' => 'DESC']);
|
||||
$devisList = $em->getRepository(\App\Entity\Devis::class)->findBy(['customer' => $customer], ['createdAt' => 'DESC']);
|
||||
@@ -497,12 +497,8 @@ class ClientsController extends AbstractController
|
||||
|
||||
$serviceInfo = $ovhService->getDomainServiceInfo($fqdn);
|
||||
if (null !== $serviceInfo) {
|
||||
if (isset($serviceInfo['expiration'])) {
|
||||
$domain->setExpiredAt(new \DateTimeImmutable($serviceInfo['expiration']));
|
||||
}
|
||||
if (isset($serviceInfo['creation'])) {
|
||||
$domain->setUpdatedAt(new \DateTimeImmutable());
|
||||
}
|
||||
$domain->setExpiredAt(new \DateTimeImmutable($serviceInfo['expiration']));
|
||||
$domain->setUpdatedAt(new \DateTimeImmutable());
|
||||
}
|
||||
|
||||
$zoneInfo = $ovhService->getZoneInfo($fqdn);
|
||||
|
||||
@@ -201,6 +201,7 @@ class ComptabiliteController extends AbstractController
|
||||
$pdfContent = file_get_contents($tmpPath);
|
||||
@unlink($tmpPath);
|
||||
|
||||
/** @var \App\Entity\User $user */
|
||||
$user = $this->getUser();
|
||||
$redirectUrl = $this->generateUrl('app_admin_comptabilite_sign_callback', [
|
||||
'type' => $type,
|
||||
@@ -250,6 +251,7 @@ class ComptabiliteController extends AbstractController
|
||||
$pdfUrl = $documents[0]['url'] ?? null;
|
||||
$auditUrl = $submitterData['audit_log_url'] ?? null;
|
||||
|
||||
/** @var \App\Entity\User $user */
|
||||
$user = $this->getUser();
|
||||
$attachments = [];
|
||||
|
||||
@@ -488,6 +490,7 @@ class ComptabiliteController extends AbstractController
|
||||
$response = $this->rapportFinancier($fakeRequest);
|
||||
$pdfContent = $response->getContent();
|
||||
|
||||
/** @var \App\Entity\User $user */
|
||||
$user = $this->getUser();
|
||||
$redirectUrl = $this->generateUrl('app_admin_comptabilite_sign_callback', [
|
||||
'type' => 'rapport-financier',
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Controller\Admin;
|
||||
|
||||
use App\Entity\Advert;
|
||||
use App\Entity\AdvertLine;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Devis;
|
||||
@@ -150,7 +149,7 @@ class DevisController extends AbstractController
|
||||
{
|
||||
$isEdit = null !== $devis;
|
||||
|
||||
/** @var array<int, array{title?: string, description?: string, priceHt?: string, pos?: string|int}> $lines */
|
||||
/** @var array<int, array{title?: string, description?: string, priceHt?: string, pos?: string|int, type?: string, serviceId?: string|int}> $lines */
|
||||
$lines = $request->request->all('lines');
|
||||
|
||||
if ([] === $lines) {
|
||||
@@ -165,7 +164,9 @@ class DevisController extends AbstractController
|
||||
// Creation du devis (OrderNumber genere ou reutilise)
|
||||
$devis = $this->devisService->create();
|
||||
$devis->setCustomer($customer);
|
||||
$devis->setSubmitterSiteconseilId($this->getUser()?->getId());
|
||||
/** @var \App\Entity\User|null $currentUser */
|
||||
$currentUser = $this->getUser();
|
||||
$devis->setSubmitterSiteconseilId($currentUser?->getId());
|
||||
} else {
|
||||
// Edition : supprimer les lignes existantes (orphanRemoval gere la suppression DB)
|
||||
foreach ($devis->getLines()->toArray() as $oldLine) {
|
||||
@@ -234,7 +235,7 @@ class DevisController extends AbstractController
|
||||
}
|
||||
|
||||
#[Route('/{id}/generate-pdf', name: 'generate_pdf', requirements: ['id' => '\d+'], methods: ['POST'])]
|
||||
public function generatePdf(int $id, KernelInterface $kernel, \Twig\Environment $twig): Response
|
||||
public function generatePdf(int $id, KernelInterface $kernel, Environment $twig): Response
|
||||
{
|
||||
$devis = $this->em->getRepository(Devis::class)->find($id);
|
||||
if (null === $devis) {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Controller\Admin;
|
||||
|
||||
use App\Entity\Advert;
|
||||
use App\Entity\AdvertPayment;
|
||||
use App\Entity\Facture;
|
||||
use App\Entity\FacturePrestataire;
|
||||
@@ -80,7 +79,7 @@ class StatsController extends AbstractController
|
||||
'factures_impayees' => $factureStats['nbTotal'] - $factureStats['nbPaid'],
|
||||
'montant_emis' => $factureStats['totalEmis'],
|
||||
'montant_paye' => $factureStats['totalTtc'],
|
||||
'montant_impaye' => $factureStats['totalEmis'] - $factureStats['totalTtc'],
|
||||
'montant_impaye' => (float) $factureStats['totalEmis'] - (float) $factureStats['totalTtc'],
|
||||
];
|
||||
|
||||
// Paiements par methode
|
||||
@@ -104,7 +103,7 @@ class StatsController extends AbstractController
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{totalHt: string, totalTva: string, totalTtc: string, totalEmis: string, nbTotal: int, nbPaid: int}
|
||||
* @return array{totalHt: string, totalTva: string, totalTtc: string, totalEmis: float, nbTotal: int, nbPaid: int}
|
||||
*/
|
||||
private function getFactureStats(\DateTimeImmutable $from, \DateTimeImmutable $to): array
|
||||
{
|
||||
@@ -199,9 +198,9 @@ class StatsController extends AbstractController
|
||||
++$grouped[$method]['count'];
|
||||
}
|
||||
|
||||
usort($grouped, fn ($a, $b) => $b['total'] <=> $a['total']);
|
||||
usort($grouped, /** @param array{method: string, total: float, count: int} $a @param array{method: string, total: float, count: int} $b */ fn (array $a, array $b) => $b['total'] <=> $a['total']);
|
||||
|
||||
return array_values($grouped);
|
||||
return $grouped;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,13 +13,12 @@ use App\Repository\CustomerRepository;
|
||||
use App\Repository\PriceAutomaticRepository;
|
||||
use App\Repository\RevendeurRepository;
|
||||
use App\Repository\StripeWebhookSecretRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use App\Service\MeilisearchService;
|
||||
use App\Service\StripePriceService;
|
||||
use App\Service\StripeWebhookService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
@@ -394,5 +393,4 @@ class SyncController extends AbstractController
|
||||
|
||||
return $this->redirectToRoute('app_admin_sync_index');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ use App\Service\MeilisearchService;
|
||||
use App\Service\StripePriceService;
|
||||
use App\Service\TarificationService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
@@ -19,6 +19,7 @@ class DevisPdfController extends AbstractController
|
||||
private LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/uploads/devis/{id}/{type}', name: 'app_devis_pdf', methods: ['GET'], requirements: ['type' => 'unsigned|signed|audit'])]
|
||||
public function __invoke(
|
||||
int $id,
|
||||
|
||||
@@ -8,9 +8,9 @@ use App\Service\DnsCheckService;
|
||||
use App\Service\DnsInfraHelper;
|
||||
use App\Service\MailcowService;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
@@ -88,9 +88,9 @@ class DnsReportController extends AbstractController
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array> $checks
|
||||
* @param list<string> $errors
|
||||
* @param list<string> $successes
|
||||
* @param list<array> $checks
|
||||
* @param list<string> $errors
|
||||
* @param list<string> $successes
|
||||
* @param list<array<string, mixed>> $cfRecords
|
||||
*/
|
||||
private function checkAwsSes(string $domain, AwsSesService $awsSes, DnsCheckService $dnsCheck, DnsInfraHelper $helper, array &$checks, array &$errors, array &$successes, array $cfRecords): void
|
||||
@@ -143,10 +143,10 @@ class DnsReportController extends AbstractController
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array> $checks
|
||||
* @param list<string> $errors
|
||||
* @param list<string> $warnings
|
||||
* @param list<string> $successes
|
||||
* @param list<array> $checks
|
||||
* @param list<string> $errors
|
||||
* @param list<string> $warnings
|
||||
* @param list<string> $successes
|
||||
* @param list<array<string, mixed>> $cfRecords
|
||||
*/
|
||||
private function checkMailcow(string $domain, MailcowService $mailcow, DnsInfraHelper $helper, array &$checks, array &$errors, array &$warnings, array &$successes, array $cfRecords): void
|
||||
|
||||
@@ -12,6 +12,7 @@ use Symfony\Component\Routing\Attribute\Route;
|
||||
class LegalController extends AbstractController
|
||||
{
|
||||
private const RGPD_ANCHOR = '#exercer-droits';
|
||||
|
||||
#[Route('/mention-legal', name: 'mention_legal')]
|
||||
public function mentionLegal(): Response
|
||||
{
|
||||
@@ -137,8 +138,6 @@ class LegalController extends AbstractController
|
||||
$this->addFlash('success', 'Un code de verification a ete envoye a '.$email.'. Veuillez le saisir ci-dessous pour valider votre demande.');
|
||||
|
||||
return $this->redirect($this->generateUrl('app_legal_rgpd_verify', ['type' => 'deletion', 'email' => $email, 'ip' => $ip]));
|
||||
|
||||
return $this->redirect($this->generateUrl('app_legal_rgpd').self::RGPD_ANCHOR);
|
||||
}
|
||||
|
||||
#[Route('/rgpd/verify', name: 'rgpd_verify', methods: ['GET', 'POST'])]
|
||||
|
||||
@@ -317,6 +317,7 @@ class OrderPaymentController extends AbstractController
|
||||
$params['metadata']['application_fee'] = (string) $applicationFee;
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$intent = \Stripe\PaymentIntent::create($params);
|
||||
|
||||
$advert->setStripePaymentId($intent->id);
|
||||
|
||||
@@ -402,6 +402,7 @@ class WebhookDocuSealController extends AbstractController
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*
|
||||
* @codeCoverageIgnore Telecharge les PDFs depuis des URLs externes (non testable unitairement)
|
||||
*/
|
||||
private function downloadDocumentsFromWebhook(array $data, Attestation $attestation, string $projectDir): void
|
||||
|
||||
@@ -10,15 +10,15 @@ use App\Repository\StripeWebhookSecretRepository;
|
||||
use App\Service\FactureService;
|
||||
use App\Service\MailerService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Twig\Environment;
|
||||
|
||||
class WebhookStripeController extends AbstractController
|
||||
@@ -100,6 +100,7 @@ class WebhookStripeController extends AbstractController
|
||||
private function handlePaymentSucceeded(\Stripe\Event $event, string $channel): JsonResponse
|
||||
{
|
||||
$paymentIntent = $event->data->object;
|
||||
/** @phpstan-ignore-next-line */
|
||||
$metadata = $paymentIntent->metadata instanceof \Stripe\StripeObject ? $paymentIntent->metadata->toArray() : (array) ($paymentIntent->metadata ?? []);
|
||||
$advertId = $metadata['advert_id'] ?? null;
|
||||
|
||||
@@ -123,6 +124,7 @@ class WebhookStripeController extends AbstractController
|
||||
return new JsonResponse(['status' => 'ok', 'action' => 'already_processed']);
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$amount = number_format($paymentIntent->amount_received / 100, 2, '.', '');
|
||||
$method = $metadata['payment_method'] ?? ($paymentIntent->payment_method_types[0] ?? null);
|
||||
$isConnect = str_contains($channel, 'connect');
|
||||
@@ -224,6 +226,7 @@ class WebhookStripeController extends AbstractController
|
||||
private function handlePaymentFailed(\Stripe\Event $event, string $channel): JsonResponse
|
||||
{
|
||||
$paymentIntent = $event->data->object;
|
||||
/** @phpstan-ignore-next-line */
|
||||
$metadata = $paymentIntent->metadata instanceof \Stripe\StripeObject ? $paymentIntent->metadata->toArray() : (array) ($paymentIntent->metadata ?? []);
|
||||
$advertId = $metadata['advert_id'] ?? null;
|
||||
|
||||
@@ -238,7 +241,7 @@ class WebhookStripeController extends AbstractController
|
||||
|
||||
$amount = number_format(($paymentIntent->amount ?? 0) / 100, 2, '.', '');
|
||||
$method = $metadata['payment_method'] ?? ($paymentIntent->payment_method_types[0] ?? null);
|
||||
$errorMessage = $paymentIntent->last_payment_error?->message ?? 'Paiement refuse';
|
||||
$errorMessage = $paymentIntent->last_payment_error->message ?? 'Paiement refuse';
|
||||
|
||||
$methodLabel = match ($method) {
|
||||
'sepa_debit' => 'Prelevement SEPA',
|
||||
|
||||
@@ -75,7 +75,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface, EmailTw
|
||||
#[ORM\Column(type: 'json', nullable: true)]
|
||||
private ?array $backupCodes = null;
|
||||
|
||||
#[ORM\Column]
|
||||
#[ORM\Column]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
public function __construct()
|
||||
@@ -370,7 +370,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface, EmailTw
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): \DateTimeImmutable
|
||||
public function getCreatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Advert>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AdvertRepository extends ServiceEntityRepository
|
||||
|
||||
@@ -9,6 +9,7 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<AppLog>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AppLogRepository extends ServiceEntityRepository
|
||||
|
||||
@@ -8,6 +8,7 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Attestation>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AttestationRepository extends ServiceEntityRepository
|
||||
|
||||
@@ -8,6 +8,7 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Customer>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class CustomerRepository extends ServiceEntityRepository
|
||||
|
||||
@@ -8,6 +8,7 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Devis>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class DevisRepository extends ServiceEntityRepository
|
||||
|
||||
@@ -8,6 +8,7 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<EmailTracking>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class EmailTrackingRepository extends ServiceEntityRepository
|
||||
|
||||
@@ -8,6 +8,7 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Facture>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class FactureRepository extends ServiceEntityRepository
|
||||
|
||||
@@ -8,6 +8,7 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<MessengerLog>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class MessengerLogRepository extends ServiceEntityRepository
|
||||
|
||||
@@ -8,6 +8,7 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<OrderNumber>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class OrderNumberRepository extends ServiceEntityRepository
|
||||
|
||||
@@ -8,6 +8,7 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<PriceAutomatic>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class PriceAutomaticRepository extends ServiceEntityRepository
|
||||
|
||||
@@ -8,6 +8,7 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Revendeur>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class RevendeurRepository extends ServiceEntityRepository
|
||||
|
||||
@@ -8,6 +8,7 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<ServiceCategory>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ServiceCategoryRepository extends ServiceEntityRepository
|
||||
|
||||
@@ -9,6 +9,7 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Service>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ServiceRepository extends ServiceEntityRepository
|
||||
|
||||
@@ -8,6 +8,7 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<StripeWebhookSecret>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class StripeWebhookSecretRepository extends ServiceEntityRepository
|
||||
|
||||
@@ -11,6 +11,7 @@ use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<User>
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Service;
|
||||
|
||||
use App\Entity\ActionLog;
|
||||
use App\Entity\Advert;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Domain;
|
||||
use App\Entity\DomainEmail;
|
||||
@@ -20,6 +19,7 @@ class ActionService
|
||||
public function __construct(
|
||||
private EntityManagerInterface $em,
|
||||
private LoggerInterface $logger,
|
||||
/** @phpstan-ignore-next-line */
|
||||
private MailerService $mailer,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -53,6 +53,8 @@ class AdvertService
|
||||
|
||||
/**
|
||||
* Calcule les totaux selon la config TVA.
|
||||
*
|
||||
* @return array{totalHt: string, totalTva: string, totalTtc: string}
|
||||
*/
|
||||
public function computeTotals(string $totalHt): array
|
||||
{
|
||||
|
||||
@@ -134,6 +134,7 @@ class CloudflareService
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $query
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function request(string $method, string $path, array $query = []): array
|
||||
|
||||
@@ -40,6 +40,8 @@ class DevisService
|
||||
|
||||
/**
|
||||
* Calcule les totaux du devis selon la config TVA.
|
||||
*
|
||||
* @return array{totalHt: string, totalTva: string, totalTtc: string}
|
||||
*/
|
||||
public function computeTotals(string $totalHt): array
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@ class DnsCheckService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array> $checks
|
||||
* @param list<array> $checks
|
||||
* @param list<string> $errors
|
||||
* @param list<string> $warnings
|
||||
* @param list<string> $successes
|
||||
@@ -70,7 +70,7 @@ class DnsCheckService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array> $checks
|
||||
* @param list<array> $checks
|
||||
* @param list<string> $errors
|
||||
* @param list<string> $successes
|
||||
*/
|
||||
@@ -115,7 +115,7 @@ class DnsCheckService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array> $checks
|
||||
* @param list<array> $checks
|
||||
* @param list<string> $errors
|
||||
* @param list<string> $warnings
|
||||
* @param list<string> $successes
|
||||
@@ -147,7 +147,7 @@ class DnsCheckService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array> $checks
|
||||
* @param list<array> $checks
|
||||
* @param list<string> $errors
|
||||
* @param list<string> $successes
|
||||
*/
|
||||
@@ -182,7 +182,7 @@ class DnsCheckService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array> $checks
|
||||
* @param list<array> $checks
|
||||
* @param list<string> $errors
|
||||
* @param list<string> $warnings
|
||||
* @param list<string> $successes
|
||||
@@ -221,11 +221,6 @@ class DnsCheckService
|
||||
|
||||
/**
|
||||
* Verifie les NS et l'expiration du domaine via RDAP.
|
||||
*
|
||||
* @param list<array> $checks
|
||||
* @param list<string> $errors
|
||||
* @param list<string> $warnings
|
||||
* @param list<string> $successes
|
||||
*/
|
||||
public function getExpirationDate(string $domain): ?\DateTimeImmutable
|
||||
{
|
||||
@@ -248,6 +243,12 @@ class DnsCheckService
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, array<string, mixed>> $checks
|
||||
* @param array<int, string> $errors
|
||||
* @param array<int, string> $warnings
|
||||
* @param array<int, string> $successes
|
||||
*/
|
||||
public function checkWhois(string $domain, array &$checks, array &$errors, array &$warnings, array &$successes): void
|
||||
{
|
||||
// Nameservers via dig NS
|
||||
@@ -478,7 +479,7 @@ class DnsCheckService
|
||||
foreach ($records as $r) {
|
||||
$t = $r['type'] ?? '';
|
||||
match ($t) {
|
||||
'TXT' => $lines[] = "$domain.\tIN\tTXT\t\"".($r['txt'] ?? '')."\"",
|
||||
'TXT' => $lines[] = "$domain.\tIN\tTXT\t\"".($r['txt'] ?? '').'"',
|
||||
'MX' => $lines[] = "$domain.\tIN\tMX\t".($r['pri'] ?? 0).' '.($r['target'] ?? ''),
|
||||
'CNAME' => $lines[] = "$domain.\tIN\tCNAME\t".($r['target'] ?? ''),
|
||||
'SRV' => $lines[] = "$domain.\tIN\tSRV\t".($r['pri'] ?? 0).' '.($r['weight'] ?? 0).' '.($r['port'] ?? 0).' '.($r['target'] ?? ''),
|
||||
|
||||
@@ -50,7 +50,7 @@ class DnsInfraHelper
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array> $checks
|
||||
* @param list<array> $checks
|
||||
* @param list<array<string, mixed>> $cfRecords
|
||||
*/
|
||||
public function enrichWithCloudflare(array &$checks, string $recordName, string $checkType, string $dnsType, array $cfRecords): void
|
||||
@@ -80,7 +80,7 @@ class DnsInfraHelper
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array> $checks
|
||||
* @param list<array> $checks
|
||||
* @param list<array<string, mixed>> $cfRecords
|
||||
*/
|
||||
public function enrichLastCheck(array &$checks, string $recordName, string $dnsType, array $cfRecords): void
|
||||
|
||||
@@ -431,6 +431,7 @@ class DocuSealService
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param list<array<string, mixed>> $documents
|
||||
*/
|
||||
private function downloadSignedPdf(array $documents, string $dir, string $ref, Attestation $attestation): void
|
||||
@@ -450,6 +451,7 @@ class DocuSealService
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param array<string, mixed> $submitter
|
||||
*/
|
||||
private function downloadAuditCertificate(array $submitter, string $dir, string $ref, Attestation $attestation): void
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Service;
|
||||
|
||||
use App\Entity\Advert;
|
||||
use App\Entity\AdvertLine;
|
||||
use App\Entity\Facture;
|
||||
use App\Entity\FactureLine;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
@@ -133,6 +132,8 @@ class FactureService
|
||||
|
||||
/**
|
||||
* Calcule les totaux selon la config TVA.
|
||||
*
|
||||
* @return array{totalHt: string, totalTva: string, totalTtc: string}
|
||||
*/
|
||||
public function computeTotals(string $totalHt): array
|
||||
{
|
||||
|
||||
@@ -169,6 +169,8 @@ class GoogleSearchService
|
||||
// ──────── Auth OAuth2 JWT ────────
|
||||
|
||||
/**
|
||||
* @param array<string, mixed>|null $body
|
||||
*
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
private function request(string $method, string $url, ?array $body = null): ?array
|
||||
|
||||
@@ -46,7 +46,7 @@ class MailcowService
|
||||
|
||||
/**
|
||||
* Recuperer la configuration DNS attendue par Mailcow pour un domaine.
|
||||
* Basee sur la documentation Mailcow: https://docs.mailcow.email/prerequisite/dns/
|
||||
* Basee sur la documentation Mailcow: https://docs.mailcow.email/prerequisite/dns/.
|
||||
*
|
||||
* @return list<array{type: string, name: string, content: string, optional: bool}>
|
||||
*/
|
||||
|
||||
@@ -157,8 +157,8 @@ class MailerService
|
||||
$filtered = [];
|
||||
|
||||
foreach ($attachments as $a) {
|
||||
$name = $a['name'] ?? basename($a['path']);
|
||||
$path = $a['path'] ?? '';
|
||||
$name = $a['name'];
|
||||
$path = $a['path'];
|
||||
$ext = strtolower(pathinfo($name, \PATHINFO_EXTENSION));
|
||||
if (\in_array('.'.$ext, $excluded, true) || str_contains(strtolower($name), 'smime')) {
|
||||
continue;
|
||||
|
||||
@@ -4,10 +4,10 @@ namespace App\Service;
|
||||
|
||||
use App\Entity\Advert;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Facture;
|
||||
use App\Entity\CustomerContact;
|
||||
use App\Entity\Devis;
|
||||
use App\Entity\Domain;
|
||||
use App\Entity\Facture;
|
||||
use App\Entity\PriceAutomatic;
|
||||
use App\Entity\Revendeur;
|
||||
use App\Entity\Website;
|
||||
|
||||
@@ -166,7 +166,6 @@ class AdvertPdf extends Fpdi
|
||||
$this->displaySummary();
|
||||
$this->displayQrCode();
|
||||
$this->appendCgv();
|
||||
|
||||
}
|
||||
|
||||
private function appendCgv(): void
|
||||
@@ -201,6 +200,7 @@ class AdvertPdf extends Fpdi
|
||||
}
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
private function appendRib(): void
|
||||
{
|
||||
$ribPath = $this->kernel->getProjectDir().'/public/rib.pdf';
|
||||
|
||||
@@ -176,10 +176,8 @@ class FacturePdf extends Fpdi
|
||||
$this->displaySummary();
|
||||
$this->displayQrCode();
|
||||
$this->appendCgv();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Genere les CGV depuis le template Twig via Dompdf puis les importe via FPDI.
|
||||
*/
|
||||
@@ -223,6 +221,7 @@ class FacturePdf extends Fpdi
|
||||
* Importe les pages de public/rib.pdf apres les CGV.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private function appendRib(): void
|
||||
{
|
||||
@@ -244,7 +243,10 @@ class FacturePdf extends Fpdi
|
||||
}
|
||||
}
|
||||
|
||||
/** @codeCoverageIgnore */
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private function displayHmac(): void
|
||||
{
|
||||
$this->Ln(6);
|
||||
|
||||
@@ -38,8 +38,8 @@ class RapportFinancierPdf extends Fpdi
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, float> $recettes Libelle => montant
|
||||
* @param array<string, float> $depenses Libelle => montant
|
||||
* @param array<string, float> $recettes Libelle => montant
|
||||
* @param array<string, float> $depenses Libelle => montant
|
||||
*/
|
||||
public function setData(array $recettes, array $depenses): void
|
||||
{
|
||||
|
||||
@@ -58,7 +58,7 @@ class SentryService
|
||||
return null;
|
||||
}
|
||||
|
||||
return $result[0]['dsn']['public'];
|
||||
return (string) $result[0]['dsn']['public'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,6 +70,7 @@ class SentryService
|
||||
{
|
||||
$org = $this->resolveOrg($org);
|
||||
|
||||
/** @var list<array<string, mixed>> */
|
||||
return $this->request('GET', '/organizations/'.$org.'/projects/') ?? [];
|
||||
}
|
||||
|
||||
@@ -87,6 +88,7 @@ class SentryService
|
||||
$path .= '?query='.urlencode($query);
|
||||
}
|
||||
|
||||
/** @var list<array<string, mixed>> */
|
||||
return $this->request('GET', $path) ?? [];
|
||||
}
|
||||
|
||||
@@ -117,7 +119,9 @@ class SentryService
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>|null
|
||||
* @param array<string, mixed>|null $body
|
||||
*
|
||||
* @return array<int|string, mixed>|null
|
||||
*/
|
||||
private function request(string $method, string $path, ?array $body = null): ?array
|
||||
{
|
||||
|
||||
@@ -125,7 +125,7 @@ class SeoService
|
||||
if (0 === $result['url_count']) {
|
||||
// Essai sans namespace
|
||||
$urls = $xml->xpath('//url');
|
||||
$result['url_count'] = false !== $urls ? \count($urls) : 0;
|
||||
$result['url_count'] = \count($urls);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$result['issues'][] = 'Erreur acces sitemap.xml : '.$e->getMessage();
|
||||
@@ -284,7 +284,7 @@ class SeoService
|
||||
$result['valid'] = true;
|
||||
$result['issuer'] = $certInfo['issuer']['O'] ?? $certInfo['issuer']['CN'] ?? null;
|
||||
$result['expires'] = date('Y-m-d', $certInfo['validTo_time_t']);
|
||||
$result['days_remaining'] = (int) ((($certInfo['validTo_time_t']) - time()) / 86400);
|
||||
$result['days_remaining'] = (int) (($certInfo['validTo_time_t'] - time()) / 86400);
|
||||
|
||||
if ($result['days_remaining'] < 0) {
|
||||
$result['valid'] = false;
|
||||
|
||||
@@ -6,7 +6,6 @@ use App\Entity\PriceAutomatic;
|
||||
use App\Repository\PriceAutomaticRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Stripe\Price;
|
||||
use Stripe\Product;
|
||||
use Stripe\StripeClient;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ class TarificationService
|
||||
try {
|
||||
$this->stripePriceService?->syncPrice($p);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger?->error('Error syncing price with Stripe: ' . $e->getMessage(), [
|
||||
$this->logger?->error('Error syncing price with Stripe: '.$e->getMessage(), [
|
||||
'price_id' => $p->getId(),
|
||||
'type' => $p->getType(),
|
||||
'exception' => $e,
|
||||
|
||||
@@ -27,10 +27,13 @@ Object.defineProperty(globalThis, 'localStorage', { value: localStorageMock, wri
|
||||
let domContentLoadedListeners = []
|
||||
const originalAddEventListener = document.addEventListener.bind(document)
|
||||
const originalRemoveEventListener = document.removeEventListener.bind(document)
|
||||
document.addEventListener = function(type, listener, options) {
|
||||
if (type === 'DOMContentLoaded') {
|
||||
domContentLoadedListeners.push(listener)
|
||||
}
|
||||
|
||||
const trackListener = (type, listener) => {
|
||||
if (type === 'DOMContentLoaded') domContentLoadedListeners.push(listener)
|
||||
}
|
||||
|
||||
document.addEventListener = (type, listener, options) => {
|
||||
trackListener(type, listener)
|
||||
return originalAddEventListener(type, listener, options)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user