dolibarr 20.0.0
html.formlistwebportal.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2023-2024 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2023-2024 Lionel Vessiller <lvessiller@easya.solutions>
4 * Copyright (C) 2023-2024 Patrice Andreani <pandreani@easya.solutions>
5 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
6 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22
29require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
30require_once DOL_DOCUMENT_ROOT . '/core/class/discount.class.php';
31require_once DOL_DOCUMENT_ROOT . '/webportal/class/html.formwebportal.class.php';
32
39{
43 public $action = '';
44
48 public $db;
49
53 public $form;
54
58 public $object;
59
63 public $limit = -1;
64
68 public $page = 1;
69
73 public $sortfield = '';
74
78 public $sortorder = '';
79
83 public $titleKey = '';
84
88 public $titleDescKey = '';
89
93 public $contextpage = '';
94
98 public $search = array();
99
103 public $arrayfields = array();
104
108 public $companyStaticList = array();
109
110
116 public function __construct($db)
117 {
118 $this->db = $db;
119 $this->form = new FormWebPortal($this->db);
120 }
121
128 public function init($elementEn)
129 {
130 // keep compatibility
131 if ($elementEn == 'commande') {
132 $elementEn = 'order';
133 } elseif ($elementEn == 'facture') {
134 $elementEn = 'invoice';
135 }
136
137 // load module libraries
138 dol_include_once('/webportal/class/webportal' . $elementEn . '.class.php');
139
140 // Initialize technical objects
141 $objectclass = 'WebPortal' . ucfirst($elementEn);
142 $object = new $objectclass($this->db);
143
144 // set form list
145 $this->action = GETPOST('action', 'aZ09');
146 $this->object = $object;
147 $this->limit = GETPOSTISSET('limit') ? GETPOSTINT('limit') : -1;
148 $this->sortfield = GETPOST('sortfield', 'aZ09comma');
149 $this->sortorder = GETPOST('sortorder', 'aZ09comma');
150 $this->page = GETPOSTISSET('page') ? GETPOSTINT('page') : 1;
151 $this->titleKey = $objectclass . 'ListTitle';
152
153 // Initialize array of search criteria
154 //$search_all = GETPOST('search_all', 'alphanohtml');
155 $search = array();
156 foreach ($object->fields as $key => $val) {
157 if (GETPOST('search_' . $key, 'alpha') !== '') {
158 $search[$key] = GETPOST('search_' . $key, 'alpha');
159 }
160 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
161 /* Fix: this is not compatible with multilangage date format, replaced with dolibarr method
162 $postDateStart = GETPOST('search_' . $key . '_dtstart', 'alphanohtml');
163 $postDateEnd = GETPOST('search_' . $key . '_dtend', 'alphanohtml');
164 // extract date YYYY-MM-DD for year, month and day
165 $dateStartArr = explode('-', $postDateStart);
166 $dateEndArr = explode('-', $postDateEnd);
167 if (count($dateStartArr) == 3) {
168 $dateStartYear = (int) $dateStartArr[0];
169 $dateStartMonth = (int) $dateStartArr[1];
170 $dateStartDay = (int) $dateStartArr[2];
171 $search[$key . '_dtstart'] = dol_mktime(0, 0, 0, $dateStartMonth, $dateStartDay, $dateStartYear);
172 }
173 if (count($dateEndArr) == 3) {
174 $dateEndYear = (int) $dateEndArr[0];
175 $dateEndMonth = (int) $dateEndArr[1];
176 $dateEndDay = (int) $dateEndArr[2];
177 $search[$key . '_dtend'] = dol_mktime(23, 59, 59, $dateEndMonth, $dateEndDay, $dateEndYear);
178 }
179 */
180 $search[$key . '_dtstartmonth'] = GETPOSTINT('search_' . $key . '_dtstartmonth');
181 $search[$key . '_dtstartday'] = GETPOSTINT('search_' . $key . '_dtstartday');
182 $search[$key . '_dtstartyear'] = GETPOSTINT('search_' . $key . '_dtstartyear');
183 $search[$key . '_dtendmonth'] = GETPOSTINT('search_' . $key . '_dtendmonth');
184 $search[$key . '_dtendday'] = GETPOSTINT('search_' . $key . '_dtendday');
185 $search[$key . '_dtendyear'] = GETPOSTINT('search_' . $key . '_dtendyear');
186 }
187 }
188 $this->search = $search;
189
190 // List of fields to search into when doing a "search in all"
191 //$fieldstosearchall = array();
192
193 // Definition of array of fields for columns
194 $arrayfields = array();
195 foreach ($object->fields as $key => $val) {
196 // If $val['visible']==0, then we never show the field
197 if (!empty($val['visible'])) {
198 $visible = (int) dol_eval($val['visible'], 1);
199 $arrayfields['t.' . $key] = array(
200 'label' => $val['label'],
201 'checked' => (($visible < 0) ? 0 : 1),
202 'enabled' => (abs($visible) != 3 && (bool) dol_eval($val['enabled'], 1)),
203 'position' => $val['position'],
204 'help' => isset($val['help']) ? $val['help'] : ''
205 );
206 }
207 }
208 if ($elementEn == 'invoice') {
209 $arrayfields['remain_to_pay'] = array('type' => 'price', 'label' => 'RemainderToPay', 'checked' => 1, 'enabled' => 1, 'visible' => 1, 'position' => 10000, 'help' => '',);
210 }
211 $arrayfields['download_link'] = array('label' => 'File', 'checked' => 1, 'enabled' => 1, 'visible' => 1, 'position' => 10001, 'help' => '',);
212
213 $object->fields = dol_sort_array($object->fields, 'position');
214 //$arrayfields['anotherfield'] = array('type'=>'integer', 'label'=>'AnotherField', 'checked'=>1, 'enabled'=>1, 'position'=>90, 'csslist'=>'right');
215 $arrayfields = dol_sort_array($arrayfields, 'position');
216
217 $this->arrayfields = $arrayfields;
218 }
219
225 public function doActions()
226 {
227 $object = $this->object;
228 $search = $this->search;
229
230 // Purge search criteria
231 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
232 foreach ($object->fields as $key => $val) {
233 $search[$key] = '';
234 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
235 //$search[$key . '_dtstart'] = '';
236 //$search[$key . '_dtend'] = '';
237 $search[$key . '_dtstartmonth'] = '';
238 $search[$key . '_dtendmonth'] = '';
239 $search[$key . '_dtstartday'] = '';
240 $search[$key . '_dtendday'] = '';
241 $search[$key . '_dtstartyear'] = '';
242 $search[$key . '_dtendyear'] = '';
243 }
244 }
245 $this->search = $search;
246 }
247 }
248
255 public function elementList($context)
256 {
257 global $conf, $hookmanager, $langs;
258
259 $html = '';
260
261 // initialize
262 $action = $this->action;
263 $object = $this->object;
264 $limit = $this->limit;
265 $page = $this->page;
266 $sortfield = $this->sortfield;
267 $sortorder = $this->sortorder;
268 $titleKey = $this->titleKey;
269 $contextpage = $this->contextpage;
270 $search = $this->search;
271 $arrayfields = $this->arrayfields;
272 $elementEn = $object->element;
273 if ($object->element == 'commande') {
274 $elementEn = 'order';
275 } elseif ($object->element == 'facture') {
276 $elementEn = 'invoice';
277 }
278
279 // specific for invoice and remain to pay
280 $discount = null;
281 if ($elementEn == 'invoice') {
282 $discount = new DiscountAbsolute($this->db);
283 }
284
285 // empty value for select
286 $emptyValueKey = ($elementEn == 'order' ? -5 : -1);
287
288 if ($limit < 0) {
289 $limit = $conf->liste_limit;
290 }
291 if ($page <= 0) {
292 $page = 1;
293 }
294 $offset = $limit * ($page - 1);
295 if (!$sortfield) {
296 reset($object->fields); // Reset is required to avoid key() to return null.
297 $sortfield = 't.' . key($object->fields); // Set here default search field. By default 1st field in definition.
298 }
299 if (!$sortorder) {
300 $sortorder = 'DESC';
301 }
302
303 $socid = (int) $context->logged_thirdparty->id;
304
305 // Build and execute select
306 // --------------------------------------------------------------------
307 $sql = "SELECT ";
308 $sql .= $object->getFieldList('t');
309 $sql .= ", t.entity as element_entity";
310 // Add fields from hooks
311 $parameters = array();
312 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
313 $sql .= $hookmanager->resPrint;
314 $sql = preg_replace('/,\s*$/', '', $sql);
315
316 $sqlfields = $sql; // $sql fields to remove for count total
317
318 $sql .= " FROM " . $this->db->prefix() . $object->table_element . " as t";
319 // Add table from hooks
320 $parameters = array();
321 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
322 $sql .= $hookmanager->resPrint;
323 if ($object->ismultientitymanaged == 1) {
324 $sql .= " WHERE t.entity IN (" . getEntity($object->element, (GETPOSTINT('search_current_entity') ? 0 : 1)) . ")";
325 } else {
326 $sql .= " WHERE 1 = 1";
327 }
328 // filter on logged third-party
329 $sql .= " AND t.fk_soc = " . ((int) $socid);
330 // discard record with status draft
331 $sql .= " AND t.fk_statut <> 0";
332
333 foreach ($search as $key => $val) {
334 if (array_key_exists($key, $object->fields)) {
335 if (($key == 'status' || $key == 'fk_statut') && $search[$key] == $emptyValueKey) {
336 continue;
337 }
338 $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0);
339 if ((strpos($object->fields[$key]['type'], 'integer:') === 0) || (strpos($object->fields[$key]['type'], 'sellist:') === 0) || !empty($object->fields[$key]['arrayofkeyval'])) {
340 if ($search[$key] == "$emptyValueKey" || ($search[$key] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) {
341 $search[$key] = '';
342 }
343 $mode_search = 2;
344 }
345 if ($search[$key] != '') {
346 $sql .= natural_search("t." . $this->db->escape($key), $search[$key], (($key == 'status' || $key == 'fk_statut') ? ($search[$key] < 0 ? 1 : 2) : $mode_search));
347 }
348 } else {
349 if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
350 $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
351 if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
352 if (preg_match('/_dtstart$/', $key)) {
353 $sql .= " AND t." . $this->db->escape($columnName) . " >= '" . $this->db->idate($search[$key]) . "'";
354 }
355 if (preg_match('/_dtend$/', $key)) {
356 $sql .= " AND t." . $this->db->escape($columnName) . " <= '" . $this->db->idate($search[$key]) . "'";
357 }
358 }
359 }
360 }
361 }
362 //if ($search_all) {
363 // $sql .= natural_search(array_keys($fieldstosearchall), $search_all);
364 //}
365 // Add where from hooks
366 $parameters = array();
367 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
368 $sql .= $hookmanager->resPrint;
369
370 // Count total nb of records
371 $nbtotalofrecords = 0;
372 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
373 /* The fast and low memory method to get and count full list converts the sql into a sql count */
374 $sqlforcount = preg_replace('/^' . preg_quote($sqlfields, '/') . '/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
375 $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
376 $resql = $this->db->query($sqlforcount);
377 if ($resql) {
378 $objforcount = $this->db->fetch_object($resql);
379 $nbtotalofrecords = (int) $objforcount->nbtotalofrecords;
380 } else {
381 dol_print_error($this->db);
382 }
383
384 if ($offset > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 1
385 $page = 1;
386 $offset = 0;
387 }
388
389 $this->db->free($resql);
390 }
391
392 // Complete request and execute it with limit
393 $sql .= $this->db->order($sortfield, $sortorder);
394 if ($limit) {
395 $sql .= $this->db->plimit($limit, $offset);
396 }
397
398 $resql = $this->db->query($sql);
399 if (!$resql) {
400 dol_print_error($this->db);
401 return '';
402 }
403
404 $num = $this->db->num_rows($resql);
405 if ($limit > 0) {
406 $nbpages = ceil($nbtotalofrecords / $limit);
407 }
408 if ($nbpages <= 0) {
409 $nbpages = 1;
410 }
411
412 // make array[sort field => sort order] for this list
413 $sortList = array();
414 $sortFieldList = explode(",", $sortfield);
415 $sortOrderList = explode(",", $sortorder);
416 $sortFieldIndex = 0;
417 if (!empty($sortFieldList)) {
418 foreach ($sortFieldList as $sortField) {
419 if (isset($sortOrderList[$sortFieldIndex])) {
420 $sortList[$sortField] = $sortOrderList[$sortFieldIndex];
421 }
422 $sortFieldIndex++;
423 }
424 }
425
426 $param = '';
427 $param .= '&contextpage=' . urlencode($contextpage);
428 $param .= '&limit=' . $limit;
429 foreach ($search as $key => $val) {
430 if (is_array($search[$key])) {
431 foreach ($search[$key] as $skey) {
432 if ($skey != '') {
433 $param .= '&search_' . $key . '[]=' . urlencode($skey);
434 }
435 }
436 } elseif (preg_match('/(_dtstart|_dtend)$/', $key) && !empty($val)) {
437 $param .= '&search_' . $key . 'month=' . (GETPOSTINT('search_' . $key . 'month'));
438 $param .= '&search_' . $key . 'day=' . (GETPOSTINT('search_' . $key . 'day'));
439 $param .= '&search_' . $key . 'year=' . (GETPOSTINT('search_' . $key . 'year'));
440 } elseif ($search[$key] != '') {
441 $param .= '&search_' . $key . '=' . urlencode($search[$key]);
442 }
443 }
444 // Add $param from hooks
445 $parameters = array();
446 $reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
447 $param .= $hookmanager->resPrint;
448
449 $url_file = $context->getControllerUrl($context->controller);
450 $html .= '<form method="POST" id="searchFormList" action="' . $url_file . '">' . "\n";
451 $html .= $context->getFormToken();
452 $html .= '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
453 $html .= '<input type="hidden" name="action" value="list">';
454 $html .= '<input type="hidden" name="sortfield" value="' . $sortfield . '">';
455 $html .= '<input type="hidden" name="sortorder" value="' . $sortorder . '">';
456 $html .= '<input type="hidden" name="page" value="' . $page . '">';
457 $html .= '<input type="hidden" name="contextpage" value="' . $contextpage . '">';
458
459 // pagination
460 $pagination_param = $param . '&sortfield=' . $sortfield . '&sortorder=' . $sortorder;
461 $html .= '<nav id="webportal-' . $elementEn . '-pagination">';
462 $html .= '<ul>';
463 $html .= '<li><strong>' . $langs->trans($titleKey) . '</strong> (' . $nbtotalofrecords . ')</li>';
464 $html .= '</ul>';
465
466 /* Generate pagination list */
467 $html .= static::generatePageListNav($url_file . $pagination_param, $nbpages, $page);
468
469 $html .= '</nav>';
470
471 // table with search filters and column titles
472 $html .= '<table id="webportal-' . $elementEn . '-list" responsive="scroll" role="grid">';
473 // title and desc for table
474 //if ($titleKey != '') {
475 // $html .= '<caption id="table-collapse-responsive">';
476 // $html .= $langs->trans($titleKey) . '<br/>';
477 // if ($titleDescKey != '') {
478 // $html .= '<small>' . $langs->trans($titleDescKey) . '</small>';
479 // }
480 // $html .= '</caption>';
481 //}
482
483 $html .= '<thead>';
484
485 // Fields title search
486 // --------------------------------------------------------------------
487 $html .= '<tr role="search-row">';
488 // Action column
489 // if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
490 $html .= '<td data-col="row-checkbox" >';
491 $html .= ' <button class="btn-filter-icon btn-search-filters-icon" type="submit" name="button_search_x" value="x" aria-label="'.dol_escape_htmltag($langs->trans('Search')).'" ></button>';
492 $html .= ' <button class="btn-filter-icon btn-remove-search-filters-icon" type="submit" name="button_removefilter_x" value="x" aria-label="'.dol_escape_htmltag($langs->trans('RemoveSearchFilters')).'"></button>';
493 $html .= '</td>';
494 // }
495 foreach ($object->fields as $key => $val) {
496 if (!empty($arrayfields['t.' . $key]['checked'])) {
497 $html .= '<td data-label="' . $arrayfields['t.' . $key]['label'] . '" data-col="'.dol_escape_htmltag($key).'" >';
498 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
499 $html .= $this->form->selectarray('search_' . $key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', '');
500 } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
501 $postDateStart = dol_mktime(0, 0, 0, $search[$key . '_dtstartmonth'], $search[$key . '_dtstartday'], $search[$key . '_dtstartyear']);
502 $postDateEnd = dol_mktime(0, 0, 0, $search[$key . '_dtendmonth'], $search[$key . '_dtendday'], $search[$key . '_dtendyear']);
503
504 $html .= '<div class="grid width150">';
505 $html .= $this->form->inputDate('search_' . $key . '_dtstart', $postDateStart ? $postDateStart : '', $langs->trans('From'));
506 $html .= '</div>';
507 $html .= '<div class="grid width150">';
508 $html .= $this->form->inputDate('search_' . $key . '_dtend', $postDateEnd ? $postDateEnd : '', $langs->trans('to'));
509 $html .= '</div>';
510 } else {
511 $html .= '<input type="text" name="search_' . $key . '" value="' . dol_escape_htmltag(isset($search[$key]) ? $search[$key] : '') . '">';
512 }
513 $html .= '</td>';
514 }
515 }
516 // Fields from hook
517 $parameters = array('arrayfields' => $arrayfields);
518 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
519 $html .= $hookmanager->resPrint;
520 // Remain to pay
521 if (!empty($arrayfields['remain_to_pay']['checked'])) {
522 $html .= '<td data-label="' . $arrayfields['remain_to_pay']['label'] . '">';
523 $html .= '</td>';
524 }
525 // Download link
526 if (!empty($arrayfields['download_link']['checked'])) {
527 $html .= '<td data-label="' . $arrayfields['download_link']['label'] . '">';
528 $html .= '</td>';
529 }
530 $html .= '</tr>';
531
532
533 $totalarray = array();
534 $totalarray['nbfield'] = 0;
535
536 // Fields title label
537 // --------------------------------------------------------------------
538 $html .= '<tr>';
539 // Action column
540 // if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
541 $html .= '<th data-col="row-checkbox" ></th>';
542 $totalarray['nbfield']++;
543 // }
544 foreach ($object->fields as $key => $val) {
545 $tableKey = 't.' . $key;
546 if (!empty($arrayfields[$tableKey]['checked'])) {
547 $tableOrder = '';
548 if (array_key_exists($tableKey, $sortList)) {
549 $tableOrder = strtolower($sortList[$tableKey]);
550 }
551 $url_param = $url_file . '&sortfield=' . $tableKey . '&sortorder=' . ($tableOrder == 'desc' ? 'asc' : 'desc') . $param;
552 $html .= '<th data-col="'.dol_escape_htmltag($key).'" scope="col"' . ($tableOrder != '' ? ' table-order="' . $tableOrder . '"' : '') . '>';
553 $html .= '<a href="' . $url_param . '">';
554 $html .= $langs->trans($arrayfields['t.' . $key]['label']);
555 $html .= '</a>';
556 $html .= '</th>';
557 $totalarray['nbfield']++;
558 }
559 }
560 // Remain to pay
561 if (!empty($arrayfields['remain_to_pay']['checked'])) {
562 $html .= '<th scope="col">';
563 $html .= $langs->trans($arrayfields['remain_to_pay']['label']);
564 $html .= '</th>';
565 $totalarray['nbfield']++;
566 }
567 // Download link
568 if (!empty($arrayfields['download_link']['checked'])) {
569 $html .= '<th scope="col">';
570 $html .= $langs->trans($arrayfields['download_link']['label']);
571 $html .= '</th>';
572 $totalarray['nbfield']++;
573 }
574
575 // Hook fields
576 $parameters = array('arrayfields' => $arrayfields, 'sortfield' => $sortfield, 'sortorder' => $sortorder, 'totalarray' => &$totalarray);
577 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
578 $html .= $hookmanager->resPrint;
579 $html .= '</tr>';
580
581 $html .= '</thead>';
582
583 $html .= '<tbody>';
584
585 // Store company
586 $idCompany = (int) $socid;
587 if (!isset($this->companyStaticList[$socid])) {
588 $companyStatic = new Societe($this->db);
589 $companyStatic->fetch($idCompany);
590 $this->companyStaticList[$idCompany] = $companyStatic;
591 }
592 $companyStatic = $this->companyStaticList[$socid];
593
594 // Loop on record
595 // --------------------------------------------------------------------
596 $i = 0;
597 $totalarray = [
598 'nbfield' => 0,
599 'totalizable' => [],
600 ];
601 $imaxinloop = ($limit ? min($num, $limit) : $num);
602 while ($i < $imaxinloop) {
603 $obj = $this->db->fetch_object($resql);
604 if (empty($obj)) {
605 break; // Should not happen
606 }
607
608 // Store properties in $object
609 $object->setVarsFromFetchObj($obj);
610
611 // specific to get invoice status (depends on payment)
612 $payment = -1;
613 if ($elementEn == 'invoice') {
614 // paid sum
615 $payment = $object->getSommePaiement();
616 $totalcreditnotes = $object->getSumCreditNotesUsed();
617 $totaldeposits = $object->getSumDepositsUsed();
618
619 // remain to pay
620 $totalpay = $payment + $totalcreditnotes + $totaldeposits;
621 $remaintopay = price2num($object->total_ttc - $totalpay);
622 if ($object->status == Facture::STATUS_CLOSED && $object->close_code == 'discount_vat') { // If invoice closed with discount for anticipated payment
623 $remaintopay = 0;
624 }
625 if ($object->type == Facture::TYPE_CREDIT_NOTE && $obj->paye == 1 && $discount) {
626 $remaincreditnote = $discount->getAvailableDiscounts($companyStatic, '', 'rc.fk_facture_source=' . $object->id);
627 $remaintopay = -$remaincreditnote;
628 }
629 }
630
631 // Show line of result
632 $html .= '<tr data-rowid="' . $object->id . '">';
633 // if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
634 $html .= '<td class="nowraponall">';
635 $html .= '</td>';
636 if (!$i) {
637 $totalarray['nbfield']++;
638 }
639 // }
640 foreach ($object->fields as $key => $val) {
641 if (!empty($arrayfields['t.' . $key]['checked'])) {
642 $html .= '<td class="nowraponall" data-label="' . $arrayfields['t.' . $key]['label'] . '">';
643 if ($key == 'status' || $key == 'fk_statut') {
644 if ($elementEn == 'invoice') {
645 // specific to get invoice status (depends on payment)
646 $html .= $object->getLibStatut(5, $payment);
647 } else {
648 $html .= $object->getLibStatut(5);
649 }
650 } elseif ($key == 'rowid') {
651 $html .= $this->form->showOutputFieldForObject($object, $val, $key, $object->id, '');
652 } else {
653 $html .= $this->form->showOutputFieldForObject($object, $val, $key, $object->$key, '');
654 }
655 $html .= '</td>';
656
657
658 if (!$i) {
659 $totalarray['nbfield']++;
660 }
661 if (!empty($val['isameasure']) && $val['isameasure'] == 1) {
662 if (!$i) {
663 $totalarray['pos'][$totalarray['nbfield']] = 't.' . $key;
664 }
665 if (!isset($totalarray['val'])) {
666 $totalarray['val'] = array();
667 }
668 if (!isset($totalarray['val']['t.' . $key])) {
669 $totalarray['val']['t.' . $key] = 0;
670 }
671 $totalarray['val']['t.' . $key] += $object->$key;
672 }
673 }
674 }
675 // Remain to pay
676 if (!empty($arrayfields['remain_to_pay']['checked'])) {
677 $html .= '<td class="nowraponall" data-label="' . $arrayfields['remain_to_pay']['label'] . '">';
678 $html .= $this->form->showOutputFieldForObject($object, $arrayfields['remain_to_pay'], 'remain_to_pay', $remaintopay, '');
679 //$html .= price($remaintopay);
680 $html .= '</td>';
681 if (!$i) {
682 $totalarray['nbfield']++;
683 }
684 }
685 // Download link
686 if (!empty($arrayfields['download_link']['checked'])) {
687 $element = $object->element;
688 $html .= '<td class="nowraponall" data-label="' . $arrayfields['download_link']['label'] . '">';
689 $filename = dol_sanitizeFileName($obj->ref);
690 $filedir = $conf->{$element}->multidir_output[$obj->element_entity] . '/' . dol_sanitizeFileName($obj->ref);
691 $html .= $this->form->getDocumentsLink($element, $filename, $filedir);
692 $html .= '</td>';
693 if (!$i) {
694 $totalarray['nbfield']++;
695 }
696 }
697 // Fields from hook
698 $parameters = array('arrayfields' => $arrayfields, 'object' => $object, 'obj' => $obj, 'i' => $i, 'totalarray' => &$totalarray);
699 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
700 $html .= $hookmanager->resPrint;
701
702
703 $html .= '</tr>';
704
705 $i++;
706 }
707
708 // Move fields of totalizable into the common array pos and val
709 if (!empty($totalarray['totalizable']) && is_array($totalarray['totalizable'])) {
710 foreach ($totalarray['totalizable'] as $keytotalizable => $valtotalizable) {
711 $totalarray['pos'][$valtotalizable['pos']] = $keytotalizable;
712 $totalarray['val'][$keytotalizable] = isset($valtotalizable['total']) ? $valtotalizable['total'] : 0;
713 }
714 }
715 // Show total line
716 if (isset($totalarray['pos'])) {
717 $html .= '<tr>';
718 $i = 0;
719 while ($i < $totalarray['nbfield']) {
720 $i++;
721 if (!empty($totalarray['pos'][$i])) {
722 $html .= '<td class="nowraponall essai">';
723 $html .= price(!empty($totalarray['val'][$totalarray['pos'][$i]]) ? $totalarray['val'][$totalarray['pos'][$i]] : 0);
724 $html .= '</td>';
725 } else {
726 if ($i == 1) {
727 $html .= '<td>' . $langs->trans("Total") . '</td>';
728 } else {
729 $html .= '<td></td>';
730 }
731 }
732 }
733 $html .= '</tr>';
734 }
735
736 // If no record found
737 if ($num == 0) {
738 $colspan = 1;
739 foreach ($arrayfields as $key => $val) {
740 if (!empty($val['checked'])) {
741 $colspan++;
742 }
743 }
744 $html .= '<tr><td colspan="' . $colspan . '"><span class="opacitymedium">' . $langs->trans("NoRecordFound") . '</span></td></tr>';
745 }
746
747 $html .= '</tbody>';
748
749 $this->db->free($resql);
750
751 $parameters = array('arrayfields' => $arrayfields, 'sql' => $sql);
752 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
753 $html .= $hookmanager->resPrint;
754
755 $html .= '</table>';
756
757 $html .= '</form>';
758
759 return $html;
760 }
761
770 public static function generatePageListNav(string $url, int $nbPages, int $currentPage)
771 {
772 global $langs;
773
774 // Return nothing (no navigation bar), if there is only 1 page.
775 if ($nbPages <= 1) {
776 return '';
777 }
778
779 $pSep = strpos($url, '?') === false ? '?' : '&amp;';
780
781 $html = '<ul class="pages-nav-list">';
782
783 if ($currentPage > 1) {
784 $html .= '<li><a class="pages-nav-list__icon --prev" aria-label="' . dol_escape_htmltag($langs->trans('AriaPrevPage')) . '" href="' . $url . $pSep . 'page=' . ($currentPage - 1) . '" ' . ($currentPage <= 1 ? ' disabled' : '') . '></a></li>';
785 }
786
787 $maxPaginItem = min($nbPages, 5);
788 $minPageNum = max(1, $currentPage - 3);
789 $maxPageNum = min($nbPages, $currentPage + 3);
790
791 if ($minPageNum > 1) {
792 $html .= '<li><a class="pages-nav-list__link ' . ($currentPage == 1 ? '--active' : '') . '" aria-label="' . dol_escape_htmltag($langs->trans('AriaPageX', 1)) . '" href="' . $url . $pSep . 'page=1" >1</a></li>';
793 $html .= '<li>&hellip;</li>';
794 }
795
796 for ($p = $minPageNum; $p <= $maxPageNum; $p++) {
797 $html .= '<li><a class="pages-nav-list__link ' . ($currentPage === $p ? '--active' : '') . '" aria-label="' . dol_escape_htmltag($langs->trans('AriaPageX', $p)) . '" href="' . $url . $pSep . 'page=' . $p . '">' . $p . '</a></li>';
798 }
799
800 if ($maxPaginItem < $nbPages) {
801 $html .= '<li>&hellip;</li>';
802 $html .= '<li><a class="pages-nav-list__link ' . ($currentPage == $nbPages ? '--active' : '') . '" aria-label="' . dol_escape_htmltag($langs->trans('AriaPageX', $nbPages)) . '" href="' . $url . $pSep . 'page=' . $nbPages . '">' . $nbPages . '</a></li>';
803 }
804
805 if ($currentPage < $nbPages) {
806 $html .= '<li><a class="pages-nav-list__icon --next" aria-label="' . dol_escape_htmltag($langs->trans('AriaNextPage')) . '" href="' . $url . $pSep . 'page=' . ($currentPage + 1) . '" ' . ($currentPage >= $nbPages ? ' disabled' : '') . '></a></li>';
807 }
808
809 $html .= '</ul>';
810
811 return $html;
812 }
813}
Class to manage absolute discounts.
const TYPE_CREDIT_NOTE
Credit note invoice.
const STATUS_CLOSED
Classified paid.
Class to manage generation of HTML components Only common components for WebPortal must be here.
static generatePageListNav(string $url, int $nbPages, int $currentPage)
Generate with pagination navigaion.
elementList($context)
List for an element in the page context.
Class to manage generation of HTML components Only common components for WebPortal must be here.
Class to manage third parties objects (customers, suppliers, prospects...)
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
natural_search($fields, $value, $mode=0, $nofirstand=0)
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by the value of a given key, which produces ascending (default) or descending out...
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...