PageRenderTime 60ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

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

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

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