dolibarr 25.0.0-alpha
supplier_invoice.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2003-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2013 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2011 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
6 * Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
7 * Copyright (C) 2010-2013 Juanjo Menent <jmenent@2byte.es>
8 * Copyright (C) 2011-2018 Philippe Grand <philippe.grand@atoo-net.com>
9 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
10 * Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
11 * Copyright (C) 2026 Pierre Ardoin <developpeur@lesmetiersdubatiment.fr>
12 * Copyright (C) 2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27
34// Load Dolibarr environment
35require '../../main.inc.php';
36
46require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
47require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
48if (getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD')) {
49 require_once DOL_DOCUMENT_ROOT . '/core/lib/supplier_invoice.lib.php';
50} else {
51 require_once DOL_DOCUMENT_ROOT . '/core/lib/fourn.lib.php';
52}
53require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php';
54require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
55
56// Load translation files required by the page
57$langs->loadLangs(array("admin", "other", "orders"));
58
59$action = GETPOST('action', 'aZ09');
60
61$type = GETPOST('type', 'alpha');
62$value = GETPOST('value', 'alpha');
63$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php
64
65$label = GETPOST('label', 'alpha');
66$scandir = GETPOST('scan_dir', 'alpha');
67
68$specimenthirdparty = new Societe($db);
69$specimenthirdparty->initAsSpecimen();
70
71$error = 0;
72
73if (!$user->admin) {
75}
76
77
78/*
79 * Actions
80 */
81
82include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
83
84if ($action == 'updateMask') {
85 $maskconstinvoice = GETPOST('maskconstinvoice', 'aZ09');
86 $maskconstcredit = GETPOST('maskconstcredit', 'aZ09');
87 $maskconstdeposit = GETPOST('maskconstdeposit', 'aZ09');
88 $maskinvoice = GETPOST('maskinvoice', 'alpha');
89 $maskcredit = GETPOST('maskcredit', 'alpha');
90 $maskdeposit = GETPOST('maskdeposit', 'alpha');
91 $res = 0;
92
93 if ($maskconstinvoice && preg_match('/_MASK$/', $maskconstinvoice)) {
94 $res = dolibarr_set_const($db, $maskconstinvoice, $maskinvoice, 'chaine', 0, '', $conf->entity);
95 }
96 if ($maskconstcredit && preg_match('/_MASK$/', $maskconstcredit)) {
97 $res = dolibarr_set_const($db, $maskconstcredit, $maskcredit, 'chaine', 0, '', $conf->entity);
98 }
99 if ($maskconstdeposit && preg_match('/_MASK$/', $maskconstdeposit)) {
100 $res = dolibarr_set_const($db, $maskconstdeposit, $maskdeposit, 'chaine', 0, '', $conf->entity);
101 }
102
103 if (!($res > 0)) {
104 $error++;
105 }
106
107 if (!$error) {
108 setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
109 } else {
110 setEventMessages($langs->trans("Error"), null, 'errors');
111 }
112}
113
114if ($action == 'specimen') { // For invoices
115 $modele = GETPOST('module', 'alpha');
116
117 $facture = new FactureFournisseur($db);
118 $facture->initAsSpecimen();
119 $facture->thirdparty = $specimenthirdparty; // Define who should has build the invoice (so the supplier)
120
121 // Search template files
122 $file = '';
123 $classname = '';
124 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
125 foreach ($dirmodels as $reldir) {
126 $file = dol_buildpath($reldir."core/modules/supplier_invoice/doc/pdf_".$modele.".modules.php", 0);
127 if (file_exists($file)) {
128 $classname = "pdf_".$modele;
129 break;
130 }
131 }
132
133 if ($classname !== '') {
134 require_once $file;
135
136 $module = new $classname($db, $facture);
137 '@phan-var-force ModelePDFSuppliersInvoices $module';
138
139 if ($module->write_file($facture, $langs) > 0) {
140 header("Location: ".DOL_URL_ROOT."/document.php?modulepart=facture_fournisseur&file=SPECIMEN.pdf");
141 return;
142 } else {
143 setEventMessages($module->error, $module->errors, 'errors');
144 dol_syslog($module->error, LOG_ERR);
145 }
146 } else {
147 setEventMessages($langs->trans("ErrorModuleNotFound"), null, 'errors');
148 dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR);
149 }
150} elseif ($action == 'set') {
151 // Activate a model
152 $ret = addDocumentModel($value, $type, $label, $scandir);
153} elseif ($action == 'del') {
154 $ret = delDocumentModel($value, $type);
155 if ($ret > 0) {
156 if (getDolGlobalString('INVOICE_SUPPLIER_ADDON_PDF') == "$value") {
157 dolibarr_del_const($db, 'INVOICE_SUPPLIER_ADDON_PDF', $conf->entity);
158 }
159 }
160} elseif ($action == 'setdoc') {
161 // Set default model
162 if (dolibarr_set_const($db, "INVOICE_SUPPLIER_ADDON_PDF", $value, 'chaine', 0, '', $conf->entity)) {
163 // The constant that was read before the new set
164 // so we go through a variable to get a consistent display
165 $conf->global->INVOICE_SUPPLIER_ADDON_PDF = $value;
166 }
167
168 // On active le modele
169 $ret = delDocumentModel($value, $type);
170 if ($ret > 0) {
171 $ret = addDocumentModel($value, $type, $label, $scandir);
172 }
173} elseif ($action == 'unsetdoc') {
174 dolibarr_del_const($db, "INVOICE_SUPPLIER_ADDON_PDF", $conf->entity);
175}
176
177if ($action == 'setmod') {
178 // TODO Verify if the chosen numbering module can be activated
179 // by calling method canBeActivated
180
181 dolibarr_set_const($db, "INVOICE_SUPPLIER_ADDON_NUMBER", $value, 'chaine', 0, '', $conf->entity);
182}
183
184if ($action == 'addcat') {
185 $fourn = new Fournisseur($db);
186 $fourn->CreateCategory($user, GETPOST('cat', 'alphanohtml'));
187}
188
189if ($action == 'set_SUPPLIER_INVOICE_FREE_TEXT') {
190 $freetext = GETPOST('SUPPLIER_INVOICE_FREE_TEXT', 'restricthtml'); // No alpha here, we want exact string
191
192 $res = dolibarr_set_const($db, "SUPPLIER_INVOICE_FREE_TEXT", $freetext, 'chaine', 0, '', $conf->entity);
193
194 if (!($res > 0)) {
195 $error++;
196 }
197
198 if (!$error) {
199 setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
200 } else {
201 setEventMessages($langs->trans("Error"), null, 'errors');
202 }
203}
204
205
206/*
207 * View
208 */
209
210$form = new Form($db);
211
212$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
213
214llxHeader('', '', '', '', 0, 0, '', '', '', 'mod-admin page-supplier_invoice');
215
216$linkback = '<a href="'.dolBuildUrl(DOL_URL_ROOT.'/admin/modules.php', ['restore_lastsearch_values' => 1]).'">'.img_picto($langs->trans("BackToModuleList"), 'back', 'class="pictofixedwidth"').'<span class="hideonsmartphone">'.$langs->trans("BackToModuleList").'</span></a>';
217
218print load_fiche_titre($langs->trans("SuppliersSetup"), $linkback, 'title_setup');
219
220print "<br>";
221
222if (getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD')) {
224} else {
226}
227
228print dol_get_fiche_head($head, 'invoice', $langs->trans("Suppliers"), -1, 'company');
229
230
231// Supplier invoice numbering module
232
233$invoice = new FactureFournisseur($db);
234$invoice->initAsSpecimen();
235
236printNumberingModuleList('supplier_invoice', 'mod_facture_fournisseur_', 'INVOICE_SUPPLIER_ADDON_NUMBER', $langs->trans("SuppliersInvoiceNumberingModel"), $invoice);
237
238print '<br>';
239
240
241
242
243/*
244 * Documents models for supplier invoices
245 */
246
247print load_fiche_titre($langs->trans("BillsPDFModules"), '', '');
248
249// Define array def of model
250$def = array();
251
252$sql = "SELECT nom";
253$sql .= " FROM ".MAIN_DB_PREFIX."document_model";
254$sql .= " WHERE type = 'invoice_supplier'";
255$sql .= " AND entity = ".((int) $conf->entity);
256
257$resql = $db->query($sql);
258if ($resql) {
259 $i = 0;
260 $num_rows = $db->num_rows($resql);
261 while ($i < $num_rows) {
262 $array = $db->fetch_array($resql);
263 if (is_array($array)) {
264 array_push($def, $array[0]);
265 }
266 $i++;
267 }
268} else {
269 dol_print_error($db);
270}
271
272print '<div class="div-table-responsive-no-min">';
273print '<table class="noborder centpercent">'."\n";
274print '<tr class="liste_titre">'."\n";
275print '<td width="100">'.$langs->trans("Name").'</td>'."\n";
276print '<td>'.$langs->trans("Description").'</td>'."\n";
277print '<td align="center" width="60">'.$langs->trans("Status").'</td>'."\n";
278print '<td align="center" width="60">'.$langs->trans("Default").'</td>'."\n";
279print '<td align="center" width="40">'.$langs->trans("ShortInfo").'</td>';
280print '<td align="center" width="40">'.$langs->trans("Preview").'</td>';
281print '</tr>'."\n";
282
283clearstatcache();
284
285foreach ($dirmodels as $reldir) {
286 $realpath = $reldir."core/modules/supplier_invoice/doc";
287 $dir = dol_buildpath($realpath);
288
289 if (is_dir($dir)) {
290 $handle = opendir($dir);
291
292
293 if (is_resource($handle)) {
294 while (($file = readdir($handle)) !== false) {
295 if (preg_match('/\.modules\.php$/i', $file) && preg_match('/^(pdf_|doc_)/', $file)) {
296 $name = dol_substr($file, 4, dol_strlen($file) - 16);
297 $classname = dol_substr($file, 0, dol_strlen($file) - 12);
298
299 require_once $dir.'/'.$file;
300 $module = new $classname($db, new FactureFournisseur($db));
301
302 '@phan-var-force ModelePDFSuppliersInvoices $module';
303
304
305 print "<tr class=\"oddeven\">\n";
306 print "<td>";
307 print(empty($module->name) ? $name : $module->name);
308 print "</td>\n";
309 print "<td>\n";
310 require_once $dir.'/'.$file;
311 $module = new $classname($db, $specimenthirdparty);
312 '@phan-var-force ModelePDFSuppliersInvoices $module';
313 if (method_exists($module, 'info')) {
314 print $module->info($langs); // @phan-suppress-current-line PhanUndeclaredMethod
315 } else {
316 print $module->description;
317 }
318
319 print "</td>\n";
320
321 // Active
322 if (in_array($name, $def)) {
323 print '<td class="center">'."\n";
324 //if ($conf->global->INVOICE_SUPPLIER_ADDON_PDF != "$name")
325 //{
326 // Even if choice is the default value, we allow to disable it: For supplier invoice, we accept to have no doc generation at all
327 print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=del&token='.newToken().'&value='.urlencode($name).'&scan_dir='.urlencode($module->scandir).'&label='.urlencode($module->name).'&amp;type=invoice_supplier">';
328 print img_picto($langs->trans("Enabled"), 'switch_on');
329 print '</a>';
330 /*}
331 else
332 {
333 print img_picto($langs->trans("Enabled"),'switch_on');
334 }*/
335 print "</td>";
336 } else {
337 print '<td class="center">'."\n";
338 print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=set&token='.newToken().'&value='.urlencode($name).'&scan_dir='.urlencode($module->scandir).'&label='.urlencode($module->name).'&amp;type=invoice_supplier">'.img_picto($langs->trans("Disabled"), 'switch_off').'</a>';
339 print "</td>";
340 }
341
342 // Default
343 print '<td class="center">';
344 if (getDolGlobalString("INVOICE_SUPPLIER_ADDON_PDF") == "$name") {
345 //print img_picto($langs->trans("Default"),'on');
346 // Even if choice is the default value, we allow to disable it: For supplier invoice, we accept to have no doc generation at all
347 print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=unsetdoc&token='.newToken().'&value='.$name.'&scan_dir='.$module->scandir.'&label='.urlencode($module->name).'&type=invoice_supplier"" alt="'.$langs->trans("Disable").'">'.img_picto($langs->trans("Enabled"), 'on').'</a>';
348 } else {
349 print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=setdoc&token='.newToken().'&value='.$name.'&scan_dir='.$module->scandir.'&label='.urlencode($module->name).'&type=invoice_supplier"" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').'</a>';
350 }
351 print '</td>';
352
353 // Info
354 $htmltooltip = ''.$langs->trans("Name").': '.$module->name;
355 $htmltooltip .= '<br>'.$langs->trans("Type").': '.($module->type ? $module->type : $langs->trans("Unknown"));
356 $htmltooltip .= '<br>'.$langs->trans("Width").'/'.$langs->trans("Height").': '.$module->page_largeur.'/'.$module->page_hauteur;
357 $htmltooltip .= '<br>'.$langs->trans("Path").': '.preg_replace('/^\//', '', $realpath).'/'.$file;
358
359 $htmltooltip .= '<br><br><u>'.$langs->trans("FeaturesSupported").':</u>';
360 $htmltooltip .= '<br>'.$langs->trans("Logo").': '.yn($module->option_logo, 1, 1);
361 $htmltooltip .= '<br>'.$langs->trans("PaymentMode").': '.yn($module->option_modereg, 1, 1);
362 $htmltooltip .= '<br>'.$langs->trans("PaymentConditions").': '.yn($module->option_condreg, 1, 1);
363 print '<td class="center">';
364 print $form->textwithpicto('', $htmltooltip, 1, 'info');
365 print '</td>';
366 print '<td class="center">';
367 print '<a href="'.$_SERVER["PHP_SELF"].'?action=specimen&module='.urlencode($name).'">'.img_object($langs->trans("Preview"), 'pdf').'</a>';
368 print '</td>';
369
370 print "</tr>\n";
371 }
372 }
373
374 closedir($handle);
375 }
376 }
377}
378
379print '</table></div><br>';
380
381/*
382 * Other options
383 */
384
385print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
386print '<input type="hidden" name="token" value="'.newToken().'">';
387print '<input type="hidden" name="action" value="set_SUPPLIER_INVOICE_FREE_TEXT">';
388
389print load_fiche_titre($langs->trans("OtherOptions"), '', '');
390
391print '<div class="div-table-responsive-no-min">';
392print '<table class="noborder centpercent">';
393print '<tr class="liste_titre">';
394print '<td>'.$langs->trans("Parameter").'</td>';
395print '<td></td>';
396print '<td width="80">&nbsp;</td>';
397print "</tr>\n";
398
399$substitutionarray = pdf_getSubstitutionArray($langs, null, null, 2);
400$substitutionarray['__(AnyTranslationKey)__'] = $langs->trans("Translation");
401$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
402foreach ($substitutionarray as $key => $val) {
403 $htmltext .= $key.'<br>';
404}
405$htmltext .= '</i>';
406
407print '<tr class="oddeven"><td colspan="2">';
408print $form->textwithpicto($langs->trans("FreeLegalTextOnInvoices"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext, 1, 'help', '', 0, 2, 'freetexttooltip').'<br>';
409$variablename = 'SUPPLIER_INVOICE_FREE_TEXT';
410if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) {
411 print '<textarea name="'.$variablename.'" class="flat" cols="120">'.getDolGlobalString($variablename).'</textarea>';
412} else {
413 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
414 $doleditor = new DolEditor($variablename, getDolGlobalString($variablename), '', 80, 'dolibarr_notes');
415 print $doleditor->Create();
416}
417print '</td><td class="right">';
418print '<input type="submit" class="button button-edit" value="'.$langs->trans("Modify").'">';
419print "</td></tr>\n";
420
421// Allow external download
422print '<tr class="oddeven">';
423print '<td>'.$langs->trans("AllowExternalDownload").'</td>';
424print '<td class="left" colspan="2">';
425print ajax_constantonoff('SUPPLIER_INVOICE_ALLOW_EXTERNAL_DOWNLOAD', array(), null, 0, 0, 0, 2, 0, 1);
426print '</td></tr>';
427
428// Notifications
429print '<tr class="oddeven">';
430print '<td>'.img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("Notifications").'</td>';
431print '<td colspan="2">';
432print $langs->trans("YouMayFindNotificationsFeaturesIntoModuleNotification");
433print '</td></tr>';
434
435// More PDF options
436/*
437print '<tr class="oddeven">';
438print '<td>'.img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("MoreOptionsRelatedToPDF").'</td>';
439print '<td colspan="2">';
440print img_picto('', 'url', 'class="pictofixedwidth"').'<a href="'.DOL_URL_ROOT.'/admin/pdf_other.php">'.$langs->trans("SeeInPDFSetupPage").'</a>';
441print '</td></tr>';
442*/
443
444print '</table></div><br>';
445
446print '</form>';
447
448print '</table>';
449print '</div>';
450
451// End of page
452llxFooter();
453$db->close();
addDocumentModel($name, $type, $label='', $description='')
Add document model used by doc generator.
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
dolibarr_del_const($db, $name, $entity=1)
Delete a constant.
delDocumentModel($name, $type)
Delete document model used by doc generator.
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage a WYSIWYG editor.
Class to manage suppliers invoices.
Class to manage generation of HTML components Only common components must be here.
Class to manage suppliers.
Class to manage third parties objects (customers, suppliers, prospects...)
if(! $sortfield) if(! $sortorder) $module
Definition list.php:193
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
supplierorder_admin_prepare_head()
Return array head with list of tabs to view object information.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
dol_substr($string, $start, $length=null, $stringencoding='', $trunconbytes=0)
Make a substring.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
Definition html.lib.php:540
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
pdf_getSubstitutionArray($outputlangs, $exclude=null, $object=null, $onlykey=0, $include=null)
Return array of possible substitutions for PDF content (without external module substitutions).
Definition pdf.lib.php:1180
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:140
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.
supplier_invoice_admin_prepare_head()
Prepare array with list of tabs.