dolibarr 24.0.0-beta
myobject.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2023-2025 Frédéric France <frederic.france@free.fr>
4 * Copyright (C) ---Replace with your own copyright and developer email---
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
26// Put here all includes required by your class file
27require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
28//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
29//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
30
35{
39 public $module = 'mymodule';
40
44 public $element = 'myobject';
45
50 public $TRIGGER_PREFIX = 'MYMODULE_MYOBJECT'; // Will be used to build trgiger keys 'MYMODULE_MYOBJECT_MODIFY', ...
51
55 public $table_element = 'mymodule_myobject';
56
60 //public $element_for_permission = 'mymodule';
61
65 public $picto = 'fa-file';
66
70 public $isextrafieldmanaged = 0;
71
76 public $ismultientitymanaged = 0;
77
78
79 const STATUS_DRAFT = 0;
80 const STATUS_VALIDATED = 1;
81 const STATUS_CANCELED = 9;
82
126 // BEGIN MODULEBUILDER PROPERTIES
131 public $fields = array(
132 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => 'Id', 'lang' => 'mymodule@mymodule'),
133 'ref' => array('type' => 'varchar(128)', 'label' => 'Ref', 'enabled' => 1, 'position' => 15, 'notnull' => 1, 'visible' => 1, 'index' => 1, 'searchall' => 1, 'showoncombobox' => 1, 'validate' => 1, 'comment' => 'Reference of object', 'lang' => 'mymodule@mymodule'),
134 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => 0, 'notnull' => 1, 'position' => 20, 'index' => 1),
135 'label' => array('type' => 'varchar(255)', 'label' => 'Label', 'enabled' => 1, 'position' => 30, 'notnull' => 0, 'visible' => 1, 'alwayseditable' => 1, 'searchall' => 1, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'help' => 'Help text', 'showoncombobox' => 2, 'validate' => 1, 'lang' => 'mymodule@mymodule'),
136 'amount' => array('type' => 'price', 'label' => 'Amount', 'enabled' => 1, 'position' => 40, 'notnull' => 0, 'visible' => 1, 'default' => 'null', 'isameasure' => 1, 'help' => 'Help text for amount', 'validate' => 1, 'lang' => 'mymodule@mymodule'),
137 'qty' => array('type' => 'real', 'label' => 'Qty', 'enabled' => 1, 'position' => 45, 'notnull' => 0, 'visible' => 1, 'default' => '0', 'isameasure' => 1, 'css' => 'maxwidth75imp', 'help' => 'Help text for quantity', 'validate' => 1, 'lang' => 'mymodule@mymodule'),
138 'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))', 'label' => 'ThirdParty', 'picto' => 'company', 'enabled' => 'isModEnabled("societe")', 'position' => 50, 'notnull' => -1, 'visible' => 1, 'index' => 1, 'css' => 'maxwidth500 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150', 'help' => 'OrganizationEventLinkToThirdParty', 'validate' => 1, 'lang' => 'mymodule@mymodule'),
139 'fk_project' => array('type' => 'integer:Project:projet/class/project.class.php:1', 'label' => 'Project', 'picto' => 'project', 'enabled' => 'isModEnabled("project")', 'position' => 52, 'notnull' => -1, 'visible' => -1, 'index' => 1, 'css' => 'maxwidth500 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150', 'validate' => 1, 'lang' => 'mymodule@mymodule'),
140 'description' => array('type' => 'text', 'label' => 'Description', 'enabled' => 1, 'position' => 60, 'notnull' => 0, 'visible' => 3, 'validate' => 1, 'lang' => 'mymodule@mymodule'),
141 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 61, 'notnull' => 0, 'visible' => 0, 'cssview' => 'wordbreak', 'validate' => 1, 'lang' => 'mymodule@mymodule'),
142 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 62, 'notnull' => 0, 'visible' => 0, 'cssview' => 'wordbreak', 'validate' => 1, 'lang' => 'mymodule@mymodule'),
143 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2, 'lang' => 'mymodule@mymodule'),
144 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2, 'lang' => 'mymodule@mymodule'),
145 'fk_user_creat' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'picto' => 'user', 'enabled' => 1, 'position' => 510, 'notnull' => 1, 'visible' => -2, 'foreignkey' => '0', 'csslist' => 'tdoverflowmax150', 'lang' => 'mymodule@mymodule'),
146 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'picto' => 'user', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2, 'csslist' => 'tdoverflowmax150', 'lang' => 'mymodule@mymodule'),
147 'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'position' => 600, 'notnull' => 0, 'visible' => 0, 'lang' => 'mymodule@mymodule'),
148 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2, 'lang' => 'mymodule@mymodule'),
149 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0, 'lang' => 'mymodule@mymodule'),
150 'status' => array('type' => 'integer', 'label' => 'Status', 'enabled' => 1, 'position' => 2000, 'notnull' => 1, 'visible' => 1, 'index' => 1, 'arrayofkeyval' => array(0 => 'Draft', '1' => 'Validated', 9 => 'Canceled'), 'validate' => 1, 'lang' => 'mymodule@mymodule'),
151 );
152
156 public $rowid;
157
161 public $ref;
162
166 public $label;
167
171 public $amount;
172
176 public $socid; // both socid and fk_soc are used
180 public $fk_soc; // both socid and fk_soc are used
181
185 public $status;
186
190 public $fk_user_creat;
191
195 public $fk_user_modif;
196
200 public $last_main_doc;
201
205 public $import_key;
206 // END MODULEBUILDER PROPERTIES
207
208 //BEGIN MODULEBUILDER LINES
209 // If this object has a subtable with lines
210
214 public $table_element_line = 'mymodule_myobjectline';
215
219 public $fk_element = 'fk_myobject';
220
224 public $class_element_line = 'MyObjectline';
225
229 protected $childtables = array('mychildtable' => array('name'=>'MyObject', 'fk_element'=>'fk_myobject'));
230
236 protected $childtablesoncascade = array('mymodule_myobjectdet');
237
241 public $lines = array();
242
243 //END MODULEBUILDER LINES
244
250 public function __construct(DoliDB $db)
251 {
252 global $langs;
253
254 $this->db = $db;
255
256 if (!getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) {
257 $this->fields['rowid']['visible'] = 0;
258 }
259 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
260 $this->fields['entity']['enabled'] = 0;
261 }
262
263 // Example to show how to set values of fields definition dynamically
264 /*if ($user->hasRight('mymodule', 'myobject', 'read')) {
265 $this->fields['myfield']['visible'] = 1;
266 $this->fields['myfield']['noteditable'] = 0;
267 }*/
268
269 // Unset fields that are disabled
270 foreach ($this->fields as $key => $val) {
271 if (isset($val['enabled']) && empty($val['enabled'])) {
272 unset($this->fields[$key]);
273 }
274 }
275
276 // Translate some data of arrayofkeyval
277 if (is_object($langs)) {
278 foreach ($this->fields as $key => $val) {
279 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
280 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
281 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
282 }
283 }
284 }
285 }
286 }
287
295 public function create(User $user, $notrigger = 0)
296 {
297 $result = $this->createCommon($user, $notrigger);
298
299 // uncomment lines below if you want to validate object after creation
300 // if ($result > 0) {
301 // $this->fetch($this->id); // needed to retrieve some fields (ie date_creation for masked ref)
302 // $resultupdate = $this->validate($user, $notrigger);
303 // if ($resultupdate < 0) { return $resultupdate; }
304 // }
305
306 return $result;
307 }
308
316 public function createFromClone(User $user, $fromid)
317 {
318 global $langs, $extrafields;
319 $error = 0;
320
321 dol_syslog(__METHOD__, LOG_DEBUG);
322
323 $object = new self($this->db);
324
325 $this->db->begin();
326
327 // Load source object
328 $result = $object->fetchCommon($fromid);
329 //BEGIN MODULEBUILDER LINES
330 if ($result > 0 && !empty($object->table_element_line)) {
331 $object->fetchLines();
332 }
333
334 // get lines so they will be clone
335 foreach ($this->lines as $line)
336 $line->fetch_optionals();
337 //END MODULEBUILDER LINES
338 // Reset some properties
339 unset($object->id);
340 unset($object->fk_user_creat);
341 unset($object->import_key);
342
343 // Clear fields
344 if (property_exists($object, 'ref')) {
345 $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
346 }
347 if (property_exists($object, 'label')) {
348 $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
349 }
350 if (property_exists($object, 'status')) {
351 $object->status = self::STATUS_DRAFT;
352 }
353 if (property_exists($object, 'date_creation')) {
354 $object->date_creation = dol_now();
355 }
356 if (property_exists($object, 'date_modification')) {
357 $object->date_modification = null;
358 }
359 // ...
360 // Clear extrafields that are unique
361 if (is_array($object->array_options) && count($object->array_options) > 0) {
362 $extrafields->fetch_name_optionals_label($this->table_element);
363 foreach ($object->array_options as $key => $option) {
364 $shortkey = preg_replace('/options_/', '', $key);
365 if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
366 //var_dump($key);
367 //var_dump($clonedObj->array_options[$key]); exit;
368 unset($object->array_options[$key]);
369 }
370 }
371 }
372
373 // Create clone
374 $object->context['createfromclone'] = 'createfromclone';
375 $result = $object->createCommon($user);
376 if ($result < 0) {
377 $error++;
379 }
380
381 if (!$error) {
382 // copy internal contacts
383 if ($this->copy_linked_contact($object, 'internal') < 0) {
384 $error++;
385 }
386 }
387
388 if (!$error) {
389 // copy external contacts if same company
390 if (!empty($object->socid) && ((property_exists($this, 'fk_soc') && ($this->fk_soc == $object->socid)) || (property_exists($this, 'socid') && ($this->socid == $object->socid)))) { // @phpstan-ignore-line
391 if ($this->copy_linked_contact($object, 'external') < 0) {
392 $error++;
393 }
394 }
395 }
396
397 unset($object->context['createfromclone']);
398
399 // End
400 if (!$error) {
401 $this->db->commit();
402 return $object;
403 } else {
404 $this->db->rollback();
405 return -1;
406 }
407 }
408
418 public function fetch($id, $ref = null, $noextrafields = 0, $nolines = 0)
419 {
420 $result = $this->fetchCommon($id, $ref, '', $noextrafields);
421 //BEGIN MODULEBUILDER LINES
422 if ($result > 0 && !empty($this->table_element_line) && empty($nolines)) {
423 $this->fetchLines($noextrafields);
424 }
425 //END MODULEBUILDER LINES
426 return $result;
427 }
428
435 public function fetchLines($noextrafields = 0)
436 {
437 $this->lines = array();
438
439 $result = $this->fetchLinesCommon('', $noextrafields);
440 return $result;
441 }
442 //END MODULEBUILDER LINES
457 public function fetchAll($sortorder = '', $sortfield = '', $limit = 1000, $offset = 0, string $filter = '', $filtermode = 'AND')
458 {
459 dol_syslog(__METHOD__, LOG_DEBUG);
460
461 $records = array();
462
463 $sql = "SELECT ";
464 $sql .= $this->getFieldList('t');
465 $sql .= " FROM ".$this->db->prefix().$this->table_element." as t";
466 if (!empty($this->isextrafieldmanaged) && $this->isextrafieldmanaged == 1) {
467 $sql .= " LEFT JOIN ".$this->db->prefix().$this->table_element."_extrafields as te ON te.fk_object = t.rowid";
468 }
469 if (!empty($this->ismultientitymanaged) && (int) $this->ismultientitymanaged == 1) {
470 $sql .= " WHERE t.entity IN (".getEntity($this->element).")";
471 } elseif (preg_match('/^\w+@\w+$/', (string) $this->ismultientitymanaged)) {
472 $tmparray = explode('@', (string) $this->ismultientitymanaged);
473 $sql .= " LEFT JOIN ".$this->db->prefix().$tmparray[1]." as pt ON t.".$this->db->sanitize($tmparray[0])." = pt.rowid";
474 $sql .= " WHERE pt.entity IN (".getEntity($this->element).")";
475 } else {
476 $sql .= " WHERE 1 = 1";
477 }
478
479 // Manage filter
480 $errormessage = '';
481 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
482 if ($errormessage) {
483 $this->errors[] = $errormessage;
484 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
485 return -1;
486 }
487
488 if (!empty($sortfield)) {
489 $sql .= $this->db->order($sortfield, $sortorder);
490 }
491 if (!empty($limit)) {
492 $sql .= $this->db->plimit($limit, $offset);
493 }
494
495 $resql = $this->db->query($sql);
496 if ($resql) {
497 $num = $this->db->num_rows($resql);
498 $i = 0;
499 while ($i < ($limit ? min($limit, $num) : $num)) {
500 $obj = $this->db->fetch_object($resql);
501
502 $record = new self($this->db);
503 $record->setVarsFromFetchObj($obj);
504
505 if (!empty($record->isextrafieldmanaged)) {
506 $record->fetch_optionals();
507 }
508
509 $records[$record->id] = $record;
510
511 $i++;
512 }
513 $this->db->free($resql);
514
515 return $records;
516 } else {
517 $this->errors[] = 'Error '.$this->db->lasterror();
518 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
519
520 return -1;
521 }
522 }
523
531 public function update(User $user, $notrigger = 0)
532 {
533 return $this->updateCommon($user, $notrigger);
534 }
535
543 public function delete(User $user, $notrigger = 0)
544 {
545 return $this->deleteCommon($user, $notrigger);
546 //return $this->deleteCommon($user, $notrigger, 1);
547 }
548
549 //BEGIN MODULEBUILDER LINES
558 public function deleteLine(User $user, $idline, $notrigger = 0)
559 {
560 if ($this->status < 0) {
561 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
562 return -2;
563 }
564
565 return $this->deleteLineCommon($user, $idline, $notrigger);
566 }
567 //END MODULEBUILDER LINES
568
569
577 public function validate($user, $notrigger = 0)
578 {
579 global $conf;
580
581 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
582
583 $error = 0;
584
585 // Protection
586 if ($this->status == self::STATUS_VALIDATED) {
587 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
588 return 0;
589 }
590
591 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule', 'myobject', 'write'))
592 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule', 'myobject_advance', 'validate')))
593 {
594 $this->error='NotEnoughPermissions';
595 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
596 return -1;
597 }*/
598
599 $now = dol_now();
600
601 $this->db->begin();
602
603 // Define new ref
604 if (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref)) { // empty should not happened, but when it occurs, the test save life
605 $num = $this->getNextNumRef();
606 } else {
607 $num = (string) $this->ref;
608 }
609 $this->newref = $num;
610
611 if (!empty($num)) {
612 // Validate
613 $sql = "UPDATE ".$this->db->prefix().$this->table_element;
614 $sql .= " SET ";
615 if (!empty($this->fields['ref'])) {
616 $sql .= " ref = '".$this->db->escape($num)."',";
617 }
618 $sql .= " status = ".self::STATUS_VALIDATED;
619 if (!empty($this->fields['date_validation'])) {
620 $sql .= ", date_validation = '".$this->db->idate($now)."'";
621 }
622 if (!empty($this->fields['fk_user_valid'])) {
623 $sql .= ", fk_user_valid = ".((int) $user->id);
624 }
625 $sql .= " WHERE rowid = ".((int) $this->id);
626
627 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
628 $resql = $this->db->query($sql);
629 if (!$resql) {
630 dol_print_error($this->db);
631 $this->error = $this->db->lasterror();
632 $error++;
633 }
634
635 if (!$error && !$notrigger) {
636 // Call trigger
637 $result = $this->call_trigger('MYOBJECT_VALIDATE', $user);
638 if ($result < 0) {
639 $error++;
640 }
641 // End call triggers
642 }
643 }
644
645 if (!$error) {
646 $this->oldref = $this->ref;
647
648 // Rename directory if dir was a temporary ref
649 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
650 // Now we rename also files into index
651 $sql = 'UPDATE '.$this->db->prefix()."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'myobject/".$this->db->escape($this->newref)."'";
652 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'myobject/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
653 $resql = $this->db->query($sql);
654 if (!$resql) {
655 $error++;
656 $this->error = $this->db->lasterror();
657 }
658 $sql = 'UPDATE '.$this->db->prefix()."ecm_files set filepath = 'myobject/".$this->db->escape($this->newref)."'";
659 $sql .= " WHERE filepath = 'myobject/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
660 $resql = $this->db->query($sql);
661 if (!$resql) {
662 $error++;
663 $this->error = $this->db->lasterror();
664 }
665
666 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
667 $oldref = dol_sanitizeFileName($this->ref);
668 $newref = dol_sanitizeFileName($num);
669 $dirsource = $conf->mymodule->dir_output.'/myobject/'.$oldref;
670 $dirdest = $conf->mymodule->dir_output.'/myobject/'.$newref;
671 if (!$error && file_exists($dirsource)) {
672 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
673
674 if (@rename($dirsource, $dirdest)) {
675 dol_syslog("Rename ok");
676 // Rename docs starting with $oldref with $newref
677 $listoffiles = dol_dir_list($conf->mymodule->dir_output.'/myobject/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
678 foreach ($listoffiles as $fileentry) {
679 $dirsource = $fileentry['name'];
680 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
681 $dirsource = $fileentry['path'].'/'.$dirsource;
682 $dirdest = $fileentry['path'].'/'.$dirdest;
683 @rename($dirsource, $dirdest);
684 }
685 }
686 }
687 }
688 }
689
690 // Set new ref and current status
691 if (!$error) {
692 $this->ref = $num;
693 $this->status = self::STATUS_VALIDATED;
694 }
695
696 if (!$error) {
697 $this->db->commit();
698 return 1;
699 } else {
700 $this->db->rollback();
701 return -1;
702 }
703 }
704
705
713 public function setDraft($user, $notrigger = 0)
714 {
715 // Protection
716 if ($this->status <= self::STATUS_DRAFT) {
717 return 0;
718 }
719
720 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
721 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
722 {
723 $this->error='Permission denied';
724 return -1;
725 }*/
726
727 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'MYMODULE_MYOBJECT_UNVALIDATE');
728 }
729
737 public function cancel($user, $notrigger = 0)
738 {
739 // Protection
740 if ($this->status != self::STATUS_VALIDATED) {
741 return 0;
742 }
743
744 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
745 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
746 {
747 $this->error='Permission denied';
748 return -1;
749 }*/
750
751 return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'MYMODULE_MYOBJECT_CANCEL');
752 }
753
761 public function reopen($user, $notrigger = 0)
762 {
763 // Protection
764 if ($this->status == self::STATUS_VALIDATED) {
765 return 0;
766 }
767
768 /*if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
769 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
770 {
771 $this->error='Permission denied';
772 return -1;
773 }*/
774
775 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'MYMODULE_MYOBJECT_REOPEN');
776 }
777
785 public function getTooltipContentArray($params)
786 {
787 global $langs;
788
789 $datas = [];
790
791 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
792 return ['optimize' => $langs->trans("ShowMyObject")];
793 }
794 $datas['picto'] = img_picto('', $this->picto).' <u>'.$langs->trans("MyObject").'</u>';
795 if (isset($this->status)) {
796 $datas['picto'] .= ' '.$this->getLibStatut(5);
797 }
798 if (property_exists($this, 'ref')) {
799 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
800 }
801 if (property_exists($this, 'label')) {
802 $datas['label'] = '<br>'.$langs->trans('Label').':</b> '.$this->label;
803 }
804
805 return $datas;
806 }
807
818 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
819 {
820 global $conf, $langs, $hookmanager;
821
822 if (!empty($conf->dol_no_mouse_hover)) {
823 $notooltip = 1; // Force disable tooltips
824 }
825
826 $result = '';
827 $params = [
828 'id' => (string) $this->id,
829 'objecttype' => $this->element.($this->module ? '@'.$this->module : ''),
830 'option' => $option,
831 ];
832 $classfortooltip = 'classfortooltip';
833 $dataparams = '';
834 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
835 $classfortooltip = 'classforajaxtooltip';
836 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
837 $label = '';
838 } else {
839 $label = implode($this->getTooltipContentArray($params));
840 }
841
842 $baseurl = dol_buildpath('/mymodule/myobject_card.php', 1);
843 $query = ['id' => $this->id];
844 if ($option !== 'nolink') {
845 // Add param to save lastsearch_values or not
846 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
847 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
848 $add_save_lastsearch_values = 1;
849 }
850 if ($add_save_lastsearch_values) {
851 $query = array_merge($query, ['save_lastsearch_values' => 1]);
852 }
853 }
854 $url = dolBuildUrl($baseurl, $query);
855
856 $linkclose = '';
857 if (empty($notooltip)) {
858 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
859 $label = $langs->trans("ShowMyObject");
860 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
861 }
862 $linkclose .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
863 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
864 } else {
865 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
866 }
867
868 if ($option == 'nolink') {
869 $linkstart = '<span';
870 } else {
871 $linkstart = '<a href="'.$url.'"';
872 }
873 $linkstart .= $linkclose.'>';
874 if ($option == 'nolink') {
875 $linkend = '</span>';
876 } else {
877 $linkend = '</a>';
878 }
879
880 $result .= $linkstart;
881
882 if (empty($this->showphoto_on_popup)) {
883 if ($withpicto) {
884 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1);
885 }
886 } else {
887 if ($withpicto) {
888 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
889
890 list($class, $module) = explode('@', $this->picto);
891 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
892 $filearray = dol_dir_list($upload_dir, "files");
893 $filename = $filearray[0]['name'];
894 if (!empty($filename)) {
895 $pospoint = strpos($filearray[0]['name'], '.');
896
897 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
898 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
899 $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref"><img class="photo'.$module.'" alt="No photo" border="0" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$module.'&entity='.$conf->entity.'&file='.urlencode($pathtophoto).'"></div></div>';
900 } else {
901 $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photouserphoto userphoto" alt="No photo" border="0" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$module.'&entity='.$conf->entity.'&file='.urlencode($pathtophoto).'"></div>';
902 }
903
904 $result .= '</div>';
905 } else {
906 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
907 }
908 }
909 }
910
911 if ($withpicto != 2) {
912 $result .= $this->ref;
913 }
914
915 $result .= $linkend;
916 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
917
918 global $action, $hookmanager;
919 $hookmanager->initHooks(array($this->element.'dao'));
920 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
921 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
922 if ($reshook > 0) {
923 $result = $hookmanager->resPrint;
924 } else {
925 $result .= $hookmanager->resPrint;
926 }
927
928 return $result;
929 }
930
938 public function getKanbanView($option = '', $arraydata = null)
939 {
940 global $conf, $langs;
941
942 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
943
944 $return = '<div class="box-flex-item box-flex-grow-zero">';
945 $return .= '<div class="info-box info-box-sm">';
946 $return .= '<span class="info-box-icon bg-infobox-action">';
947 $return .= img_picto('', $this->picto);
948 $return .= '</span>';
949 $return .= '<div class="info-box-content">';
950 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
951 if ($selected >= 0) {
952 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
953 }
954 if (property_exists($this, 'label')) {
955 $return .= ' <div class="inline-block opacitymedium valignmiddle tdoverflowmax100">'.$this->label.'</div>';
956 }
957 if (property_exists($this, 'thirdparty') && is_object($this->thirdparty)) {
958 $return .= '<br><div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).'</div>';
959 }
960 if (property_exists($this, 'amount')) {
961 $return .= '<br>';
962 $return .= '<span class="info-box-label amount">'.price($this->amount, 0, $langs, 1, -1, -1, $conf->currency).'</span>';
963 }
964 if (method_exists($this, 'getLibStatut')) {
965 $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
966 }
967 $return .= '</div>';
968 $return .= '</div>';
969 $return .= '</div>';
970
971 return $return;
972 }
973
980 public function getLabelStatus($mode = 0)
981 {
982 return $this->LibStatut($this->status, $mode);
983 }
984
991 public function getLibStatut($mode = 0)
992 {
993 return $this->LibStatut($this->status, $mode);
994 }
995
996 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1004 public function LibStatut($status, $mode = 0)
1005 {
1006 // phpcs:enable
1007 if (is_null($status)) {
1008 return '';
1009 }
1010
1011 $paramsBadge = array('badgeParams' => array('attr' => array(
1012 'data-status-element' => $this->element,
1013 'data-status' => (int) $status
1014 )));
1015
1016
1017 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
1018 global $langs;
1019 //$langs->load("mymodule@mymodule");
1020 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
1021 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
1022 $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
1023 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
1024 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
1025 $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
1026 }
1027
1028 $statusType = 'status'.$status;
1029 //if ($status == self::STATUS_VALIDATED) $statusType = 'status1';
1030 if ($status == self::STATUS_CANCELED) {
1031 $statusType = 'status6';
1032 }
1033
1034 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode, '', $paramsBadge);
1035 }
1036
1043 public function info($id)
1044 {
1045 $sql = "SELECT t.rowid, t.date_creation as datec";
1046 if (!empty($this->isextrafieldmanaged) && $this->isextrafieldmanaged == 1) {
1047 $sql .= ", GREATEST(t.tms, COALESCE(te.tms, t.tms)) as datem";
1048 } else {
1049 $sql .= ", t.tms as datem";
1050 }
1051 if (!empty($this->fields['date_validation'])) {
1052 $sql .= ", t.date_validation as datev";
1053 }
1054 if (!empty($this->fields['fk_user_creat'])) {
1055 $sql .= ", t.fk_user_creat";
1056 }
1057 if (!empty($this->fields['fk_user_modif'])) {
1058 $sql .= ", t.fk_user_modif";
1059 }
1060 if (!empty($this->fields['fk_user_valid'])) {
1061 $sql .= ", t.fk_user_valid";
1062 }
1063 $sql .= " FROM ".$this->db->prefix().$this->table_element." as t";
1064 if (!empty($this->isextrafieldmanaged) && $this->isextrafieldmanaged == 1) {
1065 $sql .= " LEFT JOIN ".$this->db->prefix().$this->table_element."_extrafields as te ON te.fk_object = t.rowid";
1066 }
1067 $sql .= " WHERE t.rowid = ".((int) $id);
1068
1069 $result = $this->db->query($sql);
1070 if ($result) {
1071 if ($this->db->num_rows($result)) {
1072 $obj = $this->db->fetch_object($result);
1073
1074 $this->id = $obj->rowid;
1075
1076 if (!empty($this->fields['fk_user_creat'])) {
1077 $this->user_creation_id = $obj->fk_user_creat;
1078 }
1079 if (!empty($this->fields['fk_user_modif'])) {
1080 $this->user_modification_id = $obj->fk_user_modif;
1081 }
1082 if (!empty($this->fields['fk_user_valid'])) {
1083 $this->user_validation_id = $obj->fk_user_valid;
1084 }
1085 $this->date_creation = $this->db->jdate($obj->datec);
1086 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
1087 if (!empty($obj->datev)) {
1088 $this->date_validation = empty($obj->datev) ? '' : $this->db->jdate($obj->datev);
1089 }
1090 }
1091
1092 $this->db->free($result);
1093 } else {
1094 dol_print_error($this->db);
1095 }
1096 }
1097
1104 public function initAsSpecimen()
1105 {
1106 // Set here init that are not commonf fields
1107 // $this->property1 = ...
1108 // $this->property2 = ...
1109
1110 return $this->initAsSpecimenCommon();
1111 }
1112
1113 //BEGIN MODULEBUILDER LINES
1119 public function getLinesArray()
1120 {
1121 $this->lines = array();
1122
1123 $objectline = new MyObjectLine($this->db);
1124 $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_myobject:=:'.((int) $this->id).')');
1125
1126 if (is_numeric($result)) {
1127 $this->setErrorsFromObject($objectline);
1128 return $result;
1129 } else {
1131 $this->lines = $result;
1132 return $this->lines;
1133 }
1134 }
1135 //END MODULEBUILDER LINES
1136
1142 public function getNextNumRef()
1143 {
1144 global $langs, $conf;
1145 $langs->load("mymodule@mymodule");
1146
1147 if (!getDolGlobalString('MYMODULE_MYOBJECT_ADDON')) {
1148 $conf->global->MYMODULE_MYOBJECT_ADDON = 'mod_myobject_standard';
1149 }
1150
1151 if (getDolGlobalString('MYMODULE_MYOBJECT_ADDON')) {
1152 $mybool = false;
1153
1154 $file = getDolGlobalString('MYMODULE_MYOBJECT_ADDON').".php";
1155 $classname = getDolGlobalString('MYMODULE_MYOBJECT_ADDON');
1156
1157 // Include file with class
1158 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1159 foreach ($dirmodels as $reldir) {
1160 $dir = dol_buildpath($reldir."core/modules/mymodule/");
1161
1162 // Load file with numbering class (if found)
1163 $mybool = $mybool || @include_once $dir.$file;
1164 }
1165
1166 if (!$mybool) {
1167 dol_print_error(null, "Failed to include file ".$file);
1168 return '';
1169 }
1170
1171 if (class_exists($classname)) {
1172 $obj = new $classname();
1173 '@phan-var-force ModeleNumRefMyObject $obj';
1174 $numref = $obj->getNextValue($this);
1175
1176 if ($numref != '' && $numref != '-1') {
1177 return $numref;
1178 } else {
1179 $this->error = $obj->error;
1180 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1181 return "";
1182 }
1183 } else {
1184 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1185 return "";
1186 }
1187 } else {
1188 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1189 return "";
1190 }
1191 }
1192
1204 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1205 {
1206 global $langs;
1207
1208 $result = 0;
1209 $includedocgeneration = 0;
1210
1211 $langs->load("mymodule@mymodule");
1212
1213 if (!dol_strlen($modele)) {
1214 if (!empty($this->model_pdf)) {
1215 $modele = $this->model_pdf;
1216 } else {
1217 $modele = getDolGlobalString('MYOBJECT_ADDON_PDF', 'standard_myobject');
1218 }
1219 }
1220
1221 $modelpath = "core/modules/mymodule/doc/";
1222
1223 if ($includedocgeneration && !empty($modele)) {
1224 $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1225 }
1226
1227 return $result;
1228 }
1229
1239 public function validateField($fields, $fieldKey, $fieldValue)
1240 {
1241 // Add your own validation rules here.
1242 // ...
1243
1244 return parent::validateField($fields, $fieldKey, $fieldValue);
1245 }
1246
1254 public function doScheduledJob()
1255 {
1256 //global $conf, $langs;
1257
1258 //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlogfile.log';
1259
1260 $error = 0;
1261 $this->output = '';
1262 $this->error = '';
1263
1264 dol_syslog(__METHOD__." start", LOG_INFO);
1265
1266 //$now = dol_now();
1267
1268 $this->db->begin();
1269
1270 // ...
1271
1272 $this->db->commit();
1273
1274 dol_syslog(__METHOD__." end", LOG_INFO);
1275
1276 return $error;
1277 }
1278}
1279
1280
1281require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
1282//BEGIN MODULEBUILDER LINES
1287{
1288 // To complete with content of an object MyObjectLine
1289 // We should have a field rowid, fk_myobject and position
1290
1295 public $parent_element = ''; // Example: '' or 'myobject'
1296
1301 public $fk_parent_attribute = ''; // Example: '' or 'fk_myobject'
1302
1306 public $isextrafieldmanaged = 0;
1307
1312 public $ismultientitymanaged = 0;
1313
1314
1320 public function __construct(DoliDB $db)
1321 {
1322 $this->db = $db;
1323 }
1324}
1325//END MODULEBUILDER LINES
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
$object ref
Definition info.php:90
Parent class of all other business classes (invoices, contracts, proposals, orders,...
deleteLineCommon(User $user, $idline, $notrigger=0)
Delete a line of object in database.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
setErrorsFromObject($object)
setErrorsFromObject
createCommon(User $user, $notrigger=0)
Create object in the database.
getFieldList($alias='', $excludefields=array())
Function to concat keys of fields.
updateCommon(User $user, $notrigger=0)
Update object into database.
setStatusCommon($user, $status, $notrigger=0, $triggercode='')
Set to a status.
initAsSpecimenCommon()
Initialise object with example values Id must be 0 if object instance is a specimen.
copy_linked_contact($objFrom, $source='internal')
Copy contact from one element to current.
fetchLinesCommon($morewhere='', $noextrafields=0)
Load object in memory from the database.
fetchCommon($id, $ref=null, $morewhere='', $noextrafields=0)
Load object in memory from the database.
deleteCommon(User $user, $notrigger=0, $forcechilddeletion=0)
Delete object in database.
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
Class to manage Dolibarr database access.
Class for MyObject.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
createFromClone(User $user, $fromid)
Clone an object into another one.
getKanbanView($option='', $arraydata=null)
Return a thumb for kanban views.
getLibStatut($mode=0)
Return the label of the status.
create(User $user, $notrigger=0)
Create object into database.
update(User $user, $notrigger=0)
Update object into database.
getTooltipContentArray($params)
getTooltipContentArray
reopen($user, $notrigger=0)
Set back to validated status.
setDraft($user, $notrigger=0)
Set draft status.
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Return a link to the object card (with optionally the picto)
LibStatut($status, $mode=0)
Return the label of a given status.
validateField($fields, $fieldKey, $fieldValue)
Return validation test result for a field.
getNextNumRef()
Returns the reference to the following non used object depending on the active numbering module.
fetchAll($sortorder='', $sortfield='', $limit=1000, $offset=0, string $filter='', $filtermode='AND')
Load list of objects in memory from the database.
initAsSpecimen()
Initialize object with example values Id must be 0 if object instance is a specimen.
__construct(DoliDB $db)
Constructor.
deleteLine(User $user, $idline, $notrigger=0)
Delete a line of object in database.
cancel($user, $notrigger=0)
Set cancel status.
fetchLines($noextrafields=0)
Load object lines in memory from the database.
info($id)
Load the info information in the object.
doScheduledJob()
Action executed by scheduler CAN BE A CRON TASK.
fetch($id, $ref=null, $noextrafields=0, $nolines=0)
Load object in memory from the database.
getLabelStatus($mode=0)
Return the label of the status.
validate($user, $notrigger=0)
Validate object.
$fields
'type' field format: 'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortf...
getLinesArray()
Create an array of lines.
Class MyObjectLine.
$parent_element
To overload.
$fk_parent_attribute
To overload.
__construct(DoliDB $db)
Constructor.
Class to manage Dolibarr users.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:168
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:64
dol_now($mode='gmt')
Return date for now.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
dolBuildUrl($url, $params=[], $addtoken=false, $anchor='')
Return path of url.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
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.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
print $langs trans('Date')." left Ref Label right Qty right Price right TotalHT right TotalTTC right right right right right right right right right centpercent right TotalHT right n right VAT right n right TotalVAT right n No sujeto a RE IRPF right TotalLT1 right n right TotalLT2 right n right TotalTTC right n takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency right TotalTTC takeposcustomercurrency right takeposcustomercurrency n right Paid right PaymentTypeShortLIQ right SELECT p pos_change as p datep as p p num_paiement as f pf amount as amount
Definition receipt.php:489