651 lines
25 KiB
PHP
651 lines
25 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
/**
|
|
* Calendar App
|
|
*
|
|
* @copyright 2021 Anna Larch <anna.larch@gmx.net>
|
|
*
|
|
* @author Anna Larch <anna.larch@gmx.net>
|
|
* @author Richard Steinmetz <richard@steinmetz.cloud>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
|
* License as published by the Free Software Foundation; either
|
|
* version 3 of the License, or any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
namespace OCA\Gestion\Service;
|
|
|
|
use DateTime;
|
|
use Exception;
|
|
use OCA\Gestion\Db\Bdd;
|
|
use OCP\Files\IRootFolder;
|
|
use OCA\Gestion\Helpers\DateHelpers;
|
|
use OCA\Gestion\Constants\BddConstant;
|
|
use OCA\Gestion\Service\HtmlToPdfService;
|
|
use OCA\Gestion\Exception\TemplateException;
|
|
use OCA\Gestion\Constants\FactureTypeConstant;
|
|
use OCA\Gestion\Constants\DevisMentionConstant;
|
|
use OCA\Gestion\Constants\ClientTemplateTypeConstant;
|
|
use OCA\Gestion\Constants\MultipleFactureTypeConstant;
|
|
use OCA\Gestion\Service\InvoiceRecap\InvoiceRecapService;
|
|
use OCA\Gestion\Service\InvoiceGroupPdfHandler\InvoiceOgfPdfHandler;
|
|
use OCA\Gestion\Service\InvoiceGroupPdfHandler\InvoiceGroupPdfHandler;
|
|
use OCA\Gestion\Service\InvoiceGroupPdfHandler\InvoiceFunecapPdfHandler;
|
|
|
|
class InvoicePdfService
|
|
{
|
|
/** @var Bdd */
|
|
private $gestionBdd;
|
|
|
|
/** @var IRootFolder */
|
|
private $rootFolder;
|
|
|
|
/** @var InvoiceRecapService */
|
|
private $invoiceRecapService;
|
|
|
|
private $htmlToPdfService;
|
|
|
|
private const DEFAULT_NEXTCLOUD_ADMIN = "admin";
|
|
public function __construct(
|
|
Bdd $gestionBdd,
|
|
IRootFolder $rootFolder,
|
|
InvoiceRecapService $invoiceRecapService
|
|
) {
|
|
$this->gestionBdd = $gestionBdd;
|
|
$this->rootFolder = $rootFolder;
|
|
$this->invoiceRecapService = $invoiceRecapService;
|
|
$this->htmlToPdfService = new HtmlToPdfService();
|
|
}
|
|
|
|
private function getLogo()
|
|
{
|
|
$storage = $this->rootFolder->getUserFolder(self::DEFAULT_NEXTCLOUD_ADMIN);
|
|
try {
|
|
try {
|
|
if(isset($storage)) {
|
|
$file = $storage->get('/.gestion/logo.png');
|
|
} else {
|
|
return "nothing";
|
|
}
|
|
} catch(\OCP\Files\NotFoundException $e) {
|
|
$file = $storage->get('/.gestion/logo.jpeg');
|
|
}
|
|
} catch(\OCP\Files\NotFoundException $e) {
|
|
return "nothing";
|
|
}
|
|
|
|
return base64_encode($file->getContent());
|
|
}
|
|
|
|
private function generateFactureSinglePdfByFactureId($factureId, $idNextCloud)
|
|
{
|
|
$storage = $this->rootFolder->getUserFolder($idNextCloud);
|
|
$configs = json_decode($this->gestionBdd->getConfiguration(self::DEFAULT_NEXTCLOUD_ADMIN));
|
|
$currentConfig = $configs[0];
|
|
$logo = $this->getLogo();
|
|
$invoicePdfData = $this->gestionBdd->getInvoicePdfData($factureId, $currentConfig);
|
|
if($invoicePdfData == null) {
|
|
return null;
|
|
}
|
|
$clean_folder = html_entity_decode(string: $currentConfig->path).'/';
|
|
$factureFolders = $this->getFacturesFolder($invoicePdfData, $clean_folder);
|
|
$pdf = new InvoicePdfHandler();
|
|
$pdf->AddFont('ComicSans', '', 'Comic Sans MS.php');
|
|
$pdf->AddFont('ComicSans', 'B', 'comic-sans-bold.php');
|
|
$pdf->InvoicePdfFactory($invoicePdfData, $logo);
|
|
$pdf->SetFactureContent();
|
|
$pdfContent = $pdf->Output('', 'S');
|
|
$pdfFilename = $pdf->GetInvoiceFilename();
|
|
$prefixPdf = "FACTURE";
|
|
if($invoicePdfData['is_negative']) {
|
|
$prefixPdf = "AVOIR";
|
|
}
|
|
$pdfFilename = $prefixPdf."_".$pdfFilename;
|
|
$filenames = [];
|
|
$filenames = $this->savePdfToFolders($factureFolders, $pdfFilename, $pdfContent, $storage);
|
|
$this->gestionBdd->setFactureGeneratedDate($factureId);
|
|
return [
|
|
"content" => $pdfContent,
|
|
"filenames" => $filenames
|
|
];
|
|
}
|
|
|
|
public function generateFacturePdfByFactureId($factureId, $idNextCloud)
|
|
{
|
|
$factureType = $this->gestionBdd->getFactureTypeByFactureId($factureId);
|
|
if($factureType == FactureTypeConstant::TYPE_SINGLE) {
|
|
return $this->generateFactureSinglePdfByFactureId($factureId, $idNextCloud);
|
|
} else {
|
|
return $this->generateFactureGroupPdfByFactureId($factureId, $idNextCloud);
|
|
}
|
|
}
|
|
|
|
private function getGroupFactureFolder(array $factureData, $racinePath)
|
|
{
|
|
$clientRacineFolder = $racinePath.'CLIENTS/'.mb_strtoupper($factureData["group_name"], 'UTF-8').'/';
|
|
$factureDate = $factureData['date_paiement'];
|
|
$factureDatetime = new DateTime($factureDate);
|
|
$factureDateYear = $factureDatetime->format('Y');
|
|
$factureMonth = DateHelpers::GetDateWithFormatDayAndMonthPlainString($factureData['date_paiement']);
|
|
$factureByYearFolder = $clientRacineFolder."$factureDateYear".'/'.$factureMonth.'/'.'FACTURES'.'/';
|
|
return [
|
|
$factureByYearFolder
|
|
];
|
|
}
|
|
|
|
private function getFacturesFolder(array $factureData, $racinePath)
|
|
{
|
|
$clientRacineFolder = $racinePath.'CLIENTS/'.mb_strtoupper($factureData["client_nom"], 'UTF-8').'/';
|
|
$defuntsFolder = $clientRacineFolder.'DEFUNTS/'.mb_strtoupper($factureData['defunt_nom'], 'UTF-8').'/'.'FACTURES'.'/';
|
|
$devisDate = $factureData['devis_date'];
|
|
$devisDatetime = new DateTime($devisDate);
|
|
$devisDateYear = $devisDatetime->format('Y');
|
|
$devisMonth = DateHelpers::GetDateWithFormatDayAndMonthPlainString($factureData['devis_date']);
|
|
$factureByYearFolder = $clientRacineFolder."$devisDateYear".'/'.$devisMonth.'/'.'FACTURES'.'/';
|
|
return [
|
|
$defuntsFolder,
|
|
$factureByYearFolder
|
|
];
|
|
}
|
|
|
|
private function generateFactureGroupPdfByFactureId($factureId, $idNextCloud)
|
|
{
|
|
$storage = $this->rootFolder->getUserFolder($idNextCloud);
|
|
$configs = json_decode($this->gestionBdd->getConfiguration(self::DEFAULT_NEXTCLOUD_ADMIN));
|
|
$currentConfig = $configs[0];
|
|
$logo = $this->getLogo();
|
|
$invoicePdfData = $this->gestionBdd->getInvoiceGroupPdfData($factureId, $currentConfig);
|
|
if($invoicePdfData == null) {
|
|
return "";
|
|
}
|
|
|
|
// NOUVELLE LOGIQUE : Vérifier si TVA exonérée
|
|
/*if ($this->isTvaExempt($invoicePdfData)) {
|
|
return $this->generateWithHtmlTemplate($invoicePdfData, $storage);
|
|
}*/
|
|
|
|
$templateType = $invoicePdfData['template_type_key'];
|
|
$clean_folder = html_entity_decode(string: $currentConfig->path).'/';
|
|
$factureFolders = $this->getGroupFactureFolder($invoicePdfData, $clean_folder);
|
|
//For testing
|
|
// $templateType = ClientTemplateTypeConstant::OGF;
|
|
|
|
switch ($templateType) {
|
|
case ClientTemplateTypeConstant::FUNECAP:
|
|
$pdf = new InvoiceFunecapPdfHandler();
|
|
break;
|
|
|
|
case ClientTemplateTypeConstant::OGF:
|
|
$pdf = new InvoiceOgfPdfHandler();
|
|
break;
|
|
|
|
default:
|
|
$pdf = new InvoiceGroupPdfHandler();
|
|
break;
|
|
}
|
|
$pdf->AddFont('ComicSans', '', 'Comic Sans MS.php');
|
|
$pdf->AddFont('ComicSans', 'B', 'comic-sans-bold.php');
|
|
$pdf->InvoicePdfFactory($invoicePdfData, $logo);
|
|
$pdf->SetFactureContent();
|
|
$pdfContent = $pdf->Output('', 'S');
|
|
$pdfFilename = $pdf->GetInvoiceFilename();
|
|
$filenames = [];
|
|
$filenames = $this->savePdfToFolders($factureFolders, $pdfFilename, $pdfContent, $storage);
|
|
$this->gestionBdd->setFactureGeneratedDate($factureId);
|
|
return [
|
|
"content" => $pdfContent,
|
|
"filenames" => $filenames
|
|
];
|
|
}
|
|
|
|
public function sanitizePathDev(string $path): string
|
|
{
|
|
$path = ltrim($path, '/');
|
|
// Remplacer accents UTF-8 par ASCII
|
|
$path = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $path);
|
|
// Supprimer caractères interdits par Nextcloud/Docker
|
|
$path = preg_replace('#[<>:"/\\|?*]#', '_', $path);
|
|
// Supprimer doublons d'espaces
|
|
$path = preg_replace('#\s+#', ' ', $path);
|
|
return trim($path);
|
|
}
|
|
|
|
|
|
public function generateFacturePdfByFactureIds(array $factureIds, $idNextCloud)
|
|
{
|
|
foreach($factureIds as $factureId) {
|
|
$this->generateFacturePdfByFactureId($factureId, $idNextCloud);
|
|
}
|
|
}
|
|
|
|
public function generateMultipleInvoicePdfByClientAndMonthYear($filter, $month, $year, $idNextCloud, $filterType)
|
|
{
|
|
$storage = $this->rootFolder->getUserFolder($idNextCloud);
|
|
$configs = json_decode($this->gestionBdd->getConfiguration(self::DEFAULT_NEXTCLOUD_ADMIN));
|
|
$currentConfig = $configs[0];
|
|
$logo = $this->getLogo();
|
|
$invoiceData = $this->gestionBdd->getInvoicePdfDataByClientAndMonthYear($filter, $month, $year, $currentConfig, $filterType);
|
|
if(empty($invoiceData)) {
|
|
return null;
|
|
}
|
|
$pdf = new InvoicePdfHandler();
|
|
$pdf->AddFont('ComicSans', '', 'Comic Sans MS.php');
|
|
$pdf->AddFont('ComicSans', 'B', 'comic-sans-bold.php');
|
|
$pdf->MutlipleInvoicePdfFactory($invoiceData, $logo);
|
|
$pdf->SetMultipleFactureContent();
|
|
$racinePath = html_entity_decode(string: $currentConfig->path).'/';
|
|
$clientNameInFolder = $invoiceData[0]["client_nom"];
|
|
if($invoiceData[0]['facture_type'] == MultipleFactureTypeConstant::GROUP_FILTER_TYPE) {
|
|
if($invoiceData[0]["group_name"] != null && $invoiceData[0]["group_name"] != "") {
|
|
$clientNameInFolder = $invoiceData[0]["group_name"];
|
|
}
|
|
}
|
|
$clientRacineFolder = $racinePath.'CLIENTS/'.mb_strtoupper($clientNameInFolder, 'UTF-8').'/';
|
|
$filename = "FACTURE".'_'.$pdf->GetMultipleInvoiceFilename($month, $year);
|
|
$pdfContent = $pdf->Output('', 'S');
|
|
$singleFolderArray = [$clientRacineFolder];
|
|
$filenames = $this->savePdfToFolders($singleFolderArray, $filename, $pdfContent, $storage);
|
|
return $filenames[0];
|
|
}
|
|
|
|
public function generateInvoiceRecap($filter, $filterType, $date, $idNextCloud)
|
|
{
|
|
$this->invoiceRecapService->generateInvoiceRecap($filter, $filterType, $date, $idNextCloud);
|
|
}
|
|
|
|
public function exportGroupOfDevisIntoFacture($clientId, $clientType, $month, $year, $facturationDate, $idNextcloud = BddConstant::DEFAULT_ADMIN_ID_NEXTCLOUD)
|
|
{
|
|
try {
|
|
$datetime = new Datetime();
|
|
$month = $month ?? $datetime->format('m');
|
|
$year = $year ?? $datetime->format('Y');
|
|
|
|
$factureId = null;
|
|
$fkClientId = null;
|
|
$fkClientGroupFacturationId = null;
|
|
$devisMentionFiltersToBeInvoiced = [
|
|
DevisMentionConstant::NEW,
|
|
DevisMentionConstant::MENTION
|
|
];
|
|
// Recuperer les devis non facturés du client avant la date de facturation du mois
|
|
//Si il a devis qui n est pas encore facturés
|
|
//Cree un facture, atttaché l ID du facture au devis et generer le pdf
|
|
|
|
if($clientType == MultipleFactureTypeConstant::CLIENT_FILTER_TYPE) {
|
|
$devisIds = $this->gestionBdd->getDevisIdsByClientIdAndDate($clientId, $facturationDate, $devisMentionFiltersToBeInvoiced);
|
|
$fkClientId = $clientId;
|
|
$factureId = $this->gestionBdd->getFactureIdByClientIdAndDate($clientId, $facturationDate);
|
|
|
|
} else {
|
|
$devisIds = $this->gestionBdd->getDevisIdsByClientGroupFacturationIdAnDate($clientId, $facturationDate, $devisMentionFiltersToBeInvoiced);
|
|
$fkClientGroupFacturationId = $clientId;
|
|
$factureId = $this->gestionBdd->getFactureIdByClientGroupFacturationIdAndDate($clientId, $facturationDate);
|
|
|
|
}
|
|
// if($clientType == MultipleFactureTypeConstant::CLIENT_FILTER_TYPE){
|
|
// $devisIds = $this->gestionBdd->getDevisIdsByClientIdAndMonthYear($clientId,$month,$year,$devisMentionFiltersToBeInvoiced);
|
|
// $fkClientId = $clientId;
|
|
// }
|
|
// else{
|
|
// $factureId = $this->gestionBdd->getFactureIdByClientGroupFacturationIdAndMonthYear($clientId,$month,$year);
|
|
// $devisIds = $this->gestionBdd->getDevisIdsByClientGroupFacturationIdAndMonthYear($clientId,$month,$year);
|
|
// $fkClientGroupFacturationId = $clientId;
|
|
// }
|
|
// $clientIsAlreadyFacturedForThisMonthAndYear = $factureId != null && $factureId != 0;
|
|
// if($clientIsAlreadyFacturedForThisMonthAndYear == false){
|
|
// $factureId = $this->gestionBdd->createFactureAndReturnFactureId(
|
|
// $facturationDate,
|
|
// FactureTypeConstant::TYPE_GROUP,
|
|
// $month,
|
|
// $year,
|
|
// $fkClientId,
|
|
// $fkClientGroupFacturationId);
|
|
// }
|
|
|
|
if (!empty($devisIds)) {
|
|
//Get facture by date and client
|
|
$clientIsAlreadyFacturedForThisDate = $factureId != null && $factureId != 0;
|
|
if (!$clientIsAlreadyFacturedForThisDate) {
|
|
$factureId = $this->gestionBdd->createFactureAndReturnFactureId(
|
|
$facturationDate,
|
|
FactureTypeConstant::TYPE_GROUP,
|
|
$month,
|
|
$year,
|
|
$fkClientId,
|
|
$fkClientGroupFacturationId
|
|
);
|
|
}
|
|
$this->gestionBdd->invoiceListOfDevisIds($devisIds, $factureId);
|
|
$factureGeneratedResponse = $this->generateFactureGroupPdfByFactureId($factureId, $idNextcloud);
|
|
return $factureGeneratedResponse["filenames"];
|
|
}
|
|
return null;
|
|
} catch(Exception) {
|
|
return null;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* NOUVELLE MÉTHODE : Génération avec template HTML
|
|
*/
|
|
private function generateWithHtmlTemplate($invoicePdfData, $storage)
|
|
{
|
|
try {
|
|
// Préparer les données pour le template HTML
|
|
$templateData = $this->prepareHtmlTemplateData($invoicePdfData);
|
|
|
|
// Générer le PDF avec le nouveau système
|
|
$pdfContent = $this->htmlToPdfService->generatePdf('facture_dv_thanato', $templateData);
|
|
|
|
// Nom du fichier
|
|
$pdfFilename = $this->htmlToPdfService->generateInvoiceFilename($invoicePdfData);
|
|
|
|
// Sauvegarder dans Nextcloud
|
|
$clean_folder = html_entity_decode(string: $invoicePdfData['configuration']->path).'/';
|
|
$factureFolders = $this->getGroupFactureFolder($invoicePdfData, $clean_folder);
|
|
$filenames = [];
|
|
$filenames = $this->savePdfToFolders($factureFolders, $pdfFilename, $pdfContent, $storage);
|
|
$this->gestionBdd->setFactureGeneratedDate($invoicePdfData['id']);
|
|
|
|
return [
|
|
"content" => $pdfContent,
|
|
"filenames" => $filenames
|
|
];
|
|
|
|
} catch (TemplateException $e) {
|
|
error_log('HTML Template PDF Error: ' . $e->getMessage());
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* NOUVELLE MÉTHODE : Détecte si TVA exonérée
|
|
*/
|
|
private function isTvaExempt($invoicePdfData)
|
|
{
|
|
// Vérifier si c'est un client unique avec TVA = 0
|
|
if (isset($invoicePdfData['fk_client_id']) && $invoicePdfData['fk_client_id'] != null && $invoicePdfData['fk_client_id'] != 0) {
|
|
$client = $this->gestionBdd->getClientById($invoicePdfData['fk_client_id']);
|
|
if (isset($client['tva']) && $client['tva'] == 0) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Prépare les données pour le template HTML - Version refactorisée
|
|
*/
|
|
private function prepareHtmlTemplateData($invoicePdfData)
|
|
{
|
|
return [
|
|
'company' => $this->prepareCompanyData($invoicePdfData),
|
|
'client' => $this->prepareClientData($invoicePdfData),
|
|
'facture' => $this->prepareInvoiceData($invoicePdfData),
|
|
'groupedArticles' => $this->prepareGroupedArticles($invoicePdfData),
|
|
'totals' => $this->prepareTotals($invoicePdfData),
|
|
'bank' => $this->prepareBankData($invoicePdfData),
|
|
'legal_text' => $this->getLegalText()
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Prépare les données de l'entreprise
|
|
*/
|
|
private function prepareCompanyData($invoicePdfData)
|
|
{
|
|
$config = $invoicePdfData['configuration'];
|
|
|
|
return [
|
|
'name' => $config->entreprise ?? 'DV Thanato',
|
|
'address' => $invoicePdfData['configuration_adresse'] ?? '47 rue Boldoduc',
|
|
'city' => $invoicePdfData['configuration_adresse_city'] ?? '59800 Lille',
|
|
'phone' => $config->telephone ?? '06.13.57.29.84',
|
|
'email' => $config->mail ?? 'soins@dvthanato.fr',
|
|
'logo' => 'logo_dv_thanato.png'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Prépare les données du client
|
|
*/
|
|
private function prepareClientData($invoicePdfData)
|
|
{
|
|
return [
|
|
'name' => $invoicePdfData['group_name'] ?? '',
|
|
'address' => $invoicePdfData['client_real_adress'] ?? '',
|
|
'city' => $invoicePdfData['client_adress_city'] ?? '',
|
|
'siret' => $invoicePdfData['siret'] ?? ''
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Prépare les données de la facture
|
|
*/
|
|
private function prepareInvoiceData($invoicePdfData)
|
|
{
|
|
$numero = $invoicePdfData['num'] ?? '';
|
|
|
|
return [
|
|
'date' => date('d-m-Y'),
|
|
'number' => 'FAC' . str_pad((string)$numero, 6, '0', STR_PAD_LEFT),
|
|
'echeance' => date('d-m-Y', strtotime('+30 days')),
|
|
'period_start' => date('d/m/Y', strtotime($invoicePdfData['date'] ?? 'now')),
|
|
'period_end' => date('d/m/Y', strtotime($invoicePdfData['date_paiement'] ?? 'now'))
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Prépare les articles groupés par date et défunt
|
|
*/
|
|
private function prepareGroupedArticles($invoicePdfData)
|
|
{
|
|
if (!isset($invoicePdfData['devis']) || !is_array($invoicePdfData['devis'])) {
|
|
return [];
|
|
}
|
|
|
|
$groupedByDate = [];
|
|
|
|
foreach ($invoicePdfData['devis'] as $devis) {
|
|
$this->processDevis($devis, $groupedByDate);
|
|
}
|
|
|
|
return $this->convertToIndexedArray($groupedByDate);
|
|
}
|
|
|
|
/**
|
|
* Traite un devis et l'ajoute aux données groupées
|
|
*/
|
|
private function processDevis($devis, &$groupedByDate)
|
|
{
|
|
$dateDevis = date('d/m/Y', strtotime($devis['devis_date'] ?? 'now'));
|
|
$defuntNom = $devis['defunt_nom'] ?? 'Non défini';
|
|
|
|
$this->initializeDateGroup($groupedByDate, $dateDevis);
|
|
$this->initializeDefuntGroup($groupedByDate, $dateDevis, $defuntNom);
|
|
$this->addServicesToDefunt($groupedByDate, $dateDevis, $defuntNom, $devis['products'] ?? []);
|
|
}
|
|
|
|
/**
|
|
* Initialise un groupe de date
|
|
*/
|
|
private function initializeDateGroup(&$groupedByDate, $dateDevis)
|
|
{
|
|
if (!isset($groupedByDate[$dateDevis])) {
|
|
$groupedByDate[$dateDevis] = [
|
|
'date' => $dateDevis,
|
|
'defunts' => []
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialise un groupe de défunt
|
|
*/
|
|
private function initializeDefuntGroup(&$groupedByDate, $dateDevis, $defuntNom)
|
|
{
|
|
if (!isset($groupedByDate[$dateDevis]['defunts'][$defuntNom])) {
|
|
$groupedByDate[$dateDevis]['defunts'][$defuntNom] = [
|
|
'nom' => $defuntNom,
|
|
'services' => []
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ajoute les services à un défunt
|
|
*/
|
|
private function addServicesToDefunt(&$groupedByDate, $dateDevis, $defuntNom, $products)
|
|
{
|
|
foreach ($products as $product) {
|
|
$service = $this->createServiceFromProduct($product);
|
|
$groupedByDate[$dateDevis]['defunts'][$defuntNom]['services'][] = $service;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Crée un service à partir d'un produit
|
|
*/
|
|
private function createServiceFromProduct($product)
|
|
{
|
|
$prixHt = ($product['produit_price'] ?? 0) * ($product['quantite'] ?? 1);
|
|
|
|
return [
|
|
'reference' => $product['produit_reference'] ?? '',
|
|
'description' => $product['produit_description'] ?? 'Produit inconnu',
|
|
'prix_ht' => number_format($prixHt, 2, ',', ' '),
|
|
'quantite' => number_format($product['quantite'] ?? 1, 2, ',', ' '),
|
|
'prix_ttc' => number_format($prixHt, 2, ',', ' ')
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Convertit les données groupées en array indexé
|
|
*/
|
|
private function convertToIndexedArray($groupedByDate)
|
|
{
|
|
$groupedArticles = [];
|
|
|
|
foreach ($groupedByDate as $dateGroup) {
|
|
$defuntsArray = array_values($dateGroup['defunts']);
|
|
$dateGroup['defunts'] = $defuntsArray;
|
|
$groupedArticles[] = $dateGroup;
|
|
}
|
|
|
|
return $groupedArticles;
|
|
}
|
|
|
|
/**
|
|
* Prépare les totaux
|
|
*/
|
|
private function prepareTotals($invoicePdfData)
|
|
{
|
|
$totalPrices = $invoicePdfData['totalPrices'] ?? [];
|
|
|
|
return [
|
|
'total_ht' => number_format($totalPrices['TOTAL HT'] ?? 0, 2, ',', ' '),
|
|
'total_tva' => '0,00',
|
|
'total_ttc' => number_format($totalPrices['TOTAL TTC'] ?? 0, 2, ',', ' '),
|
|
'tva_label' => 'TVA (exonéré)'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Prépare les données bancaires
|
|
*/
|
|
private function prepareBankData($invoicePdfData)
|
|
{
|
|
$config = $invoicePdfData['configuration'];
|
|
|
|
return [
|
|
'iban' => 'FR76 1670 6052 4453 9757 9734 871',
|
|
'swift' => 'AGRI FR PP867',
|
|
'rcs' => $config->legal_one ?? '901 115 931 R.C.S Lille Métropole'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Texte légal
|
|
*/
|
|
private function getLegalText()
|
|
{
|
|
return "Tout retard de paiement entraînera de plein droit une pénalité de retard de 3 fois le taux légal " .
|
|
"(Loi 2008-776 du 4 août 2008) et une indemnité forfaitaire de 40 EUR pour frais de recouvrement sera appliquée.\n" .
|
|
"Si les frais de recouvrement sont supérieurs à ce montant forfaitaire, une indemnisation complémentaire " .
|
|
"sera due sur présentation de justificatifs (articles L 441-3 et L 441-6 du code de commerce).";
|
|
}
|
|
|
|
/**
|
|
* Fonction générique pour sauvegarder un fichier PDF dans plusieurs dossiers
|
|
*
|
|
* @param array $factureFolders Liste des dossiers où sauvegarder
|
|
* @param string $pdfFilename Nom du fichier PDF (sans extension)
|
|
* @param string $pdfContent Contenu binaire du PDF
|
|
* @param mixed $storage Instance de stockage Nextcloud
|
|
* @return array Liste des chemins des fichiers créés
|
|
*/
|
|
private function savePdfToFolders(array $factureFolders, string $pdfFilename, string $pdfContent, $storage): array
|
|
{
|
|
$filenames = [];
|
|
|
|
foreach ($factureFolders as $folder) {
|
|
// Créer le chemin complet étape par étape
|
|
$this->ensurePathExists($storage, $folder);
|
|
|
|
$ff_pdf = $folder . $pdfFilename . '.pdf';
|
|
|
|
try {
|
|
if ($storage->nodeExists($ff_pdf)) {
|
|
$file_pdf = $storage->get($ff_pdf);
|
|
} else {
|
|
$file_pdf = $storage->newFile($ff_pdf);
|
|
}
|
|
$file_pdf->putContent($pdfContent);
|
|
$filenames[] = $ff_pdf;
|
|
} catch (\Throwable $e) {
|
|
// Supprimez ce var_dump pour éviter l'erreur de headers
|
|
// var_dump("yyyyyyyyyyyyyyyyyyyy".$e->getMessage());
|
|
error_log("ERROR on file '$ff_pdf': " . $e->getMessage());
|
|
continue;
|
|
}
|
|
}
|
|
|
|
return $filenames;
|
|
}
|
|
|
|
private function ensurePathExists($storage, $path)
|
|
{
|
|
$parts = explode('/', trim($path, '/'));
|
|
$currentPath = '';
|
|
|
|
foreach ($parts as $part) {
|
|
if (empty($part)) {
|
|
continue;
|
|
}
|
|
|
|
$currentPath .= '/' . $part;
|
|
|
|
try {
|
|
if (!$storage->nodeExists($currentPath)) {
|
|
$storage->newFolder($currentPath);
|
|
}
|
|
} catch (\Throwable $e) {
|
|
error_log("Cannot create folder '$currentPath': " . $e->getMessage());
|
|
}
|
|
}
|
|
}
|
|
}
|