dolibarr 21.0.0-alpha
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 a 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 $postDateStart = GETPOST('search_' . $key . '_dtstart', 'alphanohtml');
162 $postDateEnd = GETPOST('search_' . $key . '_dtend', 'alphanohtml');
163 // extract date YYYY-MM-DD for year, month and day
164 $dateStartArr = explode('-', $postDateStart);
165 $dateEndArr = explode('-', $postDateEnd);
166 if (count($dateStartArr) == 3) {
167 $dateStartYear = (int) $dateStartArr[0];
168 $dateStartMonth = (int) $dateStartArr[1];
169 $dateStartDay = (int) $dateStartArr[2];
170 $search[$key . '_dtstart'] = dol_mktime(0, 0, 0, $dateStartMonth, $dateStartDay, $dateStartYear);
171 }
172 if (count($dateEndArr) == 3) {
173 $dateEndYear = (int) $dateEndArr[0];
174 $dateEndMonth = (int) $dateEndArr[1];
175 $dateEndDay = (int) $dateEndArr[2];
176 $search[$key . '_dtend'] = dol_mktime(23, 59, 59, $dateEndMonth, $dateEndDay, $dateEndYear);
177 }
178 }
179 }
180 $this->search = $search;
181
182 // List of fields to search into when doing a "search in all"
183 //$fieldstosearchall = array();
184
185 // Definition of array of fields for columns
186 $arrayfields = array();
187 foreach ($object->fields as $key => $val) {
188 // If $val['visible']==0, then we never show the field
189 if (!empty($val['visible'])) {
190 $visible = (int) dol_eval($val['visible'], 1);
191 $arrayfields['t.' . $key] = array(
192 'label' => $val['label'],
193 'checked' => (($visible < 0) ? 0 : 1),
194 'enabled' => (abs($visible) != 3 && (bool) dol_eval($val['enabled'], 1)),
195 'position' => $val['position'],
196 'help' => isset($val['help']) ? $val['help'] : ''
197 );
198 }
199 }
200 if ($elementEn == 'invoice') {
201 $arrayfields['remain_to_pay'] = array('type' => 'price', 'label' => 'RemainderToPay', 'checked' => 1, 'enabled' => 1, 'visible' => 1, 'position' => 10000, 'help' => '',);
202 }
203 $arrayfields['download_link'] = array('label' => 'File', 'checked' => 1, 'enabled' => 1, 'visible' => 1, 'position' => 10001, 'help' => '',);
204 if ($elementEn == "propal" && getDolGlobalString("PROPOSAL_ALLOW_ONLINESIGN") != 0) {
205 $arrayfields['signature_link'] = array('label' => 'Signature', 'checked' => 1, 'enabled' => 1, 'visible' => 1, 'position' => 10002, 'help' => '',);
206 }
207
208 $object->fields = dol_sort_array($object->fields, 'position');
209 //$arrayfields['anotherfield'] = array('type'=>'integer', 'label'=>'AnotherField', 'checked'=>1, 'enabled'=>1, 'position'=>90, 'csslist'=>'right');
210 $arrayfields = dol_sort_array($arrayfields, 'position');
211
212 $this->arrayfields = $arrayfields;
213 }
214
220 public function doActions()
221 {
222 $object = $this->object;
223 $search = $this->search;
224
225 // Purge search criteria
226 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
227 foreach ($object->fields as $key => $val) {
228 $search[$key] = '';
229 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
230 $search[$key . '_dtstart'] = '';
231 $search[$key . '_dtend'] = '';
232 }
233 }
234 $this->search = $search;
235 }
236 }
237
244 public function elementList($context)
245 {
246 global $conf, $hookmanager, $langs;
247
248 $html = '';
249
250 // initialize
251 $action = $this->action;
252 $object = $this->object;
253 $limit = $this->limit;
254 $page = $this->page;
255 $sortfield = $this->sortfield;
256 $sortorder = $this->sortorder;
257 $titleKey = $this->titleKey;
258 $contextpage = $this->contextpage;
259 $search = $this->search;
260 $arrayfields = $this->arrayfields;
261 $elementEn = $object->element;
262 if ($object->element == 'commande') {
263 $elementEn = 'order';
264 } elseif ($object->element == 'facture') {
265 $elementEn = 'invoice';
266 }
267
268 // specific for invoice and remain to pay
269 $discount = null;
270 if ($elementEn == 'invoice') {
271 $discount = new DiscountAbsolute($this->db);
272 }
273
274 // empty value for select
275 $emptyValueKey = ($elementEn == 'order' ? -5 : -1);
276
277 if ($limit < 0) {
278 $limit = $conf->liste_limit;
279 }
280 if ($page <= 0) {
281 $page = 1;
282 }
283 $offset = $limit * ($page - 1);
284 if (!$sortfield) {
285 reset($object->fields); // Reset is required to avoid key() to return null.
286 $sortfield = 't.' . key($object->fields); // Set here default search field. By default 1st field in definition.
287 }
288 if (!$sortorder) {
289 $sortorder = 'DESC';
290 }
291
292 $socid = (int) $context->logged_thirdparty->id;
293
294 // Build and execute select
295 // --------------------------------------------------------------------
296 $sql = "SELECT ";
297 $sql .= $object->getFieldList('t');
298 $sql .= ", t.entity as element_entity";
299 // Add fields from hooks
300 $parameters = array();
301 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
302 $sql .= $hookmanager->resPrint;
303 $sql = preg_replace('/,\s*$/', '', $sql);
304
305 $sqlfields = $sql; // $sql fields to remove for count total
306
307 $sql .= " FROM " . $this->db->prefix() . $object->table_element . " as t";
308 // Add table from hooks
309 $parameters = array();
310 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
311 $sql .= $hookmanager->resPrint;
312 if ($object->ismultientitymanaged == 1) {
313 $sql .= " WHERE t.entity IN (" . getEntity($object->element, (GETPOSTINT('search_current_entity') ? 0 : 1)) . ")";
314 } else {
315 $sql .= " WHERE 1 = 1";
316 }
317 // filter on logged third-party
318 $sql .= " AND t.fk_soc = " . ((int) $socid);
319 // discard record with status draft
320 $sql .= " AND t.fk_statut <> 0";
321
322 foreach ($search as $key => $val) {
323 if (array_key_exists($key, $object->fields)) {
324 if (($key == 'status' || $key == 'fk_statut') && $search[$key] == $emptyValueKey) {
325 continue;
326 }
327 $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0);
328 if ((strpos($object->fields[$key]['type'], 'integer:') === 0) || (strpos($object->fields[$key]['type'], 'sellist:') === 0) || !empty($object->fields[$key]['arrayofkeyval'])) {
329 if ($search[$key] == "$emptyValueKey" || ($search[$key] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) {
330 $search[$key] = '';
331 }
332 $mode_search = 2;
333 }
334 if ($search[$key] != '') {
335 $sql .= natural_search("t." . $this->db->escape($key), $search[$key], (($key == 'status' || $key == 'fk_statut') ? ($search[$key] < 0 ? 1 : 2) : $mode_search));
336 }
337 } else {
338 if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
339 $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
340 if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
341 if (preg_match('/_dtstart$/', $key)) {
342 $sql .= " AND t." . $this->db->escape($columnName) . " >= '" . $this->db->idate($search[$key]) . "'";
343 }
344 if (preg_match('/_dtend$/', $key)) {
345 $sql .= " AND t." . $this->db->escape($columnName) . " <= '" . $this->db->idate($search[$key]) . "'";
346 }
347 }
348 }
349 }
350 }
351 //if ($search_all) {
352 // $sql .= natural_search(array_keys($fieldstosearchall), $search_all);
353 //}
354 // Add where from hooks
355 $parameters = array();
356 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
357 $sql .= $hookmanager->resPrint;
358
359 // Count total nb of records
360 $nbtotalofrecords = 0;
361 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
362 /* The fast and low memory method to get and count full list converts the sql into a sql count */
363 $sqlforcount = preg_replace('/^' . preg_quote($sqlfields, '/') . '/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
364 $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
365 $resql = $this->db->query($sqlforcount);
366 if ($resql) {
367 $objforcount = $this->db->fetch_object($resql);
368 $nbtotalofrecords = (int) $objforcount->nbtotalofrecords;
369 } else {
370 dol_print_error($this->db);
371 }
372
373 if ($offset > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 1
374 $page = 1;
375 $offset = 0;
376 }
377
378 $this->db->free($resql);
379 }
380
381 // Complete request and execute it with limit
382 $sql .= $this->db->order($sortfield, $sortorder);
383 if ($limit) {
384 $sql .= $this->db->plimit($limit, $offset);
385 }
386
387 $resql = $this->db->query($sql);
388 if (!$resql) {
389 dol_print_error($this->db);
390 return '';
391 }
392
393 $num = $this->db->num_rows($resql);
394 if ($limit > 0) {
395 $nbpages = ceil($nbtotalofrecords / $limit);
396 }
397 if ($nbpages <= 0) {
398 $nbpages = 1;
399 }
400
401 // make array[sort field => sort order] for this list
402 $sortList = array();
403 $sortFieldList = explode(",", $sortfield);
404 $sortOrderList = explode(",", $sortorder);
405 $sortFieldIndex = 0;
406 if (!empty($sortFieldList)) {
407 foreach ($sortFieldList as $sortField) {
408 if (isset($sortOrderList[$sortFieldIndex])) {
409 $sortList[$sortField] = $sortOrderList[$sortFieldIndex];
410 }
411 $sortFieldIndex++;
412 }
413 }
414
415 $param = '';
416 $param .= '&contextpage=' . urlencode($contextpage);
417 $param .= '&limit=' . $limit;
418 foreach ($search as $key => $val) {
419 if (is_array($search[$key])) {
420 foreach ($search[$key] as $skey) {
421 if ($skey != '') {
422 $param .= '&search_' . $key . '[]=' . urlencode($skey);
423 }
424 }
425 } elseif (preg_match('/(_dtstart|_dtend)$/', $key) && !empty($val)) {
426 $param .= '&search_' . $key . 'month=' . (GETPOSTINT('search_' . $key . 'month'));
427 $param .= '&search_' . $key . 'day=' . (GETPOSTINT('search_' . $key . 'day'));
428 $param .= '&search_' . $key . 'year=' . (GETPOSTINT('search_' . $key . 'year'));
429 } elseif ($search[$key] != '') {
430 $param .= '&search_' . $key . '=' . urlencode($search[$key]);
431 }
432 }
433 // Add $param from hooks
434 $parameters = array();
435 $reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
436 $param .= $hookmanager->resPrint;
437
438 $url_file = $context->getControllerUrl($context->controller);
439 $html .= '<form method="POST" id="searchFormList" action="' . $url_file . '">' . "\n";
440 $html .= $context->getFormToken();
441 $html .= '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
442 $html .= '<input type="hidden" name="action" value="list">';
443 $html .= '<input type="hidden" name="sortfield" value="' . $sortfield . '">';
444 $html .= '<input type="hidden" name="sortorder" value="' . $sortorder . '">';
445 $html .= '<input type="hidden" name="page" value="' . $page . '">';
446 $html .= '<input type="hidden" name="contextpage" value="' . $contextpage . '">';
447
448 // pagination
449 $pagination_param = $param . '&sortfield=' . $sortfield . '&sortorder=' . $sortorder;
450 $html .= '<nav id="webportal-' . $elementEn . '-pagination">';
451 $html .= '<ul>';
452 $html .= '<li><strong>' . $langs->trans($titleKey) . '</strong> (' . $nbtotalofrecords . ')</li>';
453 $html .= '</ul>';
454
455 /* Generate pagination list */
456 $html .= static::generatePageListNav($url_file . $pagination_param, $nbpages, $page);
457
458 $html .= '</nav>';
459
460 // table with search filters and column titles
461 $html .= '<table id="webportal-' . $elementEn . '-list" responsive="scroll" role="grid">';
462 // title and desc for table
463 //if ($titleKey != '') {
464 // $html .= '<caption id="table-collapse-responsive">';
465 // $html .= $langs->trans($titleKey) . '<br/>';
466 // if ($titleDescKey != '') {
467 // $html .= '<small>' . $langs->trans($titleDescKey) . '</small>';
468 // }
469 // $html .= '</caption>';
470 //}
471
472 $html .= '<thead>';
473
474 // Fields title search
475 // --------------------------------------------------------------------
476 $html .= '<tr role="search-row">';
477 // Action column
478 // if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
479 $html .= '<td data-col="row-checkbox" >';
480 $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>';
481 $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>';
482 $html .= '</td>';
483 // }
484 foreach ($object->fields as $key => $val) {
485 if (!empty($arrayfields['t.' . $key]['checked'])) {
486 $html .= '<td data-label="' . $arrayfields['t.' . $key]['label'] . '" data-col="'.dol_escape_htmltag($key).'" >';
487 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
488 $html .= $this->form->selectarray('search_' . $key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', '');
489 } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
490 $postDateStart = GETPOST('search_' . $key . '_dtstart', 'alphanohtml');
491 $postDateEnd = GETPOST('search_' . $key . '_dtend', 'alphanohtml');
492
493 $html .= '<div class="grid">';
494 $html .= $this->form->inputDate('search_' . $key . '_dtstart', $postDateStart ? $postDateStart : '', $langs->trans('From'));
495 $html .= '</div>';
496 $html .= '<div class="grid">';
497 $html .= $this->form->inputDate('search_' . $key . '_dtend', $postDateEnd ? $postDateEnd : '', $langs->trans('to'));
498 $html .= '</div>';
499 } else {
500 $html .= '<input type="text" name="search_' . $key . '" value="' . dol_escape_htmltag(isset($search[$key]) ? $search[$key] : '') . '">';
501 }
502 $html .= '</td>';
503 }
504 }
505 // Fields from hook
506 $parameters = array('arrayfields' => $arrayfields);
507 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
508 $html .= $hookmanager->resPrint;
509 // Remain to pay
510 if (!empty($arrayfields['remain_to_pay']['checked'])) {
511 $html .= '<td data-label="' . $arrayfields['remain_to_pay']['label'] . '">';
512 $html .= '</td>';
513 }
514 // Download link
515 if (!empty($arrayfields['download_link']['checked'])) {
516 $html .= '<td data-label="' . $arrayfields['download_link']['label'] . '">';
517 $html .= '</td>';
518 }
519 $html .= '</tr>';
520 // Signature link
521 if ($elementEn == "propal" && getDolGlobalString("PROPOSAL_ALLOW_ONLINESIGN") != 0) {
522 if (!empty($arrayfields['signature_link']['checked'])) {
523 $html .= '<td data-label="' . $arrayfields['signature_link']['label'] . '">';
524 $html .= '</td>';
525 }
526 }
527
528 $totalarray = array();
529 $totalarray['nbfield'] = 0;
530
531 // Fields title label
532 // --------------------------------------------------------------------
533 $html .= '<tr>';
534 // Action column
535 // if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
536 $html .= '<th data-col="row-checkbox" ></th>';
537 $totalarray['nbfield']++;
538 // }
539 foreach ($object->fields as $key => $val) {
540 $tableKey = 't.' . $key;
541 if (!empty($arrayfields[$tableKey]['checked'])) {
542 $tableOrder = '';
543 if (array_key_exists($tableKey, $sortList)) {
544 $tableOrder = strtolower($sortList[$tableKey]);
545 }
546 $url_param = $url_file . '&sortfield=' . $tableKey . '&sortorder=' . ($tableOrder == 'desc' ? 'asc' : 'desc') . $param;
547 $html .= '<th data-col="'.dol_escape_htmltag($key).'" scope="col"' . ($tableOrder != '' ? ' table-order="' . $tableOrder . '"' : '') . '>';
548 $html .= '<a href="' . $url_param . '">';
549 $html .= $langs->trans($arrayfields['t.' . $key]['label']);
550 $html .= '</a>';
551 $html .= '</th>';
552 $totalarray['nbfield']++;
553 }
554 }
555 // Remain to pay
556 if (!empty($arrayfields['remain_to_pay']['checked'])) {
557 $html .= '<th scope="col">';
558 $html .= $langs->trans($arrayfields['remain_to_pay']['label']);
559 $html .= '</th>';
560 $totalarray['nbfield']++;
561 }
562 // Download link
563 if (!empty($arrayfields['download_link']['checked'])) {
564 $html .= '<th scope="col">';
565 $html .= $langs->trans($arrayfields['download_link']['label']);
566 $html .= '</th>';
567 $totalarray['nbfield']++;
568 }
569 // Signature link
570 if ($elementEn == "propal" && getDolGlobalString("PROPOSAL_ALLOW_ONLINESIGN") != 0) {
571 if (!empty($arrayfields['signature_link']['checked'])) {
572 $html .= '<th scope="col">';
573 $html .= $langs->trans($arrayfields['signature_link']['label']);
574 $html .= '</th>';
575 $totalarray['nbfield']++;
576 }
577 }
578
579 // Hook fields
580 $parameters = array('arrayfields' => $arrayfields, 'sortfield' => $sortfield, 'sortorder' => $sortorder, 'totalarray' => &$totalarray);
581 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
582 $html .= $hookmanager->resPrint;
583 $html .= '</tr>';
584
585 $html .= '</thead>';
586
587 $html .= '<tbody>';
588
589 // Store company
590 $idCompany = (int) $socid;
591 if (!isset($this->companyStaticList[$socid])) {
592 $companyStatic = new Societe($this->db);
593 $companyStatic->fetch($idCompany);
594 $this->companyStaticList[$idCompany] = $companyStatic;
595 }
596 $companyStatic = $this->companyStaticList[$socid];
597
598 // Loop on record
599 // --------------------------------------------------------------------
600 $i = 0;
601 $totalarray = [
602 'nbfield' => 0,
603 'totalizable' => [],
604 ];
605 $imaxinloop = ($limit ? min($num, $limit) : $num);
606 while ($i < $imaxinloop) {
607 $obj = $this->db->fetch_object($resql);
608 if (empty($obj)) {
609 break; // Should not happen
610 }
611
612 // Store properties in $object
613 $object->setVarsFromFetchObj($obj);
614
615 // specific to get invoice status (depends on payment)
616 $payment = -1;
617 if ($elementEn == 'invoice') {
618 // paid sum
619 $payment = $object->getSommePaiement();
620 $totalcreditnotes = $object->getSumCreditNotesUsed();
621 $totaldeposits = $object->getSumDepositsUsed();
622
623 // remain to pay
624 $totalpay = $payment + $totalcreditnotes + $totaldeposits;
625 $remaintopay = price2num($object->total_ttc - $totalpay);
626 if ($object->status == Facture::STATUS_CLOSED && $object->close_code == 'discount_vat') { // If invoice closed with discount for anticipated payment
627 $remaintopay = 0;
628 }
629 if ($object->type == Facture::TYPE_CREDIT_NOTE && $obj->paye == 1 && $discount) {
630 $remaincreditnote = $discount->getAvailableDiscounts($companyStatic, '', 'rc.fk_facture_source=' . $object->id);
631 $remaintopay = -$remaincreditnote;
632 }
633 }
634
635 // Show line of result
636 $html .= '<tr data-rowid="' . $object->id . '">';
637 // if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
638 $html .= '<td class="nowraponall">';
639 $html .= '</td>';
640 if (!$i) {
641 $totalarray['nbfield']++;
642 }
643 // }
644 foreach ($object->fields as $key => $val) {
645 if (!empty($arrayfields['t.' . $key]['checked'])) {
646 $html .= '<td class="nowraponall" data-label="' . $arrayfields['t.' . $key]['label'] . '">';
647 if ($key == 'status' || $key == 'fk_statut') {
648 if ($elementEn == 'invoice') {
649 // specific to get invoice status (depends on payment)
650 $html .= $object->getLibStatut(5, $payment);
651 } else {
652 $html .= $object->getLibStatut(5);
653 }
654 } elseif ($key == 'rowid') {
655 $html .= $this->form->showOutputFieldForObject($object, $val, $key, $object->id, '');
656 } else {
657 $html .= $this->form->showOutputFieldForObject($object, $val, $key, $object->$key, '');
658 }
659 $html .= '</td>';
660
661
662 if (!$i) {
663 $totalarray['nbfield']++;
664 }
665 if (!empty($val['isameasure']) && $val['isameasure'] == 1) {
666 if (!$i) {
667 $totalarray['pos'][$totalarray['nbfield']] = 't.' . $key;
668 }
669 if (!isset($totalarray['val'])) {
670 $totalarray['val'] = array();
671 }
672 if (!isset($totalarray['val']['t.' . $key])) {
673 $totalarray['val']['t.' . $key] = 0;
674 }
675 $totalarray['val']['t.' . $key] += $object->$key;
676 }
677 }
678 }
679 // Remain to pay
680 if (!empty($arrayfields['remain_to_pay']['checked'])) {
681 $html .= '<td class="nowraponall" data-label="' . $arrayfields['remain_to_pay']['label'] . '">';
682 $html .= $this->form->showOutputFieldForObject($object, $arrayfields['remain_to_pay'], 'remain_to_pay', $remaintopay, '');
683 //$html .= price($remaintopay);
684 $html .= '</td>';
685 if (!$i) {
686 $totalarray['nbfield']++;
687 }
688 }
689 // Download link
690 if (!empty($arrayfields['download_link']['checked'])) {
691 $element = $object->element;
692 $html .= '<td class="nowraponall" data-label="' . $arrayfields['download_link']['label'] . '">';
693 $filename = dol_sanitizeFileName($obj->ref);
694 $filedir = $conf->{$element}->multidir_output[$obj->element_entity] . '/' . dol_sanitizeFileName($obj->ref);
695 $html .= $this->form->getDocumentsLink($element, $filename, $filedir);
696 $html .= '</td>';
697 if (!$i) {
698 $totalarray['nbfield']++;
699 }
700 }
701 // Signature link
702 if ($elementEn == "propal" && getDolGlobalString("PROPOSAL_ALLOW_ONLINESIGN") != 0) {
703 if (!empty($arrayfields['signature_link']['checked'])) {
704 $html .= '<td class="nowraponall" data-label="' . $arrayfields['signature_link']['label'] . '">';
705 if ($object->fk_statut == Propal::STATUS_VALIDATED) {
706 $html .= $this->form->getSignatureLink('proposal', $object);
707 }
708 $html .= '</td>';
709 if (!$i) {
710 $totalarray['nbfield']++;
711 }
712 }
713 }
714 // Fields from hook
715 $parameters = array('arrayfields' => $arrayfields, 'object' => $object, 'obj' => $obj, 'i' => $i, 'totalarray' => &$totalarray);
716 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
717 $html .= $hookmanager->resPrint;
718
719 $html .= '</tr>';
720
721 $i++;
722 }
723
724 // Move fields of totalizable into the common array pos and val
725 if (!empty($totalarray['totalizable']) && is_array($totalarray['totalizable'])) {
726 foreach ($totalarray['totalizable'] as $keytotalizable => $valtotalizable) {
727 $totalarray['pos'][$valtotalizable['pos']] = $keytotalizable;
728 $totalarray['val'][$keytotalizable] = isset($valtotalizable['total']) ? $valtotalizable['total'] : 0;
729 }
730 }
731 // Show total line
732 if (isset($totalarray['pos'])) {
733 $html .= '<tr>';
734 $i = 0;
735 while ($i < $totalarray['nbfield']) {
736 $i++;
737 if (!empty($totalarray['pos'][$i])) {
738 $html .= '<td class="nowraponall essai">';
739 $html .= price(!empty($totalarray['val'][$totalarray['pos'][$i]]) ? $totalarray['val'][$totalarray['pos'][$i]] : 0);
740 $html .= '</td>';
741 } else {
742 if ($i == 1) {
743 $html .= '<td>' . $langs->trans("Total") . '</td>';
744 } else {
745 $html .= '<td></td>';
746 }
747 }
748 }
749 $html .= '</tr>';
750 }
751
752 // If no record found
753 if ($num == 0) {
754 $colspan = 1;
755 foreach ($arrayfields as $key => $val) {
756 if (!empty($val['checked'])) {
757 $colspan++;
758 }
759 }
760 $html .= '<tr><td colspan="' . $colspan . '"><span class="opacitymedium">' . $langs->trans("NoRecordFound") . '</span></td></tr>';
761 }
762
763 $html .= '</tbody>';
764
765 $this->db->free($resql);
766
767 $parameters = array('arrayfields' => $arrayfields, 'sql' => $sql);
768 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
769 $html .= $hookmanager->resPrint;
770
771 $html .= '</table>';
772
773 $html .= '</form>';
774
775 return $html;
776 }
777
786 public static function generatePageListNav(string $url, int $nbPages, int $currentPage)
787 {
788 global $langs;
789
790 // Return nothing (no navigation bar), if there is only 1 page.
791 if ($nbPages <= 1) {
792 return '';
793 }
794
795 $pSep = strpos($url, '?') === false ? '?' : '&amp;';
796
797 $html = '<ul class="pages-nav-list">';
798
799 if ($currentPage > 1) {
800 $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>';
801 }
802
803 $maxPaginItem = min($nbPages, 5);
804 $minPageNum = max(1, $currentPage - 3);
805 $maxPageNum = min($nbPages, $currentPage + 3);
806
807 if ($minPageNum > 1) {
808 $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>';
809 $html .= '<li>&hellip;</li>';
810 }
811
812 for ($p = $minPageNum; $p <= $maxPageNum; $p++) {
813 $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>';
814 }
815
816 if ($maxPaginItem < $nbPages) {
817 $html .= '<li>&hellip;</li>';
818 $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>';
819 }
820
821 if ($currentPage < $nbPages) {
822 $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>';
823 }
824
825 $html .= '</ul>';
826
827 return $html;
828 }
829}
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.
const STATUS_VALIDATED
Validated status.
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...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
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...