paiementfourn.class.php 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. <?php
  2. /* Copyright (C) 2002-2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2004-2007 Laurent Destailleur <eldy@users.sourceforge.net>
  4. * Copyright (C) 2005 Marc Barilley / Ocebo <marc@ocebo.com>
  5. * Copyright (C) 2005-2009 Regis Houssin <regis.houssin@inodbox.com>
  6. * Copyright (C) 2010-2011 Juanjo Menent <jmenent@2byte.es>
  7. * Copyright (C) 2014 Marcos García <marcosgdf@gmail.com>
  8. * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
  9. * Copyright (C) 2018 Frédéric France <frederic.francenetlogic.fr>
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 3 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  23. */
  24. /**
  25. * \file htdocs/fourn/class/paiementfourn.class.php
  26. * \ingroup fournisseur, facture
  27. * \brief File of class to manage payments of suppliers invoices
  28. */
  29. require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
  30. require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
  31. require_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
  32. /**
  33. * Class to manage payments for supplier invoices
  34. */
  35. class PaiementFourn extends Paiement
  36. {
  37. /**
  38. * @var string ID to identify managed object
  39. */
  40. public $element = 'payment_supplier';
  41. /**
  42. * @var string Name of table without prefix where object is stored
  43. */
  44. public $table_element = 'paiementfourn';
  45. /**
  46. * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
  47. */
  48. public $picto = 'payment';
  49. public $statut; //Status of payment. 0 = unvalidated; 1 = validated
  50. // fk_paiement dans llx_paiement est l'id du type de paiement (7 pour CHQ, ...)
  51. // fk_paiement dans llx_paiement_facture est le rowid du paiement
  52. /**
  53. * Label of payment type
  54. * @var string
  55. */
  56. public $type_label;
  57. /**
  58. * Code of Payment type
  59. * @var string
  60. */
  61. public $type_code;
  62. /**
  63. * @var string Id of prelevement
  64. */
  65. public $id_prelevement;
  66. /**
  67. * @var string num_prelevement
  68. */
  69. public $num_prelevement;
  70. /**
  71. * Constructor
  72. *
  73. * @param DoliDB $db Database handler
  74. */
  75. public function __construct($db)
  76. {
  77. $this->db = $db;
  78. }
  79. /**
  80. * Load payment object
  81. *
  82. * @param int $id Id if payment to get
  83. * @param string $ref Ref of payment to get
  84. * @param int $fk_bank Id of bank line associated to payment
  85. * @return int <0 if KO, -2 if not found, >0 if OK
  86. */
  87. public function fetch($id, $ref = '', $fk_bank = '')
  88. {
  89. $error = 0;
  90. $sql = 'SELECT p.rowid, p.ref, p.entity, p.datep as dp, p.amount, p.statut, p.fk_bank, p.multicurrency_amount,';
  91. $sql .= ' c.code as payment_code, c.libelle as payment_type,';
  92. $sql .= ' p.num_paiement as num_payment, p.note, b.fk_account, p.fk_paiement';
  93. $sql .= ' FROM '.MAIN_DB_PREFIX.'paiementfourn as p';
  94. $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as c ON p.fk_paiement = c.id';
  95. $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank as b ON p.fk_bank = b.rowid';
  96. $sql .= ' WHERE p.entity IN ('.getEntity('facture_fourn').')';
  97. if ($id > 0) {
  98. $sql .= ' AND p.rowid = '.((int) $id);
  99. } elseif ($ref) {
  100. $sql .= " AND p.ref = '".$this->db->escape($ref)."'";
  101. } elseif ($fk_bank > 0) {
  102. $sql .= ' AND p.fk_bank = '.((int) $fk_bank);
  103. }
  104. //print $sql;
  105. $resql = $this->db->query($sql);
  106. if ($resql) {
  107. $num = $this->db->num_rows($resql);
  108. if ($num > 0) {
  109. $obj = $this->db->fetch_object($resql);
  110. $this->id = $obj->rowid;
  111. $this->ref = $obj->ref;
  112. $this->entity = $obj->entity;
  113. $this->date = $this->db->jdate($obj->dp);
  114. $this->datepaye = $this->db->jdate($obj->dp);
  115. $this->num_payment = $obj->num_payment;
  116. $this->numero = $obj->num_payment;
  117. $this->bank_account = $obj->fk_account;
  118. $this->fk_account = $obj->fk_account;
  119. $this->bank_line = $obj->fk_bank;
  120. $this->montant = $obj->amount; // deprecated
  121. $this->amount = $obj->amount;
  122. $this->multicurrency_amount = $obj->multicurrency_amount;
  123. $this->note = $obj->note;
  124. $this->note_private = $obj->note;
  125. $this->type_code = $obj->payment_code;
  126. $this->type_label = $obj->payment_type;
  127. $this->fk_paiement = $obj->fk_paiement;
  128. $this->statut = $obj->statut;
  129. $error = 1;
  130. } else {
  131. $error = -2; // TODO Use 0 instead
  132. }
  133. $this->db->free($resql);
  134. } else {
  135. dol_print_error($this->db);
  136. $error = -1;
  137. }
  138. return $error;
  139. }
  140. /**
  141. * Create payment in database
  142. *
  143. * @param User $user Object of creating user
  144. * @param int $closepaidinvoices 1=Also close payed invoices to paid, 0=Do nothing more
  145. * @param Societe $thirdparty Thirdparty
  146. * @return int id of created payment, < 0 if error
  147. */
  148. public function create($user, $closepaidinvoices = 0, $thirdparty = null)
  149. {
  150. global $langs, $conf;
  151. $error = 0;
  152. $way = $this->getWay();
  153. $now = dol_now();
  154. // Clean parameters
  155. $totalamount = 0;
  156. $totalamount_converted = 0;
  157. $atleastonepaymentnotnull = 0;
  158. if ($way == 'dolibarr') {
  159. $amounts = &$this->amounts;
  160. $amounts_to_update = &$this->multicurrency_amounts;
  161. } else {
  162. $amounts = &$this->multicurrency_amounts;
  163. $amounts_to_update = &$this->amounts;
  164. }
  165. $currencyofpayment = '';
  166. foreach ($amounts as $key => $value) {
  167. if (empty($value)) {
  168. continue;
  169. }
  170. // $key is id of invoice, $value is amount, $way is a 'dolibarr' if amount is in main currency, 'customer' if in foreign currency
  171. $value_converted = Multicurrency::getAmountConversionFromInvoiceRate($key, $value ? $value : 0, $way, 'facture_fourn');
  172. // Add controls of input validity
  173. if ($value_converted === false) {
  174. // We failed to find the conversion for one invoice
  175. $this->error = 'FailedToFoundTheConversionRateForInvoice';
  176. return -1;
  177. }
  178. if (empty($currencyofpayment)) {
  179. $currencyofpayment = $this->multicurrency_code[$key];
  180. }
  181. if ($currencyofpayment != $this->multicurrency_code[$key]) {
  182. // If we have invoices with different currencies in the payment, we stop here
  183. $this->error = 'ErrorYouTryToPayInvoicesWithDifferentCurrenciesInSamePayment';
  184. return -1;
  185. }
  186. $totalamount_converted += $value_converted;
  187. $amounts_to_update[$key] = price2num($value_converted, 'MT');
  188. $newvalue = price2num($value, 'MT');
  189. $amounts[$key] = $newvalue;
  190. $totalamount += $newvalue;
  191. if (!empty($newvalue)) {
  192. $atleastonepaymentnotnull++;
  193. }
  194. }
  195. if (!empty($currencyofpayment)) {
  196. // We must check that the currency of invoices is the same than the currency of the bank
  197. $bankaccount = new Account($this->db);
  198. $bankaccount->fetch($this->fk_account);
  199. $bankcurrencycode = empty($bankaccount->currency_code) ? $conf->currency : $bankaccount->currency_code;
  200. if ($currencyofpayment != $bankcurrencycode && $currencyofpayment != $conf->currency && $bankcurrencycode != $conf->currency) {
  201. $langs->load("errors");
  202. $this->error = $langs->trans('ErrorYouTryToPayInvoicesInACurrencyFromBankWithAnotherCurrency', $currencyofpayment, $bankcurrencycode);
  203. return -1;
  204. }
  205. }
  206. $totalamount = price2num($totalamount);
  207. $totalamount_converted = price2num($totalamount_converted);
  208. dol_syslog(get_class($this)."::create", LOG_DEBUG);
  209. $this->db->begin();
  210. if ($totalamount <> 0) { // On accepte les montants negatifs
  211. $ref = $this->getNextNumRef(is_object($thirdparty) ? $thirdparty : '');
  212. if ($way == 'dolibarr') {
  213. $total = $totalamount;
  214. $mtotal = $totalamount_converted; // Maybe use price2num with MT for the converted value
  215. } else {
  216. $total = $totalamount_converted; // Maybe use price2num with MT for the converted value
  217. $mtotal = $totalamount;
  218. }
  219. $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'paiementfourn (';
  220. $sql .= 'ref, entity, datec, datep, amount, multicurrency_amount, fk_paiement, num_paiement, note, fk_user_author, fk_bank)';
  221. $sql .= " VALUES ('".$this->db->escape($ref)."', ".((int) $conf->entity).", '".$this->db->idate($now)."',";
  222. $sql .= " '".$this->db->idate($this->datepaye)."', ".((float) $total).", ".((float) $mtotal).", ".((int) $this->paiementid).", '".$this->db->escape($this->num_payment)."', '".$this->db->escape($this->note_private)."', ".((int) $user->id).", 0)";
  223. $resql = $this->db->query($sql);
  224. if ($resql) {
  225. $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'paiementfourn');
  226. // Insere tableau des montants / factures
  227. foreach ($this->amounts as $key => $amount) {
  228. $facid = $key;
  229. if (is_numeric($amount) && $amount <> 0) {
  230. $amount = price2num($amount);
  231. $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'paiementfourn_facturefourn (fk_facturefourn, fk_paiementfourn, amount, multicurrency_amount)';
  232. $sql .= " VALUES (".((int) $facid).", ".((int) $this->id).", ".((float) $amount).', '.((float) $this->multicurrency_amounts[$key]).')';
  233. $resql = $this->db->query($sql);
  234. if ($resql) {
  235. $invoice = new FactureFournisseur($this->db);
  236. $invoice->fetch($facid);
  237. // If we want to closed paid invoices
  238. if ($closepaidinvoices) {
  239. $paiement = $invoice->getSommePaiement();
  240. $creditnotes=$invoice->getSumCreditNotesUsed();
  241. //$creditnotes = 0;
  242. $deposits=$invoice->getSumDepositsUsed();
  243. //$deposits = 0;
  244. $alreadypayed = price2num($paiement + $creditnotes + $deposits, 'MT');
  245. $remaintopay = price2num($invoice->total_ttc - $paiement - $creditnotes - $deposits, 'MT');
  246. if ($remaintopay == 0) {
  247. // If invoice is a down payment, we also convert down payment to discount
  248. if ($invoice->type == FactureFournisseur::TYPE_DEPOSIT) {
  249. $amount_ht = $amount_tva = $amount_ttc = array();
  250. $multicurrency_amount_ht = $multicurrency_amount_tva = $multicurrency_amount_ttc = array();
  251. // Insert one discount by VAT rate category
  252. require_once DOL_DOCUMENT_ROOT . '/core/class/discount.class.php';
  253. $discount = new DiscountAbsolute($this->db);
  254. $discount->fetch('', 0, $invoice->id);
  255. if (empty($discount->id)) { // If the invoice was not yet converted into a discount (this may have been done manually before we come here)
  256. $discount->discount_type = 1; // Supplier discount
  257. $discount->description = '(DEPOSIT)';
  258. $discount->fk_soc = $invoice->socid;
  259. $discount->fk_invoice_supplier_source = $invoice->id;
  260. // Loop on each vat rate
  261. $i = 0;
  262. foreach ($invoice->lines as $line) {
  263. if ($line->total_ht != 0) { // no need to create discount if amount is null
  264. $amount_ht[$line->tva_tx] += $line->total_ht;
  265. $amount_tva[$line->tva_tx] += $line->total_tva;
  266. $amount_ttc[$line->tva_tx] += $line->total_ttc;
  267. $multicurrency_amount_ht[$line->tva_tx] += $line->multicurrency_total_ht;
  268. $multicurrency_amount_tva[$line->tva_tx] += $line->multicurrency_total_tva;
  269. $multicurrency_amount_ttc[$line->tva_tx] += $line->multicurrency_total_ttc;
  270. $i++;
  271. }
  272. }
  273. foreach ($amount_ht as $tva_tx => $xxx) {
  274. $discount->amount_ht = abs($amount_ht[$tva_tx]);
  275. $discount->amount_tva = abs($amount_tva[$tva_tx]);
  276. $discount->amount_ttc = abs($amount_ttc[$tva_tx]);
  277. $discount->multicurrency_amount_ht = abs($multicurrency_amount_ht[$tva_tx]);
  278. $discount->multicurrency_amount_tva = abs($multicurrency_amount_tva[$tva_tx]);
  279. $discount->multicurrency_amount_ttc = abs($multicurrency_amount_ttc[$tva_tx]);
  280. $discount->tva_tx = abs($tva_tx);
  281. $result = $discount->create($user);
  282. if ($result < 0) {
  283. $error++;
  284. break;
  285. }
  286. }
  287. }
  288. if ($error) {
  289. setEventMessages($discount->error, $discount->errors, 'errors');
  290. $error++;
  291. }
  292. }
  293. // Set invoice to paid
  294. if (!$error) {
  295. $result = $invoice->setPaid($user, '', '');
  296. if ($result < 0) {
  297. $this->error = $invoice->error;
  298. $error++;
  299. }
  300. }
  301. } else {
  302. dol_syslog("Remain to pay for invoice ".$facid." not null. We do nothing.");
  303. }
  304. }
  305. // Regenerate documents of invoices
  306. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
  307. $newlang = '';
  308. $outputlangs = $langs;
  309. if ($conf->global->MAIN_MULTILANGS && empty($newlang)) {
  310. $newlang = $invoice->thirdparty->default_lang;
  311. }
  312. if (!empty($newlang)) {
  313. $outputlangs = new Translate("", $conf);
  314. $outputlangs->setDefaultLang($newlang);
  315. }
  316. $ret = $invoice->fetch($facid); // Reload to get new records
  317. $result = $invoice->generateDocument($invoice->model_pdf, $outputlangs);
  318. if ($result < 0) {
  319. setEventMessages($invoice->error, $invoice->errors, 'errors');
  320. $error++;
  321. }
  322. }
  323. } else {
  324. $this->error = $this->db->lasterror();
  325. $error++;
  326. }
  327. } else {
  328. dol_syslog(get_class($this).'::Create Amount line '.$key.' not a number. We discard it.');
  329. }
  330. }
  331. if (!$error) {
  332. // Call trigger
  333. $result = $this->call_trigger('PAYMENT_SUPPLIER_CREATE', $user);
  334. if ($result < 0) {
  335. $error++;
  336. }
  337. // End call triggers
  338. }
  339. } else {
  340. $this->error = $this->db->lasterror();
  341. $error++;
  342. }
  343. } else {
  344. $this->error = "ErrorTotalIsNull";
  345. dol_syslog('PaiementFourn::Create Error '.$this->error, LOG_ERR);
  346. $error++;
  347. }
  348. if ($totalamount <> 0 && $error == 0) { // On accepte les montants negatifs
  349. $this->amount = $total;
  350. $this->total = $total;
  351. $this->multicurrency_amount = $mtotal;
  352. $this->db->commit();
  353. dol_syslog('PaiementFourn::Create Ok Total = '.$this->amount.', Total currency = '.$this->multicurrency_amount);
  354. return $this->id;
  355. } else {
  356. $this->db->rollback();
  357. return -1;
  358. }
  359. }
  360. /**
  361. * Delete a payment and lines generated into accounts
  362. * Si le paiement porte sur un ecriture compte qui est rapprochee, on refuse
  363. * Si le paiement porte sur au moins une facture a "payee", on refuse
  364. *
  365. * @param int $notrigger No trigger
  366. * @return int <0 si ko, >0 si ok
  367. */
  368. public function delete($notrigger = 0)
  369. {
  370. global $conf, $user, $langs;
  371. $bank_line_id = $this->bank_line;
  372. $this->db->begin();
  373. // Verifier si paiement porte pas sur une facture a l'etat payee
  374. // Si c'est le cas, on refuse la suppression
  375. $billsarray = $this->getBillsArray('paye=1');
  376. if (is_array($billsarray)) {
  377. if (count($billsarray)) {
  378. $this->error = "ErrorCantDeletePaymentSharedWithPayedInvoice";
  379. $this->db->rollback();
  380. return -1;
  381. }
  382. } else {
  383. $this->db->rollback();
  384. return -2;
  385. }
  386. // Verifier si paiement ne porte pas sur ecriture bancaire rapprochee
  387. // Si c'est le cas, on refuse le delete
  388. if ($bank_line_id) {
  389. $accline = new AccountLine($this->db);
  390. $accline->fetch($bank_line_id);
  391. if ($accline->rappro) {
  392. $this->error = "ErrorCantDeletePaymentReconciliated";
  393. $this->db->rollback();
  394. return -3;
  395. }
  396. }
  397. // Efface la ligne de paiement (dans paiement_facture et paiement)
  398. $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'paiementfourn_facturefourn';
  399. $sql .= ' WHERE fk_paiementfourn = '.((int) $this->id);
  400. $resql = $this->db->query($sql);
  401. if ($resql) {
  402. $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'paiementfourn';
  403. $sql .= " WHERE rowid = ".((int) $this->id);
  404. $result = $this->db->query($sql);
  405. if (!$result) {
  406. $this->error = $this->db->error();
  407. $this->db->rollback();
  408. return -3;
  409. }
  410. // Supprimer l'ecriture bancaire si paiement lie a ecriture
  411. if ($bank_line_id) {
  412. $accline = new AccountLine($this->db);
  413. $result = $accline->fetch($bank_line_id);
  414. if ($result > 0) { // If result = 0, record not found, we don't try to delete
  415. $result = $accline->delete($user);
  416. }
  417. if ($result < 0) {
  418. $this->error = $accline->error;
  419. $this->db->rollback();
  420. return -4;
  421. }
  422. }
  423. if (!$notrigger) {
  424. // Appel des triggers
  425. $result = $this->call_trigger('PAYMENT_SUPPLIER_DELETE', $user);
  426. if ($result < 0) {
  427. $this->db->rollback();
  428. return -1;
  429. }
  430. // Fin appel triggers
  431. }
  432. $this->db->commit();
  433. return 1;
  434. } else {
  435. $this->error = $this->db->error;
  436. $this->db->rollback();
  437. return -5;
  438. }
  439. }
  440. /**
  441. * Information on object
  442. *
  443. * @param int $id Id du paiement dont il faut afficher les infos
  444. * @return void
  445. */
  446. public function info($id)
  447. {
  448. $sql = 'SELECT c.rowid, datec, fk_user_author as fk_user_creat, tms';
  449. $sql .= ' FROM '.MAIN_DB_PREFIX.'paiementfourn as c';
  450. $sql .= ' WHERE c.rowid = '.((int) $id);
  451. $resql = $this->db->query($sql);
  452. if ($resql) {
  453. $num = $this->db->num_rows($resql);
  454. if ($num) {
  455. $obj = $this->db->fetch_object($resql);
  456. $this->id = $obj->rowid;
  457. if ($obj->fk_user_creat) {
  458. $cuser = new User($this->db);
  459. $cuser->fetch($obj->fk_user_creat);
  460. $this->user_creation = $cuser;
  461. }
  462. if ($obj->fk_user_modif) {
  463. $muser = new User($this->db);
  464. $muser->fetch($obj->fk_user_modif);
  465. $this->user_modification = $muser;
  466. }
  467. $this->date_creation = $this->db->jdate($obj->datec);
  468. $this->date_modification = $this->db->jdate($obj->tms);
  469. }
  470. $this->db->free($resql);
  471. } else {
  472. dol_print_error($this->db);
  473. }
  474. }
  475. /**
  476. * Return list of supplier invoices the payment point to
  477. *
  478. * @param string $filter SQL filter. Warning: This value must not come from a user input.
  479. * @return array Array of supplier invoice id
  480. */
  481. public function getBillsArray($filter = '')
  482. {
  483. $sql = 'SELECT fk_facturefourn';
  484. $sql .= ' FROM '.MAIN_DB_PREFIX.'paiementfourn_facturefourn as pf, '.MAIN_DB_PREFIX.'facture_fourn as f';
  485. $sql .= ' WHERE pf.fk_facturefourn = f.rowid AND fk_paiementfourn = '.((int) $this->id);
  486. if ($filter) {
  487. $sql .= " AND ".$filter;
  488. }
  489. dol_syslog(get_class($this).'::getBillsArray', LOG_DEBUG);
  490. $resql = $this->db->query($sql);
  491. if ($resql) {
  492. $i = 0;
  493. $num = $this->db->num_rows($resql);
  494. $billsarray = array();
  495. while ($i < $num) {
  496. $obj = $this->db->fetch_object($resql);
  497. $billsarray[$i] = $obj->fk_facturefourn;
  498. $i++;
  499. }
  500. return $billsarray;
  501. } else {
  502. $this->error = $this->db->error();
  503. dol_syslog(get_class($this).'::getBillsArray Error '.$this->error);
  504. return -1;
  505. }
  506. }
  507. /**
  508. * Retourne le libelle du statut d'une facture (brouillon, validee, abandonnee, payee)
  509. *
  510. * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
  511. * @return string Libelle
  512. */
  513. public function getLibStatut($mode = 0)
  514. {
  515. return $this->LibStatut($this->statut, $mode);
  516. }
  517. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  518. /**
  519. * Renvoi le libelle d'un statut donne
  520. *
  521. * @param int $status Statut
  522. * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
  523. * @return string Libelle du statut
  524. */
  525. public function LibStatut($status, $mode = 0)
  526. {
  527. // phpcs:enable
  528. global $langs;
  529. $langs->load('compta');
  530. /*if ($mode == 0)
  531. {
  532. if ($status == 0) return $langs->trans('ToValidate');
  533. if ($status == 1) return $langs->trans('Validated');
  534. }
  535. if ($mode == 1)
  536. {
  537. if ($status == 0) return $langs->trans('ToValidate');
  538. if ($status == 1) return $langs->trans('Validated');
  539. }
  540. if ($mode == 2)
  541. {
  542. if ($status == 0) return img_picto($langs->trans('ToValidate'),'statut1').' '.$langs->trans('ToValidate');
  543. if ($status == 1) return img_picto($langs->trans('Validated'),'statut4').' '.$langs->trans('Validated');
  544. }
  545. if ($mode == 3)
  546. {
  547. if ($status == 0) return img_picto($langs->trans('ToValidate'),'statut1');
  548. if ($status == 1) return img_picto($langs->trans('Validated'),'statut4');
  549. }
  550. if ($mode == 4)
  551. {
  552. if ($status == 0) return img_picto($langs->trans('ToValidate'),'statut1').' '.$langs->trans('ToValidate');
  553. if ($status == 1) return img_picto($langs->trans('Validated'),'statut4').' '.$langs->trans('Validated');
  554. }
  555. if ($mode == 5)
  556. {
  557. if ($status == 0) return $langs->trans('ToValidate').' '.img_picto($langs->trans('ToValidate'),'statut1');
  558. if ($status == 1) return $langs->trans('Validated').' '.img_picto($langs->trans('Validated'),'statut4');
  559. }
  560. if ($mode == 6)
  561. {
  562. if ($status == 0) return $langs->trans('ToValidate').' '.img_picto($langs->trans('ToValidate'),'statut1');
  563. if ($status == 1) return $langs->trans('Validated').' '.img_picto($langs->trans('Validated'),'statut4');
  564. }*/
  565. return '';
  566. }
  567. /**
  568. * Return clicable name (with picto eventually)
  569. *
  570. * @param int $withpicto 0=No picto, 1=Include picto into link, 2=Only picto
  571. * @param string $option Sur quoi pointe le lien
  572. * @param string $mode 'withlistofinvoices'=Include list of invoices into tooltip
  573. * @param int $notooltip 1=Disable tooltip
  574. * @param string $morecss Add more CSS
  575. * @return string Chaine avec URL
  576. */
  577. public function getNomUrl($withpicto = 0, $option = '', $mode = 'withlistofinvoices', $notooltip = 0, $morecss = '')
  578. {
  579. global $langs, $conf, $hookmanager;
  580. if (!empty($conf->dol_no_mouse_hover)) {
  581. $notooltip = 1; // Force disable tooltips
  582. }
  583. $result = '';
  584. $text = $this->ref; // Sometimes ref contains label
  585. $reg = array();
  586. if (preg_match('/^\((.*)\)$/i', $text, $reg)) {
  587. // Label generique car entre parentheses. On l'affiche en le traduisant
  588. if ($reg[1] == 'paiement') {
  589. $reg[1] = 'Payment';
  590. }
  591. $text = $langs->trans($reg[1]);
  592. }
  593. $label = img_picto('', $this->picto).' <u>'.$langs->trans("Payment").'</u><br>';
  594. $label .= '<strong>'.$langs->trans("Ref").':</strong> '.$text;
  595. $dateofpayment = ($this->datepaye ? $this->datepaye : $this->date);
  596. if ($dateofpayment) {
  597. $label .= '<br><strong>'.$langs->trans("Date").':</strong> '.dol_print_date($dateofpayment, 'dayhour', 'tzuser');
  598. }
  599. if ($this->amount) {
  600. $label .= '<br><strong>'.$langs->trans("Amount").':</strong> '.price($this->amount, 0, $langs, 1, -1, -1, $conf->currency);
  601. }
  602. $linkclose = '';
  603. if (empty($notooltip)) {
  604. if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
  605. $label = $langs->trans("Payment");
  606. $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
  607. }
  608. $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
  609. $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
  610. } else {
  611. $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
  612. }
  613. $linkstart = '<a href="'.DOL_URL_ROOT.'/fourn/paiement/card.php?id='.$this->id.'"';
  614. $linkstart .= $linkclose.'>';
  615. $linkend = '</a>';
  616. $result .= $linkstart;
  617. if ($withpicto) {
  618. $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
  619. }
  620. if ($withpicto != 2) {
  621. $result .= $this->ref;
  622. }
  623. $result .= $linkend;
  624. global $action;
  625. $hookmanager->initHooks(array($this->element . 'dao'));
  626. $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
  627. $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
  628. if ($reshook > 0) {
  629. $result = $hookmanager->resPrint;
  630. } else {
  631. $result .= $hookmanager->resPrint;
  632. }
  633. return $result;
  634. }
  635. /**
  636. * Initialise an instance with random values.
  637. * Used to build previews or test instances.
  638. * id must be 0 if object instance is a specimen.
  639. *
  640. * @param string $option ''=Create a specimen invoice with lines, 'nolines'=No lines
  641. * @return void
  642. */
  643. public function initAsSpecimen($option = '')
  644. {
  645. global $user, $langs, $conf;
  646. $now = dol_now();
  647. $arraynow = dol_getdate($now);
  648. $nownotime = dol_mktime(0, 0, 0, $arraynow['mon'], $arraynow['mday'], $arraynow['year']);
  649. // Initialize parameters
  650. $this->id = 0;
  651. $this->ref = 'SPECIMEN';
  652. $this->specimen = 1;
  653. $this->facid = 1;
  654. $this->socid = 1;
  655. $this->datepaye = $nownotime;
  656. }
  657. /**
  658. * Return next reference of supplier invoice not already used (or last reference)
  659. * according to numbering module defined into constant SUPPLIER_PAYMENT_ADDON
  660. *
  661. * @param Societe $soc object company
  662. * @param string $mode 'next' for next value or 'last' for last value
  663. * @return string free ref or last ref
  664. */
  665. public function getNextNumRef($soc, $mode = 'next')
  666. {
  667. global $conf, $db, $langs;
  668. $langs->load("bills");
  669. // Clean parameters (if not defined or using deprecated value)
  670. if (empty($conf->global->SUPPLIER_PAYMENT_ADDON)) {
  671. $conf->global->SUPPLIER_PAYMENT_ADDON = 'mod_supplier_payment_bronan';
  672. } elseif ($conf->global->SUPPLIER_PAYMENT_ADDON == 'brodator') {
  673. $conf->global->SUPPLIER_PAYMENT_ADDON = 'mod_supplier_payment_brodator';
  674. } elseif ($conf->global->SUPPLIER_PAYMENT_ADDON == 'bronan') {
  675. $conf->global->SUPPLIER_PAYMENT_ADDON = 'mod_supplier_payment_bronan';
  676. }
  677. if (!empty($conf->global->SUPPLIER_PAYMENT_ADDON)) {
  678. $mybool = false;
  679. $file = $conf->global->SUPPLIER_PAYMENT_ADDON.".php";
  680. $classname = $conf->global->SUPPLIER_PAYMENT_ADDON;
  681. // Include file with class
  682. $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
  683. foreach ($dirmodels as $reldir) {
  684. $dir = dol_buildpath($reldir."core/modules/supplier_payment/");
  685. // Load file with numbering class (if found)
  686. if (is_file($dir.$file) && is_readable($dir.$file)) {
  687. $mybool |= include_once $dir.$file;
  688. }
  689. }
  690. // For compatibility
  691. if ($mybool === false) {
  692. $file = $conf->global->SUPPLIER_PAYMENT_ADDON.".php";
  693. $classname = "mod_supplier_payment_".$conf->global->SUPPLIER_PAYMENT_ADDON;
  694. $classname = preg_replace('/\-.*$/', '', $classname);
  695. // Include file with class
  696. foreach ($conf->file->dol_document_root as $dirroot) {
  697. $dir = $dirroot."/core/modules/supplier_payment/";
  698. // Load file with numbering class (if found)
  699. if (is_file($dir.$file) && is_readable($dir.$file)) {
  700. $mybool |= include_once $dir.$file;
  701. }
  702. }
  703. }
  704. if ($mybool === false) {
  705. dol_print_error('', "Failed to include file ".$file);
  706. return '';
  707. }
  708. $obj = new $classname();
  709. $numref = "";
  710. $numref = $obj->getNextValue($soc, $this);
  711. /**
  712. * $numref can be empty in case we ask for the last value because if there is no invoice created with the
  713. * set up mask.
  714. */
  715. if ($mode != 'last' && !$numref) {
  716. dol_print_error($db, "SupplierPayment::getNextNumRef ".$obj->error);
  717. return "";
  718. }
  719. return $numref;
  720. } else {
  721. $langs->load("errors");
  722. print $langs->trans("Error")." ".$langs->trans("ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv("Supplier"));
  723. return "";
  724. }
  725. }
  726. /**
  727. * Create a document onto disk according to template model.
  728. *
  729. * @param string $modele Force template to use ('' to not force)
  730. * @param Translate $outputlangs Object lang a utiliser pour traduction
  731. * @param int $hidedetails Hide details of lines
  732. * @param int $hidedesc Hide description
  733. * @param int $hideref Hide ref
  734. * @param null|array $moreparams Array to provide more information
  735. * @return int <0 if KO, 0 if nothing done, >0 if OK
  736. */
  737. public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
  738. {
  739. global $conf, $user, $langs;
  740. $langs->load("suppliers");
  741. // Set the model on the model name to use
  742. if (empty($modele)) {
  743. if (!empty($conf->global->SUPPLIER_PAYMENT_ADDON_PDF)) {
  744. $modele = $conf->global->SUPPLIER_PAYMENT_ADDON_PDF;
  745. } else {
  746. $modele = ''; // No default value. For supplier invoice, we allow to disable all PDF generation
  747. }
  748. }
  749. if (empty($modele)) {
  750. return 0;
  751. } else {
  752. $modelpath = "core/modules/supplier_payment/doc/";
  753. return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
  754. }
  755. }
  756. /**
  757. * get the right way of payment
  758. *
  759. * @return string 'dolibarr' if standard comportment or paid in dolibarr currency, 'customer' if payment received from multicurrency inputs
  760. */
  761. public function getWay()
  762. {
  763. global $conf;
  764. $way = 'dolibarr';
  765. if (!empty($conf->multicurrency->enabled)) {
  766. foreach ($this->multicurrency_amounts as $value) {
  767. if (!empty($value)) { // one value found then payment is in invoice currency
  768. $way = 'customer';
  769. break;
  770. }
  771. }
  772. }
  773. return $way;
  774. }
  775. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  776. /**
  777. * Load the third party of object, from id into this->thirdparty
  778. *
  779. * @param int $force_thirdparty_id Force thirdparty id
  780. * @return int <0 if KO, >0 if OK
  781. */
  782. public function fetch_thirdparty($force_thirdparty_id = 0)
  783. {
  784. // phpcs:enable
  785. require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
  786. if (empty($force_thirdparty_id)) {
  787. $billsarray = $this->getBillsArray(); // From payment, the fk_soc isn't available, we should load the first supplier invoice to get him
  788. if (!empty($billsarray)) {
  789. $supplier_invoice = new FactureFournisseur($this->db);
  790. if ($supplier_invoice->fetch($billsarray[0]) > 0) {
  791. $force_thirdparty_id = $supplier_invoice->fk_soc;
  792. }
  793. }
  794. }
  795. return parent::fetch_thirdparty($force_thirdparty_id);
  796. }
  797. }