PageRenderTime 222ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/htdocs/compta/facture/class/facture.class.php

https://github.com/zeert/dolibarr
PHP | 3554 lines | 2564 code | 390 blank | 600 comment | 415 complexity | a54f7a268fdc7be3bdb5ef40d040a10a MD5 | raw file
Possible License(s): LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /* Copyright (C) 2002-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
  4. * Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
  5. * Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
  6. * Copyright (C) 2005 Marc Barilley / Ocebo <marc@ocebo.com>
  7. * Copyright (C) 2005-2012 Regis Houssin <regis@dolibarr.fr>
  8. * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
  9. * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
  10. * Copyright (C) 2010-2011 Juanjo Menent <jmenent@2byte.es>
  11. * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
  12. *
  13. * This program is free software; you can redistribute it and/or modify
  14. * it under the terms of the GNU General Public License as published by
  15. * the Free Software Foundation; either version 2 of the License, or
  16. * (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  25. */
  26. /**
  27. * \file htdocs/compta/facture/class/facture.class.php
  28. * \ingroup facture
  29. * \brief File of class to manage invoices
  30. */
  31. include_once(DOL_DOCUMENT_ROOT."/core/class/commoninvoice.class.php");
  32. require_once(DOL_DOCUMENT_ROOT ."/product/class/product.class.php");
  33. require_once(DOL_DOCUMENT_ROOT ."/societe/class/client.class.php");
  34. require_once(DOL_DOCUMENT_ROOT ."/margin/lib/margins.lib.php");
  35. /**
  36. * Class to manage invoices
  37. */
  38. class Facture extends CommonInvoice
  39. {
  40. public $element='facture';
  41. public $table_element='facture';
  42. public $table_element_line = 'facturedet';
  43. public $fk_element = 'fk_facture';
  44. protected $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
  45. var $id;
  46. //! Id client
  47. var $socid;
  48. //! Objet societe client (to load with fetch_client method)
  49. var $client;
  50. var $author;
  51. var $fk_user_author;
  52. var $fk_user_valid;
  53. //! Invoice date
  54. var $date; // Invoice date
  55. var $date_creation; // Creation date
  56. var $date_validation; // Validation date
  57. var $datem;
  58. var $ref;
  59. var $ref_client;
  60. var $ref_ext;
  61. var $ref_int;
  62. //! 0=Standard invoice, 1=Replacement invoice, 2=Credit note invoice, 3=Deposit invoice, 4=Proforma invoice
  63. var $type=0;
  64. //var $amount;
  65. var $remise_absolue;
  66. var $remise_percent;
  67. var $total_ht=0;
  68. var $total_tva=0;
  69. var $total_ttc=0;
  70. var $note; // deprecated
  71. var $note_private;
  72. var $note_public;
  73. //! 0=draft,
  74. //! 1=validated (need to be paid),
  75. //! 2=classified paid partially (close_code='discount_vat','badcustomer') or completely (close_code=null),
  76. //! 3=classified abandoned and no payment done (close_code='badcustomer','abandon' or 'replaced')
  77. var $statut;
  78. //! Fermeture apres paiement partiel: discount_vat, badcustomer, abandon
  79. //! Fermeture alors que aucun paiement: replaced (si remplace), abandon
  80. var $close_code;
  81. //! Commentaire si mis a paye sans paiement complet
  82. var $close_note;
  83. //! 1 if invoice paid COMPLETELY, 0 otherwise (do not use it anymore, use statut and close_code
  84. var $paye;
  85. //! id of source invoice if replacement invoice or credit note
  86. var $fk_facture_source;
  87. var $origin;
  88. var $origin_id;
  89. var $linked_objects=array();
  90. var $fk_project;
  91. var $date_lim_reglement;
  92. var $cond_reglement_id; // Id in llx_c_paiement
  93. var $cond_reglement_code; // Code in llx_c_paiement
  94. var $mode_reglement_id; // Id in llx_c_paiement
  95. var $mode_reglement_code; // Code in llx_c_paiement
  96. var $modelpdf;
  97. var $products=array(); // deprecated
  98. var $lines=array();
  99. var $line;
  100. var $extraparams=array();
  101. //! Pour board
  102. var $nbtodo;
  103. var $nbtodolate;
  104. var $specimen;
  105. /**
  106. * Constructor
  107. *
  108. * @param DoliDB $db Database handler
  109. */
  110. function __construct($db)
  111. {
  112. $this->db = $db;
  113. }
  114. /**
  115. * Create invoice in database
  116. * Note: this->ref can be set or empty. If empty, we will use "(PROV)"
  117. *
  118. * @param User $user Object user that create
  119. * @param int $notrigger 1=Does not execute triggers, 0 otherwise
  120. * @param int $forceduedate 1=Do not recalculate due date from payment condition but force it with value
  121. * @return int <0 if KO, >0 if OK
  122. */
  123. function create($user,$notrigger=0,$forceduedate=0)
  124. {
  125. global $langs,$conf,$mysoc;
  126. $error=0;
  127. // Clean parameters
  128. if (empty($this->type)) $this->type = 0;
  129. $this->ref_client=trim($this->ref_client);
  130. $this->note=(isset($this->note) ? trim($this->note) : trim($this->note_private)); // deprecated
  131. $this->note_private=(isset($this->note_private) ? trim($this->note_private) : trim($this->note));
  132. $this->note_public=trim($this->note_public);
  133. if (! $this->cond_reglement_id) $this->cond_reglement_id = 0;
  134. if (! $this->mode_reglement_id) $this->mode_reglement_id = 0;
  135. $this->brouillon = 1;
  136. dol_syslog(get_class($this)."::create user=".$user->id);
  137. // Check parameters
  138. if (empty($this->date) || empty($user->id))
  139. {
  140. $this->error="ErrorBadParameter";
  141. dol_syslog(get_class($this)."::create Try to create an invoice with an empty parameter (user, date, ...)", LOG_ERR);
  142. return -3;
  143. }
  144. $soc = new Societe($this->db);
  145. $result=$soc->fetch($this->socid);
  146. if ($result < 0)
  147. {
  148. $this->error="Failed to fetch company";
  149. dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
  150. return -2;
  151. }
  152. $now=dol_now();
  153. $this->db->begin();
  154. // Create invoice from a predefined invoice
  155. if ($this->fac_rec > 0)
  156. {
  157. require_once(DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php');
  158. $_facrec = new FactureRec($this->db);
  159. $result=$_facrec->fetch($this->fac_rec);
  160. $this->fk_project = $_facrec->fk_project;
  161. $this->cond_reglement = $_facrec->cond_reglement_id;
  162. $this->cond_reglement_id = $_facrec->cond_reglement_id;
  163. $this->mode_reglement = $_facrec->mode_reglement_id;
  164. $this->mode_reglement_id = $_facrec->mode_reglement_id;
  165. $this->remise_absolue = $_facrec->remise_absolue;
  166. $this->remise_percent = $_facrec->remise_percent;
  167. // Clean parametres
  168. if (! $this->type) $this->type = 0;
  169. $this->ref_client=trim($this->ref_client);
  170. $this->note=trim($this->note);
  171. $this->note_public=trim($this->note_public);
  172. //if (! $this->remise) $this->remise = 0;
  173. if (! $this->mode_reglement_id) $this->mode_reglement_id = 0;
  174. $this->brouillon = 1;
  175. }
  176. // Define due date if not already defined
  177. $datelim=(empty($forceduedate)?$this->calculate_date_lim_reglement():$forceduedate);
  178. // Insert into database
  179. $socid = $this->socid;
  180. $sql = "INSERT INTO ".MAIN_DB_PREFIX."facture (";
  181. $sql.= " facnumber";
  182. $sql.= ", entity";
  183. $sql.= ", ref_ext";
  184. $sql.= ", type";
  185. $sql.= ", fk_soc";
  186. $sql.= ", datec";
  187. $sql.= ", remise_absolue";
  188. $sql.= ", remise_percent";
  189. $sql.= ", datef";
  190. $sql.= ", note";
  191. $sql.= ", note_public";
  192. $sql.= ", ref_client, ref_int";
  193. $sql.= ", fk_facture_source, fk_user_author, fk_projet";
  194. $sql.= ", fk_cond_reglement, fk_mode_reglement, date_lim_reglement, model_pdf";
  195. $sql.= ")";
  196. $sql.= " VALUES (";
  197. $sql.= "'(PROV)'";
  198. $sql.= ", ".$conf->entity;
  199. $sql.= ", ".($this->ref_ext?"'".$this->db->escape($this->ref_ext)."'":"null");
  200. $sql.= ", '".$this->type."'";
  201. $sql.= ", '".$socid."'";
  202. $sql.= ", '".$this->db->idate($now)."'";
  203. $sql.= ",".($this->remise_absolue>0?$this->remise_absolue:'NULL');
  204. $sql.= ",".($this->remise_percent>0?$this->remise_percent:'NULL');
  205. $sql.= ", '".$this->db->idate($this->date)."'";
  206. $sql.= ",".($this->note_private?"'".$this->db->escape($this->note_private)."'":"null");
  207. $sql.= ",".($this->note_public?"'".$this->db->escape($this->note_public)."'":"null");
  208. $sql.= ",".($this->ref_client?"'".$this->db->escape($this->ref_client)."'":"null");
  209. $sql.= ",".($this->ref_int?"'".$this->db->escape($this->ref_int)."'":"null");
  210. $sql.= ",".($this->fk_facture_source?"'".$this->db->escape($this->fk_facture_source)."'":"null");
  211. $sql.= ",".($user->id > 0 ? "'".$user->id."'":"null");
  212. $sql.= ",".($this->fk_project?$this->fk_project:"null");
  213. $sql.= ','.$this->cond_reglement_id;
  214. $sql.= ",".$this->mode_reglement_id;
  215. $sql.= ", '".$this->db->idate($datelim)."', '".$this->modelpdf."')";
  216. dol_syslog(get_class($this)."::create sql=".$sql);
  217. $resql=$this->db->query($sql);
  218. if ($resql)
  219. {
  220. $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'facture');
  221. // Update ref with new one
  222. $this->ref='(PROV'.$this->id.')';
  223. $sql = 'UPDATE '.MAIN_DB_PREFIX."facture SET facnumber='".$this->ref."' WHERE rowid=".$this->id;
  224. dol_syslog(get_class($this)."::create sql=".$sql);
  225. $resql=$this->db->query($sql);
  226. if (! $resql) $error++;
  227. // Add object linked
  228. if (! $error && $this->id && is_array($this->linked_objects) && ! empty($this->linked_objects))
  229. {
  230. foreach($this->linked_objects as $origin => $origin_id)
  231. {
  232. $ret = $this->add_object_linked($origin, $origin_id);
  233. if (! $ret)
  234. {
  235. dol_print_error($this->db);
  236. $error++;
  237. }
  238. // TODO mutualiser
  239. if ($origin == 'commande')
  240. {
  241. // On recupere les differents contact interne et externe
  242. $order = new Commande($this->db);
  243. $order->id = $origin_id;
  244. // On recupere le commercial suivi propale
  245. $this->userid = $order->getIdcontact('internal', 'SALESREPFOLL');
  246. if ($this->userid)
  247. {
  248. //On passe le commercial suivi commande en commercial suivi paiement
  249. $this->add_contact($this->userid[0], 'SALESREPFOLL', 'internal');
  250. }
  251. // On recupere le contact client facturation commande
  252. $this->contactid = $order->getIdcontact('external', 'BILLING');
  253. if ($this->contactid)
  254. {
  255. //On passe le contact client facturation commande en contact client facturation
  256. $this->add_contact($this->contactid[0], 'BILLING', 'external');
  257. }
  258. }
  259. }
  260. }
  261. /*
  262. * Insert lines of invoices into database
  263. */
  264. if (count($this->lines) && is_object($this->lines[0]))
  265. {
  266. $fk_parent_line = 0;
  267. dol_syslog("There is ".count($this->lines)." lines that are invoice lines objects");
  268. foreach ($this->lines as $i => $val)
  269. {
  270. $newinvoiceline=new FactureLigne($this->db);
  271. $newinvoiceline=$this->lines[$i];
  272. $newinvoiceline->fk_facture=$this->id;
  273. if ($result >= 0 && ($newinvoiceline->info_bits & 0x01) == 0) // We keep only lines with first bit = 0
  274. {
  275. // Reset fk_parent_line for no child products and special product
  276. if (($newinvoiceline->product_type != 9 && empty($newinvoiceline->fk_parent_line)) || $newinvoiceline->product_type == 9) {
  277. $fk_parent_line = 0;
  278. }
  279. $newinvoiceline->fk_parent_line=$fk_parent_line;
  280. $result=$newinvoiceline->insert();
  281. // Defined the new fk_parent_line
  282. if ($result > 0 && $newinvoiceline->product_type == 9) {
  283. $fk_parent_line = $result;
  284. }
  285. }
  286. if ($result < 0)
  287. {
  288. $this->error=$newinvoiceline->error;
  289. $error++;
  290. break;
  291. }
  292. }
  293. }
  294. else
  295. {
  296. $fk_parent_line = 0;
  297. dol_syslog("There is ".count($this->lines)." lines that are array lines");
  298. foreach ($this->lines as $i => $val)
  299. {
  300. if (($this->lines[$i]->info_bits & 0x01) == 0) // We keep only lines with first bit = 0
  301. {
  302. // Reset fk_parent_line for no child products and special product
  303. if (($this->lines[$i]->product_type != 9 && empty($this->lines[$i]->fk_parent_line)) || $this->lines[$i]->product_type == 9) {
  304. $fk_parent_line = 0;
  305. }
  306. $result = $this->addline(
  307. $this->id,
  308. $this->lines[$i]->desc,
  309. $this->lines[$i]->subprice,
  310. $this->lines[$i]->qty,
  311. $this->lines[$i]->tva_tx,
  312. $this->lines[$i]->localtax1_tx,
  313. $this->lines[$i]->localtax2_tx,
  314. $this->lines[$i]->fk_product,
  315. $this->lines[$i]->remise_percent,
  316. $this->lines[$i]->date_start,
  317. $this->lines[$i]->date_end,
  318. $this->lines[$i]->fk_code_ventilation,
  319. $this->lines[$i]->info_bits,
  320. $this->lines[$i]->fk_remise_except,
  321. 'HT',
  322. 0,
  323. $this->lines[$i]->product_type,
  324. $this->lines[$i]->rang,
  325. $this->lines[$i]->special_code,
  326. '',
  327. 0,
  328. $fk_parent_line,
  329. $this->lines[$i]->fk_fournprice,
  330. $this->lines[$i]->pa_ht
  331. );
  332. if ($result < 0)
  333. {
  334. $this->error=$this->db->lasterror();
  335. dol_print_error($this->db);
  336. $this->db->rollback();
  337. return -1;
  338. }
  339. // Defined the new fk_parent_line
  340. if ($result > 0 && $this->lines[$i]->product_type == 9) {
  341. $fk_parent_line = $result;
  342. }
  343. }
  344. }
  345. }
  346. /*
  347. * Insert lines of predefined invoices
  348. */
  349. if (! $error && $this->fac_rec > 0)
  350. {
  351. foreach ($_facrec->lines as $i => $val)
  352. {
  353. if ($_facrec->lines[$i]->fk_product)
  354. {
  355. $prod = new Product($this->db);
  356. $res=$prod->fetch($_facrec->lines[$i]->fk_product);
  357. }
  358. $tva_tx = get_default_tva($mysoc,$soc,$prod->id);
  359. $localtax1_tx=get_localtax($tva_tx,1,$soc);
  360. $localtax2_tx=get_localtax($tva_tx,2,$soc);
  361. $result_insert = $this->addline(
  362. $this->id,
  363. $_facrec->lines[$i]->desc,
  364. $_facrec->lines[$i]->subprice,
  365. $_facrec->lines[$i]->qty,
  366. $tva_tx,
  367. $localtax1_tx,
  368. $localtax2_tx,
  369. $_facrec->lines[$i]->fk_product,
  370. $_facrec->lines[$i]->remise_percent,
  371. '','',0,0,'','HT',0,
  372. $_facrec->lines[$i]->product_type,
  373. $_facrec->lines[$i]->rang,
  374. $_facrec->lines[$i]->special_code
  375. );
  376. if ( $result_insert < 0)
  377. {
  378. $error++;
  379. $this->error=$this->db->error();
  380. break;
  381. }
  382. }
  383. }
  384. if (! $error)
  385. {
  386. $result=$this->update_price(1);
  387. if ($result > 0)
  388. {
  389. // Appel des triggers
  390. include_once(DOL_DOCUMENT_ROOT . "/core/class/interfaces.class.php");
  391. $interface=new Interfaces($this->db);
  392. $result=$interface->run_triggers('BILL_CREATE',$this,$user,$langs,$conf);
  393. if ($result < 0) { $error++; $this->errors=$interface->errors; }
  394. // Fin appel triggers
  395. if (! $error)
  396. {
  397. $this->db->commit();
  398. return $this->id;
  399. }
  400. else
  401. {
  402. $this->db->rollback();
  403. return -4;
  404. }
  405. }
  406. else
  407. {
  408. $this->error=$langs->trans('FailedToUpdatePrice');
  409. $this->db->rollback();
  410. return -3;
  411. }
  412. }
  413. else
  414. {
  415. dol_syslog(get_class($this)."::create error ".$this->error, LOG_ERR);
  416. $this->db->rollback();
  417. return -2;
  418. }
  419. }
  420. else
  421. {
  422. $this->error=$this->db->error();
  423. dol_syslog(get_class($this)."::create error ".$this->error." sql=".$sql, LOG_ERR);
  424. $this->db->rollback();
  425. return -1;
  426. }
  427. }
  428. /**
  429. * Create a new invoice in database from current invoice
  430. *
  431. * @param User $user Object user that ask creation
  432. * @param int $invertdetail Reverse sign of amounts for lines
  433. * @return int <0 if KO, >0 if OK
  434. */
  435. function createFromCurrent($user,$invertdetail=0)
  436. {
  437. // Charge facture source
  438. $facture=new Facture($this->db);
  439. $facture->fk_facture_source = $this->fk_facture_source;
  440. $facture->type = $this->type;
  441. $facture->socid = $this->socid;
  442. $facture->date = $this->date;
  443. $facture->note_public = $this->note_public;
  444. $facture->note = $this->note;
  445. $facture->ref_client = $this->ref_client;
  446. $facture->modelpdf = $this->modelpdf;
  447. $facture->fk_project = $this->fk_project;
  448. $facture->cond_reglement_id = $this->cond_reglement_id;
  449. $facture->mode_reglement_id = $this->mode_reglement_id;
  450. $facture->remise_absolue = $this->remise_absolue;
  451. $facture->remise_percent = $this->remise_percent;
  452. $facture->lines = $this->lines; // Tableau des lignes de factures
  453. $facture->products = $this->lines; // Tant que products encore utilise
  454. // Loop on each line of new invoice
  455. foreach($facture->lines as $i => $line)
  456. {
  457. if ($invertdetail)
  458. {
  459. $facture->lines[$i]->subprice = -$facture->lines[$i]->subprice;
  460. //$facture->lines[$i]->price = -$facture->lines[$i]->price;
  461. $facture->lines[$i]->total_ht = -$facture->lines[$i]->total_ht;
  462. $facture->lines[$i]->total_tva = -$facture->lines[$i]->total_tva;
  463. $facture->lines[$i]->total_localtax1 = -$facture->lines[$i]->total_localtax1;
  464. $facture->lines[$i]->total_localtax2 = -$facture->lines[$i]->total_localtax2;
  465. $facture->lines[$i]->total_ttc = -$facture->lines[$i]->total_ttc;
  466. }
  467. }
  468. dol_syslog(get_class($this)."::createFromCurrent invertdetail=".$invertdetail." socid=".$this->socid." nboflines=".count($facture->lines));
  469. $facid = $facture->create($user);
  470. if ($facid <= 0)
  471. {
  472. $this->error=$facture->error;
  473. $this->errors=$facture->errors;
  474. }
  475. return $facid;
  476. }
  477. /**
  478. * Load an object from its id and create a new one in database
  479. *
  480. * @param int $socid Id of thirdparty
  481. * @param HookManager $hookmanager Hook manager instance
  482. * @return int New id of clone
  483. */
  484. function createFromClone($socid=0,$hookmanager=false)
  485. {
  486. global $conf,$user,$langs;
  487. $error=0;
  488. $this->db->begin();
  489. // Load source object
  490. $objFrom = dol_clone($this);
  491. // Change socid if needed
  492. if (! empty($socid) && $socid != $this->socid)
  493. {
  494. $objsoc = new Societe($this->db);
  495. if ($objsoc->fetch($socid)>0)
  496. {
  497. $this->socid = $objsoc->id;
  498. $this->cond_reglement_id = (! empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
  499. $this->mode_reglement_id = (! empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
  500. $this->fk_project = '';
  501. $this->fk_delivery_address = '';
  502. }
  503. // TODO Change product price if multi-prices
  504. }
  505. $this->id=0;
  506. $this->statut=0;
  507. // Clear fields
  508. $this->user_author = $user->id;
  509. $this->user_valid = '';
  510. $this->fk_facture_source = 0;
  511. $this->date_creation = '';
  512. $this->date_validation = '';
  513. $this->ref_client = '';
  514. $this->close_code = '';
  515. $this->close_note = '';
  516. $this->products = $this->lines; // Tant que products encore utilise
  517. // Loop on each line of new invoice
  518. foreach($this->lines as $i => $line)
  519. {
  520. if (($this->lines[$i]->info_bits & 0x02) == 0x02) // We do not clone line of discounts
  521. {
  522. unset($this->lines[$i]);
  523. unset($this->products[$i]); // Tant que products encore utilise
  524. }
  525. }
  526. // Create clone
  527. $result=$this->create($user);
  528. if ($result < 0) $error++;
  529. if (! $error)
  530. {
  531. // Hook of thirdparty module
  532. if (is_object($hookmanager))
  533. {
  534. $parameters=array('objFrom'=>$objFrom);
  535. $action='';
  536. $reshook=$hookmanager->executeHooks('createFrom',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks
  537. if ($reshook < 0) $error++;
  538. }
  539. // Appel des triggers
  540. include_once(DOL_DOCUMENT_ROOT . "/core/class/interfaces.class.php");
  541. $interface=new Interfaces($this->db);
  542. $result=$interface->run_triggers('BILL_CLONE',$this,$user,$langs,$conf);
  543. if ($result < 0) { $error++; $this->errors=$interface->errors; }
  544. // Fin appel triggers
  545. }
  546. // End
  547. if (! $error)
  548. {
  549. $this->db->commit();
  550. return $this->id;
  551. }
  552. else
  553. {
  554. $this->db->rollback();
  555. return -1;
  556. }
  557. }
  558. /**
  559. * Load an object from an order and create a new invoice into database
  560. *
  561. * @param Object $object Object source
  562. * @return int <0 if KO, 0 if nothing done, 1 if OK
  563. */
  564. function createFromOrder($object)
  565. {
  566. global $conf,$user,$langs;
  567. $error=0;
  568. // Closed order
  569. $this->date = dol_now();
  570. $this->source = 0;
  571. $num=count($object->lines);
  572. for ($i = 0; $i < $num; $i++)
  573. {
  574. $line = new FactureLigne($this->db);
  575. $line->libelle = $object->lines[$i]->libelle;
  576. $line->desc = $object->lines[$i]->desc;
  577. //$line->price = $object->lines[$i]->price;
  578. $line->subprice = $object->lines[$i]->subprice;
  579. $line->total_ht = $object->lines[$i]->total_ht;
  580. $line->total_tva = $object->lines[$i]->total_tva;
  581. $line->total_ttc = $object->lines[$i]->total_ttc;
  582. $line->tva_tx = $object->lines[$i]->tva_tx;
  583. $line->localtax1_tx = $object->lines[$i]->localtax1_tx;
  584. $line->localtax2_tx = $object->lines[$i]->localtax2_tx;
  585. $line->qty = $object->lines[$i]->qty;
  586. $line->fk_remise_except = $object->lines[$i]->fk_remise_except;
  587. $line->remise_percent = $object->lines[$i]->remise_percent;
  588. $line->fk_product = $object->lines[$i]->fk_product;
  589. $line->info_bits = $object->lines[$i]->info_bits;
  590. $line->product_type = $object->lines[$i]->product_type;
  591. $line->rang = $object->lines[$i]->rang;
  592. $line->special_code = $object->lines[$i]->special_code;
  593. $line->fk_parent_line = $object->lines[$i]->fk_parent_line;
  594. $this->lines[$i] = $line;
  595. }
  596. $this->socid = $object->socid;
  597. $this->fk_project = $object->fk_project;
  598. $this->cond_reglement_id = $object->cond_reglement_id;
  599. $this->mode_reglement_id = $object->mode_reglement_id;
  600. $this->availability_id = $object->availability_id;
  601. $this->demand_reason_id = $object->demand_reason_id;
  602. $this->date_livraison = $object->date_livraison;
  603. $this->fk_delivery_address = $object->fk_delivery_address;
  604. $this->contact_id = $object->contactid;
  605. $this->ref_client = $object->ref_client;
  606. $this->note = $object->note;
  607. $this->note_public = $object->note_public;
  608. $this->origin = $object->element;
  609. $this->origin_id = $object->id;
  610. // Possibility to add external linked objects with hooks
  611. $this->linked_objects[$this->origin] = $this->origin_id;
  612. if (is_array($object->other_linked_objects) && ! empty($object->other_linked_objects))
  613. {
  614. $this->linked_objects = array_merge($this->linked_objects, $object->other_linked_objects);
  615. }
  616. $ret = $this->create($user);
  617. if ($ret > 0)
  618. {
  619. // Actions hooked (by external module)
  620. include_once(DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php');
  621. $hookmanager=new HookManager($this->db);
  622. $hookmanager->initHooks(array('invoicedao'));
  623. $parameters=array('objFrom'=>$object);
  624. $action='';
  625. $reshook=$hookmanager->executeHooks('createFrom',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks
  626. if ($reshook < 0) $error++;
  627. if (! $error)
  628. {
  629. return 1;
  630. }
  631. else return -1;
  632. }
  633. else return -1;
  634. }
  635. /**
  636. * Return clicable link of object (with eventually picto)
  637. *
  638. * @param int $withpicto Add picto into link
  639. * @param string $option Where point the link
  640. * @param int $max Maxlength of ref
  641. * @param int $short 1=Return just URL
  642. * @param string $moretitle Add more text to title tooltip
  643. * @return string String with URL
  644. */
  645. function getNomUrl($withpicto=0,$option='',$max=0,$short=0,$moretitle='')
  646. {
  647. global $langs;
  648. $result='';
  649. if ($option == 'withdraw') $url = DOL_URL_ROOT.'/compta/facture/prelevement.php?facid='.$this->id;
  650. else $url = DOL_URL_ROOT.'/compta/facture.php?facid='.$this->id;
  651. if ($short) return $url;
  652. $picto='bill';
  653. if ($this->type == 1) $picto.='r'; // Replacement invoice
  654. if ($this->type == 2) $picto.='a'; // Credit note
  655. if ($this->type == 3) $picto.='d'; // Deposit invoice
  656. $label=$langs->trans("ShowInvoice").': '.$this->ref;
  657. if ($this->type == 1) $label=$langs->transnoentitiesnoconv("ShowInvoiceReplace").': '.$this->ref;
  658. if ($this->type == 2) $label=$langs->transnoentitiesnoconv("ShowInvoiceAvoir").': '.$this->ref;
  659. if ($this->type == 3) $label=$langs->transnoentitiesnoconv("ShowInvoiceDeposit").': '.$this->ref;
  660. if ($moretitle) $label.=' - '.$moretitle;
  661. //$linkstart='<a href="'.$url.'" title="'.dol_escape_htmltag($label).'">';
  662. $linkstart='<a href="'.$url.'">';
  663. $linkend='</a>';
  664. if ($withpicto) $result.=($linkstart.img_object(($max?dol_trunc($label,$max):$label),$picto).$linkend);
  665. if ($withpicto && $withpicto != 2) $result.=' ';
  666. if ($withpicto != 2) $result.=$linkstart.($max?dol_trunc($this->ref,$max):$this->ref).$linkend;
  667. return $result;
  668. }
  669. /**
  670. * Get object and lines from database
  671. *
  672. * @param int $rowid Id of object to load
  673. * @param string $ref Reference of invoice
  674. * @param string $ref_ext External reference of invoice
  675. * @param int $ref_int Internal reference of other object
  676. * @return int >0 if OK, <0 if KO, 0 if not found
  677. */
  678. function fetch($rowid, $ref='', $ref_ext='', $ref_int='')
  679. {
  680. global $conf;
  681. if (empty($rowid) && empty($ref) && empty($ref_ext) && empty($ref_int)) return -1;
  682. $sql = 'SELECT f.rowid,f.facnumber,f.ref_client,f.ref_ext,f.ref_int,f.type,f.fk_soc,f.amount,f.tva, f.localtax1, f.localtax2, f.total,f.total_ttc,f.remise_percent,f.remise_absolue,f.remise';
  683. $sql.= ', f.datef as df';
  684. $sql.= ', f.date_lim_reglement as dlr';
  685. $sql.= ', f.datec as datec';
  686. $sql.= ', f.date_valid as datev';
  687. $sql.= ', f.tms as datem';
  688. $sql.= ', f.note as note_private, f.note_public, f.fk_statut, f.paye, f.close_code, f.close_note, f.fk_user_author, f.fk_user_valid, f.model_pdf';
  689. $sql.= ', f.fk_facture_source';
  690. $sql.= ', f.fk_mode_reglement, f.fk_cond_reglement, f.fk_projet, f.extraparams';
  691. $sql.= ', p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
  692. $sql.= ', c.code as cond_reglement_code, c.libelle as cond_reglement_libelle, c.libelle_facture as cond_reglement_libelle_doc';
  693. $sql.= ' FROM '.MAIN_DB_PREFIX.'facture as f';
  694. $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_payment_term as c ON f.fk_cond_reglement = c.rowid';
  695. $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as p ON f.fk_mode_reglement = p.id';
  696. $sql.= ' WHERE f.entity = '.$conf->entity;
  697. if ($rowid) $sql.= " AND f.rowid=".$rowid;
  698. if ($ref) $sql.= " AND f.facnumber='".$this->db->escape($ref)."'";
  699. if ($ref_ext) $sql.= " AND f.ref_ext='".$this->db->escape($ref_ext)."'";
  700. if ($ref_int) $sql.= " AND f.ref_int='".$this->db->escape($ref_int)."'";
  701. dol_syslog(get_class($this)."::fetch sql=".$sql, LOG_DEBUG);
  702. $result = $this->db->query($sql);
  703. if ($result)
  704. {
  705. if ($this->db->num_rows($result))
  706. {
  707. $obj = $this->db->fetch_object($result);
  708. $this->id = $obj->rowid;
  709. $this->ref = $obj->facnumber;
  710. $this->ref_client = $obj->ref_client;
  711. $this->ref_ext = $obj->ref_ext;
  712. $this->ref_int = $obj->ref_int;
  713. $this->type = $obj->type;
  714. $this->date = $this->db->jdate($obj->df);
  715. $this->date_creation = $this->db->jdate($obj->datec);
  716. $this->date_validation = $this->db->jdate($obj->datev);
  717. $this->datem = $this->db->jdate($obj->datem);
  718. $this->remise_percent = $obj->remise_percent;
  719. $this->remise_absolue = $obj->remise_absolue;
  720. //$this->remise = $obj->remise;
  721. $this->total_ht = $obj->total;
  722. $this->total_tva = $obj->tva;
  723. $this->total_localtax1 = $obj->localtax1;
  724. $this->total_localtax2 = $obj->localtax2;
  725. $this->total_ttc = $obj->total_ttc;
  726. $this->paye = $obj->paye;
  727. $this->close_code = $obj->close_code;
  728. $this->close_note = $obj->close_note;
  729. $this->socid = $obj->fk_soc;
  730. $this->statut = $obj->fk_statut;
  731. $this->date_lim_reglement = $this->db->jdate($obj->dlr);
  732. $this->mode_reglement_id = $obj->fk_mode_reglement;
  733. $this->mode_reglement_code = $obj->mode_reglement_code;
  734. $this->mode_reglement = $obj->mode_reglement_libelle;
  735. $this->cond_reglement_id = $obj->fk_cond_reglement;
  736. $this->cond_reglement_code = $obj->cond_reglement_code;
  737. $this->cond_reglement = $obj->cond_reglement_libelle;
  738. $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
  739. $this->fk_project = $obj->fk_projet;
  740. $this->fk_facture_source = $obj->fk_facture_source;
  741. $this->note = $obj->note_private; // deprecated
  742. $this->note_private = $obj->note_private;
  743. $this->note_public = $obj->note_public;
  744. $this->user_author = $obj->fk_user_author;
  745. $this->user_valid = $obj->fk_user_valid;
  746. $this->modelpdf = $obj->model_pdf;
  747. $this->extraparams = (array) json_decode($obj->extraparams, true);
  748. if ($this->statut == 0) $this->brouillon = 1;
  749. /*
  750. * Lines
  751. */
  752. $this->lines = array();
  753. $result=$this->fetch_lines();
  754. if ($result < 0)
  755. {
  756. $this->error=$this->db->error();
  757. dol_syslog(get_class($this)."::fetch Error ".$this->error, LOG_ERR);
  758. return -3;
  759. }
  760. return 1;
  761. }
  762. else
  763. {
  764. $this->error='Bill with id '.$rowid.' or ref '.$ref.' not found sql='.$sql;
  765. dol_syslog(get_class($this)."::fetch Error ".$this->error, LOG_ERR);
  766. return 0;
  767. }
  768. }
  769. else
  770. {
  771. $this->error=$this->db->error();
  772. dol_syslog(get_class($this)."::fetch Error ".$this->error, LOG_ERR);
  773. return -1;
  774. }
  775. }
  776. /**
  777. * Load all detailed lines into this->lines
  778. *
  779. * @return int 1 if OK, < 0 if KO
  780. */
  781. function fetch_lines()
  782. {
  783. $this->lines=array();
  784. $sql = 'SELECT l.rowid, l.fk_product, l.fk_parent_line, l.description, l.product_type, l.price, l.qty, l.tva_tx, ';
  785. $sql.= ' l.localtax1_tx, l.localtax2_tx, l.remise, l.remise_percent, l.fk_remise_except, l.subprice,';
  786. $sql.= ' l.rang, l.special_code,';
  787. $sql.= ' l.date_start as date_start, l.date_end as date_end,';
  788. $sql.= ' l.info_bits, l.total_ht, l.total_tva, l.total_localtax1, l.total_localtax2, l.total_ttc, l.fk_code_ventilation, l.fk_export_compta, l.fk_product_fournisseur_price as fk_fournprice, l.buy_price_ht as pa_ht,';
  789. $sql.= ' p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc';
  790. $sql.= ' FROM '.MAIN_DB_PREFIX.'facturedet as l';
  791. $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON l.fk_product = p.rowid';
  792. $sql.= ' WHERE l.fk_facture = '.$this->id;
  793. $sql.= ' ORDER BY l.rang';
  794. dol_syslog(get_class($this).'::fetch_lines sql='.$sql, LOG_DEBUG);
  795. $result = $this->db->query($sql);
  796. if ($result)
  797. {
  798. $num = $this->db->num_rows($result);
  799. $i = 0;
  800. while ($i < $num)
  801. {
  802. $objp = $this->db->fetch_object($result);
  803. $line = new FactureLigne($this->db);
  804. $line->rowid = $objp->rowid;
  805. $line->desc = $objp->description; // Description line
  806. $line->product_type = $objp->product_type; // Type of line
  807. $line->product_ref = $objp->product_ref; // Ref product
  808. $line->libelle = $objp->product_label; // TODO deprecated
  809. $line->product_label = $objp->product_label; // Label product
  810. $line->product_desc = $objp->product_desc; // Description product
  811. $line->fk_product_type = $objp->fk_product_type; // Type of product
  812. $line->qty = $objp->qty;
  813. $line->subprice = $objp->subprice;
  814. $line->tva_tx = $objp->tva_tx;
  815. $line->localtax1_tx = $objp->localtax1_tx;
  816. $line->localtax2_tx = $objp->localtax2_tx;
  817. $line->remise_percent = $objp->remise_percent;
  818. $line->fk_remise_except = $objp->fk_remise_except;
  819. $line->fk_product = $objp->fk_product;
  820. $line->date_start = $this->db->jdate($objp->date_start);
  821. $line->date_end = $this->db->jdate($objp->date_end);
  822. $line->date_start = $this->db->jdate($objp->date_start);
  823. $line->date_end = $this->db->jdate($objp->date_end);
  824. $line->info_bits = $objp->info_bits;
  825. $line->total_ht = $objp->total_ht;
  826. $line->total_tva = $objp->total_tva;
  827. $line->total_localtax1 = $objp->total_localtax1;
  828. $line->total_localtax2 = $objp->total_localtax2;
  829. $line->total_ttc = $objp->total_ttc;
  830. $line->export_compta = $objp->fk_export_compta;
  831. $line->code_ventilation = $objp->fk_code_ventilation;
  832. $line->fk_fournprice = $objp->fk_fournprice;
  833. $marginInfos = getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
  834. $line->pa_ht = $marginInfos[0];
  835. $line->marge_tx = $marginInfos[1];
  836. $line->marque_tx = $marginInfos[2];
  837. $line->rang = $objp->rang;
  838. $line->special_code = $objp->special_code;
  839. $line->fk_parent_line = $objp->fk_parent_line;
  840. // Ne plus utiliser
  841. //$line->price = $objp->price;
  842. //$line->remise = $objp->remise;
  843. $this->lines[$i] = $line;
  844. $i++;
  845. }
  846. $this->db->free($result);
  847. return 1;
  848. }
  849. else
  850. {
  851. $this->error=$this->db->error();
  852. dol_syslog(get_class($this).'::fetch_lines '.$this->error,LOG_ERR);
  853. return -3;
  854. }
  855. }
  856. /**
  857. * Update database
  858. *
  859. * @param User $user User that modify
  860. * @param int $notrigger 0=launch triggers after, 1=disable triggers
  861. * @return int <0 if KO, >0 if OK
  862. */
  863. function update($user=0, $notrigger=0)
  864. {
  865. global $conf, $langs;
  866. $error=0;
  867. // Clean parameters
  868. if (empty($this->type)) $this->type=0;
  869. if (isset($this->facnumber)) $this->facnumber=trim($this->ref);
  870. if (isset($this->ref_client)) $this->ref_client=trim($this->ref_client);
  871. if (isset($this->increment)) $this->increment=trim($this->increment);
  872. if (isset($this->close_code)) $this->close_code=trim($this->close_code);
  873. if (isset($this->close_note)) $this->close_note=trim($this->close_note);
  874. if (isset($this->note) || isset($this->note_private)) $this->note=(isset($this->note) ? trim($this->note) : trim($this->note_private)); // deprecated
  875. if (isset($this->note) || isset($this->note_private)) $this->note_private=(isset($this->note_private) ? trim($this->note_private) : trim($this->note));
  876. if (isset($this->note_public)) $this->note_public=trim($this->note_public);
  877. if (isset($this->modelpdf)) $this->modelpdf=trim($this->modelpdf);
  878. if (isset($this->import_key)) $this->import_key=trim($this->import_key);
  879. // Check parameters
  880. // Put here code to add control on parameters values
  881. // Update request
  882. $sql = "UPDATE ".MAIN_DB_PREFIX."facture SET";
  883. $sql.= " facnumber=".(isset($this->ref)?"'".$this->db->escape($this->ref)."'":"null").",";
  884. $sql.= " type=".(isset($this->type)?$this->type:"null").",";
  885. $sql.= " ref_client=".(isset($this->ref_client)?"'".$this->db->escape($this->ref_client)."'":"null").",";
  886. $sql.= " increment=".(isset($this->increment)?"'".$this->db->escape($this->increment)."'":"null").",";
  887. $sql.= " fk_soc=".(isset($this->socid)?$this->socid:"null").",";
  888. $sql.= " datec=".(strval($this->date_creation)!='' ? "'".$this->db->idate($this->date_creation)."'" : 'null').",";
  889. $sql.= " datef=".(strval($this->date)!='' ? "'".$this->db->idate($this->date)."'" : 'null').",";
  890. $sql.= " date_valid=".(strval($this->date_validation)!='' ? "'".$this->db->idate($this->date_validation)."'" : 'null').",";
  891. $sql.= " paye=".(isset($this->paye)?$this->paye:"null").",";
  892. $sql.= " remise_percent=".(isset($this->remise_percent)?$this->remise_percent:"null").",";
  893. $sql.= " remise_absolue=".(isset($this->remise_absolue)?$this->remise_absolue:"null").",";
  894. //$sql.= " remise=".(isset($this->remise)?$this->remise:"null").",";
  895. $sql.= " close_code=".(isset($this->close_code)?"'".$this->db->escape($this->close_code)."'":"null").",";
  896. $sql.= " close_note=".(isset($this->close_note)?"'".$this->db->escape($this->close_note)."'":"null").",";
  897. $sql.= " tva=".(isset($this->total_tva)?$this->total_tva:"null").",";
  898. $sql.= " localtax1=".(isset($this->total_localtax1)?$this->total_localtax1:"null").",";
  899. $sql.= " localtax2=".(isset($this->total_localtax2)?$this->total_localtax2:"null").",";
  900. $sql.= " total=".(isset($this->total_ht)?$this->total_ht:"null").",";
  901. $sql.= " total_ttc=".(isset($this->total_ttc)?$this->total_ttc:"null").",";
  902. $sql.= " fk_statut=".(isset($this->statut)?$this->statut:"null").",";
  903. $sql.= " fk_user_author=".(isset($this->user_author)?$this->user_author:"null").",";
  904. $sql.= " fk_user_valid=".(isset($this->fk_user_valid)?$this->fk_user_valid:"null").",";
  905. $sql.= " fk_facture_source=".(isset($this->fk_facture_source)?$this->fk_facture_source:"null").",";
  906. $sql.= " fk_projet=".(isset($this->fk_project)?$this->fk_project:"null").",";
  907. $sql.= " fk_cond_reglement=".(isset($this->cond_reglement_id)?$this->cond_reglement_id:"null").",";
  908. $sql.= " fk_mode_reglement=".(isset($this->mode_reglement_id)?$this->mode_reglement_id:"null").",";
  909. $sql.= " date_lim_reglement=".(strval($this->date_lim_reglement)!='' ? "'".$this->db->idate($this->date_lim_reglement)."'" : 'null').",";
  910. $sql.= " note=".(isset($this->note_private)?"'".$this->db->escape($this->note_private)."'":"null").",";
  911. $sql.= " note_public=".(isset($this->note_public)?"'".$this->db->escape($this->note_public)."'":"null").",";
  912. $sql.= " model_pdf=".(isset($this->modelpdf)?"'".$this->db->escape($this->modelpdf)."'":"null").",";
  913. $sql.= " import_key=".(isset($this->import_key)?"'".$this->db->escape($this->import_key)."'":"null")."";
  914. $sql.= " WHERE rowid=".$this->id;
  915. $this->db->begin();
  916. dol_syslog(get_class($this)."::update sql=".$sql, LOG_DEBUG);
  917. $resql = $this->db->query($sql);
  918. if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
  919. if (! $error)
  920. {
  921. if (! $notrigger)
  922. {
  923. // Call triggers
  924. include_once(DOL_DOCUMENT_ROOT . "/core/class/interfaces.class.php");
  925. $interface=new Interfaces($this->db);
  926. $result=$interface->run_triggers('BILL_MODIFY',$this,$user,$langs,$conf);
  927. if ($result < 0) { $error++; $this->errors=$interface->errors; }
  928. // End call triggers
  929. }
  930. }
  931. // Commit or rollback
  932. if ($error)
  933. {
  934. foreach($this->errors as $errmsg)
  935. {
  936. dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
  937. $this->error.=($this->error?', '.$errmsg:$errmsg);
  938. }
  939. $this->db->rollback();
  940. return -1*$error;
  941. }
  942. else
  943. {
  944. $this->db->commit();
  945. return 1;
  946. }
  947. }
  948. /**
  949. * Add a discount line into invoice using an existing absolute discount
  950. *
  951. * @param int $idremise Id of absolute discount
  952. * @return int >0 if OK, <0 if KO
  953. */
  954. function insert_discount($idremise)
  955. {
  956. global $langs;
  957. include_once(DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php');
  958. include_once(DOL_DOCUMENT_ROOT.'/core/class/discount.class.php');
  959. $this->db->begin();
  960. $remise=new DiscountAbsolute($this->db);
  961. $result=$remise->fetch($idremise);
  962. if ($result > 0)
  963. {
  964. if ($remise->fk_facture) // Protection against multiple submission
  965. {
  966. $this->error=$langs->trans("ErrorDiscountAlreadyUsed");
  967. $this->db->rollback();
  968. return -5;
  969. }
  970. $facligne=new FactureLigne($this->db);
  971. $facligne->fk_facture=$this->id;
  972. $facligne->fk_remise_except=$remise->id;
  973. $facligne->desc=$remise->description; // Description ligne
  974. $facligne->tva_tx=$remise->tva_tx;
  975. $facligne->subprice=-$remise->amount_ht;
  976. $facligne->fk_product=0; // Id produit predefini
  977. $facligne->qty=1;
  978. $facligne->remise_percent=0;
  979. $facligne->rang=-1;
  980. $facligne->info_bits=2;
  981. $facligne->total_ht = -$remise->amount_ht;
  982. $facligne->total_tva = -$remise->amount_tva;
  983. $facligne->total_ttc = -$remise->amount_ttc;
  984. $lineid=$facligne->insert();
  985. if ($lineid > 0)
  986. {
  987. $result=$this->update_price(1);
  988. if ($result > 0)
  989. {
  990. // Create linke between discount and invoice line
  991. $result=$remise->link_to_invoice($lineid,0);
  992. if ($result < 0)
  993. {
  994. $this->error=$remise->error;
  995. $this->db->rollback();
  996. return -4;
  997. }
  998. $this->db->commit();
  999. return 1;
  1000. }
  1001. else
  1002. {
  1003. $this->error=$facligne->error;
  1004. $this->db->rollback();
  1005. return -1;
  1006. }
  1007. }
  1008. else
  1009. {
  1010. $this->error=$facligne->error;
  1011. $this->db->rollback();
  1012. return -2;
  1013. }
  1014. }
  1015. else
  1016. {
  1017. $this->db->rollback();
  1018. return -3;
  1019. }
  1020. }
  1021. /**
  1022. * Set customer ref
  1023. *
  1024. * @param string $ref_client Customer ref
  1025. * @return int <0 if KO, >0 if OK
  1026. */
  1027. function set_ref_client($ref_client)
  1028. {
  1029. $sql = 'UPDATE '.MAIN_DB_PREFIX.'facture';
  1030. if (empty($ref_client))
  1031. $sql .= ' SET ref_client = NULL';
  1032. else
  1033. $sql .= ' SET ref_client = \''.$this->db->escape($ref_client).'\'';
  1034. $sql .= ' WHERE rowid = '.$this->id;
  1035. if ($this->db->query($sql))
  1036. {
  1037. $this->ref_client = $ref_client;
  1038. return 1;
  1039. }
  1040. else
  1041. {
  1042. dol_print_error($this->db);
  1043. return -1;
  1044. }
  1045. }
  1046. /**
  1047. * Delete invoice
  1048. *
  1049. * @param int $rowid Id of invoice to delete. If empty, we delete current instance of invoice
  1050. * @param int $notrigger 1=Does not execute triggers, 0= execute triggers
  1051. * @return int <0 if KO, >0 if OK
  1052. */
  1053. function delete($rowid=0, $notrigger=0)
  1054. {
  1055. global $user,$langs,$conf;
  1056. require_once(DOL_DOCUMENT_ROOT."/core/lib/files.lib.php");
  1057. if (! $rowid) $rowid=$this->id;
  1058. dol_syslog(get_class($this)."::delete rowid=".$rowid, LOG_DEBUG);
  1059. // TODO Test if there is at least on payment. If yes, refuse to delete.
  1060. $error=0;
  1061. $this->db->begin();
  1062. if (! $error && ! $notrigger)
  1063. {
  1064. // Appel des triggers
  1065. include_once(DOL_DOCUMENT_ROOT . "/core/class/interfaces.class.php");
  1066. $interface=new Interfaces($this->db);
  1067. $result=$interface->run_triggers('BILL_DELETE',$this,$user,$langs,$conf);
  1068. if ($result < 0) {
  1069. $error++; $this->errors=$interface->errors;
  1070. }
  1071. // Fin appel triggers
  1072. }
  1073. if (! $error)
  1074. {
  1075. // Delete linkeā€¦

Large files files are truncated, but you can click here to view the full file