* Copyright (C) 2012 Cedric Salvador * Copyright (C) 2024-2025 MDW * Copyright (C) 2024-2025 Frédéric France * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file htdocs/core/class/commonobjectline.class.php * \ingroup core * \brief File of the superclass of classes of lines of business objects (invoice, contract, proposal, orders, etc. ...) */ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; /** * Parent class for class inheritance lines of business objects * This class is useless for the moment so no inherit are done on it * * TODO For the moment we use the extends on CommonObject until PHP min is 5.4 so we can use Traits. */ abstract class CommonObjectLine extends CommonObject { /** * @var string ID to identify parent CommonObject type (element name) */ public $parent_element = ''; /** * @var string Attribute related to parent CommonObject rowid (many2one) */ public $fk_parent_attribute = ''; /** * Id of the line * @var int */ public $id; /** * Id of the line * @var int * @deprecated Try to use id property as possible (even if field into database is still rowid) * @see $id */ public $rowid; /** * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png */ public $picto = 'line'; /** * @var ?int ID of the unit of measurement (rowid in llx_c_units table) * @see measuringUnitString() * @see getLabelOfUnit() */ public $fk_unit; /** * @var int|'' */ public $date_debut_prevue; /** * @var int|'' */ public $date_debut_reel; /** * @var int|'' */ public $date_fin_prevue; /** * @var int|'' */ public $date_fin_reel; /** * @var float|string */ public $weight; /** * @var int|string */ public $weight_units; // scale -3, 0, 3, 6 /** * @var float|string */ public $length; /** * @var int|string */ public $length_units; // scale -3, 0, 3, 6 /** * @var float|string */ public $width; /** * @var int|string */ public $width_units; // scale -3, 0, 3, 6 /** * @var float|string|null */ public $height; /** * @var int|string|null */ public $height_units; // scale -3, 0, 3, 6 /** * @var float|string|null */ public $surface; /** * @var int|string|null */ public $surface_units; // scale -3, 0, 3, 6 /** * @var float|string|null */ public $volume; /** * @var int|string|null */ public $volume_units; // scale -3, 0, 3, 6 /** * @var ?array> */ public $multilangs; /** * @var int type in line */ public $product_type; /** * @var int product id in line (when line is linked to a product or service) */ public $fk_product; /** * Description of the line * @var string */ public $desc; /** * Description of the line * @var string * @deprecated * @see $desc */ public $description; /** * @var Product Object product to store full product object after a fetch_product() on a line */ public $product; /** * @var string reference in product table */ public $product_ref; /** * @var string label in product table */ public $product_label; /** * @var string barcode in product table */ public $product_barcode; /** * @var string description in product table */ public $product_desc; /** * @var ?string Product custom code */ public $product_custom_code; /** * @var ?string Product custom country code */ public $product_custom_country_code; /** * @var ?int Product custom country id */ public $product_custom_country_id; /** * @var int type in product table */ public $fk_product_type; /** * @var float Quantity */ public $qty; /** * @var int */ public $duree; /** * @var float|string */ public $remise_percent; /** * List of cumulative options: * Bit 0: 0 for common VAT - 1 if VAT french NPR * Bit 1: 0 si ligne normal - 1 si bit discount (link to line into llx_remise_except) * @var ?int */ public $info_bits; /** * @var int special code */ public $special_code; /** * Unit price before taxes * @var float */ public $subprice; /** * Unit price including taxes * @var float */ public $subprice_ttc; /** * @var float|string */ public $tva_tx; /** * @var int multicurrency id */ public $fk_multicurrency; /** * @var string Multicurrency code */ public $multicurrency_code; /** * @var float Multicurrency unit price without taxes */ public $multicurrency_subprice; /** * @var float Multicurrency unit price including taxes */ public $multicurrency_subprice_ttc; /** * @var float Multicurrency total without tax */ public $multicurrency_total_ht; /** * @var float Multicurrency total vat */ public $multicurrency_total_tva; /** * @var float|string Multicurrency total localtax1 */ public $multicurrency_total_localtax1; // not in database /** * @var float|string Multicurrency total localtax2 */ public $multicurrency_total_localtax2; // not in database /** * @var float Multicurrency total with tax */ public $multicurrency_total_ttc; /** * Constructor * * @param DoliDB $db Database handler */ public function __construct($db) { $this->db = $db; } /** * Reads the units dictionary to return the translation code of a unit (if type='code'), or translated long label (if type='long') or short label (if type='short'). * TODO Duplicate of getLabelOfUnit() in product.class.php * * @param string $type Code type ('code', 'long' or 'short') * @param Translate|null $outputlangs Language to use for long label translation * @param int $noentities No entities * @return string|int Return integer <0 if KO, code or label of unit if OK. */ public function getLabelOfUnit($type = 'long', $outputlangs = null, $noentities = 0) { global $langs; if (empty($this->fk_unit)) { return ''; } if (empty($outputlangs)) { $outputlangs = $langs; } $outputlangs->load('products'); $label = ''; $sql = "SELECT code, label, short_label FROM ".$this->db->prefix()."c_units where rowid = ".((int) $this->fk_unit); $resql = $this->db->query($sql); if (!$resql) { $this->error = $this->db->error(); dol_syslog(get_class($this)."::getLabelOfUnit Error ".$this->error, LOG_ERR); return -1; } elseif ($this->db->num_rows($resql) > 0 && $res = $this->db->fetch_array($resql)) { if ($type == 'short') { if ($noentities) { $label = $outputlangs->transnoentitiesnoconv($res['short_label']); } else { $label = $outputlangs->trans($res['short_label']); } } elseif ($type == 'code') { $label = $res['code']; } else { if ($outputlangs->trans('unit'.$res['code']) == 'unit'.$res['code']) { // No translation available $label = $res['label']; } else { // Return the translated value if ($noentities) { $label = $outputlangs->transnoentitiesnoconv('unit'.$res['code']); } else { $label = $outputlangs->trans('unit'.$res['code']); } } } } $this->db->free($resql); return $label; } /** * Empty function to prevent errors on call of this function. Must be overload if useful * * @param string $sortorder Sort Order * @param string $sortfield Sort field * @param int $limit Limit the number of lines returned * @param int $offset Offset * @param string|string[] $filter Filter as an Universal Search string. * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' * @param string $filtermode No more used * @return self[]|int<-1,-1> int <0 if KO, array of pages if OK */ public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND') { return -1; // NOK because nothing done. } /** * Return clickable link of object line (optionally with picto) * May (should) also return information about the associated "parent" object. * To overload * * @param int $withpicto Add picto into link * @return string String with URL */ public function getNomUrl($withpicto = 0) { $parentattribute = $this->fk_parent_attribute; /* if ($parentattribute) { return 'Parent #'.$this->$parentattribute.' - Line #'.$this->id; } else { return 'Line #'.$this->id; } */ $parent_element_properties = getElementProperties($this->parent_element); $parent_classname = $parent_element_properties['classname']; $parent_element = new $parent_classname($this->db); /** @var CommonObject $parent_element */ $parentattribute = $this->fk_parent_attribute; if ($parentattribute && method_exists($parent_element, 'fetch')) { $parent_element->fetch($this->$parentattribute); // @phan-suppress-current-line PhanPluginUnknownObjectMethodCall } return $parent_element->getNomUrl($withpicto).' - Line #'.$this->id; // @phan-suppress-current-line PhanPluginUnknownObjectMethodCall } }