forked from Wavyzz/dolibarr
# Qual: Update fields phpdoc to include fields that are defined/used in some cases comment, copytoclipboard, autofocusoncreated are documented and used in some cases for the $fields definition
1041 lines
34 KiB
PHP
1041 lines
34 KiB
PHP
<?php
|
|
/* Copyright (C) 2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
|
|
* Copyright (C) 2004-2012 Destailleur Laurent <eldy@users.sourceforge.net>
|
|
* Copyright (C) 2005-2014 Regis Houssin <regis.houssin@inodbox.com>
|
|
* Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
|
|
* Copyright (C) 2008 Raphael Bertrand <raphael.bertrand@resultic.fr>
|
|
* Copyright (C) 2010-2016 Juanjo Menent <jmenent@2byte.es>
|
|
* Copyright (C) 2013 Christophe Battarel <christophe.battarel@altairis.fr>
|
|
* Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
|
|
* Copyright (C) 2014-2015 Marcos García <marcosgdf@gmail.com>
|
|
* Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
|
|
* Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
|
|
* Copyright (C) 2015-2018 Ferran Marcet <fmarcet@2byte.es>
|
|
* Copyright (C) 2024 William Mead <william.mead@manchenumerique.fr>
|
|
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
|
|
*
|
|
* 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 <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/**
|
|
* \file htdocs/contrat/class/contratligne.class.php
|
|
* \ingroup contrat
|
|
* \brief File of class to manage contract lines
|
|
*/
|
|
|
|
require_once DOL_DOCUMENT_ROOT."/core/class/commonobjectline.class.php";
|
|
require_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/margin/lib/margins.lib.php';
|
|
|
|
/**
|
|
* Class to manage lines of contracts
|
|
*/
|
|
class ContratLigne extends CommonObjectLine
|
|
{
|
|
/**
|
|
* @var string ID to identify managed object
|
|
*/
|
|
public $element = 'contratdet';
|
|
|
|
/**
|
|
* @var string Name of table without prefix where object is stored
|
|
*/
|
|
public $table_element = 'contratdet';
|
|
|
|
/**
|
|
* @see CommonObjectLine
|
|
*/
|
|
public $parent_element = 'contrat';
|
|
|
|
/**
|
|
* @see CommonObjectLine
|
|
*/
|
|
public $fk_parent_attribute = 'fk_contrat';
|
|
|
|
/**
|
|
* @var string Name to use for 'features' parameter to check module permissions user->rights->feature with restrictedArea().
|
|
* Undefined means same value than $element. Can be use to force a check on another element for example for class of line, we mention here the parent element.
|
|
*/
|
|
public $element_for_permission = 'contrat';
|
|
|
|
/**
|
|
* @var int ID
|
|
*/
|
|
public $id;
|
|
|
|
/**
|
|
* @var string Ref
|
|
*/
|
|
public $ref;
|
|
|
|
/**
|
|
* @var int ID
|
|
*/
|
|
public $fk_contrat;
|
|
|
|
/**
|
|
* @var int ID
|
|
*/
|
|
public $fk_product;
|
|
|
|
/**
|
|
* @var int 0 inactive, 4 active, 5 closed
|
|
*/
|
|
public $statut;
|
|
|
|
/**
|
|
* @var int 0 for product, 1 for service
|
|
*/
|
|
public $type;
|
|
|
|
/**
|
|
* @var string
|
|
* @deprecated
|
|
*/
|
|
public $label;
|
|
|
|
/**
|
|
* @var string
|
|
* @deprecated
|
|
*/
|
|
public $libelle;
|
|
|
|
/**
|
|
* @var string description
|
|
*/
|
|
public $description;
|
|
|
|
/**
|
|
* @var int 0 for product, 1 for service
|
|
*/
|
|
public $product_type;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
public $product_ref;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
public $product_label;
|
|
|
|
/**
|
|
* @var int|string
|
|
*/
|
|
public $date_commande;
|
|
|
|
/**
|
|
* @var int|string date start planned
|
|
*/
|
|
public $date_start;
|
|
|
|
/**
|
|
* @var int|string date start real
|
|
*/
|
|
public $date_start_real;
|
|
|
|
/**
|
|
* @var int|string date end planned
|
|
*/
|
|
public $date_end;
|
|
|
|
/**
|
|
* @var null|int|string date end real
|
|
*/
|
|
public $date_end_real;
|
|
|
|
/**
|
|
* @var float|string
|
|
*/
|
|
public $tva_tx;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
public $vat_src_code;
|
|
|
|
/**
|
|
* @var string|float
|
|
*/
|
|
public $localtax1_tx;
|
|
|
|
/**
|
|
* @var string|float
|
|
*/
|
|
public $localtax2_tx;
|
|
|
|
/**
|
|
* @var string Local tax 1 type
|
|
*/
|
|
public $localtax1_type;
|
|
|
|
/**
|
|
* @var string Local tax 2 type
|
|
*/
|
|
public $localtax2_type;
|
|
|
|
/**
|
|
* @var float
|
|
*/
|
|
public $qty;
|
|
|
|
/**
|
|
* @var float|string
|
|
*/
|
|
public $remise_percent;
|
|
|
|
/**
|
|
* @var float|string
|
|
* @deprecated
|
|
*/
|
|
public $remise;
|
|
|
|
/**
|
|
* @var int ID
|
|
*/
|
|
public $fk_remise_except;
|
|
|
|
/**
|
|
* Unit price before taxes
|
|
* @var float
|
|
*/
|
|
public $subprice;
|
|
|
|
/**
|
|
* @var float
|
|
* @deprecated Use $price_ht instead
|
|
* @see $price_ht
|
|
*/
|
|
public $price;
|
|
|
|
/**
|
|
* @var float price without tax
|
|
*/
|
|
public $price_ht;
|
|
|
|
/**
|
|
* @var float
|
|
*/
|
|
public $total_ht;
|
|
|
|
/**
|
|
* @var float
|
|
*/
|
|
public $total_tva;
|
|
|
|
/**
|
|
* @var float
|
|
*/
|
|
public $total_localtax1;
|
|
|
|
/**
|
|
* @var float
|
|
*/
|
|
public $total_localtax2;
|
|
|
|
/**
|
|
* @var float
|
|
*/
|
|
public $total_ttc;
|
|
|
|
/**
|
|
* @var int ID
|
|
*/
|
|
public $fk_fournprice;
|
|
|
|
/**
|
|
* @var float
|
|
*/
|
|
public $pa_ht;
|
|
|
|
/**
|
|
* @var int Info bits
|
|
*/
|
|
public $info_bits;
|
|
|
|
/**
|
|
* @var int ID of user that insert the service
|
|
*/
|
|
public $fk_user_author;
|
|
|
|
/**
|
|
* @var int ID of user opening the service
|
|
*/
|
|
public $fk_user_ouverture;
|
|
|
|
/**
|
|
* @var int ID of user closing the service
|
|
*/
|
|
public $fk_user_cloture;
|
|
|
|
/**
|
|
* @var string Comment
|
|
*/
|
|
public $commentaire;
|
|
|
|
|
|
/**
|
|
* @var int line rank
|
|
*/
|
|
public $rang = 0;
|
|
|
|
|
|
const STATUS_INITIAL = 0;
|
|
const STATUS_OPEN = 4;
|
|
const STATUS_CLOSED = 5;
|
|
|
|
|
|
// BEGIN MODULEBUILDER PROPERTIES
|
|
/**
|
|
* @var array<string,array{type:string,label:string,enabled:int<0,2>|string,position:int,notnull?:int,visible:int<-5,5>|string,alwayseditable?:int<0,1>,noteditable?:int<0,1>,default?:string,index?:int,foreignkey?:string,searchall?:int<0,1>,isameasure?:int<0,1>,css?:string,csslist?:string,help?:string,showoncombobox?:int<0,4>,disabled?:int<0,1>,arrayofkeyval?:array<int|string,string>,autofocusoncreate?:int<0,1>,comment?:string,copytoclipboard?:int<1,2>,validate?:int<0,1>,showonheader?:int<0,1>}> Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
|
|
*/
|
|
public $fields = array(
|
|
'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10),
|
|
'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 30, 'index' => 1),
|
|
'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 35),
|
|
'qty' => array('type' => 'integer', 'label' => 'Quantity', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'position' => 35, 'isameasure' => 1),
|
|
'total_ht' => array('type' => 'integer', 'label' => 'AmountHT', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 36, 'isameasure' => 1),
|
|
'total_tva' => array('type' => 'integer', 'label' => 'AmountVAT', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 37, 'isameasure' => 1),
|
|
'total_ttc' => array('type' => 'integer', 'label' => 'AmountTTC', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 38, 'isameasure' => 1),
|
|
//'datec' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'position'=>40),
|
|
//'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>70),
|
|
'fk_contrat' => array('type' => 'integer:Contrat:contrat/class/contrat.class.php', 'label' => 'Contract', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 70),
|
|
'fk_product' => array('type' => 'integer:Product:product/class/product.class.php:1', 'label' => 'Product', 'enabled' => 1, 'visible' => -1, 'position' => 75),
|
|
//'fk_user_author' =>array('type'=>'integer:User:user/class/user.class.php', 'label'=>'Fk user author', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>90),
|
|
'note_private' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 105),
|
|
'note_public' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 110),
|
|
//'model_pdf' =>array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>1, 'visible'=>0, 'position'=>115),
|
|
//'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>120),
|
|
//'extraparams' =>array('type'=>'varchar(255)', 'label'=>'Extraparams', 'enabled'=>1, 'visible'=>-1, 'position'=>125),
|
|
'fk_user_ouverture' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserStartingService', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 135),
|
|
'fk_user_cloture' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserClosingService', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 135),
|
|
'statut' => array('type' => 'smallint(6)', 'label' => 'Statut', 'enabled' => 1, 'visible' => -1, 'position' => 500, 'arrayofkeyval' => array(0 => 'Draft', 4 => 'Open', 5 => 'Closed')),
|
|
'rang' => array('type' => 'integer', 'label' => 'Rank', 'enabled' => 1, 'visible' => 0, 'position' => 500, 'default' => '0')
|
|
);
|
|
// END MODULEBUILDER PROPERTIES
|
|
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param DoliDB $db Database handler
|
|
*/
|
|
public function __construct($db)
|
|
{
|
|
$this->db = $db;
|
|
}
|
|
|
|
|
|
/**
|
|
* Return label of this contract line status
|
|
*
|
|
* @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
|
|
* @return string Label of status
|
|
*/
|
|
public function getLibStatut($mode)
|
|
{
|
|
return $this->LibStatut($this->statut, $mode, ((!empty($this->date_end)) ? ($this->date_end < dol_now() ? 1 : 0) : -1));
|
|
}
|
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
/**
|
|
* Return label of a contract line status
|
|
*
|
|
* @param int $status Id status
|
|
* @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
|
|
* @param int $expired 0=Not expired, 1=Expired, -1=Both or unknown
|
|
* @param string $moreatt More attribute
|
|
* @param string $morelabel More label
|
|
* @return string Label of status
|
|
*/
|
|
public static function LibStatut($status, $mode, $expired = -1, $moreatt = '', $morelabel = '')
|
|
{
|
|
// phpcs:enable
|
|
global $langs;
|
|
$langs->load("contracts");
|
|
|
|
if ($status == self::STATUS_INITIAL) {
|
|
$labelStatus = $langs->transnoentities("ServiceStatusInitial");
|
|
$labelStatusShort = $langs->transnoentities("ServiceStatusInitial");
|
|
} elseif ($status == self::STATUS_OPEN && $expired == -1) {
|
|
$labelStatus = $langs->transnoentities("ServiceStatusRunning");
|
|
$labelStatusShort = $langs->transnoentities("ServiceStatusRunning");
|
|
} elseif ($status == self::STATUS_OPEN && $expired == 0) {
|
|
$labelStatus = $langs->transnoentities("ServiceStatusNotLate");
|
|
$labelStatusShort = $langs->transnoentities("ServiceStatusNotLateShort");
|
|
} elseif ($status == self::STATUS_OPEN && $expired == 1) {
|
|
$labelStatus = $langs->transnoentities("ServiceStatusLate");
|
|
$labelStatusShort = $langs->transnoentities("ServiceStatusLateShort");
|
|
} elseif ($status == self::STATUS_CLOSED) {
|
|
$labelStatus = $langs->transnoentities("ServiceStatusClosed");
|
|
$labelStatusShort = $langs->transnoentities("ServiceStatusClosed");
|
|
} else {
|
|
$labelStatus = '';
|
|
$labelStatusShort = '';
|
|
}
|
|
|
|
$statusType = 'status'.$status;
|
|
if ($status == self::STATUS_OPEN && $expired == 1) {
|
|
$statusType = 'status1';
|
|
}
|
|
if ($status == self::STATUS_CLOSED) {
|
|
$statusType = 'status6';
|
|
}
|
|
|
|
$params = array();
|
|
$reg = array();
|
|
if (preg_match('/class="(.*)"/', $moreatt, $reg)) {
|
|
$params = array('badgeParams' => array('css' => $reg[1]));
|
|
}
|
|
return dolGetStatus($labelStatus.($morelabel ? ' '.$morelabel : ''), $labelStatusShort.($morelabel ? ' '.$morelabel : ''), '', $statusType, $mode, '', $params);
|
|
}
|
|
|
|
/**
|
|
* getTooltipContentArray
|
|
* @param array<string,mixed> $params params to construct tooltip data
|
|
* @since v18
|
|
* @return array<string,string>
|
|
*/
|
|
public function getTooltipContentArray($params)
|
|
{
|
|
global $conf, $langs, $user;
|
|
|
|
$datas = [];
|
|
$datas['label'] = $langs->trans("ShowContractOfService").': '.$this->label;
|
|
if (empty($datas['label'])) {
|
|
$datas['label'] = $this->description;
|
|
}
|
|
|
|
return $datas;
|
|
}
|
|
|
|
/**
|
|
* Return clickable name (with picto eventually) for ContratLigne
|
|
*
|
|
* @param int $withpicto 0=No picto, 1=Include picto into link, 2=Only picto
|
|
* @param int $maxlength Max length
|
|
* @return string Chaine avec URL
|
|
*/
|
|
public function getNomUrl($withpicto = 0, $maxlength = 0)
|
|
{
|
|
global $langs;
|
|
|
|
$result = '';
|
|
$label = $langs->trans("ShowContractOfService").': '.$this->label;
|
|
if (empty($label)) {
|
|
$label = $this->description;
|
|
}
|
|
$classfortooltip = 'classfortooltip';
|
|
$dataparams = '';
|
|
if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
|
|
$params = [
|
|
'id' => $this->fk_contrat,
|
|
'objecttype' => $this->element,
|
|
];
|
|
$classfortooltip = 'classforajaxtooltip';
|
|
$dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
|
|
$label = '';
|
|
}
|
|
|
|
$link = '<a href="'.DOL_URL_ROOT.'/contrat/card.php?id='.$this->fk_contrat.'"';
|
|
$link .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
|
|
$link .= $dataparams.' class="'.$classfortooltip.'">';
|
|
$linkend = '</a>';
|
|
|
|
$picto = 'service';
|
|
if ($this->type == 0) {
|
|
$picto = 'product';
|
|
}
|
|
|
|
if ($withpicto) {
|
|
$result .= ($link.img_object($label, $picto, $dataparams.' class="'.$classfortooltip.'"').$linkend);
|
|
}
|
|
if ($withpicto && $withpicto != 2) {
|
|
$result .= ' ';
|
|
}
|
|
if ($withpicto != 2) {
|
|
$result .= $link.($this->product_ref ? $this->product_ref.' ' : '').($this->label ? $this->label : $this->description).$linkend;
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Load object in memory from database
|
|
*
|
|
* @param int $id Id object
|
|
* @param string $ref Ref of contract line
|
|
* @return int Return integer <0 if KO, >0 if OK
|
|
*/
|
|
public function fetch($id, $ref = '')
|
|
{
|
|
// Check parameters
|
|
if (empty($id) && empty($ref)) {
|
|
return -1;
|
|
}
|
|
|
|
$sql = "SELECT";
|
|
$sql .= " t.rowid,";
|
|
$sql .= " t.tms,";
|
|
$sql .= " t.fk_contrat,";
|
|
$sql .= " t.fk_product,";
|
|
$sql .= " t.statut,";
|
|
$sql .= " t.label,"; // This field is not used. Only label of product
|
|
$sql .= " p.ref as product_ref,";
|
|
$sql .= " p.label as product_label,";
|
|
$sql .= " p.description as product_desc,";
|
|
$sql .= " p.fk_product_type as product_type,";
|
|
$sql .= " t.description,";
|
|
$sql .= " t.date_commande,";
|
|
$sql .= " t.date_ouverture_prevue as date_start,";
|
|
$sql .= " t.date_ouverture as date_start_real,";
|
|
$sql .= " t.date_fin_validite as date_end,";
|
|
$sql .= " t.date_cloture as date_end_real,";
|
|
$sql .= " t.tva_tx,";
|
|
$sql .= " t.vat_src_code,";
|
|
$sql .= " t.localtax1_tx,";
|
|
$sql .= " t.localtax2_tx,";
|
|
$sql .= " t.localtax1_type,";
|
|
$sql .= " t.localtax2_type,";
|
|
$sql .= " t.qty,";
|
|
$sql .= " t.remise_percent,";
|
|
$sql .= " t.remise,";
|
|
$sql .= " t.fk_remise_except,";
|
|
$sql .= " t.subprice,";
|
|
$sql .= " t.price_ht,";
|
|
$sql .= " t.total_ht,";
|
|
$sql .= " t.total_tva,";
|
|
$sql .= " t.total_localtax1,";
|
|
$sql .= " t.total_localtax2,";
|
|
$sql .= " t.total_ttc,";
|
|
$sql .= " t.fk_product_fournisseur_price as fk_fournprice,";
|
|
$sql .= " t.buy_price_ht as pa_ht,";
|
|
$sql .= " t.info_bits,";
|
|
$sql .= " t.fk_user_author,";
|
|
$sql .= " t.fk_user_ouverture,";
|
|
$sql .= " t.fk_user_cloture,";
|
|
$sql .= " t.commentaire,";
|
|
$sql .= " t.fk_unit,";
|
|
$sql .= " t.rang";
|
|
$sql .= " FROM ".MAIN_DB_PREFIX."contratdet as t LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = t.fk_product";
|
|
if ($id) {
|
|
$sql .= " WHERE t.rowid = ".((int) $id);
|
|
}
|
|
if ($ref) {
|
|
$sql .= " WHERE t.rowid = '".$this->db->escape($ref)."'";
|
|
}
|
|
|
|
dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
|
|
$resql = $this->db->query($sql);
|
|
if ($resql) {
|
|
if ($this->db->num_rows($resql)) {
|
|
$obj = $this->db->fetch_object($resql);
|
|
|
|
$this->id = $obj->rowid;
|
|
$this->ref = $obj->rowid;
|
|
|
|
$this->tms = $this->db->jdate($obj->tms);
|
|
$this->fk_contrat = $obj->fk_contrat;
|
|
$this->fk_product = $obj->fk_product;
|
|
$this->statut = $obj->statut;
|
|
$this->product_ref = $obj->product_ref;
|
|
$this->product_label = $obj->product_label;
|
|
$this->product_type = $obj->product_type;
|
|
$this->label = $obj->label; // deprecated. We do not use this field. Only ref and label of product, and description of contract line
|
|
$this->description = $obj->description;
|
|
$this->date_commande = $this->db->jdate($obj->date_commande);
|
|
|
|
$this->date_start = $this->db->jdate($obj->date_start);
|
|
$this->date_start_real = $this->db->jdate($obj->date_start_real);
|
|
$this->date_end = $this->db->jdate($obj->date_end);
|
|
$this->date_end_real = $this->db->jdate($obj->date_end_real);
|
|
// For backward compatibility
|
|
//$this->date_ouverture_prevue = $this->db->jdate($obj->date_ouverture_prevue);
|
|
//$this->date_ouverture = $this->db->jdate($obj->date_ouverture);
|
|
//$this->date_fin_validite = $this->db->jdate($obj->date_fin_validite);
|
|
//$this->date_cloture = $this->db->jdate($obj->date_cloture);
|
|
|
|
$this->tva_tx = $obj->tva_tx;
|
|
$this->vat_src_code = $obj->vat_src_code;
|
|
$this->localtax1_tx = $obj->localtax1_tx;
|
|
$this->localtax2_tx = $obj->localtax2_tx;
|
|
$this->localtax1_type = $obj->localtax1_type;
|
|
$this->localtax2_type = $obj->localtax2_type;
|
|
$this->qty = $obj->qty;
|
|
$this->remise_percent = $obj->remise_percent;
|
|
$this->fk_remise_except = $obj->fk_remise_except;
|
|
$this->subprice = $obj->subprice;
|
|
$this->price_ht = $obj->price_ht;
|
|
$this->total_ht = $obj->total_ht;
|
|
$this->total_tva = $obj->total_tva;
|
|
$this->total_localtax1 = $obj->total_localtax1;
|
|
$this->total_localtax2 = $obj->total_localtax2;
|
|
$this->total_ttc = $obj->total_ttc;
|
|
$this->info_bits = $obj->info_bits;
|
|
$this->fk_user_author = $obj->fk_user_author;
|
|
$this->fk_user_ouverture = $obj->fk_user_ouverture;
|
|
$this->fk_user_cloture = $obj->fk_user_cloture;
|
|
$this->commentaire = $obj->commentaire;
|
|
$this->fk_fournprice = $obj->fk_fournprice;
|
|
|
|
$marginInfos = getMarginInfos($obj->subprice, $obj->remise_percent, $obj->tva_tx, $obj->localtax1_tx, $obj->localtax2_tx, $this->fk_fournprice, $obj->pa_ht);
|
|
$this->pa_ht = $marginInfos[0];
|
|
$this->fk_unit = $obj->fk_unit;
|
|
|
|
$this->rang = $obj->rang;
|
|
|
|
$this->fetch_optionals();
|
|
}
|
|
|
|
$this->db->free($resql);
|
|
|
|
return 1;
|
|
} else {
|
|
$this->error = "Error ".$this->db->lasterror();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Update database for contract line
|
|
*
|
|
* @param User $user User that modify
|
|
* @param int $notrigger 0=no, 1=yes (no update trigger)
|
|
* @return int Return integer <0 if KO, >0 if OK
|
|
*/
|
|
public function update($user, $notrigger = 0)
|
|
{
|
|
global $mysoc;
|
|
|
|
$error = 0;
|
|
|
|
// Clean parameters
|
|
$this->fk_contrat = (int) $this->fk_contrat;
|
|
$this->fk_product = (int) $this->fk_product;
|
|
$this->statut = (int) $this->statut;
|
|
$this->label = trim($this->label);
|
|
$this->description = trim($this->description);
|
|
$this->vat_src_code = trim($this->vat_src_code);
|
|
$this->tva_tx = trim((string) $this->tva_tx);
|
|
$this->localtax1_tx = trim($this->localtax1_tx);
|
|
$this->localtax2_tx = trim($this->localtax2_tx);
|
|
$this->qty = (float) $this->qty;
|
|
$this->remise_percent = trim((string) $this->remise_percent);
|
|
$this->fk_remise_except = (int) $this->fk_remise_except;
|
|
$this->subprice = (float) price2num($this->subprice);
|
|
$this->price_ht = (float) price2num($this->price_ht);
|
|
$this->info_bits = (int) $this->info_bits;
|
|
$this->fk_user_author = (int) $this->fk_user_author;
|
|
$this->fk_user_ouverture = (int) $this->fk_user_ouverture;
|
|
$this->fk_user_cloture = (int) $this->fk_user_cloture;
|
|
$this->commentaire = trim($this->commentaire);
|
|
$this->rang = (int) $this->rang;
|
|
//if (empty($this->subprice)) $this->subprice = 0;
|
|
if (empty($this->price_ht)) {
|
|
$this->price_ht = 0;
|
|
}
|
|
if (empty($this->total_ht)) {
|
|
$this->total_ht = 0;
|
|
}
|
|
if (empty($this->total_tva)) {
|
|
$this->total_tva = 0;
|
|
}
|
|
if (empty($this->total_ttc)) {
|
|
$this->total_ttc = 0;
|
|
}
|
|
if (empty($this->localtax1_tx)) {
|
|
$this->localtax1_tx = 0;
|
|
}
|
|
if (empty($this->localtax2_tx)) {
|
|
$this->localtax2_tx = 0;
|
|
}
|
|
if (empty($this->remise_percent)) {
|
|
$this->remise_percent = 0;
|
|
}
|
|
|
|
// Calcul du total TTC et de la TVA pour la ligne a partir de
|
|
// qty, pu, remise_percent et txtva
|
|
// TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
|
|
// la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
|
|
$localtaxes_type = getLocalTaxesFromRate($this->tva_tx, 0, $this->thirdparty, $mysoc);
|
|
|
|
$tabprice = calcul_price_total($this->qty, $this->price_ht, $this->remise_percent, $this->tva_tx, $this->localtax1_tx, $this->localtax2_tx, 0, 'HT', 0, 1, $mysoc, $localtaxes_type);
|
|
$this->total_ht = (float) $tabprice[0];
|
|
$this->total_tva = (float) $tabprice[1];
|
|
$this->total_ttc = (float) $tabprice[2];
|
|
$this->total_localtax1 = (float) $tabprice[9];
|
|
$this->total_localtax2 = (float) $tabprice[10];
|
|
|
|
if (empty($this->pa_ht)) {
|
|
$this->pa_ht = 0;
|
|
}
|
|
|
|
// if buy price not defined, define buyprice as configured in margin admin
|
|
if ($this->pa_ht == 0) {
|
|
$result = $this->defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product);
|
|
if ($result < 0) {
|
|
return -1;
|
|
} else {
|
|
$this->pa_ht = $result;
|
|
}
|
|
}
|
|
|
|
// $this->oldcopy should have been set by the caller of update (here properties were already modified)
|
|
if (empty($this->oldcopy)) {
|
|
dol_syslog("this->oldcopy should have been set by the caller of update (here properties were already modified)", LOG_WARNING);
|
|
$this->oldcopy = dol_clone($this, 2);
|
|
}
|
|
|
|
$this->db->begin();
|
|
|
|
// Update request
|
|
$sql = "UPDATE ".MAIN_DB_PREFIX."contratdet SET";
|
|
$sql .= " fk_contrat = ".((int) $this->fk_contrat).",";
|
|
$sql .= " fk_product = ".($this->fk_product ? ((int) $this->fk_product) : 'null').",";
|
|
$sql .= " statut = ".((int) $this->statut).",";
|
|
$sql .= " label = '".$this->db->escape($this->label)."',";
|
|
$sql .= " description = '".$this->db->escape($this->description)."',";
|
|
$sql .= " date_commande = ".($this->date_commande != '' ? "'".$this->db->idate($this->date_commande)."'" : "null").",";
|
|
$sql .= " date_ouverture_prevue = ".($this->date_start != '' ? "'".$this->db->idate($this->date_start)."'" : "null").",";
|
|
$sql .= " date_ouverture = ".($this->date_start_real != '' ? "'".$this->db->idate($this->date_start_real)."'" : "null").",";
|
|
$sql .= " date_fin_validite = ".($this->date_end != '' ? "'".$this->db->idate($this->date_end)."'" : "null").",";
|
|
$sql .= " date_cloture = ".($this->date_end_real != '' ? "'".$this->db->idate($this->date_end_real)."'" : "null").",";
|
|
$sql .= " vat_src_code = '".$this->db->escape($this->vat_src_code)."',";
|
|
$sql .= " tva_tx = ".price2num($this->tva_tx).",";
|
|
$sql .= " localtax1_tx = ".price2num($this->localtax1_tx).",";
|
|
$sql .= " localtax2_tx = ".price2num($this->localtax2_tx).",";
|
|
$sql .= " qty = ".price2num($this->qty).",";
|
|
$sql .= " remise_percent = ".price2num($this->remise_percent).",";
|
|
$sql .= " remise = ".($this->remise ? price2num($this->remise) : "null").",";
|
|
$sql .= " fk_remise_except = ".($this->fk_remise_except > 0 ? $this->fk_remise_except : "null").",";
|
|
$sql .= " subprice = ".($this->subprice != '' ? $this->subprice : "null").",";
|
|
$sql .= " price_ht = ".($this->price_ht != '' ? $this->price_ht : "null").",";
|
|
$sql .= " total_ht = ".((float) $this->total_ht).",";
|
|
$sql .= " total_tva = ".((float) $this->total_tva).",";
|
|
$sql .= " total_localtax1 = ".((float) $this->total_localtax1).",";
|
|
$sql .= " total_localtax2 = ".((float) $this->total_localtax2).",";
|
|
$sql .= " total_ttc = ".((float) $this->total_ttc).",";
|
|
$sql .= " fk_product_fournisseur_price = ".(!empty($this->fk_fournprice) ? $this->fk_fournprice : "NULL").",";
|
|
$sql .= " buy_price_ht = '".price2num($this->pa_ht)."',";
|
|
$sql .= " info_bits = '".$this->db->escape($this->info_bits)."',";
|
|
$sql .= " fk_user_author = ".($this->fk_user_author >= 0 ? $this->fk_user_author : "NULL").",";
|
|
$sql .= " fk_user_ouverture = ".($this->fk_user_ouverture > 0 ? $this->fk_user_ouverture : "NULL").",";
|
|
$sql .= " fk_user_cloture = ".($this->fk_user_cloture > 0 ? $this->fk_user_cloture : "NULL").",";
|
|
$sql .= " commentaire = '".$this->db->escape($this->commentaire)."',";
|
|
$sql .= " fk_unit = ".(!$this->fk_unit ? 'NULL' : $this->fk_unit).",";
|
|
$sql .= " rang = ".(empty($this->rang) ? '0' : (int) $this->rang);
|
|
$sql .= " WHERE rowid = ".((int) $this->id);
|
|
|
|
dol_syslog(get_class($this)."::update", LOG_DEBUG);
|
|
$resql = $this->db->query($sql);
|
|
if (!$resql) {
|
|
$this->error = "Error ".$this->db->lasterror();
|
|
$error++;
|
|
}
|
|
|
|
if (!$error) { // For avoid conflicts if trigger used
|
|
$result = $this->insertExtraFields();
|
|
if ($result < 0) {
|
|
$error++;
|
|
}
|
|
}
|
|
|
|
// If we change a planned date (start or end) of one contract line, sync dates for all other services too
|
|
if (!$error && getDolGlobalString('CONTRACT_SYNC_PLANNED_DATE_OF_SERVICES')) {
|
|
dol_syslog(get_class($this)."::update CONTRACT_SYNC_PLANNED_DATE_OF_SERVICES is on so we update date for all lines", LOG_DEBUG);
|
|
|
|
if ($this->date_start != $this->oldcopy->date_start) {
|
|
$sql = 'UPDATE '.MAIN_DB_PREFIX.'contratdet SET';
|
|
$sql .= " date_ouverture_prevue = ".($this->date_start != '' ? "'".$this->db->idate($this->date_start)."'" : "null");
|
|
$sql .= " WHERE fk_contrat = ".((int) $this->fk_contrat);
|
|
|
|
$resql = $this->db->query($sql);
|
|
if (!$resql) {
|
|
$error++;
|
|
$this->error = "Error ".$this->db->lasterror();
|
|
}
|
|
}
|
|
if ($this->date_end != $this->oldcopy->date_end) {
|
|
$sql = 'UPDATE '.MAIN_DB_PREFIX.'contratdet SET';
|
|
$sql .= " date_fin_validite = ".($this->date_end != '' ? "'".$this->db->idate($this->date_end)."'" : "null");
|
|
$sql .= " WHERE fk_contrat = ".((int) $this->fk_contrat);
|
|
|
|
$resql = $this->db->query($sql);
|
|
if (!$resql) {
|
|
$error++;
|
|
$this->error = "Error ".$this->db->lasterror();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$error && !$notrigger) {
|
|
// Call trigger
|
|
$result = $this->call_trigger('LINECONTRACT_MODIFY', $user);
|
|
if ($result < 0) {
|
|
$error++;
|
|
$this->db->rollback();
|
|
}
|
|
// End call triggers
|
|
}
|
|
|
|
if (!$error) {
|
|
$this->db->commit();
|
|
return 1;
|
|
} else {
|
|
$this->db->rollback();
|
|
$this->errors[] = $this->error;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
/**
|
|
* Update in database the fields total_xxx of lines
|
|
* Used by migration process
|
|
*
|
|
* @return int Return integer <0 if KO, >0 if OK
|
|
*/
|
|
public function update_total()
|
|
{
|
|
// phpcs:enable
|
|
$this->db->begin();
|
|
|
|
// Mise a jour ligne en base
|
|
$sql = "UPDATE ".MAIN_DB_PREFIX."contratdet SET";
|
|
$sql .= " total_ht=".price2num($this->total_ht, 'MT');
|
|
$sql .= ",total_tva=".price2num($this->total_tva, 'MT');
|
|
$sql .= ",total_localtax1=".price2num($this->total_localtax1, 'MT');
|
|
$sql .= ",total_localtax2=".price2num($this->total_localtax2, 'MT');
|
|
$sql .= ",total_ttc=".price2num($this->total_ttc, 'MT');
|
|
$sql .= " WHERE rowid = ".((int) $this->id);
|
|
|
|
dol_syslog(get_class($this)."::update_total", LOG_DEBUG);
|
|
|
|
$resql = $this->db->query($sql);
|
|
if ($resql) {
|
|
$this->db->commit();
|
|
return 1;
|
|
} else {
|
|
$this->error = $this->db->error();
|
|
$this->db->rollback();
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Inserts a contrat line into database
|
|
*
|
|
* @param int $notrigger Set to 1 if you don't want triggers to be fired
|
|
* @return int Return integer <0 if KO, >0 if OK
|
|
*/
|
|
public function insert($notrigger = 0)
|
|
{
|
|
global $user;
|
|
|
|
$error = 0;
|
|
|
|
// Insertion dans la base
|
|
$sql = "INSERT INTO ".MAIN_DB_PREFIX."contratdet";
|
|
$sql .= " (fk_contrat, label, description, fk_product, qty, vat_src_code, tva_tx,";
|
|
$sql .= " localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, remise_percent, subprice,";
|
|
$sql .= " total_ht, total_tva, total_localtax1, total_localtax2, total_ttc,";
|
|
$sql .= " info_bits,";
|
|
$sql .= " rang,";
|
|
$sql .= " price_ht, remise, fk_product_fournisseur_price, buy_price_ht";
|
|
if ($this->date_start > 0) {
|
|
$sql .= ",date_ouverture_prevue";
|
|
}
|
|
if ($this->date_end > 0) {
|
|
$sql .= ",date_fin_validite";
|
|
}
|
|
$sql .= ") VALUES ($this->fk_contrat, '', '".$this->db->escape($this->description)."',";
|
|
$sql .= ($this->fk_product > 0 ? $this->fk_product : "null").",";
|
|
$sql .= " '".$this->db->escape($this->qty)."',";
|
|
$sql .= " '".$this->db->escape($this->vat_src_code)."',";
|
|
$sql .= " '".$this->db->escape($this->tva_tx)."',";
|
|
$sql .= " '".$this->db->escape($this->localtax1_tx)."',";
|
|
$sql .= " '".$this->db->escape($this->localtax2_tx)."',";
|
|
$sql .= " '".$this->db->escape($this->localtax1_type)."',";
|
|
$sql .= " '".$this->db->escape($this->localtax2_type)."',";
|
|
$sql .= " ".price2num($this->remise_percent).",".price2num($this->subprice).",";
|
|
$sql .= " ".price2num($this->total_ht).",".price2num($this->total_tva).",".price2num($this->total_localtax1).",".price2num($this->total_localtax2).",".price2num($this->total_ttc).",";
|
|
$sql .= " '".$this->db->escape($this->info_bits)."',";
|
|
$sql .= " ".(empty($this->rang) ? '0' : (int) $this->rang).",";
|
|
$sql .= " ".price2num($this->price_ht).",".price2num($this->remise).",";
|
|
if ($this->fk_fournprice > 0) {
|
|
$sql .= ' '.((int) $this->fk_fournprice).',';
|
|
} else {
|
|
$sql .= ' null,';
|
|
}
|
|
if ($this->pa_ht > 0) {
|
|
$sql .= ' '.((float) price2num($this->pa_ht));
|
|
} else {
|
|
$sql .= ' null';
|
|
}
|
|
if ($this->date_start > 0) {
|
|
$sql .= ",'".$this->db->idate($this->date_start)."'";
|
|
}
|
|
if ($this->date_end > 0) {
|
|
$sql .= ",'".$this->db->idate($this->date_end)."'";
|
|
}
|
|
$sql .= ")";
|
|
|
|
dol_syslog(get_class($this)."::insert", LOG_DEBUG);
|
|
|
|
$resql = $this->db->query($sql);
|
|
if ($resql) {
|
|
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'contratdet');
|
|
|
|
// Insert of extrafields
|
|
if (!$error) {
|
|
$result = $this->insertExtraFields();
|
|
if ($result < 0) {
|
|
$this->db->rollback();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (!$notrigger) {
|
|
// Call trigger
|
|
$result = $this->call_trigger('LINECONTRACT_INSERT', $user);
|
|
if ($result < 0) {
|
|
$this->db->rollback();
|
|
return -1;
|
|
}
|
|
// End call triggers
|
|
}
|
|
|
|
$this->db->commit();
|
|
return 1;
|
|
} else {
|
|
$this->db->rollback();
|
|
$this->error = $this->db->error()." sql=".$sql;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
/**
|
|
* Activate a contract line
|
|
*
|
|
* @param User $user Object User who activate contract
|
|
* @param int $date Date real activation
|
|
* @param int|string $date_end Date planned end. Use '-1' to keep it unchanged.
|
|
* @param string $comment A comment typed by user
|
|
* @return int Return integer <0 if KO, >0 if OK
|
|
*/
|
|
public function active_line($user, $date, $date_end = '', $comment = '')
|
|
{
|
|
// phpcs:enable
|
|
$error = 0;
|
|
|
|
$this->db->begin();
|
|
|
|
$this->statut = ContratLigne::STATUS_OPEN;
|
|
$this->date_start_real = $date;
|
|
$this->date_end = $date_end;
|
|
$this->fk_user_ouverture = $user->id;
|
|
$this->date_end_real = null;
|
|
$this->commentaire = $comment;
|
|
|
|
$sql = "UPDATE ".MAIN_DB_PREFIX."contratdet SET statut = ".((int) $this->statut).",";
|
|
$sql .= " date_ouverture = ".(dol_strlen((string) $this->date_start_real) != 0 ? "'".$this->db->idate($this->date_start_real)."'" : "null").",";
|
|
if ($date_end >= 0) {
|
|
$sql .= " date_fin_validite = ".(dol_strlen($this->date_end) != 0 ? "'".$this->db->idate($this->date_end)."'" : "null").",";
|
|
}
|
|
$sql .= " fk_user_ouverture = ".((int) $this->fk_user_ouverture).",";
|
|
$sql .= " date_cloture = null,";
|
|
$sql .= " commentaire = '".$this->db->escape($comment)."'";
|
|
$sql .= " WHERE rowid = ".((int) $this->id)." AND (statut = ".ContratLigne::STATUS_INITIAL." OR statut = ".ContratLigne::STATUS_CLOSED.")";
|
|
|
|
dol_syslog(get_class($this)."::active_line", LOG_DEBUG);
|
|
$resql = $this->db->query($sql);
|
|
if ($resql) {
|
|
// Call trigger
|
|
$result = $this->call_trigger('LINECONTRACT_ACTIVATE', $user);
|
|
if ($result < 0) {
|
|
$error++;
|
|
}
|
|
// End call triggers
|
|
|
|
if (!$error) {
|
|
$this->db->commit();
|
|
return 1;
|
|
} else {
|
|
$this->db->rollback();
|
|
return -1;
|
|
}
|
|
} else {
|
|
$this->error = $this->db->lasterror();
|
|
$this->db->rollback();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
/**
|
|
* Close a contract line
|
|
*
|
|
* @param User $user Object User who close contract
|
|
* @param int $date_end_real Date end
|
|
* @param string $comment A comment typed by user
|
|
* @param int $notrigger 1=Does not execute triggers, 0=Execute triggers
|
|
* @return int Return integer <0 if KO, >0 if OK
|
|
*/
|
|
public function close_line($user, $date_end_real, $comment = '', $notrigger = 0)
|
|
{
|
|
// phpcs:enable
|
|
$this->date_cloture = $date_end_real;
|
|
$this->date_end_real = $date_end_real;
|
|
$this->user_closing_id = $user->id;
|
|
$this->commentaire = $comment;
|
|
|
|
$error = 0;
|
|
|
|
// statut actif : 4
|
|
|
|
$this->db->begin();
|
|
|
|
$sql = "UPDATE ".MAIN_DB_PREFIX."contratdet SET statut = ".((int) ContratLigne::STATUS_CLOSED).",";
|
|
$sql .= " date_cloture = '".$this->db->idate($date_end_real)."',";
|
|
$sql .= " fk_user_cloture = ".((int) $user->id).",";
|
|
$sql .= " commentaire = '".$this->db->escape($comment)."'";
|
|
$sql .= " WHERE rowid = ".((int) $this->id)." AND statut = ".((int) ContratLigne::STATUS_OPEN);
|
|
|
|
$resql = $this->db->query($sql);
|
|
if ($resql) {
|
|
if (!$notrigger) {
|
|
// Call trigger
|
|
$result = $this->call_trigger('LINECONTRACT_CLOSE', $user);
|
|
if ($result < 0) {
|
|
$error++;
|
|
$this->db->rollback();
|
|
return -1;
|
|
}
|
|
// End call triggers
|
|
}
|
|
|
|
$this->db->commit();
|
|
return 1;
|
|
} else {
|
|
$this->error = $this->db->lasterror();
|
|
$this->db->rollback();
|
|
return -1;
|
|
}
|
|
}
|
|
}
|