diff --git a/class/diffusion.class.php b/class/diffusion.class.php index 6bcf70e..26caf18 100644 --- a/class/diffusion.class.php +++ b/class/diffusion.class.php @@ -24,8 +24,8 @@ */ // Put here all includes required by your class file -require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; //require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; //require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; @@ -184,42 +184,42 @@ class Diffusion extends CommonObject * * @param DoliDB $db Database handler */ - public function __construct(DoliDB $db) - { - global $conf, $langs; - - $this->db = $db; - $this->ismultientitymanaged = 0; - $this->isextrafieldmanaged = 1; - - $entity = !empty($conf->entity) ? (int) $conf->entity : 1; - - if (!isset($conf->diffusionplans) || !is_object($conf->diffusionplans)) { - $conf->diffusionplans = new stdClass(); - } - - if (empty($conf->diffusionplans->dir_output)) { - $conf->diffusionplans->dir_output = DOL_DATA_ROOT.($entity > 1 ? '/'.$entity : '').'/diffusionplans'; - } - - if (empty($conf->diffusionplans->multidir_output) || !is_array($conf->diffusionplans->multidir_output)) { - $conf->diffusionplans->multidir_output = array(); - } - - if (empty($conf->diffusionplans->multidir_output[$entity])) { - $conf->diffusionplans->multidir_output[$entity] = $conf->diffusionplans->dir_output; - } - - $this->modulepart = 'diffusion'; - $this->dir_output = $conf->diffusionplans->dir_output.'/diffusion'; - - if (!empty($this->dir_output)) { - dol_mkdir($this->dir_output); - } - - if (!getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) { - $this->fields['rowid']['visible'] = 0; - } + public function __construct(DoliDB $db) + { + global $conf, $langs; + + $this->db = $db; + $this->ismultientitymanaged = 0; + $this->isextrafieldmanaged = 1; + + $entity = !empty($conf->entity) ? (int) $conf->entity : 1; + + if (!isset($conf->diffusionplans) || !is_object($conf->diffusionplans)) { + $conf->diffusionplans = new stdClass(); + } + + if (empty($conf->diffusionplans->dir_output)) { + $conf->diffusionplans->dir_output = DOL_DATA_ROOT.($entity > 1 ? '/'.$entity : '').'/diffusionplans'; + } + + if (empty($conf->diffusionplans->multidir_output) || !is_array($conf->diffusionplans->multidir_output)) { + $conf->diffusionplans->multidir_output = array(); + } + + if (empty($conf->diffusionplans->multidir_output[$entity])) { + $conf->diffusionplans->multidir_output[$entity] = $conf->diffusionplans->dir_output; + } + + $this->modulepart = 'diffusion'; + $this->dir_output = $conf->diffusionplans->dir_output.'/diffusion'; + + if (!empty($this->dir_output)) { + dol_mkdir($this->dir_output); + } + + if (!getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) { + $this->fields['rowid']['visible'] = 0; + } if (!isModEnabled('multicompany') && isset($this->fields['entity'])) { $this->fields['entity']['enabled'] = 0; } diff --git a/class/diffusioncontact.class.php b/class/diffusioncontact.class.php index 7d823a0..5780e63 100644 --- a/class/diffusioncontact.class.php +++ b/class/diffusioncontact.class.php @@ -24,8 +24,8 @@ */ // Put here all includes required by your class file -require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; //require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; //require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; @@ -172,41 +172,41 @@ class DiffusionContact extends CommonObject * * @param DoliDB $db Database handler */ - public function __construct(DoliDB $db) - { - global $conf, $langs; - - $this->db = $db; - $this->ismultientitymanaged = 0; - $this->isextrafieldmanaged = 1; - - $entity = !empty($conf->entity) ? (int) $conf->entity : 1; - - if (!isset($conf->diffusionplans) || !is_object($conf->diffusionplans)) { - $conf->diffusionplans = new stdClass(); - } - - if (empty($conf->diffusionplans->dir_output)) { - $conf->diffusionplans->dir_output = DOL_DATA_ROOT.($entity > 1 ? '/'.$entity : '').'/diffusionplans'; - } - - if (empty($conf->diffusionplans->multidir_output) || !is_array($conf->diffusionplans->multidir_output)) { - $conf->diffusionplans->multidir_output = array(); - } - - if (empty($conf->diffusionplans->multidir_output[$entity])) { - $conf->diffusionplans->multidir_output[$entity] = $conf->diffusionplans->dir_output; - } - - $this->modulepart = 'diffusioncontact'; - $this->dir_output = $conf->diffusionplans->dir_output.'/diffusioncontact'; - - if (!empty($this->dir_output)) { - dol_mkdir($this->dir_output); - } - - if (!getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) { - $this->fields['rowid']['visible'] = 0; + public function __construct(DoliDB $db) + { + global $conf, $langs; + + $this->db = $db; + $this->ismultientitymanaged = 0; + $this->isextrafieldmanaged = 1; + + $entity = !empty($conf->entity) ? (int) $conf->entity : 1; + + if (!isset($conf->diffusionplans) || !is_object($conf->diffusionplans)) { + $conf->diffusionplans = new stdClass(); + } + + if (empty($conf->diffusionplans->dir_output)) { + $conf->diffusionplans->dir_output = DOL_DATA_ROOT.($entity > 1 ? '/'.$entity : '').'/diffusionplans'; + } + + if (empty($conf->diffusionplans->multidir_output) || !is_array($conf->diffusionplans->multidir_output)) { + $conf->diffusionplans->multidir_output = array(); + } + + if (empty($conf->diffusionplans->multidir_output[$entity])) { + $conf->diffusionplans->multidir_output[$entity] = $conf->diffusionplans->dir_output; + } + + $this->modulepart = 'diffusioncontact'; + $this->dir_output = $conf->diffusionplans->dir_output.'/diffusioncontact'; + + if (!empty($this->dir_output)) { + dol_mkdir($this->dir_output); + } + + if (!getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) { + $this->fields['rowid']['visible'] = 0; } if (!isModEnabled('multicompany') && isset($this->fields['entity'])) { $this->fields['entity']['enabled'] = 0; diff --git a/core/modules/diffusionplans/doc/pdf_standard_diffusion.modules.php b/core/modules/diffusionplans/doc/pdf_standard_diffusion.modules.php index dd1890f..172cbba 100644 --- a/core/modules/diffusionplans/doc/pdf_standard_diffusion.modules.php +++ b/core/modules/diffusionplans/doc/pdf_standard_diffusion.modules.php @@ -36,8 +36,12 @@ dol_include_once('/diffusionplans/core/modules/diffusionplans/modules_diffusion.php'); require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; +require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; +require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; +require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; @@ -183,8 +187,9 @@ public function write_file($object, $outputlangs, $srctemplatepath = '', $hidede } // Load translation files required by the page - $langfiles = array("main", "bills", "products", "dict", "companies", "compta"); - $outputlangs->loadLangs($langfiles); + $langfiles = array("main", "bills", "products", "dict", "companies", "compta"); + $outputlangs->loadLangs($langfiles); + $outputlangs->loadLangs(array("diffusionplans@diffusionplans")); // Show Draft Watermark if (getDolGlobalString('DIFFUSION_DRAFT_WATERMARK') && $object->status == $object::STATUS_DRAFT) { @@ -800,8 +805,17 @@ public function write_file($object, $outputlangs, $srctemplatepath = '', $hidede } */ - // Pagefoot - $this->_pagefoot($pdf, $object, $outputlangs); + $pdf->setPage($pagenb); + $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext); + $baseline = ($pagenb == $pageposbeforeprintlines ? $tab_top : $tab_top_newpage); + $pdf->SetY(max($pdf->GetY(), $baseline)); + + $sectionY = $this->renderContactsSection($pdf, $object, $outputlangs, $outputlangsbis, $pagenb, empty($tplidx) ? null : $tplidx, $heightforfooter, $heightforfreetext); + $pdf->SetY($sectionY + 4); + $this->renderAttachmentsSection($pdf, $object, $outputlangs, $outputlangsbis, $pagenb, empty($tplidx) ? null : $tplidx, $heightforfooter, $heightforfreetext); + + // Pagefoot + $this->_pagefoot($pdf, $object, $outputlangs); if (method_exists($pdf, 'AliasNbPages')) { $pdf->AliasNbPages(); // @phan-suppress-current-line PhanUndeclaredMethod } @@ -864,51 +878,378 @@ public static function liste_modeles($db, $maxfilenamelength = 0) * @param ?Translate $outputlangsbis Langs object bis * @return void */ - protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '', $outputlangsbis = null) - { - global $conf; - - // Force to disable hidetop and hidebottom - $hidebottom = 0; - if ($hidetop) { - $hidetop = -1; - } - - $currency = !empty($currency) ? $currency : $conf->currency; - $default_font_size = pdf_getPDFFontSize($outputlangs); - - // Amount in (at tab_top - 1) - $pdf->SetTextColor(0, 0, 0); - $pdf->SetFont('', '', $default_font_size - 2); - - if (empty($hidetop)) { - $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency)); - if (getDolGlobalInt('PDF_USE_ALSO_LANGUAGE_CODE') && is_object($outputlangsbis)) { - $titre .= ' - '.$outputlangsbis->transnoentities("AmountInCurrency", $outputlangsbis->transnoentitiesnoconv("Currency".$currency)); - } - - $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4); - $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre); - - //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230'; - if (getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')) { - $pdf->Rect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite - $this->marge_gauche, $this->tabTitleHeight, 'F', array(), explode(',', getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR'))); - } - } - - $pdf->SetDrawColor(128, 128, 128); - $pdf->SetFont('', '', $default_font_size - 1); - - // Output Rect - $this->printRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect takes a length in 3rd parameter and 4th parameter - - - $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop); - - if (empty($hidetop)) { - $pdf->line($this->marge_gauche, $tab_top + $this->tabTitleHeight, $this->page_largeur - $this->marge_droite, $tab_top + $this->tabTitleHeight); // line takes a position y in 2nd parameter and 4th parameter - } - } + protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '', $outputlangsbis = null) + { + global $conf; + + // Force to disable hidetop and hidebottom + $hidebottom = 0; + if ($hidetop) { + $hidetop = -1; + } + + $currency = !empty($currency) ? $currency : $conf->currency; + $default_font_size = pdf_getPDFFontSize($outputlangs); + + // Amount in (at tab_top - 1) + $pdf->SetTextColor(0, 0, 0); + $pdf->SetFont('', '', $default_font_size - 2); + + if (empty($hidetop)) { + $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency)); + if (getDolGlobalInt('PDF_USE_ALSO_LANGUAGE_CODE') && is_object($outputlangsbis)) { + $titre .= ' - '.$outputlangsbis->transnoentities("AmountInCurrency", $outputlangsbis->transnoentitiesnoconv("Currency".$currency)); + } + + $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4); + $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre); + + //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230'; + if (getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')) { + $pdf->Rect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite - $this->marge_gauche, $this->tabTitleHeight, 'F', array(), explode(',', getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR'))); + } + } + + $pdf->SetDrawColor(128, 128, 128); + $pdf->SetFont('', '', $default_font_size - 1); + + // Output Rect + $this->printRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect takes a length in 3rd parameter and 4th parameter + + + $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop); + + if (empty($hidetop)) { + $pdf->line($this->marge_gauche, $tab_top + $this->tabTitleHeight, $this->page_largeur - $this->marge_droite, $tab_top + $this->tabTitleHeight); // line takes a position y in 2nd parameter and 4th parameter + } + } + + /** + * Render the contacts section. + * + * @param TCPDF|TCPDI $pdf PDF handler + * @param Diffusion $object Diffusion object + * @param Translate $outputlangs Language handler + * @param ?Translate $outputlangsbis Secondary language handler + * @param int $pagenb Current page number (updated if new pages are added) + * @param int|null $tplidx Background template index + * @param float $heightforfooter Footer height + * @param float $heightforfreetext Free text height + * @return float Current Y position after rendering + */ + protected function renderContactsSection(&$pdf, $object, $outputlangs, $outputlangsbis, &$pagenb, $tplidx, $heightforfooter, $heightforfreetext) + { + $contacts = $this->fetchDiffusionContacts($object, $outputlangs); + $default_font_size = pdf_getPDFFontSize($outputlangs); + $this->ensureContentHeight($pdf, $object, $outputlangs, $outputlangsbis, $pagenb, $tplidx, 8, $heightforfooter, $heightforfreetext); + + $pdf->SetFont('', 'B', $default_font_size); + $pdf->SetTextColor(0, 0, 60); + $pdf->SetX($this->marge_gauche); + $pdf->MultiCell($this->page_largeur - $this->marge_gauche - $this->marge_droite, 6, $outputlangs->transnoentities('DiffusionContactsTitle'), 0, 'L'); + + $pdf->SetFont('', '', $default_font_size - 1); + $pdf->SetTextColor(0, 0, 0); + $pdf->SetY($pdf->GetY() + 2); + + if (empty($contacts)) { + $this->ensureContentHeight($pdf, $object, $outputlangs, $outputlangsbis, $pagenb, $tplidx, 5, $heightforfooter, $heightforfreetext); + $pdf->SetX($this->marge_gauche); + $pdf->MultiCell($this->page_largeur - $this->marge_gauche - $this->marge_droite, 5, $outputlangs->transnoentities('DiffusionNoContacts'), 0, 'L'); + return $pdf->GetY(); + } + + $headers = array( + $outputlangs->transnoentities('ThirdParty'), + $outputlangs->transnoentities('Contacts'), + $outputlangs->transnoentities('ContactType'), + $outputlangs->transnoentities('methodMail'), + $outputlangs->transnoentities('methodLetter'), + $outputlangs->transnoentities('methodHand'), + ); + $widths = array(45, 45, 35, 20, 20, 20); + $aligns = array('L', 'L', 'L', 'C', 'C', 'C'); + + $pdf->SetFillColor(240, 240, 240); + $this->renderTableRow($pdf, $object, $outputlangs, $outputlangsbis, $headers, $widths, $aligns, true, $pagenb, $tplidx, $heightforfooter, $heightforfreetext); + + $fill = false; + foreach ($contacts as $contactRow) { + $pdf->SetFillColor($fill ? 248 : 255, $fill ? 248 : 255, $fill ? 248 : 255); + $row = array( + $contactRow['thirdparty'], + $contactRow['contact'], + $contactRow['type'], + $contactRow['mail_status'], + $contactRow['letter_status'], + $contactRow['hand_status'], + ); + $this->renderTableRow($pdf, $object, $outputlangs, $outputlangsbis, $row, $widths, $aligns, $fill, $pagenb, $tplidx, $heightforfooter, $heightforfreetext); + $fill = !$fill; + } + + return $pdf->GetY(); + } + + /** + * Render the attachments section. + * + * @param TCPDF|TCPDI $pdf PDF handler + * @param Diffusion $object Diffusion object + * @param Translate $outputlangs Language handler + * @param ?Translate $outputlangsbis Secondary language handler + * @param int $pagenb Current page number (updated if new pages are added) + * @param int|null $tplidx Background template index + * @param float $heightforfooter Footer height + * @param float $heightforfreetext Free text height + * @return float Current Y position after rendering + */ + protected function renderAttachmentsSection(&$pdf, $object, $outputlangs, $outputlangsbis, &$pagenb, $tplidx, $heightforfooter, $heightforfreetext) + { + $files = $this->fetchDiffusionAttachments($object); + $default_font_size = pdf_getPDFFontSize($outputlangs); + $this->ensureContentHeight($pdf, $object, $outputlangs, $outputlangsbis, $pagenb, $tplidx, 8, $heightforfooter, $heightforfreetext); + + $pdf->SetFont('', 'B', $default_font_size); + $pdf->SetTextColor(0, 0, 60); + $pdf->SetX($this->marge_gauche); + $pdf->MultiCell($this->page_largeur - $this->marge_gauche - $this->marge_droite, 6, $outputlangs->transnoentities('DiffusionAttachmentsTitle'), 0, 'L'); + + $pdf->SetFont('', '', $default_font_size - 1); + $pdf->SetTextColor(0, 0, 0); + $pdf->SetY($pdf->GetY() + 2); + + if (empty($files)) { + $this->ensureContentHeight($pdf, $object, $outputlangs, $outputlangsbis, $pagenb, $tplidx, 5, $heightforfooter, $heightforfreetext); + $pdf->SetX($this->marge_gauche); + $pdf->MultiCell($this->page_largeur - $this->marge_gauche - $this->marge_droite, 5, $outputlangs->transnoentities('DiffusionNoDocuments'), 0, 'L'); + return $pdf->GetY(); + } + + $width = $this->page_largeur - $this->marge_gauche - $this->marge_droite; + foreach ($files as $file) { + $line = $outputlangs->transnoentities('DiffusionAttachmentLine', $file['label'], $file['size']); + $text = $outputlangs->convToOutputCharset($line); + $height = max(5, $pdf->getStringHeight($width, $text)); + $this->ensureContentHeight($pdf, $object, $outputlangs, $outputlangsbis, $pagenb, $tplidx, $height + 1, $heightforfooter, $heightforfreetext); + $pdf->SetX($this->marge_gauche); + $pdf->MultiCell($width, $height, $text, 0, 'L'); + $pdf->SetY($pdf->GetY() + 1); + } + + return $pdf->GetY(); + } + + /** + * Render a table row with automatic height and page break handling. + * + * @param TCPDF|TCPDI $pdf PDF handler + * @param Diffusion $object Diffusion object + * @param Translate $outputlangs Language handler + * @param ?Translate $outputlangsbis Secondary language handler + * @param array $cells Cell contents + * @param array $widths Column widths + * @param array $aligns Column alignments + * @param bool $fill Background fill flag + * @param int $pagenb Current page number (updated if new pages are added) + * @param int|null $tplidx Background template index + * @param float $heightforfooter Footer height + * @param float $heightforfreetext Free text height + * @return float Current Y position after rendering + */ + protected function renderTableRow(&$pdf, $object, $outputlangs, $outputlangsbis, $cells, $widths, $aligns, $fill, &$pagenb, $tplidx, $heightforfooter, $heightforfreetext) + { + $converted = array(); + $rowHeight = 0; + foreach ($cells as $index => $cell) { + $text = $outputlangs->convToOutputCharset(dol_string_nohtmltag($cell)); + $converted[$index] = $text; + $rowHeight = max($rowHeight, $pdf->getStringHeight($widths[$index], $text)); + } + + $rowHeight = max($rowHeight, 6); + $this->ensureContentHeight($pdf, $object, $outputlangs, $outputlangsbis, $pagenb, $tplidx, $rowHeight + 1, $heightforfooter, $heightforfreetext); + + $x = $this->marge_gauche; + $y = $pdf->GetY(); + $count = count($converted); + for ($i = 0; $i < $count; $i++) { + $ln = ($i + 1 === $count) ? 1 : 0; + $pdf->MultiCell($widths[$i], $rowHeight, $converted[$i], 1, $aligns[$i], $fill, $ln, $x, $y, true, 0, false, true, $rowHeight, 'M'); + $x += $widths[$i]; + } + + $pdf->SetY($y + $rowHeight); + return $pdf->GetY(); + } + + /** + * Ensure there is enough vertical space, adding a page if needed. + * + * @param TCPDF|TCPDI $pdf PDF handler + * @param Diffusion $object Diffusion object + * @param Translate $outputlangs Language handler + * @param ?Translate $outputlangsbis Secondary language handler + * @param int $pagenb Current page number (updated if new pages are added) + * @param int|null $tplidx Background template index + * @param float $neededHeight Required height + * @param float $heightforfooter Footer height + * @param float $heightforfreetext Free text height + * @return void + */ + protected function ensureContentHeight(&$pdf, $object, $outputlangs, $outputlangsbis, &$pagenb, $tplidx, $neededHeight, $heightforfooter, $heightforfreetext) + { + $available = $this->page_hauteur - $pdf->GetY() - $heightforfooter - $heightforfreetext; + if ($available >= $neededHeight) { + return; + } + + $this->_pagefoot($pdf, $object, $outputlangs, 1); + $pdf->AddPage('', '', true); + $pagenb++; + + if (!empty($tplidx)) { + $pdf->useTemplate($tplidx); + } + + if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) { + $this->_pagehead($pdf, $object, 0, $outputlangs, $outputlangsbis); + } + + $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext); + $pdf->SetY(max($pdf->GetY(), $this->marge_haute)); + } + + /** + * Retrieve diffusion contacts with their statuses. + * + * @param Diffusion $object Diffusion object + * @param Translate $outputlangs Language handler + * @return array> + */ + protected function fetchDiffusionContacts($object, $outputlangs) + { + $contactsData = array(); + $societestatic = new Societe($this->db); + $contactstatic = new Contact($this->db); + $userstatic = new User($this->db); + + if (empty($object->thirdparty) || empty($object->thirdparty->id)) { + $object->fetch_thirdparty(); + } + + $defaultThirdparty = ''; + if (!empty($object->thirdparty->id)) { + $defaultThirdparty = dol_string_nohtmltag($object->thirdparty->getFullName($outputlangs)); + } elseif (!empty($this->emetteur->name)) { + $defaultThirdparty = dol_string_nohtmltag($this->emetteur->name); + } else { + $defaultThirdparty = dol_string_nohtmltag(getDolGlobalString('MAIN_INFO_SOCIETE_NOM')); + } + + foreach (array('internal', 'external') as $source) { + $contactList = $object->liste_contact(-1, $source); + foreach ($contactList as $contact) { + $entry = array( + 'thirdparty' => $defaultThirdparty, + 'contact' => '', + 'type' => dol_string_nohtmltag(isset($contact['libelle']) ? $contact['libelle'] : ''), + ); + + if ($source === 'internal') { + if ($userstatic->fetch((int) $contact['id']) > 0) { + $entry['contact'] = dol_string_nohtmltag($userstatic->getFullName($outputlangs)); + } else { + $entry['contact'] = dol_string_nohtmltag(isset($contact['lastname']) ? $contact['lastname'] : ''); + } + } else { + if ($contactstatic->fetch((int) $contact['id']) > 0) { + $entry['contact'] = dol_string_nohtmltag($contactstatic->getFullName($outputlangs)); + } else { + $entry['contact'] = dol_string_nohtmltag(isset($contact['lastname']) ? $contact['lastname'] : ''); + } + + if (!empty($contact['socid']) && $contact['socid'] > 0 && $societestatic->fetch((int) $contact['socid']) > 0) { + $entry['thirdparty'] = dol_string_nohtmltag($societestatic->getFullName($outputlangs)); + } + } + + $status = $this->fetchDiffusionContactStatus($object->id, (int) $contact['id'], $source); + $entry['mail_status'] = $outputlangs->transnoentities($status['mail_status'] ? 'Enabled' : 'Disabled'); + $entry['letter_status'] = $outputlangs->transnoentities($status['letter_status'] ? 'Enabled' : 'Disabled'); + $entry['hand_status'] = $outputlangs->transnoentities($status['hand_status'] ? 'Enabled' : 'Disabled'); + + $contactsData[] = $entry; + } + } + + return $contactsData; + } + + /** + * Retrieve contact status row. + * + * @param int $diffusionId Diffusion identifier + * @param int $contactId Contact identifier + * @param string $source Contact source (internal|external) + * @return array + */ + protected function fetchDiffusionContactStatus($diffusionId, $contactId, $source) + { + $result = array('mail_status' => 0, 'letter_status' => 0, 'hand_status' => 0); + + $sql = "SELECT mail_status, letter_status, hand_status"; + $sql .= " FROM ".MAIN_DB_PREFIX."diffusionplans_diffusioncontact"; + $sql .= " WHERE fk_diffusion = ".((int) $diffusionId); + $sql .= " AND fk_contact = ".((int) $contactId); + $sql .= " AND contact_source = '".$this->db->escape($source)."'"; + $sql .= " LIMIT 1"; + + $resql = $this->db->query($sql); + if ($resql) { + $obj = $this->db->fetch_object($resql); + if ($obj) { + $result['mail_status'] = (int) $obj->mail_status; + $result['letter_status'] = (int) $obj->letter_status; + $result['hand_status'] = (int) $obj->hand_status; + } + $this->db->free($resql); + } + + return $result; + } + + /** + * Retrieve attachments linked to diffusion. + * + * @param Diffusion $object Diffusion object + * @return array> + */ + protected function fetchDiffusionAttachments($object) + { + $attachments = array(); + $dir = getMultidirOutput($object); + $objectref = dol_sanitizeFileName($object->ref); + + if (empty($dir) || empty($objectref)) { + return $attachments; + } + + $docdir = $dir.'/'.$objectref; + if (!is_dir($docdir)) { + return $attachments; + } + + $filelist = dol_dir_list($docdir, 'files', 0, '', '(\\.meta|_preview.*\\.png)$', 'name', SORT_ASC); + foreach ($filelist as $file) { + $attachments[] = array( + 'label' => $file['name'], + 'size' => dol_string_nohtmltag(dol_print_size($file['size'], 1)), + ); + } + + return $attachments; + } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore /** diff --git a/core/modules/modDiffusionPlans.class.php b/core/modules/modDiffusionPlans.class.php index 2ad5626..bf28b10 100644 --- a/core/modules/modDiffusionPlans.class.php +++ b/core/modules/modDiffusionPlans.class.php @@ -83,25 +83,25 @@ public function __construct($db) // Key used in llx_const table to save module status enabled/disabled (where DIFFUSIONPLANS is value of property name of module in uppercase) $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); - if (!isset($conf->diffusionplans) || !is_object($conf->diffusionplans)) { - $conf->diffusionplans = new stdClass(); - } - - $entity = !empty($conf->entity) ? (int) $conf->entity : 1; - $defaultDir = DOL_DATA_ROOT.($entity > 1 ? '/'.$entity : '').'/diffusionplans'; - - if (empty($conf->diffusionplans->dir_output)) { - $conf->diffusionplans->dir_output = $defaultDir; - } - if (empty($conf->diffusionplans->dir_temp)) { - $conf->diffusionplans->dir_temp = $conf->diffusionplans->dir_output.'/temp'; - } - if (empty($conf->diffusionplans->multidir_output) || !is_array($conf->diffusionplans->multidir_output)) { - $conf->diffusionplans->multidir_output = array(); - } - if (empty($conf->diffusionplans->multidir_output[$entity])) { - $conf->diffusionplans->multidir_output[$entity] = $defaultDir; - } + if (!isset($conf->diffusionplans) || !is_object($conf->diffusionplans)) { + $conf->diffusionplans = new stdClass(); + } + + $entity = !empty($conf->entity) ? (int) $conf->entity : 1; + $defaultDir = DOL_DATA_ROOT.($entity > 1 ? '/'.$entity : '').'/diffusionplans'; + + if (empty($conf->diffusionplans->dir_output)) { + $conf->diffusionplans->dir_output = $defaultDir; + } + if (empty($conf->diffusionplans->dir_temp)) { + $conf->diffusionplans->dir_temp = $conf->diffusionplans->dir_output.'/temp'; + } + if (empty($conf->diffusionplans->multidir_output) || !is_array($conf->diffusionplans->multidir_output)) { + $conf->diffusionplans->multidir_output = array(); + } + if (empty($conf->diffusionplans->multidir_output[$entity])) { + $conf->diffusionplans->multidir_output[$entity] = $defaultDir; + } // Name of image file used for this module. // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' @@ -157,11 +157,11 @@ public function __construct($db) // Data directories to create when module is enabled. // Example: this->dirs = array("/diffusionplans/temp","/diffusionplans/subdir"); - $this->dirs = array( - "/diffusionplans/temp", - "/diffusionplans/diffusion", - "/diffusionplans/diffusioncontact", - ); + $this->dirs = array( + "/diffusionplans/temp", + "/diffusionplans/diffusion", + "/diffusionplans/diffusioncontact", + ); // Config pages. Put here list of php page, stored into diffusionplans/admin directory, to use to setup module. $this->config_page_url = array("setup.php@diffusionplans"); diff --git a/langs/en_US/diffusionplans.lang b/langs/en_US/diffusionplans.lang index 8e0c9c6..5678ace 100644 --- a/langs/en_US/diffusionplans.lang +++ b/langs/en_US/diffusionplans.lang @@ -1,46 +1,147 @@ # Translation file -# -# Generic -# - -# Module label 'ModuleDiffusionPlansName' -ModuleDiffusionPlansName = DiffusionPlans -# Module description 'ModuleDiffusionPlansDesc' -ModuleDiffusionPlansDesc = DiffusionPlans description - -# -# Admin page -# +About = About +Actions = Actions +Activated = Activated +Add = Add +AddAnAction = Add an action +AddProject = Add project +Agenda = Agenda +AmountInCurrency = Amount in %s +AnotherField = Another field +BackToList = Back to list +BackToModuleList = Back to module list +BillFrom = Bill from +BoxTitleLatestModifiedMyObjects = Latest modified items +ClassNotFound = Class not found +CloneMainAttributes = Clone main attributes +ConfirmClone = Confirm cloning +ContactType = Contact type +Contacts = Contacts +CopyOf = Copy of +Currency = Currency +CustomerAccountancyCode = Customer accountancy code +CustomerCode = Customer code +DIRECTION = DIRECTION +Date = Date +DateModificationShort = Modified +Default = Default +Delete = Delete +Description = Description +Diffusion = Diffusion +DiffusionAttachmentLine = %s (%s) +DiffusionAttachmentsTitle = Attached documents +DiffusionContact = Diffusion contact +DiffusionContacts = Diffusion contacts +DiffusionContactsTitle = Diffusion contacts +DiffusionNoContacts = No contact is linked to this diffusion. +DiffusionNoDocuments = No document is attached to this diffusion. +DiffusionPlansArea = DiffusionPlans area DiffusionPlansSetup = DiffusionPlans setup -Settings = Settings DiffusionPlansSetupPage = DiffusionPlans setup page -NewSection=New section -DIFFUSIONPLANS_MYPARAM1 = My param 1 -DIFFUSIONPLANS_MYPARAM1Tooltip = My param 1 tooltip -DIFFUSIONPLANS_MYPARAM2=My param 2 -DIFFUSIONPLANS_MYPARAM2Tooltip=My param 2 tooltip - - -# -# About page -# -About = About -DiffusionPlansAbout = About DiffusionPlans -DiffusionPlansAboutPage = DiffusionPlans about page - -# -# Sample page -# -DiffusionPlansArea = Home DiffusionPlans -MyPageName = My page name - -# -# Sample widget -# -MyWidget = My widget -MyWidgetDescription = My widget description - +Diffusions = Diffusions +Disable = Disable +Disabled = Disabled +DocumentModelOdt = OpenDocument templates +DocumentModules = Document models +Draft = Draft +DraftMyObjects = My drafts +Enabled = Enabled +Error = Error +ErrorAddAtLeastOneLineFirst = Add at least one line before validating. +ErrorCanNotCreateDir = Cannot create directory %s +ErrorConstantNotDefined = Constant %s is not defined +ErrorDirNotFound = Directory %s not found +ErrorFailedToWriteInTempDirectory = Failed to write into temporary directory +ErrorGoToGlobalSetup = Check the global setup. +ErrorLogoFileNotFound = Logo file %s not found +ErrorModuleNotFound = Module not found +ErrorNumberingModuleNotSetup = Numbering module is not configured. +ErrorThisContactIsAlreadyDefinedAsThisType = This contact is already linked with this type. +Events = Events +Example = Example +ExampleOfDirectoriesForModelGen = Example of directories for models +ExtraFields = Extra fields +FeaturesSupported = Supported features +FieldEdition = Field edition +Files = Files +FilterOnInto = Filter on +FollowingSubstitutionKeysCanBeUsed = You can use the following substitution keys: +FullListOnOnlineDocumentation = See the online documentation for the complete list. +GenericMaskCodes = Generic mask codes: {yyyy}, {yy}, {mm}, {dd}, {0000}, {@}, {cccc}, {tt}, ... +GenericMaskCodes2 = Example: {yyyy}{mm}-{0000} gives 202501-0001. +GenericMaskCodes3 = Counter length is the number of zeros. {0000@99} starts at 0100. +GenericMaskCodes4a = Use a mask compatible with %s numbering to keep existing %s references. +GenericMaskCodes5 = Use {cccc} for third party code, {ss} for supplier code. +GenericMaskCodes5b = See online documentation for other placeholders. +Height = Height +Id = Id +Link = Link +ListOfDirectories = List of directories +ListOfDirectoriesForModelGenODT = List of directories for ODT models +Logo = Logo +Mask = Mask +Modify = Modify +ModuleDiffusionPlansDesc = Module to create plan or document diffusions. +ModuleDiffusionPlansName = Diffusion plans +MultiLanguage = Multi-language +MyOwnFamily = My own family +Name = Name +NatureOfContact = Nature of contact +NbOfAttachedFiles = Number of attached files +NewAttribute = New attribute +NewDiffusion = New diffusion +NewObject = New object +NextValue = Next value +NoOrder = No order +NoRecordFound = No record found +NoSpecificContactAddress = No dedicated contact address +NoSpecificContactAddressBis = No dedicated address +None = None +NotAvailable = Not available +NotValidated = Not validated +NothingToSetup = Nothing to configure +NumberOfModelFilesFound = Number of model files found +NumberingModules = Numbering modules +OtherOrders = Other orders +PDFMerge = Merge PDF +Path = Path +PdfTitle = Diffusion +Preview = Preview +PreviewNotAvailable = Preview not available +Project = Project +PuttingPricesUpToDate = Update prices +ReGeneratePDF = Regenerate PDF +Ref = Ref +RefCustomer = Customer ref +RefProject = Project ref +SalesRepresentative = Sales representative +SelectWarehouseForStockDecrease = Select warehouse for stock decrease +SendByMail = Send by email +Settings = Settings +SetupSaved = Setup saved +ShortInfo = Short information +ShowDiffusion = Show diffusion +ShowDiffusionContact = Show diffusion contact +SimpleNumRefModelDesc = Simple automatic numbering +Status = Status +ThirdParty = Third party +ThirdPartyContact = Third party contact +To = To +Total = Total +TotalSizeOfAttachedFiles = Total size of attached files +Type = Type +Unknown = Unknown +Unlink = Unlink +Upload = Upload +UploadNewTemplate = Upload a new template +User = User +Users = Users +Validate = Validate +Version = Version +Width = Width +bytes = bytes +methodHand = Hand delivered +methodLetter = Send by letter methodMail = Send by email -methodLetter = Send by mail -methodHand = Hand delivered \ No newline at end of file +or = or diff --git a/langs/fr_FR/diffusionplans.lang b/langs/fr_FR/diffusionplans.lang index bcccce7..ff684c0 100644 --- a/langs/fr_FR/diffusionplans.lang +++ b/langs/fr_FR/diffusionplans.lang @@ -1,47 +1,147 @@ -# Translation file - -# -# Generic -# - -# Module label 'ModuleDiffusionPlansName' -ModuleDiffusionPlansName = Diffusion de Plans -# Module description 'ModuleDiffusionPlansDesc' -ModuleDiffusionPlansDesc = Module permettant de créer des courriers de diffusions de plans ou de documents. - -# -# Admin page -# -DiffusionPlansSetup = DiffusionPlans setup -Settings = Settings -DiffusionPlansSetupPage = DiffusionPlans setup page -NewSection=New section -DIFFUSIONPLANS_MYPARAM1 = My param 1 -DIFFUSIONPLANS_MYPARAM1Tooltip = My param 1 tooltip -DIFFUSIONPLANS_MYPARAM2=My param 2 -DIFFUSIONPLANS_MYPARAM2Tooltip=My param 2 tooltip - - -# -# About page -# -About = About -DiffusionPlansAbout = About DiffusionPlans -DiffusionPlansAboutPage = DiffusionPlans about page - -# -# Sample page -# -DiffusionPlansArea = Home DiffusionPlans -MyPageName = My page name - -# -# Sample widget -# -MyWidget = My widget -MyWidgetDescription = My widget description - - -methodMail = Envoyer par e-mail -methodLetter = Envoyer par courrier -methodHand = Remis en main propre \ No newline at end of file +# Translation file + +About = À propos +Actions = Actions +Activated = Activé +Add = Ajouter +AddAnAction = Ajouter une action +AddProject = Ajouter un projet +Agenda = Agenda +AmountInCurrency = Montant en %s +AnotherField = Autre champ +BackToList = Retour à la liste +BackToModuleList = Retour à la liste des modules +BillFrom = Facturer depuis +BoxTitleLatestModifiedMyObjects = Derniers éléments modifiés +ClassNotFound = Classe introuvable +CloneMainAttributes = Cloner les attributs principaux +ConfirmClone = Confirmer le clonage +ContactType = Type de contact +Contacts = Contacts +CopyOf = Copie de +Currency = Devise +CustomerAccountancyCode = Code comptable client +CustomerCode = Code client +DIRECTION = DIRECTION +Date = Date +DateModificationShort = Modifié +Default = Par défaut +Delete = Supprimer +Description = Description +Diffusion = Diffusion +DiffusionAttachmentLine = %s (%s) +DiffusionAttachmentsTitle = Documents joints +DiffusionContact = Contact de diffusion +DiffusionContacts = Contacts de diffusion +DiffusionContactsTitle = Contacts de la diffusion +DiffusionNoContacts = Aucun contact n'est lié à cette diffusion. +DiffusionNoDocuments = Aucun document n'est joint à cette diffusion. +DiffusionPlansArea = Accueil DiffusionPlans +DiffusionPlansSetup = Configuration DiffusionPlans +DiffusionPlansSetupPage = Page de configuration DiffusionPlans +Diffusions = Diffusions +Disable = Désactiver +Disabled = Désactivé +DocumentModelOdt = Modèles OpenDocument +DocumentModules = Modèles de documents +Draft = Brouillon +DraftMyObjects = Mes brouillons +Enabled = Activé +Error = Erreur +ErrorAddAtLeastOneLineFirst = Ajoutez au moins une ligne avant de valider. +ErrorCanNotCreateDir = Impossible de créer le répertoire %s +ErrorConstantNotDefined = La constante %s n'est pas définie +ErrorDirNotFound = Répertoire %s introuvable +ErrorFailedToWriteInTempDirectory = Impossible d'écrire dans le répertoire temporaire +ErrorGoToGlobalSetup = Vérifiez la configuration globale. +ErrorLogoFileNotFound = Fichier logo %s introuvable +ErrorModuleNotFound = Module introuvable +ErrorNumberingModuleNotSetup = Le module de numérotation n'est pas configuré. +ErrorThisContactIsAlreadyDefinedAsThisType = Ce contact est déjà lié avec ce type. +Events = Événements +Example = Exemple +ExampleOfDirectoriesForModelGen = Exemple de répertoires pour les modèles +ExtraFields = Champs supplémentaires +FeaturesSupported = Fonctionnalités prises en charge +FieldEdition = Édition du champ +Files = Fichiers +FilterOnInto = Filtrer sur +FollowingSubstitutionKeysCanBeUsed = Vous pouvez utiliser les clés de substitution suivantes : +FullListOnOnlineDocumentation = Voir la documentation en ligne pour la liste complète. +GenericMaskCodes = Codes génériques : {yyyy}, {yy}, {mm}, {dd}, {0000}, {@}, {cccc}, {tt}, ... +GenericMaskCodes2 = Exemple : {yyyy}{mm}-{0000} donne 202501-0001. +GenericMaskCodes3 = La longueur du compteur correspond au nombre de zéros. {0000@99} démarre à 0100. +GenericMaskCodes4a = Utilisez un masque compatible avec la numérotation %s pour conserver les références %s existantes. +GenericMaskCodes5 = Utilisez {cccc} pour le code tiers, {ss} pour le code fournisseur. +GenericMaskCodes5b = Consultez la documentation en ligne pour d'autres paramètres. +Height = Hauteur +Id = Id +Link = Lien +ListOfDirectories = Liste des répertoires +ListOfDirectoriesForModelGenODT = Liste des répertoires pour les modèles ODT +Logo = Logo +Mask = Masque +Modify = Modifier +ModuleDiffusionPlansDesc = Module permettant de créer des diffusions de plans ou de documents. +ModuleDiffusionPlansName = Diffusion de plans +MultiLanguage = Multilingue +MyOwnFamily = Ma propre famille +Name = Nom +NatureOfContact = Nature du contact +NbOfAttachedFiles = Nombre de fichiers joints +NewAttribute = Nouvel attribut +NewDiffusion = Nouvelle diffusion +NewObject = Nouvel objet +NextValue = Valeur suivante +NoOrder = Sans ordre +NoRecordFound = Aucun enregistrement trouvé +NoSpecificContactAddress = Pas d'adresse de contact dédiée +NoSpecificContactAddressBis = Aucune adresse dédiée +None = Aucun +NotAvailable = Non disponible +NotValidated = Non validé +NothingToSetup = Aucun paramètre à configurer +NumberOfModelFilesFound = Nombre de fichiers modèles trouvés +NumberingModules = Modules de numérotation +OtherOrders = Autres commandes +PDFMerge = Fusionner le PDF +Path = Chemin +PdfTitle = Diffusion +Preview = Prévisualisation +PreviewNotAvailable = Prévisualisation indisponible +Project = Projet +PuttingPricesUpToDate = Mise à jour des prix +ReGeneratePDF = Régénérer le PDF +Ref = Réf +RefCustomer = Réf client +RefProject = Réf projet +SalesRepresentative = Représentant commercial +SelectWarehouseForStockDecrease = Sélectionnez l'entrepôt pour la sortie de stock +SendByMail = Envoyer par mail +Settings = Paramètres +SetupSaved = Configuration enregistrée +ShortInfo = Information courte +ShowDiffusion = Afficher la diffusion +ShowDiffusionContact = Afficher le contact de diffusion +SimpleNumRefModelDesc = Numérotation automatique simple +Status = Statut +ThirdParty = Tiers +ThirdPartyContact = Contact tiers +To = À +Total = Total +TotalSizeOfAttachedFiles = Taille totale des fichiers joints +Type = Type +Unknown = Inconnu +Unlink = Dissocier +Upload = Téléverser +UploadNewTemplate = Téléverser un nouveau modèle +User = Utilisateur +Users = Utilisateurs +Validate = Valider +Version = Version +Width = Largeur +bytes = octets +methodHand = Remis en main propre +methodLetter = Envoyer par courrier +methodMail = Envoyer par e-mail +or = ou