dolibarr  13.0.2
paiement.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2002-2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2010 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005 Marc Barilley / Ocebo <marc@ocebo.com>
5  * Copyright (C) 2012 Cédric Salvador <csalvador@gpcsolutions.fr>
6  * Copyright (C) 2014 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
7  * Copyright (C) 2014 Marcos García <marcosgdf@gmail.com>
8  * Copyright (C) 2015 Juanjo Menent <jmenent@2byte.es>
9  * Copyright (C) 2018 Ferran Marcet <fmarcet@2byte.es>
10  * Copyright (C) 2018 Thibault FOUCART <support@ptibogxiv.net>
11  * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
12  * Copyright (C) 2020 Andreu Bisquerra Gaya <jove@bisquerra.com>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program. If not, see <https://www.gnu.org/licenses/>.
26  */
27 
33 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
35 
36 
40 class Paiement extends CommonObject
41 {
45  public $element = 'payment';
46 
50  public $table_element = 'paiement';
51 
55  public $picto = 'payment';
56 
57  public $facid;
58  public $datepaye;
59 
64  public $total;
65 
70  public $montant;
71 
72  public $amount; // Total amount of payment (in the main currency)
73  public $multicurrency_amount; // Total amount of payment (in the currency of the bank account)
74  public $amounts = array(); // array: invoice ID => amount for that invoice (in the main currency)>
75  public $multicurrency_amounts = array(); // array: invoice ID => amount for that invoice (in the invoice's currency)>
76 
77  public $pos_change = 0; // Excess received in TakePOS cash payment
78 
79  public $author;
80  public $paiementid; // Type of payment. Id saved into fields fk_paiement on llx_paiement
81  public $paiementcode; // Code of payment.
82 
86  public $type_label;
87 
91  public $type_code;
92 
98  public $num_paiement;
99 
103  public $num_payment;
104 
108  public $ext_payment_id;
109 
113  public $ext_payment_site;
114 
120  public $bank_account;
121 
125  public $fk_account;
126 
130  public $bank_line;
131 
132  // fk_paiement dans llx_paiement est l'id du type de paiement (7 pour CHQ, ...)
133  // fk_paiement dans llx_paiement_facture est le rowid du paiement
137  public $fk_paiement; // Type of payment
138 
142  public $ref_ext;
143 
149  public function __construct($db)
150  {
151  $this->db = $db;
152  }
153 
162  public function fetch($id, $ref = '', $fk_bank = '')
163  {
164  $sql = 'SELECT p.rowid, p.ref, p.ref_ext, p.datep as dp, p.amount, p.statut, p.ext_payment_id, p.ext_payment_site, p.fk_bank, p.multicurrency_amount,';
165  $sql .= ' c.code as type_code, c.libelle as type_label,';
166  $sql .= ' p.num_paiement as num_payment, p.note,';
167  $sql .= ' b.fk_account';
168  $sql .= ' FROM '.MAIN_DB_PREFIX.'paiement as p LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as c ON p.fk_paiement = c.id';
169  $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank as b ON p.fk_bank = b.rowid';
170  $sql .= ' WHERE p.entity IN ('.getEntity('invoice').')';
171  if ($id > 0)
172  $sql .= ' AND p.rowid = '.$id;
173  elseif ($ref)
174  $sql .= " AND p.ref = '".$ref."'";
175  elseif ($fk_bank)
176  $sql .= ' AND p.fk_bank = '.$fk_bank;
177 
178  $resql = $this->db->query($sql);
179  if ($resql)
180  {
181  if ($this->db->num_rows($resql))
182  {
183  $obj = $this->db->fetch_object($resql);
184 
185  $this->id = $obj->rowid;
186  $this->ref = $obj->ref ? $obj->ref : $obj->rowid;
187  $this->ref_ext = $obj->ref_ext;
188  $this->date = $this->db->jdate($obj->dp);
189  $this->datepaye = $this->db->jdate($obj->dp);
190  $this->num_payment = $obj->num_payment;
191  $this->montant = $obj->amount; // deprecated
192  $this->amount = $obj->amount;
193  $this->multicurrency_amount = $obj->multicurrency_amount;
194  $this->note = $obj->note;
195  $this->type_label = $obj->type_label;
196  $this->type_code = $obj->type_code;
197  $this->statut = $obj->statut;
198  $this->ext_payment_id = $obj->ext_payment_id;
199  $this->ext_payment_site = $obj->ext_payment_site;
200 
201  $this->bank_account = $obj->fk_account; // deprecated
202  $this->fk_account = $obj->fk_account;
203  $this->bank_line = $obj->fk_bank;
204 
205  $this->db->free($resql);
206  return 1;
207  } else {
208  $this->db->free($resql);
209  return 0;
210  }
211  } else {
212  dol_print_error($this->db);
213  return -1;
214  }
215  }
216 
227  public function create($user, $closepaidinvoices = 0, $thirdparty = null)
228  {
229  global $conf, $langs;
230 
231  $error = 0;
232  $way = $this->getWay();
233 
234  $now = dol_now();
235 
236  // Clean parameters
237  $totalamount = 0;
238  $totalamount_converted = 0;
239  $atleastonepaymentnotnull = 0;
240 
241  if ($way == 'dolibarr')
242  {
243  $amounts = &$this->amounts;
244  $amounts_to_update = &$this->multicurrency_amounts;
245  } else {
246  $amounts = &$this->multicurrency_amounts;
247  $amounts_to_update = &$this->amounts;
248  }
249 
250  foreach ($amounts as $key => $value) // How payment is dispatch
251  {
252  $value_converted = Multicurrency::getAmountConversionFromInvoiceRate($key, $value, $way);
253  $totalamount_converted += $value_converted;
254  $amounts_to_update[$key] = price2num($value_converted, 'MT');
255 
256  $newvalue = price2num($value, 'MT');
257  $amounts[$key] = $newvalue;
258  $totalamount += $newvalue;
259  if (!empty($newvalue)) $atleastonepaymentnotnull++;
260  }
261 
262  $totalamount = price2num($totalamount);
263  $totalamount_converted = price2num($totalamount_converted);
264 
265  // Check parameters
266  if (empty($totalamount) && empty($atleastonepaymentnotnull)) // We accept negative amounts for withdraw reject but not empty arrays
267  {
268  $this->errors[] = 'TotalAmountEmpty';
269  $this->error = 'TotalAmountEmpty';
270  return -1;
271  }
272 
273  dol_syslog(get_class($this)."::create insert paiement", LOG_DEBUG);
274 
275  $this->db->begin();
276 
277  $this->ref = $this->getNextNumRef(is_object($thirdparty) ? $thirdparty : '');
278 
279  if (empty($this->ref_ext)) {
280  $this->ref_ext = '';
281  }
282 
283  if ($way == 'dolibarr')
284  {
285  $total = $totalamount;
286  $mtotal = $totalamount_converted; // Maybe use price2num with MT for the converted value
287  } else {
288  $total = $totalamount_converted; // Maybe use price2num with MT for the converted value
289  $mtotal = $totalamount;
290  }
291 
292  $num_payment = $this->num_payment;
293  $note = ($this->note_private ? $this->note_private : $this->note);
294 
295  $sql = "INSERT INTO ".MAIN_DB_PREFIX."paiement (entity, ref, ref_ext, datec, datep, amount, multicurrency_amount, fk_paiement, num_paiement, note, ext_payment_id, ext_payment_site, fk_user_creat, pos_change)";
296  $sql .= " VALUES (".$conf->entity.", '".$this->db->escape($this->ref)."', '".$this->db->escape($this->ref_ext)."', '".$this->db->idate($now)."', '".$this->db->idate($this->datepaye)."', ".$total.", ".$mtotal.", ".$this->paiementid.", ";
297  $sql .= "'".$this->db->escape($num_payment)."', '".$this->db->escape($note)."', ".($this->ext_payment_id ? "'".$this->db->escape($this->ext_payment_id)."'" : "null").", ".($this->ext_payment_site ? "'".$this->db->escape($this->ext_payment_site)."'" : "null").", ".$user->id.", ".((float) $this->pos_change).")";
298 
299  $resql = $this->db->query($sql);
300  if ($resql)
301  {
302  $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'paiement');
303 
304  // Insert links amount / invoices
305  foreach ($this->amounts as $key => $amount)
306  {
307  $facid = $key;
308  if (is_numeric($amount) && $amount <> 0)
309  {
310  $amount = price2num($amount);
311  $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'paiement_facture (fk_facture, fk_paiement, amount, multicurrency_amount)';
312  $sql .= ' VALUES ('.$facid.', '.$this->id.', \''.$amount.'\', \''.$this->multicurrency_amounts[$key].'\')';
313 
314  dol_syslog(get_class($this).'::create Amount line '.$key.' insert paiement_facture', LOG_DEBUG);
315  $resql = $this->db->query($sql);
316  if ($resql)
317  {
318  $invoice = new Facture($this->db);
319  $invoice->fetch($facid);
320 
321  // If we want to closed payed invoices
322  if ($closepaidinvoices)
323  {
324  $paiement = $invoice->getSommePaiement();
325  $creditnotes = $invoice->getSumCreditNotesUsed();
326  $deposits = $invoice->getSumDepositsUsed();
327  $alreadypayed = price2num($paiement + $creditnotes + $deposits, 'MT');
328  $remaintopay = price2num($invoice->total_ttc - $paiement - $creditnotes - $deposits, 'MT');
329 
330  //var_dump($invoice->total_ttc.' - '.$paiement.' -'.$creditnotes.' - '.$deposits.' - '.$remaintopay);exit;
331 
332  //Invoice types that are eligible for changing status to paid
333  $affected_types = array(
334  Facture::TYPE_STANDARD,
335  Facture::TYPE_REPLACEMENT,
336  Facture::TYPE_CREDIT_NOTE,
337  Facture::TYPE_DEPOSIT,
338  Facture::TYPE_SITUATION
339  );
340 
341  if (!in_array($invoice->type, $affected_types)) dol_syslog("Invoice ".$facid." is not a standard, nor replacement invoice, nor credit note, nor deposit invoice, nor situation invoice. We do nothing more.");
342  elseif ($remaintopay) dol_syslog("Remain to pay for invoice ".$facid." not null. We do nothing more.");
343  //else if ($mustwait) dol_syslog("There is ".$mustwait." differed payment to process, we do nothing more.");
344  else {
345  // If invoice is a down payment, we also convert down payment to discount
346  if ($invoice->type == Facture::TYPE_DEPOSIT)
347  {
348  $amount_ht = $amount_tva = $amount_ttc = array();
349  $multicurrency_amount_ht = $multicurrency_amount_tva = $multicurrency_amount_ttc = array();
350 
351  // Insert one discount by VAT rate category
352  $discount = new DiscountAbsolute($this->db);
353  $discount->fetch('', $invoice->id);
354  if (empty($discount->id)) { // If the invoice was not yet converted into a discount (this may have been done manually before we come here)
355  $discount->description = '(DEPOSIT)';
356  $discount->fk_soc = $invoice->socid;
357  $discount->fk_facture_source = $invoice->id;
358 
359  // Loop on each vat rate
360  $i = 0;
361  foreach ($invoice->lines as $line) {
362  if ($line->total_ht != 0) { // no need to create discount if amount is null
363  $amount_ht[$line->tva_tx] += $line->total_ht;
364  $amount_tva[$line->tva_tx] += $line->total_tva;
365  $amount_ttc[$line->tva_tx] += $line->total_ttc;
366  $multicurrency_amount_ht[$line->tva_tx] += $line->multicurrency_total_ht;
367  $multicurrency_amount_tva[$line->tva_tx] += $line->multicurrency_total_tva;
368  $multicurrency_amount_ttc[$line->tva_tx] += $line->multicurrency_total_ttc;
369  $i++;
370  }
371  }
372 
373  foreach ($amount_ht as $tva_tx => $xxx) {
374  $discount->amount_ht = abs($amount_ht[$tva_tx]);
375  $discount->amount_tva = abs($amount_tva[$tva_tx]);
376  $discount->amount_ttc = abs($amount_ttc[$tva_tx]);
377  $discount->multicurrency_amount_ht = abs($multicurrency_amount_ht[$tva_tx]);
378  $discount->multicurrency_amount_tva = abs($multicurrency_amount_tva[$tva_tx]);
379  $discount->multicurrency_amount_ttc = abs($multicurrency_amount_ttc[$tva_tx]);
380  $discount->tva_tx = abs($tva_tx);
381 
382  $result = $discount->create($user);
383  if ($result < 0) {
384  $error++;
385  break;
386  }
387  }
388  }
389 
390  if ($error)
391  {
392  setEventMessages($discount->error, $discount->errors, 'errors');
393  $error++;
394  }
395  }
396 
397  // Set invoice to paid
398  if (!$error)
399  {
400  $result = $invoice->set_paid($user, '', '');
401  if ($result < 0)
402  {
403  $this->error = $invoice->error;
404  $this->errors = $invoice->errors;
405  $error++;
406  }
407  }
408  }
409  }
410 
411  // Regenerate documents of invoices
412  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
413  {
414  dol_syslog(get_class($this).'::create Regenerate the document after inserting payment for thirdparty default_lang='.(is_object($invoice->thirdparty) ? $invoice->thirdparty->default_lang : 'null'), LOG_DEBUG);
415 
416  $newlang = '';
417  $outputlangs = $langs;
418  if ($conf->global->MAIN_MULTILANGS && empty($newlang)) {
419  $invoice->fetch_thirdparty();
420  $newlang = $invoice->thirdparty->default_lang;
421  }
422  if (!empty($newlang)) {
423  $outputlangs = new Translate("", $conf);
424  $outputlangs->setDefaultLang($newlang);
425  }
426  $ret = $invoice->fetch($facid); // Reload to get new records
427  $result = $invoice->generateDocument($invoice->modelpdf, $outputlangs);
428  if ($result < 0) {
429  setEventMessages($invoice->error, $invoice->errors, 'errors');
430  $error++;
431  }
432  }
433  } else {
434  $this->error = $this->db->lasterror();
435  $error++;
436  }
437  } else {
438  dol_syslog(get_class($this).'::Create Amount line '.$key.' not a number. We discard it.');
439  }
440  }
441 
442  if (!$error) // All payments into $this->amounts were recorded without errors
443  {
444  // Appel des triggers
445  $result = $this->call_trigger('PAYMENT_CUSTOMER_CREATE', $user);
446  if ($result < 0) { $error++; }
447  // Fin appel triggers
448  }
449  } else {
450  $this->error = $this->db->lasterror();
451  $error++;
452  }
453 
454  if (!$error)
455  {
456  $this->amount = $total;
457  $this->total = $total; // deprecated
458  $this->multicurrency_amount = $mtotal;
459  $this->db->commit();
460  return $this->id;
461  } else {
462  $this->db->rollback();
463  return -1;
464  }
465  }
466 
467 
476  public function delete($notrigger = 0)
477  {
478  global $conf, $user, $langs;
479 
480  $error = 0;
481 
482  $bank_line_id = $this->bank_line;
483 
484  $this->db->begin();
485 
486  // Verifier si paiement porte pas sur une facture classee
487  // Si c'est le cas, on refuse la suppression
488  $billsarray = $this->getBillsArray('fk_statut > 1');
489  if (is_array($billsarray))
490  {
491  if (count($billsarray))
492  {
493  $this->error = "ErrorDeletePaymentLinkedToAClosedInvoiceNotPossible";
494  $this->db->rollback();
495  return -1;
496  }
497  } else {
498  $this->db->rollback();
499  return -2;
500  }
501 
502  // Delete bank urls. If payment is on a conciliated line, return error.
503  if ($bank_line_id > 0)
504  {
505  $accline = new AccountLine($this->db);
506 
507  $result = $accline->fetch($bank_line_id);
508  if ($result == 0) {
509  $accline->id = $accline->rowid = $bank_line_id; // If not found, we set artificially rowid to allow delete of llx_bank_url
510  }
511 
512  // Delete bank account url lines linked to payment
513  $result = $accline->delete_urls($user);
514  if ($result < 0)
515  {
516  $this->error = $accline->error;
517  $this->db->rollback();
518  return -3;
519  }
520 
521  // Delete bank account lines linked to payment
522  $result = $accline->delete($user);
523  if ($result < 0)
524  {
525  $this->error = $accline->error;
526  $this->db->rollback();
527  return -4;
528  }
529  }
530 
531  if (!$notrigger)
532  {
533  // Call triggers
534  $result = $this->call_trigger('PAYMENT_CUSTOMER_DELETE', $user);
535  if ($result < 0)
536  {
537  $this->db->rollback();
538  return -1;
539  }
540  // End call triggers
541  }
542 
543  // Delete payment (into paiement_facture and paiement)
544  $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'paiement_facture';
545  $sql .= ' WHERE fk_paiement = '.$this->id;
546  dol_syslog($sql);
547  $result = $this->db->query($sql);
548  if ($result)
549  {
550  $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'paiement';
551  $sql .= ' WHERE rowid = '.$this->id;
552  dol_syslog($sql);
553  $result = $this->db->query($sql);
554  if (!$result)
555  {
556  $this->error = $this->db->lasterror();
557  $this->db->rollback();
558  return -3;
559  }
560 
561  $this->db->commit();
562  return 1;
563  } else {
564  $this->error = $this->db->error;
565  $this->db->rollback();
566  return -5;
567  }
568  }
569 
570 
585  public function addPaymentToBank($user, $mode, $label, $accountid, $emetteur_nom, $emetteur_banque, $notrigger = 0, $accountancycode = '')
586  {
587  global $conf, $langs, $user;
588 
589  $error = 0;
590  $bank_line_id = 0;
591 
592  if (!empty($conf->banque->enabled))
593  {
594  if ($accountid <= 0)
595  {
596  $this->error = 'Bad value for parameter accountid='.$accountid;
597  dol_syslog(get_class($this).'::addPaymentToBank '.$this->error, LOG_ERR);
598  return -1;
599  }
600 
601  $this->db->begin();
602 
603  $this->fk_account = $accountid;
604 
605  include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
606 
607  dol_syslog("$user->id, $mode, $label, $this->fk_account, $emetteur_nom, $emetteur_banque");
608 
609  $acc = new Account($this->db);
610  $result = $acc->fetch($this->fk_account);
611 
612  $totalamount = $this->amount;
613  if (empty($totalamount)) $totalamount = $this->total; // For backward compatibility
614 
615  // if dolibarr currency != bank currency then we received an amount in customer currency (currently I don't manage the case : my currency is USD, the customer currency is EUR and he paid me in GBP. Seems no sense for me)
616  if (!empty($conf->multicurrency->enabled) && $conf->currency != $acc->currency_code) $totalamount = $this->multicurrency_amount;
617 
618  if ($mode == 'payment_supplier') $totalamount = -$totalamount;
619 
620  // Insert payment into llx_bank
621  $bank_line_id = $acc->addline(
622  $this->datepaye,
623  $this->paiementid, // Payment mode id or code ("CHQ or VIR for example")
624  $label,
625  $totalamount, // Sign must be positive when we receive money (customer payment), negative when you give money (supplier invoice or credit note)
626  $this->num_payment,
627  '',
628  $user,
629  $emetteur_nom,
630  $emetteur_banque,
631  $accountancycode
632  );
633 
634  // Mise a jour fk_bank dans llx_paiement
635  // On connait ainsi le paiement qui a genere l'ecriture bancaire
636  if ($bank_line_id > 0)
637  {
638  $result = $this->update_fk_bank($bank_line_id);
639  if ($result <= 0)
640  {
641  $error++;
642  dol_print_error($this->db);
643  }
644 
645  // Add link 'payment', 'payment_supplier' in bank_url between payment and bank transaction
646  if (!$error)
647  {
648  $url = '';
649  if ($mode == 'payment') $url = DOL_URL_ROOT.'/compta/paiement/card.php?id=';
650  if ($mode == 'payment_supplier') $url = DOL_URL_ROOT.'/fourn/paiement/card.php?id=';
651  if ($url)
652  {
653  $result = $acc->add_url_line($bank_line_id, $this->id, $url, '(paiement)', $mode);
654  if ($result <= 0)
655  {
656  $error++;
657  dol_print_error($this->db);
658  }
659  }
660  }
661 
662  // Add link 'company' in bank_url between invoice and bank transaction (for each invoice concerned by payment)
663  //if (! $error && $label != '(WithdrawalPayment)')
664  if (!$error)
665  {
666  $linkaddedforthirdparty = array();
667  foreach ($this->amounts as $key => $value) // We should have invoices always for same third party but we loop in case of.
668  {
669  if ($mode == 'payment')
670  {
671  $fac = new Facture($this->db);
672  $fac->fetch($key);
673  $fac->fetch_thirdparty();
674  if (!in_array($fac->thirdparty->id, $linkaddedforthirdparty)) // Not yet done for this thirdparty
675  {
676  $result = $acc->add_url_line(
677  $bank_line_id,
678  $fac->thirdparty->id,
679  DOL_URL_ROOT.'/comm/card.php?socid=',
680  $fac->thirdparty->name,
681  'company'
682  );
683  if ($result <= 0) dol_syslog(get_class($this).'::addPaymentToBank '.$this->db->lasterror());
684  $linkaddedforthirdparty[$fac->thirdparty->id] = $fac->thirdparty->id; // Mark as done for this thirdparty
685  }
686  }
687  if ($mode == 'payment_supplier')
688  {
689  $fac = new FactureFournisseur($this->db);
690  $fac->fetch($key);
691  $fac->fetch_thirdparty();
692  if (!in_array($fac->thirdparty->id, $linkaddedforthirdparty)) // Not yet done for this thirdparty
693  {
694  $result = $acc->add_url_line(
695  $bank_line_id,
696  $fac->thirdparty->id,
697  DOL_URL_ROOT.'/fourn/card.php?socid=',
698  $fac->thirdparty->name,
699  'company'
700  );
701  if ($result <= 0) dol_syslog(get_class($this).'::addPaymentToBank '.$this->db->lasterror());
702  $linkaddedforthirdparty[$fac->thirdparty->id] = $fac->thirdparty->id; // Mark as done for this thirdparty
703  }
704  }
705  }
706  }
707 
708  // Add link 'WithdrawalPayment' in bank_url
709  if (!$error && $label == '(WithdrawalPayment)') {
710  $result = $acc->add_url_line(
711  $bank_line_id,
712  $this->id_prelevement,
713  DOL_URL_ROOT.'/compta/prelevement/card.php?id=',
714  $this->num_payment,
715  'withdraw'
716  );
717  }
718 
719  if (!$error && !$notrigger)
720  {
721  // Appel des triggers
722  $result = $this->call_trigger('PAYMENT_ADD_TO_BANK', $user);
723  if ($result < 0) { $error++; }
724  // Fin appel triggers
725  }
726  } else {
727  $this->error = $acc->error;
728  $error++;
729  }
730 
731  if (!$error)
732  {
733  $this->db->commit();
734  } else {
735  $this->db->rollback();
736  }
737  }
738 
739  if (!$error)
740  {
741  return $bank_line_id;
742  } else {
743  return -1;
744  }
745  }
746 
747 
748  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
755  public function update_fk_bank($id_bank)
756  {
757  // phpcs:enable
758  $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.' set fk_bank = '.$id_bank;
759  $sql .= ' WHERE rowid = '.$this->id;
760 
761  dol_syslog(get_class($this).'::update_fk_bank', LOG_DEBUG);
762  $result = $this->db->query($sql);
763  if ($result)
764  {
765  return 1;
766  } else {
767  $this->error = $this->db->lasterror();
768  dol_syslog(get_class($this).'::update_fk_bank '.$this->error);
769  return -1;
770  }
771  }
772 
773  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
780  public function update_date($date)
781  {
782  // phpcs:enable
783  $error = 0;
784 
785  if (!empty($date) && $this->statut != 1)
786  {
787  $this->db->begin();
788 
789  dol_syslog(get_class($this)."::update_date with date = ".$date, LOG_DEBUG);
790 
791  $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
792  $sql .= " SET datep = '".$this->db->idate($date)."'";
793  $sql .= " WHERE rowid = ".$this->id;
794 
795  $result = $this->db->query($sql);
796  if (!$result)
797  {
798  $error++;
799  $this->error = 'Error -1 '.$this->db->error();
800  }
801 
802  $type = $this->element;
803 
804  $sql = "UPDATE ".MAIN_DB_PREFIX.'bank';
805  $sql .= " SET dateo = '".$this->db->idate($date)."', datev = '".$this->db->idate($date)."'";
806  $sql .= " WHERE rowid IN (SELECT fk_bank FROM ".MAIN_DB_PREFIX."bank_url WHERE type = '".$this->db->escape($type)."' AND url_id = ".$this->id.")";
807  $sql .= " AND rappro = 0";
808 
809  $result = $this->db->query($sql);
810  if (!$result)
811  {
812  $error++;
813  $this->error = 'Error -1 '.$this->db->error();
814  }
815 
816  if (!$error)
817  {
818  }
819 
820  if (!$error)
821  {
822  $this->datepaye = $date;
823  $this->date = $date;
824 
825  $this->db->commit();
826  return 0;
827  } else {
828  $this->db->rollback();
829  return -2;
830  }
831  }
832  return -1; //no date given or already validated
833  }
834 
835  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
842  public function update_num($num)
843  {
844  // phpcs:enable
845  if (!empty($num) && $this->statut != 1) {
846  $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
847  $sql .= " SET num_paiement = '".$this->db->escape($num)."'";
848  $sql .= " WHERE rowid = ".$this->id;
849 
850  dol_syslog(get_class($this)."::update_num", LOG_DEBUG);
851  $result = $this->db->query($sql);
852  if ($result)
853  {
854  $this->num_payment = $this->db->escape($num);
855  return 0;
856  } else {
857  $this->error = 'Error -1 '.$this->db->error();
858  return -2;
859  }
860  }
861  return -1; //no num given or already validated
862  }
863 
871  public function valide(User $user = null)
872  {
873  return $this->validate($user);
874  }
875 
882  public function validate(User $user = null)
883  {
884  $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.' SET statut = 1 WHERE rowid = '.$this->id;
885 
886  dol_syslog(get_class($this).'::valide', LOG_DEBUG);
887  $result = $this->db->query($sql);
888  if ($result)
889  {
890  return 1;
891  } else {
892  $this->error = $this->db->lasterror();
893  dol_syslog(get_class($this).'::valide '.$this->error);
894  return -1;
895  }
896  }
897 
904  public function reject(User $user = null)
905  {
906  $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.' SET statut = 2 WHERE rowid = '.$this->id;
907 
908  dol_syslog(get_class($this).'::reject', LOG_DEBUG);
909  $result = $this->db->query($sql);
910  if ($result)
911  {
912  return 1;
913  } else {
914  $this->error = $this->db->lasterror();
915  dol_syslog(get_class($this).'::reject '.$this->error);
916  return -1;
917  }
918  }
919 
926  public function info($id)
927  {
928  $sql = 'SELECT p.rowid, p.datec, p.fk_user_creat, p.fk_user_modif, p.tms';
929  $sql .= ' FROM '.MAIN_DB_PREFIX.'paiement as p';
930  $sql .= ' WHERE p.rowid = '.$id;
931 
932  dol_syslog(get_class($this).'::info', LOG_DEBUG);
933  $result = $this->db->query($sql);
934 
935  if ($result)
936  {
937  if ($this->db->num_rows($result))
938  {
939  $obj = $this->db->fetch_object($result);
940  $this->id = $obj->rowid;
941  if ($obj->fk_user_creat)
942  {
943  $cuser = new User($this->db);
944  $cuser->fetch($obj->fk_user_creat);
945  $this->user_creation = $cuser;
946  }
947  if ($obj->fk_user_modif)
948  {
949  $muser = new User($this->db);
950  $muser->fetch($obj->fk_user_modif);
951  $this->user_modification = $muser;
952  }
953  $this->date_creation = $this->db->jdate($obj->datec);
954  $this->date_modification = $this->db->jdate($obj->tms);
955  }
956  $this->db->free($result);
957  } else {
958  dol_print_error($this->db);
959  }
960  }
961 
968  public function getBillsArray($filter = '')
969  {
970  $sql = 'SELECT pf.fk_facture';
971  $sql .= ' FROM '.MAIN_DB_PREFIX.'paiement_facture as pf, '.MAIN_DB_PREFIX.'facture as f'; // We keep link on invoice to allow use of some filters on invoice
972  $sql .= ' WHERE pf.fk_facture = f.rowid AND pf.fk_paiement = '.$this->id;
973  if ($filter) $sql .= ' AND '.$filter;
974  $resql = $this->db->query($sql);
975  if ($resql)
976  {
977  $i = 0;
978  $num = $this->db->num_rows($resql);
979  $billsarray = array();
980 
981  while ($i < $num)
982  {
983  $obj = $this->db->fetch_object($resql);
984  $billsarray[$i] = $obj->fk_facture;
985  $i++;
986  }
987 
988  return $billsarray;
989  } else {
990  $this->error = $this->db->error();
991  dol_syslog(get_class($this).'::getBillsArray Error '.$this->error.' -', LOG_DEBUG);
992  return -1;
993  }
994  }
995 
1001  public function getAmountsArray()
1002  {
1003  $sql = 'SELECT pf.fk_facture, pf.amount';
1004  $sql .= ' FROM '.MAIN_DB_PREFIX.'paiement_facture as pf';
1005  $sql .= ' WHERE pf.fk_paiement = '.$this->id;
1006  $resql = $this->db->query($sql);
1007  if ($resql)
1008  {
1009  $i = 0;
1010  $num = $this->db->num_rows($resql);
1011  $amounts = array();
1012 
1013  while ($i < $num)
1014  {
1015  $obj = $this->db->fetch_object($resql);
1016  $amounts[$obj->fk_facture] = $obj->amount;
1017  $i++;
1018  }
1019 
1020  return $amounts;
1021  } else {
1022  $this->error = $this->db->error();
1023  dol_syslog(get_class($this).'::getAmountsArray Error '.$this->error.' -', LOG_DEBUG);
1024  return -1;
1025  }
1026  }
1027 
1036  public function getNextNumRef($soc, $mode = 'next')
1037  {
1038  global $conf, $db, $langs;
1039  $langs->load("bills");
1040 
1041  // Clean parameters (if not defined or using deprecated value)
1042  if (empty($conf->global->PAYMENT_ADDON)) $conf->global->PAYMENT_ADDON = 'mod_payment_cicada';
1043  elseif ($conf->global->PAYMENT_ADDON == 'ant') $conf->global->PAYMENT_ADDON = 'mod_payment_ant';
1044  elseif ($conf->global->PAYMENT_ADDON == 'cicada') $conf->global->PAYMENT_ADDON = 'mod_payment_cicada';
1045 
1046  if (!empty($conf->global->PAYMENT_ADDON))
1047  {
1048  $mybool = false;
1049 
1050  $file = $conf->global->PAYMENT_ADDON.".php";
1051  $classname = $conf->global->PAYMENT_ADDON;
1052 
1053  // Include file with class
1054  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1055 
1056  foreach ($dirmodels as $reldir) {
1057  $dir = dol_buildpath($reldir."core/modules/payment/");
1058 
1059  // Load file with numbering class (if found)
1060  if (is_file($dir.$file) && is_readable($dir.$file))
1061  {
1062  $mybool |= include_once $dir.$file;
1063  }
1064  }
1065 
1066  // For compatibility
1067  if (!$mybool)
1068  {
1069  $file = $conf->global->PAYMENT_ADDON.".php";
1070  $classname = "mod_payment_".$conf->global->PAYMENT_ADDON;
1071  $classname = preg_replace('/\-.*$/', '', $classname);
1072  // Include file with class
1073  foreach ($conf->file->dol_document_root as $dirroot)
1074  {
1075  $dir = $dirroot."/core/modules/payment/";
1076 
1077  // Load file with numbering class (if found)
1078  if (is_file($dir.$file) && is_readable($dir.$file)) {
1079  $mybool |= include_once $dir.$file;
1080  }
1081  }
1082  }
1083 
1084  if (!$mybool)
1085  {
1086  dol_print_error('', "Failed to include file ".$file);
1087  return '';
1088  }
1089 
1090  $obj = new $classname();
1091  $numref = "";
1092  $numref = $obj->getNextValue($soc, $this);
1093 
1098  if ($mode != 'last' && !$numref) {
1099  dol_print_error($db, "Payment::getNextNumRef ".$obj->error);
1100  return "";
1101  }
1102 
1103  return $numref;
1104  } else {
1105  $langs->load("errors");
1106  print $langs->trans("Error")." ".$langs->trans("ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv("Invoice"));
1107  return "";
1108  }
1109  }
1110 
1116  public function getWay()
1117  {
1118  global $conf;
1119 
1120  $way = 'dolibarr';
1121  if (!empty($conf->multicurrency->enabled))
1122  {
1123  foreach ($this->multicurrency_amounts as $value)
1124  {
1125  if (!empty($value)) // one value found then payment is in invoice currency
1126  {
1127  $way = 'customer';
1128  break;
1129  }
1130  }
1131  }
1132 
1133  return $way;
1134  }
1135 
1144  public function initAsSpecimen($option = '')
1145  {
1146  global $user, $langs, $conf;
1147 
1148  $now = dol_now();
1149  $arraynow = dol_getdate($now);
1150  $nownotime = dol_mktime(0, 0, 0, $arraynow['mon'], $arraynow['mday'], $arraynow['year']);
1151 
1152  // Initialize parameters
1153  $this->id = 0;
1154  $this->ref = 'SPECIMEN';
1155  $this->specimen = 1;
1156  $this->facid = 1;
1157  $this->datepaye = $nownotime;
1158  }
1159 
1160 
1170  public function getNomUrl($withpicto = 0, $option = '', $mode = 'withlistofinvoices', $notooltip = 0)
1171  {
1172  global $conf, $langs;
1173 
1174  if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips
1175 
1176  $result = '';
1177 
1178  $label = img_picto('', $this->picto).' <u>'.$langs->trans("Payment").'</u><br>';
1179  $label .= '<strong>'.$langs->trans("Ref").':</strong> '.$this->ref;
1180  $dateofpayment = ($this->datepaye ? $this->datepaye : $this->date);
1181  if ($dateofpayment) {
1182  $label .= '<br><strong>'.$langs->trans("Date").':</strong> ';
1183  $tmparray = dol_getdate($dateofpayment);
1184  if ($tmparray['seconds'] == 0 && $tmparray['minutes'] == 0 && ($tmparray['hours'] == 0 || $tmparray['hours'] == 12)) { // We set hours to 0:00 or 12:00 because we don't know it
1185  $label .= dol_print_date($dateofpayment, 'day');
1186  } else { // Hours was set to real date of payment (special case for POS for example)
1187  $label .= dol_print_date($dateofpayment, 'dayhour', 'tzuser');
1188  }
1189  }
1190  if ($mode == 'withlistofinvoices')
1191  {
1192  $arraybill = $this->getBillsArray();
1193  if (is_array($arraybill) && count($arraybill) > 0)
1194  {
1195  include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
1196  $facturestatic = new Facture($this->db);
1197  foreach ($arraybill as $billid)
1198  {
1199  $facturestatic->fetch($billid);
1200  $label .= '<br> '.$facturestatic->getNomUrl(1, '', 0, 0, '', 1).' '.$facturestatic->getLibStatut(2, 1);
1201  }
1202  }
1203  }
1204 
1205  $linkclose = '';
1206  if (empty($notooltip))
1207  {
1208  if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
1209  {
1210  $label = $langs->trans("ShowMyObject");
1211  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1212  }
1213  $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
1214  $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
1215  } else $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1216 
1217  $url = DOL_URL_ROOT.'/compta/paiement/card.php?id='.$this->id;
1218 
1219  $linkstart = '<a href="'.$url.'"';
1220  $linkstart .= $linkclose.'>';
1221  $linkend = '</a>';
1222 
1223  $result .= $linkstart;
1224  if ($withpicto) $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);
1225  if ($withpicto && $withpicto != 2) $result .= ($this->ref ? $this->ref : $this->id);
1226  $result .= $linkend;
1227 
1228  return $result;
1229  }
1230 
1237  public function getLibStatut($mode = 0)
1238  {
1239  return $this->LibStatut($this->statut, $mode);
1240  }
1241 
1242  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1250  public function LibStatut($status, $mode = 0)
1251  {
1252  // phpcs:enable
1253  global $langs; // TODO Renvoyer le libelle anglais et faire traduction a affichage
1254 
1255  $langs->load('compta');
1256  /*if ($mode == 0)
1257  {
1258  if ($status == 0) return $langs->trans('ToValidate');
1259  if ($status == 1) return $langs->trans('Validated');
1260  }
1261  if ($mode == 1)
1262  {
1263  if ($status == 0) return $langs->trans('ToValidate');
1264  if ($status == 1) return $langs->trans('Validated');
1265  }
1266  if ($mode == 2)
1267  {
1268  if ($status == 0) return img_picto($langs->trans('ToValidate'),'statut1').' '.$langs->trans('ToValidate');
1269  if ($status == 1) return img_picto($langs->trans('Validated'),'statut4').' '.$langs->trans('Validated');
1270  }
1271  if ($mode == 3)
1272  {
1273  if ($status == 0) return img_picto($langs->trans('ToValidate'),'statut1');
1274  if ($status == 1) return img_picto($langs->trans('Validated'),'statut4');
1275  }
1276  if ($mode == 4)
1277  {
1278  if ($status == 0) return img_picto($langs->trans('ToValidate'),'statut1').' '.$langs->trans('ToValidate');
1279  if ($status == 1) return img_picto($langs->trans('Validated'),'statut4').' '.$langs->trans('Validated');
1280  }
1281  if ($mode == 5)
1282  {
1283  if ($status == 0) return $langs->trans('ToValidate').' '.img_picto($langs->trans('ToValidate'),'statut1');
1284  if ($status == 1) return $langs->trans('Validated').' '.img_picto($langs->trans('Validated'),'statut4');
1285  }
1286  if ($mode == 6)
1287  {
1288  if ($status == 0) return $langs->trans('ToValidate').' '.img_picto($langs->trans('ToValidate'),'statut1');
1289  if ($status == 1) return $langs->trans('Validated').' '.img_picto($langs->trans('Validated'),'statut4');
1290  }*/
1291  return '';
1292  }
1293 
1294  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1302  public function fetch_thirdparty($force_thirdparty_id = 0)
1303  {
1304  // phpcs:enable
1305  include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
1306 
1307  if (empty($force_thirdparty_id))
1308  {
1309  $billsarray = $this->getBillsArray(); // From payment, the fk_soc isn't available, we should load the first supplier invoice to get him
1310  if (!empty($billsarray))
1311  {
1312  $invoice = new Facture($this->db);
1313  if ($invoice->fetch($billsarray[0]) > 0)
1314  {
1315  $force_thirdparty_id = $invoice->socid;
1316  }
1317  }
1318  }
1319 
1320  return parent::fetch_thirdparty($force_thirdparty_id);
1321  }
1322 }
getBillsArray($filter= '')
Return list of invoices the payment is related to.
getAmountsArray()
Return list of amounts of payments.
create($user, $closepaidinvoices=0, $thirdparty=null)
Create payment of invoices into database.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm= 'auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
if(!empty($arrayfields['u.datec']['checked'])) print_liste_field_titre("DateCreationShort"u if(!empty($arrayfields['u.tms']['checked'])) print_liste_field_titre("DateModificationShort"u if(!empty($arrayfields['u.statut']['checked'])) print_liste_field_titre("Status"u statut
Definition: list.php:632
dol_now($mode= 'auto')
Return date for now.
Class to manage Dolibarr users.
Definition: user.class.php:44
__construct($db)
Constructor.
addPaymentToBank($user, $mode, $label, $accountid, $emetteur_nom, $emetteur_banque, $notrigger=0, $accountancycode= '')
Add a record into bank for payment + links between this bank record and sources of payment...
Class to manage bank transaction lines.
reject(User $user=null)
Reject payment.
Class to manage suppliers invoices.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
$conf db
API class for accounts.
Definition: inc.php:54
Class to manage bank accounts.
info($id)
Information sur l&#39;objet.
initAsSpecimen($option= '')
Initialise an instance with random values.
update_fk_bank($id_bank)
Mise a jour du lien entre le paiement et la ligne generee dans llx_bank.
update_date($date)
Updates the payment date.
fetch_thirdparty($force_thirdparty_id=0)
Load the third party of object, from id into this-&gt;thirdparty.
fetch($id, $ref= '', $fk_bank= '')
Load payment from database.
price2num($amount, $rounding= '', $option=0)
Function that return a number with universal decimal format (decimal separator is &#39;...
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt= '', $morecss= '', $marginleftonlyshort=2)
Show picto whatever it&#39;s its name (generic function)
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
Class to manage payments of customer invoices.
getLibStatut($mode=0)
Retourne le libelle du statut d&#39;une facture (brouillon, validee, abandonnee, payee) ...
dol_getdate($timestamp, $fast=false, $forcetimezone= '')
Return an array with locale date info.
img_object($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
valide(User $user=null)
Validate payment.
update_num($num)
Updates the payment number.
validate(User $user=null)
Validate payment.
getWay()
get the right way of payment
print
Draft customers invoices.
Definition: index.php:89
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
call_trigger($triggerName, $user)
Call trigger based on this instance.
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->don->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1232
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
LibStatut($status, $mode=0)
Renvoi le libelle d&#39;un statut donne.
Class to manage invoices.
Parent class of all other business classes (invoices, contracts, proposals, orders, ...)
if(!empty($search_group)) natural_search(array("g.nom"g note
Definition: list.php:122
getNextNumRef($soc, $mode= 'next')
Return next reference of customer invoice not already used (or last reference) according to numbering...
getNomUrl($withpicto=0, $option= '', $mode= 'withlistofinvoices', $notooltip=0)
Return clicable name (with picto eventually)