feat generate recap devis
This commit is contained in:
parent
90d9b5a52c
commit
a278022748
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'routes' => [
|
'routes' => [
|
||||||
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
|
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
|
||||||
@ -72,6 +73,7 @@ return [
|
|||||||
['name' => 'page#exportDevisToFacture', 'url' => '/exportDevisToFacture', 'verb' => 'POST'],
|
['name' => 'page#exportDevisToFacture', 'url' => '/exportDevisToFacture', 'verb' => 'POST'],
|
||||||
['name' => 'page#exportFactureToPdf', 'url' => '/facture/exportFactureToPdf', 'verb' => 'POST'],
|
['name' => 'page#exportFactureToPdf', 'url' => '/facture/exportFactureToPdf', 'verb' => 'POST'],
|
||||||
['name' => 'page#exportFactureByClientAndMonthYearToPdf', 'url' => '/facture/exportFactureByClientAndMonthYearToPdf', 'verb' => 'POST'],
|
['name' => 'page#exportFactureByClientAndMonthYearToPdf', 'url' => '/facture/exportFactureByClientAndMonthYearToPdf', 'verb' => 'POST'],
|
||||||
|
['name' => 'page#exportDevisRecap', 'url' => '/devis/exportDevisRecap', 'verb' => 'POST'],
|
||||||
|
|
||||||
['name' => 'page#getProduits', 'url' => '/getProduits', 'verb' => 'PROPFIND'],
|
['name' => 'page#getProduits', 'url' => '/getProduits', 'verb' => 'PROPFIND'],
|
||||||
['name' => 'page#getProduitsById', 'url' => '/getProduitsById', 'verb' => 'POST'],
|
['name' => 'page#getProduitsById', 'url' => '/getProduitsById', 'verb' => 'POST'],
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
173
gestion/lib/Service/Devis/DevisDataProcessor.php
Normal file
173
gestion/lib/Service/Devis/DevisDataProcessor.php
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace OCA\Gestion\Service\Devis;
|
||||||
|
|
||||||
|
use OCA\Gestion\Db\Bdd;
|
||||||
|
use OCA\Gestion\Constants\MultipleFactureTypeConstant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe responsable du traitement et de la préparation des données de devis
|
||||||
|
*/
|
||||||
|
class DevisDataProcessor
|
||||||
|
{
|
||||||
|
/** @var Bdd */
|
||||||
|
private $gestionBdd;
|
||||||
|
|
||||||
|
public function __construct(Bdd $gestionBdd)
|
||||||
|
{
|
||||||
|
$this->gestionBdd = $gestionBdd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepareDevisData($devisData, $currentConfig, $filter, $idNextCloud)
|
||||||
|
{
|
||||||
|
$data_devis = [];
|
||||||
|
|
||||||
|
foreach ($devisData as $devis) {
|
||||||
|
$devis_temp = $this->createDevisStructure($devis, $currentConfig);
|
||||||
|
$devis_temp = $this->calculateDevisAmounts($devis_temp, $devis, $filter, $idNextCloud);
|
||||||
|
$data_devis[] = $devis_temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data_devis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createDevisStructure($devis, $currentConfig)
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'devis_id' => $devis['devis_id'],
|
||||||
|
'devis_full_number' => $devis['devis_full_number'],
|
||||||
|
'calendar_uuid' => $devis['calendar_uuid'],
|
||||||
|
'num_commande' => '',
|
||||||
|
'devis_date' => $devis['devis_date'],
|
||||||
|
'lieu_nom' => $devis['lieu_nom'],
|
||||||
|
'lieu_adresse' => $devis['lieu_adresse'],
|
||||||
|
'defunt_nom' => $devis['defunt_nom'],
|
||||||
|
'defunt_sexe' => $devis['defunt_sexe'],
|
||||||
|
'client_nom' => $devis['client_nom'],
|
||||||
|
'client_entreprise' => $devis['client_entreprise'],
|
||||||
|
'client_adresse' => $devis['client_adresse'],
|
||||||
|
'group_name' => $devis['group_name'],
|
||||||
|
'group_address' => $devis['group_address'],
|
||||||
|
'group_postal_code' => $devis['group_postal_code'],
|
||||||
|
'group_city' => $devis['group_city'],
|
||||||
|
'group_email' => $devis['group_email'],
|
||||||
|
'group_siret_number' => $devis['group_siret_number'],
|
||||||
|
'montant_htc' => 0,
|
||||||
|
'tva' => $currentConfig->tva_default,
|
||||||
|
'montant_tva' => 0,
|
||||||
|
'montant_ttc' => 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function calculateDevisAmounts($devis_temp, $devis, $filter, $idNextCloud)
|
||||||
|
{
|
||||||
|
$produits = json_decode($this->gestionBdd->getListProduit($devis['devis_id'], $idNextCloud));
|
||||||
|
|
||||||
|
foreach ($produits as $produit) {
|
||||||
|
$htPrice = $this->getProductPrice($produit, $devis, $filter);
|
||||||
|
$devis_temp['montant_htc'] += $htPrice * $produit->quantite;
|
||||||
|
}
|
||||||
|
|
||||||
|
$devis_temp['montant_tva'] = ($devis_temp['montant_htc'] * $devis_temp['tva']) / 100;
|
||||||
|
$devis_temp['montant_ttc'] = $devis_temp['montant_tva'] + $devis_temp['montant_htc'];
|
||||||
|
|
||||||
|
return $devis_temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getProductPrice($produit, $devis, $filter)
|
||||||
|
{
|
||||||
|
$htPrice = $produit->prix_unitaire;
|
||||||
|
|
||||||
|
if ($devis['group_name'] != null) {
|
||||||
|
$price = $this->gestionBdd->getProductPriceByClientGroupId($filter, $produit->id);
|
||||||
|
if ($price != null) {
|
||||||
|
$htPrice = $price;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $htPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClientInfoForDevis($devis, $filterType)
|
||||||
|
{
|
||||||
|
if ($filterType === 'group' && !empty($devis['group_name'])) {
|
||||||
|
return [
|
||||||
|
'name' => 'Groupe ' . $devis['group_name'],
|
||||||
|
'address' => $devis['group_address'],
|
||||||
|
'city' => $devis['group_postal_code'] . ' ' . $devis['group_city'],
|
||||||
|
'siret' => $devis['group_siret_number'],
|
||||||
|
'email' => $devis['group_email']
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$clientAddresses = \OCA\Gestion\Helpers\FileExportHelpers::GetAddressAndCityFromAddress($devis['client_adresse']);
|
||||||
|
return [
|
||||||
|
'name' => $devis['client_nom'],
|
||||||
|
'address' => $clientAddresses['address'],
|
||||||
|
'city' => $clientAddresses['city'],
|
||||||
|
'siret' => '',
|
||||||
|
'email' => ''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generateCsvContent($devisData)
|
||||||
|
{
|
||||||
|
$headers = [
|
||||||
|
'Numéro Devis',
|
||||||
|
'Date',
|
||||||
|
'Client Nom',
|
||||||
|
'Client Entreprise',
|
||||||
|
'Défunt',
|
||||||
|
'Lieu',
|
||||||
|
'Thanatopracteur',
|
||||||
|
'Commentaire',
|
||||||
|
'UUID Calendrier'
|
||||||
|
];
|
||||||
|
|
||||||
|
$csvContent = $this->arrayToCsv($headers);
|
||||||
|
|
||||||
|
foreach ($devisData as $devis) {
|
||||||
|
$row = [
|
||||||
|
$devis['devis_full_number'] ?? '',
|
||||||
|
$devis['devis_date'] ?? '',
|
||||||
|
$devis['client_nom'] ?? '',
|
||||||
|
$devis['client_entreprise'] ?? '',
|
||||||
|
$devis['defunt_nom'] ?? '',
|
||||||
|
$devis['lieu_nom'] ?? '',
|
||||||
|
trim(($devis['thanato_nom'] ?? '') . ' ' . ($devis['thanato_prenom'] ?? '')),
|
||||||
|
$devis['devis_comment'] ?? '',
|
||||||
|
$devis['calendar_uuid'] ?? ''
|
||||||
|
];
|
||||||
|
|
||||||
|
$csvContent .= $this->arrayToCsv($row);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $csvContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClientNameForFolder($firstDevis, $filterType)
|
||||||
|
{
|
||||||
|
if ($filterType === MultipleFactureTypeConstant::GROUP_FILTER_TYPE && !empty($firstDevis["group_name"])) {
|
||||||
|
return $firstDevis["group_name"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $firstDevis["client_nom"] ?? 'CLIENT_INCONNU';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRecapFilename($month, $year)
|
||||||
|
{
|
||||||
|
$monthStr = str_pad($month, 2, '0', STR_PAD_LEFT);
|
||||||
|
return $year . $monthStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function arrayToCsv($array)
|
||||||
|
{
|
||||||
|
$output = fopen('php://temp', 'r+');
|
||||||
|
fputcsv($output, $array, ';');
|
||||||
|
rewind($output);
|
||||||
|
$csvLine = fgets($output);
|
||||||
|
fclose($output);
|
||||||
|
|
||||||
|
return $csvLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
144
gestion/lib/Service/Devis/DevisPdfGenerator.php
Normal file
144
gestion/lib/Service/Devis/DevisPdfGenerator.php
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace OCA\Gestion\Service\Devis;
|
||||||
|
|
||||||
|
use OCP\Files\IRootFolder;
|
||||||
|
use OCP\Files\NotPermittedException;
|
||||||
|
|
||||||
|
class DevisPdfGenerator
|
||||||
|
{
|
||||||
|
/** @var IRootFolder */
|
||||||
|
private $rootFolder;
|
||||||
|
|
||||||
|
/** @var DevisPdfLayoutManager */
|
||||||
|
private $layoutManager;
|
||||||
|
|
||||||
|
/** @var DevisPdfTableRenderer */
|
||||||
|
private $tableRenderer;
|
||||||
|
|
||||||
|
public const DEFAULT_NEXTCLOUD_ADMIN = 'admin';
|
||||||
|
|
||||||
|
public function __construct(IRootFolder $rootFolder)
|
||||||
|
{
|
||||||
|
$this->rootFolder = $rootFolder;
|
||||||
|
$this->layoutManager = new DevisPdfLayoutManager($rootFolder);
|
||||||
|
$this->tableRenderer = new DevisPdfTableRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generatePdfDocument($storage, $currentConfig, $data_devis, $clientInfo, $month, $year, $montant)
|
||||||
|
{
|
||||||
|
$configurationAddresses = \OCA\Gestion\Helpers\FileExportHelpers::GetAddressAndCityFromAddress($currentConfig->adresse);
|
||||||
|
$configurationAddress = $configurationAddresses["address"];
|
||||||
|
$configurationAddressCity = $configurationAddresses["city"];
|
||||||
|
|
||||||
|
$pdf = $this->createPdfInstance();
|
||||||
|
$folderPath = $this->createDestinationFolder($storage, $currentConfig, $data_devis[0], $month, $year);
|
||||||
|
|
||||||
|
// Créer le contexte une seule fois
|
||||||
|
$context = new PageContext($pdf, $currentConfig, $configurationAddress, $configurationAddressCity, $data_devis, $clientInfo, $year, $montant);
|
||||||
|
|
||||||
|
$this->generatePdfPages($context);
|
||||||
|
|
||||||
|
return $this->savePdfFile($storage, $pdf, $folderPath, $clientInfo, $month, $year);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createPdfInstance()
|
||||||
|
{
|
||||||
|
$pdf = new \FPDF();
|
||||||
|
$pdf->AddFont('Arial', '', 'Comic Sans MS.php');
|
||||||
|
$pdf->AddFont('Arial', 'B', 'comic-sans-bold.php');
|
||||||
|
return $pdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createDestinationFolder($storage, $currentConfig, $firstDevis, $month, $year)
|
||||||
|
{
|
||||||
|
$date_temp = date("t-m-Y", strtotime($firstDevis['devis_date']));
|
||||||
|
$formatter = new \IntlDateFormatter('fr_FR', \IntlDateFormatter::LONG, \IntlDateFormatter::NONE);
|
||||||
|
$date_formated = $formatter->format(\DateTime::createFromFormat('d-m-Y', $date_temp));
|
||||||
|
|
||||||
|
$folderPath = html_entity_decode($currentConfig->path) . '/DOCUMENTS RECAPITULATIFS/' . $year . '/' .
|
||||||
|
str_pad($month, 2, '0', STR_PAD_LEFT) . ' ' .
|
||||||
|
strtoupper(\OCA\Gestion\Helpers\FileExportHelpers::ConvertSpecialChar(explode(' ', $date_formated)[1])) . '/';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$storage->newFolder($folderPath);
|
||||||
|
} catch(NotPermittedException $e) {
|
||||||
|
// Le dossier existe déjà
|
||||||
|
}
|
||||||
|
|
||||||
|
return $folderPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function generatePdfPages(PageContext $context)
|
||||||
|
{
|
||||||
|
$pagination = $this->calculatePagination(count($context->dataDevis));
|
||||||
|
$totals = ['ht' => 0, 'tva' => 0, 'ttc' => 0];
|
||||||
|
|
||||||
|
for ($num_page = 1; $num_page <= $pagination['nb_pages']; $num_page++) {
|
||||||
|
$this->generateSinglePage($context, $num_page, $pagination, $totals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function calculatePagination($totalItems)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nb_pages' => ceil($totalItems / 26),
|
||||||
|
'items_per_page' => 26,
|
||||||
|
'current_index' => 0
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// VOICI LA FONCTION CORRIGÉE - 4 paramètres au lieu de 10
|
||||||
|
private function generateSinglePage(PageContext $context, $num_page, &$pagination, &$totals)
|
||||||
|
{
|
||||||
|
$context->pdf->AddPage();
|
||||||
|
$context->pdf->SetAutoPagebreak(false);
|
||||||
|
$context->pdf->SetMargins(0, 0, 10);
|
||||||
|
|
||||||
|
$this->layoutManager->addPageHeader($context->pdf, $context->currentConfig, $context->configurationAddress, $context->configurationAddressCity);
|
||||||
|
$this->layoutManager->addPageNumber($context->pdf, $num_page, $pagination['nb_pages']);
|
||||||
|
$this->layoutManager->addClientInfoSection($context->pdf, $context->clientInfo, $context->dataDevis[0]);
|
||||||
|
$this->layoutManager->addDocumentTitle($context->pdf, $context->dataDevis[0], $context->year);
|
||||||
|
|
||||||
|
$itemsToProcess = min($pagination['items_per_page'], count($context->dataDevis) - $pagination['current_index']);
|
||||||
|
|
||||||
|
$config = [
|
||||||
|
'pagination' => $pagination,
|
||||||
|
'itemsToProcess' => $itemsToProcess,
|
||||||
|
'numPage' => $num_page,
|
||||||
|
'nbPage' => $pagination['nb_pages'],
|
||||||
|
'totals' => &$totals,
|
||||||
|
'sansMontant' => $context->montant
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->tableRenderer->createDevisTable(
|
||||||
|
$context->pdf,
|
||||||
|
$context->dataDevis,
|
||||||
|
$config
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->layoutManager->addLegalFooter($context->pdf, $context->currentConfig);
|
||||||
|
$pagination['current_index'] += $itemsToProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function savePdfFile($storage, $pdf, $folderPath, $clientInfo, $month, $year)
|
||||||
|
{
|
||||||
|
$filename = $this->generateDevisRecapFilename($clientInfo, $month, $year);
|
||||||
|
$fullPdfPath = $folderPath . $filename . '.pdf';
|
||||||
|
|
||||||
|
$storage->newFile($fullPdfPath);
|
||||||
|
$pdfContent = $pdf->Output('', 'S');
|
||||||
|
$file_pdf = $storage->get($fullPdfPath);
|
||||||
|
$file_pdf->putContent($pdfContent);
|
||||||
|
|
||||||
|
return $fullPdfPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function generateDevisRecapFilename($clientInfo, $month, $year)
|
||||||
|
{
|
||||||
|
$monthName = strtoupper(\OCA\Gestion\Helpers\FileExportHelpers::ConvertSpecialChar(date('F', mktime(0, 0, 0, $month, 10))));
|
||||||
|
$clientName = strtoupper(\OCA\Gestion\Helpers\FileExportHelpers::ConvertSpecialChar($clientInfo['name']));
|
||||||
|
|
||||||
|
return $clientName . '_RECAP_DEVIS_' . $monthName . '_' . $year;
|
||||||
|
}
|
||||||
|
}
|
||||||
155
gestion/lib/Service/Devis/DevisPdfLayoutManager.php
Normal file
155
gestion/lib/Service/Devis/DevisPdfLayoutManager.php
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace OCA\Gestion\Service\Devis;
|
||||||
|
|
||||||
|
use OCP\Files\IRootFolder;
|
||||||
|
|
||||||
|
class DevisPdfLayoutManager
|
||||||
|
{
|
||||||
|
/** @var IRootFolder */
|
||||||
|
private $rootFolder;
|
||||||
|
|
||||||
|
private $defaultImagePath = "/var/www/html/data/admin/files/.gestion/";
|
||||||
|
|
||||||
|
public const DEFAULT_NEXTCLOUD_ADMIN = 'admin';
|
||||||
|
|
||||||
|
public function __construct(IRootFolder $rootFolder)
|
||||||
|
{
|
||||||
|
$this->rootFolder = $rootFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addPageHeader($pdf, $config, $address, $city)
|
||||||
|
{
|
||||||
|
if ($this->doesLogoExist()) {
|
||||||
|
$pdf->Image($this->defaultImagePath."logo.png", 10, 10, 75, 25);
|
||||||
|
}
|
||||||
|
$this->addCompanyInfo($pdf, $config, $address, $city);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addPageNumber($pdf, $currentPage, $totalPages)
|
||||||
|
{
|
||||||
|
if ($totalPages > 1) {
|
||||||
|
$pdf->SetXY(120, 5);
|
||||||
|
$pdf->SetFont("Arial", "B", 9);
|
||||||
|
$pdf->Cell(160, 8, $currentPage . '/' . $totalPages, 0, 0, 'C');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addClientInfoSection($pdf, $clientInfo, $firstDevis)
|
||||||
|
{
|
||||||
|
$date_temp = date("t-m-Y", strtotime($firstDevis['devis_date']));
|
||||||
|
$formatter = new \IntlDateFormatter('fr_FR', \IntlDateFormatter::LONG, \IntlDateFormatter::NONE);
|
||||||
|
$date_formated = $formatter->format(\DateTime::createFromFormat('d-m-Y', $date_temp));
|
||||||
|
|
||||||
|
$this->addClientInfo($pdf, $clientInfo, $date_formated);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addDocumentTitle($pdf, $firstDevis, $year)
|
||||||
|
{
|
||||||
|
$date_temp = date("t-m-Y", strtotime($firstDevis['devis_date']));
|
||||||
|
$formatter = new \IntlDateFormatter('fr_FR', \IntlDateFormatter::LONG, \IntlDateFormatter::NONE);
|
||||||
|
$date_formated = $formatter->format(\DateTime::createFromFormat('d-m-Y', $date_temp));
|
||||||
|
|
||||||
|
$pdf->SetFont("Arial", "B", 14);
|
||||||
|
$pdf->SetXY(10, 90);
|
||||||
|
$pdf->Cell(
|
||||||
|
0,
|
||||||
|
10,
|
||||||
|
"RECAPITULATIF DEVIS " .
|
||||||
|
strtoupper(\OCA\Gestion\Helpers\FileExportHelpers::ConvertSpecialChar(explode(' ', $date_formated)[1])) . " " . $year,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
'C'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addLegalFooter($pdf, $config)
|
||||||
|
{
|
||||||
|
$y0 = 260;
|
||||||
|
$pageWidth = $pdf->GetPageWidth();
|
||||||
|
|
||||||
|
$pdf->SetFont('Arial', '', 6);
|
||||||
|
$pdf->SetXY(1, $y0 + 4);
|
||||||
|
$pdf->Cell($pageWidth, 5, mb_convert_encoding(html_entity_decode($config->legal_one), 'ISO-8859-1', 'UTF-8'), 0, 0, 'C');
|
||||||
|
$pdf->SetXY(1, $y0 + 8);
|
||||||
|
$pdf->Cell($pageWidth, 5, mb_convert_encoding(html_entity_decode($config->legal_two), 'ISO-8859-1', 'UTF-8'), 0, 0, 'C');
|
||||||
|
$pdf->SetXY(1, $y0 + 12);
|
||||||
|
$pdf->Cell($pageWidth, 5, mb_convert_encoding(html_entity_decode($config->telephone), 'ISO-8859-1', 'UTF-8'), 0, 0, 'C');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addCompanyInfo($pdf, $config, $address, $city)
|
||||||
|
{
|
||||||
|
$companyInfoXAxis = 10;
|
||||||
|
$companyInfoYAxis = 40;
|
||||||
|
|
||||||
|
$pdf->SetFont('Arial', '', 11);
|
||||||
|
$pdf->SetXY($companyInfoXAxis, $companyInfoYAxis);
|
||||||
|
$pdf->Cell(0, 7, \OCA\Gestion\Helpers\FileExportHelpers::FormatTextForExport($config->entreprise));
|
||||||
|
|
||||||
|
$companyInfoYAxis += 7;
|
||||||
|
$pdf->SetXY($companyInfoXAxis, $companyInfoYAxis);
|
||||||
|
$pdf->Cell(0, 7, \OCA\Gestion\Helpers\FileExportHelpers::FormatTextForExport($address));
|
||||||
|
|
||||||
|
$companyInfoYAxis += 7;
|
||||||
|
$pdf->SetXY($companyInfoXAxis, $companyInfoYAxis);
|
||||||
|
$pdf->Cell(0, 7, \OCA\Gestion\Helpers\FileExportHelpers::FormatTextForExport($city));
|
||||||
|
|
||||||
|
$companyInfoYAxis += 7;
|
||||||
|
$pdf->SetXY($companyInfoXAxis, $companyInfoYAxis);
|
||||||
|
$pdf->Cell(0, 7, mb_convert_encoding(html_entity_decode('Tél : '), 'ISO-8859-1', 'UTF-8') . \OCA\Gestion\Helpers\FileExportHelpers::FormatTextForExport($config->telephone));
|
||||||
|
|
||||||
|
$companyInfoYAxis += 7;
|
||||||
|
$pdf->SetXY($companyInfoXAxis, $companyInfoYAxis);
|
||||||
|
$pdf->Cell(0, 7, 'Mail : ' . $config->mail);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addClientInfo($pdf, $clientInfo, $dateFormatted)
|
||||||
|
{
|
||||||
|
$clientInfoXAxis = 125;
|
||||||
|
$clientInfoYAxis = 40;
|
||||||
|
|
||||||
|
$pdf->SetFont('Arial', '', 11);
|
||||||
|
$pdf->SetXY($clientInfoXAxis, $clientInfoYAxis);
|
||||||
|
$pdf->Cell(0, 7, mb_convert_encoding($clientInfo['name'], 'ISO-8859-1', 'UTF-8'));
|
||||||
|
|
||||||
|
$clientInfoYAxis += 7;
|
||||||
|
$pdf->SetXY($clientInfoXAxis, $clientInfoYAxis);
|
||||||
|
$pdf->SetMargins(0, 0, 10);
|
||||||
|
$pdf->MultiCell(0, 7, trim(\OCA\Gestion\Helpers\FileExportHelpers::FormatTextForExport($clientInfo['address'])));
|
||||||
|
$pdf->SetMargins(0, 0, 0);
|
||||||
|
|
||||||
|
$clientInfoYAxis += 14;
|
||||||
|
$pdf->SetXY($clientInfoXAxis, $clientInfoYAxis);
|
||||||
|
$pdf->Cell(0, 7, trim(mb_convert_encoding(html_entity_decode($clientInfo['city']), 'ISO-8859-1', 'UTF-8')));
|
||||||
|
|
||||||
|
if (!empty($clientInfo['siret'])) {
|
||||||
|
$clientInfoYAxis += 7;
|
||||||
|
$pdf->SetXY($clientInfoXAxis, $clientInfoYAxis);
|
||||||
|
$pdf->Cell(0, 7, 'Siret: ' . \OCA\Gestion\Helpers\FileExportHelpers::FormatTextForExport($clientInfo['siret']));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($clientInfo['email'])) {
|
||||||
|
$clientInfoYAxis += 7;
|
||||||
|
$pdf->SetXY($clientInfoXAxis, $clientInfoYAxis);
|
||||||
|
$pdf->Cell(0, 7, 'Email: ' . mb_convert_encoding(html_entity_decode($clientInfo['email']), 'ISO-8859-1', 'UTF-8'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$clientInfoYAxis += 7;
|
||||||
|
$pdf->SetXY($clientInfoXAxis, $clientInfoYAxis);
|
||||||
|
$pdf->Cell(0, 7, "le " . mb_convert_encoding($dateFormatted, 'ISO-8859-1', 'UTF-8'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function doesLogoExist()
|
||||||
|
{
|
||||||
|
$storage = $this->rootFolder->getUserFolder(self::DEFAULT_NEXTCLOUD_ADMIN);
|
||||||
|
try {
|
||||||
|
if (isset($storage)) {
|
||||||
|
$storage->get('/.gestion/logo.png');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (\OCP\Files\NotFoundException $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
176
gestion/lib/Service/Devis/DevisPdfTableRenderer.php
Normal file
176
gestion/lib/Service/Devis/DevisPdfTableRenderer.php
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace OCA\Gestion\Service\Devis;
|
||||||
|
|
||||||
|
class DevisPdfTableRenderer
|
||||||
|
{
|
||||||
|
public function createDevisTable($pdf, $dataDevis, $config)
|
||||||
|
{
|
||||||
|
// Extraction des paramètres du tableau de configuration
|
||||||
|
$pagination = $config['pagination'];
|
||||||
|
$itemsToProcess = $config['itemsToProcess'];
|
||||||
|
$numPage = $config['numPage'];
|
||||||
|
$nbPage = $config['nbPage'];
|
||||||
|
$totals = &$config['totals']; // Référence pour modification
|
||||||
|
$sansMontant = $config['sansMontant'] ?? false; // false par défaut = afficher les montants
|
||||||
|
|
||||||
|
$this->drawTableStructure($pdf, $numPage, $nbPage, $sansMontant);
|
||||||
|
$this->addTableHeaders($pdf, $sansMontant);
|
||||||
|
$this->populateTableData($pdf, $dataDevis, $pagination['current_index'], $itemsToProcess, $totals, $sansMontant);
|
||||||
|
|
||||||
|
// Afficher les totaux seulement sur la dernière page ET si les montants sont affichés
|
||||||
|
if ($numPage == $nbPage && !$sansMontant) {
|
||||||
|
$this->addTableTotals($pdf, $totals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function drawTableStructure($pdf, $numPage, $nbPage, $sansMontant)
|
||||||
|
{
|
||||||
|
$pdf->SetLineWidth(0.2);
|
||||||
|
$pdf->Rect(5, 105, 200, 130, "D");
|
||||||
|
$pdf->Line(5, 115, 205, 115);
|
||||||
|
|
||||||
|
// Si c'est la dernière page ET qu'on affiche les montants, ligne de total à 225
|
||||||
|
$endY = ($numPage == $nbPage && !$sansMontant) ? 225 : 235;
|
||||||
|
|
||||||
|
if (!$sansMontant) {
|
||||||
|
// AVEC montants : toutes les colonnes
|
||||||
|
$verticalLines = [25, 45, 70, 90, 125, 155, 175, 190];
|
||||||
|
} else {
|
||||||
|
// SANS montants : seulement jusqu'à Défunt
|
||||||
|
$verticalLines = [35, 70, 105, 125, 155];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($verticalLines as $x) {
|
||||||
|
$pdf->Line($x, 105, $x, $endY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addTableHeaders($pdf, $sansMontant)
|
||||||
|
{
|
||||||
|
$pdf->SetFont('Arial', 'B', 8);
|
||||||
|
|
||||||
|
if (!$sansMontant) {
|
||||||
|
// AVEC montants
|
||||||
|
$headers = [
|
||||||
|
[5, 20, mb_convert_encoding(html_entity_decode("N° Devis"), 'ISO-8859-1', 'UTF-8')],
|
||||||
|
[25, 20, mb_convert_encoding(html_entity_decode("N° Dossier"), 'ISO-8859-1', 'UTF-8')],
|
||||||
|
[45, 25, mb_convert_encoding(html_entity_decode("N° Commande"), 'ISO-8859-1', 'UTF-8')],
|
||||||
|
[70, 20, "Date"],
|
||||||
|
[90, 35, "Lieu du soin"],
|
||||||
|
[125, 30, \OCA\Gestion\Helpers\FileExportHelpers::FormatTextForExport("Défunt")],
|
||||||
|
[155, 20, "H.T."],
|
||||||
|
[175, 15, "TVA 20%"],
|
||||||
|
[190, 15, "T.T.C"]
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// SANS montants - colonnes plus larges
|
||||||
|
$headers = [
|
||||||
|
[5, 30, mb_convert_encoding(html_entity_decode("N° Devis"), 'ISO-8859-1', 'UTF-8')],
|
||||||
|
[35, 35, mb_convert_encoding(html_entity_decode("N° Dossier"), 'ISO-8859-1', 'UTF-8')],
|
||||||
|
[70, 35, mb_convert_encoding(html_entity_decode("N° Commande"), 'ISO-8859-1', 'UTF-8')],
|
||||||
|
[105, 20, "Date"],
|
||||||
|
[125, 30, "Lieu du soin"],
|
||||||
|
[155, 50, \OCA\Gestion\Helpers\FileExportHelpers::FormatTextForExport("Défunt")]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($headers as $header) {
|
||||||
|
$pdf->SetXY($header[0], 106);
|
||||||
|
$pdf->Cell($header[1], 8, $header[2], 0, 0, 'C');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function populateTableData($pdf, $dataDevis, $startIndex, $itemsToProcess, &$totals, $sansMontant)
|
||||||
|
{
|
||||||
|
$formatterDate = new \IntlDateFormatter('fr_FR', \IntlDateFormatter::SHORT, \IntlDateFormatter::NONE);
|
||||||
|
$formatterDate->setPattern('dd-MMM');
|
||||||
|
|
||||||
|
$yDevis = 115;
|
||||||
|
|
||||||
|
for ($i = $startIndex; $i < $startIndex + $itemsToProcess && $i < count($dataDevis); $i++) {
|
||||||
|
$devis = $dataDevis[$i];
|
||||||
|
$dateSoin = new \DateTime($devis['devis_date']);
|
||||||
|
|
||||||
|
$this->addTableRow($pdf, $devis, $formatterDate, $dateSoin, $yDevis, $sansMontant);
|
||||||
|
|
||||||
|
// Calculer les totaux seulement si on affiche les montants
|
||||||
|
if (!$sansMontant) {
|
||||||
|
$totals['ht'] += $devis['montant_htc'];
|
||||||
|
$totals['tva'] += $devis['montant_tva'];
|
||||||
|
$totals['ttc'] += $devis['montant_ttc'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$yDevis += 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addTableRow($pdf, $devis, $formatterDate, $dateSoin, $yDevis, $sansMontant)
|
||||||
|
{
|
||||||
|
$pdf->SetFont('Arial', '', 7);
|
||||||
|
|
||||||
|
if (!$sansMontant) {
|
||||||
|
// AVEC montants
|
||||||
|
$rowData = [
|
||||||
|
[6, 18, $devis['devis_full_number']],
|
||||||
|
[26, 18, $devis['calendar_uuid']],
|
||||||
|
[46, 23, $devis['num_commande']],
|
||||||
|
[71, 18, mb_convert_encoding($formatterDate->format($dateSoin), 'ISO-8859-1', 'UTF-8')],
|
||||||
|
[91, 33, \OCA\Gestion\Helpers\FileExportHelpers::FormatTextForExport($devis['lieu_nom'])],
|
||||||
|
[126, 28, \OCA\Gestion\Helpers\FileExportHelpers::FormatTextForExport($devis['defunt_nom'])],
|
||||||
|
[156, 18, number_format($devis['montant_htc'], 2, '.', '') . chr(128), 'C'],
|
||||||
|
[176, 13, number_format($devis['montant_tva'], 2, '.', '') . chr(128), 'C'],
|
||||||
|
[191, 13, number_format($devis['montant_ttc'], 2, '.', '') . chr(128), 'C']
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// SANS montants - colonnes plus larges
|
||||||
|
$rowData = [
|
||||||
|
[6, 28, $devis['devis_full_number']],
|
||||||
|
[36, 33, $devis['calendar_uuid']],
|
||||||
|
[71, 33, $devis['num_commande']],
|
||||||
|
[106, 18, mb_convert_encoding($formatterDate->format($dateSoin), 'ISO-8859-1', 'UTF-8')],
|
||||||
|
[126, 28, \OCA\Gestion\Helpers\FileExportHelpers::FormatTextForExport($devis['lieu_nom'])],
|
||||||
|
[156, 48, \OCA\Gestion\Helpers\FileExportHelpers::FormatTextForExport($devis['defunt_nom'])]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($rowData as $data) {
|
||||||
|
$pdf->SetXY($data[0], $yDevis);
|
||||||
|
$align = isset($data[3]) ? $data[3] : '';
|
||||||
|
$pdf->Cell($data[1], 5, $data[2], 0, 0, $align);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addTableTotals($pdf, $totals)
|
||||||
|
{
|
||||||
|
// Cette méthode n'est appelée que si on affiche les montants (!$sansMontant)
|
||||||
|
$pdf->Line(5, 225, 205, 225);
|
||||||
|
$pdf->SetFont('Arial', 'B', 8);
|
||||||
|
|
||||||
|
$pdf->SetXY(5, 225);
|
||||||
|
$pdf->Cell(150, 8, 'TOTAL', 0, 0, 'C');
|
||||||
|
$pdf->SetXY(156, 225);
|
||||||
|
$pdf->Cell(18, 8, number_format($totals['ht'], 2, '.', '') . chr(128), 0, 0, 'C');
|
||||||
|
$pdf->SetXY(176, 225);
|
||||||
|
$pdf->Cell(13, 8, number_format($totals['tva'], 2, '.', '') . chr(128), 0, 0, 'C');
|
||||||
|
$pdf->SetXY(191, 225);
|
||||||
|
$pdf->Cell(13, 8, number_format($totals['ttc'], 2, '.', '') . chr(128), 0, 0, 'C');
|
||||||
|
|
||||||
|
$pdf->SetXY(170, 240);
|
||||||
|
$pdf->Cell(20, 8, 'TOTAL TTC', 0, 0, 'C');
|
||||||
|
$pdf->SetXY(190, 240);
|
||||||
|
$pdf->Cell(15, 8, number_format($totals['ttc'], 2, '.', '') . chr(128), 0, 0, 'C');
|
||||||
|
|
||||||
|
$lines = [
|
||||||
|
[170, 240, 170, 248],
|
||||||
|
[190, 240, 190, 248],
|
||||||
|
[205, 240, 205, 248],
|
||||||
|
[170, 240, 205, 240],
|
||||||
|
[170, 248, 205, 248]
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($lines as $line) {
|
||||||
|
$pdf->Line($line[0], $line[1], $line[2], $line[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
89
gestion/lib/Service/Devis/DevisRecapService.php
Normal file
89
gestion/lib/Service/Devis/DevisRecapService.php
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace OCA\Gestion\Service\Devis;
|
||||||
|
|
||||||
|
use OCA\Gestion\Db\Bdd;
|
||||||
|
use OCP\Files\IRootFolder;
|
||||||
|
use OCA\Gestion\Constants\MultipleFactureTypeConstant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service principal pour la génération des récapitulatifs de devis
|
||||||
|
*/
|
||||||
|
class DevisRecapService
|
||||||
|
{
|
||||||
|
/** @var Bdd */
|
||||||
|
private $gestionBdd;
|
||||||
|
|
||||||
|
/** @var IRootFolder */
|
||||||
|
private $rootFolder;
|
||||||
|
|
||||||
|
/** @var DevisDataProcessor */
|
||||||
|
private $dataProcessor;
|
||||||
|
|
||||||
|
/** @var DevisPdfGenerator */
|
||||||
|
private $pdfGenerator;
|
||||||
|
|
||||||
|
public const DEFAULT_NEXTCLOUD_ADMIN = 'admin';
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Bdd $gestionBdd,
|
||||||
|
IRootFolder $rootFolder,
|
||||||
|
) {
|
||||||
|
$this->gestionBdd = $gestionBdd;
|
||||||
|
$this->rootFolder = $rootFolder;
|
||||||
|
$this->dataProcessor = new DevisDataProcessor($gestionBdd);
|
||||||
|
$this->pdfGenerator = new DevisPdfGenerator($rootFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generateDevisRecap($filter, $month, $year, $idNextCloud, $filterType, $montant)
|
||||||
|
{
|
||||||
|
$storage = $this->rootFolder->getUserFolder($idNextCloud);
|
||||||
|
$configs = json_decode($this->gestionBdd->getConfiguration(self::DEFAULT_NEXTCLOUD_ADMIN));
|
||||||
|
$currentConfig = $configs[0];
|
||||||
|
|
||||||
|
$devisData = $this->getDevisData($filter, $month, $year, $currentConfig, $filterType);
|
||||||
|
if (empty($devisData)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$processedData = $this->dataProcessor->prepareDevisData($devisData, $currentConfig, $filter, $idNextCloud);
|
||||||
|
$clientInfo = $this->dataProcessor->getClientInfoForDevis($processedData[0], $filterType);
|
||||||
|
|
||||||
|
return $this->pdfGenerator->generatePdfDocument(
|
||||||
|
$storage,
|
||||||
|
$currentConfig,
|
||||||
|
$processedData,
|
||||||
|
$clientInfo,
|
||||||
|
$month,
|
||||||
|
$year,
|
||||||
|
$montant
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDevisData($filter, $month, $year, $currentConfig, $filterType)
|
||||||
|
{
|
||||||
|
$isFilterByClient = $filterType === MultipleFactureTypeConstant::CLIENT_FILTER_TYPE;
|
||||||
|
|
||||||
|
if ($isFilterByClient) {
|
||||||
|
return $this->gestionBdd->getDevisPdfDataByClientAndMonthYear($filter, $month, $year, $currentConfig);
|
||||||
|
} else {
|
||||||
|
return $this->gestionBdd->getDevisPdfDataByClientGroupFacturationAndMonthYear($filter, $month, $year, $currentConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Méthodes utilitaires conservées pour la compatibilité CSV
|
||||||
|
public function generateCsvContent($devisData)
|
||||||
|
{
|
||||||
|
return $this->dataProcessor->generateCsvContent($devisData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClientNameForFolder($firstDevis, $filterType)
|
||||||
|
{
|
||||||
|
return $this->dataProcessor->getClientNameForFolder($firstDevis, $filterType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRecapFilename($month, $year)
|
||||||
|
{
|
||||||
|
return $this->dataProcessor->getRecapFilename($month, $year);
|
||||||
|
}
|
||||||
|
}
|
||||||
32
gestion/lib/Service/Devis/PageContext.php
Normal file
32
gestion/lib/Service/Devis/PageContext.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace OCA\Gestion\Service\Devis;
|
||||||
|
|
||||||
|
use OCP\Files\IRootFolder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Objet simple pour regrouper les paramètres de contexte
|
||||||
|
*/
|
||||||
|
class PageContext
|
||||||
|
{
|
||||||
|
public $pdf;
|
||||||
|
public $currentConfig;
|
||||||
|
public $configurationAddress;
|
||||||
|
public $configurationAddressCity;
|
||||||
|
public $dataDevis;
|
||||||
|
public $clientInfo;
|
||||||
|
public $year;
|
||||||
|
public $montant;
|
||||||
|
|
||||||
|
public function __construct($pdf, $currentConfig, $configurationAddress, $configurationAddressCity, $dataDevis, $clientInfo, $year, $montant)
|
||||||
|
{
|
||||||
|
$this->pdf = $pdf;
|
||||||
|
$this->currentConfig = $currentConfig;
|
||||||
|
$this->configurationAddress = $configurationAddress;
|
||||||
|
$this->configurationAddressCity = $configurationAddressCity;
|
||||||
|
$this->dataDevis = $dataDevis;
|
||||||
|
$this->clientInfo = $clientInfo;
|
||||||
|
$this->year = $year;
|
||||||
|
$this->montant = $montant;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -41,7 +41,8 @@ use OCA\Gestion\Service\InvoiceRecap\InvoiceRecapService;
|
|||||||
use OCP\DB\Exception;
|
use OCP\DB\Exception;
|
||||||
use OCP\Files\IRootFolder;
|
use OCP\Files\IRootFolder;
|
||||||
|
|
||||||
class InvoicePdfService {
|
class InvoicePdfService
|
||||||
|
{
|
||||||
/** @var Bdd */
|
/** @var Bdd */
|
||||||
private $gestionBdd;
|
private $gestionBdd;
|
||||||
|
|
||||||
@ -55,13 +56,15 @@ class InvoicePdfService {
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
Bdd $gestionBdd,
|
Bdd $gestionBdd,
|
||||||
IRootFolder $rootFolder,
|
IRootFolder $rootFolder,
|
||||||
InvoiceRecapService $invoiceRecapService) {
|
InvoiceRecapService $invoiceRecapService
|
||||||
|
) {
|
||||||
$this->gestionBdd = $gestionBdd;
|
$this->gestionBdd = $gestionBdd;
|
||||||
$this->rootFolder = $rootFolder;
|
$this->rootFolder = $rootFolder;
|
||||||
$this->invoiceRecapService = $invoiceRecapService;
|
$this->invoiceRecapService = $invoiceRecapService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getLogo(){
|
private function getLogo()
|
||||||
|
{
|
||||||
$storage = $this->rootFolder->getUserFolder(self::DEFAULT_NEXTCLOUD_ADMIN);
|
$storage = $this->rootFolder->getUserFolder(self::DEFAULT_NEXTCLOUD_ADMIN);
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
@ -73,15 +76,15 @@ class InvoicePdfService {
|
|||||||
} catch(\OCP\Files\NotFoundException $e) {
|
} catch(\OCP\Files\NotFoundException $e) {
|
||||||
$file = $storage->get('/.gestion/logo.jpeg');
|
$file = $storage->get('/.gestion/logo.jpeg');
|
||||||
}
|
}
|
||||||
}
|
} catch(\OCP\Files\NotFoundException $e) {
|
||||||
catch(\OCP\Files\NotFoundException $e) {
|
|
||||||
return "nothing";
|
return "nothing";
|
||||||
}
|
}
|
||||||
|
|
||||||
return base64_encode($file->getContent());
|
return base64_encode($file->getContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
private function generateFactureSinglePdfByFactureId($factureId,$idNextCloud){
|
private function generateFactureSinglePdfByFactureId($factureId, $idNextCloud)
|
||||||
|
{
|
||||||
$storage = $this->rootFolder->getUserFolder($idNextCloud);
|
$storage = $this->rootFolder->getUserFolder($idNextCloud);
|
||||||
$configs = json_decode($this->gestionBdd->getConfiguration(self::DEFAULT_NEXTCLOUD_ADMIN));
|
$configs = json_decode($this->gestionBdd->getConfiguration(self::DEFAULT_NEXTCLOUD_ADMIN));
|
||||||
$currentConfig = $configs[0];
|
$currentConfig = $configs[0];
|
||||||
@ -108,8 +111,7 @@ class InvoicePdfService {
|
|||||||
foreach($factureFolders as $folder) {
|
foreach($factureFolders as $folder) {
|
||||||
try {
|
try {
|
||||||
$storage->newFolder($folder);
|
$storage->newFolder($folder);
|
||||||
}
|
} catch(\OCP\Files\NotPermittedException $e) {
|
||||||
catch(\OCP\Files\NotPermittedException $e) {
|
|
||||||
}
|
}
|
||||||
$ff_pdf = $folder.$pdfFilename.'.pdf';
|
$ff_pdf = $folder.$pdfFilename.'.pdf';
|
||||||
$storage->newFile($ff_pdf);
|
$storage->newFile($ff_pdf);
|
||||||
@ -124,17 +126,18 @@ class InvoicePdfService {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generateFacturePdfByFactureId($factureId,$idNextCloud){
|
public function generateFacturePdfByFactureId($factureId, $idNextCloud)
|
||||||
|
{
|
||||||
$factureType = $this->gestionBdd->getFactureTypeByFactureId($factureId);
|
$factureType = $this->gestionBdd->getFactureTypeByFactureId($factureId);
|
||||||
if($factureType == FactureTypeConstant::TYPE_SINGLE) {
|
if($factureType == FactureTypeConstant::TYPE_SINGLE) {
|
||||||
return $this->generateFactureSinglePdfByFactureId($factureId, $idNextCloud);
|
return $this->generateFactureSinglePdfByFactureId($factureId, $idNextCloud);
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return $this->generateFactureGroupPdfByFactureId($factureId, $idNextCloud);
|
return $this->generateFactureGroupPdfByFactureId($factureId, $idNextCloud);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getGroupFactureFolder(array $factureData,$racinePath){
|
private function getGroupFactureFolder(array $factureData, $racinePath)
|
||||||
|
{
|
||||||
$clientRacineFolder = $racinePath.'CLIENTS/'.mb_strtoupper($factureData["group_name"], 'UTF-8').'/';
|
$clientRacineFolder = $racinePath.'CLIENTS/'.mb_strtoupper($factureData["group_name"], 'UTF-8').'/';
|
||||||
$factureDate = $factureData['date_paiement'];
|
$factureDate = $factureData['date_paiement'];
|
||||||
$factureDatetime = new DateTime($factureDate);
|
$factureDatetime = new DateTime($factureDate);
|
||||||
@ -146,7 +149,8 @@ class InvoicePdfService {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getFacturesFolder(array $factureData,$racinePath){
|
private function getFacturesFolder(array $factureData, $racinePath)
|
||||||
|
{
|
||||||
$clientRacineFolder = $racinePath.'CLIENTS/'.mb_strtoupper($factureData["client_nom"], 'UTF-8').'/';
|
$clientRacineFolder = $racinePath.'CLIENTS/'.mb_strtoupper($factureData["client_nom"], 'UTF-8').'/';
|
||||||
$defuntsFolder = $clientRacineFolder.'DEFUNTS/'.mb_strtoupper($factureData['defunt_nom'], 'UTF-8').'/'.'FACTURES'.'/';
|
$defuntsFolder = $clientRacineFolder.'DEFUNTS/'.mb_strtoupper($factureData['defunt_nom'], 'UTF-8').'/'.'FACTURES'.'/';
|
||||||
$devisDate = $factureData['devis_date'];
|
$devisDate = $factureData['devis_date'];
|
||||||
@ -160,7 +164,8 @@ class InvoicePdfService {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function generateFactureGroupPdfByFactureId($factureId,$idNextCloud){
|
private function generateFactureGroupPdfByFactureId($factureId, $idNextCloud)
|
||||||
|
{
|
||||||
$storage = $this->rootFolder->getUserFolder($idNextCloud);
|
$storage = $this->rootFolder->getUserFolder($idNextCloud);
|
||||||
$configs = json_decode($this->gestionBdd->getConfiguration(self::DEFAULT_NEXTCLOUD_ADMIN));
|
$configs = json_decode($this->gestionBdd->getConfiguration(self::DEFAULT_NEXTCLOUD_ADMIN));
|
||||||
$currentConfig = $configs[0];
|
$currentConfig = $configs[0];
|
||||||
@ -198,8 +203,7 @@ class InvoicePdfService {
|
|||||||
foreach($factureFolders as $folder) {
|
foreach($factureFolders as $folder) {
|
||||||
try {
|
try {
|
||||||
$storage->newFolder($folder);
|
$storage->newFolder($folder);
|
||||||
}
|
} catch(\OCP\Files\NotPermittedException $e) {
|
||||||
catch(\OCP\Files\NotPermittedException $e) {
|
|
||||||
}
|
}
|
||||||
$ff_pdf = $folder.$pdfFilename.'.pdf';
|
$ff_pdf = $folder.$pdfFilename.'.pdf';
|
||||||
$storage->newFile($ff_pdf);
|
$storage->newFile($ff_pdf);
|
||||||
@ -214,13 +218,15 @@ class InvoicePdfService {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generateFacturePdfByFactureIds(array $factureIds,$idNextCloud){
|
public function generateFacturePdfByFactureIds(array $factureIds, $idNextCloud)
|
||||||
|
{
|
||||||
foreach($factureIds as $factureId) {
|
foreach($factureIds as $factureId) {
|
||||||
$this->generateFacturePdfByFactureId($factureId, $idNextCloud);
|
$this->generateFacturePdfByFactureId($factureId, $idNextCloud);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generateMultipleInvoicePdfByClientAndMonthYear($filter,$month,$year,$idNextCloud,$filterType){
|
public function generateMultipleInvoicePdfByClientAndMonthYear($filter, $month, $year, $idNextCloud, $filterType)
|
||||||
|
{
|
||||||
$storage = $this->rootFolder->getUserFolder($idNextCloud);
|
$storage = $this->rootFolder->getUserFolder($idNextCloud);
|
||||||
$configs = json_decode($this->gestionBdd->getConfiguration(self::DEFAULT_NEXTCLOUD_ADMIN));
|
$configs = json_decode($this->gestionBdd->getConfiguration(self::DEFAULT_NEXTCLOUD_ADMIN));
|
||||||
$currentConfig = $configs[0];
|
$currentConfig = $configs[0];
|
||||||
@ -247,8 +253,7 @@ class InvoicePdfService {
|
|||||||
$pdfContent = $pdf->Output('', 'S');
|
$pdfContent = $pdf->Output('', 'S');
|
||||||
try {
|
try {
|
||||||
$storage->newFolder($clientRacineFolder);
|
$storage->newFolder($clientRacineFolder);
|
||||||
}
|
} catch(\OCP\Files\NotPermittedException $e) {
|
||||||
catch(\OCP\Files\NotPermittedException $e) {
|
|
||||||
}
|
}
|
||||||
$storage->newFile($filenamePath);
|
$storage->newFile($filenamePath);
|
||||||
$file_pdf = $storage->get($filenamePath);
|
$file_pdf = $storage->get($filenamePath);
|
||||||
@ -256,11 +261,13 @@ class InvoicePdfService {
|
|||||||
return $filenamePath;
|
return $filenamePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generateInvoiceRecap($filter,$filterType,$date,$idNextCloud){
|
public function generateInvoiceRecap($filter, $filterType, $date, $idNextCloud)
|
||||||
|
{
|
||||||
$this->invoiceRecapService->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){
|
public function exportGroupOfDevisIntoFacture($clientId, $clientType, $month, $year, $facturationDate, $idNextcloud = BddConstant::DEFAULT_ADMIN_ID_NEXTCLOUD)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
$datetime = new Datetime();
|
$datetime = new Datetime();
|
||||||
$month = $month ?? $datetime->format('m');
|
$month = $month ?? $datetime->format('m');
|
||||||
@ -326,8 +333,7 @@ class InvoicePdfService {
|
|||||||
return $factureGeneratedResponse["filenames"];
|
return $factureGeneratedResponse["filenames"];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
} catch(Exception) {
|
||||||
catch(Exception){
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import "../css/mycss.css";
|
|||||||
import { globalConfiguration } from "./modules/mainFunction.mjs";
|
import { globalConfiguration } from "./modules/mainFunction.mjs";
|
||||||
import "./listener/main_listener";
|
import "./listener/main_listener";
|
||||||
import "./listener/devisListener";
|
import "./listener/devisListener";
|
||||||
import { exportClientDevisByMonthAndYearToPdf } from "./modules/ajaxRequest.mjs";
|
import { exportClientDevisByMonthAndYearToPdf, exportClientDevisRecap } from "./modules/ajaxRequest.mjs";
|
||||||
import 'select2/dist/css/select2.css';
|
import 'select2/dist/css/select2.css';
|
||||||
import 'select2';
|
import 'select2';
|
||||||
import '../css/mycss.css';
|
import '../css/mycss.css';
|
||||||
|
|||||||
@ -148,7 +148,6 @@ document.onchange = function(event) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$('body').on('click', '#showGroupDevisFacturationModal', function () {
|
$('body').on('click', '#showGroupDevisFacturationModal', function () {
|
||||||
console.log("sdsfs");
|
|
||||||
$('#groupDevisFacturationModal').show();
|
$('#groupDevisFacturationModal').show();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -156,6 +155,14 @@ $('body').on('click', '#closeGroupDevisModal', function () {
|
|||||||
$('#groupDevisFacturationModal').hide();
|
$('#groupDevisFacturationModal').hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('body').on('click', '#showDevisRecapModal', function () {
|
||||||
|
$('#devisRecapMontant').show();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('body').on('click', '#closeDevisRecapModal', function () {
|
||||||
|
$('#devisRecapMontant').hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
$('body').on('click', '#invoiceGroupQuote', function () {
|
$('body').on('click', '#invoiceGroupQuote', function () {
|
||||||
var dateValue = document.getElementById("facturationDate").value;
|
var dateValue = document.getElementById("facturationDate").value;
|
||||||
@ -202,3 +209,95 @@ $('body').on('click', '#invoiceGroupQuote', function () {
|
|||||||
hideLoader();
|
hideLoader();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('body').on('click', '#devisRecapAction', function () {
|
||||||
|
var valMontant = document.getElementById("sansMontant").checked;
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const filter = urlParams.get('cli');
|
||||||
|
const year = urlParams.get('annee');
|
||||||
|
const month = urlParams.get('mois');
|
||||||
|
const filterType = urlParams.get('filterType');
|
||||||
|
|
||||||
|
var devisPayload = {
|
||||||
|
clientId: filter,
|
||||||
|
month: month,
|
||||||
|
year: year,
|
||||||
|
clientType: filterType,
|
||||||
|
montant: valMontant
|
||||||
|
};
|
||||||
|
|
||||||
|
showLoader();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: baseUrl + '/devis/exportDevisRecap',
|
||||||
|
type: 'POST',
|
||||||
|
contentType: 'application/json',
|
||||||
|
data: JSON.stringify(devisPayload)
|
||||||
|
}).done(function (response) {
|
||||||
|
if (response != null && response.trim() !== "") {
|
||||||
|
// Le retour est une string directe, pas un array JSON
|
||||||
|
var filename = response.replace(/\\/g, '/'); // Corriger les backslashes Windows
|
||||||
|
showSuccess('Sauvegardé dans ' + filename);
|
||||||
|
|
||||||
|
// Fermeture de la modal avec gestion d'erreur intégrée
|
||||||
|
var modalId = 'devisRecapMontant';
|
||||||
|
|
||||||
|
// Essayer Bootstrap 5 d'abord
|
||||||
|
if (typeof bootstrap !== 'undefined' && bootstrap.Modal) {
|
||||||
|
var modalElement = document.getElementById(modalId);
|
||||||
|
if (modalElement) {
|
||||||
|
var modalInstance = bootstrap.Modal.getInstance(modalElement);
|
||||||
|
if (modalInstance) {
|
||||||
|
modalInstance.hide();
|
||||||
|
} else {
|
||||||
|
// Si pas d'instance, créer et fermer
|
||||||
|
modalInstance = new bootstrap.Modal(modalElement);
|
||||||
|
modalInstance.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Essayer Bootstrap 4/3 avec jQuery
|
||||||
|
else if (typeof $ !== 'undefined' && $.fn.modal) {
|
||||||
|
try {
|
||||||
|
$('#' + modalId).modal('hide');
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Erreur lors de la fermeture de la modal avec jQuery:', e);
|
||||||
|
// Fallback manuel
|
||||||
|
var modalElement = document.getElementById(modalId);
|
||||||
|
if (modalElement) {
|
||||||
|
modalElement.classList.remove('show');
|
||||||
|
modalElement.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fallback : fermeture manuelle pure JavaScript
|
||||||
|
else {
|
||||||
|
var modalElement = document.getElementById(modalId);
|
||||||
|
if (modalElement) {
|
||||||
|
// Retirer les classes Bootstrap
|
||||||
|
modalElement.classList.remove('show');
|
||||||
|
modalElement.style.display = 'none';
|
||||||
|
modalElement.setAttribute('aria-hidden', 'true');
|
||||||
|
|
||||||
|
// Retirer le backdrop si présent
|
||||||
|
var backdrop = document.querySelector('.modal-backdrop');
|
||||||
|
if (backdrop) {
|
||||||
|
backdrop.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retirer la classe modal-open du body
|
||||||
|
document.body.classList.remove('modal-open');
|
||||||
|
document.body.style.removeProperty('padding-right');
|
||||||
|
document.body.style.removeProperty('overflow');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
showError(t('gestion', "Les données pour sauvegarde sont vides"));
|
||||||
|
}
|
||||||
|
}).fail(function (response, code) {
|
||||||
|
showError(t('gestion', "Erreur dans la génération du récapitulatif devis"));
|
||||||
|
}).always(function () {
|
||||||
|
hideLoader();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -858,6 +858,7 @@ export function exportClientDevisByMonthAndYearToPdf(clientId,year,month,filterT
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set bijoux photo
|
* Set bijoux photo
|
||||||
* @param {*} bijouxId
|
* @param {*} bijouxId
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
<form method="get" class="d-flex flex-row align-items-center">
|
<form method="get" class="d-flex flex-row align-items-center">
|
||||||
<select name="cli" id="clientselector">
|
<select name="cli" id="clientselector">
|
||||||
<?php
|
<?php
|
||||||
|
$showRecapButton = false;
|
||||||
foreach ($_['clients'] as $key => $client) {
|
foreach ($_['clients'] as $key => $client) {
|
||||||
?>
|
?>
|
||||||
<option <?php
|
<option <?php
|
||||||
@ -17,8 +18,9 @@
|
|||||||
?>
|
?>
|
||||||
</select>
|
</select>
|
||||||
<select name="annee" id="yearselector">
|
<select name="annee" id="yearselector">
|
||||||
<option value="-1" <?php if ((int) $_GET['annee'] == -1)
|
<option value="-1" <?php if ((int) $_GET['annee'] == -1) {
|
||||||
echo 'selected' ?>>Toutes les années</option>
|
echo 'selected';
|
||||||
|
} ?>>Toutes les années</option>
|
||||||
<?php
|
<?php
|
||||||
$currentYear = date('Y');
|
$currentYear = date('Y');
|
||||||
for ($year = $currentYear; $year >= $currentYear - 10; $year--) {
|
for ($year = $currentYear; $year >= $currentYear - 10; $year--) {
|
||||||
@ -27,32 +29,45 @@
|
|||||||
?>
|
?>
|
||||||
</select>
|
</select>
|
||||||
<select name="mois" id="monthselector">
|
<select name="mois" id="monthselector">
|
||||||
<option value="0" <?php if ((int) $_GET['mois'] == 0)
|
<option value="0" <?php if ((int) $_GET['mois'] == 0) {
|
||||||
echo 'selected' ?>>Tous les mois</option>
|
echo 'selected';
|
||||||
<option value="1" <?php if ((int) $_GET['mois'] == 1)
|
} ?>>Tous les mois</option>
|
||||||
echo 'selected' ?>>Janvier</option>
|
<option value="1" <?php if ((int) $_GET['mois'] == 1) {
|
||||||
<option value="2" <?php if ((int) $_GET['mois'] == 2)
|
echo 'selected';
|
||||||
echo 'selected' ?>>Fevrier</option>
|
} ?>>Janvier</option>
|
||||||
<option value="3" <?php if ((int) $_GET['mois'] == 3)
|
<option value="2" <?php if ((int) $_GET['mois'] == 2) {
|
||||||
echo 'selected' ?>>Mars</option>
|
echo 'selected';
|
||||||
<option value="4" <?php if ((int) $_GET['mois'] == 4)
|
} ?>>Fevrier</option>
|
||||||
echo 'selected' ?>>Avril</option>
|
<option value="3" <?php if ((int) $_GET['mois'] == 3) {
|
||||||
<option value="5" <?php if ((int) $_GET['mois'] == 5)
|
echo 'selected';
|
||||||
echo 'selected' ?>>Mai</option>
|
} ?>>Mars</option>
|
||||||
<option value="6" <?php if ((int) $_GET['mois'] == 6)
|
<option value="4" <?php if ((int) $_GET['mois'] == 4) {
|
||||||
echo 'selected' ?>>Juin</option>
|
echo 'selected';
|
||||||
<option value="7" <?php if ((int) $_GET['mois'] == 7)
|
} ?>>Avril</option>
|
||||||
echo 'selected' ?>>Juillet</option>
|
<option value="5" <?php if ((int) $_GET['mois'] == 5) {
|
||||||
<option value="8" <?php if ((int) $_GET['mois'] == 8)
|
echo 'selected';
|
||||||
echo 'selected' ?>>Août</option>
|
} ?>>Mai</option>
|
||||||
<option value="9" <?php if ((int) $_GET['mois'] == 9)
|
<option value="6" <?php if ((int) $_GET['mois'] == 6) {
|
||||||
echo 'selected' ?>>Septembre</option>
|
echo 'selected';
|
||||||
<option value="10" <?php if ((int) $_GET['mois'] == 10)
|
} ?>>Juin</option>
|
||||||
echo 'selected' ?>>Octobre</option>
|
<option value="7" <?php if ((int) $_GET['mois'] == 7) {
|
||||||
<option value="11" <?php if ((int) $_GET['mois'] == 11)
|
echo 'selected';
|
||||||
echo 'selected' ?>>Novembre</option>
|
} ?>>Juillet</option>
|
||||||
<option value="12" <?php if ((int) $_GET['mois'] == 12)
|
<option value="8" <?php if ((int) $_GET['mois'] == 8) {
|
||||||
echo 'selected' ?>>Decembre</option>
|
echo 'selected';
|
||||||
|
} ?>>Août</option>
|
||||||
|
<option value="9" <?php if ((int) $_GET['mois'] == 9) {
|
||||||
|
echo 'selected';
|
||||||
|
} ?>>Septembre</option>
|
||||||
|
<option value="10" <?php if ((int) $_GET['mois'] == 10) {
|
||||||
|
echo 'selected';
|
||||||
|
} ?>>Octobre</option>
|
||||||
|
<option value="11" <?php if ((int) $_GET['mois'] == 11) {
|
||||||
|
echo 'selected';
|
||||||
|
} ?>>Novembre</option>
|
||||||
|
<option value="12" <?php if ((int) $_GET['mois'] == 12) {
|
||||||
|
echo 'selected';
|
||||||
|
} ?>>Decembre</option>
|
||||||
</select>
|
</select>
|
||||||
<input type="hidden" name="filterType" id="filterType"
|
<input type="hidden" name="filterType" id="filterType"
|
||||||
value="<?php echo($_GET['filterType'] ?? 'group'); ?>">
|
value="<?php echo($_GET['filterType'] ?? 'group'); ?>">
|
||||||
@ -62,6 +77,9 @@
|
|||||||
<?php
|
<?php
|
||||||
$clients = $_['clients'];
|
$clients = $_['clients'];
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
|
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
|
||||||
|
if(intval($_GET['mois']) != 0 && intval($_GET['annee']) != 0) {
|
||||||
|
$showRecapButton = true;
|
||||||
|
}
|
||||||
$devis = array_filter($_['devis'], function ($currentDevis) {
|
$devis = array_filter($_['devis'], function ($currentDevis) {
|
||||||
if ($currentDevis->cid) {
|
if ($currentDevis->cid) {
|
||||||
$datesplit = explode("-", $currentDevis->date);
|
$datesplit = explode("-", $currentDevis->date);
|
||||||
@ -101,6 +119,11 @@
|
|||||||
Facturer
|
Facturer
|
||||||
</button>
|
</button>
|
||||||
<?php
|
<?php
|
||||||
|
}
|
||||||
|
if (strcmp($_GET['cli'], '') != 0 && sizeof($devis) > 0) {
|
||||||
|
?>
|
||||||
|
<?php if($showRecapButton) {?><button class="btn btn-secondary" type="button" id="showDevisRecapModal" data-toggle="modal"
|
||||||
|
data-target="#devisRecapMontant">Generer le document recapitulatif</button><?php }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
@ -110,8 +133,9 @@
|
|||||||
<div id="gestion-canvas" class="canvas_div_pdf">
|
<div id="gestion-canvas" class="canvas_div_pdf">
|
||||||
<?php
|
<?php
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'GET' && strcmp($_GET['cli'], '') != 0) {
|
if ($_SERVER['REQUEST_METHOD'] == 'GET' && strcmp($_GET['cli'], '') != 0) {
|
||||||
if (sizeof($devis) == 0)
|
if (sizeof($devis) == 0) {
|
||||||
echo "Aucun devis trouvé.";
|
echo "Aucun devis trouvé.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -291,6 +315,27 @@
|
|||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="modal" id="devisRecapMontant" tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="exampleModalLabel">Souhaitez-vous le récapitulatif avec ou sans montant ?</h5>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="sansMontant" value="">
|
||||||
|
<label class="form-check-label" for="sansMontant">
|
||||||
|
Sans Montant
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button id="closeDevisRecapModal" type="button" class="btn btn-secondary">Annuler</button>
|
||||||
|
<button id="devisRecapAction" type="button" class="btn btn-primary">Générer</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="modal" id="groupDevisFacturationModal" tabindex="-1">
|
<div class="modal" id="groupDevisFacturationModal" tabindex="-1">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user