✨ feat(BackupCommand): Améliore la sauvegarde avec gestion des erreurs et nettoyage.
🐛 fix(SyncCommand): Corrige la synchronisation DNS et gère les erreurs OVH. ⚙️ refactor(DemandeCommand): Refactorise la génération du fichier hosts.ini. 🧹 chore(CustomerCommand): Purge les clients supprimés et leurs dépendances. ✅ test(TestMailerCommand): Ajoute une commande pour tester l'envoi d'emails. ➕ feat(run.sh): Ajoute un script pour exécuter les commandes de demande. ✨ feat(EmailCommand): Supprime les emails Mailcow marqués comme supprimés. ✨ feat(AccountCommand): Crée un utilisateur admin si inexistant. ✨ feat(ExportComptable): Initialise la commande d'export comptable.
This commit is contained in:
@@ -194,7 +194,13 @@
|
||||
args:
|
||||
chdir: "{{ path }}"
|
||||
when: ansible_os_family == "Debian" # Added a when condition here, often missed
|
||||
|
||||
- name: "Execute created subcriber link"
|
||||
cron:
|
||||
name: "Mainframe - subcriber link"
|
||||
minute: "0"
|
||||
hour: "*"
|
||||
job: "sh {{ path }}/script/demande/run.sh"
|
||||
user: root
|
||||
- name: "Cron Task purge customer delete"
|
||||
cron:
|
||||
name: "Mainframe - Purge customer"
|
||||
@@ -202,6 +208,7 @@
|
||||
hour: "21"
|
||||
job: "php {{ path }}/bin/console mainframe:cron:customer"
|
||||
user: root
|
||||
|
||||
- name: "Cron Task purge email delete"
|
||||
cron:
|
||||
name: "Mainframe - Purge customer"
|
||||
@@ -209,6 +216,7 @@
|
||||
hour: "21"
|
||||
job: "php {{ path }}/bin/console mainframe:cron:email"
|
||||
user: root
|
||||
|
||||
- name: "Cron Task sync"
|
||||
ansible.builtin.cron:
|
||||
name: "Mainframe - Sync"
|
||||
|
||||
5
script/demande/run.sh
Normal file
5
script/demande/run.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
php /var/www/mainframe/app/bin/console mainframe:demande
|
||||
|
||||
|
||||
ansible-playbook -i script/demande/hosts.ini script/demande/playbook.yaml
|
||||
@@ -19,8 +19,12 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
#[AsCommand(name: 'mainframe:admin')]
|
||||
class AccountCommand extends Command
|
||||
{
|
||||
public function __construct(private readonly EventDispatcherInterface $eventDispatcher, private readonly UserPasswordHasherInterface $userPasswordHasher, private readonly EntityManagerInterface $entityManager, ?string $name = null)
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EventDispatcherInterface $eventDispatcher,
|
||||
private readonly UserPasswordHasherInterface $userPasswordHasher,
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
?string $name = null
|
||||
) {
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
@@ -29,28 +33,32 @@ class AccountCommand extends Command
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$io->title("Création d'un utilisateur administrateur");
|
||||
|
||||
$userExit = $this->entityManager->getRepository(Account::class)->findOneBy(['email'=>'jovann@siteconseil.fr']);
|
||||
if(!$userExit instanceof Account) {
|
||||
$existingUser = $this->entityManager->getRepository(Account::class)->findOneBy(['email' => 'jovann@siteconseil.fr']);
|
||||
if (!$existingUser instanceof Account) {
|
||||
$password = TempPasswordGenerator::generate();
|
||||
$userExit = new Account();
|
||||
$userExit->setRoles(['ROLE_ROOT']);
|
||||
$userExit->setUuid(Uuid::v4());
|
||||
$userExit->setIsActif(true);
|
||||
$userExit->setIsFirstLogin(true);
|
||||
$newUser = new Account();
|
||||
$newUser->setRoles(['ROLE_ROOT']);
|
||||
$newUser->setUuid(Uuid::v4());
|
||||
$newUser->setIsActif(true);
|
||||
$newUser->setIsFirstLogin(true);
|
||||
|
||||
$questionEmail = new Question("Email ?");
|
||||
$email = $io->askQuestion($questionEmail);
|
||||
$email = $io->askQuestion(new Question("Email ?"));
|
||||
$newUser->setEmail($email);
|
||||
|
||||
$userExit->setEmail($email);
|
||||
$username = $io->askQuestion(new Question("Username ?"));
|
||||
$newUser->setUsername($username);
|
||||
|
||||
$questionUsername = new Question("Username ?");
|
||||
$username = $io->askQuestion($questionUsername);
|
||||
$userExit->setUsername($username);
|
||||
$userExit->setPassword($this->userPasswordHasher->hashPassword($userExit, $password));
|
||||
$hashedPassword = $this->userPasswordHasher->hashPassword($newUser, $password);
|
||||
$newUser->setPassword($hashedPassword);
|
||||
|
||||
$this->entityManager->persist($usserExit);
|
||||
$this->entityManager->persist($newUser);
|
||||
$this->entityManager->flush();
|
||||
$this->eventDispatcher->dispatch(new CreatedAdminEvent($userExit, $password));
|
||||
|
||||
$this->eventDispatcher->dispatch(new CreatedAdminEvent($newUser, $password));
|
||||
|
||||
$io->success("Utilisateur administrateur créé avec succès.");
|
||||
} else {
|
||||
$io->warning("Un utilisateur avec l'email 'jovann@siteconseil.fr' existe déjà.");
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
|
||||
@@ -4,8 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Entity\Revendeur;
|
||||
use App\Repository\RevendeurRepository;
|
||||
use App\Service\Revendeur\RevendeurService;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
@@ -18,12 +16,11 @@ use Symfony\Component\HttpKernel\KernelInterface;
|
||||
#[AsCommand(name: 'mainframe:backup', description: 'Backup command')]
|
||||
class BackupCommand extends Command
|
||||
{
|
||||
|
||||
public function __construct(
|
||||
private readonly KernelInterface $kernelInterface,
|
||||
private readonly KernelInterface $kernel,
|
||||
private readonly RevendeurService $revendeurService,
|
||||
?string $name = null)
|
||||
{
|
||||
?string $name = null
|
||||
) {
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
@@ -32,88 +29,102 @@ class BackupCommand extends Command
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$io->title('Backup command');
|
||||
|
||||
$path = $this->kernelInterface->getProjectDir()."/backup";
|
||||
$this->backuped($path);
|
||||
$backupPath = $this->kernel->getProjectDir() . '/backup';
|
||||
|
||||
if (!is_dir($backupPath) && !mkdir($backupPath, 0755, true) && !is_dir($backupPath)) {
|
||||
$io->error(sprintf('Impossible de créer le dossier de sauvegarde %s', $backupPath));
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->performBackup($backupPath);
|
||||
} catch (\Exception $e) {
|
||||
$io->error('Erreur lors de la sauvegarde : ' . $e->getMessage());
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
// Nettoyage des fichiers anciens (> 7 jours)
|
||||
$finder = new Finder();
|
||||
$files = $finder->in($path)->files()->name('*.tar.gz');
|
||||
$finder->files()->in($backupPath)->name('*.tar.gz');
|
||||
$now = time();
|
||||
foreach ($files as $file) {
|
||||
if ($now - $file->getMTime() > 60 * 60 * 24 * 7) {
|
||||
|
||||
foreach ($finder as $file) {
|
||||
if (($now - $file->getMTime()) > 60 * 60 * 24 * 7) {
|
||||
@unlink($file->getRealPath());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
$io->success('Sauvegarde terminée avec succès.');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
private function backuped(string $backupPath): void
|
||||
|
||||
private function performBackup(string $backupPath): void
|
||||
{
|
||||
$database= $_ENV['DATABASE_URL'];
|
||||
$databaseUrl = $_ENV['DATABASE_URL'] ?? '';
|
||||
preg_match(
|
||||
'/^postgres(?:ql)?:\\/\\/(.*?):(.*?)@(.*?):(\\d+)\\/(.*?)(?:\\?|$)/',
|
||||
$database,
|
||||
'/^postgres(?:ql)?:\/\/(.*?):(.*?)@(.*?):(\d+)\/(.*?)(?:\?|$)/',
|
||||
$databaseUrl,
|
||||
$matches
|
||||
);
|
||||
// À adapter selon ta configuration/env Symfony !
|
||||
$user = $matches[1] ?? null;
|
||||
$password = $matches[2] ?? null;
|
||||
$host = $matches[3] ?? null;
|
||||
$port = $matches[4] ?? null;
|
||||
$db = $matches[5] ?? null;
|
||||
|
||||
if (count($matches) < 6) {
|
||||
throw new \RuntimeException('DATABASE_URL invalide ou non configurée.');
|
||||
}
|
||||
|
||||
[$user, $password, $host, $port, $db] = array_slice($matches, 1, 5);
|
||||
|
||||
$sqlFilename = sprintf('%s/pgsql_backup_%s.sql', $backupPath, date('Y-m-d_His'));
|
||||
|
||||
// Pour éviter les exposes de mdp dans commande : passer par env
|
||||
putenv("PGPASSWORD={$password}");
|
||||
|
||||
// Option -F c pour backup custom compressé, -f pour destination
|
||||
$command = sprintf(
|
||||
'pg_dump -h %s -U %s -F c %s -f %s',
|
||||
$host,
|
||||
$user,
|
||||
$db,
|
||||
$sqlFilename
|
||||
escapeshellarg($host),
|
||||
escapeshellarg($user),
|
||||
escapeshellarg($db),
|
||||
escapeshellarg($sqlFilename)
|
||||
);
|
||||
|
||||
// Exécution du backup
|
||||
exec($command);
|
||||
exec($command, $output, $returnVar);
|
||||
if ($returnVar !== 0) {
|
||||
throw new \RuntimeException('Erreur lors de l\'exécution de pg_dump.');
|
||||
}
|
||||
|
||||
$zipFilename = sprintf('%s/backup_%s.zip', $backupPath, date('d-m-Y'));
|
||||
// Création du ZIP et ajout du SQL dedans
|
||||
$zip = new \ZipArchive();
|
||||
if ($zip->open($zipFilename, \ZipArchive::CREATE) === true) {
|
||||
// Le fichier dans le zip portera juste le nom du .sql
|
||||
$zip->addFile($sqlFilename, basename($sqlFilename));
|
||||
|
||||
$vichUploadDirs = [
|
||||
$this->kernelInterface->getProjectDir() . '/public/storage', // Exemple chemin upload
|
||||
// ajouter d’autres chemins si besoin
|
||||
];
|
||||
foreach ($vichUploadDirs as $dir) {
|
||||
$this->addDirToZip($zip, $dir, basename($dir));
|
||||
}
|
||||
$zip->close();
|
||||
unlink($sqlFilename);
|
||||
if ($zip->open($zipFilename, \ZipArchive::CREATE) !== true) {
|
||||
throw new \RuntimeException("Impossible de créer l'archive ZIP : $zipFilename");
|
||||
}
|
||||
|
||||
$zip->addFile($sqlFilename, basename($sqlFilename));
|
||||
|
||||
$uploadDirs = [
|
||||
$this->kernel->getProjectDir() . '/public/storage', // Ajouter d'autres chemins si nécessaire
|
||||
];
|
||||
|
||||
foreach ($uploadDirs as $dir) {
|
||||
$this->addDirectoryToZip($zip, $dir, basename($dir));
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
|
||||
@unlink($sqlFilename);
|
||||
}
|
||||
|
||||
private function addDirToZip(\ZipArchive $zip, string $folder, string $zipPath): void
|
||||
private function addDirectoryToZip(\ZipArchive $zip, string $folderPath, string $zipPath): void
|
||||
{
|
||||
$files = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($folder),
|
||||
new \RecursiveDirectoryIterator($folderPath, \FilesystemIterator::SKIP_DOTS),
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY
|
||||
);
|
||||
|
||||
foreach ($files as $name => $file) {
|
||||
if (!$file->isDir()) {
|
||||
foreach ($files as $file) {
|
||||
if ($file->isFile()) {
|
||||
$filePath = $file->getRealPath();
|
||||
$relativePath = $zipPath . '/' . substr($filePath, strlen($folder) + 1);
|
||||
$relativePath = $zipPath . '/' . substr($filePath, strlen($folderPath) + 1);
|
||||
$zip->addFile($filePath, $relativePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2,48 +2,51 @@
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Entity\Account;
|
||||
use App\Entity\Customer;
|
||||
use App\Service\Generator\TempPasswordGenerator;
|
||||
use App\Service\Mailer\Event\CreatedAdminEvent;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
#[AsCommand(name: 'mainframe:cron:customer')]
|
||||
class CustomerCommand extends Command
|
||||
{
|
||||
public function __construct(private readonly EventDispatcherInterface $eventDispatcher, private readonly EntityManagerInterface $entityManager, ?string $name = null)
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
?string $name = null
|
||||
) {
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$io->title("Purge all customer delete");
|
||||
foreach ($this->entityManager->getRepository(Customer::class)->findBy(['isDeleted'=>true]) as $delete) {
|
||||
$io->info("Delete account - ".$delete->getRaisonSocial());
|
||||
foreach ($delete->getCustomerContacts()as $customerContact) {
|
||||
$this->entityManager->remove($customerContact);
|
||||
$io->title('Purge all deleted customers');
|
||||
|
||||
$customersToDelete = $this->entityManager->getRepository(Customer::class)->findBy(['isDeleted' => true]);
|
||||
|
||||
foreach ($customersToDelete as $customer) {
|
||||
$io->info(sprintf('Deleting customer: %s', $customer->getRaisonSocial()));
|
||||
|
||||
foreach ($customer->getCustomerContacts() as $contact) {
|
||||
$this->entityManager->remove($contact);
|
||||
}
|
||||
foreach ($delete->getCustomerAdvertPayments() as $customerAdvertPayment) {
|
||||
$this->entityManager->remove($customerAdvertPayment);
|
||||
foreach ($customer->getCustomerAdvertPayments() as $advertPayment) {
|
||||
$this->entityManager->remove($advertPayment);
|
||||
}
|
||||
foreach ($delete->getCustomerDevis() as $customerDevis) {
|
||||
$this->entityManager->remove($customerDevis);
|
||||
foreach ($customer->getCustomerDevis() as $devis) {
|
||||
$this->entityManager->remove($devis);
|
||||
}
|
||||
$this->entityManager->remove($delete);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->entityManager->remove($customer);
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
$io->success('Purge complete.');
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Entity\Revendeur;
|
||||
use App\Repository\RevendeurRepository;
|
||||
use App\Service\Revendeur\RevendeurService;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
@@ -16,29 +14,38 @@ use Symfony\Component\HttpKernel\KernelInterface;
|
||||
#[AsCommand(name: 'mainframe:demande', description: 'Command generate for hosted file')]
|
||||
class DemandeCommand extends Command
|
||||
{
|
||||
|
||||
public function __construct(
|
||||
private readonly KernelInterface $kernelInterface,
|
||||
private readonly KernelInterface $kernel,
|
||||
private readonly RevendeurService $revendeurService,
|
||||
?string $name = null)
|
||||
{
|
||||
?string $name = null
|
||||
) {
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$hosts =[];
|
||||
$hosts[] = "[local_hosts]";
|
||||
/** @var Revendeur $revendeur */
|
||||
$lines = ['[local_hosts]'];
|
||||
|
||||
foreach ($this->revendeurService->list() as $revendeur) {
|
||||
$hosts[] =$revendeur->getCode()."-demande ansible_host=127.0.0.1 path=".$revendeur->getCode()."-demande";
|
||||
$code = $revendeur->getCode();
|
||||
$lines[] = sprintf('%s-demande ansible_host=127.0.0.1 path=%s-demande', $code, $code);
|
||||
}
|
||||
|
||||
$pathFile = $this->kernelInterface->getProjectDir()."/script/demande/hosts.ini";
|
||||
if(file_exists($pathFile)) {
|
||||
unlink($pathFile);
|
||||
$pathFile = $this->kernel->getProjectDir() . '/script/demande/hosts.ini';
|
||||
|
||||
if (file_exists($pathFile) && !unlink($pathFile)) {
|
||||
$output->writeln("<error>Impossible de supprimer le fichier existant : {$pathFile}</error>");
|
||||
return Command::FAILURE;
|
||||
}
|
||||
file_put_contents($pathFile, implode("\n", $hosts));
|
||||
|
||||
$result = file_put_contents($pathFile, implode("\n", $lines));
|
||||
if ($result === false) {
|
||||
$output->writeln("<error>Échec de l'écriture du fichier : {$pathFile}</error>");
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
$output->writeln("<info>Fichier hosts.ini généré avec succès à l'emplacement : {$pathFile}</info>");
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,49 +2,53 @@
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Entity\Account;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\CustomerDnsEmail;
|
||||
use App\Service\Generator\TempPasswordGenerator;
|
||||
use App\Service\Mailer\Event\CreatedAdminEvent;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Exbil\MailCowAPI;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
#[AsCommand(name: 'mainframe:cron:email')]
|
||||
class EmailCommand extends Command
|
||||
{
|
||||
public function __construct(private readonly EventDispatcherInterface $eventDispatcher, private readonly EntityManagerInterface $entityManager, ?string $name = null)
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EventDispatcherInterface $eventDispatcher,
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
?string $name = null
|
||||
) {
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$io->title("Purge all mail delete");
|
||||
foreach ($this->entityManager->getRepository(CustomerDnsEmail::class)->findBy(['isDeleted'=>true]) as $delete) {
|
||||
$io->info("Delete account - ".$delete->getEmail());
|
||||
$client = new MailCowAPI('mail.esy-web.dev',$_ENV['MAILCOW_KEY']);
|
||||
$email = $delete->getEmail()."@".$delete->getDns()->getNdd();
|
||||
$io->title('Purge des emails supprimés');
|
||||
|
||||
$mailcow = new MailCowAPI('mail.esy-web.dev', $_ENV['MAILCOW_KEY']);
|
||||
$emailsToDelete = $this->entityManager->getRepository(CustomerDnsEmail::class)->findBy(['isDeleted' => true]);
|
||||
|
||||
foreach ($emailsToDelete as $emailEntity) {
|
||||
$fullEmail = $emailEntity->getEmail() . '@' . $emailEntity->getDns()->getNdd();
|
||||
$io->info("Suppression boîte mail : $fullEmail");
|
||||
|
||||
try {
|
||||
$client->mailBoxes()->deleteMailBox([$email]);
|
||||
$mailcow->mailBoxes()->deleteMailBox([$fullEmail]);
|
||||
} catch (\Exception $e) {
|
||||
$io->error($e);
|
||||
$io->error("Erreur lors de la suppression de $fullEmail : " . $e->getMessage());
|
||||
// Optionnel : continuer ou interrompre en fonction du besoin
|
||||
}
|
||||
$this->entityManager->remove($delete);
|
||||
|
||||
$this->entityManager->remove($emailEntity);
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
$io->success('Purge terminée avec succès.');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
#[AsCommand(name: 'mainframe:export')]
|
||||
#[AsCommand(name: 'mainframe:export', description: 'Export comptable')]
|
||||
class ExportComptable extends Command
|
||||
{
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
@@ -15,8 +16,18 @@ class ExportComptable extends Command
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$io->title('Export comptable');
|
||||
|
||||
$lines =[];
|
||||
$lines[] = ['JournalCode','JournalLib','EcritureNum','EcritureDate','CompteNum','CompteLib','CompAuxNum','CompAuxLib','PieceRef','PieceDate','EcritureLib','Debit','Credit','EcritureLet','DateLet','ValidDate','Montantdevise','Idevise','DateRglt','ModeRglt','NatOp','IdClient'];
|
||||
// En-têtes de colonnes pour export CSV/comptable
|
||||
$lines = [];
|
||||
$lines[] = [
|
||||
'JournalCode', 'JournalLib', 'EcritureNum', 'EcritureDate', 'CompteNum', 'CompteLib',
|
||||
'CompAuxNum', 'CompAuxLib', 'PieceRef', 'PieceDate', 'EcritureLib', 'Debit', 'Credit',
|
||||
'EcritureLet', 'DateLet', 'ValidDate', 'Montantdevise', 'Idevise', 'DateRglt',
|
||||
'ModeRglt', 'NatOp', 'IdClient'
|
||||
];
|
||||
|
||||
// TODO: Ajouter ici la logique de génération des lignes d’export
|
||||
|
||||
$io->success('Export comptable initialisé. À compléter.');
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
@@ -2,48 +2,60 @@
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Entity\Account;
|
||||
use App\Entity\CustomerDns;
|
||||
use App\Service\Generator\TempPasswordGenerator;
|
||||
use App\Service\Mailer\Event\CreatedAdminEvent;
|
||||
use App\Service\Ovh\Client;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
#[AsCommand(name: 'mainframe:cron:sync')]
|
||||
#[AsCommand(name: 'mainframe:cron:sync', description: 'Synchronise les données DNS')]
|
||||
class SyncCommand extends Command
|
||||
{
|
||||
public function __construct(private readonly EntityManagerInterface $entityManager,private readonly Client $ovhClient,?string $name = null)
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly Client $ovhClient,
|
||||
?string $name = null
|
||||
) {
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$io->title("Sync Data");
|
||||
//sync dns
|
||||
foreach ($this->entityManager->getRepository(CustomerDns::class)->findAll() as $customerDns) {
|
||||
$io->info('Sync DNS - '.$customerDns->getDns());
|
||||
if($customerDns->getRegistar() == "ovh") {
|
||||
$data = $this->ovhClient->info($customerDns->getNdd());
|
||||
if(!is_null($data)){
|
||||
$d = \DateTime::createFromFormat(\DateTime::ATOM,$data['expired']);
|
||||
$customerDns->setExpiredAt($d);
|
||||
$this->entityManager->persist($customerDns);
|
||||
}
|
||||
$io->title('Synchronisation des données DNS');
|
||||
|
||||
$dnsRepository = $this->entityManager->getRepository(CustomerDns::class);
|
||||
$customerDnsList = $dnsRepository->findAll();
|
||||
|
||||
foreach ($customerDnsList as $customerDns) {
|
||||
$io->info(sprintf('Synchronisation DNS pour : %s', $customerDns->getDns()));
|
||||
|
||||
if ($customerDns->getRegistar() !== 'ovh') {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$data = $this->ovhClient->info($customerDns->getNdd());
|
||||
if ($data !== null && isset($data['expired'])) {
|
||||
$expiredAt = \DateTime::createFromFormat(\DateTime::ATOM, $data['expired']);
|
||||
if ($expiredAt !== false) {
|
||||
$customerDns->setExpiredAt($expiredAt);
|
||||
$this->entityManager->persist($customerDns);
|
||||
$io->writeln('Date d’expiration mise à jour : ' . $expiredAt->format('Y-m-d'));
|
||||
} else {
|
||||
$io->warning('Format de date invalide pour ' . $customerDns->getNdd());
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$io->error(sprintf('Erreur lors de la synchro DNS pour %s : %s', $customerDns->getNdd(), $e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
$io->success('Synchronisation terminée');
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
@@ -2,35 +2,35 @@
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Entity\Account;
|
||||
use App\Service\Mailer\Event\CreatedAdminEvent;
|
||||
use App\Service\Mailer\Mailer;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
#[AsCommand(name: 'mainframe:testmail')]
|
||||
#[AsCommand(name: 'mainframe:testmail', description: 'Commande de test pour l\'envoi de mail')]
|
||||
class TestMailerCommand extends Command
|
||||
{
|
||||
public function __construct(private readonly Mailer $mailer, ?string $name = null)
|
||||
{
|
||||
public function __construct(
|
||||
private readonly Mailer $mailer,
|
||||
?string $name = null
|
||||
) {
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$io->title("TEST MAILER");
|
||||
$_ENV['REAL_MAIL'] = "1";
|
||||
$this->mailer->sendTest();
|
||||
|
||||
$io->title('Test Mailer');
|
||||
|
||||
try {
|
||||
$this->mailer->sendTest();
|
||||
$io->success('Test d\'envoi de mail effectué avec succès.');
|
||||
} catch (\Exception $e) {
|
||||
$io->error('Erreur lors de l\'envoi du mail : ' . $e->getMessage());
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user